Problemas de detección de colisión 2D basados ​​en mosaicos

8

Estoy tratando de seguir este tutorial http://www.tonypa.pri.ee/tbw/tut05.html para implementar colisiones en tiempo real en un mundo basado en mosaicos.

Encuentro las coordenadas centrales de mis entidades gracias a estas propiedades:

public float CenterX
{
    get { return X + Width / 2f; }
    set { X = value - Width / 2f; }
}
public float CenterY
{
    get { return Y + Height / 2f; }
    set { Y = value - Height / 2f; }
}

Luego, en mi método de actualización, en la clase de jugador, que se llama cada cuadro, tengo este código:

public override void Update()
{
    base.Update();

    int downY = (int)Math.Floor((CenterY + Height / 2f - 1) / 16f);
    int upY = (int)Math.Floor((CenterY - Height / 2f) / 16f);
    int leftX =     (int)Math.Floor((CenterX + Speed * NextX - Width / 2f) / 16f);
    int rightX = (int)Math.Floor((CenterX + Speed * NextX + Width / 2f - 1) / 16f);

    bool upleft = Game.CurrentMap[leftX, upY] != 1;
    bool downleft = Game.CurrentMap[leftX, downY] != 1;
    bool upright = Game.CurrentMap[rightX, upY] != 1;
    bool downright = Game.CurrentMap[rightX, downY] != 1;

    if(NextX == 1)
    {
        if (upright && downright)
           CenterX += Speed;
        else
           CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
    }
 }

downY, upY, leftX y rightX deben encontrar respectivamente la posición Y más baja, la posición Y más alta, la posición X más a la izquierda y la posición X más a la derecha. Agrego + Speed ​​* NextX porque en el tutorial la función getMyCorners se llama con estos parámetros:

getMyCorners (ob.x+ob.speed*dirx, ob.y, ob);

Los métodos GetCellX y GetCellY:

public int GetCellX(float mX)
{
    return (int)Math.Floor(mX / SGame.Camera.TileSize); 
}
public int GetCellY(float mY)
{
    return (int)Math.Floor(mY / SGame.Camera.TileSize); 
}

El problema es que el jugador "parpadea" mientras golpea una pared, y la detección de esquinas ni siquiera funciona correctamente, ya que puede superponer paredes que solo golpean una de las esquinas. No entiendo lo que está mal. En el tutorial, los campos ob.x y ob.y deben ser iguales a mis propiedades CenterX y CenterY, y ob.width y ob.height deben ser iguales a Width / 2f y Height / 2f. Sin embargo, todavía no funciona.

Gracias por tu ayuda.

Vee
fuente
¿Estás probando la colisión una vez que el jugador está en ese lugar y poniéndola de nuevo si choca o estás probando si el siguiente movimiento es una colisión?
kyndigs
Recomendaría agregar una comprobación de pulsación de tecla en esa función de actualización que interrumpirá el proceso actual cuando presione la tecla. Luego presione la tecla cuando el jugador esté "parpadeando" y camine a través del depurador. (preste atención a lo que les está sucediendo a los números) Trate de averiguar qué les está sucediendo a los números cuando parpadea.
Michael Coleman

Respuestas:

1

Un par de sugerencias, aunque no estoy seguro de que solucionarán el problema, ya que no tengo el código completo para ejecutar y depurar.

En este código:

if(NextX == 1)
{
    if (upright && downright)
       CenterX += Speed;
    else
       CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
}

la instrucción else mueve el objeto aunque el objeto no debería moverse.
Supongo que está tratando de hacer que el objeto quede al ras contra la pared, pero tal vez el cálculo sea incorrecto.
Si comenta la declaración else, ¿el objeto todavía parpadea?

El cálculo parece un poco sospechoso ya que resta (Ancho / 2f) y luego el operador del conjunto CenterX hace la misma resta nuevamente.

Otra cosa que me gustaría señalar, solo para ayudar a la claridad del código, es que hizo que las propiedades de CenterX calculen el valor una y otra vez, pero el código todavía está lleno del mismo cálculo una y otra vez.
Esto bien podría ser parte del problema. De cualquier manera, sugeriría hacer algunas propiedades más y establecer un estándar para todas ellas. Por ejemplo, haga que el Centro sea la propiedad almacenada y calcule los demás a partir de él:

public float CenterX
{
    get { return X; }
    set { X; }
}

public float LeftX
{
    get { return CenterX - Width / 2f; }
    set { CenterX = value + Width / 2f; }
}

public float RightX
{
    get { return CenterX + Width / 2f; }
    set { CenterX = value - Width / 2f; }
}
Paulo Pinto
fuente