2012-04-29 23 views
5

Estoy haciendo un juego Java usando fichas. Estoy teniendo problemas con el elemento de colisión. Estoy definiendo rectángulos para cada tesela en el mapa, y otro rectángulo para el jugador. Lo que estoy teniendo problemas es saber de qué lado viene el jugador cuando golpea el rectángulo, y luego empujar al jugador en la dirección en que vino el jugador. Ya hice un método que verifica cuánto está el personaje dentro del rectángulo, de modo que pueda saber cuánto empujarlo, pero no puedo encontrar la forma de decir de qué lado proviene el personaje.Java Tile Game - Detección de colisiones

aquí es mi actual colisión methoe - nota rect1 es el carácter y rect2 es el azulejo

public void collision(Rectangle rect1, Rectangle rect2) { 
    float xAdd; 
    float xAdd2; 
    float yAdd; 
    float yAdd2; 

    boolean hitRight = false; 
    boolean hitLeft = false; 
    boolean hitTop = false; 
    boolean hitBot = false; 

    Vector2f rect1Origin = new Vector2f(rect1.x, rect1.y); 
    Vector2f rect2Origin = new Vector2f(rect2.x, rect2.y); 
    Vector2f rect1Mid = new Vector2f((rect1.x + rect1.width)/2,(rect1.y + rect1.height)/2); 
    Vector2f rect2Mid = new Vector2f((rect2.x + rect2.width)/2,(rect2.y + rect2.height)/2); 

    Vector2f rect1A = new Vector2f(rect1Origin.x + rect1.width, rect1.y); 
    Vector2f rect1B = new Vector2f(rect1Origin.x, rect1Origin.y+ rect1.height); 
    Vector2f rect1C = new Vector2f(rect1Origin.x + rect1.width,rect1Origin.y + rect1.height); 

    Vector2f rect2A = new Vector2f(rect2Origin.x + rect2.width, rect2.y); 
    Vector2f rect2B = new Vector2f(rect2Origin.x, rect2Origin.y 
      + rect2.height); 
    Vector2f rect2C = new Vector2f(rect2Origin.x + rect2.width, 
      rect2Origin.y + rect2.height); 

    xAdd = rect2C.x - rect1B.x; 
    xAdd2 = rect1C.x - rect2B.x; 

    yAdd = rect2A.y - rect1B.y; 
    yAdd2 = rect2C.y - rect1A.y; 


    if (rect1Mid.y < rect2Mid.y) { 
     if (rect1.intersects(rect2)) { 
      y_pos += yAdd; 
     } 
    } 
    if (rect1Mid.y > rect2Mid.y) { 
     if (rect1.intersects(rect2)) { 
      System.out.println(yAdd2); 
      y_pos += yAdd2; 
     } 

    } 
    if(rect1Mid.x > rect2Mid.x){ 
     if(rect1.intersects(rect2)){ 
      hitRight = true; x_pos += xAdd; 
     } 
    } 
    if(rect1Mid.x< rect2Mid.x){ 
      if(rect1.intersects(rect2)) { 
       x_pos += -xAdd2; 
      } 
    } 
} 

Cualquier ayuda sería muy apreciada

Gracias

Respuesta

2

tener dos posiciones para tu personaje - dónde está (desde el último cuadro, movimiento, etc.) y hacia dónde quieres moverlo. A continuación, solo muévalo si no detecta una colisión: si no permite el estado dañado, no tiene que arreglarlo.

Editar: El método collision debe ser boolean - se debe hacer antes mover realmente el carácter, como

if (!collision(character, tile)) 
{ 
    doMove(character); 
} 
else 
{ 
    //custom handling if required 
} 

Edit2: El anterior funcionaría sólo por un pequeño paso, si necesita un movimiento parcial, realmente necesita conocer la posición original del personaje, como move(originalPosition, desiredPosition, tile), donde puede deducir la dirección de originalPosition y tile.

El punto principal es que, en realidad, no se mueve el carácter, antes de tener una posición válida para él.

+0

Esto dará lugar a una situación extraña, dependiendo del intervalo de paso de tiempo. – Matzi

+0

@Matzi En realidad, no hay nada de validación antes de ejecutar algún comando de usuario; si no lo valida, puede hacer un manejo personalizado. – jmruc

+0

@KirilRaychev Realmente no entiendo lo que está tratando de decir – grimrader22

1

En primer lugar, cualquier Sprite (el carácter y el mosaico aquí) debe tener cuatro miembros: xPos, yPos, xVec, yVec. Con eso en mente, sabes dónde estaba el personaje y cuál será el siguiente cuadro.

sprite.xPos += sprite.xVec; 
sprite.yPos += sprite.yVec; 

también echar un vistazo a su código, debería mejorar las proposiciones (por ejemplo, comprobar si (rect1.intersects (rect2)) en los cuatro si declaraciones). En su lugar, verifique solo una vez para intersects(), y dentro de cada caso posible (izquierda, derecha, arriba, abajo).

Finalmente, el método de colisión deben recibir 2 sprites objetos (por ejemplo, sprite1 y sprite2), y después de verificación de los intersecta() método, teniendo en cuenta las posiciones originales de los dos sprites y su vectores. Si los sprites se cruzan en la nueva posición, entonces inviertes el vector del objeto en consecuencia.

+0

¿Qué representan las variables xVec y yVec? – grimrader22

+0

Lo siento, no estaba tan claro, esos son los vectores direccionales del sprite (también puedes usar Vector2f o Point2D). El valor se puede interpretar como la velocidad del sprite en cada dirección. Entonces, si el personaje golpea la ficha exactamente desde la izquierda, xVec es un valor positivo, y yVec es 0; y después del golpe, xVec debería tener el mismo valor, pero ahora negativo. Avíseme si necesita más ayuda. –

+0

No entiendo muy bien lo que dices, lo siento si estoy siendo tonto. ¿Los x y y Vecs serían la velocidad? – grimrader22

1

Suponiendo que puede detectar la colisión con su código. Aquí hay una manera de determinar la posición de tu personaje con respecto al objeto rectángulo.

  1. Encuentra el punto medio del rectángulo. (Rx, Ry).

  2. Encuentra el punto medio de tu personaje sprite. (Sx, Sy).

  3. Ahora puede comparar Rx, Ry, Sx, Sy para determinar en qué lado está Sx y Sy de Rx y Ry

  4. para excepto:

    if Sx < Rx then 
        Sx = left side of Rx 
    
1

estaba luchando con esto mismo, pero después de pensar que este control se puede hacer teniendo todas tus entidades en una lista, en mi código tuve que bloquear al jugador para que no se moviera a través de bloques. Todos los bloques están en una lista. Ahora, al verificar la posición de los jugadores, creo un nuevo rectángulo y coloco a los jugadores un cuadro hacia delante en la dirección en que la actualización sucederá en el siguiente cuadro, si el rectángulo se cruza, esa actualización no se producirá en esa dirección. Aquí está mi código para esto:

if (isKeyPressed(KeyEvent.VK_LEFT)) { 
     if(!collisionWithBlocks(1)){ 
      pl.x = pl.x - updatePlayerPosition; 
     } 
    } 
    if (isKeyPressed(KeyEvent.VK_RIGHT)) { 
     if(!collisionWithBlocks(0)){ 
      pl.x = pl.x + updatePlayerPosition; 
     } 
    } 
    if (isKeyPressed(KeyEvent.VK_UP)) { 
     if(!collisionWithBlocks(3)){ 
      pl.y = pl.y - updatePlayerPosition; 
     } 
    } 
    if (isKeyPressed(KeyEvent.VK_DOWN)) { 
     if(!collisionWithBlocks(2)){ 
      pl.y = pl.y + updatePlayerPosition; 
     } 
    } 

collisionWithBlocks():

public boolean collisionWithBlocks(int side){ 
    for(Block b : main.blocks){ 
     Rectangle block = b.getBounds(); 
     Rectangle player = null; 
     if(side == 0){ 
      player = new Rectangle(pl.x + updatePlayerPosition, pl.y, pl.getWidth(), pl.getHeight()); 
     } else if(side == 1){ 
      player = new Rectangle(pl.x - updatePlayerPosition, pl.y, pl.getWidth(), pl.getHeight()); 
     } else if(side == 2){ 
      player = new Rectangle(pl.x, pl.y + updatePlayerPosition, pl.getWidth(), pl.getHeight()); 
     } else if(side == 3){ 
      player = new Rectangle(pl.x, pl.y - updatePlayerPosition, pl.getWidth(), pl.getHeight()); 
     } 

     if(player.intersects(block)){ 
      return true; 
     } 
    } 

    return false; 
} 

updatePlayerPosition es 2, y los cambios en mi código, pero lo suficiente sobre eso. En su caso, recomiendo poner las entidades en una lista y luego verificar como lo hice.

Cuestiones relacionadas