I have try to wrote my first 2D tile based game, i read some tutorials found around the web and i was able only to make scrolling working a little, but not collisions...
Is there anyone who knew about a good and complete tutorial about 2D tile based games?
I put here my work, i don't fully understand how scrolling works with collisions.
from loserjuegos.
Thanks for help :]

- {l Code}: {l Select All Code}
//gcc -o scrolling scrolling.c -lSDL
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <time.h>
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 320
#define TILESIZE 32
#define ROWS 15
#define COLUMNS 40
#define PLAYER_W 10
#define PLAYER_H 10
//Global variables
int t, tl = 0, frequency = 1000 / 100, temp, t2; //StopBall variables
int repeat, i, quit=0, paused=0, shoot=0;
SDL_Event event;
SDL_Surface *screen;
SDL_Rect rect; //Main drawing surface
Uint8 *keystate; // keyboard state
int playfield[ROWS][COLUMNS] =
{
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,1,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,
1,1,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,
0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,
1,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,
0,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};
struct _Player
{
int w, h, onGround;
int x, y, jump, lockjump;
float dirX, dirY;
} Player;
struct _Game{
int mapx;
} Game;
struct _Camera
{
int x, y;
} Camera;
void DrawRect(int x, int y, int width, int height, int color)
{
rect.x = x;
rect.y = y;
rect.w = width;
rect.h = height;
SDL_FillRect(screen, &rect, color);
}
void drawbackground()
{
int i;
int j;
int row = Camera.y / TILESIZE;
int column = Camera.x / TILESIZE;
int shiftX = Camera.x % TILESIZE;
int shiftY = Camera.y % TILESIZE;
for (i = 0; i < ROWS; i ++)
{
for (j = 0; j < COLUMNS; j ++)
{
if(playfield[row + i][column + j]==0)
DrawRect(j * TILESIZE - shiftX, i * TILESIZE - shiftY, TILESIZE, TILESIZE, 0x000000);
}
}
}
void Draw()
{
drawbackground();
DrawRect(Player.x - Camera.x + (SCREEN_WIDTH/2), Player.y - Camera.y + (SCREEN_HEIGHT/2), PLAYER_W, PLAYER_H, 0xff0000);
//printf("Player.x %d Camera.x %d X %d\n", (int)Player.x, (int)Camera.x, (int)Player.x - (int)Camera.x + (SCREEN_WIDTH/2));
//printf("Player.y %d Camera.y %d Y %d\n", (int)Player.y, (int)Camera.y, (int)Player.y - (int)Camera.y + (SCREEN_WIDTH/2));
DrawRect(Camera.x, Camera.y, PLAYER_W, PLAYER_H, 0xffffff);
}
void doCamera()
{
//Converte da coordinata a tiles???
int limitX = COLUMNS * TILESIZE - SCREEN_WIDTH;
int limitY = ROWS * TILESIZE - SCREEN_HEIGHT;
/* se acerca a la posición del tanque de manera gradual */
Camera.x += Player.x - Camera.x;
Camera.y += Player.y - Camera.y;
/* detiene el desplazamiento en los límites */
if (Camera.x < 0)
Camera.x = 0;
if (Camera.y < 0)
Camera.y = 0;
if (Camera.x > limitX)
Camera.x = limitX;
if (Camera.y > limitY)
Camera.y = limitY;
}
int tileCollision(int x, int y, int w, int h)
{
int i, j;
int minx, miny, maxx, maxy;
// Return a collision if the rectangle is outside of the map.
if (x < 0 || (x + w) > TILESIZE * COLUMNS ||
y < 0 || (y + h) > TILESIZE * ROWS)
return 1;
// The passed coordinates are in pixels so convert them to tiles.
minx = x / TILESIZE;
miny = y / TILESIZE;
printf("minx %d\n", minx);
maxx = (x + w - 1) / TILESIZE;
maxy = (y + h - 1) / TILESIZE;
// Return a collision if the rectangle intersects with a tile.
for (i = minx; i <= maxx ; i++)
{
for (j = miny ; j <= maxy ; j++)
{
if (playfield[j][i])
return 1;
}
}
// No collision otherwise.
return 0;
}
int getInput()
{
int x, y;
x = Player.x;
y = Player.y;
printf("player X %d\n", Player.x);
while(SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE)) quit = 1; /* Window closed */
}
// Grab a keystate snapshot
keystate = SDL_GetKeyState( NULL );
/* Handle key presses */
if (keystate[SDLK_LEFT])
{
if((int)Player.x - (int)Camera.x + (SCREEN_WIDTH/2) != 0)
if(!tileCollision(x-1, y, TILESIZE, TILESIZE))
Player.x -= 1;
}
if (keystate[SDLK_RIGHT])
{
if(!tileCollision(x+1, y, TILESIZE, TILESIZE))
Player.x += 1;
}
if (keystate[SDLK_UP])
if((int)Player.y - (int)Camera.y + (SCREEN_HEIGHT/2) != 0 )
if(!tileCollision(x, y-1, TILESIZE, TILESIZE))
Player.y-=1;
if (keystate[SDLK_DOWN])
if((int)Player.y - (int)Camera.y + (SCREEN_HEIGHT/2) != 320 - PLAYER_H )
if(!tileCollision(x, y+1, TILESIZE, TILESIZE))
Player.y+=1;
}
int fps_sync ()
{
t = SDL_GetTicks ();
//printf("tl: %d t: %d\n", tl, t);
if (t - tl >= frequency)
{
temp = (t - tl) / frequency; //delta time
tl += temp * frequency;
//printf("temp: %d tl: %d \n", t, tl);
return temp;
}
else
{
SDL_Delay (frequency - (t - tl));
tl += frequency;
return 1;
}
}
void logicLoop()
{
getInput();
}
int mainLoop()
{
//main game loop
while(!quit)
{
repeat = fps_sync ();
for (i = 0; i < repeat; i ++)
{
logicLoop();
doCamera();
//Debug purpose
//int x = (int)Player.x/TILESIZE;
//int y = (int)Player.y/TILESIZE;
//printf("Player tile %d %d\n", x, y);
}
//clear the screen
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 128, 128, 128));
//draw to the screen
Draw();
//update the screen
SDL_Flip(screen);
}
}
int main(int argc, char *argv[])
{
// init video stuff
// init screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE);
if(screen == NULL)
{
fprintf(stderr, "Can't initialize SDL: %s\n", SDL_GetError());
exit(-1);
}
SDL_WM_SetCaption("Scrolling", "Scrolling");
Player.x = 32; //-SCREEN_WIDTH/2 + TILESIZE;
Player.y = 32; //36 middle
//main game loop
mainLoop();
SDL_Quit();
return 0;
}