41:描画処理を作ろう

◆PROCESSINGで始めるゲーム作りとコンピュータ

Monster_1 41:描画処理を作ろう

今日の話題

 

21:描画処理の大枠を作成する

前回はSPD(冒険の地図)に従ってゲームの初期化処理を作成しました。

今回は初期化処理に続いて、ゲームの中心的な流れである描画処理を作成していきたいと思います。

ヨウコ
いろいろな変数を初期化する処理が出来たから、次は描画処理を作りましょう。

ユカ
描画処理って、画面に色々なものを表示する処理ですよね?。

ヨウコ
そうよ。

ヨウコ
前回作成した初期化処理では、駒配列やゲームの中で使う変数を用意したでしょ?。描画処理では、それらを画面に表示するのよ。


ヨウコ
画面を表示する処理は「gameDisp 関数」ね。そこを詳しく書いたフローは以下の通りよ。


ユカ
画面を表示する処理は、「①駒の数を表示する」処理と「②駒を表示する」処理から出来ているんですね。

ヨウコ
そうね。

ヨウコ
36:背景画像を表示しよう」の回で、ゲームのベースとなる背景画像をdraw関数で表示したと思うけど、少し復習しておきましょうか。

ケンジ
えっと・・・、確かこんな処理だったと思うんですけど?。


ユカ
あら、ケンジが覚えているなんて珍しいわね。

ケンジ
よけいなお世話だい。

ヨウコ
このdraw関数の中に、必要な処理を追加していくのよ。

ヨウコ
まずはゲーム画面を表示する処理をgameDispという名前で作成して、呼び出してみてくれるかしら?。

ユカ
ねぇ、ヨウコ先生。関数にする目的は、同じ処理をひとまとめにしておく事でしたよね?。

ヨウコ
そうよ 。

ユカ
ゲーム画面を表示する処理は、ここでしか登場しないと思うんですけど、それでも関数にする必要があるんですか?。

ヨウコ
あら、いい質問ね。

ヨウコ
処理を関数にまとめる目的は、共通で使う処理を1つにしておくという事だけじゃないのよ。

ケンジ
?。

ヨウコ
たとえば、次のようなオモチャの散乱した部屋があったとして・・・

(画像URL:illust-AC 様:reiさん、カタテマデザイン室 さん)

ユカ
うわ、まるでケンジの部屋みたい。

ケンジ
・・・。

ヨウコ
この中から、女の子の人形で遊びたいと思った時、直ぐに探し出すことができるかしら?。

ケンジ
ウォーリーを探せ状態ですね・・・。えーと・・・真ん中の下にある人形がそうかな?。

ヨウコ
それじゃぁこの部屋が、次のように整理されていうたとしたらどうかしら?。

(画像URL:illust-AC 様:reiさん、カタテマデザイン室 さん)

ケンジ
これなら直ぐに見つけられるね。

ユカ
そうか。関数化する目的は「共通化」の為だけじゃなくて、「処理を解りやすくする」為でもあるんですね!。

ヨウコ
その通りよ。

ヨウコ
処理が沢山詰め込まれた関数は、散らかった部屋みたいなものよ。見通しが悪くなって、何をしているのか、わかりにくくなってしまうの。

ケンジ
なるほど。じゃぁ、こんな感じかな?。

ヨウコ
いいわよ。同じように、フローを見ながら以下のような関数を呼び出す部分を追加してくれるかしら。

ヨウコ
駒の数を表示する関数と、駒を表示する関数は、gameDisp関数から呼び出すところは注意してね。

ケンジ
わかりました。

ヨウコ
OKかな?。・・・あら、ちょっと惜しい所があるわね。

ケンジ
え?。

ユカ
あ、わかった!。ケンジのプログラムには、GAMEOVERか判定する処理がないんだ。

ユカ
ほら、draw関数の中に、ゲームオーバーか判定する処理が無いでしょ?。

ケンジ
それはそうだけど・・・。ゲームオーバーになったかどうかは、どうやって調べるんだろう?。

ヨウコ
前回、ゲーム内で使ういろいろな変数を作成したのを覚えているかしら?。

ケンジ
これの事ですよね?。

ヨウコ
そうよ。

ヨウコ
今回のリバーシゲームでは、全ての駒を打ち終えたらゲーム終了(ゲームオーバー)になるわよね?。

ケンジ
うん。

ヨウコ
じゃあ、この変数の中でゲームオーバーの判定に使えそうなものは無いかしら?。

ケンジ
駒の状態は駒配列で管理しているから、駒の無い空の配列があるか調べるのかな?。

ユカ
それでも良さそうだけど、白の駒数と黒の駒数を変数で管理しているから、その2つを足せば、打ち終わった駒の数がわかるんじゃない?。

ケンジ
そうだね。駒を打つ場所(マス目)の数は64個あるから、白駒数と黒駒数の合計が64個になったらゲームオーバーなんだ!。

ヨウコ
大正解。それをプログラムで書くと、どうなるかしら?

ユカ
プログラムで、なにかを判定するには if 文を使うんでしたよね?。


ケンジ
という事は、こんな風にすればいいのかな?。

ヨウコ
その通りよ。あとは、ゲームオーバーになった時、ゲーム状態変数を[ゲーム中]から[ゲームオーバー]に変える処理も忘れちゃだめね。

ケンジ
よし。じゃぁゲーム状態変数の変更処理を加えておこう。

ヨウコ
これで、描画処理の大枠ができたわね。

.
プログラムを作成する時は、この話の中に登場した「散らかった部屋」にならないように気をつけてくださいね。

特に初心者の方は、1つの関数にズラズラといろいろな処理を詰め込んで、何百行もあるような処理を作ることが良くあります。

再利用する部分ではなくても、処理ごとに関数としてまとめて、全体として見通しが良いプログラムを作るようにしましょう。

 

22:改行しながら文字を表示する

ヨウコ
次は、1つ1つの関数の中身を作成していきましょう。まずは「駒の数を表示する処理」ね。


ヨウコ
駒の数を表示する piecesCountDisp関数のSPDは、上記のような感じよ。

ケンジ
白駒数と黒駒数を覚えておく変数を0にしてから、駒配列の値をループ命令で調べるんですね。

ヨウコ
そうよ。ループ命令は for 文。条件判定は if 文ね。どちらも今まで登場した命令だから難しいことはない筈よ。

ヨウコ
駒数を表示する処理は、とりあえずtextDispという名前の関数を呼び出してね。

ケンジ
文字の色を変更するのは、どうするんでしたっけ?。

ヨウコ
文字の色は fill 命令で変更するのよ。「31:文字を表示する(実践編)」の授業で説明したと思うけど。

ユカ
もう!、ケンジは物忘れだけは得意ね。fill 命令の使い方はこうよ。

ケンジ
了解。じゃ、こんな処理でいいかな?


ケンジ
でも textDisp() の所が、よくわからないなぁ。

ヨウコ
白駒数と黒駒数を表示するところは、これから説明するから大丈夫よ。

ヨウコ
今回のゲームでは、駒の数は画面右側に下図のように表示しているの。

ユカ
黒駒数は(800,235)の位置から、白駒数は(800,320)の位置から、それぞれ表示しているんですね。

ヨウコ
ところで2人は、文字を好きな位置から表示する命令は覚えているかしら?。

ユカ
はい。text 命令ですよね。「37:文字ファイルを読み込もう」の回でやりました。

ヨウコ
そうね。

ヨウコ
それじゃあ、まずは単純に textDisp関数でtext命令を使って文字を書いてみましょうか。

ヨウコ
textDisp関数は文字を表示したい箇所で共通的に使うから、表示する文字と座標は呼び出し元から与える事にしましょう。


ユカ
piecesCountDisp関数から、表示したい文字列(String)とXYの座標(int)を、textDisp関数に渡すんですね。


ケンジ
こんなんで良いのかな?。

ヨウコ
いいわよ。じゃ、実行してみてちょうだい。


ケンジ
あれ?・・・。文字が右側にハミ出しているや。

ヨウコ
text命令は文字列を単純に書き出す命令なの。

ヨウコ
だから文字列が画面の右端を超えても、何も処理はしてはくれないのよ。

ケンジ
ちぇ、気がきかないなぁ。

ヨウコ
(笑)。文字列が画面をはみ出しそうになった時、「どうしたいのか」はプログラマーが指定してあげないといけないのよ。

ヨウコ
今回はtextDisp関数の中で、1行に表示可能なMAX文字数を超えた時に、改行する処理を入れてみましょう。

ケンジ
改行処理って難しそうだな・・・。

ヨウコ
落ち着いて順番に考えれば、大丈夫よ。

ヨウコ
改行処理を図にすると、下のようになるわ。

ユカ
XとYはpiecesCountDisp関数から渡された、文字を表示したい開始座標ね。

ケンジ
文字が右に行くほど、横座標のXは文字の幅分だけ増えていくんだね。

ユカ
文字が下に表示される時は、縦座標のYが文字の高さ分だけ増えるのね。

ケンジ
という事は、1行に表示したいMAX文字数になるまではXを増やしながら文字を横に表示して

ケンジ
MAX文字数になったら、今度はYを文字の高さ分だけ増やせばいいんだ!。


ヨウコ
その通りよ。

ヨウコ
そのためには、文字列の文字数を知る命令と、文字列から1文字づつ文字を取り出す命令が必要ね。

ヨウコ
PROCESSINGには文字数を知る length 命令と、文字列から文字を取り出す substring 命令があるわよ。

ヨウコ
substring 命令の使い方はこうね。


ヨウコ
この2つの命令をループ処理の中で使いながら、1文字づつ表示していけばいいの。

ヨウコ
改行処理を組み込んだ textDisp関数のSPDを示すから、プログラムしてみてね。


ケンジ
えっと・・・まずは引数のXとYをDXとDYという変数に覚えておくんだよね。

ユカ
1行に何文字表示したか数える変数はDCね。これも用意して初期化しておきましょう。


ケンジ
次はループ処理か。for文を使うとして、条件が「全ての文字を処理するまで」になっているけど?。

ユカ
文字列の長さは length でわかるから、ループ変数 i が length 以下の時だけ回ればいいんじゃない?。


ケンジ
そうだね。ループの中で文字列の先頭から、1文字づつ取り出して表示すればいいんだ。

ユカ
取り出した文字は、DX、DYの位置に表示して、DXを文字幅だけ加算すればいいのね。

ヨウコ
今回の文字には等倍のものを採用しているから、文字幅も文字の高さも、共にFONT_SIZE(32)になるわよ。この定数は以前定義したわよね。

ケンジ
じゃ、こんな感じだな。


ユカ
あとは、DCがMAX文字数になったら、DYを増やして、DXを元の座標(X)に戻すのね。


ヨウコ
MAXの文字数は 8 と固定で書かないで、呼び出し元からの引数にした方がいいわよ。必ず8文字で改行するとは限らないから。

ケンジ
わかりました。


ユカ
そして、この textDisp関数を呼び出す部分は、こうね。


ヨウコ
2人とも、よく出来たわ。試しに「あいうえおかきくけこ」という10文字の文字列を表示してみましょうか。


ケンジ
やりー。

.
いかがでしたか?。改行処理というと難しく思えますが、仕組みは案外単純なんです。

ここで登場したシンプルな改行処理であれば、理屈さえわかれば初心者の方でも十分理解できると思います。

 

23:GameOverの表示を作る

ヨウコ
次は、ゲームオーバーになった時の表示を作成しましょう。

ユカ
draw関数から呼んでいるdispGameOver関数ですね?。


ヨウコ
そうよ。ゲームオーバーの時は画面右下に、以下のようなメッセージを表示するの。


ヨウコ
次の図はdispGameOver関数のSPDだけど、先程作った textDisp関数を使う事で簡単にプログラミングできる筈だから、がんばってね!。


ケンジ
文字の色は薄い青色って・・・えーと、どうするんだっけ?。

ヨウコ
ヒントをあげるわ。青は color命令で color( 0, 0, 255 ) と書くわよ。

ケンジ
じゃあ、薄い青だからRとGの成分が少し混ざっている感じで、 color( 50, 50, 255 ) くらいかな?。


ヨウコ
いいと思うわよ。最後は手番を表示するturnDisp関数ね。

ヨウコ
緑で網掛けしてある checkAllPutOk 関数は、とりあえず空っぽの処理でいいわよ。

ユカ
打ち先があるか調べる処理って、どういう事なんですか?。打ち先がなくなったら、全部のマス目が埋まったって事で、ゲームオーバーのような気がするんですけど。

ヨウコ
リバーシでは全部のマス目が埋まっていなくても、手番の色が置けない事があるからよ。

ケンジ
?。

ヨウコ
例えば今は黒の手番だとして、盤面が次のようになっていたといしたらどうかしら?。


ケンジ
こ、これは・・・黒を置く場所がないや!。

ヨウコ
checkAllPutOk 関数では、このような手詰まり状態を状態をチェックするの。

ユカ
チェックした結果、もしも手詰まりだったら、その色の手番をパス(黒の手番なら白に、白の手番なら黒に)するんですね。

ヨウコ
そうよ。でもこの処理は、後で作成するから今は「手詰まりじゃない=true」を返すだけの空の関数を用意しておいてね。

ケンジ
わかりました。


 

.
さて、これで描画処理の大部分が出来上がりました。のこりは、最も肝心な「ゲームボード上に駒を表示する」処理ですね。

この部分は、次の回に解説したいと思います。

ケンジくんとユカさんが、ここまでに作成したプログラムを、下記からダウンロードできるようにしておきました。処理の全体像が見たい方は、参考としてみてください。

リバーシゲーム(第41回分)

リソースファイルの再配布は禁止されています。ご注意願います。これは学習途中のプログラムであるため、ゲームとして遊ぶことはできません。

なお上記のプログラムは作成途中のものになりますので、完成版は「34:さぁ、ゲームを作ろう!」から入手してください。

※上記会話に登場する素敵な人物画像は、次のサイト様の画像を利用させて頂いております。ありがとうございます。

画像URL:とりのすみか

 

Forest今日の言葉

・なし

 

scroll今日の文法

・length文

文字列の文字数を取得します。

文字数を数える命令です。msg1なら8、msg2なら13が戻されます。

 

・substring文

文字列の一部を取り出します。

文字列から、指定した範囲の部分文字列を取り出します。
上記例では、3文字目から4文字取り出すので、以下のようになります。

 今日のまとめ

  • 関数は共通化以外にも、「見やすくする」目的で使う
  • text命令だけでは改行してくれない
  • 文字の色は fill 命令で変更できる

40:ゲームの初期化をしよう に戻る
目次へ戻る


本ページで利用している特に参照元記載のないアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。