[MULTI] Colisiones entre sprites y tiles.

Hola a todos!

Veréis llevo ya bastante tiempo intentando que me funcionen las colisiones entre un sprite y un mapa de tiles.

Bien, el mapa lo almaceno en una matriz y lo cargo con un bucle.
Eso creo que lo hago bien.

Bueno os pongo el código que uso:
/** FUNCION DE RENDERIZADO LOGICA **/
void RenderGraphics(int bLogicUpdate) {
PJHandler();
DrawMap();
Link.GFX->Draw();
}

/** FUNCION DE MANEJO DEL PJ **/
void PJHandler(void) {
// Realizamos un mapeado del teclado
keyboard = SDL_GetKeyState(NULL);

// Guarda la última posición válida
Link.lastX = Link.posX;
Link.lastY = Link.posY;

// Usa otras variables para almacenar la posible nueva posición
int newX = Link.posX;
int newY = Link.posY;

// Comprobamos los movimientos de Link y las colisiones
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 se pulsa ninguna tecla
Link.GFX->Pause();
Link.GFX->SelectFrame(0);
}

// Covertimos cada posición, a coordenadas de tiles
Link.tX = Link.lastX / 32;
Link.tY = Link.lastY / 32;
Link.tX2 = (Link.lastX + 80) / 32;
Link.tY2 = (Link.lastY + 80) / 32;

// Obtenemos las direcciones del PJ
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-configuramos la variable como verdadera
Link.libre = true;

// Recorremos todas las direcciones a las que se puede mover el PJ
// y comprobamos si se puede mover
for(int bucle = 0; bucle < 4; bucle++){
if(Link.toca[bucle] == 1) Link.libre = true;
}

// Nos movemos, así que actualizamos la nueva posición del PJ
if(Link.libre == true) {
Link.GFX->SetPosition(newX, newY, 0);
} else {
// No nos podemos mover, así que restauramos la posición anterior
Link.posX = Link.lastX;
Link.posY = Link.lastY;
}
}
/** FUNCION QUE DIBUJA LOS MAPAS **/
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]);
}
}
}

Como podéis ver, uno de los mapas lo tengo comentado, porque si lo cargo, me funciona todo muy lento. Otra cosa que podría hacer, es llamar una sola vez a la función DrawMap(), entonces me iría a una velocidad normal, aunque no se si influirá en algo, que no se actualice el mapa continuamente.

En fin, a ver si podéis decirme donde está el fallo, porque ya no se que hacer [snif]

Ah, uso la librería CRM32Pro que trabaja sobre SDL.

Salu2 y gracias!!
No se en que programas, pero lo que si que creo es que cargar continuamente un fondo creo que es innecesario...

Una vez que lo cargas, lo puedes mover, pero solo lo cargas UNA vez :S
Por partes:
1. Como bien dice Lupi, cargar el fondo más de una vez és innecesario. Al haberlo metido en un bucle lo que te hace es a cada frame vaciar la memoria que ocupan los tiles del mapa y volver a cargar (supongo que lo haces desde disco) la imagen en el mismo lugar... y eso SE COME LA VELOCIDAD.

2. Si uno de los dos mapas es de durezas (porque si és de tiles animados u otro plano de scroll no hagas caso a éste punto), no hace falta blitearlo en pantalla por varios motivos:
a)Luego le blitearias encima el de los gráficos buenos y se taparía.
b)Simplemente con crear una función que detectara dónde está Link (sobre que tile) no haría falta (y no te recomiendo un mapa de durezas y detectar colores por propia experiencia).

Yo lo haría con una función que te detectara las colisiones según es tile sobre el que se encontrara una parte del prota. Por la derecha por ejemplo sería (Link.posX + Link.ancho - 32 (tamaño del tile que usas) - 1 ) / 32 (tamaño del tile)
ésto te daría el tile con el que colisiona por la derecha y luego con un switch miras qué número de tile és y si devuelve colision o no (y por tanto en la funcion de movimiento le dejarías avanzar)


No me he explicado demasiado bien pero espero que te hagas una ligera idea de cómo hacerlo si pasas del método que pone tu librería [+risas]
Saludos!
Oki gracias. Al final conseguí tener colisiones cargando un mapa de tiles y obteniendo la casilla con la que colisionaría el PJ si lo muevo en cierta dirección. Si colisiona, pues no lo muevo y lo dejo en la posición anterior.

Ahora estoy intentando meter scroll, ¿entonces decís que no tengo que redibujar el mapa en cada frame? igual ese es el problema de porque tampoco me funciona el scroll xD.

Venga salu2 y gracias!!
a ver, a cada frame lo que no hay que hacer es CARGAR el mapa, pero si le vas a hacer scroll (o si se va a blitear algo encima q se mueva) si que hace falta dibujar el mapa cada frame porque si no link iria dejando un rastro encima...

yo el scroll si no tiene una funcion tu librería haría algo cómo lo que tengo puesto yo en el juego q estoy haciendo: cuando el personaje cruza determinado punto de la pantalla (x ej: 300) le sumo a una variable para la camara (yo lo llamo camarax y camaray) la velociadad a la que anda el personaje y luego en el bliteo del mapa añadiría algo así:

/** FUNCION QUE DIBUJA LOS MAPAS **/
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 - camaray , Pradera.posX * 32 - camarax );
Pradera.tile->Draw(NULL, Pradera_map0[Pradera.posX][Pradera.posY]);
// Pradera.tile->Draw(NULL, Pradera_map1[Pradera.posX][Pradera.posY]);
}
}
}


**teniendo en cuenta que camarax suma la velocidad del personaje en el limite de la derecha de la pantalla y lo resta en el de la izquierda y camaray suma hacia abajo y resta hacia arriba.

Así debería funcionarte, digo yo... aunque no programe demasiado bien [decaio]

Pruebalo y me dices si te va, Saludos!
4 respuestas