AOYAMA Koji's PROGRAMMING BLOG

10FPSで絵を動かすプログラミング

2020/04/29

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


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


 今回は、記述したプログラムを0.1秒単位で複数回実行する場所を用意してみました。 これを利用してボールの位置を変更して、移動してみましょう。

waiting...



 まずは以下のプログラムを、白い枠内に記載してみてください。 一文字一文字書いても良いですし、コピーして貼り付ける方式でも大丈夫です。 そしてまずは1回実行を押してみてください。
g.ballX += 8;

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

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


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

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


 「+=」(プラスイコール)は、「変数 += 数値;」の形で、変数に値を加える処理になります。 g.ballX は最初が 240 で、左端が0、右端が480です。 その中で g.ballX += 8; を1回実行すると、240 の g.ballX に 8 が加わり g.ballX は 248 になります。 g.ballX はボールのX座標なので、それによりボールが右に少し動いて見えるでしょう。
 似たような処理で「-=」(マイナスイコール)というのもあります。 こちらは引き算ですね。試してみましょう。以下のプログラムを白い枠内に書いて1回実行してみてください。
g.ballX -= 8;

 予想通りに行きましたか?今度は左に少し動けば成功ですよ!

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


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

10FPSでボールが動いています


 動いては見える…と思いますが、一般的なゲームと比べると若干コマ送り感がありますね。 0.1秒間隔の画面変化はすなわち「秒間10コマ」ということになります。 過去に読んだ本によると人間の目は秒間20コマ以上であれば連続していると感じるようなので、ちょっと秒間のコマ数が少ないのですよね。
 一般的なゲームは秒間30コマか60コマで動くことが多いです。 20コマより多いのでスムーズに見えるということになりますね。 最近のゲームは240コマとかもありますのでよりスムーズだと思います。 私の場合秒間60コマを超えるとほとんど見分けはつかないのですけれども(汗
 専門用語で秒間コマ数はFPSといいます。 ゲームをプレイする方なら聞いたことがあるかも知れませんね。 FPSはFrames Per Secondの略です。 ゲームで使用するフレームはゲーム画面の1コマのことなので、 例えば60FPSは、秒間60コマのことですね。 まあそのままです。
 本記事の連続実行は秒間10コマなので、10FPSということになります。 ゲームやっている人からすると「遅っ」っていう数値ですが、 一回一回の動作が見えた方がわかりやすくプログラミングするには良いだろうと考えて設定しています。

左右の端で止まる仕組み


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

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


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

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


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

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

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


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

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


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

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

左右の壁で跳ね返してみます


 さて、本記事で紹介したさまざまなテクニックを積み重ねて、左右の端に到達したときに跳ね返すプログラムを書いてみましょう。
 このプログラムは、方向を決めるパートと、ボールの座標を動かすパートの2つに別れています。 以下を入れて実行してください。
 ひとまず1回実行してみて、うまく行ったなら10回、その後100回実行するのが良いでしょう。
// 左右で跳ね返る
if ( g.ballX == 0 ) {
  g.dirX = "右";
}
if ( g.ballX == 480 ) {
  g.dirX = "左";
}
// 左右に動かす
if ( g.dirX == "右" ) {
  g.ballX += 8;
}
if ( g.dirX == "左" ) {
  g.ballX -= 8;
}

//は無視される注釈


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

左端に来たら右へ


if ( g.ballX == 0 ) {
  g.dirX = "右";
}

 この3行は今までのテクニックを組み合わせたものですが、説明無しでも理解できますでしょうか。 「g.ballXが0ならg.dirXを"右"にする」という処理ですね。 左端が0なので、g.dirXを"右"に、つまり意味としては、ボールが左端に来た時、右に動くようにします。
 そして次の3行は「g.ballXが480ならg.dirXを"左"にする」という処理になります。 480はボールが右端のときのX座標ですので、この部分の意味は、ボールが右端に来た時、左に動くようにする、ですね。
if ( g.ballX == 480 ) {
  g.dirX = "左";
}

まとめ


 本記事では、10FPSでボールを動かすプログラムに挑戦してみました。
 ゲームは10回とか100回とかではなく、延々と処理が繰り返されるのですが、 ここでは何か問題があったときに永遠に続くと困ってしまうと思いましたので、本記事では1回、10回、100回実行したら止まるようにしておきました。 プログラムを書いたら、1回実行してみて、思い通りに動いたら10回、それも思い通りなら100回と、実行していくと良いと思います。

補足

・今回使用しているプログラミング言語はWeb業界で一般的に使われる「JavaScript」です。
・「//」はJavaScript以外にC++など多くのプログラミング言語で注釈ですが、Pythonなど「#」が注釈の言語も多いです。
・本格的にg.ballXを増減させるなら8と-8を取る変数speedXを用意してg.ballX+=speedX;とすべきですが、マイナスの足し算の説明を避けるために本記事の形式としました。
・「g.dirX == "右"」は「"右" === g.dirX」と書くべきという議論があるというか、私ならそう書きますが、より多くのプログラミング言語にある「==」を使用した方が応用が効くだろうこと、変数を左側に統一した方がわかりやすいだろうことから、本記事の形式としました。
・「g.ballX == 0」と「g.ballX == 480」は、本番なら私は「g.ballX <= 0」および「480 <= g.ballX」と書きますが、まあ好みの問題でもありますし、不具合が無ければ不等号はいらないので、今回は説明する演算子を減らす形にしました。

カテゴリー:メガホンDEポン,プログラミング,JavaScript
著者プロフィール
青山公士(あおやま こうじ)
中学2年生からゲームプログラミングに明け暮れる。ゲーム開発者としての代表作に「スーパー桃太郎電鉄II」(ハドソン)メインプログラマー、[PR]『ドラゴンクエストX オンライン』(スクウェア・エニックス)テクニカルディレクター/プロデューサーなどがある。[PR]「ドラゴンクエストXを支える技術」(技術評論社)著者。本ブログは今までの経験を活かしプログラミングが楽しいと感じる人が少しでも増えるようなものにしたい。 @kojibm
株式会社ロジック推し
推し情報を論理的にわかりやすく紹介することで「世の中をちょっと楽しく」をミッションに活動中。 HP X Instagram
privacy policy
ピックアップ
Loading...
最新記事
Loading...
関連記事
Loading...