Problemi di rilevamento delle collisioni 2D basati su piastrelle


8

Sto cercando di seguire questo tutorial http://www.tonypa.pri.ee/tbw/tut05.html per implementare collisioni in tempo reale in un mondo basato su piastrelle.

Trovo le coordinate centrali delle mie entità grazie a queste proprietà:

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; }
}

Quindi nel mio metodo di aggiornamento, nella classe del giocatore, che si chiama ogni frame, ho questo codice:

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 e rightX dovrebbero rispettivamente trovare la posizione Y più bassa, la posizione Y più alta, la posizione X più a sinistra e la posizione X più a destra. Aggiungo + Speed ​​* NextX perché nel tutorial la funzione getMyCorners viene chiamata con questi parametri:

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

I metodi GetCellX e 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); 
}

Il problema è che il giocatore "sfarfalla" mentre colpisce un muro e il rilevamento dell'angolo non funziona nemmeno correttamente poiché può sovrapporsi ai muri che colpiscono solo uno degli angoli. Non capisco cosa c'è che non va. Nel tutorial i campi ob.xe ob.y dovrebbero essere gli stessi delle proprietà CenterX e CenterY e ob.width e ob.height dovrebbero essere uguali a Width / 2f e Height / 2f. Tuttavia non funziona ancora.

Grazie per l'aiuto.


Stai testando la collisione una volta che il giocatore si trova in quel punto e lo sta riprendendo se si scontra o stai testando se la mossa successiva è una collisione?
kyndigs l'

Vorrei raccomandare di aggiungere un tasto premere check in quella funzione di aggiornamento che interromperà il processo corrente quando si preme il tasto. Quindi premi il tasto quando il giocatore "sfarfalla" e cammina attraverso il debugger. (presta attenzione a ciò che sta accadendo ai numeri) Prova a scoprire cosa sta succedendo ai numeri quando lampeggia.
Michael Coleman,

Risposte:


1

Un paio di suggerimenti, anche se non sono sicuro che risolveranno il problema in quanto non ho codice completo da eseguire ed eseguire il debug.

In questo codice:

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

l'istruzione else sta spostando l'oggetto anche se l'oggetto non dovrebbe muoversi.
Immagino che tu stia cercando di far fluire l'oggetto contro il muro ma forse il calcolo non è corretto.
Se commentate l'istruzione else, l'oggetto sfarfalla ancora?

Il calcolo sembra un po 'sospetto in quanto sottrae (Larghezza / 2f) e quindi l'operatore del set CenterX esegue di nuovo la stessa sottrazione.

Un'altra cosa che vorrei sottolineare, solo per aiutare la chiarezza del codice, è che hai fatto in modo che le proprietà di CenterX calcolino il valore avanti e indietro, ma il codice è ancora disseminato dello stesso calcolo più e più volte.
Questo potrebbe far parte del problema. Ad ogni modo, suggerirei di creare qualche proprietà in più e stabilirmi su uno standard per tutti. Ad esempio, fai in modo che il Centro sia la proprietà memorizzata e calcola gli altri da esso:

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; }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.