Pygame : Repeating an action every x amount of time

ngong123 :

I am a beginner in Python learning to build a simple game in Pygame where the player(monkey) tries to catch as many bananas as possible falling from the top of the screen.

My problem is how to get the bananas to spawn and fall individually every x time/seconds. Either they all spawn at once or if I use time.sleep, pauses the bananas midair. Even used threading after getting completely lost.

The relevant components of my code are as follows:

catch_game

import sys

import pygame
from pygame.sprite import Group

from settings import Settings
# from background import Background
from monkey import Monkey
from banana import Banana

import functions

def run_game():
    pygame.init()
    settings = Settings()
    screen = pygame.display.set_mode((settings.screen_width, settings.screen_height))
    pygame.display.set_caption('Monkey Catch')

    monkey = Monkey(screen, settings)
    # background = Background((0, 0), screen)
    bananas = Group()

    functions.create_banana(screen, settings, bananas)

    while True:
        monkey.movement()
        functions.check_events(monkey)
        functions.update_screen(screen, settings, monkey, bananas)
        functions.update_banana(monkey, bananas)





run_game()

banana

import pygame
from pygame.sprite import Sprite
from random import randint


class Banana(Sprite):
    def __init__(self, screen, settings):
        super(Banana, self).__init__()
        self.screen = screen
        self.settings = settings


        self.image = pygame.image.load('E:\PycharmProjects\catch\images/banana.png')
        self.rect = self.image.get_rect()
        self.screen_rect = self.screen.get_rect()

        self.y = self.screen_rect.top
        self.y = float(self.rect.y)

        self.x = randint(0, 1150)

        self.speed = settings.banana_fallspeed

    def update(self):
        '''Banana falls down'''
        self.y += self.settings.banana_fallspeed

        self.rect.y = self.y
        self.rect.x = self.x

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

functions

import pygame
import sys
from banana import Banana
import threading
import time


def update_screen(screen, settings, monkey, bananas):
    screen.fill([255, 255, 255])
    # background.blit()
    monkey.blit()

    for banana in bananas:
        banana.update()
        bananas.draw(screen)

    pygame.display.flip()


def keydown_events(event, monkey):
    if event.key == pygame.K_RIGHT:
        monkey.moving_right = True
    if event.key == pygame.K_LEFT:
        monkey.moving_left = True


def keyup_events(event, monkey):
    if event.key == pygame.K_RIGHT:
        monkey.moving_right = False
    if event.key == pygame.K_LEFT:
        monkey.moving_left = False


def check_events(monkey):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN:
            keydown_events(event, monkey)
        if event.type == pygame.KEYUP:
            keyup_events(event, monkey)


def create_banana(screen, settings, bananas):
        banana = Banana(screen, settings)
        bananas.add(banana)


def update_banana(monkey, bananas):
    '''kill bananas, collisions with monkey'''
    for banana in bananas.copy():
        if banana.rect.bottom >= 720:
            bananas.remove(banana)
    collision = pygame.sprite.spritecollide(monkey, bananas, True)
    if collision:
        bananas.remove(banana)


        # time.sleep(2)
        # fall_interval = banana.threading.Timer(3, create_banana(screen, settings, bananas))
        # fall_interval.start()




Rabbid76 :

I recommend to use a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:

banana_delay = 500 # 0.5 seconds
banana_event = pygame.USEREVENT + 1
pygame.time.set_timer(banana_event, banana_delay)

Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case pygame.USEREVENT+1 is the event id for the timer event, which spawns the bullets.

Create a new banana when the event occurs in the event loop:

def check_events(screen, settings, bananas, monkey):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        # [...]

        if event.type == banana_event:
            create_banana(screen, settings, bananas)

The timer event can be stopped by passing 0 to the time parameter.


If you want spawn the bananas by a random time spawn, then you have to change the timespan (in milliseconds) randomly. Use random.randint(a, b) to generate random times:

if event.type == banana_event:
    create_banana(screen, settings, bananas)
    banana_delay = random.randint(500, 3000) # random from 0.5 to 3 seconds
    pygame.time.set_timer(banana_event, banana_delay)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=15555&siteId=1