A lot of our basic model is coded. We can take a crack at the graphics now. Too keep things simple we should focus on the 2-dimensional graphics for the game grid and cells. We'll delve into the user interaction later. We'll code something simple and then layer-on features and complexities as we develop.
A good place to start would be working out how we will draw cells. We can start with a blank cell and then create the target and mirror cells.
What do we know about the graphics for one of our cells? It's square. We haven't made a decision about its size yet. A cell should have a border. We can set a simple color for the cell background.
We will use Morphic for the game itself but at some point we'll need to make a decision about drawing of the elements. We can use a SketchMorph, which contains a Form for its graphics, but how far should we go? For example, if we make a Morphic object for the game board (the visual representation of our Grid) and more Morphic objects for each cell, that's a reasonable approach.
We could also have one SketchMorph for the game board and then have the cells draw themselves on the game board form.
For example, the cells could just be responsible for drawing their features (borders and walls) onto the target game board form at the specified location. That location could be calculated by either the board or the cell. What responsibilities would the board then push down to the cells? The cell models manage state for themselves. The board has a model too which is the grid. So really the board is the graphic representation of the grid and its cell's models.
Let's try that approach. Let's have the cells draw on the board form. How about if we create an object that knows how to render cells on the board? A CellRenderer. The instance variables would be the cell model, the grid model and the board form. We can ask the board form its extent and calculate the sizes of cells to be rendered. The renderer could have subclasses for each cell class and identify the model class in a method.
Since the renderer will have an instance variable containing the grid, it really only needs the location of the cell within the grid for its cell instance variable.
Here's the basic rendering class.
It has the three instance variables mentioned. Create the accessors for these before continuing. We can create a rendering hierarchy.
Just like we did before with the grid direction hierarchy design, each subclass provides how it will be selected. Here is the class method for the blank cell renderer.
The mirror and target cell renderers do the same thing.
The technique to find the proper renderer for each cell is simple.