Search code examples
python-2.7pygamepygame-clock

How to set waits for object in pygame without freezing other objects


Lets say I have class Truck. There are many instances of this class, on arrival to specific point instance should "unload" it's cargo - simply not move for N seconds, while other trucks should keep moving, unless they arrived to their unloading points.

I do the stop part by setting movement vector to (0,0) and then resetting it back to original.

But how to wait N seconds without freezing other cars? From what I've found so far I think I need to somehow apply pygame.time.set_timer, but it is really confusing for me.


Solution

  • Something along these lines should work: Stop the truck when the target is reached (truck.vel = Vector2(0, 0)) and then set its waiting_time and start_time attributes (I just do it in the __init__ method here).

    import pygame as pg
    from pygame.math import Vector2
    
    
    class Truck(pg.sprite.Sprite):
    
        def __init__(self, pos, waiting_time, *groups):
            super().__init__(*groups)
            self.image = pg.Surface((50, 30))
            self.image.fill(pg.Color('steelblue2'))
            self.rect = self.image.get_rect(center=pos)
            self.vel = Vector2(0, 0)
            self.pos = Vector2(pos)
            self.waiting_time = waiting_time  # In seconds.
            self.start_time = pg.time.get_ticks()
    
        def update(self):
            current_time = pg.time.get_ticks()
            # * 1000 to convert to milliseconds.
            if current_time - self.start_time >= self.waiting_time*1000:
                # If the time is up, start moving again.
                self.vel = Vector2(1, 0)
    
            self.pos += self.vel
            self.rect.center = self.pos
    
    
    def main():
        screen = pg.display.set_mode((640, 480))
        clock = pg.time.Clock()
        all_sprites = pg.sprite.Group()
        truck = Truck((70, 70), 4, all_sprites)
        truck2 = Truck((70, 300), 2, all_sprites)
    
        done = False
    
        while not done:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
    
            all_sprites.update()
            screen.fill((30, 30, 30))
            all_sprites.draw(screen)
    
            pg.display.flip()
            clock.tick(30)
    
    
    if __name__ == '__main__':
        pg.init()
        main()
        pg.quit()
    

    Here's the dt version:

    import pygame as pg
    from pygame.math import Vector2
    
    
    class Truck(pg.sprite.Sprite):
    
        def __init__(self, pos, waiting_time, *groups):
            super().__init__(*groups)
            self.image = pg.Surface((50, 30))
            self.image.fill(pg.Color('steelblue2'))
            self.rect = self.image.get_rect(center=pos)
            self.vel = Vector2(0, 0)
            self.pos = Vector2(pos)
            self.waiting_time = waiting_time
    
        def update(self, dt):
            self.waiting_time -= dt
            if self.waiting_time <= 0:
                self.vel = Vector2(1, 0)
    
            self.pos += self.vel
            self.rect.center = self.pos
    
    
    def main():
        screen = pg.display.set_mode((640, 480))
        clock = pg.time.Clock()
        all_sprites = pg.sprite.Group()
        truck = Truck((70, 70), 4, all_sprites)
        truck2 = Truck((70, 300), 2, all_sprites)
    
        done = False
    
        while not done:
            dt = clock.tick(30) / 1000
    
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    done = True
    
            all_sprites.update(dt)
            screen.fill((30, 30, 30))
            all_sprites.draw(screen)
    
            pg.display.flip()
    
    
    if __name__ == '__main__':
        pg.init()
        main()
        pg.quit()