2
\$\begingroup\$

In working on a Python/Pygame project I recently came to an impasse which couldn't be solved elegantly via my previous methodology - using wrapping functions as an Observer pattern - and it was impressed on me to look at some kind of event system instead.

As an example:

class Player(sprite):
    ...
    @property
    def lives(self):
        return self._lives
    @score.setter
    def lives(self, new):
        old = self._lives
        self._lives = new
        self.fire_event(LifeChanged(self, old, new))
    ...
mainchar = Player()
scoreboard = Scoreboard()
scoreboard.listen_for(LifeChanged, scoreboard.on_life_changed)

So this was literally the only thing in-game that I felt I 'needed' to handle in this way, and while I prefer it to calling scoreboard.text = mainchar.lives in every loop, it gives me a bit of pause because at present it is pretty much the only thing I'm using events to manage.

I realize that a lot of this stuff is by-preference, and I'm not looking to refactor my entire game here or get a breakdown of why MVC/Entity Systems/whatever is preferable, but it did raise a question for me regarding the practice of objects that create objects. The simplest example being something like a character which fires projectiles:

def fire(self, shot_direction):
    newshot = Bullet(self.rect.center[0], self.rect.center[1], shot_direction)
    newshot.add(self.groups())

Again, it may just be an implementation detail, but it does start to "feel like" a better way is to send a message to a Bullet factory instead of letting the object doing the firing instantiate the Bullet and add it to Sprite.group instances that it happens to belong to. After all - why does my Player object need to 'know' anything about the groups it belongs to, or have the responsibility to add things to a game object that is more or less not part of the game action?

I could be overthinking all the things -- I do that. :/ But I'm genuinely curious as to whether or not there is a fundamental consensus on 'best practice' (regardless of design patterns) that dictates whether or not game objects should be doing the creating of game objects directly, or whether there should instead be a factory sitting in the background somewhere that churns out all instances of new bad guys, projectiles, powerups, and so on.

\$\endgroup\$
1
\$\begingroup\$

The way I see it is, don't stick the hooks in for something that will give you no benefit. Write your code in the simplest possible manner first, which almost always means "hard-coding" some things like the sprite group snippet you mentioned. If you come across some new change or requirement that would benefit from the factory, then by all means, write it, but don't write it until you need it. Note that I'm not advocating eschewing all abstractions out of the gate - rather, just the ones where there's no recognizable benefit.

In other words, YAGNI.

\$\endgroup\$
  • 1
    \$\begingroup\$ Refactors > research? :D I can get behind that, as long as there's a modicum of common sense in the first few innings \$\endgroup\$ – Stick Apr 6 '14 at 22:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.