• No results found

The Main.cpp Program File

The main.cpp file isn’t too complicated, as it follows the DirectX frame-work application pretty well. The first class function of interest is the class constructor. It is as follows:

CD3DFramework::CD3DFramework() {

m_strWindowTitle = _T("2D Tile Example");

m_pStatsFont = NULL;

As you can see in this code, the tile map’s size is set in the class con-structor. I set the width and height to 10 so that the map fills the entire window when rendered. The tiles are 48 pixels wide and 48 pixels high, so I set the size of the window to 480 by 480. 10 * 48 = 480, so this is the proper size to have a perfect fit.

The next block of code of interest handles the initialization of the tile map.

HRESULT CD3DFramework::OneTimeSceneInit() {

m_pStatsFont = new CD3DFont(_T("Arial"), 8, NULL);

if(m_pStatsFont == NULL) return E_FAIL;

// Clear out the map with the grass tile

memset(m_iTileMap, 0, (m_shTileMapWidth*m_shTileMapHeight) * sizeof(int));

// Fill the second half with beach tile for(int i = 0; i < 50; i++) {

m_iTileMap[i+50] = 3;

}

// Randomly place rocks on the grass // Seed the randomizer

// Place the grass edging along the beach tiles for(i = 50; i < 60; i++) {

m_iTileMap[i] = 2;

}

return S_OK;

}

The first line of interest in the code above is the call to thememset() function. This piece of code clears the tile map by setting all tiles to equal 136 n Chapter 5

0. The 0 texture happens to be grass; therefore, this code clears the map with grass tiles.

The next block of code runs a loop and sets the bottom half of the map to contain tile 3. Tile 3 is a beach texture; therefore, this code sets the bottom half of the map to contain beach tiles.

Next up for bid is the section that randomly places rock tiles on the upper half of the map. The rock tiles are there for decoration; therefore, their position isn’t very important. I use therand()function to deter-mine rock density.

Lastly, the code places a line of grass-beach edging tiles along the middle of the map. This provides a nice transition from the grass to the beach tiles.

Play around with setting different tiles in the initialization code. You may want to make patterns out of it or whatever. Now is your chance to set the tile values and see the result.

I’m skipping down a bit to theRestoreDeviceObjects()function.

This is important, as it contains the texture initialization code. The fol-lowing code snippet initializes the textures:

sprintf(szFileName,"grass00.bmp");

The texture initialization code utilizes DirectX’s utility function named D3DXCreateTextureFromFile(). It’s a really cool function, as it handles all of the code to load various types of images such as BMPs, TGAs, and JPEGs. To use it, you need to include the d3dx9.lib library along with the d3dx9tex.h header file. Its prototype is as follows:

HRESULT D3DXCreateTextureFromFile(

The first parameter,pDevice, requires a pointer to the Direct3D device that you are utilizing for your rendering. In the code used for this exam-ple the device is pointed to from them_pd3dDevicemember variable. So, use it for the first parameter.

The second parameter,pSrcFile, expects the name of the texture file to load. This parameter is not very complicated, as all you have to do is give it the stringified name of your file. You do not need explicit path information as the function tries to find the texture file in the current directory. If you need to point to a different directory, you may want to read in a registry setting to retrieve the path. Personally, I just use subdi-rectories from the main program. This method allows for multiple directories without the headache of registry settings.

The last parameter,ppTexture, requires a pointer to a texture. If you recall back to my coverage of the header function, you remember that I am using them_pTexturearray to hold the texture pointers. I use an index into the texture array for this parameter. For example, texture 1 usesm_pTexture[0], texture 2 usesm_pTexture[1], and so forth.

The last part of the texture initialization routine calls the

vInitTileVB()function. This function initializes the virtual buffer to hold the 3D tile information and does nothing else.

Move back up in the code to theRender()member function. This is where the magic happens. Please ignore the man behind the curtain! The code is as follows for the rendering logic:

HRESULT CD3DFramework::Render()

for(iY = 0; iY < m_shTileMapHeight; iY++) { // Horizontal

for(iX = 0; iX < m_shTileMapWidth; iX++) { // Figure out which tile to display

iCurTile = m_iTileMap[iX + (iY * m_shTileMapWidth)];

// Figure out the on-screen coordinates fTileX = -240.0f+(iX*48.0f);

138 n Chapter 5

fTileY = 192.0f-(iY*48.0f);

// Display the tile

vDrawTile(fTileX, fTileY, 48.0f, 48.0f, iCurTile);

} }

// Show frame rate

m_pStatsFont->DrawText(2, 0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats);

// Show video device information

m_pStatsFont->DrawText(2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats);

The first part of the code calls theClear()function. TheClear() func-tion belongs to the Direct3D device and is used to clear the 3D rendering plate. I clear the view buffer to a medium gray color. You can pick what-ever color you want; it doesn’t really matter since the view area is filled with tiles.

The next call made is to theBeginScene()function. This function starts up the rendering engine of the 3D system. You must call it before performing 3D graphic operations.

6

Warning You must start your rendering with BeginScene() and end it with EndScene(). If you do not, you can crash your program.

Now the fun part begins. The next chunk of code deals with the render-ing loop required to display the tiles. There are two loops; the first one loops through the tile map from top to bottom, and the inner loop loops from left to right. The combination of these two loops results in coverage of the entire tile map.

The first line of code in the inner loop deals with figuring out the tile to render. It stores this value in theiCurTilevariable. The tile to render is calculated by adding the inner-loop value to the outer-loop value times the width of the map. You probably remember this formula from earlier in the chapter. Armed with the tile value, you now know which texture to render.

The next part figures out where to place the tiles on-screen. Since the program uses 3D space, it has to offset the tiles using floating-point values. The window created by the program measures 480 pixels across and tall. With this in mind, the tiles must start 240.0 units to the left in order to be flush with the edge. To be flush with the top of the window, the tiles must start at 240.0 – 48.0, or 192.0 units from the origin.

II

Part

The next piece of code calls thevDrawTile()function that I wrote.

The prototype for the function is as follows:

vDrawTile(

float fXPos, float fYPos, float fXSize, float fYSize, int iTexture)

The first parameter,fXPos, expects the x-coordinate at which to draw the tile on-screen. It is a floating-point unit and specifies the location in 3D space along the x-axis. Do not confuse this with pixel coordinates.

The next parameter,fYPos, is just like the first parameter, except this one corresponds to the y-axis in 3D space.

The next two parameters,fXSizeandfYSize, set the size of the tile to display on-screen. You can set the size to whatever you wish, as the function scales the tile accordingly. For this demo, the tile size is 48.0 units.

The last parameter expects an index into them_pTexturetexture array. This parameter sets the texture to render.

Once thevDrawTile()function is called, the tile appears in the dis-play buffer. All that is left to do is output the frame rate and video card information and then display the scene. All of this is accomplished in the remaining render code.

See, that wasn’t so bad, was it? To see the program flow illustrated, check out Figure 5.40.

140 n Chapter 5

Figure 5.40: Program flow of the 2DTiles example program.

In the figure you see the flow of the program from initialization to render-ing to cleanup. That about wraps it up for 2D tile renderrender-ing for now. It’s time for isometric rendering!

Related documents