Python 如何使我的子弹击中物体后产生动画效果
我想这样,当我的子弹到达一定距离时,它会通过爆炸动画,然后自行移除。我可以让它自己移除,但我不知道如何正确地设置动画Python 如何使我的子弹击中物体后产生动画效果,python,pygame,Python,Pygame,我想这样,当我的子弹到达一定距离时,它会通过爆炸动画,然后自行移除。我可以让它自己移除,但我不知道如何正确地设置动画 enemyShotList = pygame.sprite.spritecollide(bullet, enemyGroup, False) for enemy in enemyShotList: enemyGroup.remove(enemy) bulletGroup.remove(bullet)
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])
上述代码的问题是,它在动画中运行得太快。我不知道如何设置它的动画以使它变慢。您似乎已经使用了
精灵类,因此很容易跟踪精灵中的时间
你应该做的是使用所谓的增量时间。基本上,您可以测量渲染帧所需的时间,并将该值传递给游戏中“随时间移动”的每个部分。因此,当最后一帧的时间为X ms时,以S的速度移动的精灵会移动S*X像素。如果下一帧采用Y毫秒,则同一精灵将移动S*Y像素
在pygame中,您通常使用时钟
来限制调用其勾选
方法的帧速率。此方法还将返回自上次调用以来经过的毫秒数。所以这个值是我们传递给sprite的update
方法的delta时间
因此,由于现在每个精灵都知道每一帧经过了多少时间,我们可以通过创建一个实例变量(我们称之为timer
),将其值设置为我们希望等待的毫秒数,并减去每一帧的增量时间(我们称之为dt
)。一旦我们点击了,如果你可以冻结游戏的其余部分,只需在动画循环中添加一个time.sleep()
。@Valentino我需要游戏在冻结时不要被冻结。如果更复杂,你需要完全重新设计动画,并将其移动到游戏的主循环中。不能在单独的循环中循环bulletpopList
。它将冻结游戏的其余部分。你缺少的技术是控制精灵的速度。用这些关键词进行研究;在线上有很多活跃的PyGame动画的例子。
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()