Как оживить мои пули после удара - PullRequest
1 голос
/ 26 октября 2019

Я хочу сделать так, чтобы, когда моя пуля достигла определенного расстояния, она прошла анимацию взрыва и затем удалилась. Я могу удалить его сам, но не знаю, как его правильно оживить.

        enemyShotList = pygame.sprite.spritecollide(bullet, enemyGroup, False)

        for enemy in enemyShotList:
            enemyGroup.remove(enemy)
            bulletGroup.remove(bullet)

        currentBulletTime = pygame.time.get_ticks()
        currentbulletx = bullet.rect.x
        currentbullety = bullet.rect.y
        if currentBulletTime - bullet.originalBulletTime > 700:
            bulletGroup.remove(bullet)
            for i in range(0,15):
                screen.blit(bulletpopList[i], [currentbulletx,currentbullety])

Проблема с приведенным выше кодом заключается в том, что он слишком быстро проходит анимацию. Я не знаю, как его оживить, чтобы он был медленнее.

1 Ответ

1 голос
/ 28 октября 2019

Кажется, вы уже используете класс Sprite, поэтому легко отслеживать время внутри ваших спрайтов.

Что вам нужно сделать, это использовать так называемое дельта-время. По сути, вы измеряете время, необходимое для визуализации кадра, и передаете это значение в каждую часть игры, которая «движется во времени». Поэтому, когда последний кадр занял X мс, спрайт, который движется со скоростью S, перемещает S * X пикселей. Если следующий кадр занимает Y мс, тот же спрайт будет перемещать S * Y пикселей.

В pygame вы обычно используете Clock для ограничения частоты кадров, вызывая его метод tick. Этот метод также возвращает количество миллисекунд, прошедших с момента предыдущего вызова. Таким образом, это значение является нашим дельта-временем, которое мы передаем методу update наших спрайтов.

Так как теперь каждый спрайт знает каждый кадр, сколько прошло времени, мы можем сделать более медленную анимацию, создав переменную экземпляра. (давайте назовем его timer), установите его значение равным количеству миллисекунд, которое мы хотим ждать, и вычтите время дельты (назовем его dt) каждого кадра. Как только мы нажимаем <= 0, мы сбрасываем timer и меняем изображение спрайта.

Вот рабочий пример, который я взломал вместе. Стреляйте в красную ракету, нажимая любую клавишу, и попробуйте поразить синие цели. Смотрите удивительные взрывы!

import pygame
import random

TILESIZE = 32

# Since our sprites are very generic, we want to be able
# to set some attributes while creating them.
# Here we create a set of allowed options.
ACTOR_OPTIONS = set(['can_be_destroyed'])

# guess what
def random_color():
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)

# A generic Sprite class. 
# It takes a position, a velocity, a color, a function that
# controls its behaviour, and keyworded arguments.
class Actor(pygame.sprite.Sprite):
    def __init__(self, pos, vel, color, handler, all_sprites, **kwargs):
        super().__init__(all_sprites)
        # A timer and counter attribute to handle time based stuff.
        self.timer = 0
        self.counter = 0
        # Update the sprite attributes with the keyworded arguments. 
        # We only allow the keys defined in ACTOR_OPTIONS.
        self.__dict__.update(kwargs)
        self.__dict__.update((key, False) for key in ACTOR_OPTIONS)
        self.__dict__.update((key, value) for key, value in kwargs.items() if key in ACTOR_OPTIONS)
        # We keep a reference to a sprite groups that contains all sprites
        # so we can access them easily
        self.all_sprites = all_sprites
        # Simple non-colored image 
        self.image = pygame.Surface((TILESIZE, TILESIZE))
        self.image.fill(pygame.Color(color))
        self.rect = self.image.get_rect(center=pos)
        # Position and velocity as Vectors for easier math
        self.pos = pygame.Vector2(pos)
        self.vel = pygame.Vector2(vel)
        # The handler function that we're going to call each frame
        self.handler = handler

    def update(self, dt, events):
        # Let the handler function to their thing
        self.handler(self, dt, events)
        # Move the sprite
        self.pos += (self.vel * dt/10)
        self.rect.center = [int(x) for x in self.pos]

# Our sprites are very generic, so here we create some functions
# that will control the behaviour of the sprites.
# We could have created new classes and implement the update-function instead,
# but this function-approach allows us to change the behaviour of a sprite
# at runtime by setting the handler attribute

def target_handler(actor, dt, events):
    screen_rect = pygame.display.get_surface().get_rect()

    # A target does nothing but changing its direction when hittin the screen edges.
    # Note that this implementation does not handle edge cases like a huge delta time.
    if not screen_rect.contains(actor.rect):
        actor.vel *= -1

def rocket_handler(actor, dt, events):
    # A rocket will disappear when leaving the screen
    screen_rect = pygame.display.get_surface().get_rect()
    if not screen_rect.colliderect(actor.rect):
        actor.kill()

    # but when it hits a sprite with the can_be_destroyed-flag...
    collisions = pygame.sprite.spritecollide(actor, actor.all_sprites, False)
    for c in collisions:
        if c.can_be_destroyed:
            # ...we remove both sprites 
            actor.kill()
            c.kill()
            # ...and create to explosion sprites
            Actor(actor.pos, ( 0, 0), 'yellow', explosion_handler, actor.all_sprites, timer=100)
            Actor(c.pos, ( 0, 0), 'orange', explosion_handler, actor.all_sprites, timer=50)

def explosion_handler(actor, dt, events):
    # An explosion will change its color 15 times
    # every 100 milliseconds.
    if actor.timer:
        actor.timer -= dt
        if actor.timer <= 0:
            actor.image.fill(random_color())
            actor.timer = 100
            actor.counter += 1
    if actor.counter >= 15:
        actor.kill()

# Standard pygame main loop
def main():
    width, height = 640, 480
    pygame.init()
    screen = pygame.display.set_mode((width, height))
    clock = pygame.time.Clock()
    sprites = pygame.sprite.Group()
    dt = 0

    # We create three targets
    Actor((20, 20), ( 2,  0), 'dodgerblue', target_handler, sprites, can_be_destroyed=True)
    Actor((120, 120), ( 2,  0), 'dodgerblue', target_handler, sprites, can_be_destroyed=True)
    Actor((320, 220), ( 2,  0), 'dodgerblue', target_handler, sprites, can_be_destroyed=True)

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
            if e.type == pygame.KEYDOWN:
                # Fire a rocket when we press a key
                Actor((320, 479), ( 0, -4), 'red', rocket_handler, sprites)

        sprites.update(dt, events)
        screen.fill((20, 20, 20))
        sprites.draw(screen)
        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...