7
\$\begingroup\$

Suppose I'm building a chess game where I want to have animations. Pieces glide to their new squares when moved. Pieces perform attack animations when capturing other pieces.

I'm not sure how to effectively separate the data and logic needed for these animations and the actual game model (in the MVC sense). The pieces themselves should ideally not have to worry about their pixel coordinates or current animation frame. At the same time, many changes to the model are effectively driven by animations. A moved piece changes its position after (before?) its sprite is done gliding. A piece is removed from the board after the capturing piece is finished its attack animation.

How would you suggest I manage the game model, the graphics and animations, and their relationships? For example, where would the animations "live"? How would animations be created and managed in response to player moves? How would animations drive updates to the game model, or how would the game model drive animations?

\$\endgroup\$

1 Answer 1

8
\$\begingroup\$

Use a simple observer pattern:

  1. The player input (mouse clicks/button presses) manipulates the model (abstract representation of chess board with pieces on it).
  2. Your graphics component responsible for animating and rendering gets notified when the model's state changes and plays the according animation.

There are two ways to "sync" both modules:

  1. Prevent any player input while an animation is running.
  2. Maintain a queue in which you insert animations that are then being played one after another, thus giving your players the possibility to "play ahead" (for example choosing a piece that isn't involved in the current animation and moving it after realizing what the enemy just did)

Don't forget that your model contains all the game logic and follow this rule strictly. The graphics system just acts like an UI, while the model decides whether moves are actually allowed or not. This clear separation answers many questions (like: "What if someone commands a piece to do X, when it's currently doing Y?") and avoids logic problems along the course of the game implementation.

Edit: Example Implementation
Logic should be separated from the graphical representation.

class LogicalPiece {
    Type _type; //enum: "Pawn", "Knight", ...
    int _owner; //player index
}

class GraphicalPiece : LogicalPiece {
    SpriteBatch _sprite;
    Vector2 position;
}

The board can then store the logic aspects of all pieces while at the same time providing access to graphical information for the graphics system:

LogicalPiece[] _pieces = new GraphicalPiece[64];

Example move:

//graphics system asks:
if (game.board.isMoveVald(startPos, endPos, player)) {
    Move m = game.board.makeMove(startPos, endPos, player);
    //process m
} else {
    //output error msg
}

where the internal structure of m could look something like that:

m = {
    action: "move",
    piece: board[34], //the actual GraphicalPiece provided by the board
    startPos: {2, 5},
    endPos: {1, 7},
    effects : [
        { effect: "death",
          piece: board[57] //some GraphicalPiece },
        { effect: "promotion",
          callback: someFunc }
    ]
}

The graphics system updates itself with a fixed timestep (for example 60 times per second) and in the course of that includes animations of pieces. The game, when asked to do a move, not only updates itself(/the model), but collects all the changes that this move will cause and provides that information to the graphics system which parses and visualizes it. There are many implementation details to figure out, like:

  • What kind of notification to use: Events, callbacks or return values?
  • Should there be one central draw method or should every piece know how to draw (and animate) itself, so that the graphics system just dispatches animations?
  • etc.

My advice is to start coding! Set yourself very easy goals at first and only add new goals after reaching the current one. The details will crystalize out over the course of programming. By trying to plan everything ahead all you'll accomplish is a headache.

Possible roadmap:

  1. Be able to draw a game situation with the simplest imaginable implementation: Pieces' graphical representations are updated instantly just like the abstract model (they vanish at one place and pop out at another one)
  2. With the system in (1) implement all rules of the game so that players can play it with the correct outcome.
  3. Add moving animations: Pieces shall slide smoothly from origins to destinations.
  4. Add fighting animations.

...

\$\endgroup\$
7
  • \$\begingroup\$ So, for the case of moving a piece, I'd update the piece's position first in the model, then notify the graphics component to play the movement animation. The graphics component could read the new position from the model, but since the piece's original position is also needed does the notification need to send that to the graphics component? In other words, when the model notifies the graphics component would it be sending information to it that is no longer currently present in the model? \$\endgroup\$
    – AJM
    Commented Feb 16, 2011 at 22:35
  • \$\begingroup\$ @AJM correct. Changes to the model happen instantly, while the graphics component "tries to catch up" with animations. Since it's your code you're totally free to implement it in whatever way you want. For example one could raise an event "PieceMoved" with two parameters: oldPosition and newPosition. \$\endgroup\$
    – Dave O.
    Commented Feb 16, 2011 at 23:01
  • \$\begingroup\$ Would this apply to more complex actions? Suppose I'm actually working on a strategy wargame, and there is a piece that can fire a missile at a square to cause an explosion that hurts nearby pieces. To the model this could be a single update: find all pieces in range of the target square, apply damage to them, and remove any dead pieces. Animating this (well) would take several steps: the attacking piece fires, the missile files to the target, the missile explodes, and each piece caught in the explosion does either a recoil animation or a death animation. How well would your suggestion scale? \$\endgroup\$
    – AJM
    Commented Feb 17, 2011 at 0:52
  • \$\begingroup\$ @AJM It somehow seems to bother you that changes to the model are discrete while animations are "continuous" :-). It's perfectly fine though since actions in your game have a fixed outcome that is known beforehand. A counter example would be a realtime strategy game in which the logic and graphics components would be constantly updated independently from each other. \$\endgroup\$
    – Dave O.
    Commented Feb 17, 2011 at 5:07
  • 1
    \$\begingroup\$ @AJM I hope my edit answers some of your questions. \$\endgroup\$
    – Dave O.
    Commented Feb 19, 2011 at 0:56

You must log in to answer this question.

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