上一节学习如何利用spritesheet加载图片,但是player仍然是一张静态的图片,比较枯燥,我们要让它动起来!
Player类,先把各种状态的图片加载起来:
1 # 加载各种状态的图片序列
2 def load_images(self):
3 # 站立状态的图片
4 self.standing_frames = [self.game.spritesheet.get_image("bunny1_ready.png"),
5 self.game.spritesheet.get_image("bunny1_stand.png")]
6
7 # 向右走的图片
8 self.walking_frames_right = [self.game.spritesheet.get_image("bunny1_walk1.png"),
9 self.game.spritesheet.get_image("bunny1_walk2.png")]
10
11 # 向左走的图片
12 self.walking_frames_left = []
13 for frame in self.walking_frames_right:
14 # 向左走的图片,只需要把向"右"走的图片,水平(x)方向翻转即可
15 self.walking_frames_left.append(pg.transform.flip(frame, True, False))
16
17 # 跳跃状态的图片
18 self.jump_frame = self.game.spritesheet.get_image("bunny1_jump.png")
然后要有一些bool型的状态变化(不然,我们就无法知道当前角色是在jump,还是在walk,或是stand)
1 class Player(pg.sprite.Sprite):
2
3 def __init__(self, game):
4 pg.sprite.Sprite.__init__(self)
5 self.game = game
6 # 是否在行走状态
7 self.walking = False
8 # 是否处于跳跃状态
9 self.jumping = False
10 # 当前状态的动画,显示的是哪一"帧"
11 self.current_frame = 0
12 # 当前状态的动画,最后一次切换是什么时候?
13 self.last_update = 0
14 # 加载图片
15 self.load_images()
16 # 初始状态为"站立"
17 self.image = self.standing_frames[0]
18
19 ...
注:current_frame变量的作用,解释一下,一个状态下的图片可能有多张,需要知道当前切换到了第几张,这个变量保存的就是第几张图片的N值。另外一个变量last_update后面会讲到,这里先不用管。
当player向上跳起时,要切换jump的状态:
1 def jump(self):
2 hits = pg.sprite.spritecollide(self, self.game.platforms, False)
3 if hits:
4 self.vel.y = -PLAYER_JUMP
5 # 修改跳跃状态
6 self.jumping = True
为了方便统一处理角色的动画效果,在Player类中新增一个animation函数:
# 动画处理
def animate(self):
now = pg.time.get_ticks()
# 更新walking状态
if self.vel.x != 0:
self.walking = True
else:
self.walking = False
# 垂直方向速度为0,认为未跳跃
if abs(self.vel.y) < 0.5:
self.jumping = False
# 切换jumping图片
if self.jumping:
self.image = self.jump_frame
else:
self.image = self.standing_frames[0]
if not self.jumping and not self.walking:
# 调节这里的200,可以控制动画的播放速度
if now - self.last_update > 200:
self.last_update = now
self.current_frame += 1
# bunny1_ready.png与bunny1_stand.png的高度不同,所以切换后,要调整bottom值,保证图片的最下边缘正好站在档板上
old_bottom = self.rect.bottom
self.image = self.standing_frames[self.current_frame % len(self.standing_frames)]
self.rect = self.image.get_rect()
self.rect.bottom = old_bottom
last_update变量的作用,在animation中就体现出来了,这个变量结合当前时间,算出差值,可以控制每隔多少毫秒切换1次图片。相当于,控制角色动画的播放速度。
最后在update函数中,调用animation:
def update(self):
# 动画处理
self.animate()
self.acc = vec(0, PLAYER_GRAVITY)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_RIGHT]:
self.acc.x = PLAYER_ACC
self.acc.x += self.vel.x * PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel
# 因为walking状态的切换,依赖于x速度是否为0判断,当x在0左右的极小值摆动时,会导致判断出错
if abs(self.vel.x) < 0.5:
self.vel.x = 0
...