简体   繁体   中英

I am having trouble creating moving platforms in pygames. I am getting an error, can anyone help me out please?

So I have just started to learn how to program and I have been trying to create this small game with moving platforms. I can get regular walls/platforms to work but I can't seem to figure out how to get these moving ones to work. I keep getting a traceback that looks like this:

Traceback (most recent call last):
  File "C:\Users\Jacob\Desktop\gametest.py", line 227, in <module>
    walls.update()
  File "C:\Python34\lib\site-packages\pygame\sprite.py", line 462, in update
    s.update(*args)
  File "C:\Users\Jacob\Desktop\gametest.py", line 111, in update
    hit = pygame.sprite.collide_rect(self, self.player)
  File "C:\Python34\lib\site-packages\pygame\sprite.py", line 1300, in collide_rect
    return left.rect.colliderect(right.rect)
AttributeError: 'NoneType' object has no attribute 'rect'

I think the problem has to do with some of these bits of code that I have but I am not completely sure.

class Wall(pygame.sprite.Sprite):

    def __init__(self, width, height):
        #creates the wall
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.Surface([width, height])
        self.image.fill(blue)

        self.rect = self.image.get_rect()


######################################################
class MovingEnemy(Wall):
    change_x = 0
    change_y=0

    boundary_top = 0
    boundary_bottom = 0
    boundary_left = 0
    boundary_right = 0

    player = None
    level = None

    def update(self):
        # Move left/right
        self.rect.x += self.change_x

        # See if we hit the player
        hit = pygame.sprite.collide_rect(self, self.player)
        if hit:
            # We did hit the player. Shove the player around and
            # assume he/she won't hit anything else.

            # If we are moving right, set our right side
            # to the left side of the item we hit
            if self.change_x < 0:
                self.player.rect.right = self.rect.left
            else:
                # Otherwise if we are moving left, do the opposite.
                self.player.rect.left = self.rect.right

        # Move up/down
        self.rect.y += self.change_y

        # Check and see if we the player
        hit = pygame.sprite.collide_rect(self, self.player)
        if hit:
            # We did hit the player. Shove the player around and
            # assume he/she won't hit anything else.

            # Reset our position based on the top/bottom of the object.
            if self.change_y < 0:
                self.player.rect.bottom = self.rect.top
            else:
                self.player.rect.top = self.rect.bottom

        # Check the boundaries and see if we need to reverse
        # direction.
        if self.rect.bottom > self.boundary_bottom or self.rect.top < self.boundary_top:
            self.change_y *= -1

        cur_pos = self.rect.x - self.level.world_shift
        if cur_pos < self.boundary_left or cur_pos > self.boundary_right:
            self.change_x *= -1




wall = MovingEnemy(70,40)
wall.rect.x = 500
wall.rect.y = 400
wall.boundary_left = 250
wall.boundary_right = 800
wall.change_x = 1
walls.add(wall)

I am not sure if I have given the right information to receive help but I am honestly trying. I have browsed the internet for hours looking for a way to manage to do this and everything I try seems to not work. If anyone can understand this jumbled mess I have and help me out, I would really appreciate it.

Edit: I do have a player class, am I supposed to set the player within MovingEnemy to the class? I am not sure if that is possible or what exactly I am supposed to set it to. Here is my player class if this makes it easier.

class Player(pygame.sprite.Sprite):

    #Sets the starting speed
    change_x = 0
    change_y = 0
    walls = None


    def __init__(self, x, y):
        #creates the sprite for the player
        pygame.sprite.Sprite.__init__(self)

        #sets the size
        self.image = pygame.Surface([25,25])
        self.image.fill(green)

        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x

    def movement(self, x, y):

        self.change_x += x
        self.change_y += y

    def update(self):

        #changes the position of the player moving left and right
        self.rect.x += self.change_x



        #checks to see if the player sprite hits the wall
        collision = pygame.sprite.spritecollide(self, self.walls, False)
        for block in collision:
            # If the player hits a block while moving right, it is set back
            # to the left side of the block that was hit.
            if self.change_x > 0:
                self.rect.right = block.rect.left
            # Does the same as above, except with moving left.   
            else:
                self.rect.left = block.rect.right


        #changes the position of the player moving up and down    
        self.rect.y += self.change_y

        collision = pygame.sprite.spritecollide(self, self.walls, False)
        for block in collision:

            # Does the same as the above "for" except for moving up and down
            if self.change_y > 0:
                self.rect.bottom = block.rect.top
            else:
                self.rect.top = block.rect.bottom

In your MovingEnemy class you have an attribute called player . player 's starts out at None . No where in your code do you change player to anything but, None , hence player is of type none, or a NoneType . Nothing doesn't have the method rect which is used by the collide_rect method that you call.

Your compiler is telling you whats wrong.

walls.update()

First, your program calls walls.update, which is where the trouble begins.

hit = pygame.sprite.collide_rect(self, self.player)

Then, you try and detect hit detection between the wall and the player.

File "C:\Python34\lib\site-packages\pygame\sprite.py", line 1300, in collide_rect
return left.rect.colliderect(right.rect)

Notice the next clue comes in this line as this is ultimately the line that triggered the problem and it said this:

AttributeError: 'NoneType' object has no attribute 'rect'

Either your wall (self) or (self.player) is of type None, and thus has no attribute 'rect' with which it can determine a collision. Now note:

player = None

You never set player! Thus, player is of type None and has no attribute 'rect' to do collision detection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM