首页 > 解决方案 > 为什么 play_button.rect.collidepoint(mouse_x , mouse_y) 不起作用?

问题描述

这是一个用 Python 编写的打字游戏。单击“播放”按钮,游戏应该开始了。随机字母会掉下来,当您敲击相应的键时,每个字母都会消失。但是,当我单击按钮时,它无法开始。我认为问题一定与if play_button.rect.collidepoint(mouse_x , mouse_y):game_functions.py 的 check_play_button() 方法中的 if 语句有关,因为如果删除了 if 语句,则 stats.game_active 将更改为 True。另一方面,如果删除了 if 语句,则单击屏幕上的任意位置会将 stats.game_active 的值更改为 True。我对 if 语句的故障感到很困惑。请阐明它。这是我的代码(有点长但有挑战:P):

  1. 字母动物园.py
import pygame
import time
from pygame.locals import *
from settings import Settings
import game_functions as gf
from game_stats import GameStats
from button import Button

def run_game():
    pygame.init()
    az_settings =Settings()
    screen = pygame.display.set_mode((0,0), RESIZABLE)
    pygame.display.set_caption("Alphabet Zoo")
    play_button = Button(screen, "Play")
    stats = GameStats(az_settings)
    letters = pygame.sprite.Group()
    start = time.time()
    sleepTime = 3


    while True:
        now = time.time()
        gf.check_events(letters, stats, play_button)
        if stats.game_active:
            gf.update_screen(az_settings, stats, screen, letters, play_button)
            if now - start >sleepTime:
                gf.letter_generator(az_settings ,screen, letters)
                start = now
        else:
            gf.update_screen(az_settings, stats, screen, letters, play_button)



run_game()

  1. 按钮.py
import pygame.font


class Button():


    def __init__(self, screen, msg):
        self.screen = screen
        self.screen_rect = screen.get_rect()

        self.width, self.height = 200, 50
        self.button_color = (0, 0, 255)
        self.text_color = (255, 255, 255)
        self.font = pygame.font.SysFont(None, 48)

        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center

        self.prep_msg(msg)

    def prep_msg(self, msg):
        self.msg_image = self.font.render(msg, True, self.text_color,
                                          self.button_color)
        self.msg_image_rect = self.msg_image.get_rect()
        self.msg_image_rect.center = self.rect.center

    def draw_button(self):
        self.screen.fill(self.button_color, self.rect)
        self.screen.blit(self.msg_image, self.msg_image_rect)
  1. 设置.py
class Settings():
    def __init__(self):
        self.bg_color = (0, 0, 0)
        self.letter_speed_factor = 10
        self.lives_limit = 10
  1. game_stats.py
class GameStats():
    def __init__(self, az_settings):
        self.az_settings = az_settings
        self.reset_stats()
        self.game_active = False

    def reset_stats(self):
        self.lives_left = self.az_settings.lives_limit
  1. 字母.py
import pygame
import random
from pygame.sprite import Sprite


class Letter(Sprite):

    def __init__(self, az_settings, screen):
        super().__init__()
        self.screen = screen
        self.az_settings = az_settings
        a = random.randint(97, 122)
        c = chr(a)
        self.image = pygame.image.load('images/' + c.upper() + '.png')
        self.ascii = a

        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()

        self.rect.centerx = random.randint(0, self.screen_rect.right)
        self.rect.top = self.screen_rect.top
        self.center = float(self.rect.centerx)



    def update(self):
        if self.rect.bottom < self.screen_rect.bottom:
            self.rect.centery += self.az_settings.letter_speed_factor

  1. 游戏功能.py
import sys
import pygame
from letter import Letter

def letter_generator(az_settings, screen, letters):
    new_letter = Letter(az_settings, screen)
    letters.add(new_letter)

def check_events(letters, stats, play_button):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            check_play_button(stats, play_button, mouse_x, mouse_y)
            print(stats.game_active)    # for test

        elif event.type == pygame.KEYDOWN:
            for ltr in letters:
                if ltr.ascii == event.key:
                    letters.remove(ltr)

def check_play_button(stats, play_button, mouse_x, mouse_y):
    if play_button.rect.collidepoint(mouse_x , mouse_y):
        stats.game_active = True


def letter_fallen(stats):
    if stats.lives_left > 0:
        stats.lives_left -= 1
    else:
        stats.game_active = False

def check_letter_bottom(screen, letters, stats):
    screen_rect = screen.get_rect()
    for ltr in letters.sprites():
        if ltr.rect.bottom > screen_rect.bottom:    # there might be some problems
            ltr.rect.bottom = screen_rect.bottom
            letter_fallen(stats)


def update_screen(az_settings, stats, screen, letters, play_button):
    screen.fill(az_settings.bg_color)
    check_letter_bottom(screen, letters, stats)
    letters.draw(screen)
    letters.update()
    if not stats.game_active:
        play_button.draw_button()
    pygame.display.flip()

标签: pygame

解决方案


显然我无法对此进行测试,但我认为你的问题是你没有为你的play_button.rect. 默认情况下,rect的位置值为(0, 0)。不久前我遇到了同样的问题,因此您可以阅读更多详细信息来回答这个问题。解决问题的一种方法 - 在按钮类中创建一个 getRect 方法:

class Button:
    def getRect(self):
         return pygame.Rect(x, y, width, height) # Since you will 
          #be using this rect for collision, enter the arguments accordingly

然后,

if play_button.getRect().collidepoint(mouse_x , mouse_y):

其他选项是直接将位置分配给按钮 rect 但我更喜欢第一个解决方案,它只是个人喜好:

class Button():
    def __init__(self, screen, msg):
        self.rect.topleft = #your button position

推荐阅读