Search code examples
pythonpygamecollision-detectionsprite

random sprite movement and collision python


I am making a pacman style game using python in pygame. At the moment I am creating the ghosts/monsters that pacman has to avoid around the maze. I have created these and tried to add random movement a collision detection so they go around the maze and not just all over the screen. The code for these monsters is bellow. My question is that the Monster seem to slightly jump about and barely move, how can i get the, to smoothly go through the maze like the pacman ghosts? Any help is greatly appreciated.


Solution

  • I could not test your code on my computer because for some reason, python returns a few errors. But let me give analyzing your code a shot.

    The problem seems to arise from these two lines:

    self.rect.x += random.randint(-1,1)
    self.rect.y += random.randint(-1,1)
    

    which are underneath your update(self) function.

    Since you set your monsters to "update" every screen refresh, your monsters will move one pixel up, down, left or right randomly each time you call update. Your "update" function calls a random number from -1 to 1 every single time. So, your monsters either move by +1 or 0 or -1 pixels every screen refresh vertically and horizontally. As a result, they appear wiggly and not moving anywhere at all.

    What you want for a smooth movement is for your "update" function to move your monster in a single constant direction.

    I am not sure about the best way to go about your game, but here is what I suggest: (My codes are just a guide, they might contain errors)

    Give the Monster class a variable or property called "dir" which stands for direction. Upon initiating your class, give "dir" a random value from 1 to 4 (which stands for Up, Down, Left and Right)

    self.dir = random.randint(1,4)

    Then, in your "update(self)" function, write some if statements like this:

    if self.dir == 1: #Moving up
        self.rect.y+=1;
    
    if self.dir == 2: #Moving down
        self.rect.y-=1;
    
    if self.dir == 3: #Moving left
        self.rect.x-=1;
    
    if self.dir == 4: #Moving right
        self.rect.x+=1;
    

    That way, your monsters only move up down left or right in one direction at a time.

    With this, I think you'd have to modify your "check for collision" code as well. Make your code change your monster's direction depending on which part of the wall it hit.

    Hope this helps! :)

    Edit:

    Your second issue was that your monsters did not collide with walls properly. Here is your code:

    if self.rect.x > -1: # Moving right; Hit the left side of the wall
        self.rect.right = wall.rect.left
    if self.rect.x < 0: # Moving left; Hit the right side of the wall
        self.rect.left = wall.rect.right
    if self.rect.y < -1: # Moving down; Hit the top side of the wall
        self.rect.bottom = wall.rect.top
    if self.rect.y > 0: # Moving up; Hit the bottom side of the wall
        self.rect.top = wall.rect.bottom
    

    I find it peculiar that your check the direction of your monsters based on its location. Take if self.rect.x > -1: as an example. "self.rect.x" is actually the x-coordinate of your monster. So this does not indicate the direction of your monster at all. So I don't think you can use self.rect.x or self.rect.y in your if statements for collision.

    Instead, consider using the "dir" I just recommended you. I'll change the first line for you and you can do the rest of it.

    if self.dir == 4: # Moving right; Hit the left side of the wall
    self.rect.right = wall.rect.left
    

    After that, your monster will stop because it will try to move in the same direction again but this code will stop it. So, you have to change its direction randomly again. Just make sure that it does not choose the same direction again. I'll leave this as a puzzle for you for now.

    Edit 2:

    You mentioned that your collision does not work for top and bottom.

    Took a while before I got where your error is ;)

    if self.dir == 1: #Moving up
        self.rect.y+=2;
    
    if self.dir == 2: #Moving down
        self.rect.y-=2;
    

    I think you interchanged your y+=2 and y=-2. So your moving up and down motions were interchanged.