iT邦幫忙

2021 iThome 鐵人賽

DAY 30
0
Modern Web

你渴望連結嗎?將 Web 與硬體連上線吧!系列 第 30

D29 - 「來互相傷害啊!」:天時地利,建立 Phaser Scene

本系列文已改編成書「Arduino 自造趣:結合 JavaScript x Vue x Phaser 輕鬆打造個人遊戲機」,本書改用 Vue3 與 TypeScript 全面重構且加上更詳細的說明,

在此感謝 iT 邦幫忙、博碩文化與編輯小 p 的協助,歡迎大家前往購書,鱈魚在此感謝大家 (。・∀・)。

若想 DIY 卻不知道零件去哪裡買的讀者,可以參考此連結 。( •̀ ω •́ )✧


互毆之前當然要先有場地才行,讓我們建立 Phaser 場景吧!

建立場景

首先建立 src\components\window-app-cat-vs-dog\scenes 資料夾,集中所有場景。

接著建立 scene-example.js 場景。

src\components\window-app-cat-vs-dog\scenes\scene-example.js

import Phaser from 'phaser';

export default class extends Phaser.Scene {
  constructor() {
    super({ key: '' })
  }
  preload() {
  }
  create() {
  }
  update() {
  }
}

接著根據 D27 規劃的結果新增場景 scene-welcome.jsscene-main.jsscene-over.js

最後是新增一個特別的場景,專門用來預先載入所有素材、建立動畫用的場景 scene-preload.js

所以目前檔案為:

src\components\window-app-cat-vs-dog\scenes\scene-preload.js

import Phaser from 'phaser';

export default class extends Phaser.Scene {
  constructor() {
    super({ key: 'preload' })
  }
  preload() {
  }
  create() {
  }
  update() {
  }
}

src\components\window-app-cat-vs-dog\scenes\scene-welcome.js

import Phaser from 'phaser';

export default class extends Phaser.Scene {
  constructor() {
    super({ key: 'welcome' })
  }
  preload() {
  }
  create() {
  }
  update() {
  }
}

src\components\window-app-cat-vs-dog\scenes\scene-main.js

import Phaser from 'phaser';

export default class extends Phaser.Scene {
  constructor() {
    super({ key: 'main' })
  }
  preload() {
  }
  create() {
  }
  update() {
  }
}

src\components\window-app-cat-vs-dog\scenes\scene-over.js

import Phaser from 'phaser';

export default class extends Phaser.Scene {
  constructor() {
    super({ key: 'over' })
  }
  preload() {
  }
  create() {
  }
  update() {
  }
}

載入素材

接著在 scene-preload.js 場景中載入素材並建立動畫。

src\components\window-app-cat-vs-dog\scenes\scene-preload.js

import Phaser from 'phaser';

import catWork from '@/assets/cat-vs-dog/cat-work.png';
import catBeaten from '@/assets/cat-vs-dog/cat-beaten.png';
import catWeapon from '@/assets/cat-vs-dog/cat-weapon.png';
import catAttack from '@/assets/cat-vs-dog/cat-attack.png';

import dogWork from '@/assets/cat-vs-dog/dog-work.png';
import dogBeaten from '@/assets/cat-vs-dog/dog-beaten.png';
import dogWeapon from '@/assets/cat-vs-dog/dog-weapon.png';
import dogAttack from '@/assets/cat-vs-dog/dog-attack.png';

import river from '@/assets/cat-vs-dog/river.png';

export default class extends Phaser.Scene {
  constructor() {
    super({ key: 'preload' })
  }

  preload() {
    // 載入圖片
    const imgs = {
      'cat-weapon': catWeapon,
      'dog-weapon': dogWeapon,
      'river': river,
    };

    Object.entries(imgs).forEach(([key, value]) => {
      this.load.image(key, value);
    });

    // 載入 spritesheet
    const catSheets = {
      'cat-work': catWork,
      'cat-beaten': catBeaten,
      'cat-attack': catAttack,
    };
    const dogSheets = {
      'dog-work': dogWork,
      'dog-beaten': dogBeaten,
      'dog-attack': dogAttack,
    };

    Object.entries(catSheets).forEach(([key, value]) => {
      this.load.spritesheet(key, value,
        { frameWidth: 300, frameHeight: 300 }
      );
    });
    Object.entries(dogSheets).forEach(([key, value]) => {
      this.load.spritesheet(key, value,
        { frameWidth: 450, frameHeight: 450 }
      );
    });
  }
  create() {
    // 建立動畫
    this.anims.create({
      key: 'cat-work',
      frames: this.anims.generateFrameNumbers('cat-work', { start: 0, end: 1 }),
      frameRate: 4,
      repeat: -1,
    });
    this.anims.create({
      key: 'cat-attack',
      frames: this.anims.generateFrameNumbers('cat-attack', { start: 0, end: 0 }),
      frameRate: 4,
      repeat: 1,
    });
    this.anims.create({
      key: 'cat-beaten',
      frames: this.anims.generateFrameNumbers('cat-beaten', { start: 0, end: 0 }),
      frameRate: 4,
      repeat: 1,
    });

    this.anims.create({
      key: 'dog-work',
      frames: this.anims.generateFrameNumbers('dog-work', { start: 0, end: 1 }),
      frameRate: 4,
      repeat: -1,
    });
    this.anims.create({
      key: 'dog-attack',
      frames: this.anims.generateFrameNumbers('dog-attack', { start: 0, end: 0 }),
      frameRate: 4,
      repeat: 1,
    });
    this.anims.create({
      key: 'dog-beaten',
      frames: this.anims.generateFrameNumbers('dog-beaten', { start: 0, end: 0 }),
      frameRate: 4,
      repeat: 1,
    });

    // 前往下一個場景
    this.scene.start('welcome');
  }
}

所謂的 spritesheet 是指這種圖片:

Untitled

圖片來源:How to create sprite sheets for Phaser 3 with TexturePacker

將連續動作組合起來的圖片,透過 load.spritesheet 載入後,再使用 anims.generateFrameNumbers 進行分割,往後就可以在角色中使用動畫了!

以上我們成功載入所有素材了,接下來讓人物們登場吧!

總結

  • 建立場景
  • 載入所有素材並建立動畫

以上程式碼已同步至 GitLab,大家可以前往下載:

GitLab - D29


上一篇
D28 - 「來互相傷害啊!」:粗乃玩搖桿!
下一篇
D30 - 「來互相傷害啊!」:貓狗集合!建立 Sprite!
系列文
你渴望連結嗎?將 Web 與硬體連上線吧!33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言