Topic : Tiling in DirectX: Part 2
Author : Martin Estevao
Page : 1 Next >>
Go to page :


Tiling in DirectX: Part 2
by Martin Estevao


Introduction
Ok, folks, welcome back! In this second installment of "Tiling in DirectX," I plan to expand on the topics presented in the first article, which you can find in the tutorials section of this site. Due to lack of time I'm only going to cover smooth scrolling in this article. This might disappoint some of you, but please realize that with school and my own projects I have increasingly little time. Sorry.

Smooth Scrolling
If you remember from reading Part I, we set up a simple tile engine that took a map from a 2-dimensional array and blitted the tiles to the screen using DirectDraw's BltFast(). We can't stop now! I think we're ready to take the big step into producing a scrolling world effect for your games. Don't feel that this step is daunting in any way. It's actually pretty easy once you understand the concepts.

For those of us who don't know what I mean by "smooth scrolling," I am referring to the effect made when a tile-based background behind the sprites in a game moves. This creates the illusion that the main character (or whatever you are controlling in your game) is travelling from one spot of the world to another, although he may be blitted to the same location on the screen at times. Think Super Mario Bros, which is an example of a scrolling world. Get it?

The Concepts
The key to scrolling is to keep track of where the heck you are in your large tile world, and therefore which tiles in your map to draw to the screen. For example, suppose that after the right arrow on the keyboard is pressed the sprite in your game has to "move" to the right in your map by two tiles. In your tile drawing function, you would have to recognize this change and blit a set of tiles to the screen that have been shifted by two tiles in the array, or, say 64 pixels in the world, to the right. As a result, your sprite appears to move as your tile world behind it changes. I'm sorry if this explanation is hard to understand, but I hope this concept will become clearer as we continue.

As you will see in a bit, we'll create two variables to store this information and the amount of change that has taken place in the map. These two variables will be used in our final version of the draw_tiles() function to decide which tiles in our world to draw to the screen.

As far as concepts go, that's about it. If you have these ideas down pat, you're ready to put this stuff into code.

Setup
Before we rewrite the draw_tiles() function, we have to provide some defines and globals.


#define TILE_SIZE       32
#define WORLD_SIZEX     20
#define WORLD_SIZEY     20
#define SCREEN_SIZEX    12
#define SCREEN_SIZEY    12



Here we defined the size of each tile as 32 pixels, the world size (in tiles) as 20 * 20, and the screen size (also in tiles) as 12 * 12. As a result, we'll have 12 * 12 (144) tiles viewable at a time on the screen, while there are 20 * 20 tiles total in our array. We had to make the map bigger than the screen viewable size so that we can witness the scrolling in action. Note: Depending on the resolution that you set for your DirectX app, you will probably not see the whole screen filled with tiles.


int world_camerax = 0;
int world_cameray = 0;



world_camerax and world_cameray, as I mentioned in the Concepts section, are the two variables that will keep track of the position in our world. They will be used together to determine which tiles in the total map array will be blitted to the screen. Right now, we'll initialize them to 0 so our current position is at (0, 0), or the top-left corner of the world/array. world_camerax will store the position in x coordinates, or the distance from the starting point 0. world_cameray will store the position in y coordinates, or the distance from the starting point 0. Again, if you have any problems understanding this, go back and read the Concepts section a couple times. If you're still having trouble, then it's probably my fault. :)

The last thing that we have to do before re-writing the draw_tiles() routine from Part I is to define our new world (20 tiles * 20 tiles), which will be larger than the last array from tutorial I.


char map[WORLD_SIZEY][WORLD_SIZEX] = {
     {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
     {2, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
     {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2},
     {2, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
     {2, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
     {2, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
     {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, };



Pretty large world we've got here, along with a little message. :)

Drawing the Smooth Scrolling Tiles
Now to rewrite the draw_tiles() routine.


void draw_tiles(void)
{
  int tile;
  int x, y;
  int scroll_x, scroll_y;   // (NEW)
  int offset_x, offset_y;   // (NEW)


  RECT tile_src;



tile is going to be used later in determining if the tile map[scroll_y][scroll_x], for example, has an ID# of 1 or 2 when we go through the loop of the map array. x and y are the two variables used in drawing the tiles at their appropriate locations. The RECT tile_src is going to specify which graphic is going to be used at each tile location, pointing at the offscreen surface. Whe

scroll_x and scroll_y will serve the function that the regular x and y variables served in the draw_tiles() function from Tutorial 1. You may be asking, "Why can't we just use x and y again?" Good question. The answer is that some calculations have to be done with the "world camera" that include the x and y variables, as you will see in the next steps, so the product of these calculations will be placed in scroll_x and scroll_y so that we can still use x and y, with their original values, for the blitting of the tiles.

offset_x and offset_y will be used in determining the very fine, or precise location to draw our

Page : 1 Next >>