Enemyのフレーム処理案

作者はEnemy.frameをオーバーライドするとして、書き換えて欲しくない部分はEnemy._frameに定義した上で、_frame()からframe()を呼び出すようにすれば安全なような気がする。

>>> import time;
>>> class Enemy:
...     def __init__(self):
...             self.f = 0
... 
...     def fire(self):
...             print "%02d) Fire!" % self.f
... 
...     def _frame(self):
...             self.frame()
...             self.f += 1
... 
>>> class SampleEnemy(Enemy):
...     def __init__(self):
...             Enemy.__init__(self)
... 
...     def frame(self):
...             if self.f % 10 == 0:
...                     self.fire()
... 
>>> e = SampleEnemy()
>>> e
<__main__.SampleEnemy instance at 0x9a990>
>>> while True:
...     e._frame()
...     time.sleep(0.1)
... 
00) Fire!
10) Fire!
20) Fire!

実際のコードではwhile節の部分がメインループになる。メインループ内で呼び出すのは_frame()であってframe()ではない。frame()は_frame()から呼び出される。
_frame()にフレーム数を保持するfのインクリメントを委ねたことで、作者がオーバーライドするframe()では単純に「あるフレームで何をするか」さえ記述すれば良いことになる。単純なself.f+=1のし忘れミスを防げる。


また、本格的な考察はまだだが、Enemyの動作はタートルグラフィックスのように「10フレームかけて速度3で右に移動し、弾を撃って、左に5フレームかけて…」という形式でも規定できるようにしたい。
んで、それとこいつを併用すれば、例えば「弾の発射はframe()で、移動はturtle()で」みたいな分業で綺麗に書けるかもしれない。
上のコードでは_frame()はframe()だけを呼び出しているが、例えばturtle()の指定に従って動作を規定される_defined_by_turtle()も同じ_frame()で呼び出すようにするとか。