Search code examples
pythonpython-3.xpygamelag

Pygame makes the game unplayable with lag


I am making a game where you just click on the circles, and i just got it working when i noticed the game really laggs out sometimes. It just would not generate new position. This is my code:

import pygame
from pygame.font import SysFont
from pygame.display import flip
from random import randint, choice

# Bools
r = True
title = True
game = False

# Floats

# Ints
points = 0
deletewhat = [True, False]

# Strings

# Lists
spots = []
pointchoice = [1,1,1,2]

# Colors
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
YELLOW = (255,255,0)
GRAY = (20,20,20)

# Pygame init
pygame.init()
pygame.font.init()

# Pygame userevents
delete = pygame.USEREVENT

# Pygame timers
pygame.time.set_timer(delete, 1000)

# Pygame Fonts
titlefont = SysFont("Arial", 70)
headfont = SysFont("Arial", 20)
startfont = SysFont("Arial", 80)
pointsfont = SysFont("Arial", 25)

# Pygame font one-time render
titletext = titlefont.render("The Spot Spotter", False, BLACK)
headtext = headfont.render("Click the spots and earn points!", False, BLACK)
starttext = startfont.render("START", False, RED)

# Other Pygame things
screen = pygame.display.set_mode((900,750))

class Spot:
    def __init__(self, x, y, points):
        global WHITE, GRAY
        self.x = x
        self.y = y
        self.points = points
        if self.points == 1:
            self.spotcolor = WHITE
        else:
            self.spotcolor = GRAY

    def draw(self):
        pygame.draw.ellipse(screen, self.spotcolor, (self.x, self.y, 50,50))

    def get_pos(self):
        return self.x, self.y

    def get_points(self):
        return self.points

spot = Spot
while r:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            r = False
        if event.type == delete and game:
            deleteone = choice(deletewhat)
            if deleteone:
                spot1 = spot(randint(20, 880), randint(20, 600), choice(pointchoice))
                spot1ready = True

                spot2 = spot(randint(20, 880), randint(20, 600), choice(pointchoice))
                spot2ready = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse = pygame.mouse.get_pos()
            if mouse[0] > 249 and mouse[0] < 801:
                if mouse[1] > 299 and mouse[1] < 426:
                    if title:
                        title = False
                        game = True
            try:
                spot1.get_pos()
            except NameError:
                pass
            else:
                spot1pos = spot1.get_pos()
                if mouse[0] > (spot1pos[0] - 1) and mouse[0] < (spot1pos[0] + 51):
                    if mouse[1] > (spot1pos[1] - 1) and mouse[1] < (spot1pos[1] + 51):
                        if spot1ready:
                            spot1ready = False
                            points += spot1.get_points()
            try:
                spot2.get_pos()
            except NameError:
                pass
            else:
                spot2pos = spot2.get_pos()
                if mouse[0] > (spot2pos[0] - 1) and mouse[0] < (spot2pos[0] + 51):
                    if mouse[1] > (spot2pos[1] - 1) and mouse[1] < (spot2pos[1] + 51):
                        if spot2ready:
                            spot2ready = False
                            points += spot2.get_points()

    if title:
        screen.fill(WHITE)
        screen.blit(titletext, (250, 0))
        screen.blit(headtext, (350, 100))
        pygame.draw.rect(screen, YELLOW, (200, 300, 550, 125)) # Start Button
        screen.blit(starttext, (375, 315))
        flip()
    elif game:
        pointstext = pointsfont.render(f"Points: {points}", False, BLACK)
        screen.fill(BLACK)
        pygame.draw.rect(screen, WHITE, (0, 600, 900, 150))
        screen.blit(pointstext, (20, 610))
        try:
            spot1.draw()
        except NameError:
            pass
        else:
            spot1.draw()

        try:
            spot2.draw()
        except NameError:
            pass
        else:
            spot2.draw()

        flip()


pygame.quit()

If you are wondering, the bools game and title are both for detecting which tab needs to be rendered. if game is true and title is false then the game knows hey, i need to render the game.

Also please note that i am not that good in pygame.


Solution

  • The problem is the line deleteone = choice(deletewhat). This may generate multiple False in a row.

    Add a variable wait_delete. Decrement the variable when the delete event occurs. Set a new random value with randint if wait_delete is 0.

    wait_delete = 1
    spot = Spot
    while r:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                r = False
    
            if event.type == delete and game:
                wait_delete -= 1
                if wait_delete == 0:
                    wait_delete = randint(1, 3)
    
                    spot1 = spot(randint(20, 880), randint(20, 600), choice(pointchoice))
                    spot1ready = True
    
                    spot2 = spot(randint(20, 880), randint(20, 600), choice(pointchoice))
                    spot2ready = True
            # [...]