9
\$\begingroup\$

I have only previously made flash games, using MovieClips and such to separate out my animations from my game logic. Now I am getting into trying my hand at making a game for Android, but the game programming theory around separating these things still confuses me. I come from a background of developing non game web applications so I am versed in more MVC like patterns and am stuck in that mindset as I approach game programming.

I want to do things like abstract my game by having, for example, a game board class that contains the data for a grid of tiles with instances of a tile class that each contain properties. I can give my draw loop access to this and have it draw the game board based on the properties of each tile on the game board, but I don't understand where exactly animation should go. As far as I can tell, animation sort of sits between the abstracted game logic (model) and the draw loop (view). With my MVC mindset, it's frustrating trying to decide where animation is actually supposed to go. It would have quite a bit of data associated with it like a model, but seemingly needs to be very closely coupled with the draw loop in order to have things like frame independent animation.

How can I break out of this mindset and start thinking about patterns that make more sense for games?

\$\endgroup\$

3 Answers 3

6
\$\begingroup\$

Animation can still perfectly be split between logic and rendering. The abstract data state of animation would be the information that is necessary for your graphics API to render the animation.

In 2D games for example,that could be a rectangle area which marks the area that displays the current part of your sprite sheet that needs to be drawn (when you have a sheet consisting of lets say 30 80x80 drawings containing the various steps of your character jumping, sitting down, moving etc.). It can also be any kind of data that you don't need for rendering, but maybe for managing the animation states themselves, like the time left until the current animation step expires or the name of the animation ("walking","standing" etc.) All of that can be represented any way you want. That's the logics part.

In the rendering part, you just do it as usual, get that rectangle from your model and use your renderer to actually do the calls to the graphics API.

In code (using C++ syntax here):

class Sprite //Model
{
    private:
       Rectangle subrect;
       Vector2f position;
       //etc.

    public:
       Rectangle GetSubrect() 
       {
           return subrect;
       }
       //etc.
};

class AnimatedSprite : public Sprite, public Updatable //arbitrary interface for classes that need to change their state on a regular basis
{
    AnimationController animation_controller;
    //etc.
    public:
        void Update()
        {
            animation_controller.Update(); //Good OOP design ;) It will take control of changing animations in time etc. for you
            this.SetSubrect(animation_controller.GetCurrentAnimation().GetRect());
        }
        //etc.
};

That's the data. Your renderer will take that data and draw it. Since both normal Sprites and animated ones are drawn the same way, you can use polymorphy here!

class Renderer
{
    //etc.
    public:
       void Draw(const Sprite &spr)
       {
           graphics_api_pointer->Draw(spr.GetAllTheDataThatINeed());
       }
};

TMV:

I came up with another example. Say you have an RPG. Your model that represents the world map, for example, would probably need to store the character's position in the world as tile coordinates on the map. However, when you move the character, they walk a few pixels at a time to the next square. Do you store this "between tiles" position in an animation object? How do you update the model when the character has finally "arrived" at the next tile coordinate on the map?

The world map doesn't know about the players position directly (it doesn't have a Vector2f or something like that which directly stores the players position=, instead it has a direct reference to the player object itself, which in turn derives from AnimatedSprite so you can pass it to the renderer easily, and gets all necessary data from it.

In general though, your tilemap shouldn't be able to do just everything - I'd have a class "TileMap" which takes care of managing all the tiles, and maybe it also does collision detection between objects that I hand over to it and the tiles on the map. Then, I'd have another "RPGMap" class, or however you'd like to call it, which has both a reference to your tilemap and the reference to the player and makes the actual Update() calls to your player and to your tilemap.

How you want to update the model when the player moves depends on what you want to do.

Is your player allowed to move in between tiles independently (Zelda style)? Simply handle the input and move the player accordingly every frame. Or do you want the player to press "right" and your character automatically moves one tile to the right? Let your RPGMap class interpolate the players position until he arrives at his destination and meanwhile lock all the movement-key input handling.

Either way, if you want to make it easier on yourself, all of your models will have Update() methods if they actually need some logic to update themselves (instead of just changing values of variables) - You don't give away the controller in the MVC pattern that way, you just move the code from "one step above" (the controller) down to the model, and all the controller does is call this Update() method of the model (The controller in our case would be the RPGMap). You can still easily swap out the logics code - you can just directly change the code of the class or if you need completely different behaviour, you can just derive from your model class and only override the Update() method.

That approach reduces method calls and things like that a lot - which used to be one of the main disadvantages of the pure MVC pattern (you end up calling GetThis() GetThat() very very often) - it makes the code both longer and a tiny bit harder to read and also slower - even though that might be taken care of by your compiler who optimizes a lot of stuff like that.

\$\endgroup\$
5
  • \$\begingroup\$ Would you keep the animation data in the class containing the game logic, the class containing the game loop, or separate from both? Also, it's entirely up to the loop or the class containing the loop to understand how to translate animation data into actually drawing the screen, right? It would often not be as simple as just getting a rect that represents a section of the sprite sheet and using that to clip a bitmap draw from the sprite sheet. \$\endgroup\$
    – TMV
    Jun 25, 2011 at 0:39
  • \$\begingroup\$ I came up with another example. Say you have an RPG. Your model that represents the world map, for example, would probably need to store the character's position in the world as tile coordinates on the map. However, when you move the character, they walk a few pixels at a time to the next square. Do you store this "between tiles" position in an animation object? How do you update the model when the character has finally "arrived" at the next tile coordinate on the map? \$\endgroup\$
    – TMV
    Jun 25, 2011 at 0:47
  • \$\begingroup\$ I edited in the answer to your question, as the comments don't allow enough characters for that. \$\endgroup\$
    – TravisG
    Jun 25, 2011 at 8:11
  • \$\begingroup\$ If I understand everything correctly: \$\endgroup\$
    – TMV
    Jun 25, 2011 at 10:31
  • \$\begingroup\$ You could have an instance of an "Animator" class inside your View, and it would have a public "update" method which is called every frame by the view. The update method calls the "update" methods of instances of various kinds of individual animation objects inside of it. The animator and the animations inside of it have a reference to the Model (passed down through their constructors) so they can update the model data if an animation would change it. Then, in the draw loop, you get data from the animations inside the animator in a way that can be understood by the View and drawn. \$\endgroup\$
    – TMV
    Jun 25, 2011 at 10:38
2
\$\begingroup\$

I can develop on this if you wish, but I have a central renderer that gets told to draw in the loop. Rather than

handle input

for every entity:
    update entity

for every entity:
    draw entity

I have a system more like

handle input (well, update the state. Mine is event driven so this is null)

for every entity:
    update entity //still got game logic here

renderer.draw();

The renderer class simply holds a list of references to drawable components of objects. These are assigned in the constructors for simplicity.

For your example, I would have a GameBoard class with a number of Tiles. Each tile obviously knows its position, and I assume some kind of animation. Factor that out into some sort of Animation class that the tile owns, and have it pass a reference of itself to a Renderer class. There, all separated. When you update Tile, it calls Update on the animation..or updates it itself. When Renderer.Draw() is called, it draws the animation.

Frame independent animation shouldn't need too much to do with the draw loop.

\$\endgroup\$
0
\$\begingroup\$

I've been learning the paradigms myself lately, so if this answer is incomplete, I'm sure someone will add to it.

The methodology that seems to make the most sense for game design is to separate the logic from the screen output.

In most cases you would want to use a multi threaded approach, if you're not familiar with that topic, it's a question all its own, here's wiki's primer. Essentially you want your game logic to execute in one thread, locking variables that it needs to access in order to ensure the data integrity. If your logic loop is incredibly fast (super mega animated 3d pong?) you can try to fix the frequency the loop executes by sleeping the thread for small durations (120 hz has been suggested in this forum for game physics loops). Concurrently, the other thread is redrawing the screen (60 hz has been suggested in other topics) with the updated variables, again asking for a lock on the variables before it accesses them.

In that case, animations or transitions, etc, go into the drawing thread but you must signal through a flag of some sort (a global state variable perhaps) that the game logic thread must do nothing (or do something different ... setup the new map parameters perhaps).

Once you get your head around the concurrency, the rest is fairly comprehensible. If you don't have experience with concurrency I strongly suggest you write a few simple test programs so that you can understand how the flow happens.

Hope this helps :)

[edit] On systems that don't support multithreading, the animation can still go into the draw loop, but you want to set the state in such a way to signal to the logic that something different is occurring and don't keep processing the current level/map/etc...

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I disagree here. In most cases you don't want to multi-thread, especially if it's a small game. \$\endgroup\$ Jun 24, 2011 at 12:43
  • \$\begingroup\$ @TheCommunistDuck Fair enough, overhead and complexity for multithreading can be definately make it overkill, plus if the game's small, it should be able to quickly update. \$\endgroup\$
    – Stephen
    Jun 24, 2011 at 19:06

You must log in to answer this question.

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