如何用Phaser.js创建一个小游戏

445 阅读6分钟

在本教程中,我将使用Phaser.js来创建一个平台游戏。

玩家可以用左/右方向键移动,用上方向键跳跃。游戏的目标是捡起游戏中的所有星星。

当玩家拾起所有的星星时,我们将在上面显示 "游戏结束",然后就没有其他事情可做了。

这个游戏非常非常简单,但它是一个游戏的开始,继续制作会非常有趣,而且它是展示Phaser和JavaScript如何作为游戏创作编程语言的一个好方法。

设置项目

创建一个空文件夹,并运行

npm init -y

来初始化一个最小的package.json 文件

然后运行

npm install phaser

安装Parcel(如果你还没有)

npm install -g parcel-bundler

现在创建一个app.js 文件,并运行

parcel watch app.js

这将告诉Parcel在dist/app.js 文件中建立我们的游戏。

用这个内容创建一个index.html 文件

<!DOCTYPE html>
<html>
  <head>
    <script src="./dist/app.js"></script>
  </head>
</html>

安装browser-sync ,用这个文件夹的内容运行一个HTTP服务器

npm install -g browser-sync

然后运行

browser-sync start --server --files "."

上述命令观察当前文件夹(以及所有子文件夹)中的所有文件是否有变化,并在3000端口启动一个网络服务器,自动打开一个浏览器窗口连接到服务器。

任何时候你改变了一个文件,浏览器就会刷新,所以我们可以在开发过程中更加迅速。

很好!我们可以开始了。

初始化Phaser

打开app.js ,然后写

import Phaser from 'phaser'

让我们添加一个最小的配置。

const config = {
  width: 800,
  height: 600,
  backgroundColor: 0xffffff,
  scene: {
    preload,
    create,
    update
  },
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 300 },
      debug: false
    }
  }
}

const game = new Phaser.Game(config)

现在创建3个函数preload(),create()update()

function preload() {

}

function create() {

}

function update() {

}

添加艺术品

我称它为 "艺术品",但这是我做的,是你能找到的最丑陋的艺术品。

但它对我们这个简单的游戏是有效的。下载这些文件并将其保存为。

ground.png

island.png

player.png

star.png

创建一个assets 文件夹,并把它们放在那里。

创建一个画布

现在回到app.js

我们要做的第一件事是加载preload() 中的资产。

function preload() {
  this.load.image('ground', 'assets/ground.png')
  this.load.image('island', 'assets/island.png')
  this.load.image('star', 'assets/star.png')
  this.load.spritesheet('player', 'assets/player.png', {
    frameWidth: 32,
    frameHeight: 48
  })
}

我们给每个资产指定一个标签。前3个使用this.load.image() ,最后一个使用this.load.spritesheet() ,因为这个图片包含了几个小图像,我们将用它们来为播放器制作动画。

因此,我们也必须在精灵表中设置每个图像的尺寸(32x48像素)。

创建平台

现在让我们来创建平台。

我们将创建一个新的物理静态组来容纳它们,因为它们不是移动物体:它们是静止的。

let platforms = this.physics.add.staticGroup()

然后我们添加地面。

platforms.create(400, 588, "ground")

还有5个岛屿。

platforms.create(600, 450, "island")
platforms.create(50, 250, "island")
platforms.create(650, 220, "island")
platforms.create(250, 520, "island")
platforms.create(250, 320, "island")

这里的数字表示2D空间中的X和Y坐标,相对于左上角,指的是每张图片的中间位置。

这就是你在这一点上应该看到的东西。

添加播放器

现在让我们来添加播放器。

在文件的顶部创建一个变量,在任何函数之外,称为player

let player

然后在create() ,我要把它添加到屏幕的中间底部附近。

player = this.physics.add.sprite(380, 500, "player")

我们把它设定为有一个小的弹跳。

player.setBounce(0.2)

所以它在被放进屏幕后会很快静止,我们将它设置为不离开屏幕。

player.setCollideWorldBounds(true)

这样一来,它就会出现,经过几次弹跳后,它就会坐在屏幕的底部。

然而,我们想让玩家停留在地面之上。

我们可以通过在玩家和平台之间添加一个碰撞器物理规则来做到这一点。

this.physics.add.collider(player, platforms)

这样一来,玩家就不会只停留在地面上,也会停留在我们漂浮在屏幕上的其他5个平台(岛屿)上。

让玩家移动

现在,让我们使玩家能够移动。

让我们在文件的顶部添加一个变量,靠近player 声明。

let cursors

然后在create() 中添加。

cursors = this.input.keyboard.createCursorKeys()

以允许访问键盘事件。

现在在update() 函数中,它现在是空的,我们要检查这个变量。

function update() {
  if (cursors.left.isDown) {
    player.setVelocityX(-160)
  } else if (cursors.right.isDown) {
    player.setVelocityX(160)
  } else {
    player.setVelocityX(0)
  }
}

update() 被游戏循环连续调用,所以每当有一个键被按下,我们就改变X轴上的玩家速度(速度)。如果没有按键,我们就把它设置为静止。

为玩家制作动画

现在让我们使玩家的图像在移动时发生变化。

我们在create() 中创建3个动画:一个是玩家静止时的动画,一个是向左移动时的动画,一个是向右移动时的动画。

this.anims.create({
  key: 'still',
  frames: [{ key: 'player', frame: 4 }],
  frameRate: 20
})

this.anims.create({
  key: 'left',
  frames: this.anims.generateFrameNumbers('player', { start: 0, end: 3 }),
  frameRate: 10,
  repeat: -1
})

this.anims.create({
  key: 'right',
  frames: this.anims.generateFrameNumbers('player', { start: 5, end: 8 }),
  frameRate: 10,
  repeat: -1
})

still 不是一个真正的动画,因为它只有一帧。但是leftright 各由4个帧组成,它们被无限重复以模拟行走。

现在我们需要在update() 中激活这些动画。

function update() { 
  if (cursors.left.isDown) {
    player.setVelocityX(-160)
    player.anims.play('left', true)
  } else if (cursors.right.isDown) {
    player.setVelocityX(160)
    player.anims.play('right', true)
  } else {
    player.setVelocityX(0)
    player.anims.play('still')
  }
}

true 参数为leftright 设置了动画的循环。

跳跃

为了使玩家能够跳跃,在update() 中添加这段代码。

if (cursors.up.isDown && player.body.touching.down) {
  player.setVelocityY(-330)
}

每当玩家坐在底部 (player.body.touching.down) 并按下向上的箭头时,我们就把它推到顶部。重力将模拟一个跳跃,就像我们在现实世界中做的那样。

添加星星

现在让我们在屏幕上添加星星。

我们通过创建一个物理组来添加8颗星星,并让它们与平台相撞,所以它们会坐在平台上。

let stars = this.physics.add.group()
stars.create(22, 0, "star")
stars.create(122, 0, "star")
stars.create(222, 0, "star")
stars.create(322, 0, "star")
stars.create(422, 0, "star")
stars.create(522, 0, "star")
stars.create(622, 0, "star")
stars.create(722, 0, "star")

this.physics.add.collider(stars, platforms)

允许玩家拾取星星

为了让玩家捡起星星,我们要在create() 中添加一个重叠的物理效果,当玩家遇到星星时就会发射。

this.physics.add.overlap(player, stars, (player, star) => {}, null, this)

当这种情况发生时,我们会隐藏星星。

this.physics.add.overlap(
  player,
  stars,
  (player, star) => {
    star.disableBody(true, true)
  },
  null,
  this
)

让我们做一个星星计数器。当有一颗星星被拾起时,我们就把它递增。

let score = 0

this.physics.add.overlap(
  player,
  stars,
  (player, star) => {
    star.disableBody(true, true)
    score += 1
  },
  null,
  this
)

并且我们可以在屏幕上方显示它。

let score = 0
let scoreText = this.add.text(16, 16, "Stars: 0", {
  fontSize: "32px",
  fill: "#000",
})

this.physics.add.overlap(
  player,
  stars,
  (player, star) => {
    star.disableBody(true, true)
    score += 1
    scoreText.setText("Stars: " + score)
  },
  null,
  this
)

就这样!我们的小游戏成功了!