
この記事では Pixi.js を使ってブラウザで動く簡単な2Dゲームを作ってみたいと思います。
爆弾を設置して敵を倒す、某爆弾男ゲームのようなシステムを作ってみようかと。 あくまで簡易的な。
Pixi.js でゲームを作ってみる vol.1 の続きです。
OUTLINE
- キーボードで操作する
- キャラクターの方向転換
- キャラクターの移動
- キャラクターの移動を制限する
キーボードで操作する
キャラクターの方向転換
addEventListener
で keydown
のイベントを取得し、対応した方向へテクスチャの向きを変更させてみました。
PIXI.extras.AnimatedSprite
のテクスチャは、 インスタンス変数 textures
で変更できます。
index.js
// ・
// ・
// ・
/*
* jsonのパス、読み込み完了の関数を与える
*/
loader
.add('sprite', '../_assets/img/sprite.json')
.once('complete', function(){
var
/**
* テクスチャの配列(Left: 0, Back: 1, Right: 2, Front: 3)
*/
ttCharacter = [],
/**
* キャラクター要素
*/
elmCharacter,
i, j, k;
for (i = 0; i < 4; i++) {
// 4方向
ttCharacter[i] = [];
for (j = 0; j < 4; j++) {
// 4フレーム
var frame = j === 0 ? 0:
j === 1 ? 1:
j === 2 ? 0:
j === 3 ? 2:
0;
ttCharacter[i].push(PIXI.Texture.fromFrame('character-' + i + '-' + frame));
}
}
/**
* キャラクターの生成(Left: 0, Back: 1, Right: 2, Front: 3)
*/
elmCharacter = new PIXI.extras.AnimatedSprite(ttCharacter[3]);
elmCharacter.play();
elmCharacter.animationSpeed = 0.1;
/**
* キャラクターの基準点、位置を設定
*/
elmCharacter.anchor.set(0.5);
elmCharacter.position.set(640 / 2, 360 / 2);
stage.addChild(elmCharacter);
/*
* キーボードが押されたイベント
*/
document.addEventListener('keydown', handleKeyDown);
function handleKeyDown(e){
var key = e.key;
/**
* キーボードの矢印キーに対応したテクスチャに変更
*/
switch (key) {
case 'ArrowLeft':
console.log('left');
elmCharacter.textures = ttCharacter[0];
break;
case 'ArrowUp':
console.log('up');
elmCharacter.textures = ttCharacter[1];
break;
case 'ArrowRight':
console.log('right');
elmCharacter.textures = ttCharacter[2];
break;
case 'ArrowDown':
console.log('down');
elmCharacter.textures = ttCharacter[3];
break;
default:
break;
}
}
});
/*
* 読み込む
*/
loader.load();
動くんだけど、テクスチャの切り替えがやたら遅い。。。
textures
で別のテクスチャを指定してから アニメーションの play()
が1周終わるまで、テクスチャ切り替えはお預けのよう。。。
なので別の案を。 新たに PIXI.Container
を作って、4種類のアニメーションを全部ぶっこんでおく。 方向切り替えのタイミングで該当するアニメーションのみ visible = true
で表示、 その他は false
で非表示にしておく。
index.js
// ・
// ・
// ・
/*
* jsonのパス、読み込み完了の関数を与える
*/
loader
.add('sprite', '../_assets/img/sprite.json')
.once('complete', function(){
var
/**
* テクスチャの配列(Left: 0, Back: 1, Right: 2, Front: 3)
*/
ttCharacter = [],
/**
* キャラクターアニメーションの配列
*/
elmAnimationCharacter = [],
/**
* キャラクター要素
*/
elmCharacter = new PIXI.Container(),
i, j, k;
for (i = 0; i < 4; i++) {
// 4方向
ttCharacter[i] = [];
for (j = 0; j < 4; j++) {
// 4フレーム
var frame = j === 0 ? 0:
j === 1 ? 1:
j === 2 ? 0:
j === 3 ? 2:
0;
ttCharacter[i].push(PIXI.Texture.fromFrame('character-' + i + '-' + frame));
}
}
for (k = 0; k < 4; k++) {
elmAnimationCharacter.push(new PIXI.extras.AnimatedSprite(ttCharacter[k]));
elmAnimationCharacter[k].play();
elmAnimationCharacter[k].animationSpeed = 0.1;
elmAnimationCharacter[k].anchor.set(0.5);
elmAnimationCharacter[k].visible = false;
elmCharacter.addChild(elmAnimationCharacter[k]);
}
/**
* 正面(Front: 3)を表示する
*/
elmAnimationCharacter[3].visible = true;
elmCharacter.position.set(640 / 3, 360 / 2);
stage.addChild(elmCharacter);
/**
* キーボードが押されたイベント
*/
document.addEventListener('keydown', handleKeyDown);
function handleKeyDown(e){
var
key = e.key,
i;
/**
* 全てのアニメーションを非表示
*/
for (i = 0; i < 4; i++) {
elmAnimationCharacter[i].visible = false;
}
/**
* 矢印キーの方向のアニメーションのみ表示
*/
switch (key) {
case 'ArrowLeft':
console.log('left');
elmAnimationCharacter[0].visible = true;
break;
case 'ArrowUp':
console.log('up');
elmAnimationCharacter[1].visible = true;
break;
case 'ArrowRight':
console.log('right');
elmAnimationCharacter[2].visible = true;
break;
case 'ArrowDown':
console.log('down');
elmAnimationCharacter[3].visible = true;
break;
default:
break;
}
}
});
/*
* 読み込む
*/
loader.load();
これでスムーズに切り替わるようになりました!
続きますよ( ˘⊖˘)
キャラクターの移動
単純に押された方向にキャラクターを移動させるだけなら下記のように書けます。 押された方向に PIXI.Container
の position をズラすだけです。
index.js
// ・
// ・
// ・
/**
* 矢印キーの方向に移動
* 矢印キーの方向のアニメーションのみ表示
*/
switch (key) {
case 'ArrowLeft':
console.log('left');
elmAnimationCharacter[0].visible = true;
elmCharacter.position.x -= 16; // 左に16pxズラす
break;
case 'ArrowUp':
console.log('up');
elmAnimationCharacter[1].visible = true;
elmCharacter.position.y -= 16; // 上に16pxズラす
break;
case 'ArrowRight':
console.log('right');
elmAnimationCharacter[2].visible = true;
elmCharacter.position.x += 16; // 右に16pxズラす
break;
case 'ArrowDown':
console.log('down');
elmAnimationCharacter[3].visible = true;
elmCharacter.position.y += 16; // 下に16pxズラす
break;
default:
break;
}
// ・
// ・
// ・
が、キーボードを押しっぱなしにした場合に、 イベント keydown
が起こるタイミングがゲームとして致命的な感じです。 テキストエディタでカーソルを移動させるときのように、ピッ……ピッピッピッピッ……という感じで、初回の入力後に若干の間が生じた後、ようやく連続っぽい動作をします。
そこで、 こちらのブログを参考にしました。
初心者がモチベーション上げながらプログラミングをしてシューティング(っぽい)ゲームを1本作る! – Λlisue’s blog
keydown
、 keyup
のイベントのタイミングでキー入力状態を一旦保存。 常時その入力状態をチェックするループ関数で移動を行う感じです。
index.js
// ・
// ・
// ・
/**
* キーの状態を保存(true: 押されている, false: 押されていない)
*/
var
keyStatus = [],
i;
for (i = 0; i < 4; i++) {
keyStatus[i] = false;
}
/**
* キーボードが押されたイベント
*/
document.addEventListener('keydown', function (e){
keyStatus[e.keyCode - 37] = true;
}, false);
document.addEventListener('keyup', function (e){
keyStatus[e.keyCode - 37] = false;
}, false);
/*
* checkInput 関数を定義
*/
var checkInput = function () {
var
i,
KEY_LEFT = 0,
KEY_UP = 1,
KEY_RIGHT = 2,
KEY_DOWN = 3,
/**
* 全てのアニメーションを非表示
*/
hideAnimation = function () {
for (i = 0; i < 4; i++) {
elmAnimationCharacter[i].visible = false;
}
};
/**
* 矢印キーの方向に移動
* 矢印キーの方向のアニメーションのみ表示
*/
if (keyStatus[KEY_LEFT]) {
hideAnimation();
elmAnimationCharacter[0].visible = true;
elmCharacter.position.x -= 2;
}
if (keyStatus[KEY_UP]) {
hideAnimation();
elmAnimationCharacter[1].visible = true;
elmCharacter.position.y -= 2;
}
if (keyStatus[KEY_RIGHT]) {
hideAnimation();
elmAnimationCharacter[2].visible = true;
elmCharacter.position.x += 2;
}
if (keyStatus[KEY_DOWN]) {
hideAnimation();
elmAnimationCharacter[3].visible = true;
elmCharacter.position.y += 2;
}
requestAnimationFrame(checkInput);
};
checkInput();
// ・
// ・
// ・
遅延等なく動きもスムーズ! また上記のような方法だと、 同時押しも検出できるため斜め移動も可能です。 斜め方向だと移動速度が速く見えてしまいますが、今回は目をつむります。 スーファミでもよくあるしね。。。
続きますよ( ˘⊖˘)
キャラクターの移動を制限する
まだゲームステージもできてないので、とりあえず画面外には行けないように制限をかけます。
index.js
// ・
// ・
// ・
/*
* checkInput 関数を定義
*/
var checkInput = function () {
var
i,
KEY_LEFT = 0,
KEY_UP = 1,
KEY_RIGHT = 2,
KEY_DOWN = 3,
/**
* 全てのアニメーションを非表示
*/
hideAnimation = function () {
for (i = 0; i < 4; i++) {
elmAnimationCharacter[i].visible = false;
}
},
/**
* 移動を制限
*/
restrictMovement = function () {
if (elmCharacter.x - 40 <= 0) {
elmCharacter.x = 40;
} else if (elmCharacter.x + 40 >= 640 * 2) {
elmCharacter.x = 640 * 2 - 40;
}
if (elmCharacter.y - 80 <= 0) {
elmCharacter.y = 80;
} else if (elmCharacter.y >= 360 * 2) {
elmCharacter.y = 360 * 2;
}
};
/**
* 矢印キーの方向に移動
* 矢印キーの方向のアニメーションのみ表示
*/
if (keyStatus[KEY_LEFT]) {
hideAnimation();
elmAnimationCharacter[0].visible = true;
elmCharacter.position.x -= 4;
restrictMovement();
}
if (keyStatus[KEY_UP]) {
hideAnimation();
elmAnimationCharacter[1].visible = true;
elmCharacter.position.y -= 4;
restrictMovement();
}
if (keyStatus[KEY_RIGHT]) {
hideAnimation();
elmAnimationCharacter[2].visible = true;
elmCharacter.position.x += 4;
restrictMovement();
}
if (keyStatus[KEY_DOWN]) {
hideAnimation();
elmAnimationCharacter[3].visible = true;
elmCharacter.position.y += 4;
restrictMovement();
}
requestAnimationFrame(checkInput);
};
// ・
// ・
// ・
ゲームステージを作る段階でグリッドを導入するので、その時にもうちょっとちゃんと制限かけようと思います。
あとモジュール分けたり、リファクタリングしないと汚くなってきた。。。
vol.2はここまで( ˘⊖˘)
続きは Pixi.js でゲームを作ってみる vol.3 から。