Jump to content
  • Advertisement
Sign in to follow this  
TheDarkRider

A better way to do this?

This topic is 3126 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I've just finished reading a C++ Programming book, and thought of testing my newly earned skills in making a small game so I decided to make Pacman. But I have a question. I have simulated the maze using a 2-Dimensional array like this:
unsigned char maze[24][21] = {
		{'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'},
		{'_','1','1','1','1','1','1','1','1','1','_','1','1','1','1','1','1','1','1','1','_'},
		{'_','4','_','_','_','1','_','_','_','1','_','1','_','_','_','1','_','_','_','4','_'},
		{'_','1','_','_','_','1','_','_','_','1','_','1','_','_','_','1','_','_','_','1','_'},
		{'_','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','_'},
		{'_','1','_','_','_','1','_','1','_','_','_','_','_','1','_','1','_','_','_','1','_'},
		{'_','1','_','_','_','1','_','1','1','1','_','1','1','1','_','1','_','_','_','1','_'},
		{'_','1','1','1','1','1','_','_','_','2','_','2','_','_','_','1','1','1','1','1','_'},
		{'_','_','_','_','_','1','_','2','2','2','2','2','2','2','_','1','_','_','_','_','_'},
		{'2','2','2','2','_','1','_','2','_','_','1','_','_','2','_','1','_','2','2','2','2'},
		{'_','_','_','_','_','1','_','2','_','2','2','2','_','2','_','1','_','_','_','_','_'},
		{'5','5','5','5','5','1','2','2','_','2','2','2','_','2','2','1','5','5','5','5','5'},
		{'_','_','_','_','_','1','_','2','_','_','_','_','_','2','_','1','_','_','_','_','_'},
		{'2','2','2','2','_','1','_','2','2','2','2','2','2','2','_','1','_','2','2','2','2'},
		{'_','_','_','_','_','1','_','2','_','_','_','_','_','2','_','1','_','_','_','_','_'},
		{'_','1','1','1','1','1','1','1','1','1','_','1','1','1','1','1','1','1','1','1','_'},
		{'_','1','_','_','_','1','_','_','_','1','_','1','_','_','_','1','_','_','_','1','_'},
		{'_','4','1','1','_','1','1','1','1','1','2','1','1','1','1','1','_','1','1','4','_'},
		{'_','_','_','1','_','1','_','1','_','_','_','_','_','1','_','1','_','1','_','_','_'},
		{'_','1','1','1','1','1','_','1','1','1','_','1','1','1','_','1','1','1','1','1','_'},
		{'_','1','_','_','_','_','_','_','_','1','_','1','_','_','_','_','_','_','_','1','_'},
		{'_','1','_','_','_','_','_','_','_','1','_','1','_','_','_','_','_','_','_','1','_'},
		{'_','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','_'},
		{'_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_','_'}};
and here is the definition of each element of the array:
enum MazeID
{
   OBSTACLE    = '_',
   BEANS       = '1',
   NO_BEANS    = '2',
   POWERBEAN   = '4',
   TUNNEL      = '5',
};
Now i want to make a level designer so i wanted to parse and display the maze dynamically, so if i change anything in the maze i wouldn't have to change any of the code. so i draw it like this:
void Maze::Draw()
{
	LOGPEN lPen = {0};
	lPen.lopnColor = 0x00C00000;
	lPen.lopnWidth.x = 5;
	lPen.lopnWidth.x = 5;
	HPEN hPen = CreatePenIndirect(&lPen);
	HPEN hOldPen = (HPEN)::SelectObject(m_hDC, hPen);

	unsigned int startingPointX = 0;
	unsigned int startingPointY = 0;

	unsigned int blocksize = 21; // width and height of the pacman/ghost sprite

	for(int i = 0; i < 24; ++i)
	{
		for(int j = 0; j < 21; ++j)
		{
			startingPointX = (j+1) * blocksize; // for each OBSTACLE element it increases the horizontal line by blocksize(21)
			startingPointY = (i+1) * blocksize; // for each OBSTACLE element it increases the vertical line by blocksize(21)

			// draw obstacles
			if(m_Maze[j] == OBSTACLE)
			{
				// draw horizontal obstacles only if next horizontal block has 0
				if(m_Maze[j+1] == OBSTACLE)
				{
					MoveToEx(m_hDC, startingPointX, startingPointY, 0);
					LineTo(m_hDC, startingPointX + blocksize, startingPointY);
				}

				// draw vertical obstacles only if next vertical block has 0
				if(m_Maze[i+1][j] == OBSTACLE)
				{
					MoveToEx(m_hDC, startingPointX, startingPointY, 0);
					LineTo(m_hDC, startingPointX, startingPointY + blocksize);
				}
				
			}
		}
	}

	SelectObject(m_hDC, hOldPen);
	DeleteObject(hPen);
}
However this works just fine but i feel its ugly. so is there any better way to achieve this? Any comment would be highly appreciated. Please let me know if there anything unclear in the above ugly code. And by the way, what books related to Game Programming do you recommend? Regards

Share this post


Link to post
Share on other sites
Advertisement
To be honest that's about as good as the code is ever going to look. Data loading code isn't really something that can be made to look elegant, it's generally just kinda laborious.

Share this post


Link to post
Share on other sites



You could load that data as strings (omitting the extra cluttery commas and single quotes) and have every other character be a space/blank to try to get a reasonable aspect to the grid appearance (for readability)

You could use char values that mnemonicly match the actual map tiles:

O B N P T (maybe the obstacle could stay - and the NO_BEAN as a blank

You would then read those strings into your working array converting them to whatever was most efficient ( ordinals rather than chars... but for this it probably doesnt make a difference )


"----------------------------------------------"
"--B B B B B B P B B B B --
"-- ---------- -------------- ---------- --"
etc....

Share this post


Link to post
Share on other sites
Here's some ideas.


class Maze
{
enum TileType
{
SPACE,
OBSTACLE,
BEANS,
POWERBEAN,
TUNNEL
};

const int BLOCKSIZE = 21; // Should this be in a seperate graphics class?

int m_width, m_height;
std::vector<TileType> m_map; // Use a std::vector to hold the map

Maze(int width, int height) : m_width(width), m_height(height), m_map(width * height) {} // The map vector starts empty (all tiles set to SPACE)

TileType TileAt(int x, int y, TileType outOfBounds = SPACE) const
{
return x >= 0 && y >= 0 && x < m_width && y < m_height ? m_map[x + y * m_width] : outOfBounds; // If the co-ord is in range, look in the map, otherwise return a default value
}


// ...

void Draw(HDC hDC) const // Pass in the DC instead of making it part of Maze state, and be const-correct
{
HPEN hPen = CreatePen(PS_SOLID, 5, RGB(0, 0, 0xC0)); // Don't use indirect function, and use proper macros and enums
HPEN hOldPen = reinterpret_cast<HPEN>(SelectObject(hDC, hPen)); // Use C++ casts, and no need to explicitly specify scope (unless you really do have a symbol clash)

HBRUSH hObstacleBrush = CreateSolidBrush(RGB(0, 0, 0x30)); // Brush for filling obstacles

for(int y = 0; y < m_height; ++y) // Enumerate over whatever dimensions are needed, don't hardcode them in
for(int x = 0; x < m_width; ++x)
{
const RECT rcTile = {x * BLOCKSIZE, y * BLOCKSIZE, (x + 1) * BLOCKSIZE, (y + 1) * BLOCKSIZE}; // For easy GDI operations

switch(TileAt(x, y)) // Use an accessor method to get tiles at locations
{
case SPACE:
break;

case OBSTACLE:
FillRect(hDC, &rcTile, hObstacleBrush);
MaybeDrawObstacleWall(hDC, x - 1, y, rcTile.left, rcTile.top, rcTile.left, rcTile.bottom);
MaybeDrawObstacleWall(hDC, x + 1, y, rcTile.right, rcTile.top, rcTile.right, rcTile.bottom);
MaybeDrawObstacleWall(hDC, x, y - 1, rcTile.left, rcTile.top, rcTile.right, rcTile.top );
MaybeDrawObstacleWall(hDC, x, y + 1, rcTile.left, rcTile.bottom, rcTile.right, rcTile.bottom);
break;

// Other tile type cases here...
}
}

DeleteObject(hObstacleBrush);

SelectObject(hDC, hOldPen);
DeleteObject(hPen);
}

void MaybeDrawObstacleWall(HDC hDC, int nx, int ny, int xStart, int yStart, int xEnd, int yEnd) const
{
if(TileAt(nx, ny) != OBSTACLE)
{
MoveToEx(hDC, xStart, yStart, NULL);
LineTo(hDC, xEnd, yEnd);
}
}
}


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!