1

ピグレットで簡単な「落下する敵を避ける」タイプのゲームを書いています。オブジェクトは画面の上に生成され、下に移動し、表示されている画面の下を通過すると破壊されます。しかし、私はひどく間違ったことをしており、プログラムの実行時間が長くなるほど、オブジェクトの数がどんどん増えていきます。(速度が遅くなり、objgraph の問題を発見しました。) このクラスを削除すると、問題はなくなります。

落下する敵のクラス:

class Enemy(pyglet.sprite.Sprite):
    def __init__(self, **kwargs):
        super(Enemy, self).__init__(img=images.enemy_anim["front"], **kwargs)
        self.out_of_bounds = False

    def update(self, dt):
        self._move(dt)
        self._check_boundaries(dt)
        self._check_kill_condition()

    def _move(self, dt):
        self.y -= ENEMY_SPEED * dt

    def _check_boundaries(self, dt):
        if self.y + self.height < 0:
            self.out_of_bounds = True

    def _check_kill_condition(self):
        if self.out_of_bounds:
            enemy_list.remove(self)
            self.delete

主なメソッド コード:

enemy_list = []

def add_enemy(*args, **kwargs):
    randx = random.randint(0,
               WINDOW_WIDTH - images.enemy_anim["front"].get_max_width())
    randy = WINDOW_HEIGHT + images.enemy_anim["front"].get_max_height()
    enemy_list.append(Enemy(x=randx, y=randy, batch=update_batch))

def update(dt):
    for sprite in enemy_list:
        sprite.update(dt)

#send the above functions to the pyglet scheduler
pyglet.clock.schedule_interval(update, 1/TICKS_PER_SECOND)
pyglet.clock.schedule_interval(add_enemy, 1/ENEMY_ADD_RATE)

辞書 (images.enemy_anim) 内の別のモジュール (画像) に敵のアニメーションを保存しています。

リスト内の参照で敵を作成します。

敵が死ぬと、リストから自分自身を削除するように指示します。実行時にリストの長さを確認しましたが、常に適切な長さです。したがって、リストが制御不能になることはありません。オブジェクトがリストから削除された後、そのオブジェクトには参照がないはずですよね?

私は何を間違っていますか?

編集:

問題は、私がself.delete代わりに持っていたということでしself.delete()た。愚かな間違い...

4

2 に答える 2

5

独自のメソッド内でオブジェクトを削除する代わりに、別のアプローチを取り、次のように追加の schedule_interval でスプライトを削除します。

def delete_enemy(*args, **kwargs):
    items_to_delete = []
    for enemy in enemy_list:
        if enemy.out_of_bounds:
            items_to_delete.append(enemy)
    for item in items_to_delete:
        enemy_list.remove(item)

pyglet.clock.schedule_interval(delete_enemy)

そしてもちろん の行self._check_kill_condition()を削除しEnemy.updateます。

編集: pyglet はわかりませんが、このアプローチも機能しない場合は、pyglet 内の何かがスプライトへの参照を保持します。スプライトは、キャンバスまたは同様のオブジェクトで参照できます。スプライトを完全に (つまり、キャンバスから) 削除するには、pyglet に API 呼び出しが必要です。この呼び出しは、呼び出しの直後に使用する必要がありenemy_list.remove(item)ます。

于 2013-06-14T08:15:54.613 に答える
0

上記のコメントでBakuriuが指摘したように、問題は単に pyglet スプライトdeleteメソッドの括弧のペアを忘れていたことです。単純明快なミスが引き起こす大問題…

于 2013-06-14T16:14:35.537 に答える