pygame-KidsCanCode系列jumpy-part10-角色动画(上)

上一节学习如何利用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")
View Code

然后要有一些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         ...
View Code

注: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
View Code

 为了方便统一处理角色的动画效果,在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
View Code

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
        ...
View Code

posted @ 2019-02-17 17:08 菩提树下的杨过 阅读(...) 评论(...) 编辑 收藏