Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Adventures In Abattoirville

0.00/5 (No votes)
31 Jul 2001 2  
A Maze based game.
Alternate Title The game

To run this game you need DirectX 8. Even though I don�t use any direct X 8 functionality. You could modify the code around Dinput and use older version of DirectX. The game runs at 1024x768 resolution.

To compile this program you need VC++ 6 and the DirectX8 SDK. If you run into problems call Microsoft Support.

Now for the interesting coding stuff. I am only going to discuss two classes here. Some of the other classes are described in the DirectX 8 SDK and Advanced 3D Game programming book.

The CMaze class

This class takes care of reading a text file and displaying the Maze. The constructor takes the name of the texture, which will be used to display the lines.

CMaze(char* pszTextureBMP);

You load the text file calling the LoadMaze method. The Maze text file is in the format

(Name)
(Number of Horizontal lines)
(Vertical Coord) (Horiz Coord Start) (Horiz Coord End)
(Vertical Coord) (Horiz Coord Start) (Horiz Coord End)
.
.
(Number of Vertical Lines)
(Horiz Coord) (Vert Coord Start) (Vert Coord End)
(Horiz Coord) (Vert Coord Start) (Vert Coord End)
.
.
(Number of Deploy points)
(Deploy Point X) (Deploy Point Y)
(Deploy Point X) (Deploy Point Y)
.
.

(Name) is any name you like to give to this level and it appears at the bottom in my game. Horizontal and vertical lines are those displayed in the game to make the maze. The Deploy points are the points at which enemies or food can appear.

The dimensions of the texture determines the width of the line you give the maze class. If you call the method DisplayGrid you will see how the maze screen is divided. If the deploy location is 1,1 then the actual screen location is (1* WidthOfTtexture, 1 * HeightOfTexture). To see the deploy locations you need to call DisplayDeployRects and pass it the size of your sprites so that it can draw a rectangle for you.

The IsHit method takes a rectangle and return true if it collides with any of the lines in the Maze. The line is actually a rectangle where the dimensions are determined by the Texture size.

GetPathFindingArray takes an array and fills it with 1�s or 0�s based on if there is a line present or not. This is useful in creating an array that represents the maze so that it can be used with path finding algorithm. This function is not used in this game although if you use it in conjunction with a path finding algorithm it can make this game very difficult.

The CSprite class

This is the most interesting class in this game. It takes care of animating and moving the sprites around. You create a sprite by calling

void CSprite::CreateSprite(CSurface** ppSurface, long nType,long nHeight, long nWidth)

The surface contains the images for the sprite, Type is user-defined data and you give it the dimensions of the sprite. Sprite can have different states like Walking left or Walking Right. You call AddState with all the different states you have for a given sprite.

void CSprite::AddState(long nState, POINT ptFrame, long nNoOfFrames, long nDelay, 
                       RECT* prcBound, LPTSTR pszSound, bool bLoopSound)

nState is how you will identify this state. You would later on call SetState with this number to set the sprite to this state.
ptFrame is the point on the Surface which contains the first image for this state. We don�t need the dimensions here because it is fixed for a sprite and you gave it when the sprite was created.

nNoOfFrames is the number of frames for this state. Example if walking left has three animation images then nNoOfFrames would be 3.

nDelay is the rate at which the animation is changed. nDelay is a unit of time, this unit is determined by how often update is called. You can think of the unit as the game pulse. Your game may have 60 pulses per second, it all depends on how often your main game loop calls the sprites update method.

prcBound is the bounding rectangle used for collusion detection. When you call IsHit, if the give rectangle intersects with the bounding rectangle then it is a hit.
Each state can have a sound associated with it also.

void CSprite::SetAnimBiDir(bool bIsAnimBiDir) is used to make the animation frames bi-directional. If your animation has 4 frames then the order would be 1 2 3 4 3 2 1 if this is set to true.

void CSprite::EnableBorder(bool bDraw = false) displays the borders and the bounding rectangle of a sprite. It is useful for debugging.

struct SMovement {
	long m_dx,m_dy;
	long m_nMoveDelay;
	long m_nCurrMoveDelay;
	bool (*m_pfnCollision)(RECT& rcRect);
	long m_nInvulnerable;
	long m_nPathFindDelay;
	long m_nCurrPathFindDelay;
	void (*m_pfnFindPath)(CSprite* pSprite);
} m_Movement;

This structure controls the movement.

m_dx and m_dy are the rate and direction in which the sprite should move. It calls the function pointed by m_pfnCollision to see if the new location is free. If there was a collision then the function pointed to by m_pfnFindPath is called to get a new direction to move to.

The prototype for collision detection and path finding function is

bool fnCollision(RECT& rcRect);
void fnFindPath(CSprite* pSprite);

m_nInvulnerable is the delay for which a sprite should no be killed and the sprite will flicker in the display.
m_nPathFindDelay is the rate at which the path finding function is called to update the direction of movement.
If you need Update to automatically move the sprite then fnCollision and fnFindPath should point to some function. There is no point in moving sprites if there is no way of knowing if the given location is valid. Update should be called for all the sprites in the game loop every time. This takes care of updating the location and animation of the sprites.

You kill a sprite by calling SetState(ST_KILL), this results in a call immediately to the function pointed to m_pfnKill. This function is optional. The prototype is

bool fnKill(CSprite* pSprite);

if fnKill returns false, the state is not set to KILL and SetState returns. In this game this function is used to go to the next level when the player touches the Door.

If the Kill proceeds then it displays the dying animation and once it is done it will call the function pointed to by m_pfnDead, which has the prototype

void fnDead(CSprite* pSprite);

You can use this function to update the score, create a new enemy, etc.

And finally

void CSprite::Draw(LPDIRECTDRAWSURFACE7 pdds)

Draws the sprite to the given surface.

 

Let me know if you made some cool games reusing this code.

Click here to go to the game web site

History

1 Aug 2001

  • "Choice screen" displays game controls.
  • Fixed Memory leak issue in CSprite.
  • Memory Leak in dsutil.cpp was fixed by Microsoft. They will roll out the fix in the next release of SDK.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here