Here is a rough outline of how I see this program working :
- We predefine the game objects - there are not that many and most are always in use, so no faffing about creating stuff on the fly.
- Make a list of the game objects which we can use to access the objects with a simple loop.
- Write a simple loop that runs through the list and calls a control function depending on what type the game object is.
- Throw in another simple loop which runs through the list and slaps the graphics on to the screen.
- Add the control functions for each the object types at our leisure.
This way we can start with a list just containing Robbie. Once we have him whizzing about we can add a bug(creepy crawly) and get that functioning. Then maybe a spray can, and so on.
So then we will have a program structure we can build on without suffering brain melt down. We only have to grapple with little chunks of the game at a time, while knowing (hoping ?) it is all going to hold together in the end.
I have added a file called objects.h to the project. This contains the proprosed structure for the game objects. I have called it 'object' and hopefully the comments will give you all the information you need to know. I have also created some of the values the objects will use, using good old enum so I don't have to type lots of tedious numbers.
CODE
#include "SDL\SDL.h"
// This holds information to describe and control our objects
struct object {
int iType; // object type identifier
int iSubType; // object subtype identifier
bool bDraw; // only put this on the screen when this true
int iPhase; // the current phase - init, dieing etc.....
int iFacing; // currently facing - east/west
SDL_Rect C_Screen; // current screen position
SDL_Rect G_East; // graphic for east facing object
SDL_Rect G_West; // graphic for west facing object
SDL_Rect C_FrameG; // current animation frame graphic
int iAnimCount; // current animation count
int iAnimFrames; // number of animation frames
int iAnimOffset; // animation offset into graphic
struct object *oEmbed; // if another object is embedded - this points to it
struct object *oAbove; // if another object is above - this points to it
struct object *oBelow; // if another object is below - this points to it
struct object *oRight; // if another object is right - this points to it
struct object *oLeft; // if another object is left - this points to it
};
// used to signal if an object facing east of west
// I envisage using this to determine which side of Robbie his spray can should appear
enum directions {
WEST,
EAST,
};
// object ids so we know what the object is
enum types {
ROBBIE,
STEM,
LEAF,
BUD,
BLOSSOM,
SPRAY,
WORM,
SPIDER,
WASP,
SPRAY_CAN,
BONUS
};
// secondry ids - if the object is a leaf we can generally ignore it but the
// leaf itself will want to know which one it is so it knows where to grow
// The bonus is just a bonus but the bonus itself will want know if it is pretending
// to be an oil can, a ruby or a coin.
// Worms, spiders and wasps are a bad thing. They kill us and in that respect
// are all the same. If we check the subtype and it is a bug we know to die without
// tediously checking for each type - is it a worm ? is it a wasp ? etc....
enum subtypes {
SINE,
CLOUD,
DROPLET,
RED,
WHITE,
BLUE,
RUBY,
COIN,
OIL,
LEAF1,
LEAF2,
LEAF3,
LEAF4,
LEAF5,
BUG
};
// The following are possible states the items will be in at different times
// An object will use a state to behave in a particular way until something happens
// to change its state. It will then behave in the required manner for the new state
// until conditions require it to change state again
enum phases {
INIT,
INACTIVE,
WAIT,
PICKED,
CARRIED,
GO_EAST,
GO_WEST,
GO_UP_EAST,
GO_UP_WEST,
GO_DOWN_EAST,
GO_DOWN_WEST,
GO_TO_PLANT,
GO_TO_ROBBIE,
MOVE,
FIRE,
FROZEN,
EXPIRE,
};
You may have noticed that some of the members in the object structure are themselves struct objects. You may be thinking that when we use it to declare an object we will end up creating an infinite progression of structures of the type 'object'. In fact, what we have here, are pointers to structures of this type,
not the actual structures themselves.
A pointer is just the stored memory address of something we want to know the address of. What we are doing is saying we will want to store the addresses of other items that are of the data type 'struct object' in these stores. The asterisk (*) before the name defines it as a
pointer to a data type and not an
actual data type. Pointers have been known to confuse people (me especially). I have known programmers who avoid using them altogether, but in fact they are pretty handy.
You can fiddle with an object through a pointer to it. Instead of directly addressing a stucture's member as 'struct.member', using a pointer we address it as pointer_to_structure->member. So the '.' becomes'->'. If we were to manipulate the pointer as if it were the actual structure it would be like talking to a 'phone number instead of the person who's number it is.
Confused yet ? You will be. Tune in next time when you can copy and paste more stuff into code::blocks and discover new ways to make real programmers shake their heads and make tutting sounds.