Page 1 of 1

2D tile map scrolling and collision

PostPosted: 01 Jul 2011, 20:15
by Pix3l
Hello there!
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 :] :think:

{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;
    }

Re: 2D tile map scrolling and collision

PostPosted: 02 Jul 2011, 12:28
by ghoulsblade

Re: 2D tile map scrolling and collision

PostPosted: 03 Jul 2011, 20:09
by Pix3l
It's not exactly what i need :]
I can perform collisions on tile based maps, but when i try to implement scrolling, collisions doesn't works right...
I need to figure out how scrolling works and make collisions working with it

Re: 2D tile map scrolling and collision

PostPosted: 05 Jul 2011, 07:35
by Edward_Lii
Hello Pix3l,

Pix3l {l Wrote}:I can perform collisions on tile based maps, but when i try to implement scrolling, collisions doesn't works right...
I need to figure out how scrolling works and make collisions working with it

I haven't looked at your code, but what has collision to do with scrolling?

Scrolling only determines what to draw, it shouldn't influence collision.
First get collision to work than implement scrolling, if collision is broken, then it is a rendering problem.

Best of luck! ;)

Re: 2D tile map scrolling and collision

PostPosted: 06 Jul 2011, 19:10
by Pix3l
I have tested collision in a simple static tile based map without scrolling, and it works.
My problem is make tile based collision and scrolling working togheter, anyway i will try to read other tutorials and hope to makes it works.
Thanks anyway :]