AOYAMA KOJI's PROGRAMMING BLOG

10fpsで絵を動かすプログラミング【絵が動くゲームを作ってみよう】プログラミングを始めようとしている方・初心者向け

2020/04/29
10fpsで絵を動かすプログラミング【絵が動くゲームを作ってみよう】

 いやあ「鬼滅の刃」面白いですね。 結構前から話題になっていたので遅ればせながらという感じですが、 本記事を書きながらアマゾンPrimeで第一話から見始めました。 そしてまったくキーボードが進みません(笑)
 さて、それはそれとして、思いつきでプログラミングを解説するブログを始めてしまったので、 このあとどうしようか決めておらず自分の中で整理してみました。 これからは記述エリアに記載されたプログラムを単純に1回実行するだけじゃなく、 必要に応じた処理を加えて説明しつつ、 ゲームプログラミングを少しずつ紹介していきたいと思います。


[PR]

ボールの位置を変更するプログラミングをしてみる


 10fpsすなわち0.1秒単位で複数回プログラムを実行する体験ができる場所を、本記事で用意しました。 これを利用して、ボールの位置を変更して、ゲームのように絵が移動するプログラムを体験してみましょう。

 まずは以下のプログラムを試しましょう。 1回実行を押下してみてください。
waiting...
g.iBallX += 8;

 どうでしょうか?ボールがちょっとだけ右に動けば成功です!

変数g.iBallXはボールのX座標


 本記事では、ボールの位置はg.iBallXとという名前の入れ物に入っています。 このように値を入れておく入れ物を、プログラム用語では変数と呼びます。 変数の名前は自由に付けることができて、g.iBallX は筆者が命名しました。
 また「位置」と書きましたが、正確には横の位置になり、数学の用語で言うとX座標になります。
 つまり先程の説明を言い換えると、変数g.iBallXにボールのX座標が入っているということになります。 こうした専門用語は、知らない人にはわかりづらいと思いますが、 知っている人同士であれば正確かつより端的に表現できるのでベターなのですよね。 そういう意識もあるので、当ブログでも積極的に使っていきたいと思います。

「+=」は足し算、「-=」は引き算


 「+=」(プラスイコール)は、「変数 += 数値;」の形で、変数に値を加える処理になります。 g.iBallX は最初が 144 で、左端が0、右端が288です。 その中で g.iBallX += 8; を1回実行すると、144 の g.iBallX に 8 が加わり g.iBallX は 152 になります。 g.iBallX はボールのX座標なので、それによりボールが右に少し動いて見えるでしょう。

左へ動く処理


 似たような処理で「-=」(マイナスイコール)というのもあります。 こちらは引き算ですね。試してみましょう。
waiting...
g.iBallX -= 8;

 「1回実行」をしてみてください。 予想通りに行きましたか?今度は左に少し動けば成功です!

連続実行するとボールが動いて見えるように


 では、「10回実行」をクリックやタップしてみてください。
 うまくいきましたか?約1秒間、左にボールが動き続ければ成功です!
 本記事の「10回実行」は、記載のプログラムを0.1秒ごとに10回実行する処理になります。 つまり、0.1秒ごとに「g.iBallX -= 8;」を実行します。 「10回実行」を押す前は、g.iBallXが144から「1回実行」して136になっていました。 そこから128、112…と減っていって、最終的には48になります。
 このように、コマ送りでボールのX座標が変化しているのですが、どうでしょう?動いているようにも見えますよね?

10fpsでボールが動いて見える


 動いては見える…と思いますが、一般的なゲームと比べると若干コマ送り感がありますね。

コマ送り感の理由


 0.1秒間隔の画面変化はすなわち「秒間10コマ」ということになります。 過去に読んだ本によると人間の目は秒間20コマ以上であれば連続していると感じるようなので、ちょっと秒間のコマ数が少ないのですよね。

一般的なゲームは秒間30コマ以上


 一般的なゲームは、秒間30コマか60コマ、あるいはそれ以上で動くことが多いです。
 20コマより多いのでスムーズに見えるということになりますね。 最近のゲームは240コマとかもありますのでよりスムーズだと思います。 筆者は秒間60コマを超えると、ほとんど見分けはつかないのですけれども(汗)

秒間コマ数「fps」


 専門用語で、秒間コマ数はfpsといいます。
 ゲームをプレイする方なら、聞いたことがあるかもしれません。 fpsはFrames Per Secondの略です。
 ゲームで使用するフレームは、ゲーム画面の1コマのことです。 例えば60fpsは、秒間60コマです。 まあそのままです。
 本記事の連続実行は、秒間10コマなので、10fpsということになります。
 ゲームやっている人からすると「遅っ」っていう数値ですが、 1回1回の動作が見えた方がわかりやすくプログラミングするには良いだろうと考えて設定しています。

左右の端で止まる仕組み


waiting...
g.iBallX -= 8;

 今度は「20回実行」をクリックやタップしてみてください。 「g.iBallX -= 8;」が20回実行されます。ボールが左端に到着すれば成功です。
 本記事のプログラムはで、g.iBallXは0より小さくなったら強制的に0にする処理を入れてあるので、左端で止まるようにできています。 同様にg.iBallXが288より大きくならないようにしているので「g.iBallX += 8;」を多く実行しても右端で止まります。

左右に動くプログラムを書いてみましょう


 ではもう一歩進んで、左右の両方に動くプログラムを試してみましょう。
 本記事ではそのために変数g.sDirXを用意しました。 最初は"右"が入っています。 これを使って以下のプログラムを実行してみてください。
waiting...
if ( "右" === g.sDirX ) {
  g.iBallX += 8;
}
if ( "左" === g.sDirX ) {
  g.iBallX -= 8;
}

ifは条件を判定して処理する機能


 最初の行にある if は、英語のifから来ているもので、日本語に訳すと「もし」ですね。 以下の書き方で使用します。
if ( 条件 ) {
  処理
}

 そして「もし条件が成立していれば処理を実行する」という機能になります。

「===」は同じかどうかを判定する機能


 ifの中の条件にあたる部分にある「===」(イコールイコールイコール)は、同じかどうかを判定する機能になります。 つまり「"右" === g.sDirX」は、g.sDirXが"右"かどうか判定します。

変数g.sDirXの値に応じて左右に動かす


 以上を組み合わせた以下のプログラムは、「g.sDirXが"右"ならg.iBallX += 8;を実行する」というプログラムになります。 もう少し言い換えると「g.sDirXが"右"ならボールを右に動かす」ですね。
if ( "右" === g.sDirX ) {
  g.iBallX += 8;
}

 以下は「g.sDirXが"左"ならボールを左に動かす」となります。
if ( "左" === g.sDirX ) {
  g.iBallX -= 8;
}

左右の壁で跳ね返す


10fpsで絵を動かすプログラミング【絵が動くゲームを作ってみよう】  さて、本記事で紹介したさまざまなテクニックを積み重ねて、左右の端に到達したときに跳ね返すプログラムを書いてみましょう。
[PR]

 このプログラムは、方向を決めるパートと、ボールの座標を動かすパートの2つに別れています。 以下の「100回実行」をしてみてください。 左右の壁で跳ね返りながら動いていますか?
waiting...
// 左右で跳ね返る
if ( g.iBallX <= 0 ) {
  g.sDirX = "右";
}
if ( 288 <= g.iBallX ) {
  g.sDirX = "左";
}
// 左右に動かす
if ( "右" === g.sDirX ) {
  g.iBallX += 8;
}
if ( "左" === g.sDirX ) {
  g.iBallX -= 8;
}

//は無視される注釈


 最初の行にある「//」は注釈です。 プログラムのある行の中に「//」が出てきた場合、それより右は意味がないプログラムとして無視されます。 先頭にあればその行すべてが無視されます。
 無視されるプログラムってに感じると思いますが、 そこにプログラミングの規則を無視したテキストが書けるので、人間向けの注釈を書くときに使用します。 このプログラムがどんなことをしているのか、理解を助けるコメントを入れておくと良いでしょう。
 自分の書いたプログラムも時間が経過するとれてしまうことがよくあります。 仕事であればチームを組んでプログラミングすることも多く、他人の書いたプログラムを読む機会が増えますが、自分の書いたものより理解が難しいです。 本格的にプログラミングする場合は、ちょくちょく適切な注釈を入れることをお勧めします。

左端に来たら右へ


if ( g.iBallX <= 0 ) {
  g.sDirX = "右";
}

 この3行は今までのテクニックを組み合わせたものです。 「g.iBallXが0(以下)ならg.sDirXを"右"にする」という処理です。 左端が0なので、g.sDirXを"右"に、つまり意味としては、ボールが左端に来た時、右に動くようにします。 何かの間違いでマイナスになってしまっても対応できるように、条件を0「以下」としています。

右端に来たら左へ


 そして次の3行は「g.iBallXが288ならg.sDirXを"左"にする」という処理になります。 288はボールが右端のときのX座標ですので、この部分の意味は、ボールが右端に来た時、左に動くようにする、ですね。 同様に、条件を288「以上」としています。
if ( 288 <= g.iBallX ) {
  g.sDirX = "左";
}

動くゲームの基本も同じ


 色々なものが動いているゲームもこのように、一定間隔で処理をして、画面に表示することで、動いているように見せています。
 ここでは最大100回の制限をかけましたが、もちろんゲームではこの処理が延々と処理が繰り返されます。 ほかにも色々なテクニックがありますが、基本的な仕組みは、これで解説できたと思います。
[PR]

まとめ


 本記事では、10fpsすなわち0.1秒単位で複数回プログラムを実行し、ゲームのように絵が移動するプログラムを体験しました。
 本記事を通して、少しでも、プログラミングをしく感じていただけましたら、幸いです。

補足

  • 今回使用しているプログラミング言語はWeb業界で一般的に使われる「JavaScript」です。
  • 「//」はJavaScript以外にC++など多くのプログラミング言語で注釈ですが、Pythonなど「#」が注釈の言語も多いです。
  • 本格的にg.iBallXを増減させるなら8と-8を取る変数speedXを用意してg.iBallX+=speedX;とすべきですが、マイナスの足し算の説明を避けるために本記事の形式としました。
  • (本記事公開後変更)多くのプログラミング言語は「===」ではなく「==」で同一かどうかを比較をします。JavaScriptも「==」での比較が可能ですが、「===」の方が厳密のため、筆者はこちらを使用しています。
  • (本記事公開後変更)「"右" === g.sDirX」を「g.sDirX === "右"」と書く方も多いと思います。どちらでも大丈夫です。筆者は、コーディングルールで特に決まっていなければ、定数を左辺、変数を右辺にしています。
  • (本記事公開後変更)「288 <= g.iBallX」を「g.iBallX >= 288」と書く方も多いと思います。どちらでも大丈夫です。筆者は、コーディングルールで特に決まっていなければ、小さい方を左辺にしています。
  • (本記事公開後)初期に提示していたプログラム記述ギミックを2025年5月にセキュリティー上の都合で閉じました。

カテゴリー:絵が動くゲームを作ってみよう,絵を動かす
[PR]