改变精灵动画速度(pygame)
Posted
技术标签:
【中文标题】改变精灵动画速度(pygame)【英文标题】:Changing Sprite animation Speed (pygame) 【发布时间】:2018-08-20 14:22:39 【问题描述】:我设法使用我创建的“动画”功能为我的播放器设置动画 - 在角色移动时循环遍历每帧的角色图像列表。但是,我也发现这与游戏运行的速度相同;并希望有一种简单的方法来改变它,使精灵的动画速度比游戏 FPS 慢。
这是我的精灵类代码:
class Civilian(pg.sprite.Sprite):
def __init__(self, game, x, y):
self.groups = game.all_sprites, game.player1group, game.bothplayers
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self._layer = PLAYER1_LAYER
self.image = pg.Surface((61, 67))
self.rect = self.image.get_rect()
self.hit_rect = PLAYER_HIT_RECT
self.hit_rect.center = self.rect.center
self.playerspeed = 90
self.vel = vec(0, 0)
self.pos = vec(x , y)
self.move = 0
self.speedboost = False
self.last_dir = 'down'#
self.anim_speed = 0
def animate(self, direction):
if direction == 'right':
self.spritesheet = pg.image.load('walk right civ.png') # Loading the right directional movement spritesheet into the variable
if direction == 'left':
self.spritesheet = pg.image.load('walk left civ.png')
if direction == 'up':
self.spritesheet = pg.image.load('walk up civ.png')
if direction == 'down':
self.spritesheet = pg.image.load('walk down civ.png')
self.frames = [] # List which will contain each cell of the spritesheet
# Adding the cells to the list #
self.frames.append(self.spritesheet.subsurface(pg.Rect(0, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(61, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(122, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(183, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(244, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(305, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(366, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(427, 0, 61, 67)).convert_alpha())
self.frames.append(self.spritesheet.subsurface(pg.Rect(488, 0, 61, 67)).convert_alpha())
# Number of frames/cells
self.frames_number = len(self.frames)
# Current animation frame
self.current_frame = 0
# Frame rectangle
self.frame_rect = self.frames[0].get_rect()
self.last_dir = direction
def get_keys(self):
self.vel= vec(0, 0)
keys = pg.key.get_pressed()
if keys[pg.K_a]: # Const. subtracts player speed from velocity (E.g. Moves sprite to the left)
self.vel.x= -self.playerspeed
self.move += 1
self.moving = 'left' # Uses different spritesheet depending on direction
elif keys[pg.K_d]: # Const. adds player speed value to velocity (E.g. Moves sprite to the right)
self.vel.x= self.playerspeed
self.move += 1
self.moving = 'right'
elif keys[pg.K_w]: # Const. subtracts player speed value from y velocity (Moves player upwards; opposite)
self.vel.y= -self.playerspeed
self.move += 1
self.moving = 'up'
elif keys[pg.K_s]: # Const. adds player speed value to y velocity (Moves player downwards; opposite)
self.vel.y= self.playerspeed
self.move += 1
self.moving = 'down'
def add_speed(self):
pass
def collide_with_player2(self, dir, ifColliding):
if dir == 'x':
collides = pg.sprite.spritecollide(self, self.game.player2group, False, collide_player_hit_rect)
if collides:
if self.vel.x > 0:
self.pos.x = collides[0].hit_rect.left - self.hit_rect.width / 2
if self.vel.x < 0:
self.pos.x = collides[0].hit_rect.right + self.hit_rect.width / 2
self.vel.x = 0
self.hit_rect.centerx = self.pos.x
print("collide x")
if random.randint(0, 100) <= 4:
random.choice(self.game.thief_hit_sounds).play()
self.ifColliding = True
if dir == 'y':
collides = pg.sprite.spritecollide(self, self.game.player2group, False, collide_player_hit_rect)
if collides:
if self.vel.y > 0:
self.pos.y = collides[0].hit_rect.top - self.hit_rect.height / 2
if self.vel.y < 0:
self.pos.y = collides[0].hit_rect.bottom + self.hit_rect.height / 2
self.vel.y = 0
self.hit_rect.centery = self.pos.y
print("collide y")
if random.randint(0, 100) <= 4:
random.choice(self.game.thief_hit_sounds).play()
self.ifColliding = True
def collide_with_walls(self, dir):
if dir == 'x':
collides = pg.sprite.spritecollide(self, self.game.walls, False, collide_hit_rect)
if collides:
if self.vel.x > 0:
self.pos.x = collides[0].rect.left - self.hit_rect.width / 2
if self.vel.x < 0:
self.pos.x = collides[0].rect.right + self.hit_rect.width / 2
self.vel.x = 0
self.hit_rect.centerx = self.pos.x
if dir == 'y':
collides = pg.sprite.spritecollide(self, self.game.walls, False, collide_hit_rect)
if collides:
if self.vel.y > 0:
self.pos.y = collides[0].rect.top - self.hit_rect.height / 2
if self.vel.y < 0:
self.pos.y = collides[0].rect.bottom + self.hit_rect.height / 2
self.vel.y = 0
self.hit_rect.centery = self.pos.y
def update(self):
# frame updates
self.anim_speed += 1
self.moving = 'idle'
self.animate(self.last_dir) # Sets the down spritesheet as default
self.get_keys()
if self.moving == 'up':
self.animate(self.moving) # Uses the up-movement spritesheet if char moving upwards
if self.moving == 'down':
self.animate(self.moving) # Same as above, different direction
if self.moving == 'left':
self.animate(self.moving)
if self.moving == 'right':
self.animate(self.moving)
self.ifColliding = False
self.rect.center = self.pos
self.pos += self.vel * self.game.dt
self.hit_rect.centerx = self.pos.x
self.collide_with_walls('x'), self.collide_with_player2('x', self.ifColliding)
self.hit_rect.centery = self.pos.y
self.collide_with_walls('y'), self.collide_with_player2('y', self.ifColliding)
self.rect.center = self.hit_rect.midtop
if self.ifColliding == True:
Thief.health -= COL_DAMAGE
print(Thief.health)
self.current_frame = (self.current_frame + self.move) % self.frames_number
if self.moving == 'idle':
self.current_frame = 0
self.image = self.frames[self.current_frame] # Image of sprite changes as program cycles through the sheet
【问题讨论】:
【参考方案1】:您可以通过某种方式将动画速率与帧速率联系起来,从而将动画速率与帧速率解耦。
一种方法是使用pygame.time.get_ticks() 返回自调用pygame.init()
以来的毫秒数。如果您存储此值,您可以测量已经过去了多少时间并适当地制作动画。
def update(self):
self.elapsed = pygame.time.get_ticks() - self.elapsed
if self.elapsed > 500: # animate every half second
self.animate()
注意:您还需要在构造函数中初始化self.elapsed
。
【讨论】:
你提到在搞乱动画等之前初始化'self.elapsed';其中的值可以是任何数字/自定义值吗? - 只是为了澄清:) 上面的逻辑非常简单,如果你想确保在第一次update
调用时产生动画,你可以将值初始化为零。如果您有多个精灵并且不希望它们同步,则应在创建时将这些值初始化为 0 到 500 之间的随机值。【参考方案2】:
这是我为帧速率为 60 的精灵制作动画并且精灵动画比帧速率慢的代码
import pygame
import glob
def fps():
fr = "V.3 Fps: " + str(int(clock.get_fps()))
frt = font.render(fr, 1, pygame.Color("coral"))
return frt
class MySprite(pygame.sprite.Sprite):
def __init__(self, action):
super(MySprite, self).__init__()
self.action = action
# This is to slow down animation # takes the frame now and...
self.elapsed = 0
self.images = []
self.temp_imgs = []
self.load_images()
self.count = 0
def load_images(self):
l_imgs = glob.glob(f"png\\self.action*.png")
for img in l_imgs:
if len(img) == len(l_imgs[0]):
self.images.append(pygame.image.load(img))
else:
self.temp_imgs.append(pygame.image.load(img))
self.images.extend(self.temp_imgs)
self.index = 0
self.rect = pygame.Rect(5, 5, 150, 198)
def update(self):
self.count += 1
if self.index == len(self.images):
self.index = 0
self.image = self.images[self.index]
if self.count > 2:
#self.image = self.images[self.index]
self.index += 1
self.count = 0
def group_sprites(self):
return pygame.sprite.Group(self)
def group():
"Dictionary of group of sprites"
dici =
actions = "idle walk run jump dead"
actions = actions.split()
for action in actions:
dici[action] = MySprite(action).group_sprites()
return dici
def main():
global clock
global font
SIZE = 600, 600
FPS = 60
pygame.init()
action = group()
my_group = action["idle"]
screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption("Game v.3")
font = pygame.font.SysFont("Arial", 60)
clock = pygame.time.Clock()
loop = 1
while loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
loop = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
my_group = action["walk"]
if event.key == pygame.K_UP:
my_group = action["jump"]
if event.key == pygame.K_SPACE:
my_group = action["idle"]
if event.key == pygame.K_RIGHT:
my_group = action["run"]
if event.key == pygame.K_DOWN:
my_group = action["dead"]
my_group.update()
screen.fill((0, 0, 0))
my_group.draw(screen)
screen.blit(fps(), (10, 0))
pygame.display.update()
clock.tick(FPS)
pygame.quit()
if __name__ == '__main__':
main()
阅读这篇文章...slow down animation without affecting the frame rate
Dowload images and put the in a directory called png
【讨论】:
以上是关于改变精灵动画速度(pygame)的主要内容,如果未能解决你的问题,请参考以下文章