游戏设计 - 处理奖励 / 鸭子类型 - Python
我现在在游戏设计上遇到一个问题,虽然不算太严重,但让我有点烦,所以想请教一下大家的意见 :-)
我正在尝试使用pygame,开发了一个小型的太空射击游戏,现在我想处理一些奖励。
目前我有一个抽象类叫做Bonus,所有实现的奖励都是从这个类派生出来的:比如“生命奖励”,可以给玩家恢复一些生命值,还有“死亡奖励”,会把玩家的生命值降到1。
在我的游戏循环中,我大致是这样做的:
def testCollisionBonusBolt():
#bolts are sprites fired by the player that allow him to get the bonuses
collisions = pygame.sprite.groupcollide(bonusesGroup, boltsGroup, True, True)
for col in collisions:
player.bonuses.append(col)
然后我会告诉玩家如何使用这些奖励。
class Player:
...
def useBonuses(self):
for bonus in self.bonuses:
bonus.use(self)
到现在为止一切都还不错,但我想添加一个“炸弹奖励”,当玩家发射时会爆炸并杀死周围的敌人。
这个“奖励”也实现了我抽象类Bonus中的“use(target)”方法,和其他奖励一样,但我觉得把这个奖励加到玩家的奖励列表中有点不妥,因为它们之间似乎没有关系!
奖励的概念是“某样东西对某样东西做了某事”,之前的目标是我的玩家类,但现在就不太清楚了……当然,我可以在检测到哪些奖励被发射后,调用player.useBonuses(),也可以测试奖励的类型(使用isinstance),但考虑到我读过的关于鸭子类型和为什么这是Pythonic方式的讨论,我在想我该如何处理我的奖励问题呢?
谢谢你们读到这里,希望你们能帮我一下!
祝好
4 个回答
我觉得你走在正确的道路上——我想说“炸弹奖励”还是和玩家对象有关,因为它会影响到玩家周围的敌人。你只需要像这样实现“炸弹奖励”的 use()
方法:
class BombBonus(Bonus):
def use(self, player):
assert isinstance(player, Player)
# TODO: find all enemies that are close to the player - assuming you
# have all enemy objects in a list call 'enemies'
global enemies
for enemy in enemies:
if distance(player.position, enemy.position) < 400:
# if the distance between player and an enemy is less than 400
# (change this value to your liking), destroy that enemy.
enemy.explode()
你需要自己想出 distance()
方法的实现。
在没有详细计划的情况下开发游戏,意味着你经常会有一些新想法,这些想法几乎可以和你现有的对象结合在一起。你需要决定是给现有的类添加新功能来支持这些新想法,还是创建一套新的类,因为你觉得这些新想法和现有的差别太大。这里没有对错之分,只要确保你的想法以一种对你有意义的方式保持有序就可以了。
我虽然不写Python,但我有个建议:给你的角色装备上他能拿到的每种武器(包括那些通过奖励获得的武器),然后把通过奖励得到的武器的弹药设置为0。这样,当你的角色捡到一个“炸弹奖励”(或者其他什么奖励)时,就给炸弹武器加一发弹药。这样应该能很好地实现。
如果你不想让某个 col
加入到 player.bonuses
中,而是放到其他地方,可以在抽象类 Bonus
中创建一个 toplayer
方法,并给它一个默认的实现:
def toplayer(self, player):
player.bonuses.append(self)
然后在 bomb bonus
类中重写这个方法。(你可以选择不继承,就像你提到的那样,但如果这样做能让你更方便地复用功能,也没有问题。)
举个例子,玩家可以有一个属性 bomb
,通常情况下这个属性是 None
,而 bomb bonus
类可以这样做:
def toplayer(self, player):
player.bomb = self
当需要处理所有累积的奖励时,可以从以下内容开始:
if player.bomb is not None:
player.bomb.explode(player.position)
或者类似的内容。