• Advertisement
Sign in to follow this  

Tile-based game.....

This topic is 4874 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

okay... ill give the code first:
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>

SDL_Surface *screen;
int game_state;
int i;
int x;
int y;
int bytecount;

SDL_Surface *tiles[3];
int world[100*100];//map is 100x100

//this is to be called from your game loop
//this is the same code from the earlier example
int player_x;//player's x position in the world
int player_y;//player's y position in the wolrd

//...insert code that get player input and updates player_x and player_y based on player input.

//assume player character is at center of screen
//find start position to draw from in tile array
int start_x;//assume tiles are 32x32 and screen width is 640. 
int start_y;//assume tiles are 32x32 and screen height is 480. 

void init_tile()
     tiles[0] = SDL_LoadBMP("gfx/water.bmp");
     tiles[1] = SDL_LoadBMP("gfx/desert.bmp");
     tiles[2] = SDL_LoadBMP("gfx/grass.bmp");

  	long size;
	int bytecount;
	int count;

	FILE *f;
  	if (f==NULL) perror ("Error opening file desert.map");
    		fseek (f, 0, SEEK_END);
    		size=ftell (f);
		bytecount = size;  	
		fseek (f, 0, SEEK_SET);
	int player_index = 0;//stores our position in the world array

		int temp = fgetc(f)-48;//read a tile index from the file
		world[player_index] = temp;//store value from file in our world map array
		//printf("%i", temp);
		printf(", %i", world[player_index]);
		++player_index;//move to next position in array

void draw()
	int x, y;
	int tile_index;	
	SDL_Surface *curr_tile = tiles[tile_index];

	int draw_x = 0;//x position on screen to draw to
	int draw_y = 0;//y position on screen to draw to

	char *tilefile;//Tile to print
	start_x= player_x-10;
	start_y = player_y-7;
	SHORT DESCRIPTION: start_y/x = start position to draw from
	draw_x/y = Position on screen to draw to
	player_x/y = playersXpos

	for(y = start_y; y < start_y+15; ++y)//again, assumes 15 rows
          		for(x = start_x; x < start_x+20; ++x)//assumes 20 columns
               			tile_index = world[y*20+x]; //wich tile do we want to print? results in 0,1,2.
				//printf("world = %i", world[y*20+x]);//debugging

				//Printing the tiles got from tile_index

					ShowBMP(tilefile, screen, draw_x, draw_y);
     				draw_x+=32;//move over 32 pixels because that is the width of one tile

     		draw_x=0;//When we have painted one row, reset X and put 32 to Y to start on the next row.


void game_keypress()
	SDL_Event event;
    	while( SDL_PollEvent( &event ) )
        	switch( event.type )
            	/* Look for a keypress */
            	case SDL_KEYDOWN:
                switch( event.key.keysym.sym )
			case SDLK_RIGHT:
			case SDLK_LEFT:
			case SDLK_ESCAPE:
                        	fprintf(stderr, "\nQuiting game, have a nice day...\n");
				game_state = 4;

desert.map looks like this: 1111111111111111111111111111 1000000000000000000000000001 1000000000000000000000000001 1000000000000000000000000001 1000000000222222000000000001 1000000002222222220000000001 1000000022222222222000000001 1000000000222222220000000001 1000000000002222200000000001 1000000000000000000000000001 1000000000000000000000000001 1111111111111111111111111111 where 0 = water, 1=grass, 2=desert. Im running it in 640x480, and tiles are 32px square... so there are 20 rows and 15 columns... The problem is: that when it takes the first 20 1's it prints like this: GGGGGGGGGGGGGGGGGGGG (Where G = grass) and then starts with the remaining 1's on the second row but still on the first row in the file: GGGGGGGGGGGGGGGGGGGG Okay now i need to fix this, so i guess i need to have an array: curr_screen[20][15]; or something like that but i need some help... thanks

Share this post

Link to post
Share on other sites
Your problem was stated a little unclearly, but I think I know what you are talking about. Here's some quick demo code I whipped up a while ago. It's not optimal, but it was enough that I could animate a sprite walking around a map of arbitrary size. I won't post the whole code for brevity, but if you want the rest just ask.

By the way, how do you put your code in a box like that? :P

class MapData {
int num_tile_rows, num_tile_cols, num_tiles;
int col_pos, row_pos;
vector <string> tile_vector;
vector <vector<int> > map_vector;
friend class MapMode; // Necessary so that the MapMode class can access and change these data members
void LoadData(string map_name);
void BlitMap(int startx, int starty);

void MapData::LoadData(string map_name) {
// First remove all the old data in our vectors
for (unsigned int r = 0; r < map_vector.size(); r++)

// The following is temporary code until we get the data configuration code working
if (map_name == "testing") {
num_tile_rows = TILE_ROWS * 2; // Set the # of tile rows in the new map
num_tile_cols = TILE_COLS * 4; // Set the # of tile columns in the new map
col_pos = 2 * TILE_COLS + 4; // Set the initial column position
row_pos = TILE_ROWS; // Set the initial row position
num_tiles = 15; // Set the number of unique tile images that compose the map

//tile_vector.resize(num_tiles); // Resize our tile vector. For some weird reason, this causes a seg fault

// Load the tile vector with all of the tile filename strings

// Load all the new tile images into the image_cache
for (unsigned int i = 0; i < tile_vector.size(); i++)

// Resize our map_vector
for (int r = 0; r < num_tile_rows; r++)

// Now we go thru and generate a random map with the tiles we loaded in. Cool huh?
for (int r = 0; r < num_tile_rows; r++) {
for (int c = 0; c < num_tile_cols; c++) {
if (r == 0 || r == num_tile_rows - 1) // Make the top and bottom one tile for distinction
map_vector[r][c] = num_tiles - 1; // Top & bottom are now "water"
else if (c == 0 || c == num_tile_cols - 1) // Make the sides one tile for distinction
map_vector[r][c] = num_tiles - 2; // Top & bottom are now "wall"
map_vector[r][c] = RandomNum(0, num_tiles - 3); // Assign a random tile in the map_vector

Share this post

Link to post
Share on other sites
If I understand correctly what you are trying to do here, let me offer you a few suggestions.

to read in the map:

// globals
// use constants to define the size of the map so that
// if you change your mond about the size, you only have
// to change it here.
const int map_w = 100;
const int map_h = 100;
int world[map_w*map_h];

void load_map()
FILE *fp;
int x,y,index;
int c;

fp = fopen("maps/desert.map","r");

if (fp == NULL)
perror ("Error opening file desert.map");
//some sort of exit code here

// this only works if you know the dimensions of the map
// in the mapfile. This should be changed to account
// for error or different sizes.
// if you need help, e-mail me and I will be happy to help
for ( y = 0; y < map_h; y++ )
for ( x = 0; x < map_w; x++ )
// skip the newline chars
c = fgetc(fp);
}while( c == '\n' || c == '\r' );

// with a one dimensional array use math to
// simulate a 2 dimensional array
world[ x + (map_w*y) ] = c;
// for debugging I guess?
printf( "%2c", c );
// new line. depends, might want \n\r
printf( "\n" );

fclose( fp );

take into account that the map you showed us is only 28x12 so you would have to change the map_w and map_h to the actual dimensions of the map in the map file for the above to work.

I notice you are using standard C style functions instead of C++ classes which is fine and well especially for a first time project so i will stick to the same.

Try breaking your draw function down into smaller functions like:

// again use constants instead of the actual numbers
const int tile_w = 32;
const int tile_h = 32;
const int screen_w = 20;
const int screen_h = 15;

void draw_tile( int x, int y, int tile )
// you get the idea
SDL_BlitSurface( .... );

void draw_map( int start_x, int start_y )
int x, y;

for ( y = start_y; y<start_y+screen_h; y++ )
for( x = start_x; x<start_x<screen_w; x++ )
draw_tile( (x-start_x)*tile_w, (y-start_y)*tile_h, world[(x%map_w)+((y*map_w)%map_h)] );

void draw_player( int x, int y )
// you get the idea
SDL_BlitSurface( ... );

void draw()
draw_map( player_x - 10, player_y - 7 );
draw_player( tile_w*10+tile_w/2, tile_h*7+tile_h/2 );

and change your player_x and player_y by 1 for the keypress to keep it to a tile by tile walk.

Off the top of my head that should allow you to wrap around your small map on a tile by tile scroll with the player in somewhat the middle of the screen. As I said, this hasn't been tested but is merely a few suggestions to help you keep somewhat organized.

For smooth pixel by pixel scrolling it isn't much different but if you need any help I will be more than happy to help you. Just send me an e-mail or if you want I can write a small working C example of what it looks like you are trying to do.

Hope that helped.

Share this post

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

  • Advertisement