キャラクターの状態遷移
キャラクターは「状態(State)」と「サーフェス(Surface)」の組み合わせで動作します。状態はキャラクターが何をしているか(歩く・休む・登るなど),サーフェスはキャラクターが乗っている面(床・ウィンドウ天面・壁・コーナー)を表します。
各ティックで現在の状態と状況に応じて次の状態への遷移を判定します。サーフェスが消失(ウィンドウを閉じるなど)すると状態に関わらず Falling に遷移し,新たなサーフェスに着地すると LandingStandUp に遷移します。
サーフェスの種類
| サーフェス | 説明 |
|---|---|
| Desktop | デスクトップの床 |
| WindowTop | ウィンドウの上端(天面) |
| WindowWall | ウィンドウの側壁 |
| WindowUpperCorner | ウィンドウ上部のコーナー(天面と側壁の接合部) |
| Airborne | 空中(サーフェスなし,Falling 状態で使用) |
サーフェス間の遷移概略
床・ウィンドウ天面の状態
サーフェスが Desktop または WindowTop のとき使われる状態です。
Falling
スプライト: s-jump / f-shocked(shocked > 0 の間は f-shocked)
空中にある状態。速度ベクトル (vx, vy) を持ち,エンジンが重力(jump.gravity)を含む物理演算を行います。next_state からは遷移せず,on_landed イベントで着地した瞬間に次の状態へ切り替わります。
shocked はエッジから驚いて落ちた時間(秒)で,floor.shocked_duration で初期値が設定されます。この間は f-shocked スプライトを表示します。on_surface_lost(住処ウィンドウが閉じられた場合)でも同様に shocked_duration が設定されます。
| 遷移先 | 条件 |
|---|---|
LandingStandUp | サーフェスへの着地(on_landed) |
LandingStandUp
スプライト: s-stand-up
着地直後の立ち上がりポーズです。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
Observing | floor.standup_duration 秒経過 | floor.standup_duration |
Observing
スプライト: s-stand
着地後の観察フェーズです。floor.observe_duration の範囲でランダムに決定した時間が経過すると次の行動へ移ります。
Desktop サーフェスで jump.climb_attract_dist 以内に対象ウィンドウがある場合,jump.climb_attract_prob の確率でウィンドウ方向に歩き始めます。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
Walking(窓方向) | Desktop かつウィンドウが jump.climb_attract_dist 以内かつ確率 jump.climb_attract_prob | jump.climb_attract_dist, jump.climb_attract_prob |
PeekDown | 上記不発,確率 floor.peek_prob | floor.peek_prob |
Walking(コーナー方向) | 上記以外 | — |
duration 範囲: floor.observe_duration
PeekDown
スプライト: s-peek-down
エッジから下を覗き込むポーズです。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
Walking(同方向) | floor.peek_duration 秒経過,確率 floor.peek_walk_prob | floor.peek_duration, floor.peek_walk_prob |
TurningAround | floor.peek_duration 秒経過,確率 1 − floor.peek_walk_prob | floor.peek_walk_prob |
Walking
スプライト: s-walk-0 / s-walk-1 / s-walk-2(ピンポンフレーム,4 フレームサイクル)
floor.walk_speed px/s で移動します。floor.walk_frame_secs ごとにフレームを進めます。
Desktop 上で jump.wall_jump_max_dist 以内に対象ウィンドウがあり画面端でない場合,即座に JumpRunup に遷移します。エッジに到達した場合の遷移先はサーフェス種別で異なります。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
JumpRunup | Desktop かつウィンドウが wall_jump_max_dist 以内(歩行中随時) | jump.wall_jump_max_dist |
TurningAround | Desktop エッジ到達,ウィンドウなし | — |
JumpRunup | Desktop エッジ到達,ウィンドウあり | jump.wall_jump_max_dist |
| StandIdle / SitIdle / LieIdle / Sleeping のいずれか | WindowTop エッジ到達,確率 floor.edge_idle_prob(内訳は floor.edge_arrive_*_prob) | floor.edge_idle_prob, floor.edge_arrive_stand_prob 等 |
Falling(shocked > 0) | WindowTop エッジ到達,非アイドル分局内,確率 floor.edge_fall_prob | floor.edge_fall_prob, floor.shocked_duration |
CornerTransitionSide | WindowTop エッジ到達,非アイドル分局内,確率 1 − floor.edge_fall_prob | floor.edge_fall_prob |
TurningAround
スプライト: s-stand-close → f-stand → s-stand-close(3 フェーズ)
floor.turn_duration 秒かけて振り向くアニメーションを再生します。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
Walking(新方向) | floor.turn_duration 秒経過,確率 floor.turn_walk_prob | floor.turn_duration, floor.turn_walk_prob |
StandIdle | floor.turn_duration 秒経過,確率 1 − floor.turn_walk_prob | floor.turn_walk_prob |
StandIdle
スプライト: s-stand(bob_phase=false) / s-stand-close(bob_phase=true)
立ちアイドルです。floor.headbob_period 秒ごとに口を開き(s-stand-close),floor.headbob_open_duration 秒後に閉じる(s-stand)ヘッドボブを繰り返します。floor.stand_duration が経過すると次へ移行します。
WindowTop のエッジにいる場合は,アイドル連鎖(エッジ休憩)に入るかコーナーを回って壁へ移動します。Desktop サーフェスで近くにウィンドウがある場合,jump.climb_attract_prob の確率で引き寄せられます。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
JumpRunup | 非 Desktop かつ近くにウィンドウありかつ corner.outing_interval 経過(強制お出かけ) | corner.outing_interval |
SitIdle | WindowTop エッジ,確率 floor.edge_stand_to_sit_prob | floor.edge_stand_to_sit_prob |
CornerTransitionSide | WindowTop エッジ,確率 1 − edge_stand_to_sit_prob | floor.edge_stand_to_sit_prob |
Walking(窓方向) | Desktop かつウィンドウが近く,確率 jump.climb_attract_prob | jump.climb_attract_prob |
SitIdle | 上記以外,r < floor.stand_idle_sit_prob | floor.stand_idle_sit_prob |
Walking | 上記以外,floor.stand_idle_sit_prob ≤ r < floor.stand_idle_walk_prob | floor.stand_idle_walk_prob |
TurningAround | 上記以外,floor.stand_idle_walk_prob ≤ r < floor.stand_idle_turn_prob | floor.stand_idle_turn_prob |
PeekDown | 上記以外,r ≥ floor.stand_idle_turn_prob | floor.stand_idle_turn_prob |
duration 範囲: floor.stand_duration,ヘッドボブ閉じ間隔: floor.headbob_period,開き時間: floor.headbob_open_duration
SitIdle
スプライト: s-sit(横向き) / f-sit(正面向き,head_front=true)
座りアイドルです。floor.head_side_duration 経過後に f-sit(正面向き)に切り替わり,floor.head_front_duration 経過後に s-sit(横向き)に戻ります。floor.sit_duration が経過すると次へ移行します。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
JumpRunup | 非 Desktop かつ近くにウィンドウありかつ corner.outing_interval 経過(強制お出かけ) | corner.outing_interval |
LieIdle | WindowTop エッジ,確率 floor.edge_sit_to_lie_prob | floor.edge_sit_to_lie_prob |
StandIdle | WindowTop エッジ,確率 1 − edge_sit_to_lie_prob | floor.edge_sit_to_lie_prob |
Walking(窓方向) | Desktop かつウィンドウが近く,確率 jump.climb_attract_prob | jump.climb_attract_prob |
LieIdle | 上記以外,r < floor.sit_idle_lie_prob | floor.sit_idle_lie_prob |
StandIdle | 上記以外,floor.sit_idle_lie_prob ≤ r < floor.sit_idle_stand_prob | floor.sit_idle_stand_prob |
Walking | 上記以外,r ≥ floor.sit_idle_stand_prob | floor.sit_idle_stand_prob |
duration 範囲: floor.sit_duration,頭の向き切り替え: floor.head_side_duration / floor.head_front_duration
LieIdle
スプライト: s-lie(横向き) / f-lie(正面向き,head_front=true)
伏せアイドルです。頭の向き切り替えは SitIdle と同じ仕組みです。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
JumpRunup | 非 Desktop かつ近くにウィンドウありかつ corner.outing_interval 経過(強制お出かけ) | corner.outing_interval |
Sleeping | WindowTop エッジ,確率 floor.edge_lie_to_sleep_prob | floor.edge_lie_to_sleep_prob |
SitIdle | WindowTop エッジ,確率 1 − edge_lie_to_sleep_prob | floor.edge_lie_to_sleep_prob |
Walking(窓方向) | Desktop かつウィンドウが近く,確率 jump.climb_attract_prob | jump.climb_attract_prob |
Sleeping | 上記以外,r < floor.lie_idle_sleep_prob | floor.lie_idle_sleep_prob |
SitIdle | 上記以外,floor.lie_idle_sleep_prob ≤ r < floor.lie_idle_sit_prob | floor.lie_idle_sit_prob |
Walking | 上記以外,r ≥ floor.lie_idle_sit_prob | floor.lie_idle_sit_prob |
duration 範囲: floor.lie_duration,頭の向き切り替え: floor.head_side_duration / floor.head_front_duration
Sleeping
スプライト: s-lie-sleep(横向き) / f-lie-sleep(正面向き)
睡眠中です。頭の向き切り替えは SitIdle / LieIdle と同じ仕組みで続きます。duration が経過すると常に LieIdle に戻ります。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
JumpRunup | 非 Desktop かつ近くにウィンドウありかつ corner.outing_interval 経過(強制お出かけ) | corner.outing_interval |
LieIdle | floor.sleep_duration 経過 | floor.sleep_duration |
duration 範囲: floor.sleep_duration,頭の向き切り替え: floor.head_side_duration / floor.head_front_duration
アイドル状態チェーン
StandIdle / SitIdle / LieIdle / Sleeping は互いに遷移し合い,緩やかな休憩チェーンを形成します。下図の前進方向(右向き矢印)は一般的な傾向を示し,実際の遷移は確率で決まります(Walking への復帰など逆行も起こります)。
ジャンプの状態
Desktop でウィンドウ壁に飛びつくときに使われます。
JumpRunup
スプライト: s-stand-up
壁へジャンプする前のダッシュポーズです。jump.runup_duration 秒保持後,ウィンドウ壁への吸着が完了して WallEntry に遷移します(位置の更新はエンジンが行います)。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
WallEntry | jump.runup_duration 秒経過 | jump.runup_duration |
ウィンドウ壁の状態
サーフェスが WindowWall のとき使われます。
WallEntry
スプライト: s-hang-wall-0
壁への取り付き直後の保持ポーズです。wall.entry_hold 秒間静止してから登り始めます。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
ClimbingUp | wall.entry_hold 秒経過 | wall.entry_hold |
ClimbingUp
スプライト: s-hang-wall-0 / s-hang-wall-1 / s-hang-wall-2(ピンポンフレーム)
wall.climb_speed px/s で上昇します。wall.climb_frame_secs ごとにフレームを進め,3 フレームごとに wall.pause_prob の確率で一時停止します。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
CornerTransitionSide | 壁の上端に到達(at_edge=true) | — |
WallPause(was_climbing_up=true) | 3 フレームごとに確率 wall.pause_prob | wall.pause_prob |
ClimbingDown
スプライト: s-hang-wall-0 / s-hang-wall-1 / s-hang-wall-2(ピンポンフレーム,逆順)
下降版です。一時停止の仕組みは ClimbingUp と同じです。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
Falling | 壁の下端に到達(at_edge=true) | — |
WallPause(was_climbing_up=false) | 3 フレームごとに確率 wall.pause_prob | wall.pause_prob |
WallPause
スプライト: s-hang-wall-0
壁上での一時停止です。was_climbing_up フラグで再開方向を記憶し,duration 経過後にその方向のクライム状態に戻ります。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
ClimbingUp | duration 経過かつ was_climbing_up=true | wall.pause_duration |
ClimbingDown | duration 経過かつ was_climbing_up=false | wall.pause_duration |
duration 範囲: wall.pause_duration
コーナーの状態
サーフェスが WindowUpperCorner(ウィンドウ上部の角)のとき使われます。壁の上端からウィンドウ天面へ,またはその逆方向の遷移をアニメーションで表現します。
CornerTransitionSide
スプライト: s-hang-corner
コーナー遷移の側面ビューです。壁の上端で CornerTransitionFront への橋渡し役を担います。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
CornerTransitionFront | corner.side_corner_secs 秒経過 | corner.side_corner_secs |
CornerTransitionFront
スプライト: f-hang-corner
コーナー遷移の正面ビューです。going_up フラグで進行方向(壁から上がる/天面から下りる)を区別します。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
CornerRest | corner.front_corner_secs 秒経過かつ going_up=true,確率 corner.rest_prob | corner.rest_prob, corner.front_corner_secs |
Walking(天面を内側へ) | corner.front_corner_secs 秒経過かつ going_up=true,確率 1 − corner.rest_prob | corner.front_corner_secs |
ClimbingDown | corner.front_corner_secs 秒経過かつ going_up=false | corner.front_corner_secs |
CornerRest
スプライト: f-sit(lying=false,確率 1 − corner.rest_lying_prob) / f-lie(lying=true,確率 corner.rest_lying_prob)
コーナー上端での休憩(座るか伏せるかはランダム)です。
| 遷移先 | 条件 | 関連設定 |
|---|---|---|
JumpRunup | duration 経過,近くにウィンドウありかつ(強制お出かけまたは確率 corner.corner_jump_prob) | corner.outing_interval, corner.corner_jump_prob, corner.corner_jump_dist |
CornerTransitionFront(going_up=false) | 上記不発で duration 経過,確率 corner.rest_descend_prob | corner.rest_duration, corner.rest_descend_prob |
Walking(天面を内側へ) | 上記不発で duration 経過,確率 1 − corner.rest_descend_prob | corner.rest_descend_prob |
duration 範囲: corner.rest_duration
ユーザー操作
Grabbed
スプライト: s-hang-corner
⌘+ドラッグ(macOS)/Ctrl+ドラッグ(Windows)でキャラクターを掴んでいる状態です。状態遷移は発生しません。ドロップされると on_surface_lost が発火し Falling に遷移します。
イベントによる遷移
以下のイベントは現在の状態に関わらず即座に発生します。
| イベント | 遷移先 |
|---|---|
サーフェス消失(ウィンドウを閉じる等,on_surface_lost) | Falling(shocked = floor.shocked_duration,f-shocked を表示) |
サーフェスへの着地(on_landed) | LandingStandUp |