Here’s the code:
/Here’s my little 'ol app. spot_tile.bmp and brick.bmp are just 64x48 bitmaps I use for tiles
A Word or two about how it (suppositly) works: A retangle representing the area of the TileMap
that is curently visableis maintaned. I call this the ViewRectangle or VRect for
short. The VRect can be passed to DrawTiles() and all tiles in the VRect will
be blitted to screen. By moving the VRect and calling DrawTiles() scrolling
can be done. This is a brute force method I’ll fix pretty soon/
//includes
#include <stdio.h>
#include <stdlib.h>
#include “SDL.h”
//end includes
//typedefs
#define X_TILE_SIZE 64
#define Y_TILE_SIZE 48
#define SCREEN_EXTENT_X 640
#define SCREEN_EXTENT_Y 480
#define NUM_TILES_X 10
#define NUM_TILES_Y 40
#define WORLD_MAP_EXTENT_X (X_TILE_SIZE * NUM_TILES_X)
#define WORLD_MAP_EXTENT_Y (Y_TILE_SIZE * NUM_TILES_Y)
//end of typedefs
//function decs
Uint16 CreateHicolorPixel( SDL_PixelFormat fmt, Uint8 red, Uint8 green, Uint8 blue );
SDL_Surface LoadImage( char* file );
int DrawTiles(SDL_Rect* WorldCoordsRect);
//end function decs
//globals
SDL_Surface screen;
int done = 0;
SDL_Event event;
char TileMap[NUM_TILES_X][NUM_TILES_Y];
SDL_Surface Tiles[2];
SDL_Rect VRect;
//end globals
int main(){
VRect.x = 0;
VRect.y = WORLD_MAP_EXTENT_Y - 640;
VRect.w = 640;
VRect.h = WORLD_MAP_EXTENT_Y;
/* Initialize SDL */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
exit(1);
}
if ( (screen=SDL_SetVideoMode(640,480, 16,SDL_FULLSCREEN | SDL_ANYFORMAT )) == NULL ) {
fprintf(stderr, "Couldn't set 640x480 video mode: %s\n",
SDL_GetError());
exit(2);
}
//load the tiles
Tiles[0] = LoadImage( "spot_tile.bmp" );
Tiles[1] = LoadImage( "brick.bmp" );
for(int j = 0; j < 40; j++){
for(int i = 0; i < 10; i++){
TileMap[i][j] = i % 2;
}//end for loop i
}//end for loop j
int loopcount = 0;
int initial_ticks = SDL_GetTicks();
while ( VRect.y > 0 ){
DrawTiles(&VRect);
VRect.y -= 5;
VRect.h -= 5;
loopcount++;
}
int final_ticks = SDL_GetTicks();
printf("Time to do a DrawTiles(): %d\n", (final_ticks-initial_ticks) );
printf("loopcount: %d\n", loopcount);
SDL_UpdateRect(screen, 0,0,640,480);
while ( !done ) {
/* Check for events */
while ( SDL_PollEvent(&event) ) {
switch (event.type) {
case SDL_KEYDOWN:
/* Any keypress quits the app... */
case SDL_QUIT:
done = 1;
break;
default:
break;
}//end switch
}//end while ( SDL_PollEvent(&event) )
}//end while (!done)
SDL_Quit();
return 0;
}//end main
SDL_Surface* LoadImage( char* file ){
SDL_Surface* temp = NULL;
/* Load an image */
temp = SDL_LoadBMP(file);
if ( temp == NULL ) {
fprintf(stderr, “Couldn’t load %s: %s\n”, file, SDL_GetError());////////
exit(1);
}
/* Convert image to video format */
temp = SDL_DisplayFormat(temp);
if ( temp == NULL ) {
fprintf(stderr, "Couldn't convert background: %s\n",
SDL_GetError());
exit(1);
}
return temp;
}//end methond LoadImage
Uint16 CreateHicolorPixel( SDL_PixelFormat *fmt, Uint8 red, Uint8 green, Uint8 blue ){
Uint16 value;
/* This series of bit shifts uses the information from the SDL_Format
structure to correctly compose a 16-bit pixel value from 8-bit red,
green, and blue data. */
value = ((red >> fmt->Rloss) << fmt->Rshift) +
((green >> fmt->Gloss) << fmt->Gshift) +
((blue >> fmt->Bloss) << fmt->Bshift);
return value;
}//end method CreateHicolorPixel
int DrawTiles(SDL_Rect* WorldCoordsRect){
SDL_Rect destpts, Blit_Tiles_Extents, SDL_Blit_Rect;
int first_destpts_x;
destpts.x = -(WorldCoordsRect->x % X_TILE_SIZE);
destpts.y = -(WorldCoordsRect->y % Y_TILE_SIZE);
destpts.w = WorldCoordsRect->w - WorldCoordsRect->x;
destpts.h = WorldCoordsRect->h - WorldCoordsRect->y;
first_destpts_x = destpts.x;
Blit_Tiles_Extents.x = WorldCoordsRect->x / X_TILE_SIZE;
Blit_Tiles_Extents.y = WorldCoordsRect->y / Y_TILE_SIZE;
// The following lines of code make sure that when Blit_Tiles_Extents’ members are use to form
//Tile map indexes those indexes don’t overrun the bounds of the array
if ( Blit_Tiles_Extents.x < 0 )
Blit_Tiles_Extents.x = 0;
if ( Blit_Tiles_Extents.y < 0 )
Blit_Tiles_Extents.y = 0;
if ( Blit_Tiles_Extents.w > (NUM_TILES_X) )
Blit_Tiles_Extents.w = (NUM_TILES_X-1);
if ( Blit_Tiles_Extents.h > (NUM_TILES_Y) )
Blit_Tiles_Extents.h = (NUM_TILES_Y-1);
// The following lines of code make sure that partial tile get blited, SDL handles the clipping here
if( Blit_Tiles_Extents.x > 0 )
Blit_Tiles_Extents.x–;
if( Blit_Tiles_Extents.y > 0 )
Blit_Tiles_Extents.y–;
if( Blit_Tiles_Extents.w < (NUM_TILES_X) )
Blit_Tiles_Extents.w++;
if( Blit_Tiles_Extents.h < (NUM_TILES_Y) )
Blit_Tiles_Extents.h++;
for( int j = Blit_Tiles_Extents.y; j < Blit_Tiles_Extents.h; j++){
for( int i = Blit_Tiles_Extents.x; i < Blit_Tiles_Extents.w; i++){
SDL_Blit_Rect.x = destpts.x;
SDL_Blit_Rect.y = destpts.y;
SDL_BlitSurface(Tiles[ TileMap[i][j] ], NULL, screen, &SDL_Blit_Rect );
destpts.x += X_TILE_SIZE;
}//end for loop i
destpts.y += Y_TILE_SIZE;
destpts.x = first_destpts_x;
}//end for loop j
//right now I’m just redrawing the whole screen, I’ll fix that when I start optimizing
SDL_UpdateRect(screen, 0,0,640,480);
return 0;
}–
Jeremy Gregorio
jgreg at azstarnet.com