Many platform games or simulations involve building a grid of cells (or tiles) representing a simulated "world" where some characters can move within the grid.
This example show how simple it is to display grids with WinBGIm graphics and small GIF images. It also demonstrates how to move characters on the grid.
Ample comments in the example explain the sticky points.
Before we start
Download the example in a zip file: 
With Quincy the example can be built by loading the project gridTest[gridTest.exe].PRJ and building it.
___________
Three C++ classes:
The example is made up of 3 C++ classes, one BGI utility module, and a driver program:The Grid class represents a 2D array of Cells.
A grid object can draw itself to screen by asking each of its cells to draw itself in turn.
___________
The Cell class represents a small square area. A unit of grid. A cell object can draw itself when requested by the grid. It has a colour and it may also have a "tile" (a small GIF image that is displayed on the cell area).
In the example, 3 different tiles are used in various cells: the green "grass" tile
is used to represent grassed areas, red "brick" tiles
are used to display walls. A blue smiley "bob" tile
is used to represent a character that can move on the grid.
The cells are 20x20 pixels square, and the tiles are all 18x18 pixels squares, leaving 1 pixel at the side for a cell border. Using a 20x20 pixel tile would eliminate the borders. Smaller tiles may be needed for larger grids.
A number of variables of Cell are static (or class-wide) variables. This is for example the case of the tile images. All the individual cells that have the same appearance share the same class-wide ImageBuffer instance. This instance gets drawn repeatedly on the grid at all the various locations where that tile is needed. Having a single image per tile type for the whole Cell class, rather than having one separate image per Cell object offers great savings in memory space.
Static variables are created by the program before main() starts, so the ImageBuffer constructor for the tiles runs before the main window is initialized. This creates a small problem as ImageBuffers require a window for their initialisation. This is remedied by instantiating a global window variable before the ImageBuffer constructor is called (at the top of cell.cpp. After the imageBuffers are created, the small helper window is closed at the start of main() by a call to "closegraph()".
Note: This is a rare case when a global variable is useful.
___________
The ImageBuffer class is a low level class that manages the storage of images in memory. It can read image files to memory and it can draw the images on the screen. This is used by the cell to draw its "tile" image if it has been given one.
___________
The BGI_util module is not a class, but it contains a set of functions that make it easier to use the WinBGIm graphics library.
It contains a very essential function: synchronise(), that is used after each major drawing call to synchronise the active screen page and the visual screen page in a process called double-buffering.
Double buffering avoids flickering of the screen during fast drawing.
In double buffering, two page "buffers" are used. The image is drawn by the program in the background on the active page buffer. The visual page is what the user sees and does not change during this background drawing. When all the background drawing is done, the synchronise() function swaps the two pages. At that stage the changes to the drawing become visible. synchronise() then copies the new drawing to the other page so the two page buffers end up containing the same image.
___________
The driver, gridTest.cpp initialises the graphics window and creates a small 10 x 10 cells grid. The grid in this small example is defined by a simple mathematical formula that creates something that looks a bit like a game or maze grid.
In a typical application the grid structure (its array of cells that represents the "game world") is more likely to be read from file.
After this initialisation, the program goes into its animation loop.
At the beginning of each cycle in the animation loop, the character (Bob here) decides where to move, then the cells that have changed are redrawn. In this simple example, the old "Bob" cell is overdrawn by a "grass" cell, then the "Bob" cell is drawn over a grass cell at its new location.
Communication between classes:
The Cell does not know about the Grid, or the window.
This is a good design. Low-level classes, like Cell, should not know anything about other programs or classes that may use it. Cell therefore does not know its own coordinates on the window or on the grid. As a solution to this, the Cell draws itself on request from the grid. The grid can give the cell its window coordinates as function parameters when it calls the draw() Cell function.
- WinGBIm is a basic graphics drawing package that emulates one of the most successful graphics libraries of all times, the Borland Graphics Interface (BGI). WinbGIm adds some extra facilities, like the possibility of catching mouse clicks and mouse position.
The success of BGI was due to its simplicity.
The code of graphical programs produced with WinBGIm is very simple, compared to that of other graphics packages.
Basic help about functions available in the WinBGIm library is given by the Quincy menu: Help->Programmer's Help.
______
- You'll understand really well how this code works if you implement your own modifications and extensions to the grid example.
