Phaser -- HTML 遊戲框架

第 6 章    Pacman

(1) 遊戲規格

∗ Pacman (小精靈):在 80 年代非常流行的遊戲

▸ 小精靈大嚼豆豆

pacman

(2) 建立專案

∗ 遊戲專案

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

▸ 下載資產 assets06.zip

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

▸ 遊戲視窗 448x496

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

(3) Preload

∗ 載入資產:地圖資料、磚塊影像、小精靈動畫

  preload: function() {
    game.load.image('dot', 'assets/dot.png');
    game.load.image('tiles', 'assets/pacman-tiles.png');
    game.load.spritesheet('pacman', 'assets/pacman.png', 32, 32);
    game.load.tilemap('map', 'assets/pacman-map.json', null,
                      Phaser.Tilemap.TILED_JSON); 
  },

game.load.image('dot', ...):載入豆豆影像

.load.image('tiles', ...):載入磚塊影像 (圖 1,影像尺寸 256x48,磚塊尺寸 16x16)

pacman-tiles圖 1 dot圖 2

.load.spritesheet('pacman', ...):載入小精靈影像 (圖 2,影像尺寸 96x32)

.load.tilemap(...):載入地圖資料

▸ 註:網格尺寸為 16x16,但小精靈尺寸為 32x32 (16x16 太小,不好看),因此,之後會將其 Body size 改為 16x16

(4) Create

∗ 設定各個變數值 (類似迷宮飆車,但改變 safeTileIndex, gridSize, this.currentDir)

  create: function() {
    this.safeTileIndex = 14;
    this.gridsize = 16;
  
    ...
    this.currentDir = Phaser.LEFT;
    ...
  },

∗ 設定遊戲世界隨瀏覽器縮放 (保持寬高比例),並設定水平垂直對齊

  create: function() {
    ...
    this.currentDir = Phaser.LEFT;
  
    game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
    game.scale.pageAlignHorizontally = true;
    game.scale.pageAlignVertically = true;
    Phaser.Canvas.setImageRenderingCrisp(game.canvas);
  
    game.physics.startSystem(Phaser.Physics.ARCADE);
  },

.scaleMode = Phaser.ScaleManager.SHOW_ALL:遊戲縮放模式設定為看到全部視窗

.pageAlignHorizontally, .pageAlignVertically:水平、垂直均對齊

.setImageRenderingCrisp(game.canvas):設定遊戲畫布在縮放時,影像呈現銳利 (不模糊)

∗ 加入磚塊地圖 (類似迷宮飆車)

  create: function() {
    ...
    game.physics.startSystem(Phaser.Physics.ARCADE);
  
    this.map = game.add.tilemap('map');
    this.map.addTilesetImage('pacman-tiles', 'tiles');
    this.layer = this.map.createLayer('Pacman');
    this.map.setCollision(20, true, this.layer); 
    ...
  },

▸ JSON 檔案裡所設定的:

tilesets 的名稱為 pacman-tiles
layers 的名稱為 Pacman

∗ 產生豆豆群組及設定碰撞磚塊

  create: function() {
    ...
    this.layer = this.map.createLayer('Pacman');
  
    this.dots = game.add.physicsGroup();
    this.map.createFromTiles(7, this.safeTileIndex, 'dot', this.layer, this.dots);
    this.dots.setAll('x', 6, false, false, 1);
    this.dots.setAll('y', 6, false, false, 1);
  
    this.map.setCollisionByExclusion([this.safeTileIndex], true, this.layer);
  
    this.car = game.add.sprite(48, 48, 'car');
    ...
  
  },

.add.physicsGroup():設定有物理特性的群組 (等於兩行指令: <var> = game.add.group(); <var>.enableBody = true;)

this.map.createFromTiles(...):從磚塊產生精靈,指令格式如下:createFromTiles(tiles, replacements, key, layer, group, properties);

tiles:產生精靈的磚塊編號 (資料型態:整數或陣列)
replacements:精靈要轉成的磚塊編號 (資料型態:整數或陣列)
key:資產鍵
layer:目標圖層 (非必要參數)
group:所產生的精靈將要加入的群組 (非必要參數)
properties:設定精靈的特性 (非必要參數)
.createFromTiles(7, this.safeTileIndex, 'dot', this.layer, this.dots):利用7號磚塊產生豆豆精靈,並將這些磚塊轉為 this.safeTileIndex 磚塊 (小精靈可以行走),並將豆豆精靈加入 this.dots 群組

this.dots.setAll(...):一次設定群組裡的所有成員,指令格式如下:.setAll(key, value, checkAlive, checkVisible, operation, force);

key:要設定的屬性 (字串)
value:設定屬性值
checkAlive:如果是 true,則 alive==true 的成員才會設定,否則不檢查
checkVisible:如果是 true,則 visible==true 的成員才會設定,否則不檢查
operation:如何改變原值:
# 0:將原值置換為新值
# 1:將原值加新值
# 2:將原值減新值
# 3:將原值乘新值
# 4:將原值除以新值
.setAll('x', 6, false, false, 1);:豆豆群組中所有元素的 x 座標都加 6,因為豆豆影像尺寸只有 4x4 (中心點 (2, 2)),磚塊中心點為 (8, 8),故需位移 (6, 6)

.setCollisionByExclusion([this.safeTileIndex], true, this.layer):設定排除圖層磚塊的碰撞效應

✶ 第 1 個參數:沒有碰撞效應的磚塊編號 (存在陣列資料結構中,其餘磚塊都有碰撞效應),小精靈可以行走
✶ 第 2 個參數:是否啟用碰撞效果 (true:啟用,false:停用)
✶ 第 3 個參數:所使用的圖層

∗ 產生小精靈及設定方向鍵等

▸ 首先將所有 this.car 改為 this.pacman

  create: function() {
    ...
  
    this.map.setCollisionByExclusion([this.safeTileIndex], true, this.layer);
  
    this.pacman = game.add.sprite(14*16+8, 17*16+8, 'pacman');
    this.pacman.anchor.set(0.5);
    this.pacman.animations.add('munch', [0, 1, 2, 1], 20, true); 
  
    game.physics.arcade.enable(this.pacman)
    this.pacman.body.setSize(16, 16, 8, 8); 
  
    this.cursors = game.input.keyboard.createCursorKeys();
  
    this.pacman.play('munch'); 
    this.move(Phaser.LEFT );
  },

game.add.sprite(..., 'pacman'):在遊戲中的適當位置加入小精靈

.anchor.set(0.5):設定小精靈錨點為中心點

.animations.add(...):加入動畫,名稱為 munch (大嚼),使用 [0, 1, 2, 1] 畫面,每秒播放 20 幀,重複播放 (true)

.arcade.enable(...):小精靈啟用 Arcade 物理特性 (偵測碰撞)

.body.setSize(...):設定小精靈物理物體的尺寸為 16x16 (因為網格尺寸為 16x16),並位移 (8, 8)使其置中

.createCursorKeys():設定方向鍵

.play('munch'):開始播放大嚼動畫

(5) Update

∗ 類似迷宮飆車,增加 pacman 與 dots 的碰撞偵測

  update: function() {
    game.physics.arcade.collide(this.pacman, this.layer);
    game.physics.arcade.overlap(this.pacman, this.dots, this.eatDot, null, this); 
  
    this.gridPos.x = game.math.snapToFloor(Math.floor(this.pacman.x),
                                          this.gridsize)/this.gridsize;
    ...
  },

.physics.arcade.collide(...):設定汽車與圖層碰撞效應

.overlap(this.pacman, this.dots, this.eatDot, ...):小精靈與豆豆碰撞偵測,呼叫 .eatDot() 方法

.eatDot() 方法:

  turn: function(to) {
    ...
  },
  
  eatDot: function(pacman, dot) {
    dot.kill();
    if (this.dots.total==0) {
      this.dots.callAll('revive');
    }
  },
✶ 將豆豆殺掉,如果豆豆總數等於 0,全部復活

(6) 練習

上一章       下一章