十二、动画

我们即将结束短暂而愉快的旅程。是时候开始添加一些收尾工作了。例如,我们的精灵过于坚忍。让我们来制作动画吧!

为玩家制作动画

玩家精灵是整个游戏中最重要的部分之一。我们可以花很长时间盯着这个小动物,如果我们不添加一点动画,它会非常无聊。

幸运的是,PixiJS 提供了一些工具来简化这个过程。让我们开始使用其中的一个:

const playerIdleLeftImages = [
  "path/to/sprites/player-idle-1.png",
  "path/to/sprites/player-idle-2.png",
  "path/to/sprites/player-idle-3.png",
  "path/to/sprites/player-idle-4.png",
]

const playerIdleLeftTextures =
  playerIdleLeftImages.map(function(image) {
    return PIXI.Texture.fromImage(image)
  })

const playerIdleLeftSprite =
  new PIXI.MovieClip(playerIdleLeftTextures)

playerIdleLeftSprite.play()
playerIdleLeftSprite.animationSpeed = 0.12

const player = new Player(
  playerIdleLeftSprite,
  new PIXI.Rectangle(
    Math.round(width / 2),
    Math.round(height / 2),
    48,
    56,
  ),
)

player.idleLeftSprite = playerIdleLeftSprite

这是出自 http://codepen.io/assertchris/pen/ALyPGw

我们用new PIXI.MovieClip代替了new PIXI.Sprite.fromImage。我们首先创建一个图像数组(任何好的精灵包都应该有)并为每个图像创建新的PIXI.Texture对象。

我们需要调用play让动画开始,调整动画速度也无妨。我们将很快看到为什么存储动画的引用是一个好主意。

Tip

没有静态图像可以做到这一点。看看 CodePen,看看它在动!

交换动画

我们不仅可以让玩家看起来静止不动。例如,我们可以添加行走、跳跃甚至受伤的动画。让我们开始添加运行动画。动画初始化代码如下所示:

const playerIdleLeftImages = [
  "path/to/sprites/player-idle-1.png",
  "path/to/sprites/player-idle-2.png",
  "path/to/sprites/player-idle-3.png",
  "path/to/sprites/player-idle-4.png",
]

const playerIdleLeftTextures =
  playerIdleLeftImages.map(function(image) {
    return PIXI.Texture.fromImage(image)
  })

const playerIdleLeftSprite = new PIXI.MovieClip(playerIdleLeftTextures)

playerIdleLeftSprite.play()
playerIdleLeftSprite.animationSpeed = 0.12

const playerRunLeftImages = [
  "path/to/sprites/player-run-1.png",
  "path/to/sprites/player-run-2.png",
  "path/to/sprites/player-run-3.png",
  "path/to/sprites/player-run-4.png",
  "path/to/sprites/player-run-5.png",
  "path/to/sprites/player-run-6.png",
  "path/to/sprites/player-run-7.png",
  "path/to/sprites/player-run-8.png",
  "path/to/sprites/player-run-9.png",
  "path/to/sprites/player-run-10.png",
]

const playerRunLeftTextures =
  playerRunLeftImages.map(function(image) {
    return PIXI.Texture.fromImage(image)
  })

const playerRunLeftSprite = new PIXI.MovieClip(playerRunLeftTextures)

playerRunLeftSprite.play()
playerRunLeftSprite.animationSpeed = 0.2

const player = new Player(
  playerIdleLeftSprite,
  new PIXI.Rectangle(
    Math.round(width / 2),
    Math.round(height / 2),
    48,
    56,
  ),
)

player.idleLeftSprite = playerIdleLeftSprite
player.runLeftSprite = playerRunLeftSprite

game.addObject(player)
game.player = player

这是出自 http://codepen.io/assertchris/pen/ALyPGw

添加动画确实很有趣,但也可能相当乏味。我们需要裁剪和导出每个动作的每一帧。然后,我们需要将它们拼接成许多图像数组和动画精灵。

最好将每个动画精灵的引用分配给player。这样,我们可以在Player.animate中交换它们:

this.rectangle.x += this.velocityX

if (!this.isOnLadder && !this.isOnSlope) {
  this.rectangle.y += this.velocityY
}

if (this.isOnGround && Math.abs(this.velocityX) < 0.5) {
  state.game.stage.removeChild(this.sprite)
  state.game.stage.addChild(this.idleLeftSprite)
  this.sprite = this.idleLeftSprite
}

if (this.isOnGround && Math.abs(this.velocityX) > 0.5) {
  state.game.stage.removeChild(this.sprite)
  state.game.stage.addChild(this.runLeftSprite)
  this.sprite = this.runLeftSprite
}

this.sprite.x = this.rectangle.x
this.sprite.y = this.rectangle.y

这是出自 http://codepen.io/assertchris/pen/ALyPGw

animate方法的最后,我们可以检查玩家是否还在移动(很多)。如果没有,我们用空闲的动画来交换当前可见的精灵。

如果玩家还在移动,我们就把可见的精灵换成奔跑的动画。这个逻辑只在一个方向上起作用,但是我们可以推断出这个行为包含了很大范围的动画和方向。

摘要

在这一章中,我们给游戏添加了一些动画(不是巡逻的暴徒那种)。我们可以花几个小时观察运动员的头发上下起伏。

我们可以添加许多不同种类的动画:

  • 跳跃和/或坠落
  • 受伤了
  • 着陆(带着一阵灰尘)
  • 爬梯
  • 发射射弹(手持武器)

我们只添加了两个,但您还可以添加更多。这些的关键是找到(或设计)一个好的雪碧包;把所有的东西都缝好。如果你能做到这一点,你就能制作出一个精美的动画游戏!