kafka
kafka

Reputation: 129

why doesn't play_button.rect.collidepoint(mouse_x , mouse_y) function?

This is a typing game in Python. Click the 'Play' button and the game is supposed to start. Random letters will fall down and each letter will disappear when you strike the corresponding key. However, it failed to begin when I click on the button. I think the problem must be related to the if statements if play_button.rect.collidepoint(mouse_x , mouse_y): in method check_play_button() of game_functions.py since if the if statement is removed, the stats.game_active is changed to True. On the other hand, if the if statement is removed, then click anywhere on the screen would change the value of stats.game_active to True. I am quite puzzled about the malfunction of the if statement. Please shed light on it. Here are my codes( a bit long but a challenge:P):

  1. alphabet_zoo.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. button.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. settings.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. letter.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. game_functions.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()

Upvotes: 1

Views: 105

Answers (1)

user12291970
user12291970

Reputation:

Obviously I cannot test this but I think your problem is that you are not assigning position to your play_button.rect. By default, rect's positions values are (0, 0). I had the same problem a little while ago, so you are read some more details in answer to this question. One way to fix the problem - in button class make a getRect method:

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

Then,

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

Other option is to directly assign position to the button rect but I prefer the first solution, its just a personal preference:

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

Upvotes: 2

Related Questions