第15章 状態を分けて小さな世界を保つ
タイトル画面、遊んでいる画面、終わった画面を一つの draw に足していくと、条件分岐が互いに影響し始めます。作品全体の状態を一つに決め、その状態に必要な処理だけを呼ぶと、今どこにいるかを追いやすくなります。
15.1 3 つの場面を一つの @scene で表す
def setup
createCanvas(600, 360)
@scene = :title
@x = 0
end
def draw
case @scene
when :title
draw_title
when :playing
update_playing
draw_playing
when :finished
draw_finished
end
end
def draw_title
background(30, 35, 55)
fill(255)
textAlign(CENTER, CENTER)
textSize(36)
text("SPACE ではじめる", width / 2, height / 2)
end
@scene は同時に一つの値だけを持ちます。タイトルと終了画面が同時に表示される矛盾を避けられます。
この段階では @scene が :title なので、draw から呼ばれるのは、いちばん下で定義した draw_title だけです。そのまま実行するとタイトル画面が表示されます。まだ SPACE キーは反応しませんが、エラーではありません。次の節から、残りの場面と動きを一つずつ足します。
15.2 場面ごとに描画を分ける
タイトル画面を描く draw_title は15.1で定義しました。次の 2 つのメソッドは変更部分です。15.1 の長いコードのあとへ続けて足します。
def draw_playing
background(245)
fill(235, 90, 120)
ellipse(@x, height / 2, 60, 60)
end
def draw_finished
background(235, 90, 120)
fill(255)
textAlign(CENTER, CENTER)
textSize(36)
text("もう一度 SPACE", width / 2, height / 2)
end
各メソッドは、自分の場面だけを描きます。色や文字を変えるとき、別の場面へ影響しにくくなります。
図 15-2 と図 15-3 は、15.3と15.4まで追加した完成後の画面を先に示しています。この15.2の段階ではまだ SPACE キーは反応しません。二つのメソッドを追加できたら、図を見て先の変化を予想し、15.3へ進みます。
15.3 更新と描画を分ける理由
次のメソッドも変更部分で、15.2 の 2 つのメソッドのあとへ足します。
def update_playing
@x += 4
@scene = :finished if @x > width + 30
end
update_playing は値を変え、draw_playing は現在値を画面へ描きます。この分離により、一時停止では更新だけ止め、同じ画面を描き続ける設計ができます。
必ず分けなければならない規則ではありません。小さなスケッチでは一つの draw が読みやすい場合があります。状態が増え、変更する処理と見せる処理を別々に考えたくなったときに分けます。
15.4 キーで遷移する
次のイベントメソッドも変更部分で、同じコードの末尾へ足します。
def keyPressed
return if key != " "
case @scene
when :title
@x = 0
@scene = :playing
when :finished
@x = 0
@scene = :playing
end
end
状態が変わることを遷移と呼びます。タイトルから実行中へ、実行中から終了へ移ります。終了から実行中へ戻るときは、@x も初期値へ戻します。
状態だけ変えて値を戻し忘れると、再開した瞬間にまた終了します。場面を切り替えるとき、その場面が必要とする値をどこで初期化するかまで考える必要があります。
15.5 デバッグ表示で状態と位置を確かめる
制作中だけ、現在の状態を左上へ表示できます。次の変更部分は draw の case が終わった直後、draw 最後の end より前へ足します。
fill(0, 160)
rect(6, 6, 210, 26)
fill(255)
textAlign(LEFT, TOP)
textSize(14)
text("scene: #{@scene} x: #{@x}", 10, 10)
見えない状態を文字へ変えると、「キーは反応したが位置を戻していない」といった違いを見つけやすくなります。完成時には、表示を消す方法と、調べる道具として残す方法のどちらも選べます。
15.6 三つの場面に違いを付ける
場面管理を使うと、同じ円を別の出来事として見せられます。まずタイトル場面の背景色だけを変えて実行し、実行中との切り替わりが見えるか確かめます。次に試すなら、終了場面の「もう一度 SPACE」を「夜が明けた」や「種が届いた」のような短い言葉へ変えます。
色と文字を同時に変える必要はありません。場面を一つ選び、変更前の版と見比べます。コードを追えなくなったときは、15.1 のタイトル画面の版へ戻せます。
第4部では、増えた値や処理をメソッド、配列、クラス、状態へ分けました。第5部では、その書き方を使って音、3D、ゲームを作ります。
参考資料
- Ruby リファレンスマニュアル「制御構造」 —
caseと条件分岐の構文 - rbCanvas/p5 0.5.1 API リファレンス — キー入力と文字描画の仕様