pyxen.Entity

Entityは軽量なハンドル — コンポーネントのコンテナです。

エンティティコンポーネントシステムの紹介はエンティティ&コンポーネントを参照してください。


組み込みコンポーネント

コンポーネントアクセス
Transforme.x, e.y, e.rotation, e.scale
Spritee.sprite, e.color
Animatione.animation
Sounde.sound
Musice.music
GridBodye.body
GridMape.map
Nodee.parent, e.children
Layere.layer
Namee.name
Camerae.camera

Transform

e.x = 100
e.y = 50
e.rotation = 45
e.scale = (2, 2)

scaleを読み取るとVector2が返されます:

s = e.scale
print(s.x, s.y)

Sprite

e.sprite = sprite
e.color = (1.0, 0.5, 0.5, 1.0)

colorを読み取るとColorが返されます:

c = e.color
print(c.r, c.g, c.b, c.a)

スプライトアニメーション

スプライトがanimationパラメータ付きで作成されると、エンジンが自動的にアニメーションを再生します。e.animationでアニメーションの状態を読み取れます:

player.sprite = Sprite("hero", animation="walk")

プロパティ

プロパティ説明
namestr現在のアニメーションクリップの名前
frameintクリップ内の現在のフレームインデックス
playingboolアニメーションが再生中ならTrue
finishedboolワンショットアニメーションが完了したらTrue
anim = player.animation
if anim:
    print(anim.name)      # "walk"
    print(anim.frame)     # 2
    print(anim.playing)   # True
    print(anim.finished)  # False

アニメーションがアクティブでない場合、e.animationNoneを返します:

player.sprite = Sprite("hero", tile=(0, 0, 16, 16))
print(player.animation)  # None

キャンセル

e.animationNoneを設定すると再生が停止します:

player.animation = None

新しいスプライトを割り当てると、既存のアニメーションは自動的にキャンセルされます。

ワンショットアニメーション

一度だけ再生するアニメーションにはloop=Falseを使用します:

player.sprite = Sprite("hero", animation="attack", loop=False)

def update():
    if player.animation and player.animation.finished:
        player.sprite = Sprite("hero", animation="idle")

Tweens

Tweensはエンティティのプロパティを時間をかけてスムーズにアニメーションします。エンジンが自動的に補間を処理するため、フレームごとのコードは不要です。

entity.tween()

# プロパティ名指定
entity.tween("x", to=200, duration=1.0)
entity.tween("alpha", to=0, duration=0.5, ease="out_quad")

# キーワード省略形 — 複数のプロパティを同時にアニメーション
entity.tween(x=200, y=100, duration=1.0, ease="out_quad")
パラメータデフォルト説明
propertystrプロパティ名(位置引数またはキーワード形式)
tofloat目標値
byfloat相対オフセット(toの代替)
startfloat現在の値開始値(デフォルトは現在の値)
durationfloat1.0秒単位の継続時間
easestr"linear"イージング関数名

toで絶対目標値、byで相対オフセットを指定します:

entity.tween("x", to=200, duration=1.0)    # x=200へ移動
entity.tween("x", by=50, duration=0.5)     # 右に50ピクセル移動

startで開始値を上書きできます:

entity.tween("x", to=200, start=0, duration=1.0)  # 常に0から開始

アニメーション可能なプロパティ

コンポーネントプロパティ
Transformx, y, rotation, sx, sy
Spriter, g, b, alpha
Camerazoom

イージング関数

名前カーブ
linear一定速度(デフォルト)
in_quadゆっくり開始、加速
out_quad速く開始、減速
in_out_quadゆっくり開始と終了
in_cubicquadより遅い開始
out_cubicquadより速い開始
in_out_cubicなめらかな開始と終了
in_expo非常に遅い開始、爆発的加速
in_out_expo中間が爆発的
out_expo非常に速い開始、穏やかな停止
in_back前進前に引き戻す
out_back目標を超えてから安定
in_out_back引き戻しと超過
in_elastic弾性的な巻き上げ
out_elastic弾性的な超過と振動
in_out_elastic両端で弾性的

entity.tweens.cancel()

エンティティのTweenをキャンセルします。プロパティ名を渡すと1つのTweenをキャンセルし、引数なしで呼び出すとすべてのTweenをキャンセルします。値は現在の位置で固定されます。

entity.tweens.cancel("x")   # 1つのプロパティをキャンセル
entity.tweens.cancel()       # すべてキャンセル

競合の解決

同じエンティティとプロパティで新しいTweenを開始すると、前のものが置き換えられます。異なるプロパティのTweenは独立して実行されます。

entity.tween("x", to=100, duration=1.0)
entity.tween("x", to=200, duration=0.5)  # 最初のTweenを置き換える
entity.tween("y", to=50, duration=1.0)   # xのTweenと並行して実行

破棄されたエンティティのTweenは自動的にクリーンアップされます。

プロパティで animate() を開始すると、そのプロパティのアクティブな tween() がキャンセルされます。逆も同様です。


アニメーション

無限に実行される連続アニメーション — 正弦波の振動(パルス、呼吸、揺れ)と一定速度の回転。

entity.animate() — 振動

正弦波で中心値の周りにプロパティを振動させます。

entity.animate("sx", "sy", by=0.15, speed=6.0)     # coin pulse
entity.animate("alpha", by=0.3, center=0.7, speed=4.0)  # flicker 0.4–1.0

値は次の式に従います: center + sin(elapsed * speed) * by

entity.animate() — スピン

一定の速度で値を累積します。スピンモードを使用するには by= を省略します。

entity.animate("rotation", speed=180)   # 180°/sec clockwise

パラメータ

パラメータデフォルト説明
*propsstr1つ以上のプロパティ名(位置引数)
byfloat振幅(振動モード)。スピンの場合は省略。
centerfloat現在値振動の中心値
speedfloat1.0角周波数(振動)または単位/秒(スピン)

Tweenと同じ10個のプロパティ: x, y, rotation, sx, sy, r, g, b, alpha, zoom

entity.animations.cancel()

エンティティのアニメーションをキャンセルします。プロパティ名を渡すと1つのアニメーションをキャンセルし、引数なしで呼び出すとすべてのアニメーションをキャンセルします。

entity.animations.cancel("rotation")   # 1つのプロパティをキャンセル
entity.animations.cancel()             # すべてキャンセル

親 / 子

child.parent = parent

子にアクセス:

for c in parent.children:
    print(c.name)

子の数を取得:

parent.children.count

カスタムコンポーネント

コンポーネントは以下を割り当てて作成します:

  • 辞書 — 構造化コンポーネント
  • ブーリアン — マーカーコンポーネント
e.cell = {
    'row': 0,
    'col': 0
}

最初の割り当てでスキーマが作成されます。フィールドの型が推論され、スキーマは固定されます — 後から新しいフィールドを追加することはできません。


システムでのコンポーネントの使用

for cell in world.all("cell"):
    ...

参照:pyxen.world.all()


マーカーコンポーネント

e.alive = True

マーカーはデータを保持しません — 存在のみを示します。通常のコンポーネントと同様にクエリできます:

for e in world.all("alive"):
    ...

コンポーネントフィールドへのアクセス

e.cell.row
e.cell.col
e.cell.row = 5

サポートされるフィールド型

Python型格納形式
int32ビット整数
float32ビット浮動小数点数
boolブーリアン
str固定文字列(最大31文字)
Entityエンティティ参照

無効な型の場合:

TypeError: invalid value type in dict

スキーマのルール

  • 最大コンポーネントサイズ:256バイト
  • 文字列の最大長:31文字
  • 辞書のキーは文字列でなければならない
  • スキーマ作成後に新しいフィールドを追加できない
e.cell = {'row': 0}
e.cell = {'row': 0, 'new_field': 5}
ValueError: cannot create new fields after schema is complete

後続の割り当てでフィールドを省略するのは有効です — デフォルト値は00.0False""などになります。


コンポーネントの存在チェック

e.has("cell")

エンティティがそのコンポーネントを持っていればTrue、そうでなければFalseを返します。

カスタムと組み込みの両方のコンポーネント名で動作します:

e.has("sprite")   # エンティティがスプライトを持っていればTrue
e.has("body")     # エンティティがグリッドボディを持っていればTrue

子孫のクエリ

entity.all(*components, without=(), include_self=False)

エンティティの子孫すべて(シーングラフ階層を深さ優先で走査)のうち、指定のコンポーネントフィルタに一致するもののイテレータを返します。

world.all()と同様に動作しますが、ワールド全体ではなくサブツリーにスコープされます。

# "enemy"コンポーネントを持つすべての子孫
for e in parent.all("enemy"):
    ...

# 除外付き
for e in parent.all("enemy", without=("boss",)):
    ...

# 親エンティティ自身も含める
for e in parent.all("tag", include_self=True):
    ...
パラメータデフォルト説明
*componentsstr必須のコンポーネント名
withouttuple()除外するコンポーネント名
include_selfboolFalseエンティティ自身を含めるかどうか

組み込みとカスタムの両方のコンポーネント名に対応しています。


コンポーネントの削除

del を使用するか None を代入して、エンティティからコンポーネントを削除します:

# どちらも同じ意味です:
del entity.health
entity.health = None

削除後、entity.has("health")False を返し、そのコンポーネントのクエリにエンティティはマッチしなくなります。

e = world.spawn()
e.health = {'hp': 100}

del e.health

e.has("health")         # False
# world.all("health") に e は含まれない

削除後にコンポーネントを再追加できます:

del e.health
e.health = {'hp': 50}   # 問題なく動作する

組み込みコンポーネント

すべての組み込みコンポーネントを削除できます:

del e.sprite    # スプライトデータをクリア
del e.body      # 物理ボディをクリア
del e.camera    # カメラを削除
del e.text      # テキストを削除
del e.sound     # サウンドを削除
del e.music     # ミュージックを削除
del e.map       # グリッドマップを削除

spriteとbodyはゼロ初期化されます(エンティティにはストレージが残りますが、データは空になります)。camera、text、sound、music、mapは完全に消去されます。

マーカー

e.enemy = True
del e.enemy      # または: e.enemy = None
e.has("enemy")   # False

エンティティのライフサイクル

  • world.spawn() で作成
  • コンポーネントの割り当てで変更
  • del または = None でコンポーネントを削除
  • world.destroy() で破棄

参照:pyxen.world.spawn() | pyxen.world.destroy()