Phaser -- HTML 遊戲框架

第 3 章    採星星

(1) 遊戲規格

∗ 小精靈左右前進或跳躍來採擷星星

phaserLogo

▸ 視窗尺寸 800x600,背景為天空藍,綠色部份為固定的地面及平台

▸ 12 顆星星以自由落體方式自上方落下,碰到平台後則以不同的彈跳係數往上彈跳

▸ 小精靈可左右移動及跳躍,可站在地面或平台,碰到星星時刪除星星並加分數

(2) 建立專案目錄及初始檔案

∗遊戲專案

▸ 建立專案目錄結構,遊戲名稱:collectStars

▸ 下載資產 assets03.zip

▸ 建立 index.html 及初始 main.js

▸ 遊戲視窗 800x600

▸ 接下來修改 main.js 開始建構遊戲

(3) 設定視窗尺寸

∗ main.js:

...
var game = new Phaser.Game( 800,600, Phaser.AUTO, 'gameDiv');
...

(4) 載入遊戲資產

∗ 在 preload 中載入四個遊戲資產:三個影像、一個精靈表

  preload: function() { 
    game.load.image('sky', 'assets/sky.png');
    game.load.image('ground', 'assets/platform.png');
    game.load.image('star', 'assets/star.png');
    game.load.spritesheet('dude', 'assets/dude.png', 32, 48); 
  },

▸ 影像資產 (天空、地面、星星) 之 Asset key 分別為 skyground 、及 star

▸ 精靈表 (Sprite sheet) 資產:與上一章相同

(5) 加入背景及平台

∗ 將背景及平台加入遊戲世界:在 create 階段加入以下內容

  create: function() { 
    game.physics.startSystem(Phaser.Physics.ARCADE);
    game.add.image(0, 0, 'sky');
  
    this.platforms = game.add.group();
    this.platforms.enableBody = true;
  
    var ground = this.platforms.create(0, game.world.height-64, 'ground');
    ground.scale.setTo(2, 2);
  
    this.platforms.create(400, 400, 'ground');
    this.platforms.create(-150, 250, 'ground');
  
    this.platforms.setAll('body.immovable', true); 
  },

game.physics.startSystem():首先啟用遊戲的物理系統

game.add.image(..., 'sky'):在遊戲世界中加入天空影像,使用 sky 資產

game.add.group():加入一個群組 (Group),並設定為 main 的屬性 this.platforms ,包含地面及 2 個窗台,小精靈可以跳上去

this.platforms.enableBody = true;:設定平台裡的所有物件都符合物理學的物體特性

var ground = this.platforms.create(..., 'ground'):在平台群組產生一個地面物件, 並將其設定給區域變數 ground

✶ 位置在遊戲視窗底部,使用 ground 資產
ground.scale.setTo(2, 2):縮放符合視窗的寬度:原影像 400x32,放大 2 倍為 800x64

var ledge = this.platforms.create(..., 'ground'):在平台群組產生窗台物件, 並將其設定給區域變數 ledge

✶ 設定適當位置,亦使用 ground 資產

ledge = platforms.create(..., 'ground'):產生第 2 個窗台,其餘設定類似

this.platforms.setAll('body.immovable', true);:此群組所有成員在碰撞時不會移動 (以免小精靈跳上去時,地面會陷落)

▸ 結果:

phaserLogo

(6) 加入小精靈

∗繼續在 create 中加入小精靈並設定其特性

  create: function() {
    ...
    this.platforms.setAll('body.immovable', true);
  
    this.player = game.add.sprite(32, game.world.height-150, 'dude');
    game.physics.arcade.enable(this.player);
    this.player.body.bounce.y = 0.2;
    this.player.body.gravity.y = 300;
    this.player.body.collideWorldBounds = true;
    this.player.body.setSize(20, 32, 5, 16);
  
    this.player.animations.add('left', [0, 1, 2, 3], 10, true);
    this.player.animations.add('right', [5, 6, 7, 8], 10, true);
  
    this.cursors = game.input.keyboard.createCursorKeys(); 
  },

this.player = game.add.sprite():產生小精靈,設定給屬性 player ,設定適當起始位置,並使用 dude 資產,

game.physics.arcade.enable():小精靈啟用 Arcade 物理系統

▸ 設定小精靈的物理特性:

.body.bounce.y = 0.2:縱向 (y 軸) 彈跳係數為 0.2 (數值範圍: 0 ~ 1,0 :不彈跳,1:完全彈跳)
.body.gravity.y:重力係數
.body.collideWorldBounds = true:會碰撞遊戲世界的邊界
.body.setSize(...):物理物體碰撞尺寸

▸ 動畫設定方式同前一章

▸ 最後設定方向鍵

▸ 測試結果

(7) 導入碰撞偵測

∗在 update 中導入碰撞偵測

  update: function() {
    game.physics.arcade.collide(this.player, this.platforms); 
  },

game.pyhsics.arcade.collide():偵測小精靈是否碰撞平台 (平台群組裡的所有物件), 因此小精靈墜落時會停在地面

∗ 接著加入移動小精靈的功能

  update: function() {
    game.physics.arcade.collide(this.player, this.platforms);
  
    this.player.body.velocity.x = 0;
    if (this.cursors.left.isDown) {
      this.player.body.velocity.x = -150;
      this.player.animations.play('left');
    }
    else if (this.cursors.right.isDown) {
      this.player.body.velocity.x = 150;
      this.player.animations.play('right');
    }
    else {
      this.player.animations.stop();
      this.player.frame = 4;
    }
  
    if (this.cursors.up.isDown && this.player.body.touching.down) {
      this.player.body.velocity.y = -350;
    } 
  },

this.cursors = game.input.keyboard.createCursorKeys():設定方向鍵

▸ 設定小精靈的動作同前一章並測試

phaserLogo

(8) 加入星星

∗ 再來,加一堆星星吧!

▸ 在 create 函式中加入星星群組

  create: function() {
    ...
    this.cursors = game.input.keyboard.createCursorKeys();
  
    this.stars = game.add.group();
    this.stars.enableBody = true;
    for (var i=0; i<12; i++) {
      var star = this.stars.create(i*70, 0, 'star');
      star.body.gravity.y = 20;
      star.body.bounce.y = 0.8 + Math.random()*0.2;
    } 
  },
this.stas = game.add.group();:加入星星群組
→ 產生星星群組的方式和產生平台群組類似:加入群組,設定物理物體
✶ 利用 for 迴圈產生 12 個星星
# 位置都在上方,水平間隔 70 像素,使用 star 資產
# 重力係數為 20 (慢慢落下)
# 各個星星的彈性係數隨機設定 (數值範圍: 0.8 ~ 1.0),產生上下彈跳模式

▸ 在 update 中加入碰撞設定及重疊偵測

var main = {
  ...
  update: function() {
    ...
    if (cursors.up.isDown && player.body.touching.down) {
      player.body.velocity.y = -350;
    }
 
    game.physics.arcade.collide(this.stars, this.platforms);
    game.physics.arcade.overlap(this.player, this.stars, this.collectStar,
                                null, this); 
  },
 
  collectStar: function(player, star) {
    star.kill();
  }, 

};

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'gameDiv');
...
✶ 星星與平台的碰撞設定類似小精靈與平台的碰撞設定
game.physics.arcade.overlap() :偵測兩個物件或是物件與群組是否重疊
# 語法: game.physics.arcade.overlap(object, objectOrGroup, overlapCallback, processCallback, callbackContext)
# 參數 1 ( object ):物件
# 參數 2 ( objectOrGroup):物件或群組
# 參數 3 ( overlapCallback ):如果重疊即執行此「回呼函式」(Callback function), 如果只判斷是否重疊而不做額外處理,則可給 null 參數,本範例給 collectStar 函式,亦即如果重疊就呼叫 collectStar 函式
# 參數 4 ( processCallback ):如果重疊先執行此回呼函式,如果此函式回覆 true ,則執行 overlapCallback(),否則就不執行 (本範例給 null 參數)
# 參數 5 ( callbackContext ):在哪個環境執行回呼函式,本範例給 this 參數,亦即在本物件中執行
✶ 最後,在 main 之中定義 collectStart 屬性 (是一個方法):將重疊的星星刪除

(9) 加入計分

∗ 最後,給點分數吧!

▸ 在 create 中設定 scorescoreText

  create: function() {
    ...
    for (var i=0; i<12; i++) {
      ...
    }
  
    this.score = 0;
    this.scoreText = game.add.text(16, 16, '分數: 0',
                                   {fontSize: '24px', fill: '#000'});
  },
this.score = 0:分數屬性初始值為 0
this.scoreText = game.add.text():加入文字,並設定為 scoreText 屬性
# 位置在 (16, 16),初始值為 "分數: 0 " 字串,字體大小 24 px,黑色 (#000)

▸ 在 collectStar() 函式中加入分數計算

  collectStar: function(player, star) {
    star.kill(); 
    this.score += 10;
    this.scoreText.text = '分數: ' + this.score; 
  },

(10) 練習

上一章       下一章