ゲームループ

Pyxenはゲームを固定の毎秒30フレームで実行します。メインループを書く必要はありません — 2つの関数を定義するだけで、Pyxenが呼び出します。

start()とupdate()

def start():
    # 最初に1回呼び出される
    pass

def update():
    # 毎フレーム、1秒に30回呼び出される
    pass

start()はワールドをセットアップする場所です:エンティティの生成、配置、シーンの設定。

update()はゲームロジックが実行される場所です:入力の読み取り、エンティティの移動、条件のチェック、状態の更新。update()の各呼び出し後、エンジンがフレームをレンダリングします。

固定フレームレート

各フレームは正確に同じ時間がかかります:1/30秒(約33ms)。つまり:

時間ベースの移動を好む場合はtime.dt(デルタタイム)も使えますが、常に1/30です。

フレームの順序

各フレームで、Pyxenはこの順序でステップを実行します:

  1. 入力 — キーボード、マウス、タッチ、ゲームパッドの状態を読み取る
  2. update() — あなたのコードが実行される
  3. 衝突 — エンジンがグリッドボディを解決し、衝突コールバックを呼び出す
  4. レンダリング — エンジンがすべての可視エンティティを描画

これは、update()で入力を読むとき値が最新であることを意味します。エンティティを移動すると、衝突解決がその直後に行われます。

衝突コールバック

トップレベルでon_collisionon_tile_collisionを定義すると、エンジンが衝突ステップ中にそれらを呼び出します:

def on_collision(entity, other):
    # 2つのグリッドボディが重なった
    pass

def on_tile_collision(entity, tile):
    # グリッドボディがタイルマップのタイルに当たった
    pass

これらはupdate()の後、レンダリングの前に実行されます。

タイミング

pyxen.timeモジュールが提供するもの:

プロパティ用途
time.frame0, 1, 2, ...開始からのフレームカウンター
time.dt0.0333...デルタタイム(常に1/30)
time.t0.0, 0.033, 0.066, ...経過時間(秒)
time.fps30フレーム毎秒

タイミングイベントにはどちらのアプローチも使えます:

# フレームベース:60フレーム(2秒)ごとに発火
if time.frame % 60 == 0:
    fire()

# タイムベース:同じこと
if int(time.t * 30) % 60 == 0:
    fire()

フレームカウントの方が通常シンプルで予測可能です。