2015-06-23 22 views
9

Sono stato a questo per 2-3 settimane e non riesco ancora a ottenere un rilevamento di collisione corretto. Ho creato un labirinto usando rettangoli. Voglio che il mio oggetto (che si trova in un rettangolo) si fermi ogni volta che il mio oggetto entra in collisione con qualsiasi muro e può spostarsi ovunque (o scivolare lungo un muro). Le mie pareti (i rettangoli) hanno coordinate negative come la seguente:Rilevamento di collisioni tra rettangoli (nessuna sovrapposizione) - libgdx

shapeRenderer.rect(0.9f, 12, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); //NORTH 
shapeRenderer.rect(1, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // WEST 
shapeRenderer.rect(2, 12, 0, -1.05f, Color.RED, Color.RED, Color.RED, Color.RED); // EAST 
shapeRenderer.rect(0.9f, 11, 1.15f, 0, Color.RED, Color.RED, Color.RED, Color.RED); // SOUTH 

Attualmente sto usando un metodo di sovrapposizioni che ho trovato in SO. Ecco il metodo che è nella mia classe CollisionManager:

private boolean overlaps (Rectangle collision, Rectangle wall) { 
    return Math.min(collision.x, collision.x + collision.width) 
     < Math.max(wall.x, wall.x + wall.width) 
    && Math.max(collision.x, collision.x + collision.width) 
     > Math.min(wall.x, wall.x + wall.width) 
    && Math.min(collision.y, collision.y + collision.height) 
     < Math.max(wall.y, wall.y + wall.height) 
    && Math.max(collision.y, collision.y + collision.height) 
     > Math.min(wall.y, wall.y + wall.height); 
} 

Ho una funzione che salva tutte le mosse di posizione da parte l'oggetto. Così, quando si verifica una collisione, l'oggetto restituisce alla mossa precedente prima che l'ultima mossa (dal momento che l'ultima mossa è quando la collisione si è verificato) (esempio qui sotto):

private void overlapsTop(Entity object, Rectangle wall){ 

    Rectangle r = new Rectangle(); 
    if(spritePositions.size() != 0){ 
     r = spritePositions.get(spritePositions.size()-1); 
    } 
    object.update(r.x, r.y, r.width, r.height); 
    object.getObject().setBounds(r.x, r.y, r.width, r.height); 
    spritePositions.clear(); 
} 

Ulteriori informazioni: mi sto muovendo il mio oggetto In questo modo:

public void moveRight(){ 
    position.x += 1f; 
    update(); 
} 

public void update(){ 

     boundingRectangle.set(position.x, position.y, object.getWidth(), object.getHeight()); 
} 

Dove sono bloccato è la funzione di sovrapposizioni (quella che ho trovato in SO). Funziona nella maggior parte dei casi; tuttavia, ad esempio, se l'oggetto si sposta vicino a un muro a destra e lo tocca, la funzione restituisce true e tutto viene eseguito. Ma diciamo che se scivolo lungo il muro e mi muovo direttamente verso il basso e che non ci sono muri, l'oggetto si arresta in un punto perché rileva una collisione tra il fondo dell'oggetto e la parte superiore di un muro (quando non ce n'è) e un collisione tra il diritto dell'oggetto e la sinistra di un muro.

Sto cercando di trovare un'altra soluzione per questo. Voglio solo che il mio oggetto si fermi su qualsiasi muro e che sia in grado di muoversi (o scivolare giù da un muro) senza sospettare che possa esserci una collisione in cui non ci sono muri nelle vicinanze. Sento di essere molto vicino a una soluzione, ma avrei bisogno di un po 'di aiuto in più.

UPDATE

Ho aggiornato la funzione MoveRight e la funzione di aggiornamento. @Adrian Shum e @Matthew Mark Miller Ho fatto tutto ora con un numero intero (significato invece di 0.01f, io uso 1f).

Così il seguente codice che uso per spostare l'oggetto è come questo:

if(Gdx.input.isKeyPressed(Keys.RIGHT)){ 

       if(collisionManager.canSpriteNotMoveRight(object)){ 
        object.stopGoingRight(); 
       }else{ 
        object.moveRight(); 
       } 
      } 

Nella mia classe collisionManager, la funzione stopGoingRight è la seguente:

public void stopGoingRight(){ 
    position.x -= 1f; 
    update(); 
} 

Finora, così buono. Quando l'oggetto si scontra con il muro, l'oggetto si arresta e rimbalza. Quello è buono. Ma ho un altro problema (che è irritante) che cercherò di descrivere il meglio che posso. Se, ad esempio, continuo a spostare l'oggetto fino a un muro, l'oggetto si riprenderà più volte da quel muro; se smetto di premere il tasto Su, l'oggetto a volte rimane bloccato nel muro. Quindi quello che succede è quando premo il tasto giù, salirà invece di scendere (o se premo a sinistra, l'oggetto andrà a destra invece di andare a sinistra) perché la funzione di sovrapposizione viene eseguita (poiché sia ​​l'oggetto che il muro intersecano).

C'è un modo per risolvere questo? Sembra che Libgdx non sia perfettamente adatto per gestire questo tipo di rilevamento delle collisioni, ma sono molto avanti nel costruire il mio gioco proprio adesso.

+0

È possibile ruotare il rettangolo che si sta controllando? O stai semplicemente ruotando la sua voce? –

+0

Sì, è possibile controllarne la rotazione. Fondamentalmente, quando si sposta in basso, in alto, a destra o a sinistra, l'oggetto ruoterà in modo corrispondente. –

+0

Ma il 'Rettangolo' sarà sempre allineato all'Asse giusto? – Springrbua

risposta

4

ho finalmente trovato una buona soluzione tutto grazie al seguente link: On overlap, player gets stuck libgdx Rectangle.

Fondamentalmente devo creare una mossa "falsa" per vedere se l'oggetto si scontrerà con il muro. In caso di collisione, interrompo l'oggetto e non eseguo la nuova mossa.

Grazie per l'aiuto di tutti :) !! È molto apprezzato !!

5

L'algoritmo di collisione sembra prolisso ma corretto (Wordy perché il minimo di x, x + larghezza è sempre solo x come larghezza deve essere> = 0 e l'inverso è vero per max).

Avete considerato la possibilità che si tratti di un problema di precisione in virgola mobile? Ad esempio, se aggiungi 1 a un numero fp, quindi rimuovi 1 dal risultato, non ti sarà garantito il ritorno al valore originale. Potresti essere un po 'più o meno come il risultato intermedio potrebbe non essere rappresentabile come un galleggiante.

Il mio esempio preferito: .1f + .2f> .3f