第5章 条件分岐が振る舞いを生む
第4章の円は、画面の外へ出ても進み続けました。端に着いたときだけ向きを変えるには、「もし端を越えたら」という条件が要ります。if は、値を見て次の行動を選ぶ仕組みです。
5.1 右端を越えたら左へ戻す
前章のコードへ 3 行を足します。
def setup
createCanvas(480, 240)
@x = 0
@speed = 3
end
def draw
background(245)
fill(235, 90, 120)
ellipse(@x, height / 2, 60, 60)
@x += @speed
if @x > width
@x = 0
end
end
@x > width は、円の中心がキャンバスの幅より右へ進んだかを比べています。条件が成り立つときだけ、@x = 0 が実行されます。
円は完全に見えなくなってから左へ戻ります。中心が右端へ着いた時点では、円の半分がまだ画面内にあるためです。この見え方が気になるなら、直前のコードの draw にある if 3行を、次の変更部分と置き換えます。
radius = 30
if @x - radius > width
@x = -radius
end
形の中心だけでなく大きさも考えると、画面の外へ出た瞬間をより正確に表せます。
5.2 戻る動きと跳ね返る動き
左へ戻す代わりに、直前のコードの draw にある if を次の変更部分と置き換え、速度の符号を反転します。
if @x > width - 30
@speed *= -1
end
右端で 3 は -3 になり、円は左へ進みます。しかし左端の条件がないため、そのまま消えます。今入れた if 3行を、次の変更部分と置き換えて両端を一つの条件にまとめます。
if @x > width - 30 || @x < 30
@speed *= -1
end
|| は「または」です。右端を越えた場合、または左端を越えた場合に速度を反転します。
5.3 条件だけでは端へめり込むことがある
速度を 25 のように大きくすると、円が端を越えてから反転し、少し不自然に揺れることがあります。1 フレームで境界を大きく飛び越えるためです。
直前の if 3行を次の変更部分と置き換え、境界で位置を戻してから速度を反転すると安定します。
if @x > width - 30
@x = width - 30
@speed *= -1
elsif @x < 30
@x = 30
@speed *= -1
end
elsif は、最初の条件が成り立たなかった場合に、別の条件を調べます。右端と左端を別々に処理できました。
条件分岐は「正しい答えを選ぶ」ものではありません。端を越えたとき、戻る、跳ねる、消える、色が変わるという作品の振る舞いを選ぶ場所です。
5.4 状態を色で見えるようにする
進む方向に応じて色を変えると、見えない速度の符号を観察できます。次の変更部分は、draw にある fill と ellipse の2行と置き換えます。
if @speed > 0
fill(235, 90, 120)
else
fill(50, 130, 230)
end
ellipse(@x, height / 2, 60, 60)
else は、それまでの条件がどれも成り立たなかった場合です。右向きなら赤、左向きなら青になります。
デバッグでは、内部の値を色や文字へ変えて表示すると原因を探しやすくなります。作品として残さなくても、見えない状態を一時的に見えるようにする考え方は今後も使います。
戻る動きと跳ね返る動きを同時に見る
二つの境界処理を同じ画面へ置くと、違いを見失いにくくなります。次はそれだけで実行できる完成コードです。上段の赤い円は右端を越えると左から現れ、下段の青い円は端で向きを変えます。
def setup
createCanvas(600, 260)
@wrap_x = 540
@bounce_x = 540
@bounce_speed = 4
end
def draw
background(245)
@wrap_x += 4
if @wrap_x > width + 30
@wrap_x = -30
end
@bounce_x += @bounce_speed
if @bounce_x > width - 30
@bounce_x = width - 30
@bounce_speed *= -1
elsif @bounce_x < 30
@bounce_x = 30
@bounce_speed *= -1
end
stroke(190)
line(0, 130, width, 130)
noStroke
fill(235, 90, 120)
ellipse(@wrap_x, 70, 60, 60)
fill(50, 130, 230)
ellipse(@bounce_x, 190, 60, 60)
end
どちらも同じ速さで右へ出発します。しかし、赤い円は位置を反対側へ移し、青い円は速度の正負を変えます。図では、赤い円が左へ戻ったあと、青い円が右端で跳ね返って左へ進んでいます。
5.5 自分で選ぶ境界の反応
次のうち一つだけ選び、円の端での反応を変えてみてください。難しさを三段階に分けています。
- そのままでできる: 跳ね返らず、反対側から現れる。5.2のコードを使える
- ヒントあり: 端に触れるたび速くする。跳ね返す
ifの中へ@speed *= 1.1を足す - 挑戦: 端に触れるたび色を変える。
setupで色の変数を用意し、端のifでrandomを入れ直す - 挑戦: 端でしばらく止める。止まる残り時間を覚える変数が必要になるため、今は動きの案だけメモして先へ進んでもよい
一度に全部を足す必要はありません。「そのままでできる」一つだけでも十分です。ヒントの意味がまだ分からなければ、数字を変える案へ戻ります。条件が一つ増えるだけで、単なる移動が「性格のある動き」へ変わります。次章では、形そのものを繰り返して画面を埋めます。
5.6 跳ね返るものに性格を付ける
端へ触れたときの反応は、作品の登場人物が何を感じたかのように見せられます。たとえば、跳ね返る瞬間だけ目を大きくすると、ただの円が驚く生き物になります。これは数フレーム分の状態を覚える必要がある挑戦課題です。今は絵として想像するだけでもかまいません。反対に、端で速度を半分にすると、壁を怖がっているように見えます。
最初は顔を描くコードを複雑にせず、円の中へ目を2つ足すだけで十分です。「速い性格」「慎重な性格」「端を無視して反対側へ抜ける性格」から一つ選び、条件式を振る舞いの演出に使ってください。
5.7 もっと自然な動きを探すなら
位置と速度に加えて、速度そのものを少しずつ変える値を持たせると、落下や加速のような動きになります。この値を加速度と呼びます。ほかにも、摩擦、重力、ばね、複数のものが集まって動く群れなど、動きから広がる題材があります。
今すぐ式を覚える必要はありません。まず「だんだん速くなる」「止まる前に少し滑る」「壁から離れるほど戻る力が強くなる」のどれかを言葉や矢印で描きます。その一文が、あとで「加速度」「摩擦」「ばね」「ベクトル」を調べる手掛かりになります。
この章の小さな区切り
- 円が端へ着いたかを
ifで調べられた - 折り返すか跳ね返るかを一つ試した
- 余裕があれば、速度か見た目で動きへ性格を付けた
端で一度反応するところまで確認できれば、保存して次章へ進めます。