在這個教程中,我將使用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上啟動一個Web服務器,自動打開一個瀏覽器窗口以連接到服務器。
每次更改文件,瀏覽器都會刷新,因此我們可以更快地進行開發。
太好了!我們可以開始了。
初始化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
})
}
我們為每個資源分配一個標籤。前三個使用’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’並不是真正的動畫,因為它只有一個幀。但’left’和’right’各由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')
}
}
’left’和’right’的’true’參數設置了動畫循環。
跳躍
為了讓玩家能夠跳躍,在’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
)
完成!我們的小遊戲可以運行了!