mardi 15 septembre 2020

Best practices : Design pattern for managing view-level informations

This question is about best-practices in design and classes organization for a game. (language independant)

Let's say I'm developping a chess game. I may have a model representing the game board and pieces in several classes. I'll certainly have a class called Piece, which will represent a piece. This class may have the following attributes :

int boardX
int boardY

These attributes will represent the position on the board, using the squares frame coordinates (square (0,0) to square (7,7)). From the game modelization perspective, a piece must be on one specific square (that means it can't be astride two squares).

When the game controller will operate some action on the game, it will call some function of the model that will immediately change one piece position.

That's the model point of view. Now, let's talk about the View (in the MVC pattern).

The view will render the board and pieces on it. It may have a reference of the game model, register model events, and fetch pieces positions. To render the whole scene, the view will draw a static board, and will iterate through the game model to draw all pieces belongs to it. Coordinates from the board frame (square unit) will be converted to the view frame (pixel unit) So far so good.

Now let's imagine you want to add animations, so one piece move will take one second to accomplish.

The view has a reference to the game model, but the game model doesn't have the real position of the piece during its movement (in pixel). So we'll need a new class for managing the pixel position of the piece during its move. Let's call it GraphicPiece, containing a reference to the underlying Piece, and two attributes :

int pixelX
int pixelY

Now before asking the questions, in this example, I used a chess game with a trivial example, but consider a complex game model with multiples item types, and with relations between these, regularly updated.

Q1 : where does instances of GraphicPieces should be stored ? Should I make a View-oriented duplicate of the game model storing only view informations (called game view-model ? If so, how could the view-model be synchronized with the game model that is heavily changing its content ?) In addition, during the animation, the view-model will be un-synchronized with the logical model state ; that can lead to undesired behaviour (using some information from unsynchronized view-model AND model)

Q2 : When the view will render, it will use the game model to iterate through pieces (Piece class) that must be rendered and so on. But from the Piece class, there is no way to find the corresponding GraphicsPiece containing real pixel positions. Using a Map<Piece,GraphicPiece> is over-killed and not acceptable for performance reasons.

Q3 : Piece class can't have a reference to a GraphicPiece because that's breaking isolation between logic and display. If worst comes to worst, a Piece class can have a generic pointer or Object that will contain a GraphicPiece and will be downcasted, but it's really not a beautiful solution.

Q4 : Summary question : Which design may be the best for a view to render a (game) model, that will need many informations (of display level) related to the potentially complex (game) model ? On which object/model the view should iterate to render and access all information it need ?

I hope I had clearly explained the problem. Thanks at least for having read !

Aucun commentaire:

Enregistrer un commentaire