私は現在、Pythonとpygameを使用して非常に単純なゲームを書いています。動くものがあります。そして、このようなものをスムーズに動かすために、 Fix Your Timestepで述べたように、補間を使用してメインゲームループを配置しました。
これが私が今補間を処理する方法です。
class Interpolator(object):
"""Handles interpolation"""
def __init__(self):
self.ship_prev = None
self.ship = None
self.stars_prev = []
self.stars = []
self.bullets_prev = {}
self.bullets = {}
self.alpha = 0.5
def add_ship(self, ship):
self.ship_prev = self.ship
self.ship = ship
def add_stars(self, stars):
self.stars_prev = self.stars
self.stars = stars[:]
def add_bullets(self, bullets):
self.bullets_prev = self.bullets
self.bullets = bullets.copy()
def add_enemies(self, enemies):
self.enemies_prev = self.enemies
self.enemies = enemies # to be continued
def lerp_ship(self):
if self.ship_prev is None:
return self.ship
return lerp_xy(self.ship_prev, self.ship, self.alpha)
def lerp_stars(self):
if len(self.stars_prev) == 0:
return self.stars
return (lerp_xy(s1, s2, self.alpha) for s1, s2 in izip(self.stars_prev, self.stars))
def lerp_bullets(self):
keys = list(set(self.bullets_prev.keys() + self.bullets.keys()))
for k in keys:
# interpolate as usual
if k in self.bullets_prev and k in self.bullets:
yield lerp_xy(self.bullets_prev[k], self.bullets[k], self.alpha)
# bullet is dead
elif k in self.bullets_prev:
pass
# bullet just added
elif k in self.bullets:
yield self.bullets[k]
lerp_xy()関数とデータ型
def lerp_xy(o1, o2, alpha, threshold=100):
"""Expects namedtuples with x and y parameters."""
if sqrt((o1.x - o2.x) ** 2 + (o1.y - o2.y) ** 2) > 100:
return o2
return o1._replace(x=lerp(o1.x, o2.x, alpha), y=lerp(o1.y, o2.y, alpha))
Ship = namedtuple('Ship', 'x, y')
Star = namedtuple('Star', 'x, y, r')
Bullet = namedtuple('Bullet', 'x, y')
データ型はもちろん一時的なものですが、将来的にはx属性とy属性を持つことを期待しています。更新: lerper.alphaはフレームごとに更新されます。
船は単一のオブジェクトとして追加されます-それはプレイヤーの船です。星がリストとして追加されます。弾丸はdict{id、Bullet}として追加されます。弾丸は常に追加および削除されるため、どちらの弾丸がどれであるかを追跡し、両方が存在するかどうかを補間し、追加または削除されたばかりの場合は何かを実行する必要があります。
とにかく、ここにあるこのコードはがらくたです。機能を追加するにつれて成長しましたが、今はもっと一般的なものに書き直して、成長を続け、うんちマークのような臭い山にならないようにしたいと思っています。
今でも私はPythonにかなり慣れていませんが、リスト内包表記、ジェネレーター、コルーチンについてはすでにかなり快適に感じています。
私が最も経験が少ないのは、Pythonのオブジェクト指向側であり、10行のハッキーな使い捨てスクリプトよりも大きなアーキテクチャを設計することです。
質問は私が知らないもののような質問ではなく、それについて何もできません。私は、私が望むものに何らかの形で近い形で機能するこの非常に単純なコードを書き直すことができると確信しています。
私が知りたいのは、経験豊富なPythonプログラマーがこの単純な問題をPythonの方法で解決する方法です。そのため、私(そしてもちろん他の人)は、Python開発者の間でそのようなケースを処理するエレガントな方法と見なされる方法を学ぶことができました。
だから、私がおおよそ達成したいことは、擬似コードで:
lerper = Interpolator()
# game loop
while(1):
# physics
# physics done
lerper.add(ship)
lerper.add(stars)
lerper.add(bullets)
lerper.add(enemies) # you got the idea
# rendering
draw_ship(lerper.lerp('Ship'))
# or
draw_ship(lerper.lerp_ship())
ただし、より良い解決策を考えている場合は、その擬似コードで停止させないでください=)
それで。すべてのゲームオブジェクトを個別の/継承されたクラスとして作成しますか?それらすべてにIDを持たせる?それらすべてをlist/dictとして追加しますlerper.add([ship])
か?dict / whateverから継承する特別なコンテナクラスを作成しますか?これを解決するためのエレガントでパイソン的な方法は何だと思いますか?どうしますか?