2011-08-10 13 views
5

Estoy programando un juego 2D basado en fichas en Java como Bomberman (mi primer juego).¿Cómo se coordina la posición gráfica y lógica en un juego 2D basado en fichas utilizando una matriz?

Utilizo una matriz 2D para representar el mapa en el que realizo un seguimiento de las paredes, espacios transitables, etc. Ahora pude hacer que el jugador se moviera suavemente cambiando los sprites dependiendo de la tecla de dirección que presiona (pero no interactuando con el fondo/mapa, puede caminar al azar y salir de la pantalla).

Mi problema surge cuando quiero hacer un seguimiento de la posición del jugador en la matriz. Lógicamente, el personaje siempre pertenece a un solo mosaico, pero gráficamente puede estar entre dos mosaicos. ¿Cómo puedo resolver este problema?

ya yo probamos este:

currentTileArrayX = x/tileWidth;

currentTileArrayY = y/tileHeight;

Donde xey son las coordenadas superiores-izquierdas del sprite. Pero todo se volvió muy defectuoso porque los sprites del jugador no son del mismo tamaño que los cuadros.

Tenía otra opción en mente que resolvería el problema anterior: Cuando el jugador presiona una tecla de dirección, mueve el personaje al siguiente mosaico como una animación. Esto no permitiría que el jugador se detenga en medio de dos fichas ... ¿Pero qué sucede si lo interrumpe con otra pulsación de tecla? ¿Cómo puedo detener la acción del usuario mientras se está ejecutando la animación? Creo que esta es la solución más fácil, pero no sé cómo implementarla.

Ya traté de encontrar la solución en otras preguntas, pero no tuve suerte. Espero que puedas ayudarme.

Muchas gracias.

Respuesta

2

Aaaaaaaaaaaaaaah! Encontrando el 'problema de espacio discreto' :) Su mapa de lógica es discreto pero sus movimientos de UI están en el espacio continuo.El usuario no puede estar en ambos cuadros "al mismo tiempo", sí visualmente, pero nunca "internamente". Ahora que está recibiendo la posición del jugador y que puede ser "en cualquier lugar" dentro de la baldosa o "en el límite" de 2 azulejos por así decirlo ...

Tiene dos soluciones a este problema, la OMI:

  1. Utilice el redondeo simple: si la posición del jugador es < tile-boundary solo manténgalo en la casilla anterior. Si es mayor en el siguiente. Ahora el problema de los límites: puede usar una heurística, ya que no debe confiar en la precisión de las comparaciones de coma flotante (es decir, comparar con 0 no es algo bueno que hacer). Así que puedes probar algo como esto if(currentPosition - boundary <= 0.000000001) y luego asumir que es el siguiente azulejo en el mismo.
  2. Bien @Jay me ganó. Así que el segundo es tener realmente una velocidad de movimiento definida y mover el carácter que muchos pasos por 'clic'/'presionar botón' - pero usted dice que tiene el problema de la tecla presionada en "entre". Supongo que si el código está diseñado como esto entonces no debería ser un problema:
 
    update() 
     { 
      calculate(); //update all datastructures/calculations 
      draw(); //update the visual representation based on calculations 
     } 

update() es a.k.a, gameLoop. Creo que esto debería resolver su problema ...

+0

Nupul Cambié mi código usando la solución número uno. Gracias a eso solucionó muchos errores, podría decir que casi funciona ahora. Pero todavía tengo un problema: http://imageshack.us/f/687/bomberbug.png/ Espero haberlo explicado correctamente en la imagen. – Rama

+0

En la imagen, currentPosition sigue siendo el mosaico rojo. Como la derecha del azulejo rojo es libre, puedo caminar hacia la derecha, pero no debo hacerlo gráficamente. – Rama

+0

@Rama: No está claro lo que quieres decir ... Si puedes caminar hacia la derecha, entonces "¿por qué no?" En segundo lugar, si "gráficamente" usted no debe, entonces, estructuralmente, tampoco debería permitírsele. Su modelo interno debe ser una representación precisa de su punto de vista. Si no puedo ir directamente al modelo, no debería permitírmelo en la vista y no al revés, ya que la vista es v.v.v.v orientada a decimales, por así decirlo. ¿Podría aclarar el problema un poco más si no lo he entendido correctamente? – PhD

1

Intentaré mantener la parte lógica (el mosaico al que pertenece el reproductor) y la parte de visualización (animación entre los mosaicos) lo más separada posible. Mi enfoque sería tener una ubicación lógica (el jugador está encendido) y una velocidad de movimiento (lo que esencialmente significa una cantidad de tiempo que el jugador no puede pasar a la siguiente ficha después de pasar a una ficha). Entonces, la animación de una ficha a otra significaría que tu sprite siempre se mueve hacia las coordenadas de la pantalla de tu ficha; el tiempo que esto tome podría determinarse fácilmente por la velocidad de movimiento (un movimiento completo debería durar tanto como el jugador tenga que descansar en el mosaico actual).

El único caso especial sería este "giro", en el que permitiría que el jugador regrese a la ficha de la que procede en cualquier momento, tomando solo (timeToRecoverOnTile - (timeToRecoverOnTile - timeSinceMovementStarted)).

1

Una vez hice básicamente lo mismo en AS3, pero el concepto se transfiere a Java. Decidí crear dos valores principales para ayudar a mantener un seguimiento del movimiento, un Punto que contiene el valor x/y del jugador (por mosaico) y un Punto de dirección para la dirección del movimiento. He aquí algunos pseudo-código:

if(direction.x == 0 && direction.x == 0) { 
    if (up) direction.y = -1; 
    else if (down) direction.y = 1; 
    else if (left) direction.x = -1; 
    else if (right) direction.x = 1; 
} else { 
    player.x += direction.x; 
    player.y += direction.y; 
    distance--; 
    if(distance == 0) { 
     direction.x = direction.y = 0; 
     distance = tileWidth; 
    } 
} 

Obviamente, habría que modificar eso para satisfacer sus necesidades, pero eso es lo básico. Además, tileWidth se puede reemplazar por un literal entero que simplemente es igual al ancho de una única ficha.

Cuestiones relacionadas