Sign in to follow this  
peb

Tile-based game.....

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;
	f=fopen("maps/desert.map","r");
  	if (f==NULL) perror ("Error opening file desert.map");
  	else
  	{
    		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
	while(i<bytecount)
	{

		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
		i=i+1;
	}
	game_state=2;
}

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
				if(tile_index==0)
				{
					tilefile="gfx/water.bmp";
				}
				if(tile_index==1)
				{
					tilefile="gfx/grass.bmp";
				}
				if(tile_index==2)
				{
					tilefile="gfx/desert.bmp";
				}

				if(tile_index!=-38)
				{
					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.
     		draw_y+=32;
     		}

}

void game_keypress()
{
	SDL_EnableUNICODE(1);
	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:
                        	player_x=player_x+32;
				break;
			case SDLK_LEFT:
				player_x=player_x-32;
				break;
			case SDLK_ESCAPE:
                        	fprintf(stderr, "\nQuiting game, have a nice day...\n");
				game_state = 4;
				break;
			default:
				break;
			}
		}
        }
}

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
public:
MapData();
~MapData();
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
tile_vector.clear();
for (unsigned int r = 0; r < map_vector.size(); r++)
map_vector[r].clear();
map_vector.clear();

// 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
tile_vector.push_back("tile/bones_01.png");
tile_vector.push_back("tile/clay_01.png");
tile_vector.push_back("tile/desert_01.png");
tile_vector.push_back("tile/desert_02.png");
tile_vector.push_back("tile/desert_03.png");
tile_vector.push_back("tile/dirt_01.png");
tile_vector.push_back("tile/forest_01.png");
tile_vector.push_back("tile/path_01.png");
tile_vector.push_back("tile/path_02.png");
tile_vector.push_back("tile/road_01.png");
tile_vector.push_back("tile/road_02.png");
tile_vector.push_back("tile/rock_01.png");
tile_vector.push_back("tile/rock_02.png");
tile_vector.push_back("tile/wall_01.png");
tile_vector.push_back("tile/water_01.png");

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

// Resize our map_vector
map_vector.resize(num_tile_rows);
for (int r = 0; r < num_tile_rows; r++)
map_vector[r].resize(num_tile_cols);

// 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"
else
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
exit(1);
}

// 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
do
{
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this