Search code examples
pythonclassobjectpygamekey-bindings

Object not moving when keys are pressed


I just started learning pygame to create a simple game for a project. I have an object "Rectangle" which has a method which changes the x and y position. However, for some reason, the object doesn't move. I found some examples where the x and y are changed when a key is pressed and a new object is drawn with the new coordinates. However, rather than do that I want to call a method which will move that rectangle and not create a new one. What's the best way to do it?

My code:

import pygame

#init the pygame and create a screen
pygame.init()
screen = pygame.display.set_mode((1080,720))
done = False

#colours
blue = (0,0,255)
red = (255,0,0)
green = (0,255,0)
black = (0,0,0)
white = (255,255,255)
yellow = (255,255,0)

x = 540
y = 660

#starts the game clock
clock = pygame.time.Clock()

#class for all of the objects on the screen
class shape():
    def __init__(self, place, colour, x, y):
        self.place = place
        self.colour = colour
        self.x = x
        self.y = y

#class for a rectangle
class rectangle(shape):
    def __init__(self, place, colour, x, y, length, width):
        super().__init__(place, colour, x, y)
        self.length = length
        self.width = width

        pygame.draw.rect(screen, colour, pygame.Rect(x, y, length, width))

    def move_up(self):
        self.y = self.y + 3

    def move_down(self):
        self.y = self.y - 3

    def move_right(self):
        self.x = self.x + 3

    def move_left(self):
        self.x = self.x - 3


#main loop
while not done:

        #checking for game events
        for event in pygame.event.get():

                #quitting gamw when window is closed
                if event.type == pygame.QUIT:
                        done = True

        Rectangle = rectangle(screen, yellow, x, y, 30, 30)

        #detecting key presses
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_UP]:Rectangle.move_up()
        if pressed[pygame.K_DOWN]:Rectangle.move_down()
        if pressed[pygame.K_LEFT]:Rectangle.move_left()
        if pressed[pygame.K_RIGHT]:Rectangle.move_right()

        pygame.display.update() 

        #controls FPS
        clock.tick(60)


Solution

  • What you actually do is to create a new rectangle at the initial position in every frame. The position is of the rectangle is updated, but since a new rectangle is created in the next frame, the rectangles seems to be immovable.

    Do not draw the rectangle in its constructor, but add a draw method to the class rectangle:

    class rectangle(shape):
        def __init__(self, place, colour, x, y, length, width):
            super().__init__(place, colour, x, y)
            self.length = length
            self.width = width
    
        def move_up(self):
            self.y = self.y - 3
        def move_down(self):
            self.y = self.y + 3
        def move_right(self):
            self.x = self.x + 3
        def move_left(self):
            self.x = self.x - 3
    
        def draw(self):
            pygame.draw.rect(screen, self.colour, pygame.Rect(self.x, self.y, self.length, self.width))
    

    Create a rectangle object before the main application loop and call the draw() method in the main application loop:

    # create rectangle object
    Rectangle = rectangle(screen, yellow, x, y, 30, 30)
    
    #main loop
    while not done:
    
            #checking for game events
            for event in pygame.event.get():
                    #quitting gamw when window is closed
                    if event.type == pygame.QUIT:
                            done = True
    
            # detecting key presses and change location of the rectangle
            pressed = pygame.key.get_pressed()
            if pressed[pygame.K_UP]:Rectangle.move_up()
            if pressed[pygame.K_DOWN]:Rectangle.move_down()
            if pressed[pygame.K_LEFT]:Rectangle.move_left()
            if pressed[pygame.K_RIGHT]:Rectangle.move_right()
    
            # clear display
            screen.fill(0)
    
            # draw rectangle
            Rectangle.draw()
    
            # update diesplay
            pygame.display.update() 
    
            #controls FPS
            clock.tick(60)