この記事は最終更新日から1年以上が経過しています。
@programming
投稿日 2020/2/27
更新日 2020/3/6 ✏
PixiJSでブラウザゲーム 05方向キーで操作
PixiJSでブラウザゲーム 04クリックイベントではクリックイベントの実装方法を紹介しました。 今回は、矢印方向キーでキャラを操作する処理を実装してみたいと思います。 サンプルでは、矢印方向キーでキャラアイコンを動かすことができます。さらに障害物の猫を設置しその上を通過することは出来なくしてあります。
目次:
前提
- PixiJS v5.2.1
サンプルコード
05-move-character.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>方向キーでキャラを操作</title>
</head>
<body>
<div>
方向キーでキャラを動かせます。
障害物(猫)の上は通過できなくしてあります。
</div>
<div id="game"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.3/pixi.min.js"></script>
<script>
// Create a Pixi Application
const app = new PIXI.Application({
width: 512,
height: 512,
antialiasing: true,
transparent: false,
resolution: 1
});
let gameScene;
let player;
const collisions = []; // 障害物(猫)一覧
// #game要素にpixiApp.view追加
document.querySelector("#game").appendChild(app.view);
// ロード
PIXI.Loader.shared
// リソースを登録
// 第一引数は任意のキー、第二引数は実体パス
.add("chara-1", "https://i.imgur.com/JNGbC6F.png")
.add("chara-2", "https://i.imgur.com/H9smyaD.png")
.add("chara-3", "https://i.imgur.com/xT6FStW.png")
.add("explorer", "https://i.imgur.com/rWus6RK.png")
.add("cat", "https://i.imgur.com/Fk2JkI5.png")
.add("dungeon", "https://i.imgur.com/EzpxVBZ.png")
.load(setup);
//This `setup` function will run when the image has loaded
function setup(loader, res) {
// ゲームシーンを作成
gameScene = new PIXI.Container();
app.stage.addChild(gameScene);
// ダンジョン作成(ここで画面の大枠サイズを確定)
const dungeon = new PIXI.Sprite(PIXI.utils.TextureCache["dungeon"]);
gameScene.addChild(dungeon);
// アニメーションを作成してシーンに追加
player = createAnim(["chara-1", "chara-2", "chara-3", ]);
player.x = 68;
player.y = gameScene.height / 2 - player.height / 2;
player.vx = 0;
player.vy = 0;
player.play();
player.anchor.set(0.5, 0.5); // NOTE: キャラアイコンの重心をアイコンの中心にセット
gameScene.addChild(player);
//
// 障害物(猫)をテキトーに配置
//
// 障害物1(猫)を作成してシーンに追加
const cat = new PIXI.Sprite(PIXI.utils.TextureCache["cat"]);
cat.x = 200;
cat.y = gameScene.height / 2 - cat.height / 2;
gameScene.addChild(cat);
collisions.push(cat); // 障害物として登録
// 障害物2(猫)を作成してシーンに追加
const cat2 = new PIXI.Sprite(PIXI.utils.TextureCache["cat"]);
cat2.x = 100;
cat2.y = 400;
gameScene.addChild(cat2);
collisions.push(cat2); // 障害物として登録
// 障害物3(猫)を作成してシーンに追加
const cat3 = new PIXI.Sprite(PIXI.utils.TextureCache["cat"]);
cat3.x = 400;
cat3.y = 200;
gameScene.addChild(cat3);
collisions.push(cat3); // 障害物として登録
// 方向キーイベントを初期化
initArrowEvent();
// Start the game loop
app.ticker.add((delta) => {
// プレイヤーの移動方向取得
const playerDirection = getPlayerDirection();
// 障害物と衝突していないかチェック
for (let len = collisions.length, i = 0; i < len; i++) {
const collision = collisions[i];
const hitDirection = getCollisionDirection(collision);
if (hitDirection) return;
}
player.x += player.vx;
player.y += player.vy;
});
}
/**
* アニメーションスプライトオブジェクトを作成
* @param {Array<String>} imgs - imageパスの配列
* @param {Object} opts - [OPTIONAL] オプション @see PIXI.AnimatedSprite
* @return {AnimatedSprite}
*/
function createAnim(imgs, opts) {
const textureArray = [];
for (let i = 0; i < imgs.length; i++) {
let texture = PIXI.Texture.from(imgs[i]);
textureArray.push(texture);
};
const animatedSprite = new PIXI.AnimatedSprite(textureArray);
animatedSprite.animationSpeed = (opts && opts.animationSpeed) ? opts.animationSpeed : 0.1;
return animatedSprite;
}
/** プレイヤーの移動方向を取得 */
function getPlayerDirection() {
if (player.vx > 0) return "right";
if (player.vx < 0) return "left";
if (player.vy > 0) return "bottom";
if (player.vy < 0) return "top";
return null;
}
/** プレイヤーが衝突した障害物の方向を取得 */
function getCollisionDirection(collision) {
const { x, y, vx, vy } = player;
let direction = null;
const nextX = x + vx;
const nextY = y + vy;
const targetRangeX = [collision.x, collision.x + collision.width];
const targetRangeY = [collision.y, collision.y + collision.height];
if ((nextX >= targetRangeX[0] && nextX <= targetRangeX[1]) &&
(nextY >= targetRangeY[0] && nextY <= targetRangeY[1])) {
if (vx > 0) direction = "right";
else if (vx < 0) direction = "left";
else if (vy > 0) direction = "bottom";
else if (vy < 0) direction = "top";
}
return direction;
}
/**
* 方向キーイベントを初期化
*/
function initArrowEvent() {
// Capture the keyboard arrow keys
const left = keyboard(37),
up = keyboard(38),
right = keyboard(39),
down = keyboard(40);
//Left arrow key `press` method
left.press = function() {
//Change the player's velocity when the key is pressed
player.vx = -5;
player.vy = 0;
};
//Left arrow key `release` method
left.release = function() {
//If the left arrow has been released, and the right arrow isn't down,
//and the player isn't moving vertically:
//Stop the player
if (!right.isDown && player.vy === 0) {
player.vx = 0;
}
};
//Up
up.press = function() {
player.vy = -5;
player.vx = 0;
};
up.release = function() {
if (!down.isDown && player.vx === 0) {
player.vy = 0;
}
};
//Right
right.press = function() {
player.vx = 5;
player.vy = 0;
};
right.release = function() {
if (!left.isDown && player.vy === 0) {
player.vx = 0;
}
};
//Down
down.press = function() {
player.vy = 5;
player.vx = 0;
};
down.release = function() {
if (!up.isDown && player.vx === 0) {
player.vy = 0;
}
};
// The `keyboard` helper function
function keyboard(keyCode) {
var key = {};
key.code = keyCode;
key.isDown = false;
key.isUp = true;
key.press = undefined;
key.release = undefined;
//The `downHandler`
key.downHandler = function(event) {
if (event.keyCode === key.code) {
if (key.isUp && key.press) key.press();
key.isDown = true;
key.isUp = false;
}
event.preventDefault();
};
//The `upHandler`
key.upHandler = function(event) {
if (event.keyCode === key.code) {
if (key.isDown && key.release) key.release();
key.isDown = false;
key.isUp = true;
}
event.preventDefault();
};
//Attach event listeners
window.addEventListener(
"keydown", key.downHandler.bind(key), false
);
window.addEventListener(
"keyup", key.upHandler.bind(key), false
);
return key;
}
}
</script>
</body>
</html>
実行
以下のiframeをクリックしカーソルを当ててから方向キーを操作してみてください。
ひとこと
以上、方向キーでキャラを動かす方法が分かりましたね。 次回はドラクエ風の流れるメッセージをゲームシーン上に表示してみましょう。
宣伝: PixiJSを使ったブラウザゲーム開発なら田中ソフトウェアラボにご相談ください!