< disclaimer >
No part of this article may be reprinted or duplicated in any manner without prior written permission by the Author, Jim Adams with one exception- You may display it unmodified on your Web Page for free public viewing. It must include credits to author, Jim Adams.
The author, Jim Adams, will not to be held responsible for any damages, directly or indirectly, resulting from the use of this file or it's information.
< /disclaimer >
[size="5"]Introduction
Well, here's another attempt at bringing a little information into the world that seems to be a problem for some of you out there. This article will quickly go over scrolling a map view using a tile engine.
I will not be showing how to make a tile blitting routine. If you're reading this, I'm assuming you already have one. What I will be showing is a way to use your tile blitter to render a view, and a very simple one at that. It will consist of one layer.
Also - I didn't have time to add some graphics, but if I get some response, I'll put it in html format and add some pictures.
With that all said, let's get on with it, shall we?
Jim Adams
[email="tcm@pobox.com"]tcm@pobox.com[/email]
[size="5"]Map Structure
As I mentioned, we'll use a very simple one layered map. It will consist of one thing - the tile number to draw at that location. Let's say you have 256 tiles, numbered 0-255.
typedef struct {
unsigned char tile_number;
} MAP_INFO;
#define MAP_HEIGHT 128
#define MAPWIDTH 128
MAP_INFO map[MAP_HEIGHT][MAP_WIDTH];
Our map can be stored inside a PCX file, with a 128x128 image representing it. Each color palette entry (0-255) would represent the tile number to draw. If you have a standard PCX reader, just load a map like:
signed short map_load(char *pcx_filename)
{
char *pcxmapbuf;
short i, j;
if(pcx_loadimage(pcx_filename, pcxmapbuf) == -1)
return -1;
for(i = 0; i < 128; i++) {
for(j = 0; j < 128; j++)
map[j] = get_pixel(pcxmapbuf, j, i);
}
free(pcxmapbuf);
return 1;
}
From there you should have a map in memory along with your tiles. I'll assume you have your tiles in an array. I'll use a structure array for example. You should be able to follow along.
#define NUM_TILES 256
TILE_INFO tiles[NUM_TILES];
void map_draw(short mapx, short mapy)
{
short i, j;
for(i = 0; i < 15; i++) {
for(j = 0; j < 20; j++)
tile_draw(map[mapy + i][mapx + j].tile_number, j * 16, i * 16);
}
}
If you draw with the above increasing a coordinate, like X, every time, you'll see it scrolls by the size of the tile, or 16 pixels at a time. We need it smoother.
[size="5"]Smooth Scrolling
As a matter of fact, it's extremely easy to change this to smooth scrolling. First thing we have to do is ensure our tile sizes are in the power of 2 (2, 4, 8, 16, 32, 64, etc). This helps the math. There are ways to do other sizes, but I'm dealing with those as they are most popular.
We now create a fine coordinate system for the map. The fine coordinates are simply the size of the tiles, or 16x16. So each map coordinate now is 16x16 in size. That means a map 128x128 is 2048x2048 in fine coordinates.
When we render a map from now on, we tell it to draw from those coordinates. For the rendering function to deal with it, it must decide how much to scroll all the tiles we draw left and up.
So basically, we're now making the map seem like a huge bitmap. We pick an exact coordinate from that to start drawing in the top-left of the screen. To do that from tiles, we have to decided how the tiles align into that large area.
That's why we use tile sizes with the power of 2. First of all, when we want to render the map, say at 100,126 , we have to find the coordinate in the map array.
Since the fine coordinates run off the tile size, we just divide the numbers by 16, coming up with (100/16) 6, (126/16) 7. That tile will be first draw at the top-left of the screen.
mapx = map_drawx / 16;
mapy = map_drawy / 16;
map_xoff = map_drawx & 15;
map_yoff = map_drawy & 15;
So our new rendering function looks like:
void map_draw(short map_drawx, short map_drawy)
{
short i, j;
short mapx, mapy;
short map_xoff, map_yoff;
mapx = map_drawx / 16;
mapy = map_drawy / 16;
map_xoff = map_drawx & 15;
map_yoff = map_drawy & 15;
for(i = 0; i < 16; i++) {
for(j = 0; j < 21; j++)
tile_draw(map[mapy + i][mapx + j].tile_number, j * 16 - map_xoff, i * 16 - map_yoff);
}
}
Hope it helps!
Jim Adams
the Collective Mind
[email="tcm@pobox.com"]tcm@pobox.com [/email]
[email="tcm.lv@worldnet.att.net"]tcm.lv@worldnet.att.net [/email]