Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第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

各メソッドは、自分の場面だけを描きます。色や文字を変えるとき、別の場面へ影響しにくくなります。

濃紺の 600×360 のキャンバス中央に、白い文字で「SPACE ではじめる」と表示されたタイトル画面
図 15-1 title 状態では開始案内だけを描く。

図 15-2 と図 15-3 は、15.3と15.4まで追加した完成後の画面を先に示しています。この15.2の段階ではまだ SPACE キーは反応しません。二つのメソッドを追加できたら、図を見て先の変化を予想し、15.3へ進みます。

薄い灰色の 600×360 のキャンバスで赤い円が左から右へ進んでいる実行中の画面
図 15-2 SPACE キーを押したあとの playing 状態では、位置を更新して円を描く。
赤い 600×360 のキャンバス中央に白い文字で「もう一度 SPACE」と表示された終了画面
図 15-3 円が画面外へ出ると finished 状態へ移り、終了案内を描く。

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、ゲームを作ります。

参考資料