本記事はゲームプログラミング初心者向けのものです。
特定のゲームエンジンやフレームワークを使わずに、Javascriptだけでゲームのベースになる部分を作ります。
動作デモ
下記のページに動作するデモを置きました。
キーボードの左右キーでキャラクターが移動します。後をモンスターが追いかけます。
ソースコード
デモのソースコードは下記に置きました。
実装の説明
本記事では、キャラクターの状態に合わせてアニメーションを切り替える仕組みを説明します。
ひとつの実装方法として参考になればと思います。
キャラクターの状態管理
ゲーム中に動き回るキャラクターは、いろんな状態があります。例えば、止まっている、ジャンプしている、走っている、攻撃しているなど。
この記事のデモでは、以下のようなキャラクターの状態があります。
状態管理の実装
プログラムの中で状態を管理するには、状態を定義して状態を保持する変数を作成すればOKです。
const State = {
STANDING: 'STANDING',
MOVE_LEFT: 'MOVE_LEFT',
MOVE_RIGHT: 'MOVE_RIGHT',
}
状態を保持するのはクラスの中のthis.state変数だとします。
状態の変更はthis.state = State.MOVE_LEFTのように行います。また、this.stateを見て、状態にあった座標移動やアニメーションをするように実装します。
以下は状態遷移の実装例です。
switch(this.state) {
case State.STANDING:
// 右キーが押されたら状態を MOVE_RIGHT に変更する
// 左キーが押されたら状態を MOVE_LEFT に変更する
break;
case State.MOVE_RIGHT:
// キャラクタを右に動かす
// キー入力が止まったら STANDING に変更する
// 左キーが押されたら状態を MOVE_LEFT に変更する
break;
case State.MOVE_LEFT:
// キャラクタを左に動かす
// キー入力が止まったら STANDING に変更する
// 右キーが押されたら状態を MOVE_RIGHT に変更する
break;
}
状態ごとのアニメーション管理
ドット絵キャラクターにアニメーションをさせる方法に関しては、下記記事をご参照ください。
状態とアニメーションの対応表
まずは、どの状態にどのようなアニメーションをさせたいか整理します。
この記事のデモでは以下のようになります。
MOVE_LEFTとMOVE_RIGHTのスプライト番号は同じですが、javascriptで描画時に反転処理します。
「スプライト番号」に対応するスプライトシートは下記のとおりです。
状態と対応するアニメーションのテーブル(実装)
今回は以下のような実装で実現しています。
3つの状態があって、状態名からアニメーション用の情報テーブルを弾けるように、javascript言語のプロパティを使っています。pythonの連想配列(dict)と同じようなものです。
const anime_table = {
STANDING: {move_count: 0, frames: [0,1], frame_interval: 60},
MOVE_LEFT: {move_count: 9, frames: [2,3,4], frame_interval: 3},
MOVE_RIGHT: {move_count: 9, frames: [2,3,4], frame_interval: 3},
}
framesがその状態のアニメーションで使うスプライト番号の配列です。この配列のindexを順番に切り替えることで描画するスプライト番号が変わりアニメーションします。
move_countは、状態の動作フレーム数です。
frame_intervalは、アニメーションの更新間隔 (更新待ちフレーム数)です。60に設定されている場合は、60フレームに1回indexを進めるという意味です。
このテーブルを利用してアニメーションを切り替えている実装は下記です。
anime_update() {
let frames = this.anime_table[this.state].frames;
let frame_interval = this.anime_table[this.state].frame_interval;
if (this.anime_count >= frame_interval) {
this.anime_index = (this.anime_index+1) % frames.length;
this.anime_count = 0;
}
this.sprite = frames[this.anime_index];
this.anime_count++;
}
状態ごとアニメーションの切り替え
も少し詳しく、状態の切り替わりとアニメーションについて説明します。
キャラが右に動いている状態 State.MOVE_RIGHT を例にします。
このアニメーションの動きを図にすると、下記のようになります。
右キーが押されたときに、playerキャラの状態は State.MOVE_RIGHT に切り替わります。
切り替わった後に、move_count に設定された 9フレームを使って動きます。その間のアニメーションは frames: [2,3,4] のスプライトを切り替えて行います。切り替えは、frame_interval 設定に従って、3フレームごとの間隔で行います。
9フレーム分の時間が経ったら、State.STANDINGに自動遷移します。
このようなアニメーションの制御(スプライトの切り替え)は下記の関数で実現しています。
キャラクターの移動
Stat¥.MOVE_RIGHT時に、キャラはアニメーションしながら、右にも移動しています。これは、以下のコードで実現しています
update() は20ミリ秒ごとに呼ばれます。これがアニメーションの1フレームです。
setInterval(update, 20);
update()の中で移動の状態のときは、フレームごとに this.count_move() 関数を呼びます。
update() {
・・・
switch(this.state) {
・・・
case State.MOVE_RIGHT:
this.count_move(1, 0);
break;
・・・
}
・・・
}
count_move()関数内で、キャラクターの座標移動をしています。これが this.move_count 分だけ繰り返されます。
count_move(dx, dy) {
this.move_count--;
if (this.move_count < 0) {
this.stop_move();
return;
}
this.x += dx;
this.y += dy;
}
count_move()では、dx = 1, dy = 0 で、右に1ドットずつ動きます。
this.anime_table で、MOVE_RIGHT状態は move_count が 9 に設定されているので、トータルで 9ドット動きます。
まとめ
キャラクターの状態ごとアニメーションの切り替えの実装について説明しました。
ここで示した実装方法は一例にしか過ぎませんが、このベースがあれば、ある程度複雑なゲームの作成に対応できます。マリオブラザーズのようなアクションゲームもこの延長線上で作れます。




