Is it possible to do a delay in python without stopping the program?

1

Hello today I asked myself if it would be possible to do a delay in the background or something so that the program does not stop. Is it possible?

I would like to have a rectangle moved to a position x every 2 seconds and after another 2 seconds it disappears. All this without stopping the other processes.

Edition:

After doing the code I have a problem. When it disappears exactly twice as long as it appears there is a problem and it does not disappear because the appearance and disappearance contradict each other.

Code to explain better:

here is the class:

class Laser1(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("sprites/laserH.png")
        self.rect = self.image.get_rect()
        self.rect.left = 176
        self.rect.top = 400

    def update(self, dt):
        pass    

    def move_1(self, dt):
        self.rect.left = 176
        self.rect.top = 400

    def move_2(self, dt):
        self.rect.left = 1000
        self.rect.top = 700       

here are the timers:

pygame.time.set_timer(pygame.USEREVENT + 1, 700)
pygame.time.set_timer(pygame.USEREVENT + 2, 1400)

here is the event detection:

for event in pygame.event.get():
    if event.type == QUIT:
        pygame.quit()
        sys.exit()
    elif event.type == pygame.USEREVENT + 1:
        laser1.move_1(dt)        

    elif event.type == pygame.USEREVENT + 2:
        laser1.move_2(dt)

It's as if USEREVENT + 2 never happened. Some help? Thanks.

    
asked by ElAlien123 02.03.2018 в 22:56
source

1 answer

2

In PyGame there are two methods that can and usually are used for this type of tasks:

  • pygame.time.get_ticks : This method gives us the last milliseconds since pygame.init() was called.

  • pygame.time.set_timer : It allows to launch an event repetitively every x milliseconds and that we can capture in the event queue and launch a response when that event is present.

In principle with both methods we can play enough to adapt to a multitude of situations that require timing or schedule certain tasks without blocking of course the mainloop.

To illustrate its use a little we will see two examples:

Sprite changes position every x time repetitively.

An example is the tetrix pieces. For this we can use pygame.time.set_timer . Of course, the possibilities are not limited to moving the object, we can perform any task repetitively every x milliseconds.

We can make multiple calls to pygame.time.set_timer , each one will have its own timer and will place the assigned event when it touches the event queue.

To stop a timer for a given event, simply re-call the method by passing 0 in the second argument (milliseconds).

import sys
import random
import pygame
from pygame.locals import *



ANCHO = 400
ALTO = 200
NEGRO = (0, 0, 0)
FPS = 60


class Square(pygame.sprite.Sprite):
    def __init__(self):
        super(Square, self).__init__()
        self.image = pygame.image.load("square.png")
        self.rect = self.image.get_rect()
        self.rect.centery = ALTO / 2


    def move(self):
        new_x = self.rect.left + ((ANCHO-self.rect.width)/4)
        if new_x > ANCHO:
            new_x = 0
        self.rect.left = new_x



def game():
    pygame.init()
    pygame.key.set_repeat(1, 25)

    all_sprites = pygame.sprite.Group()

    square = Square()
    all_sprites.add(square)

    ventana = pygame.display.set_mode((ANCHO, ALTO))
    pygame.display.set_caption("Game")
    fps_clock = pygame.time.Clock()

    # Creamos nuestro timer, que lanzará el evento cada segundo (1000 ms)
    pygame.time.set_timer(pygame.USEREVENT + 1, 1000)

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            # comprobamos si el timer ha lanzado el evento
            ## En caso afirmativo llamamos al método move del sprite.
            elif event.type == pygame.USEREVENT + 1:
                square.move()

        dt = fps_clock.tick(FPS) / 1000.0
        all_sprites.update(dt)
        ventana.fill(NEGRO)
        all_sprites.draw(ventana)
        pygame.display.flip()


if __name__ == "__main__":
    game()

Make a sprite move to a certain position after two seconds since it was created and after another two seconds it will be destroyed.

This is something similar in principle to what you want, in this case we are going to use pygame.time.get_ticks . Pressing the space creates a new sprite (limited to 5 simultaneous sprites), when 2 seconds pass since it is created it moves to the center of the screen, after another two seconds it disappears:

import sys
import random
import pygame
from pygame.locals import *



ANCHO = 700
ALTO = 695
NEGRO = (0, 0, 0)
FPS = 60


class Square(pygame.sprite.Sprite):
    def __init__(self):
        super(Square, self).__init__()
        self.image = pygame.image.load("square.png")
        self.rect = self.image.get_rect()
        self.rect.center=(random.randrange(self.rect.width//2, ANCHO-self.rect.width//2),
                          random.randrange(self.rect.height//2, ALTO-self.rect.height//2))
        self.init_ticks = pygame.time.get_ticks()


    def update(self, dt):
        # Comprobamos los milisegundos que tiene el sprite de existencia
        ticks = pygame.time.get_ticks() - self.init_ticks

        # Si han pasado mas de 4 segundos desde que se creo lo destruimos
        if ticks >= 4000:
            self.kill()

        # Si han pasado  2 segundos desde que se creo lo movemos
        elif ticks >= 2000:
            self.rect.centerx = ANCHO/2



def game():
    pygame.init()
    pygame.key.set_repeat(1, 25)

    all_sprites = pygame.sprite.Group()
    squares = pygame.sprite.Group()

    ventana = pygame.display.set_mode((ANCHO, ALTO))
    pygame.display.set_caption("Game")
    fps_clock = pygame.time.Clock()


    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

            elif event.type == KEYDOWN:
                if event.key == K_SPACE and len(squares) < 5:
                    square = Square()
                    squares.add(square)
                    all_sprites.add(square)

        dt = fps_clock.tick(FPS) / 1000.0
        all_sprites.update(dt)
        ventana.fill(NEGRO)
        all_sprites.draw(ventana)
        pygame.display.flip()


if __name__ == "__main__":
    game()

There are only two simple examples to try to illustrate a general idea, depending on the particular situation we can adapt the code to cover the specific needs.

If someone wants to reproduce the examples, this is the sprite used ( square.png ):

    
answered by 03.03.2018 / 14:12
source