Problema de colisiones en Tetris

Encuentra personas para llevar adelante tu proyecto, muestra el progreso de esos proyectos y participa en competencias grupales.

Moderador: Dokan

Problema de colisiones en Tetris

Notapor Juanxo » Vie May 01, 2009 1:19 am

Buenas, estoy tratando de hacer un simple tetris, pero el problema es que no se me ocurre como manejar las colisiones laterales(es decir, que si pulso a derecha y hay otro bloque en esa posicion, no me deje realizar el movimiento.

Gracias

Juanxo
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor ceferino » Vie May 01, 2009 8:49 pm

Hola,

Para poder comprobar si un bloque colisiona con otro previamente necesitas tener almacenado el conjunto de bloques que ya han sido colocados al fondo de la pantalla (llamemosle 'muertos').
Lo que puedes hacer es dividir cada bloque en 4 bloquecitos, y tener una lista con todos los bloquecitos muertos. Entonces a la hora de mover el bloque en juego primero compruebas si algun bloquecito de ese bloque colisiona con algun otro de la lista de bloquecitos muertos.

En C++, un algoritmo podría ser así:

Código: Seleccionar todo
struct Bloquecito {
      SDL_Surface * pixmap;
      SDL_Rect posicion, clip;
};

struct Bloque {
      struct Bloquecito * bloquecitos[4];
      int centro_x, centro_y;
};

vector<Bloquecito*> bloquecitos_muertos;

bool colisiona_bloque (Bloque* bloque)
{
    vector<Bloquecito*>::iterator it;
    for (it=bloquecitos_muertos.begin(); it!=bloquecitos_muertos.end();it++)
    {
      for (int i=0; i<4;i++)
      {
       if(colisiona_rect((*it)->posicion,bloque->bloquecitos[i]->posicion))
                return true;
      }
    }
    return false;
}



Donde colisiona_rect() comprueba si dos SDL_rect's intersectan. Puedes encontrar esta función en casi cualquier juego, es bastante sencilla.

Por otro lado tene en cuenta que ademas debes llevar cuenta de que cantidad de bloquecitos muertos hay en cada linea, por lo que en realidad convendria utilizar una matriz para los bloquecitos muertos. Donde para cada fila i le corresponde un vector con los bloquecitos pertenecientes a la linea i , entonces las estructuras quedarían así:

Código: Seleccionar todo
struct Bloquecito {
      SDL_Surface * pixmap;
      SDL_Rect posicion, clip;
      // nuevo atributo.... inicialmente 'false'
      bool muerto;
};

struct Bloque {
      struct Bloquecito * bloquecitos[4];
      int centro_x, centro_y;
};

// una matriz,  m[i][j] representa el bloque j de la linea i
vector<vector<Bloquecito*> > bloquecitos_muertos;


Luego, recorriendo esa matriz puedes determinar la cantidad de bloquecitos muertos para cada linea, y asi eliminar esa linea (que en este caso seria eliminar una fila de la matriz).

Si no estas familiarizado con la biblioteca STL te recomiendo el sitio:

http://www.cplusplus.com/reference/

saludos!!
Ceferino


Zeitgeist!! - www.zeitgeistmovie.com/
Avatar de Usuario
ceferino
 
Mensajes: 4
Registrado: Vie May 01, 2009 7:41 pm
Ubicación: Argentina

Notapor endaramiz » Dom May 03, 2009 1:31 pm

Hola, hay otra manera más simple de plantear el problema que usando un struct Bloquecito. La idea consiste en que toda la lógica se hace únicamente con una matriz de enteros (toda la pantalla con los cuadrados en reposo) y una pieza compuesta de una matriz y una posición. El entero tiene valor 0 si no hay ningún cuadrado en esa posición o un número diferente de 0 si hay un cuadrado (el número indica el color).
Planteado de esta manera, comprobar las colisiones es bien simple:
Código: Seleccionar todo
bool col(int f, int c, const Matriz& pieza, const Matriz& pantalla) {
    for (int i = 0; i < altura_pieza; ++i) {
        for (int j = 0; j < anchura_pieza; ++j) {
            if (pieza[i][j] and pantalla[i+f][j+c]) return true;
            //if (pieza[i][j] != 0 and pantalla[i+f][j+c] != 0) return true;
        }
    }
    return false;
}

Donde la 'f' y la 'c' es la posición de la pieza. Un int se trata como un bool: false sí y solo sí el int es 0. El tipo Matriz dejo que lo definas a tu gusto: como un array o verctor de vector. Si eliges la segunda opción, compilalo con optimización ya que sinó puede notarse la ineficiencia del vector.

Hola ceferino, bienvenido al foro. Si quieres tener un contenedor donde importa añadir y quitar cosas rápidamente y, sin embargo, no importa el orden de los elementos, es mejor usar una list que un vector (lo digo por el primer código: bloquecitos_muertos).

Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor ceferino » Dom May 03, 2009 8:21 pm

endaramiz escribió:Hola ceferino, bienvenido al foro. Si quieres tener un contenedor donde importa añadir y quitar cosas rápidamente y, sin embargo, no importa el orden de los elementos, es mejor usar una list que un vector (lo digo por el primer código: bloquecitos_muertos).


Buenas,
Claro una list es mas adecuado, pero vamos, un tetris no necesita 100 FPS :-)

saludos.
Ceferino


Zeitgeist!! - www.zeitgeistmovie.com/
Avatar de Usuario
ceferino
 
Mensajes: 4
Registrado: Vie May 01, 2009 7:41 pm
Ubicación: Argentina

Notapor Juanxo » Dom May 03, 2009 9:25 pm

gracias a los dos por los comentarios. Miraré lo de las matrices, lo que pasa es que mi intención era hacerlo por colisiones...
Pero parece más facil con matrices, y mi objetivo de momento es tenerlo terminadito

Gracias a ambos
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)


Volver a Propuestas de desarrollo y concursos

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado