views:

193

answers:

4

Hi!

I am currently faced with a design problem in my game design, not terrible but it bothers me enough so I want to ask others opinions :-)

I am currently experimenting with pygame, I have developed a little space shooter and now I would like to handle some bonuses.

Right now I have an abstract class Bonus from which derive all the bonuses currently implemented: a "health bonus" which gives back some health to the player, a "death bonus" which drops the player's health to 1.

In my game loop here is what I do (roughly):

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)

And right after I tell the player to use the bonuses

class Player:
...
def useBonuses(self):
    for bonus in self.bonuses:
        bonus.use(self)

Until now everything is OK, but I would like to add a "bomb bonus" which when shooted by the player explodes and kills the enemies on his surroundings.

This "bonus" implements the "use(target)" method of my abstract class Bonus as the others to, but I feel kind of bad adding such a bonus to the list of the player's bonuses as there should be no relation between them!

The concept behind a bonus is that this is "something that does something to something", previously the targets where my player class but now it is not as clear... Of course instead of calling player.useBonuses() after detecting which bonuses where shooted I could test the type (using isinstance) for example of the bonuses but after all the discussions I've read about duck-typing and why it's the pythonic way I am wondering how can I manage my bonus problem?

Thanks for reading this far, hope you guys can help me out!

regards

+1  A: 

If you don't want a certain col to go in player.bonuses but elsewhere, make a toplayer method in the abstract class Bonus with the default implementation:

def toplayer(self, player):
    player.bonuses.append(self)

and override it in the bomb bonus class. (You don't have to inherit, as you mention, but there's no trouble in so doing if it gets you some easy functionality reuse.)

So for example a player could have an attribute bomb, normally None, and the bomb bonus class could do:

def toplayer(self, player):
    player.bomb = self

And when the time comes to act on all the bonus accrued, it could start with

if player.bomb is not None:
    player.bomb.explode(player.position)

or the like.

Alex Martelli
+1  A: 

I don't write in python but here's my recommendation: Load up your player with each type of weapon he can get (even ones through bonuses) and set the ammo on the ones that he gets through bonuses to 0. Then when your player picks up a "bomb bonus" (or whatever) add one ammo to the bomb weapon on the player. That ought to work nicely.

RCIX
A: 

I think you're on the right track - I would say the "Bomb Bonus" is still related to the player object because it affects the enemies around the player. You just need to implement the "Bomb Bonus"'s use() method like this:

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()

You'll need to work out your own implementation of distance().

Developing a game without a detailed plan means that you're often going to have new ideas which almost fit your existing objects, and you will need to choose whether to expand your existing classes with new features to support your new idea, or create a new set of classes because you think the new idea is too different. There's no right and wrong here, just make sure your ideas stay organized in a way that makes sense to you.

too much php
The bomb explodes when a bolt is fired on it, it doesn't explodes around the area of the playerm it can be anywhere on the screen and absolutely not related to the current player position, that was my point in saying there is no relation between this bonus and the player.But your implementation could be used for another kind of bonus like a shield for example, thanks :)
attwad
A: 

I had a bonus system in an asteroid clone I wrote a few years ago. It lives (as much as a dead project can live) on Bitbucket now. I dont think its as flexible as you seem to be aiming for. But small "bonus" entities spawns and move around, if they collide with an asteroid, the bonus is removed and missed by the player. If the player collides with it, bonus points are awarded.

mizipzor