我目前正在使用python和pygame編寫一個非常簡單的遊戲。它有東西移動。爲了讓這個東西順利移動,我按照Fix Your Timestep的說法安排了主要遊戲循環,並進行了插值。你將如何處理python遊戲中的插值?
這是我現在如何處理插值。
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的OO方面,並且設計了比10行hacky一次性腳本更大的東西。
這個問題不是一個問題,因爲我不知道什麼,也不能做任何事情。我敢肯定,我有能力重寫這個非常簡單的代碼,它可以在某種程度上接近我想要的。我想知道的是,有經驗的Python程序員會以pythonic的方式解決這個簡單的問題,所以我(當然還有其他人)可以學習在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?將它們全部添加爲列表/字典lerper.add([ship])
?做一個特殊的容器類繼承字典/什麼?你認爲什麼是解決這個問題的優雅,pythonic方式?你會怎麼做?
你看了整個問題?我沒有看到任何與插值有關的內容或我在答案中提出的問題。我在你的回答中看到的唯一「想法」是「讓每個遊戲對象自己處理插值」,但你甚至不提及它。O.o – Mikka 2012-08-01 19:11:42
也許我誤解了你的問題。我認爲,「我如何修改我的遊戲,使其更加通用,並且可以輕鬆擴展?」。如果你的問題實際上是「如何修改我的插值算法使其更通用?」,那麼你已經猜到了我的觀點:讓每個遊戲對象處理自己的插值。 (最好只有一次,在射彈基類中) – Kevin 2012-08-01 19:19:48