• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
MichaelBarth

SDL TileEngine

1 post in this topic

Okay first things first I'm only writing in C right now, not C++, so LazyFoo's tutorial doesn't help me so much.

Anyway I want to be able to create a tile map with file like:

[code]
[MapLayer]
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00

[SpriteLayer]

00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
00 01 00 00 00 00 00 10 10 00 01 02 03 04 01 00
[/code]

Something like that.

The map that will be visible on the screen I want to be 640x480 with 16x16 tiles, which totals to 1200 tiles per screen. So what I ultimately want is to be able to draw these 1200 tiles onto an SDL_Surface that I can resize to fit the screen. Now the problem isn't necessarily that I can't resize it or any of the math involved, it's reading from a file that's giving me trouble. I'm finding it very difficult to figure out how to read from a file and find where the tag [MapLayer] or [SpriteLayer] might be then reading all the tile numbers into an array, which being that I'm used to C#'s XNA, I would normally use a multidimensional array.

I've looked at input\output tutorials, but it's hard to make sense of it for what I'm trying to do. This is along the lines of what I want to do in simple terms:

[code]
Open File "mapname.map"
Read and find the string "[MapLayer]"
If string doesn't exist, close and quit.
Go to next line and read the numbers and put them into an array and get the length of how many tiles were counted and put into the array.
Continue reading the next lines and putting them into an array until there is no more tiles, and if they are a different length than the first, cancel and close the file.
Find if there is a string "[SpriteLayer]" and repeat the process of the [MapLayer], only this time, the tiles represent sprites.
Close the file.

Use array(s) to draw tiles relative to a "Camera's" position.
[/code]
If someone could give me some guidance or a C based tutorial on how to do this, it'd be very appreciated.

Just for some clarification, right now I'm running on Mac OS X 10.6 with XCode 3.2.6
(If you're making some kind of a WTF face right now, I made that same one when I had to switch back to this Mac after having some problems with my PC)
0

Share this post


Link to post
Share on other sites
Okay, I eventually decided to forget it and move back to C++. I've got a tile engine going and I'm working on a small remake of the Legend of Zelda A Link to the Past game for SNES for learning purposes.

The first part you may notice about my code just so you're not asking "why" is that when I draw a level I'm using the original resolution of 256x224 (224 tiles per screen) to make it look like the original game. Also, there's not much error checking because I know where everything is right now and I'll rewrite it with more error checking later once I have the actual TIleEngine up and running.

Okay here's my problem, I have a 1440 x 900 screen. All my tiles (so far) are 16x16 (later I'll add 32x32). What I'm doing right now is drawing 224 tiles per screen 16 tiles per line, and 14 lines. The problem I'm facing is that it's drawing at a resolution of 256 x 224 on a 1440 x 900 screen. What I want to do is re-size what's being drawn to the screen to the SCREENWIDTH and SCREENHEIGHT integers. The best case scenario would be to re-size the individual tiles using a scale factor based on the screen width and height. I'm finding that to be extremely difficult to do with the way this is set up. (I'm now following the LazyFoo SDL tutorial for a TileEngine)

Right now I have it working, but the way it's setup collision detection would be impossible once I add in a character or an enemy, or whatever. What I do right now is take the tiles blit them to the screen once have an SDL_Surface copy the contents of the screen clipping the width and the height then re-sizing that surface and blit it to the screen. It also seems to take up quite a bit of the CPU as well. Alright now that I've done all the explaining here's the actual code:

Clipping and Drawing Code and variables:
[code]

SDL_Surface *tileSheet = NULL;

const int LEVEL_WIDTH = 256;
const int LEVEL_HEIGHT = 224;

const int TileWidth = 16;
const int TileHeight = 16;


const int TOTAL_TILES = 224;
const int TILE_SPRITES = 16;

//The different tile sprites
const int TILE_ROCKS = 0;
const int TILE_BLADEGRASS = 1;
const int TILE_GRASS = 2;
const int TILE_SIGN = 3;
const int TILE_TALLGRASS = 4;
const int TILE_GRASSSPECS = 5;
const int TILE_BROWNGRASS = 6;
const int TILE_DIRTROCKS = 7;
const int TILE_STONE = 8;
const int TILE_BHOUSETLEFT = 9;
const int TILE_BHOUSET = 10;
const int TILE_BHOUSETRIGHT = 11;
const int TILE_BHOUSEMID = 12;
const int TILE_BHOUSEBLEFT = 13;
const int TILE_BHOUSEB = 14;
const int TILE_BHOUSEBRIGHT = 15;

SDL_Rect clips[ TILE_SPRITES ];
SDL_Rect camera = { 0, 0, SCREENWIDTH, SCREENHEIGHT };
void Tile::Draw()
{
//If the tile is on screen
if( check_collision( camera, box ) == true )
{
//Show the tile
RenderSurface( box.x - camera.x, box.y - camera.y, tileSheet, screen, &clips[ type ] );
}
}

void clip_tiles()
{
//Clip the sprite sheet
clips[ TILE_ROCKS ].x = 0;
clips[ TILE_ROCKS ].y = 0;
clips[ TILE_ROCKS ].w = TileWidth;
clips[ TILE_ROCKS ].h = TileHeight;

clips[ TILE_BLADEGRASS ].x = 16;
clips[ TILE_BLADEGRASS ].y = 0;
clips[ TILE_BLADEGRASS ].w = TileWidth;
clips[ TILE_BLADEGRASS ].h = TileHeight;

clips[ TILE_GRASS ].x = 32;
clips[ TILE_GRASS ].y = 0;
clips[ TILE_GRASS ].w = TileWidth;
clips[ TILE_GRASS ].h = TileHeight;

clips[ TILE_SIGN ].x = 48;
clips[ TILE_SIGN ].y = 0;
clips[ TILE_SIGN ].w = TileWidth;
clips[ TILE_SIGN ].h = TileHeight;

clips[ TILE_TALLGRASS ].x = 0;
clips[ TILE_TALLGRASS ].y = 16;
clips[ TILE_TALLGRASS ].w = TileWidth;
clips[ TILE_TALLGRASS ].h = TileHeight;

clips[ TILE_GRASSSPECS ].x = 16;
clips[ TILE_GRASSSPECS ].y = 16;
clips[ TILE_GRASSSPECS ].w = TileWidth;
clips[ TILE_GRASSSPECS ].h = TileHeight;

clips[ TILE_BROWNGRASS ].x = 32;
clips[ TILE_BROWNGRASS ].y = 16;
clips[ TILE_BROWNGRASS ].w = TileWidth;
clips[ TILE_BROWNGRASS ].h = TileHeight;

clips[ TILE_DIRTROCKS ].x = 48;
clips[ TILE_DIRTROCKS ].y = 16;
clips[ TILE_DIRTROCKS ].w = TileWidth;
clips[ TILE_DIRTROCKS ].h = TileHeight;

clips[ TILE_STONE ].x = 0;
clips[ TILE_STONE ].y = 32;
clips[ TILE_STONE ].w = TileWidth;
clips[ TILE_STONE ].h = TileHeight;

clips[ TILE_BHOUSETLEFT ].x = 16;
clips[ TILE_BHOUSETLEFT ].y = 32;
clips[ TILE_BHOUSETLEFT ].w = TileWidth;
clips[ TILE_BHOUSETLEFT ].h = TileHeight;

clips[ TILE_BHOUSET ].x = 32;
clips[ TILE_BHOUSET ].y = 32;
clips[ TILE_BHOUSET ].w = TileWidth;
clips[ TILE_BHOUSET ].h = TileHeight;

clips[ TILE_BHOUSETRIGHT ].x = 48;
clips[ TILE_BHOUSETRIGHT ].y = 32;
clips[ TILE_BHOUSETRIGHT ].w = TileWidth;
clips[ TILE_BHOUSETRIGHT ].h = TileHeight;

clips[ TILE_BHOUSEMID ].x = 0;
clips[ TILE_BHOUSEMID ].y = 48;
clips[ TILE_BHOUSEMID ].w = TileWidth;
clips[ TILE_BHOUSEMID ].h = TileHeight;

clips[ TILE_BHOUSEBLEFT ].x = 16;
clips[ TILE_BHOUSEBLEFT ].y = 48;
clips[ TILE_BHOUSEBLEFT ].w = TileWidth;
clips[ TILE_BHOUSEBLEFT ].h = TileHeight;

clips[ TILE_BHOUSEB ].x = 32;
clips[ TILE_BHOUSEB ].y = 48;
clips[ TILE_BHOUSEB ].w = TileWidth;
clips[ TILE_BHOUSEB ].h = TileHeight;

clips[ TILE_BHOUSEBRIGHT ].x = 48;
clips[ TILE_BHOUSEBRIGHT ].y = 48;
clips[ TILE_BHOUSEBRIGHT ].w = TileWidth;
clips[ TILE_BHOUSEBRIGHT ].h = TileHeight;
}
[/code]


The main():
[code]

int main( int argc, char* args[] )
{
if (!Init())
return 1;
tileSheet = Load_IMG("C:\\tiles.png");
clip_tiles();
if (set_tiles( tiles ) == false)
return 1;
while (!quit)
{
FRATE.start();
Update();
Draw();
while(SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
quit = true;
if (event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
quit = true;
}
}
}
if( SDL_Flip( screen ) == -1 )
{
printf("\nError updating the screen!");
return 1;
}
if((FRATECAPPED == true ) && ((float)FRATE.get_ticks() < 1000.0f / FPS))
{
//Sleep the remaining frame time
SDL_Delay(( 1000.0f / FPS ) - (float)FRATE.get_ticks());
}
}
clean_up(tiles);
SDL_FreeSurface(newScreen);
SDL_Quit();
return 0;
}
[/code]
The Draw() referenced in main: (Update() is not used yet)
[code]

void Draw()
{
if (!tiletoScreen)
{
for( int t = 0; t < TOTAL_TILES; t++ )
{
tiles[ t ]->Draw();
}
}
if (!tiletoScreen)
{
newScreen = SDL_ConvertSurface(screen, screen->format, SDL_SWSURFACE);
newScreen = ScaleSurface(newScreen, SCREENWIDTH, SCREENHEIGHT, 0, 0, 256, 224);
tiletoScreen = true;
}
if (tiletoScreen)
RenderSurface(0, 0, newScreen, screen, NULL);
}
[/code]

My modified version of ScaleSurface that uses the getpixel and putpixel functions:
[code]

SDL_Surface *ScaleSurface(SDL_Surface *Surface, Uint16 Width, Uint16 Height, int clipx = NULL , int clipy = NULL, int clipw = NULL, int cliph = NULL)
{
if(!Surface || !Width || !Height)
return 0;
int usingclip = 0;
if (!clipw || !cliph)
usingclip = 0;
else
usingclip = 1;
SDL_Surface *_ret = NULL;
_ret = SDL_CreateRGBSurface(Surface->flags, Width, Height, Surface->format->BitsPerPixel,
Surface->format->Rmask, Surface->format->Gmask, Surface->format->Bmask, Surface->format->Amask);
double _stretch_factor_x, _stretch_factor_y;
if (usingclip == 0)
{
_stretch_factor_x = (static_cast<double>(Width) / static_cast<double>(Surface->w));
_stretch_factor_y = (static_cast<double>(Height) / static_cast<double>(Surface->h));
}
if (usingclip == 1)
{
_stretch_factor_x = (static_cast<double>(Width) / static_cast<double>(clipw));
_stretch_factor_y = (static_cast<double>(Height) / static_cast<double>(cliph));
}

if (usingclip == 0)
{
for(Sint32 y = 0; y < Surface->h; y++)
for(Sint32 x = 0; x < Surface->w; x++)
for(Sint32 o_y = 0; o_y < _stretch_factor_y; ++o_y)
for(Sint32 o_x = 0; o_x < _stretch_factor_x; ++o_x)
putpixel(_ret, static_cast<Sint32>(_stretch_factor_x * x) + o_x,
static_cast<Sint32>(_stretch_factor_y * y) + o_y, getpixel(Surface, x, y));
}
if (usingclip == 1)
{
for(Sint32 y = static_cast<Sint32>(clipy); y < static_cast<Sint32>(cliph); y++)
for(Sint32 x = static_cast<Sint32>(clipx); x < static_cast<Sint32>(clipw); x++)
for(Sint32 o_y = 0; o_y < _stretch_factor_y; ++o_y)
for(Sint32 o_x = 0; o_x < _stretch_factor_x; ++o_x)
putpixel(_ret, static_cast<Sint32>(_stretch_factor_x * x) + o_x,
static_cast<Sint32>(_stretch_factor_y * y) + o_y, getpixel(Surface, x, y));
}

return _ret;
}
[/code]

Right now I would say that the most important part is the drawing code and the clipping code.

What's the best way I can re-size the tiles based on a scale factor that is calculated based on a comparison of the projected screen width and height (256x224) to the actual screen (1440x900 or whatever the case may be).
0

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  
Followers 0