Desde donde es mejor verificar una colisión ?

0WindUp-Bird

Hola, como andan ? espero que bien :p

Estoy desarrollando un mini motor en SFML, y llegue al punto que quiero administrar las colisiones. Nunca vi otros engines de juegos 2D por lo que no tengo ni idea desde que clase o en que parte del código seria mas elegante poner las verificaciones de colisiones.

Dejo el link al código completo en github https://github.com/0Wind-UpBird/Run-Ball-Run-2

Por ejemplo, yo defino escenarios que agrupan los sprites, y los sprites de cualquier escenario pueden solicitar al escenario (cualquiera definido) los datos de alguno de los sprites que lo componen.

En el juego, yo tengo gráficamente algo así actualmente:

http://k32.kn3.net/taringa/1/5/9/3/6/2/13/casiquecasimiro/BE2.jpg

y no se, si es mejor luego de la captura de eventos, sea desde la clase Pelota la que pregunte "Choque con la plataforma negra ?" o que sea la plataforma negra "Choque con la pelota?"



void CApp::loopGame()
{	

while ((*window).isOpen())
{
	this->clock.restart();		

	this->catchEvent();	
	this->clearScreen();
	this->draw();
	this->displayWindows();

	this->currentTimeInLoop = this->clock.getElapsedTime();
}
}


void CApp::catchEvent()
{
	sf::Event evento;
	this->updateBeforeEvent();

while ((*window).pollEvent(evento))
{
	this->updateEvent(evento);
}

//aca ejecutaria el updateAfterEvent de cada sprite de la escena actual
	this->updateAfterEvent();
}




y en cada sprite, cual seria el correcto ?


void Pelota::updateAfterEvent()
{
	//choque con la plataform ?
}

void Plataforma::updateAfterEvent()
{
	//choque con la pelota ?
}

o si es mejor idea, implementar propio al escenario, "algo" a lo que se le indique previamente "Verifica si todos estos sprites chocan, y si chocan, avísales del choque a estos sprites."



void CApp::loopGame()
{	

while ((*window).isOpen())
{
	this->clock.restart();		

	this->catchEvent();	
	this->clearScreen();
	this->draw();
	this->displayWindows();

	this->currentTimeInLoop = this->clock.getElapsedTime();
}
}


void CApp::catchEvent()
{
	sf::Event evento;
	this->updateBeforeEvent();

while ((*window).pollEvent(evento))
{
	this->updateEvent(evento);
}

//Cordinador es mi clase que agrupa y cordina los escenarios, cuando termina uno, cual sigue, etc...
	this->cordinador->getEscenario()->VerificarTodasLasColiciones();

this->updateAfterEvent();
}
}

y tener previamente en el escenario juego


#include "EscenaJuego.h"

CEscenaJuego::CEscenaJuego(void)
{
	this->key = ESCENA_JUEGO;
}

CEscenaJuego::~CEscenaJuego(void)
{

}

bool CEscenaJuego::isEndEscena(sf::Event)
{
	return false;
}
					  
std::string CEscenaJuego::getKeyOfNextEscena() { std::string str = ""; return str; } void CEscenaJuego::InicializarColisiones() { //el mensaje de aviso del choque daría info del mismo, como cordenada del choque, sprites involucrados, etc... this->MenejadorDeColisiones->AgregarVerficiacion(Array_De_Objetos_A_Verificar, Array_de_Objetos_A_Avisar_en_Caso_de_Choque); this->MenejadorDeColisiones->AgregarVerficiacion(Array_De_Objetos_A_Verificar, Array_de_Objetos_A_Avisar_en_Caso_de_Choque); this->MenejadorDeColisiones->AgregarVerficiacion(Array_De_Objetos_A_Verificar, Array_de_Objetos_A_Avisar_en_Caso_de_Choque); }

Desde ya muchas gracias y felices fiestas :p

cabron

Para detectar colisiones se usan normalmente dos pasos, el primero se llama Broad Phase, que básicamente consiste en dividir tu escenario en Quads, y detectar que sprites están en cada quad.

Luego solo tienes que comprobar colisiones entre los sprites que estén en el mismo quad, así te evitas tener que comprobar todos con todos.

Para hacer la broad phase necesitas conocer todos los objetos existentes y sus posiciones, que en tu caso sería el escenario. Además eso significa que la colisión se detectaría tanto en la pelota como en la plataforma, y tu pones en cada uno como quieres que se responda a esa colisión, puede responder solo uno, o los dos.

Sobre si hacer notificaciones o polling a veces es mejor uno, y a veces otro, Box2d por ejemplo te permite las dos cosas.

1
0WindUp-Bird

gracias cabron por tu respuesta, al final, termine haciendo un híbrido jaja,

los del Quads ya lo había leído, junto al tema de la proyección del objeto en el tiempo, cuando el desplazamiento es mayor al tamaño del objeto...

En fin, la solución que me idee, fue la creación de dos clases <colisiometro> y <chocantes> donde la segunda define un función virtual para el polling en caso de colisiones, y un conjunto de rectángulos/círculos. Colisiometro(clase estatica) contiene métodos para probar colisiones, actualmente, sus métodos reciben dos clases chocantes que intentara ver si chocan, y un ultimo parámetro a la clase a la cual le avisara del choque. a futuro pienso agregarle flag de si tiene usar quads, proyecciones en tiempo, o algún algoritmo especifico...

Luego, desde cualquier clase Sprite, le pide al Escenario el chocante de los sprites, y probara el choque

Usuarios habituales

  • 0WindUp-Bird
  • cabron