18 años en Internet

14 diciembre 2024

Adaptando el WLD_VIEW.PRG de DIV2 Games Studio a controles actuales

     Como os comentaba en la entrada anterior, donde explicaba cómo instalar DIV y DIV2 Games Studio en ordenadores actuales (enlace), DIV 2 traía un programa de ejemplo para pasear por un escenario 3D (llamado WLD_VIEW.PRG).

    El caso es que ese ejemplo ha envejecido bastante mal, puesto que hace uso de los cursores para desplazarse y no hace uso del ratón para mover la cámara... Aunque siendo justos esos controles no estaban mal en 1998 y además el programa estaba pensado más bien para navegar por escenarios 3D y no para comportarse como un shoter. Pero aún así considero que a día de hoy sus controles están bastante desfasados.

Todo "esto" es el bucle principal del programa de ejemplo.

    Si observamos el bucle principal del WLD_VIEW.PRG, vemos que los controles son los siguientes:

  • Tecla "Escape" para salir del juego.
  • Tecla ALT + Izquiera o derecha para desplazarse de costado.
  • Izquierda o Derecha para girar la cámara.
  • Arriba para avanzar la cámara.
  • Abajo para retroceder la cámara.
  • Q para subir la cámara.
  • A para bajarla.
  • W para mirar hacia arriba.
  • S para mirar hacia abajo.

    Así que un servidor se preguntó qué tal se sentiría si alterara el programa para darle controles más actuales, con el ya clásico W-A-S-D para desplazarse, el ratón para girar la cámara y además poder correr, saltar o agacharse. Y la verdad es que como ejercicio no fue tan complicado como pensaba.

     Para el manejo de la cámara con el ratón lo que hago es alterar las variables angle y m8.angle en función de las posiciones X e Y del puntero del ratón (que las obtienes con mouse.x y mouse.y). Pero para que se "sienta" bien, he tenido que tener ciertas consideraciones:

  1. El movimiento en el eje X (el que utilizo para girar la cámara de izquierda a derecha) se calcula en función del delta con el frame anterior. Es decir, si en el anterior frame el puntero del ratón estaba en la coordenada 320 y en el actual está en el 310, entiendo que hay un delta de -10 y que por consiguiente la cámara debe girar a la izquierda. De la misma forma, la cámara girará más brúscamente o menos brúscamente en función del delta: Si el delta es -100, giraremos más rápido que si éste fuera -10.
  2. El cursor del ratón tiene un valor máximo y éste varia en función de la resolución de la pantalla. Por ejemplo, si haces uso de una resolución de pantalla de 320x200, el valor máximo que tendrá el mouse.x será de 319 y el del mouse.y será de 199; Si la resolución es de 800x600, el valor máximo de mouse.x será de 799 y el de mouse.y será de 599. En todos los casos, el valor mínimo será siempre 0. ¿Por qué os digo esto? Porque al tener valores mínimos y máximos de mouse.x, a base de girar a tope a derecha o izquierda llega un momento en el que la cámara dejará de girar. Para evitar esto, cuando el la posición X del ratón ocupa su valor mínimo (0) o máximo, reposiciono el cursor del ratón al centro de la pantalla (resolución de pantalla del eje X dividido entre 2). La ñapa funciona bastante bien, cuando juegas ni te das cuenta.
  3. El m8.angle es lo que nos permite mirar hacia arriba o hacia abajo... Pero tiene un valor mínimo de -128 y un valor máximo de 128, siendo 0 el valor centrado... y es imposible girar más la cámara en el eje Y. Para saber el valor exacto del ángulo a aplicar, multiplico el valor máximo de la posición Y del cursor del ratón por 256 (rango máximo de valores del m8.angle), lo divido por la resolución del juego en su eje Y y ese valor se lo resto a 128. De esta forma de me aseguro de tener valores que van del -128 al 128.
  4. En el eje Y no hace falta hacer la ñapa de recentrar el ratón, puesto que el entorno nos impide girar al máximo la cámara para el eje Y (es decir, no puedes ver 90 grados hacia arriba o hacia abajo).


Captura de pantalla de la ayuda de Div2, donde explican los valores mínimos y máximos del m8.angle.

    Para los desplazamientos he tenido las siguientes consideraciones:
  1. Para el desplazamiento lateral símplemente he remapeado los xadvance para que se ejecuten diréctamente con las teclas A y D.
  2. He remapeado los advance para utilizar el W y el S.
  3. Para el caso de W y S, verifico antes si se está pulando el Shift izquierdo o derecho para poder diferenciar si corremos o andamos.
  4. Considero que andar y correr hacia atrás es más lento que andar y correr hacia adelante.


    Para el salto y para agacharse he considerado lo siguiente:
  • Por defecto hay gravedad en el juego y ésta la aplico restando en cada 25 al eje Z (valor calculado al ojo).
  • Utilizo una variable isJumping para evitar que se produzcan doble o triple salto.
  • Sé que el jugador no está saltando caundo isJumping es falso y el delta del Z entre el frame anterior y el actual es 0 (no quiero que se pueda saltar mientras caes).
  • El salto dura varios frames y éste se ralentiza en cada frame (empiezas saltando 30, después 28, después 26... y así hasta valer 0). Esto te da una sensación de que tienes un impulso fuerte que luego se va aminorando.
  • Agacharse símplemente recalcula la altura de la cámara. Cuando pulsas cualquier tecla Control, los valores de height y m8.height pasan a valer 2/3 del valor original. Cuando no pulsamos control, esos dos variables se resetean con su valor original.


    ¿Y con todos estos cambios, qué tal se siente el juego? Pues francamente bien. Os pongo dos vídeos, uno grabado a 320x200 y otro a 800x600:



    Y bueno, si os interesa aquí os dejo mi código fuente alterado: THENEWSC.PRG. Y sobre este código, varias cosas a destacar:

  1. He creado varias constantes para definir de forma sencillla la resolución a aplicar o el número de frames por segundo.
  2. Aunque el set_mode trabaje con valores del estilo m320x200, lo cierto es que admite variables numéricos, como 320200 para 320x200 o 800600 para 800x600. Esto se debe a que los famosos "m320x200", "m800x600", "m1024x768", realmente son constantes que tienen asignados esos respectivos valores (320200, 800600, 1024768, etc),
  3. Si IS_DEBUG vale 1, se escribe información en pantalla relativa a los frames por segundo reales o la cantidad de memoria ram utilizada. Mi consejo es que reemplaces el TOTAL_MEMORY_MB por los megas de RAM que tenga tu PC o instancia de DosBox para que el cuarto write_int de la función writeDebugInfo sea un valor real (DIV me permite saber cuanta memoria RAM hay disponible, pero no cuanta hay consumida, así que la estimo restando a esa constante la memoria disponible).

 



No hay comentarios:

Publicar un comentario

Si te ha gustado la entrada o consideras que algún dato es erróneo o símplemente deseas dar algún consejo, no dudes en dejar un comentario. Todo feedback es bienvenido siempre que sea respetuoso. También puedes contactarme por estas redes sociales https://linktr.ee/hamster_ruso si lo consideras necesario.