【プチコン講座】関数!作らずにはいられないッ!
こんにちは。継続の錬金術士なおキーヌです。
ブログ毎日更新は130日目になります。
前回「【プチコン講座】プログラミングでRPGを作りたい!ゲームの土台つくり編」で、
ゲームループとマップチップを画面全体に表示することをしました。
プチコン講座第2回目はゲームを作っていくにはかかせない、SMILEBASICの関数を学びます。
2回目でいきなりRPGつくりから反れてしまう上にお勉強ちっくになるのですが、RPGを作るのには必ず必要になるのでここで覚えてしまいましょう!
では関数(かんすう)とは一体なんなのかというと、カンタンに言ってしまうとプログラム表です。
???となってしまった人に説明すると、今言ったプログラムとは学校などの運動会で配られる
競技をやる順番が書かれているプログラム表ですね。
プログラミングではこの予定を1つにまとめて予定表にすることが出来るのが関数という仕組みです。
プチコンの公式では高度関数という難しい部類にあてられていますが関数だけは最初に覚えておいた方が良いですね。
今回は関数がなぜ必要なのかと、簡単な関数の作り方の説明だけになります。
既にプチコンの関数の重要性と作り方を知っている人は読み飛ばして次に行ってOKです。
それではプチコンでRPG作り第二回目を始めましょう。
- プチコンでの関数の作り方
- マップチップを敷きつめる処理を関数化しよう!
- 見にくいコードは悪なので自分ルールで見やすくしよう
- 関数は1ヶ所にまとめるのが良い
- 作った自作関数をつかってみよう!
- 余談:関数の中で定義した変数はそこでしかつかえないローカル変数になる
プチコンでの関数の作り方
関数についてのお勉強は後にして、まずは関数を作ってみましょう。
プログラミングの上達のコツとしてはまず使ってみて、
わからなかったら調べてまた使ってみることを繰り返せばOKです。
失敗しても壊れることがないというのは最高ですね。
それでは関数の作り方を説明します。
「DEF」という命令を使います。
DEFはDefineの略、つまり定義という意味です。
DEF~ENDまでが定義の範囲になります。
それでは早速マップチップを敷きつめるコードを関数化してみましょう!
マップチップを敷きつめる処理を関数化しよう!
DEF D_MAP_DRAW
IF NOT STOP_FLAG THEN
FOR Y=0 TO 14
FOR X=0 TO 24
BGPUT 0,X,Y,105
NEXT
NEXT
ENDIF
END
前回作ったマップチップを描写する処理を「DEF」と「END」でサンドイッチしてあげるだけです。
とても簡単ですね!
DEFの後ろに「D_MAP_DRAW」という文字列があります。
これは変数と同じように関数の名前は自分で好きなように名前を付けられます。
名前の「D_MAP_DRAW」はわかりやすいようにしているだけです。
この名前を見たらマップ……ドロー……つまりマップを描写してるんだな!って関数の名前で1発で何をしているのか大体わかります。
これ、実はとても大事!
テキトーに変な名前を付けたら後から何をしているのかわかりませんし、
もし他人に見せるときに何をしているのかわかり辛いです。
関数の名前を付けるときは、出来る限りパッと見でわかりやすい名前にすることを心がけましょう。
見にくいコードは悪なので自分ルールで見やすくしよう
もう1つ言うとBASICの関数って全部大文字なのもあって、
初見の私も関数ってわかり辛いなと感じたのでBASICでは関数の名前の頭に「D_」を付ける自分ルールをつくりました!
DEF_MAP_DRAWやFUNC_MAP_DRAWとかでもよかったのですが名前が長くなりすぎるのも嫌ですし、
「D_」となっているものは関数というルールを自分の中で作っておけば全部大文字で見辛いBASICのコードも多少は見やすくなるのではないでしょうか?
お仕事でチームを組んでプログラミングする時はコード規約(プログラムを組むための決まり事)というのが、
大体どこの会社でも存在していると思います。
私は仕事でもチーム開発をすることがないので自分ルールを自由に作れますがチームだとそうもいかないので
自分ルールというのはあまりよろしくないやり方かもしれません。
ただ、プチコンって基本一人でプログラミングする前提だと思うので私は良いと思います。
関数は1ヶ所にまとめるのが良い
関数の定義はどこの場所に書いても大丈夫ですが、できれば1カ所にまとめておきましょう。
本来は外部ファイルとして1つにまとめるのですが、外部ファイルを読み込むという手続きが必要になるので
一旦メインのファイルにコードを1つにまとめていきます。
ソースコードが多くなってきたら関数は別のファイルにまとめて、メインのプログラムをスッキリさせましょう!
果たしてsmileBASICで関数を外部ファイル化して読み込んでメインのファイルで使うことはできるのか……?
いや、出来ると信じて進みましょう。ダメだったらその時考えればいいだけです。
プログラミングは考えるよりもコードを書く方が大事です。
コードを書くことで見えてくることもあるのでまずは考える前に書きましょう。
考えるのは壁にぶつかってからでも遅くはありません!
作った自作関数をつかってみよう!
関数は定義しただけでは動きません。
道具を用意しても使わなければ意味がありませんね。
それでは自分で作った関数をどうやって使うかを見てみましょう。
前回のコードを少し修正と追記をしました。
ACLS
G_STOP_FLAG = FALSE
G_MAP_DRAW_FLAG = TRUE
WHILE G_MAP_DRAW_FLAG
D_MAPCHIP_DRAW
G_STOP_FLAG = TRUE
WEND
DEF D_MAP_DRAW
IF NOT STOP_FLAG THEN
FOR Y = 0 TO 14
FOR X = 0 TO 24
BGPUT 0,X,Y,105
NEXT
NEXT
ENDIF
END
ここでGOTOが無くなっていることに気付いた人はすごいです。
なぜGOTOをなくしてWHILEにしたかは、次回の記事で詳しくお話します。
もう1つ、変数に「G_」が付いていることに気付いたでしょうか?
これも関数と同じでわかりやすくするためです。
GとはGlobalVariableの頭文字、つまりグローバル変数ということです。
グローバル変数とはどこからでもアクセスできる変数です。
GOTOと同じで出来る限り使いたくないタイプの変数ですが、ポインタの話になると説明し辛いので
どこからでもアクセスしたい変数は一旦グローバル変数にしておきます。
このようにちゃんと「G_」を付けておけば一発でグローバル変数だということがわかるので
「この変数なんだったかな……」というのはなくなりますね。
ローカル変数の場合は「L_」を付けたほうがいいかもしれませんが、あえてつけない方がいいかもしれませんね。
プログラムが入れ子になりすぎると、どこのローカル変数だよってなってしまうからです。
余談:関数の中で定義した変数はそこでしかつかえないローカル変数になる
関数から変数の話になってしまいましたが、ローカル変数はゲームプログラミングをするうえでもかなり重要になります。
例えば「HOGE=0」という変数を関数の外で定義したとします。
次に「PIYO」という関数を作ったとして、その関数の中に変数「VAR HOGE=1」を作ります。
変数HOGEを表示した場合、0と1のどちらが表示されるでしょうか?
後から定義したんだから1?いやいや、最初に定義してるんだからエラーがでるでしょ。
色んな考えが出てくると思います。
頭の良い人ならもう察しがついていると思いますが、一度コード化してみましょう!
HOGE = 0
DEF PIYO
VAR HOGE = 1
PRINT HOGE
END
PRINT HOGE // (1
PIYO // (2
PRINT HOGE // (3
上から見ていきましょう。
まずHOGE=0でHOGEに0を代入しました。
次にPIYO関数を定義し、その中にVARを付けてHOGE=1を定義してPRINT HOGEをしています。
そしてPRINT HOGEの後にPIYOを呼び出しています。
さてどのように表示されるでしょうか?実行してみましょう!
答えは……
0
1
0
と出たと思います。
関数の外で定義した変数と、関数の中で定義した変数は同じ名前であっても完全に別物です。
ちなみに関数の中でVARを書かないと関数の外の変数にアクセスすることになります。
試しに関数の中にあるVARを消して実行してみてください。
0
1
1
となったはずです。
もう1つ言っておくと、グローバル変数もちゃんとVARを付けておいた方がいいでしょう。
もし今書いているところより前に既に定義されていたら、その変数に代入するということになります。
二回同じ名前のVARをやってみるとエラーが出るので、出来る限り変数を定義するときはVARを付けましょう!
──今回はプチコンの講座というよりも完全にプログラミング初歩の講座みたいになりましたね。
しかしゲームプログラミングするうえで関数の作り方を知っておかないと、
9割は頓挫してしまいますのでここで基本をしっかりとおぼえておきましょう!
ここで覚えておくと後にプログラマになったときにも役立ちますし
今後発売されるプチコン4でもそのまま使えるので損することはありません。
毎回コードを書いていては頭が疲れてしまうので、次回はコードを書かずにプチコンを学びましょう。
もちろん、RPGだけでなくプログラムを作る上でもかなり大事なことを書きます。
最後に今回の完成版ソースコードを載せておきます。
それでは
ACLS
VAR G_STOP_FLAG = FALSE
VAR G_MAP_DRAW_FLAG = TRUE
WHILE G_MAP_DRAW_FLAG
D_MAPCHIP_DRAW
G_STOP_FLAG = TRUE
WEND
DEF D_MAP_DRAW
IF NOT STOP_FLAG THEN
FOR Y = 0 TO 14
FOR X = 0 TO 24
BGPUT 0,X,Y,105
NEXT
NEXT
ENDIF
END