游戏设计 - 处理奖励 / 鸭子类型 - Python

4 投票
4 回答
518 浏览
提问于 2025-04-15 12:42

我现在在游戏设计上遇到一个问题,虽然不算太严重,但让我有点烦,所以想请教一下大家的意见 :-)

我正在尝试使用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 个回答

0

我觉得你走在正确的道路上——我想说“炸弹奖励”还是和玩家对象有关,因为它会影响到玩家周围的敌人。你只需要像这样实现“炸弹奖励”的 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() 方法的实现。

在没有详细计划的情况下开发游戏,意味着你经常会有一些新想法,这些想法几乎可以和你现有的对象结合在一起。你需要决定是给现有的类添加新功能来支持这些新想法,还是创建一套新的类,因为你觉得这些新想法和现有的差别太大。这里没有对错之分,只要确保你的想法以一种对你有意义的方式保持有序就可以了。

1

我虽然不写Python,但我有个建议:给你的角色装备上他能拿到的每种武器(包括那些通过奖励获得的武器),然后把通过奖励得到的武器的弹药设置为0。这样,当你的角色捡到一个“炸弹奖励”(或者其他什么奖励)时,就给炸弹武器加一发弹药。这样应该能很好地实现。

1

如果你不想让某个 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)

或者类似的内容。

撰写回答