はじめに
当記事は SLP KBIT Advent Calendar 2024 13日目の記事となります。
今回はプログラムに関する先達の産物と雀の涙ほどの知識をもとにゲームを作成し、それを通じてjavascriptについて足を踏み入れてみたいと思います。初心者目線なので稚拙な文章になるかと思いますが、何卒ご容赦願います。
Javascriptとは?
以下、話半分にお読みください。
簡単に言うと、ブラウザ上で動きを加えられる言語であり、ユーザーの動きに応じて内部処理ができるという特徴があります。環境構築・コーディング共に比較的簡単である一方で実行が遅いというデメリットがあります。
本題
今回はJavascriptを通じて、横スクロールゲームを作成していきたいと思います。ほとんど参考文献をなぞることになります。
実装したいもの
・操作キャラクターが画面ごと右に移動する
・他キャラクターが飛んできて、操作キャラクターとぶつかると動作が始まる
・他キャラクターはポイントが入るタイプ(以降「飯」)と、GameOverになるタイプ(以降「敵」)の二種
・操作キャラクターをジャンプさせ、ポイントを稼ぐ
以上です。
キャラクターの初期設定
まずは、キャラクターを配置していきましょう。
キャラクターに必要な要素として、以下を考えました。
function init() {
chara = new Element();
chara.X = 50;
chara.Y = 400;
chara.R = 16;
chara.I = new Image();
chara.I.src = "./cat.gif";
chara.S = 0;
chara.A = 0;
}
X:X座標 Y:Y座標 R:キャラの半径 I:画像 S:速度 A:加速度
同様に、敵/飯に対しても作成しました。
最上列にある、「Element」はクラスを示しています。あらかじめ項目を決めておき、それを各キャラに反映することでよりシンプルに記述できるようになります。
class Element {
I = null;
X = 0;
Y = 0;
S = 0;
A = 0;
R = 0;
}
ジャンプ
次にジャンプの動作を作成します
これはシンプルでchara.Sに初速度、chara.Aに重力を入れるだけです。無限ジャンプしないように制限もつけておきましょう。
function keydown(e) {
if (chara.Y > 399 && scene == Scenes.play) {
chara.S = -20;
chara.A = 1.5;
}
}
ただし、これだけでは速さと加速の大きさが決まっただけで、どの方向に動けばいいのかわかりません。また、キャラは地面を知らないので地面の座標以下に落下しないようにしなければなりません。Y座標と結び付けましょう。
chara.S = chara.S + chara.A;
chara.Y = chara.Y + chara.S;
if (chara.Y > 400) {
chara.Y = 400;
chara.S = 0;
chara.A = 0;
}S;
これで避けられるようになりました。が、このままでは仮に敵に当たってもすり抜けてしまいますね。当たり判定を作成しましょう。
当たり判定
当たり判定には初期設定で使用した「R」を使用します。「teki」は敵のことです。
teki.forEach((e) => {
var haniX = chara.X - e.X;
var haniY = chara.Y - e.Y;
var hani = Math.sqrt(haniX * haniX + haniY * haniY);
if (hani < chara.R + e.R) {
scene = Scenes.Gameover;
}
});
分かりやすく言うと、操作キャラと敵の座標差をX,Yでとり、三平方の定理で距離を計算し、もしそれがキャラの半径Rより近ければ当たったと判定するということですね。飯にも同様に作成しました。飯の場合if内が「tensu+=1」となっており、tensuという要素にポイントを追加してくれます。
敵/飯の行動を作成
飯は一定のリズムで出現し、敵はランダムで出現するようにします。
飯の方は簡単で、画面(-100)に行ったら出発地点(500)へ帰るようにしましょう。
meshi.X -= meshi.S;
if (meshi.X == -100) {
meshi.X = 500;
}:
敵の方はフレームが一定時間経過するごとにランダムで出現するようにしています。消え方は飯と同様です。
function NextTeki() {
var newTeki = new Teki(
600,400 - (Math.random() < 0.5 ? 0 : 50),
12,
"./inoshishi.png",
4 + 5 * Math.random(),
0
);
teki.push(newTeki);
next = Math.floor(frameCount + 30 + 80 * Math.random());
}
三行目では敵の座標を指定しているのですが、Y座標の表現(400以降)をこのかたちにすることで400から少しずれた段にも敵が出現するようにしています。
画面切り替え
Gameover状態を作りましょう。先ほどから時折目にする「scene」というやつです。
今回はゲーム中を「play」ゲームオーバー状態を「GameOver」として作成しました。
const Scenes = {
play: "play",
Gameover: "Gameover",
};
あとは並べるだけ
キャラクタを描画させましょう
draw(g) {
g.drawImage(this.I, this.X - this.I.width / 2, this.Y - this.I.height / 2);
}
これを前述のクラス内部に入れておくだけです。
完成したものがこちらになります。
左から操作キャラ、飯、敵になります。敵は操作キャラの段にも出現します。
当たるとGameOverになりますね。数字は点数を表しています。
おわりに
最期までこのような駄文をお読みいただきありがとうございました。今回は本当に基礎的な部分しかできませんでしたが、今後さらに勉強しゲーム性をもっと持たせたものを作れるよう励みたいと思います。AdventCalendarには本稿より断然優れた記事が数多くありますので以降の記事も読んでいただけたら幸いです。それでは、さようなら~
参考文献