Sign in to follow this  
Puyover

SDL: Collision: Tiles and Sprites.

Recommended Posts

Hi! Well, I present you. I´m Santiago, I´m Spanish and I´m 16 years old. I´ve lost a bit. I´m using the CRM32Pro library, than work on SDL, to create a RPG with aerial vista. The problem is than I´ve a tileset, than I represent as a matrix. Okey, the problem come, when I want check collision betwen the sprite and the tile. I don´t obtain it. Here I paste my code:
struct Mapa {
    CRM32Pro_CTile* tile;
    int posX, posY;
    int tX, tY;
} Pradera;

struct Sprite {
    CRM32Pro_CSprite* GFX;
    int columna, fila;
    int tX, tY;
    int tX2, tY2;
    bool libre;
    int toca[4];
    int lastX, lastY;
    int posX, posY;
    int velX, velY;
    int bucle;
} Link;

...

void PJHandler(void) {
    for(Link.bucle = 0; Link.bucle < 4; Link.bucle++){
        Link.toca[Link.bucle] = 0;
    }
    keyboard = SDL_GetKeyState(NULL);

    Link.posX = Link.lastX;
    Link.posY = Link.lastY;

    if(keyboard[SDLK_UP]) {
        Link.GFX->SelectAnim(SPRSTATE_UP);
        Link.GFX->Resume();
        Link.lastY -= Link.velY;
    }
    if(keyboard[SDLK_LEFT]) {
        Link.GFX->SelectAnim(SPRSTATE_LEFT);
        Link.GFX->Resume();
        Link.lastX -= Link.velX;
    }
    if(keyboard[SDLK_RIGHT]) {
        Link.GFX->SelectAnim(SPRSTATE_RIGHT);
        Link.GFX->Resume();
        Link.lastX += Link.velX;
    }
    if(keyboard[SDLK_DOWN]) {
        Link.GFX->SelectAnim(SPRSTATE_DOWN);
        Link.GFX->Resume();
        Link.lastY += Link.velY;
    }
    if(!keyboard[SDLK_UP] && !keyboard[SDLK_DOWN] && !keyboard[SDLK_LEFT]  && !keyboard[SDLK_RIGHT]) {
        Link.GFX->Pause();
        Link.GFX->SelectFrame(0);
    }

    Link.tX = Link.lastX / 32;
    Link.tY = Link.lastY / 32;
    Link.tX2 = (Link.lastX + 80) / 32;
    Link.tY2 = (Link.lastY + 80) / 32;

    Link.toca[0] == Pradera_map0[Link.tX][Link.tY];
    Link.toca[1] == Pradera_map0[Link.tX2][Link.tY];
    Link.toca[2] == Pradera_map0[Link.tX][Link.tY2];
    Link.toca[3] == Pradera_map0[Link.tX2][Link.tY2];

    for(Link.bucle = 0; Link.bucle < 4; Link.bucle++){
        if(Link.toca[Link.bucle] != 1) Link.libre = false;
    }

    if(Link.libre == true) {
        Link.GFX->SetPosition(Link.lastX, Link.lastY, 0);
    } else {
        Link.posX = Link.lastX;
        Link.posY = Link.lastY;
    }
}

const short Pradera_map0[30][40] = { data }

void DrawMap(void) {
    for(Pradera.posY = 0; Pradera.posY < 30; Pradera.posY++) {
     for(Pradera.posX = 0; Pradera.posX < 40; Pradera.posX++) {
         Pradera.tile->SetPosition(Pradera.posY * 32, Pradera.posX * 32);
         Pradera.tile->Draw(NULL, Pradera_map0[Pradera.posX][Pradera.posY]);
         Pradera.tile->Draw(NULL, Pradera_map1[Pradera.posX][Pradera.posY]);
     }
	}
}


The PJ only can walk, on the 1 value. Thank you very much! Cheers!! PD: Sorry my bad english :-P [Edited by - Puyover on March 10, 2007 4:10:46 PM]

Share this post


Link to post
Share on other sites
I think I see some potential problems.

Trying presetting the 'free' flag to true.
Link.libre = true;

Use the assignment(=) instead of the comparision(==) operator in these lines.
Link.toca[0] = Pradera_map0[Link.tX][Link.tY];
...

If you want, you can restore the animation state. I made up the
variable 'LastAnimationState ' and function 'Link.GFX->GetAnime()' to show you what I mean.

Just store the current position in lastX and lastY. Then use other
variable to store the next possible position(newX,newY). This way you
don't overwrite lastX/Y.

Lastly, it is kind of redundant to set the Link.toca[](hit array) at the beginning of the function. Also what is the purpose of having the loop counter Link.bucle as part of the class?

Modified Source.

void PJHandler(void) {
//No need to do this
for(Link.bucle = 0; Link.bucle < 4; Link.bucle++){
Link.toca[Link.bucle] = 0;
}
keyboard = SDL_GetKeyState(NULL);

//Store last valid position
Link.lastX = Link.posX;
Link.lastY = Link.posY;

//Store current animation state so that we can go back to it if move wasnt' OK
//I used a fake function called GetAnime() get the current state.
int LastAnimationState = Link.GFX->GetAnime();

//Use other variables to get posible new position
int newX = Link.posX;
int newY = Link.posY;

//Use if/else structure (assumes sprite can only move in four directions)
if(keyboard[SDLK_UP]) {
Link.GFX->SelectAnim(SPRSTATE_UP);
Link.GFX->Resume();
newY -= Link.velY;
}else if(keyboard[SDLK_LEFT]) {
Link.GFX->SelectAnim(SPRSTATE_LEFT);
Link.GFX->Resume();
newX -= Link.velX;
}else if(keyboard[SDLK_RIGHT]) {
Link.GFX->SelectAnim(SPRSTATE_RIGHT);
Link.GFX->Resume();
newX += Link.velX;
}else if(keyboard[SDLK_DOWN]) {
Link.GFX->SelectAnim(SPRSTATE_DOWN);
Link.GFX->Resume();
newY += Link.velY;
}else{ //No directional key pressed detected
Link.GFX->Pause();
Link.GFX->SelectFrame(0);
}
//convert position to tile coordinates
Link.tX = newX / 32;
Link.tY = newY / 32;
Link.tX2 = (newX + 80) / 32;
Link.tY2 = (newY + 80) / 32;

//check if we hit a solid tile (0)
//use assignment operator '=' instead of comparison operator '=='
Link.toca[0] = Pradera_map0[Link.tX][Link.tY];
Link.toca[1] = Pradera_map0[Link.tX2][Link.tY];
Link.toca[2] = Pradera_map0[Link.tX][Link.tY2];
Link.toca[3] = Pradera_map0[Link.tX2][Link.tY2];

//Pre-set 'can move' flag to true
Link.libre = true;

//we can only move if tile value is '1'
for(Link.bucle = 0; Link.bucle < 4; Link.bucle++){
if(Link.toca[Link.bucle] != 1) Link.libre = false;
}

if(Link.libre == true) {
Link.GFX->SetPosition(newX, newY, 0);
} else {
//we can't move so restore old position and state
Link.posX = Link.lastX;
Link.posY = Link.lastY;
Link.GFX->SelectAnim(LastAnimationState );
Link.GFX->Resume();
}
}







Good Luck!

[Edited by - Jack Sotac on March 11, 2007 6:32:07 PM]

Share this post


Link to post
Share on other sites
Hi!

Thank you very much for the code and the advices!

Well, the collision not work.

I know than the map array doesn´t work fine.

const short Pradera_map0[30][40] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 61, 1, 1, 1, 89,
90, 91, 92, 1, 1, 1, 63, 1, 1, 1, 1, 1, 1, 1, 104, 1,
1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 61, 1, 1, 1, 149,
150, 151, 152, 1, 1, 1, 63, 1, 1, 1, 1, 1, 1, 105, 104, 105,
1, 1, 1, 1, 1, 1, 1, 2 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 61, 89, 90, 91, 92,
1, 1, 89, 90, 91, 92, 63, 1, 1, 1, 1, 1, 1, 105, 105, 1,
1, 1, 1, 1, 1, 1, 1, 2 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 61, 109, 110, 111, 112,
1, 1, 129, 110, 111, 112, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 2 },
{ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 61, 149, 150, 151, 152,
1, 1, 149, 150, 151, 152, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 2, 2 },
{ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 81, 82, 82, 82, 82,
86, 87, 88, 82, 82, 82, 83, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 101, 102, 102, 102, 102,
106, 107, 108, 102, 102, 102, 103, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 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, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 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, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2 },
{ 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 15, 56, 56, 56, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 19 },
{ 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 35, 56, 56, 56, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 39 },
{ 33, 34, 34, 34, 34, 34, 34, 34, 145, 34, 34, 34, 34, 34, 34, 145,
34, 35, 56, 56, 56, 37, 38, 38, 38, 38, 145, 38, 38, 38, 38, 38,
38, 38, 145, 145, 38, 38, 38, 39 },
{ 33, 34, 34, 145, 34, 34, 34, 34, 34, 145, 34, 34, 34, 34, 34, 34,
145, 35, 56, 56, 56, 37, 38, 38, 145, 38, 38, 145, 38, 38, 38, 38,
38, 145, 38, 38, 38, 38, 38, 39 },
{ 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
145, 35, 56, 56, 56, 37, 38, 38, 145, 38, 38, 38, 38, 38, 38, 38,
38, 38, 38, 38, 38, 38, 38, 39 }
};



The PJ only can walk for 1, but he doesn´t move to anyplace...

The map, I only draw once, out of the loop; in main.

I know than this part are bad

Link.tX = Link.lastX / 32;
Link.tY = Link.lastY / 32;
Link.tX2 = (Link.lastX + 80) / 32;
Link.tY2 = (Link.lastY + 80) / 32;

Link.toca[0] = Pradera_map0[Link.tX][Link.tY];
Link.toca[1] = Pradera_map0[Link.tX2][Link.tY];
Link.toca[2] = Pradera_map0[Link.tX][Link.tY2];
Link.toca[3] = Pradera_map0[Link.tX2][Link.tY2];
...
void DrawMap(void) {
for(Pradera.posY = 0; Pradera.posY < 30; Pradera.posY++) {
for(Pradera.posX = 0; Pradera.posX < 40; Pradera.posX++) {
Pradera.tile->SetPosition(Pradera.posY * 32, Pradera.posX * 32);
Pradera.tile->Draw(NULL, Pradera_map0[Pradera.posX][Pradera.posY]);
Pradera.tile->Draw(NULL, Pradera_map1[Pradera.posX][Pradera.posY]);
}
}
}



Oh! Link.bucle isn´t nothing particular. Only it´s this way.

Well, cheers!

[Edited by - Puyover on March 11, 2007 8:31:58 AM]

Share this post


Link to post
Share on other sites
There many things that could be causing this problem. Without seeing the entire code it's hard to pinpoint an exact cause.

So your problem is that your sprite is going through all tiles, even the solid ones.
I would place the sprite in a solid block, then start debugging by stepping though the collision detection code line by line. That would enable me to detect the exact line where something went wrong.

I would also log the value of the Link.toca[] array and other pertinent variables each frame and look for suspicious values.

I also updated the source I posted above because I was using lastX instead of newX to get the tile coordinate.

Good Luck.

Share this post


Link to post
Share on other sites
Whoaa! The collision now works!!

The problem was in:

Link.tX = Link.X / 32;
Link.tY = Link.Y / 32;
Link.tX2 = (Link.X + 80) / 32;
Link.tY2 = (Link.Y + 80) / 32;


Really it was this way, like you said:

Link.tX = newX / 32;
Link.tY = newY / 32;
Link.tX2 = (newX + 80) / 32;
Link.tY2 = (newY + 80) / 32;


Thank you very very much!!!

Cheers and thank you!!!!

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