如何使我的子弹击中某物后产生动画效果

2024-04-25 05:14:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我想让它,当我的子弹达到一定的距离,它通过爆炸动画,然后删除自己。我可以让它自己删除,但我不知道如何正确地动画它

        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])

以上代码的问题是,它在动画中运行得太快。我不知道如何使它变慢


Tags: inrectfor动画pygameremovebullet子弹
1条回答
网友
1楼 · 发布于 2024-04-25 05:14:05

您似乎已经使用了Sprite类,因此很容易在sprite中跟踪时间

你应该做的是使用所谓的delta时间。基本上,你需要测量渲染一帧所需的时间,并将该值传递给游戏中“穿越时间”的每个部分。所以当最后一帧用了X毫秒时,一个以S的速度移动的精灵会移动S*X像素。如果下一帧采用Y ms,则相同的精灵将移动S*Y像素

在pygame中,通常使用Clock来限制调用其tick方法的帧速率。此方法还将返回自上次调用以来经过的毫秒数。所以这个值是我们传递给sprite的update方法的delta时间

因为现在每个精灵都知道每一帧经过了多少时间,所以我们可以创建一个实例变量(我们称之为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

相关问题 更多 >