-1

The title pretty much sums up the problem I am having. I am making a game using the Pygame library but the back and resume buttons keep on lagging and glitching. The back button is disappearing and reappearing multiple times in a second but it works great, meaning that it performs its designated function with one click (unlike the resume button). The resume button does not disappear and reappear numerous times per second however I need to press it multiple times in order for the game to actually resume. Please note that before I made a resume button, the 'L' key on my keyboard was responsible for resuming the game and the same issue was present, meaning I would have to press the 'L' key multiple times for the game to resume. So far, nothing else in the game is lagging.

The code in my main.py file comprised of 3 main functions: game_function(), settings_function() and main_menu_function(), the respective variables for each of the main functions, and other functions responsible for tasks such as pausing the game, drawing the spaceships, handling the bullets, etc...

The code in my Buttons_class.py file is simply 2 classes, some methods inside each class (such as the blit method, the check_for_input method, etc..) and the required variables. The first class is the Pause class and the second class is the Button_Pic class. Obviously, the Pause class is responsible for pausing the game and the Button_Pic class is responsible for the buttons.

I suspect that the problem is stemming from some issues in the game_function() in the main.py file. Here it is:

def game_function():
    global pause
    pause_text_object = Pause("PAUSED", 500, 500)
    red = pygame.Rect(700, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
    yellow = pygame.Rect(100, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)

    red_bullets = []
    yellow_bullets = []

    red_health = 10
    yellow_health = 10

    clock = pygame.time.Clock()
    run = True

    while run:
        clock.tick(FPS)
        game_mouse_pos = pygame.mouse.get_pos()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if BACK_BUTTON.check_for_input(game_mouse_pos):
                    main_menu_function()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q and len(yellow_bullets) < MAX_BULLETS:
                    bullet = pygame.Rect(
                        yellow.x + SPACESHIP_WIDTH, yellow.y + SPACESHIP_HEIGHT / 2 - BULLET_HEIGHT / 2, BULLET_WIDTH,
                        BULLET_HEIGHT)
                    yellow_bullets.append(bullet)

                if event.key == pygame.K_RSHIFT and len(red_bullets) < MAX_BULLETS:
                    bullet = pygame.Rect(
                        red.x, red.y + SPACESHIP_HEIGHT / 2 - 2, BULLET_WIDTH, BULLET_HEIGHT)
                    red_bullets.append(bullet)

                if event.key == pygame.K_RETURN:
                    make_pause_true()

            if event.type == RED_SHOT:
                red_health = red_health - 1

            if event.type == YELLOW_SHOT:
                yellow_health = yellow_health - 1

        winner_text = ""
        if red_health <= 0:
            winner_text = "Yellow Wins!"

        if yellow_health <= 0:
            winner_text = "Red Wins!"

        if winner_text != "":
            draw_winner(winner_text)
            break

        if pause:
            Button_Pic.blit(RESUME_BUTTON, WINDOW)
            Pause.draw_pause_text(pause_text_object)
            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if RESUME_BUTTON.check_for_input(game_mouse_pos) and pause:
                        pause = False

        else:

            keys_pressed = pygame.key.get_pressed()

            yellow_spaceship_movement(keys_pressed, yellow)
            red_spaceship_movement(keys_pressed, red)

            handle_bullets(yellow_bullets, red_bullets, yellow, red)

            draw_window(red, yellow, red_bullets, yellow_bullets,
                        red_health, yellow_health)

            Button_Pic.blit(BACK_BUTTON, WINDOW)

            pygame.display.update()

            pygame.event.pump()

    pygame.quit()

Here is the whole code in the main.py file:

import os
import pygame
import sys

from Buttons_Class import Pause
from Buttons_Class import Button_Pic

pygame.init()
pygame.font.init()
pygame.mixer.init()

## VARIABLES FOR GAME PAGE:

WINDOW_SIZE = (1280, 720)
WINDOW = pygame.display.set_mode(WINDOW_SIZE)

BORDER = pygame.Rect(1280 / 2 - 10 / 2, 0, 10, 720)

pygame.display.set_caption("Spaceship Duels")
PAUSE_TEXT_FONT = pygame.font.SysFont('arialblack', 50)
HEALTH_FONT = pygame.font.SysFont('arialblack', 30)
WINNER_FONT = pygame.font.SysFont('javanesetext', 80)

FONT_COLOR = (248, 248, 255)
BORDER_COLOR = (0, 0, 0)
RED_BULLET_COLOR = (248, 248, 255)
YELLOW_BULLET_COLOR = (248, 248, 255)
WINDOW_COLOR = (0, 0, 255)

FPS = 60

SPACESHIP_VELOCITY = 5
BULLET_VELOCITY = 8

MAX_BULLETS = 3
BULLET_WIDTH, BULLET_HEIGHT = 10, 5
SPACESHIP_WIDTH, SPACESHIP_HEIGHT = 55, 40

YELLOW_SHOT = pygame.USEREVENT + 1
RED_SHOT = pygame.USEREVENT + 2
pause = pygame.USEREVENT + 3
pygame.event.post(pygame.event.Event(pause))

pause = False

YELLOW_SPACESHIP_IMAGE = pygame.image.load(os.path.join(
    'Assets', 'spaceship_yellow.png'))
YELLOW_SPACESHIP = pygame.transform.rotate(
    pygame.transform.scale(YELLOW_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 90)

RED_SPACESHIP_IMAGE = pygame.image.load(os.path.join(
    'Assets', 'spaceship_red.png'))
RED_SPACESHIP = pygame.transform.rotate(pygame.transform.scale(
    RED_SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)), 270)

SPACE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'Space.jpeg')), (WINDOW_SIZE[0], WINDOW_SIZE[1]))

BACK_BUTTON_IMAGE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'back_button.png')), (300, 150))

BACK_BUTTON = Button_Pic(
    image=BACK_BUTTON_IMAGE,
    pos=(900, 500),
    base_color=(238, 59, 59),
    hovering_color=(0, 0, 205)
)

RESUME_BUTTON_IMAGE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'resume_button.png')), (300, 150))

RESUME_BUTTON = Button_Pic(
    image=RESUME_BUTTON_IMAGE,
    pos=(640, 460),
    base_color=(238, 59, 59),
    hovering_color=(0, 0, 205)
)

## VARIABLES FOR MAIN MENU PAGE:

MAIN_MENU_BACKGROUND = pygame.image.load((os.path.join('Assets', 'Background.jpeg')))

MENU_TEXT = PAUSE_TEXT_FONT.render("MAIN MENU", 1, FONT_COLOR)

MENU_RECT = MENU_TEXT.get_rect(center=(640, 100))

PLAY_BUTTON_IMAGE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'play_button.png')), (300, 100))

PLAY_BUTTON = Button_Pic(
    image=PLAY_BUTTON_IMAGE,
    pos=(640, 250),
    base_color=(238, 59, 59),
    hovering_color=(0, 0, 205)
)

SETTINGS_BUTTON_IMAGE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'settings_image.png')), (300, 100))

SETTINGS_BUTTON = Button_Pic(
    image=SETTINGS_BUTTON_IMAGE,
    pos=(640, 400),
    base_color=(238, 59, 59),
    hovering_color=(0, 0, 205)
)

QUIT_BUTTON_IMAGE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'quit_image.png')), (300, 100))

QUIT_BUTTON = Button_Pic(
    image=QUIT_BUTTON_IMAGE,
    pos=(640, 550),
    base_color=(238, 59, 59),
    hovering_color=(0, 0, 205)
)

## VARIABLES FOR SETTINGS PAGE:

SETTINGS_TEXT = PAUSE_TEXT_FONT.render("This is the SETTINGS screen.", 1, FONT_COLOR)

SETTINGS_RECT = SETTINGS_TEXT.get_rect(center=(640, 260))

SETTINGS_BACK_BUTTON_IMAGE = pygame.transform.scale(pygame.image.load(
    os.path.join('Assets', 'back_button.png')), (300, 150))

SETTINGS_BACK_BUTTON = Button_Pic(
    image=BACK_BUTTON_IMAGE,
    pos=(640, 460),
    base_color=(238, 59, 59),
    hovering_color=(0, 0, 205)
)


def draw_window(red, yellow, yellow_bullets, red_bullets, red_health, yellow_health):
    WINDOW.blit(SPACE, (0, 0))
    pygame.draw.rect(WINDOW, BORDER_COLOR, BORDER)
    red_health_text = HEALTH_FONT.render(
        "Health: " + str(red_health), 1, FONT_COLOR)
    yellow_health_text = HEALTH_FONT.render(
        "Health: " + str(yellow_health), 1, FONT_COLOR)
    WINDOW.blit(red_health_text, (WINDOW_SIZE[0] - red_health_text.get_width() - 10, 10))
    WINDOW.blit(yellow_health_text, (10, 10))

    WINDOW.blit(YELLOW_SPACESHIP, (yellow.x, yellow.y))
    WINDOW.blit(RED_SPACESHIP, (red.x, red.y))

    for bullet in red_bullets:
        pygame.draw.rect(WINDOW, RED_BULLET_COLOR, bullet)

    for bullet in yellow_bullets:
        pygame.draw.rect(WINDOW, YELLOW_BULLET_COLOR, bullet)

    pygame.display.update()


def yellow_spaceship_movement(keys_pressed, yellow):
    if keys_pressed[pygame.K_a] and yellow.x - SPACESHIP_VELOCITY > 0:  # left
        yellow.x = yellow.x + (-SPACESHIP_VELOCITY)
    if keys_pressed[pygame.K_d] and yellow.x + SPACESHIP_VELOCITY + SPACESHIP_WIDTH / 1.5 < BORDER.x:  # right
        yellow.x = yellow.x + SPACESHIP_VELOCITY
    if keys_pressed[pygame.K_w] and yellow.y - SPACESHIP_VELOCITY > 0:  # up
        yellow.y = yellow.y + (-SPACESHIP_VELOCITY)
    if keys_pressed[pygame.K_s] and yellow.y + SPACESHIP_VELOCITY + SPACESHIP_HEIGHT < WINDOW_SIZE[1] - 15:  # down
        yellow.y = yellow.y + SPACESHIP_VELOCITY


def red_spaceship_movement(keys_pressed, red):
    if keys_pressed[pygame.K_LEFT] and red.x - SPACESHIP_VELOCITY > BORDER.x + BORDER.width:
        red.x = red.x + (-SPACESHIP_VELOCITY)
    if keys_pressed[pygame.K_RIGHT] and red.x + SPACESHIP_VELOCITY + SPACESHIP_WIDTH / 1.5 < WINDOW_SIZE[0]:
        red.x = red.x + SPACESHIP_VELOCITY
    if keys_pressed[pygame.K_UP] and red.y - SPACESHIP_VELOCITY > 0:
        red.y = red.y + (-SPACESHIP_VELOCITY)
    if keys_pressed[pygame.K_DOWN] and red.y + SPACESHIP_VELOCITY + SPACESHIP_HEIGHT < WINDOW_SIZE[1] - 15:
        red.y = red.y + SPACESHIP_VELOCITY


def handle_bullets(yellow_bullets, red_bullets, yellow, red):
    for bullet in yellow_bullets:
        bullet.x = bullet.x + BULLET_VELOCITY
        if red.colliderect(bullet):
            pygame.event.post(pygame.event.Event(RED_SHOT))
            yellow_bullets.remove(bullet)
        elif bullet.x > WINDOW_SIZE[0]:
            yellow_bullets.remove(bullet)

    for bullet in red_bullets:
        bullet.x = bullet.x + (-BULLET_VELOCITY)
        if yellow.colliderect(bullet):
            pygame.event.post(pygame.event.Event(YELLOW_SHOT))
            red_bullets.remove(bullet)
        elif bullet.x < 0:
            red_bullets.remove(bullet)


def make_pause_true():
    global pause
    pause = True


def draw_winner(text):
    draw_text = WINNER_FONT.render(text, 1, FONT_COLOR)
    WINDOW.blit(draw_text, (WINDOW_SIZE[0] / 2 - draw_text.get_width() /
                            2, WINDOW_SIZE[1] / 2 - draw_text.get_height() / 2))
    pygame.display.update()
    pygame.time.delay(50000)


def game_function():
    global pause
    pause_text_object = Pause("PAUSED", 500, 500)
    red = pygame.Rect(700, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
    yellow = pygame.Rect(100, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)

    red_bullets = []
    yellow_bullets = []

    red_health = 10
    yellow_health = 10

    clock = pygame.time.Clock()
    run = True

    while run:
        clock.tick(FPS)
        game_mouse_pos = pygame.mouse.get_pos()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if BACK_BUTTON.check_for_input(game_mouse_pos):
                    main_menu_function()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q and len(yellow_bullets) < MAX_BULLETS:
                    bullet = pygame.Rect(
                        yellow.x + SPACESHIP_WIDTH, yellow.y + SPACESHIP_HEIGHT / 2 - BULLET_HEIGHT / 2, BULLET_WIDTH,
                        BULLET_HEIGHT)
                    yellow_bullets.append(bullet)

                if event.key == pygame.K_RSHIFT and len(red_bullets) < MAX_BULLETS:
                    bullet = pygame.Rect(
                        red.x, red.y + SPACESHIP_HEIGHT / 2 - 2, BULLET_WIDTH, BULLET_HEIGHT)
                    red_bullets.append(bullet)

                if event.key == pygame.K_RETURN:
                    make_pause_true()

            if event.type == RED_SHOT:
                red_health = red_health - 1

            if event.type == YELLOW_SHOT:
                yellow_health = yellow_health - 1

        winner_text = ""
        if red_health <= 0:
            winner_text = "Yellow Wins!"

        if yellow_health <= 0:
            winner_text = "Red Wins!"

        if winner_text != "":
            draw_winner(winner_text)
            break

        if pause:
            Button_Pic.blit(RESUME_BUTTON, WINDOW)
            Pause.draw_pause_text(pause_text_object)
            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if RESUME_BUTTON.check_for_input(game_mouse_pos) and pause:
                        pause = False

        else:

            keys_pressed = pygame.key.get_pressed()

            yellow_spaceship_movement(keys_pressed, yellow)
            red_spaceship_movement(keys_pressed, red)

            handle_bullets(yellow_bullets, red_bullets, yellow, red)

            draw_window(red, yellow, red_bullets, yellow_bullets,
                        red_health, yellow_health)

            Button_Pic.blit(BACK_BUTTON, WINDOW)

            pygame.display.update()

            pygame.event.pump()

    pygame.quit()


def settings_function():
    run = True
    while run:

        settings_mouse_pos = pygame.mouse.get_pos()

        WINDOW.fill((0, 0, 0))

        WINDOW.blit(SETTINGS_TEXT, SETTINGS_RECT)

        Button_Pic.blit(SETTINGS_BACK_BUTTON, WINDOW)
        SETTINGS_BACK_BUTTON.blit(WINDOW)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if SETTINGS_BACK_BUTTON.check_for_input(settings_mouse_pos):
                    main_menu_function()

        pygame.display.update()


def main_menu_function():
    run = True
    while run:

        WINDOW.blit(MAIN_MENU_BACKGROUND, (0, 0))

        menu_mouse_pos = pygame.mouse.get_pos()

        WINDOW.blit(MAIN_MENU_BACKGROUND, (0, 0))

        WINDOW.blit(MENU_TEXT, MENU_RECT)

        Button_Pic.blit(PLAY_BUTTON, WINDOW)

        Button_Pic.blit(SETTINGS_BUTTON, WINDOW)

        Button_Pic.blit(QUIT_BUTTON, WINDOW)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if PLAY_BUTTON.check_for_input(menu_mouse_pos):
                    game_function()
                elif SETTINGS_BUTTON.check_for_input(menu_mouse_pos):
                    settings_function()
                elif QUIT_BUTTON.check_for_input(menu_mouse_pos):
                    pygame.quit()
                    sys.exit()

        pygame.display.update()


main_menu_function()

if __name__ == "__main__":
    game_function()

Here is the whole code in the Buttons_class.py file:

import pygame

pygame.init()
pygame.font.init()

PAUSE_TEXT_FONT = pygame.font.SysFont('arialblack', 50)
WINDOW_SIZE = (1280, 720)
WINDOW = pygame.display.set_mode(WINDOW_SIZE)
FONT_COLOR = (248, 248, 255)


class Pause:
    def __init__(self, text, x_pos, y_pos, enabled=True):
        self.text = text
        self.enabled = enabled
        self.x_pos = x_pos
        self.y_pos = y_pos

    def draw_pause_text(self):
        pause_text = PAUSE_TEXT_FONT.render(self.text, True, FONT_COLOR)
        WINDOW.blit(pause_text, (self.x_pos, self.y_pos))


class Button_Pic:
    def __init__(self, image, pos, base_color, hovering_color):
        self.image = image
        self.x_pos = pos[0]
        self.y_pos = pos[1]
        self.base_color = base_color
        self.hovering_color = hovering_color
        self.rect = self.image.get_rect(center=(self.x_pos, self.y_pos))

    def blit(self, window):
        window.blit(self.image, self.rect)

    def check_for_input(self, position):
        if position[0] in range(self.rect.left, self.rect.right) and position[1] in range(self.rect.top,
                                                                                          self.rect.bottom):
            return True

        else:
            return False

In order to fix the problem with the pause button, I tried to put the 'if pause' if statement which is responsible for checking if the pause event is True, outside of the else: statement which is right after the while run loop. Instead, I put the 'if pause' statement closer to the top of the function.

def game_function():
    global pause
    pause_text_object = Pause("PAUSED", 500, 500)
    red = pygame.Rect(700, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
    yellow = pygame.Rect(100, 300, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)

    red_bullets = []
    yellow_bullets = []

    red_health = 10
    yellow_health = 10

    clock = pygame.time.Clock()
    run = True

    if pause:
        Button_Pic.blit(RESUME_BUTTON, WINDOW)
        Pause.draw_pause_text(pause_text_object)
        pygame.display.update()

        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                if RESUME_BUTTON.check_for_input(game_mouse_pos) and pause:
                    pause = False


    while run:
        clock.tick(FPS)
        game_mouse_pos = pygame.mouse.get_pos()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                if BACK_BUTTON.check_for_input(game_mouse_pos):
                    main_menu_function()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q and len(yellow_bullets) < MAX_BULLETS:
                    bullet = pygame.Rect(
                        yellow.x + SPACESHIP_WIDTH, yellow.y + SPACESHIP_HEIGHT / 2 - BULLET_HEIGHT / 2, BULLET_WIDTH,
                        BULLET_HEIGHT)
                    yellow_bullets.append(bullet)

                if event.key == pygame.K_RSHIFT and len(red_bullets) < MAX_BULLETS:
                    bullet = pygame.Rect(
                        red.x, red.y + SPACESHIP_HEIGHT / 2 - 2, BULLET_WIDTH, BULLET_HEIGHT)
                    red_bullets.append(bullet)

                if event.key == pygame.K_RETURN:
                    make_pause_true()

            if event.type == RED_SHOT:
                red_health = red_health - 1

            if event.type == YELLOW_SHOT:
                yellow_health = yellow_health - 1

        winner_text = ""
        if red_health <= 0:
            winner_text = "Yellow Wins!"

        if yellow_health <= 0:
            winner_text = "Red Wins!"

        if winner_text != "":
            draw_winner(winner_text)
            break

   
        else:

            keys_pressed = pygame.key.get_pressed()

            yellow_spaceship_movement(keys_pressed, yellow)
            red_spaceship_movement(keys_pressed, red)

            handle_bullets(yellow_bullets, red_bullets, yellow, red)

            draw_window(red, yellow, red_bullets, yellow_bullets,
                        red_health, yellow_health)

            Button_Pic.blit(BACK_BUTTON, WINDOW)

            pygame.display.update()

            pygame.event.pump()

    pygame.quit()

all that did was stop the button (and the pause text) from appearing at all. Please ignore any indentation issues since they only appeared here on stack over flow and are not present in my actual code in the Pycharm IDE.

In order to fix the issue with the resume button, I tried to put the 'Button_Pic.blit(BACK_BUTTON, WINDOW) string literally anywhere else in the game function but everywhere I placed it led to the button not appearing at all.

All input/help/advice is appreciated. There are no questions on stack over flow that address this exact problem so I would appreciate if the question is not removed.

yzdanh
  • 1
  • 2

0 Answers0