5
\$\begingroup\$

So I'm trying to code a game using the Model-View-Controller pattern, and therefore have a need to separate the models for my game objects with their sprite representations. The problem that I'm running into is with PyGame's sprite class. For example, let's take the code below for a Tank object in my game.

class Tank(Projectile):
    '''A tank object.'''
    MAX_SPEED = 8.0

    @property
    def MAX_TURN(self):
        return 10.0 - 0.75 * abs(self.velocity)

    def __init__(self, position=(0, 0), heading=0.0, power=100.0, name=None):
        Projectile.__init__(self, position, heading)

        self.gun = Gun(self)
        self.radar = Radar(self)

        self.power = power
        self.name = name

    def update(self, dt):
        super(Tank, self).update(dt) #Just writing this here for illustrative purposes

Additionally, in a separate views file, I have the code for the basis of a sprite:

class TankSprite(RotatableSprite):
    _image = pygame.image.load('images/tank/body.png').convert_alpha()
    _layer = 0
TankSprite.groups = tank_group, all_group

Now the standard solution might just be to merge these two into one, and then use pygame's pygame.sprite.group.update() method to update and draw everything as desired. But with a MVC pattern, I run into a few problems:

  • First, there is no way of knowing when a new object is created. For example, when the Tank fires its Gun, its creates a Bullet object. Since the Bullet is a model, there is no way to detect this creation without some awkward View code in the Models.
  • Second, I don't believe I can use pygame's collision methods or Group objects, which isn't the worst, but somewhat awkward.

Really, the bullet problem is killing me more than anything else. Any help would be appreciated.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ And now you know why the MVC pattern doesn't really work for games (and why game development != business software development) \$\endgroup\$
    – thedaian
    Commented Aug 10, 2011 at 19:56
  • \$\begingroup\$ @thedaian gets a hole in one. Just because you have a hammer, not everything is a nail. \$\endgroup\$ Commented Aug 10, 2011 at 20:17

1 Answer 1

3
\$\begingroup\$

As you've written it, your Tank is both your model and your controller. Normally, you either have a view controller and a model controller that talk to each other and their appropriate other part, or a single controller that mediates between the view and model directly.

There are a variety of ways to solve this:

  • Accept that Tanks are models and controllers. Let the Tank manage its own view.
  • Split the Tank class into separate model and controller classes. The controller mediates the two so they don't need to know about each other; object creation is a controller responsibility.
  • Realize that MVC is about abstractions, and there are ways to do abstractions that do not require three totally separate classes; two or three mixins communicating via shared state on the same object work just as well in Python.
  • Realize that MVC is a bad pattern for games, especially simple games in very high level languages, and just do what works.
\$\endgroup\$
4
  • \$\begingroup\$ Oops- So the run() method isn't actually supposed to be there in the released version. I'm just using that for debugging. That said, can you elaborate on why MVC is a bad pattern for games? It seems like a very natural fit, and I particularly wish to include the option to run the game without a visualization (since in some ways my project is closer to a simulation than a game). \$\endgroup\$
    – Ceasar
    Commented Aug 10, 2011 at 20:33
  • \$\begingroup\$ gamedev.stackexchange.com/questions/3426 goes into detail on why MVC is a bad fit for games; it is also covered in many other questions on the site. The gist is that the data in the model and view are going to be mostly the same for games. \$\endgroup\$
    – user744
    Commented Aug 10, 2011 at 20:40
  • \$\begingroup\$ (Filling in anything of consequence in your update function is still going to result in Tank being both a model and controller.) \$\endgroup\$
    – user744
    Commented Aug 10, 2011 at 20:42
  • \$\begingroup\$ And if you want an option to run the game without visulisation, just add an option that skips your rendering code (in many games, there's a single render function, which makes it easy to skip) \$\endgroup\$
    – thedaian
    Commented Aug 10, 2011 at 21:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .