Pixi.js + TypeScript + Viteでゲームを作る 2. キャラクターの表示とキー入力
前回の記事ではPixi.jsをTypeScriptで呼び出してみました、今回はPixi.jsを使ってキャラクターを表示して、キーボード入力で操作をしてみます。 基本的にPixi.js公式のチュートリアルをTypeScriptに置き換えながら進めているだけなので、詳細はリンクを参照してください。
キャラクターの読み込み処理の追加
await Assets.load([
{
alias: 'spineSkeleton',
src: 'https://raw.githubusercontent.com/pixijs/spine-v8/main/examples/assets/spineboy-pro.skel',
},
{
alias: 'spineAtlas',
src: 'https://raw.githubusercontent.com/pixijs/spine-v8/main/examples/assets/spineboy-pma.atlas',
},
{
alias: 'sky',
src: 'https://pixijs.com/assets/tutorials/spineboy-adventure/sky.png',
},
{
alias: 'background',
src: 'https://pixijs.com/assets/tutorials/spineboy-adventure/background.png',
},
{
alias: 'midground',
src: 'https://pixijs.com/assets/tutorials/spineboy-adventure/midground.png',
},
{
alias: 'platform',
src: 'https://pixijs.com/assets/tutorials/spineboy-adventure/platform.png',
},
]);
キャラクター用Classの作成
キャラクターを制御するためのクラスを作成します。 これはpixi.jsに密接に紐づいていて、コンストラクタでpixi.jsのContainerとspineを生成します
import { Spine } from "@pixi/spine-pixi";
import { Container } from "pixi.js";
// Class for handling the character Spine and its animations.
export class SpineBoy {
public view: Container;
public spine: Spine;
constructor() {
// Create the main view.
this.view = new Container();
// Create the Spine instance using the preloaded Spine asset aliases.
this.spine = Spine.from({
skeleton: "spineSkeleton",
atlas: "spineAtlas",
});
// Add the spine to the main view.
this.view.addChild(this.spine);
}
}
controllerの作成
// Map keyboard key codes to controller's state keys
const KEYS = [
'Space',
'KeyW',
'ArrowUp',
'KeyA',
'ArrowLeft',
'KeyS',
'ArrowDown',
'KeyD',
'ArrowRight',
]
type Key = typeof KEYS[number];
const keyMap: {
[key in Key]: string;
} = {
Space: 'space',
KeyW: 'up',
ArrowUp: 'up',
KeyA: 'left',
ArrowLeft: 'left',
KeyS: 'down',
ArrowDown: 'down',
KeyD: 'right',
ArrowRight: 'right',
};
// Class for handling keyboard inputs.
export class Controller
{
keys: Record<string, { pressed: boolean, doubleTap: boolean, timestamp: number }>;
constructor()
{
// The controller's state.
this.keys = {
up: { pressed: false, doubleTap: false, timestamp: 0 },
left: { pressed: false, doubleTap: false, timestamp: 0 },
down: { pressed: false, doubleTap: false, timestamp: 0 },
right: { pressed: false, doubleTap: false, timestamp: 0 },
space: { pressed: false, doubleTap: false, timestamp: 0 },
};
// Register event listeners for keydown and keyup events.
window.addEventListener('keydown', (event) => this.keydownHandler(event));
window.addEventListener('keyup', (event) => this.keyupHandler(event));
}
private keydownHandler(event: KeyboardEvent)
{
const key = keyMap[event.code];
if (!key) return;
const now = Date.now();
// If not already in the double-tap state, toggle the double tap state if the key was pressed twice within 300ms.
this.keys[key].doubleTap = this.keys[key].doubleTap || now - this.keys[key].timestamp < 300;
// Toggle on the key pressed state.
this.keys[key].pressed = true;
}
private keyupHandler(event: KeyboardEvent)
{
const key = keyMap[event.code];
if (!key) return;
const now = Date.now();
// Reset the key pressed state.
this.keys[key].pressed = false;
// Reset double tap only if the key is in the double-tap state.
if (this.keys[key].doubleTap) this.keys[key].doubleTap = false;
// Otherwise, update the timestamp to track the time difference till the next potential key down.
else this.keys[key].timestamp = now;
}
}
コメント