Pygame Sprites没有检测到碰撞

时间:2013-12-28 17:14:35

标签: python pygame collision-detection sprite

我已经制作了 开始菜单 菜单屏幕 。开始屏幕只有一个Button Sprite。单击后,它会创建校正动画,然后按预期进入菜单屏幕。但是,此菜单屏幕有两个Button Sprites。似乎我在组中首先添加的Button Sprite是可点击的,但另一个则不是。我不确定为什么会出现这种奇怪的行为。

在这段代码中我注意到它变得混乱:

        elif event.type == MOUSEBUTTONDOWN:
            #HERE IS THE ISSUE
            print("size of all_sprites after clicking:  " + str(len(all_sprites)))
            print("     info on all_sprites:  " + str(all_sprites))
            for but in all_sprites:
                print("         sprite info:  " + str(but))
                if isinstance(but, (Button)) and mouse.click(but):
                    but.set_clicked()
                    print("             clicked:  " + str(but))

迭代Sprites组并调用此方法时:

mouse.click(but)

它仅适用于添加的第一个Button。当我尝试点击其他Button时,它永远不会返回True。我不确定为什么。

以下是相关对象:

#seperate this into an object class
class Mouse(pygame.sprite.Sprite):
    """moves a hand on the screen, following the computer mouse"""
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) #call Sprite initializer
        self.clicking = 0
        self.image, self.rect = util.load_image('cursor.png',-1)

    def update(self):
        "move the hand based on the computer mouse position"
        pos = pygame.mouse.get_pos()
        self.rect.midtop = pos
        if self.clicking:
            pygame.mixer.Sound("data/high_tone_sword.wav").play()
            self.rect.move_ip(5, 10)

    def click(self, target):
        "returns true if the hand collides with the target"
        if not self.clicking:
            self.clicking = 1
            hitbox = self.rect.inflate(-5, -5)
            return hitbox.colliderect(target.rect)

    def unclick(self):
        self.clicking = 0


#seperate this into an object/menu class
class Button(pygame.sprite.Sprite):
    """Button class used for all menus.  Handles events"""
    def __init__(self, original_image_source, clicked_image_source, location_coordinates):
        pygame.sprite.Sprite.__init__(self) #call Sprite intializer
        self.original_image_source = original_image_source
        self.clicked_image_source = clicked_image_source
        self.location_coordinates = location_coordinates
        self.clicked = 0
        self.image, self.rect = util.load_image(original_image_source, None)
        self.rect.midtop = location_coordinates

    def update(self):
        "update on click or unclick"
        if self.clicked:
            self.image, self.rect = util.load_image(self.clicked_image_source, None)
            self.rect.midtop = self.location_coordinates
        else:
            self.image, self.rect = util.load_image(self.original_image_source, None)
            self.rect.midtop = self.location_coordinates

    def set_clicked(self):
        self.clicked = 1

    def set_unclicked(self):
        self.clicked = 0

这是驱动程序:

def main():

    #initialise screen
    pygame.init()
    screen = pygame.display.set_mode((1000, 600))
    pygame.display.set_caption('States of Matter')
    pygame.mouse.set_visible(0)

    #music!!!
    pygame.mixer.music.load("music/Glorious Morning 2.mp3")
    pygame.mixer.music.play(-1, 53.0)

    background = pygame.Surface(screen.get_size(), pygame.SRCALPHA, 32)
    background = background.convert()
    background.fill((250, 250, 250))

    elements_background = util.load_image("4-elements-background.jpg")


    if pygame.font:
        font = pygame.font.Font(None, 180)
        font.set_italic(True)
        text = font.render("States of Matter", 1, (20, 125, 120))
        textpos = text.get_rect(centerx=elements_background[0].get_width()/2, centery=elements_background[0].get_height()/4)
        elements_background[0].blit(text, textpos)


    background.blit(elements_background[0],(-450, -200))
    screen.blit(background, (0, 0))
    pygame.display.flip()

    flamethrower = Animation('animation/Flames/flamethrower_/flamethrower_', 29, (-50,0))
    bolt_tsela = Animation('animation/voltage_0/bolt_tesla/bolt_tesla_', 10, (600, 200))
    mouse = Mouse()
    start_button = Button("start_button_original.jpg", "start_button_clicked.jpg", (background.get_width()/2, 12.5*background.get_height()/17))
    #all_sprites = pygame.sprite.RenderPlain((flamethrower, bolt_tsela, mouse, start_button))   #arbitary order
    all_sprites = pygame.sprite.OrderedUpdates((flamethrower, bolt_tsela, start_button, mouse)) #order based on how they are added!
    clock = pygame.time.Clock()

    battle_button = Button("battle_menu_button_original.jpg", "battle_menu_button_clicked.jpg", (background.get_width()/2,4.5*background.get_height()/17))
    options_button = Button("options_menu_button_original.jpg", "options_menu_button_clicked.jpg", (background.get_width()/2, 10.5*background.get_height()/17))

    menu_control = MenuControl()
    menu_control.set_in_start_screen(True)

    #game driver
    while 1:
        clock.tick(60)

        for event in pygame.event.get():
            if event.type == QUIT:
                return
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                return
            elif event.type == MOUSEBUTTONDOWN:
                #HERE IS THE ISSUE
                print("size of all_sprites after clicking:  " + str(len(all_sprites)))
                print("     info on all_sprites:  " + str(all_sprites))
                for but in all_sprites:
                    print("         sprite info:  " + str(but))
                    if isinstance(but, (Button)) and mouse.click(but):
                        but.set_clicked()
                        print("             clicked:  " + str(but))
            elif event.type == MOUSEBUTTONUP:
                mouse.unclick()
                if menu_control.bools["in_start_screen"] and start_button.clicked:
                    #enter main manu
                    menu_control.set_in_main_menu(True)
                    start_button.set_unclicked()
                    all_sprites.empty()
                    all_sprites.add(battle_button, options_button, mouse)
                    print("size of all_sprites after enting main menu:  " + str(len(all_sprites)))
                elif menu_control.bools["in_start_screen"]:
                    start_button.set_unclicked()
                if menu_control.bools["in_main_menu"] and battle_button.clicked:
                    battle_button.set_unclicked()
                if menu_control.bools["in_main_menu"] and options_button.clicked:
                    options_button.set_unclicked()

        all_sprites.update()

        #redraw everything
        screen.blit(background, (0, 0))
        all_sprites.draw(screen)
        pygame.display.flip()

if __name__ == '__main__': main()

2 个答案:

答案 0 :(得分:1)

这是因为您在MOUSE_UP事件上重置了鼠标上的单击状态。

在检查第一个按钮时设置变量clicking,条件not self.clicking 其他按钮永远不会实现。

编辑:

我建议将此方法拆分为为鼠标设置clicking变量的部分,以及另一个检查碰撞的部分。它们是两个独立的行动。现在,如果您不添加任何按钮,鼠标将永远不会处于clicking状态。我不认为那是你的意图。

答案 1 :(得分:0)

对于发生的每个MOUSEBUTTONDOWN事件,mouse.click()中的每个Button实例都会调用all_sprites方法。 click()方法仅在尚未设置时设置self.clicking = 1。这意味着,当在第一个按钮之后的all_sprites中再次调用按钮时,它会看到self.clicking已经设置并且没有做任何事情。

希望这很清楚。

也许你想要这些[未经测试]的东西 - 这只会在self.clicking循环中设置鼠标的for属性一次(假设两个按钮不重叠):

def click(self, target):
    "returns true if the hand collides with the target"
    hitbox = self.rect.inflate(-5, -5)
    if hitbox.colliderect(target.rect):
        self.clicking = 1
        return True