Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

Javascriptに触れてみる~横スクロールゲーム~

Last updated at Posted at 2024-12-11

はじめに

当記事は 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」はクラスを示しています。あらかじめ項目を決めておき、それを各キャラに反映することでよりシンプルに記述できるようになります。

クラス「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座標と結び付けましょう。

ジャンプと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」として作成しました。

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);
  }

これを前述のクラス内部に入れておくだけです。
完成したものがこちらになります。
image.png
左から操作キャラ、飯、敵になります。敵は操作キャラの段にも出現します。
image.png
当たるとGameOverになりますね。数字は点数を表しています。

おわりに

最期までこのような駄文をお読みいただきありがとうございました。今回は本当に基礎的な部分しかできませんでしたが、今後さらに勉強しゲーム性をもっと持たせたものを作れるよう励みたいと思います。AdventCalendarには本稿より断然優れた記事が数多くありますので以降の記事も読んでいただけたら幸いです。それでは、さようなら~

参考文献

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?