Skip to main content
gamedev.net
🔒 Locked

Tile-based game.....

Started by peb Nov 12, 2004 at 7:01 AM 1 replies 1.1k views
Original Post
peb
peb
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
Roots
Roots
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 tile_vector;
vector > 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);

// 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
}
}
}
}
evillive2
evillive2
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 numbersconst 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.
Evillive2

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.