【プチコン4講座】プレイヤーを色々な位置に動かしてみよう
こんにちは。継続の錬金術士なおキーヌです。
ブログ毎日更新は209日目になります。
前回はスプライトを設定し、座標を変更しました。
今回は座標変更の命令「SPOFS」を使ってプレイヤーを色々な位置に動かしてみましょう。
今回はまだ操作できませんが、操作する前の準備運動だと思ってください。
それではプチコン4でSTG作りその第2回目始めましょう。
プレイヤーを動かし続けるには
マユミちゃん、Switch持ってきた?
うん!ちゃんとプチコン4もインストールして持ってきたよ!
トモカズ、今日は何を教えてくれるんだ?
今日は前回の復習と、プログラミングの基礎を使った応用編といこうか。それじゃあ早速だけど次のコードを打ちこんでね。コードは前回のものを流用するけど短いから全部記述しておいたよ。
' 画面全消し
ACLS
' 変数XとYを用意【追加部分】
var X = 0
var Y = 0
' スプライト準備
SPSET 0, 352
' ゲームループ
loop
' スプライト移動
SPOFS 0, X, Y
' 変数Xに1を足す
INC X
loopend
なんか色々増えたな。俺は何しているか大体わかったぜ!トモカズに教えてもらったプログラミングの基礎が役立ってる感じがするぞ!
マユミちゃんはこれ何しているかわかる?
ちょ、ちょっと時間ちょうだい!……XとYは0で……ループってことは繰り返しよね……SPOFSはキャラクター(スプライト)の移動でしょ?そしてXに+1をしてまた移動……でしょ?合ってる?
大正解だよマユミちゃん。
流石理系サマ!プログラミングを知らなくても書かれていることから推察したのはすげぇな!
ふ、ふん!これぐらい簡単よ!
ボクの認識違いだったらゴメンなんだけど、「X=0」は何をしていると思う?
え?そんなの決まってるじゃない。Xは0って意味でしょ?
じゃあ次のXの値を答えてみて
X = 0
Y = 1
X = Y
ちょっとまって!Xは0でYは1ならX=Yは成り立たないでしょ?
リキくんなら答えられるよね?
あぁ!Xの値は「1」だぜ!
え?どういうことなの?
ゴメンゴメン、ちょっと間違った認識のまま進めたくなかったから確認したんだけどなんかイジワルしたみたいになっちゃったね。
解説すると、プログラミングでの=は「代入」って意味になるんだよ。「X=0」これは算数と同じ考えで「Xは0」って意味でも合ってるんだけど……それは元々Xの数値が0だったって意味になっちゃうんだ
それは違うってこと?
プログラミングでの「X=0」っていうのはXという名前の箱に0という数値を入れたと考えてもらわなきゃダメなんだ。
箱に0を入れるぅ??0って何もないから箱に入れられるの?
頭ガチガチだな、お前……
何よ!頭ゼリーのリキに言われたくないわよ!
プログラミングにおいて何も無しは0ではないんだよ。今回はX座標ってわかりやすいように箱に「X」と名付けたんだけど実はこれはAだろうがBだろうがどんな名前にしても大丈夫なんだ。
うーん……トモくん、もうちょっとわかりやすくオネガイ!
えっと……この「X」っていう箱は変数っていうんだ。数字でも文字でも命令でもなんでも入る便利な箱って覚えてくれたらいいよ。
なんでも入る箱……変数……わかった。そういうことにしておく。
そう、その考えプログラミングにおいてとても大事。わからない場合でもこうするからこうなるって次に進んでいるといずれ悩んでたことが霧が晴れたようにわかったりするよ。
でも、「X=Y」がよくわからないわ。Yの中に1が入っているならその前にXに入っている0はどこにいったの?「01」とか「10」になるんじゃないの?
その考えも別の意味では正しい時もあるから覚えておいて。でも代入というのは、元々入っているモノを捨てて入れ替えるってことなんだ。
そうなんだ……こんな簡単なところでつまづいちゃってる私ってプログラミングの才能ないのかなぁ?
うーん、才能の有無はボクにもわからないけど、単純にこのルールを知らなかっただけだから気にしなくてもいいよ。変数に関しては嫌でも理解すると思うから一旦置いといて次にいくね。
うん、ゴメンね進行止めちゃって。
いやいや、ボクの方こそ説明が下手でごめんよ。
考え方は正解してたのになぁ。ま、俺も最初は変数の意味全く理解できなかったけど今では理解出来てるぜ!気にすんなって!
うぅ……リキに慰められるとなんかショック……
ヒデェな……
まぁまぁ……もうさっきの一度コードのおさらいをするね。追加した部分を1つずつ見ていこう。
変数を宣言して初期化する
' 変数XとYを用意
var X = 0
var Y = 0
もう一度変数の説明になるけど、「var」は変数を定義するという命令だよ。その後に変数の名前を書いてね。
そして「=」を使ってXとYそれぞれに「0」を入れて変数の初期化をするよ
ゲームループを作って毎回Xの値を+1していく
' ゲームループ
loop
' スプライト移動
SPOFS 0, X, Y
' 変数Xに1を足す
INC X
loopend
「loop」っていうのはプチコン4から追加された命令なんだ。それ以前のプチコンではちょっと特殊なやり方でやってたんだけどプチコン4になってとてもシンプルになったよ。
実はこのループを設定していないと上から下までプログラムを読んだらプログラムが完了したとみなされて動作が終了しちゃうんだ。ゲームは基本的に1つのループの中で色々動いているって思っていて。
そして中でやっている「SPOFS」はスプライトを動かす命令だったね。X座標に変数Xを。Y座標に変数Yを指定しているよ。最初のループではXもYも両方0だからプレイヤーは画面左上にいることになるんだ。
そして次が重要だよ。「INC」っていうのは何もしなければ指定した変数の数を1つ数を増やす命令なんだ。この場合「X」の中身が0で+1されるってことは「X」の中身は1ということになるよ。
これを延々と繰り返すんだ。画面上でどうなるか実際に見てみようか。
あれ、何も表示されないぞ?
あ、ゴメン。1つ忘れてた! ループの最後に「VSYNC」って入れてもっかい動かしてみて。
' 画面全消し
ACLS
' 変数XとYを用意【追加部分】
var X = 0
var Y = 0
' スプライト準備
SPSET 0, 352
' ゲームループ
loop
' スプライト移動
SPOFS 0, X, Y
' 変数Xに1を足す
INC X
VSYNC
loopend
わぁ!動いたよ!車動いた!
おぉ、なんかゆっくり動いているな!でもなんでさっき何も表示されなかったんだ?
ゲームって1秒間に60回画面が更新されるのが普通なんだけど、「VSYNC」を入れていないと制限が無くて性能があればあるほどものすごい速さで更新しちゃうんだ。
だから起動した瞬間に車のX座標がすっごい右に行っちゃてて見えなかったって感じかな。
なんかよくわからないけど、凄いから制御してあげなきゃだめってことね?
うん、早すぎたら人間が処理しきれないからそもそもゲームにならないでしょ?
た、確かに……格闘ゲームがこんな速さだったらヤ〇チャ視点だな。
VSYNCは垂直同期って言うんだけど、今は仕組みを知らなくても別に大丈夫かな。今のところゲームループの最後にVSYNCを入れておけばOKと思ってくれればいいよ。
斜め移動ってどうすればいいの?
リキよぉ、縦に動かすときはY座標をプラスしていけばいいんだよな?
うん、その通りだね。
斜めに移動したいときってどうするんだ?シューティングゲームで上下左右しか動けなかったら事故死しまくりそうなんだが……
それならXとYを同時に数値を更新すればいいよ。試しにやってみようか。
' 画面全消し
ACLS
' 変数XとYを用意【追加部分】
var X = 0
var Y = 0
' スプライト準備
SPSET 0, 352
' ゲームループ
loop
' スプライト移動
SPOFS 0, X, Y
' 変数Xに1を足す
INC X
' 変数Yに1を足す
INC Y
' ループを制御する者
VSYNC
loopend
斜めに動いた!でも不自然な斜め移動ね。
車だからそう感じるのかもね。もし自然に見せたい場合はスプライトを回転しなきゃいけないんだ。まぁゲームだから別にこのままでもいいんだけどね(笑)
画面外に行かないようにしたい
でもこのままだと画面外に行っちゃって見えなくなっちゃうわね。
ずっと数値を追加し続けているからね。
画面外に行きそうになったら止まれ!って伝えてあげなきゃいけないとか?
そう、正解。条件に一致したら何かをする。一致しなかったら何かをするという処理を加えてあげなきゃいけないんだ。次のコードを見てくれるかな。分かりやすいようにちょっとY座標の増加を消して100にしておくよ。
' 画面全消し
ACLS
' 変数XとYを用意【追加部分】
var X = 0
var Y = 100
' スプライト準備
SPSET 0, 352
' ゲームループ
loop
' 座標をチェックする
if X == 384 then
' Xが384という数値になったら動く
print "はしっこまでいったよ。"
else
' Xが384以外であればコチラが動く
' スプライト移動
SPOFS 0, X, Y
' 変数Xに1を足す
INC X
endif
' ループを制御する者
VSYNC
loopend
初めてのif文の登場だよ。これも変数と同じくプログラミングの基本中の基本になるからしっかり覚えてね。
ifって「もし」って意味よね? X == 384 の「==」ってなに?
プログラミングにおいて「==」こそが数学の「=」と同じ意味になるんだ。
なるほど!ってことはXの中身が384になったら「はしっこまでいったよ」ってこのPRINT……表示する?
そう、PRINTは画面に文字を表示してくれる命令なんだ。ゲームを作っている時に変数の中に何が入っているかとか調べることが出来るから覚えておいてね。
Xが384以外のときはいつも通り動き続けるってわけね。
そうだね。これを条件分岐っていうんだ。何かの時に何かをさせる。このif文がないとプログラミングできなくなるほど重要な基本構文だよ。それじゃあちゃんと画面の端っこに行って止まるかみてみようか。
わぁ!ちゃんと止まった!何これおもしろーい!
自分で作ったからなんで止まったか理解出来たでしょ?
うん!ってことはこれ、端っこまでいったら次はYをプラスして、一番下までいったら今度はXを減らして……ってやればずっとグルグル動き続けるんじゃない!?
流石マユミちゃんだね。今はPRINTで文字を出してるだけだけどそこを書き替えたら別の処理が出来るってわけさ。マユミちゃんの言った通りにずっと動かし続けてもいいし最初の地点に戻したりしてもいいね。
車を動かしているだけなのになんでこんな楽しく感じるんだろう?
確かにやっていることは至極単純なことだけど、自分で作ったものが動くってだけで感動するのはプログラマならだれでも通る道だよ。
後は自分の意思で動かせたらもうゲームだね!
何かが起ったら何かをするっていうのはもう覚えたから後はそこにコントロール命令を入れたら自分で動かせるようになるよ。
でも……今日はちょっと疲れちゃったな……トモくん、ス〇バいって甘いもの飲もうよ!
そうだね。今回は新しいこといっぱい覚えたから糖分補給して休憩しよう。
ホラ、リキも寝てないでいくわよ!今日から新作出てるんだから!
今回覚えたことの解説
- 変数
-
数値や文字列を入れておける箱。使う時は「var」を頭に入れて使いますよという宣言をしなければいけない。
-
変数は自由に名前を付けられるがプログラム言語で使っている名前「IFやVSYNC」は付けられないので注意しよう。
-
=を使って値を代入することができ、変数名を指定すると中身を指定したのと同じ意味になる。
- loop ~ loopend
-
動き続けるプログラムを作るときに必須。基本的にはこの中にプログラムを書いていくこととなる。
- if 条件式 then else endif
-
ifは条件分岐が出来るようになるプログラミングの基本構文の1つ
-
条件式は「==」や「>」「<」等の比較演算子というものを使って左右を比較する。
-
条件が一致した時に実行したい処理はthenの後に記述する
-
一致しないときはelseの後に処理を記述する
-
elseif 条件式 という形で別の条件を作ることが出来る。
-
endifはifの終わりを知らせる文。基本的にプログラミングは開いたら閉じるのルールを覚えておこう。
- INC
-
この命令の後に置いた変数の中身を1つ増やす。
-
変数が数値以外の場合はエラーになるので注意しよう。
-
変数の後にカンマで区切って数値を指定するとその指定した値が増加する。(INC X,2 の場合はXが+2される)
- VSYNC
-
垂直同期命令。1秒間にループする回数を制御してくれる。
-
何も数値を設定しないと1秒間に最大60ループするようにしてくれる(通称60FPS)
-
とりあえずゲームループの最後においておけば間違いない。それ以外触らなくてもOK
-
デバッグ用に画面に文字を表示させる命令
-
直接値を指定してもいいし変数を渡しても表示できる
-
今この変数に何が入っているのかなって調べるときに便利!
シューティングゲーム作り講座第2回まとめ
今回は主に変数と条件分岐(if)を使った制御が主な勉強になりましたね。
プログラミングにおいて変数と条件分岐は避けて通れない道なので今回でしっかりと覚えておきましょう。
変数と条件分岐をうまく使ってSPOFSを制御することに成功しました。
前回は直接値を指定してたのに対して今回は変数で数値を徐々に変更させて行ったり、
特定の値になったら動かさないようにしました。
マユミちゃんのようにプログラミングの独特な考え方に戸惑っている人がいたら
トモカズくんの言っているように分からない場合は一旦飛ばして次に進むということが大切になります。
分かっていなくても指定すればプログラムは動いてくれます。
もし間違っていてもプログラムが何を間違えているのか教えてくれるので、安心して次に進みましょう。
間違えることでそれを直して覚えていくのがプログラミング上達の近道です。
次回もSPOFSを使いつつ、新たにJoyConを使って自分で車を動かせるようにしてみましょう。
それでは。