您如何解决:“AttributeError: 'Boundary' 对象没有属性 'rect'"? [英] How do you fix: "AttributeError: 'Boundary' object has no attribute 'rect'"?

查看:69
本文介绍了您如何解决:“AttributeError: 'Boundary' 对象没有属性 'rect'"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个平台游戏,在关卡的开头有一个边界,所以玩家不能无缘无故地继续向左走.我决定创建一个名为边界的类并将其添加到一个列表中,其中的规则是您不能通过它.但是,我不断收到此错误:AttributeError: 'Boundary' 对象没有属性 'rect'".有人可以解决这个问题吗?此外,也可以接受更好的方法来做到这一点.谢谢!

I am making a platformer game where there is a boundary in the beginning of the level, so the player can't just keep going to the left for no reason. I decided to make a class called boundary and add it into a list where the rules are you can't pass it. However, I keep getting this error: "AttributeError: 'Boundary' object has no attribute 'rect'". Can anybody fix this? Also, a better way to do this would also be accepted. Thanks!

class Boundary(pygame.sprite.Sprite):

    def __init__(self):
        super().__init__()
        self.boundary = pygame.Surface([15,600])  
        self.boundary.fill(WHITE)
        self.boundary.set_colorkey(WHITE)
        self.boundary_rect = 
        self.boundary.get_rect()
        self.boundary_rect.x = -50
        self.boundary_rect.y = 0


class Level01(Level):

    def __init__(self, player):
        Level.__init__(self, player)

    level_boundary = [Boundary()]

    for _ in level_boundary:
        boundary = Boundary()
        boundary.player = self.player  
        self.platform_boundary_list.add
                                    (boundary)


class Player(pygame.sprite.Sprite):
    def__init__(self):
        super().init()

        self.rect.x += self.change_x
        block_hit_list = pygame.sprite.spritecollide(self, 
                 self.level.platform_boundary_list, False)
        for block in block_hit_list:
            if self.change_x > 0:
                self.rect.right = block.rect.left
            elif self.change_x < 0:
                self.rect.left = block.rect.right


        self.rect.y += self.change_y
        block_hit_list = pygame.sprite.spritecollide(self, 
                 self.level.platform_boundary_list, False)
        for block in block_hit_list:
            if self.change_y > 0:
                self.rect.bottom = block.rect.top
            elif self.change_y < 0:
                self.rect.top = block.rect.bottom

            self.change_y = 0

推荐答案

没有运行代码,但是错误信息似乎合理.你的 Boundary 类有一个属性,boundary_rect 而不是 rect(它似乎没有被 pygame 的 Sprite类).用 block.boundary_rect 替换 block.rect 应该可以解决这个问题.

Haven't ran the code, but the error message seems reasonable. Your Boundary class has a property, boundary_rect rather than rect (which doesn't appear to be directly exposed by pygame's Sprite class). Replacing block.rect with block.boundary_rect should correct this.

更新:查看您的代码,我发现了一些问题,PlayerBoundary 类都引用了不直接属于它们的 rect 属性父级,pygame.sprite.Sprite.根据您的评论,我决定将代码重写为演示碰撞测试,不仅可以修复错误,还可以为您考虑如何组织代码提供一些想法.

Update: Looking through your code, I saw a few issues, with both the Player and the Boundary classes referring to rect properties that did not directly belong their parent, pygame.sprite.Sprite. Based on your comments, I decided to rewrite the code into a demo collision test to not only fix the errors but also provide some ideas for how you could consider organizing your code.

演示非常简单;一个玩家和一堆随机块被绘制到屏幕上.玩家方块会在屏幕边缘反弹,碰撞的方块会被重新绘制成不同的颜色.结果如下:

The demo is pretty simple; a player and a bunch of random blocks are drawn to the screen. The player block bounces around the edges of the screen, and the colliding blocks are redrawn in a different color. The results look like this:

这是上面演示的代码.我添加了一堆注释来阐明代码的作用.如果有什么不清楚的,请告诉我:

Here is the code for the above demo. I added a bunch of comments to clarify what the code does. If anything is unclear, let me know:

import random
import pygame
from pygame.rect import Rect
from pygame.sprite import Sprite
from pygame.surface import Surface

class Block(Sprite):

    def __init__(self, rect):
        super().__init__()
        self.idle_color = (255, 255, 255, 255)#white - if not colliding
        self.hit_color = (0, 255, 0, 255)#green - if colliding
        self.image = Surface((rect.w, rect.h))
        self.color = self.idle_color#default
        #Do NOT set color here, decided by collision status!
        self.rect = rect

class Player(Sprite):

    def __init__(self, rect):
        super().__init__()
        self.color = (255, 0, 0, 255)#red
        self.image = Surface((rect.w, rect.h))
        self.image.fill(self.color)
        self.rect = rect

class Level(object):

    def __init__(self, screen, player, blocks):
        self.color = (20, 20, 20, 255)#gray background
        self.screen = screen
        self.player = player
        self.blocks = blocks

        #hard-coded player x and y speed for bounding around
        self.player_speed_x = 1
        self.player_speed_y = 1

    #Bounces player off the screen edges
    #Simply dummy method - no collisions here!
    def move_player(self):
        p_rect = self.player.rect
        s_rect = self.screen.get_rect()
        if p_rect.right >= s_rect.right or p_rect.left <= s_rect.left:
            self.player_speed_x *= -1
        if p_rect.top <= s_rect.top or p_rect.bottom >= s_rect.bottom:
            self.player_speed_y *= -1
        p_rect.move_ip(self.player_speed_x, self.player_speed_y)#modifies IN PLACE!

    def handle_collisions(self):
        #First set all blocks to default color
        for block in self.blocks:
            block.color = block.idle_color

        hit_blocks = pygame.sprite.spritecollide(self.player, self.blocks, False)
        for block in hit_blocks:
            block.color = block.hit_color

    #Clear screen with background color, then draw blocks, then draw player on top!
    def draw(self):
        self.screen.fill(self.color)
        for block in self.blocks:
            #update fill to color decided by handle_collisions function...
            block.image.fill(block.color)
            self.screen.blit(block.image, block.rect)

        self.screen.blit(self.player.image, self.player.rect)

    def update(self):
        self.move_player()
        self.handle_collisions()
        self.draw()

if __name__ == "__main__":
    pygame.init()
    width = 400
    height = 300
    fps = 60
    title = "Collision Test"
    screen = pygame.display.set_mode((width, height))
    pygame.display.set_caption(title)
    clock = pygame.time.Clock()
    running = True

    #Create a player
    player_size = 20
    player_x = random.randint(0, width - player_size)
    player_y = random.randint(0, height - player_size)
    player_rect = Rect(player_x, player_y, player_size, player_size)
    player = Player(player_rect)

    #Create some random blocks
    blocks = []
    num_blocks = 50
    for i in range(num_blocks):
        block_size = 20
        block_x = random.randint(0, width - block_size)
        block_y = random.randint(0, height - block_size)
        block_rect = Rect(block_x, block_y, block_size, block_size)
        block = Block(block_rect)
        blocks.append(block)

    #Create the level
    level = Level(screen, player, blocks)

    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        level.update()
        pygame.display.update()
        clock.tick(fps)

这篇关于您如何解决:“AttributeError: 'Boundary' 对象没有属性 'rect'"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆