[TUTORIAL] Sonidos de pasos en ACS

 
Publicar Nuevo Tema   Responder al Tema    Índice del Foro Diseño DooM -> Edición de mapas
Ver tema anterior :: Ver siguiente tema  
Autor Mensaje
Charon




Registrado: 24 May 2009
Mensajes: 212
Ubicación: Limansk

MensajePublicado: Vie Nov 28, 2014 10:42 am    Título del mensaje: [TUTORIAL] Sonidos de pasos en ACS Responder citando

Pasos con sonido en ACS (ZDoom)

La prescencia de pasos en un videojuego hoy es crucial. Genera inmersión y profundidad, y a pesar de que por diferentes razones anteriormente no se los incluía, hoy es dificil imaginarse un juego sin ellos.

Voy a tratar de explicar este tutorial de manera que no sea necesario algún tipo de conocimiento en modificaciones aparte del de mapeo para ZDoom. Puede parecer muy exhaustivo, pero lo cierto es que es muy sencillo, solo que está extensivamente detallado, generando algunas recomendaciones entre explicaciones, para enriquecer la manera en la que este experimento es desarrollado.

Lo que vamos a necesitar para el tutorial:

• Archivos de sonido (Que van a ser los que utilicemos para ilustrar los pasos del jugador).
• Conocimientos muy básicos en ACS (Crear un script sencillo, por ejemplo de niebla o de mensaje). Con algo de perspicacia esto no es precisamente necesario.
• Un editor de scripts en ACS (Con el de Doom Builder alcanza).
• Un compresor de archivos, como WinRar o 7zip.

Punto importante: Por una cuestión práctica, voy a explicar cómo manejarse con archivos PK3. No solo que agiliza el desarrollo de nuestro mod, si no que también es una forma práctica de localizar y reemplazar archivos cuando sea necesario.


Lo primero que tenemos que hacer es preparar un nuevo mapa, en formato ZDoom (Doom in Hexen format), aunque es posible que esto funcione igual con otros formatos mientras mantenga el ACS de tipo ZDoom.

------------[Importación de sonidos y recomendaciones iniciales]------------

Creamos una carpeta llamada "WAD". Dentro de ella se ubicará nuestro archivo .wad, es decir, el archivo que contiene el mapa de nuestro proyecto.

Luego es necesario crear, de nuevo dentro de dicha carpeta, otra carpeta llamada "Sounds".

No hace falta decir que aquí dentro es donde copiaremos los archivos de sonido que vamos a utilizar para los pasos del jugador (En este ejemplo se utilizan cuatro, dos para pisos de concreto y dos para pisos de metal).
Nótese que siempre los archivos de sonido, al igual que casi cualquier otro lump, deben de llevar un máximo de 8 carácteres. En un esfuerzo por mantener ordenado el desarrollo, para el tutorial yo los nombré con el siguiente formato:

fs_rock1

fs_ indica que se trata de un sonido de pasos. Los siguientes carácteres representan el terreno que corresponde al sonido (Rock = Concreto, Met = Metal), y el número al final representa el número de sonido. Es muy recomendable utilizar como mínimo dos sonidos diferentes para cada terreno, ya que utilizar solo uno resultaría en una repetición acustica muy molesta (Hay que tener en cuenta que esto es algo que se va a escuchar a lo largo de todo el gameplay).

De nuevo en la carpeta WAD, crearemos un archivo de texto llamado "SNDINFO". Lo que haremos aquí es indicarle al sourceport qué archivos de sonido leer para reproducir una vez dentro del juego.

Para ello, creamos seis lineas, tres para el sonido de concreto y tres para el sonido de metal:

Código:

$random fs_rock { player/fs_rock1 player/fs_rock2 }
player/fs_rock1 fs_rock1
player/fs_rock2 fs_rock2

$random fs_metal { player/fs_met1 player/fs_met2 }
player/fs_met1 fs_met1
player/fs_met2 fs_met2


Las lineas con player/ indican el nombre del sonido seguido del nombre del archivo de sonido (En este caso, el nombre del sonido es el nombre del archivo, y se le precede un player/ por cuestiones de organización).

Las lineas con $random son para reproducir aleatoriamente cualquiera de los sonidos entre las llaves, y se le asigna un nombre de sonido justo despues del $random. Es decir, en el primer caso fs_rock es el nombre que vendría a representar tanto fs_rock1 como fs_rock2, y cada vez que se reproduzca un sonido con el nombre "fs_rock" se podrá reproducir cualquiera de los dos.

Todo lo anterior quedaría algo así:



Para editar tranquilamente sin necesidad de compilar/decompilar nuestro pk3 todo el tiempo, es recomendable configurar el directorio WAD como directorio de recursos. En Doom Builder 2, se hace de la siguiente manera:

Vamos a EDIT -> Map Options.




Dentro, seleccionamos el botón Add Resource.

[img width=640 height=400]http://i838.photobucket.com/albums/zz310/KingNK/Random%20stuff/03.jpg~original[/img]


En la ventana que acaba de abrirse, vamos a la pestaña From Directory, le damos click al ícono de la carpeta y buscamos nuestra ya creada carpeta WAD, que contiene tanto el wad del mapa como el archivo de texto sndinfo.txt y el directorio Sounds.




Le damos OK, guardamos el mapa (Para no tener que volverlo a hacer si decidimos volver a recargarlo) y ya está hecho.

Una vez hecho esto, ya estamos listos para pasar al siguiente punto: Desarrollo del Script ACS.



------------[Escribiendo el Script ACS]------------

Como ya deben de saber, cada vez que uno desea agregar un script a un proyecto debe incluir, como primer linea, el siguiente comando:

Código:

#include "zcommon.acs"


Ésto es lo que va a permitir al script leer todas las funciones que el source port dispone.

A continuación, vamos a crear tres variables. Las variables nos permiten manejar datos que van a cambiar a lo largo del juego.

Código:

int fst_speedfn;
int fst_onmove;
int fst_angular;
int fst_text_snd;


La primer variable será la velocidad final del jugador. Esto nos permitirá modificar la frecuencia con la que el sonido de los pasos se reproduce (Más rápido o más despacio).
La segunda variable será utilizada para consultar si el jugador está en movimiento. Nos va a servir para generar los sonidos de pasos cuando el jugador gira su visión manteniendo su posición.
La tercer variable es para consultar el angulo del jugador, la cual nos va a permitir registrar los cambios de dicha propiedad y, por lo tanto, reproducir el sonido apropiado.
La cuarta variable sirve para indicar qué textura de sonido se utilizará, para reproducir el paso acorde al piso sobre el que el jugador se encuentre.

Huelga decir que estos nombres son a modo de ejemplo, ya que cada quién puede utilizar el que mejor le resulte.

Por supuesto, todas estas variables no tienen un valor todavía. Eso se irá asignando en el transcurso del desarrollo.


Luego debemos comenzar con el script. Utilizaremos un script con nombre, y de tipo ENTER.


Código:

Script "footsteps_check" ENTER

{

}



Dentro, asignaremos un valor a cada variable.

A la variable fst_speedfn vamos a asignarle el valor de velocidad a través de dos comandos denominados CheckActorVelX y CheckActorVelY. Estos leeran la velocidad X e Y del jugador y la traducirán a un valor único a través de una operación matemática.

Dicha operación, a su vez, utiliza otro comando, que es el que nos permite multiplicar un número decimal con otro: FixedMul (El cual funciona de la siguiente manera: FixedMul(*valor a multiplicar*, *valor por el que multiplicar*). Lo que haremos será: Raíz cuadrada de (velocidad X multiplicada por sí misma + Velocidad Y multiplicada por sí misma).

Hay que notar que cuando una variable ya existe y solo debe ser redefinida, no hay que precederla con "int", solo debe escribirse su nombre nuevamente con un igual a continuación.

En base a los datos anteriores, la linea que escribiremos será así:


Código:

Script "footsteps_check_speed" ENTER

{

fst_speedfn = FixedSqrt (FixedMul(GetActorVelX(PlayerNumber()), GetActorVelX(PlayerNumber())) + FixedMul(GetActorVelY(PlayerNumber()), GetActorVelY(PlayerNumber())));

}


Parece algo sobrecogedor, pero es sencillo si uno lo analiza brevemente: FixedSqrt es el que calculará la raíz cuadrada de un número decimal (La velocidad del jugador se traduce a números decimales). Se abre un paréntesis para que toda la operación dentro resulte en un número (Y para que no hayan errores de sintáxis). Dentro tenemos el comando FixedMul del que hablé anteriormente. Como dije, debía multiplicarse la velocidad x por la velocidad x. Entonces, rellenamos el primer y segundo parámetro de FixedMul con el comando apropiado para leer la velocidad X del jugador. Luego se agrega el símbolo de suma, y se repite la operación, pero con la velocidad Y (GetActorVelY). El PlayerNumber() dentro del comando es precisamente para que se lea la velocidad del actor que representa al jugador.

Hay que prestar especial atención a los paréntesis que se añaden para cerrarlos adecuadamente y no comenter error alguno.

Una vez que tengamos esta variable asignada, vamos a traducirla a un número entero, ya que va a ser la que genere el volumen apropiado para el sonido (Puesto que el comando de sonido que utilizaremos se maneja con números enteros). Para ello, sencillamente debemos añadir la siguiente linea:

Código:

Script "footsteps_check_speed" ENTER

{

fst_speedfn = FixedSqrt (FixedMul(GetActorVelX(PlayerNumber()), GetActorVelX(PlayerNumber())) + FixedMul(GetActorVelY(PlayerNumber()), GetActorVelY(PlayerNumber())));

fst_speedfn = fst_speedfn >> 16;

}


En resumen, lo que hace la linea es leer el valor anterior de fst_speedfn y convertir dicho valor (Que será decimal, por las operaciones que realizamos más arriba) a uno entero.


Ahora, en el mismo script, asignaremos a la variable fst_text_snd el valor correspondiente a la textura bajo el jugador, para que el sonido sea acorde al piso. Por una cuestión práctica, dejaremos el sonido de concreto sin ningún condicional, es decir, que siempre se ejecutará, a menos que el jugador se posicione encima de alguna textura en especifico.

El truco del script es que el valor de la variable (fst_text_snd) será precisamente el nombre de los archivos de sonido que corresponda a determinada texturas. Entonces, lo que hay que hacer es básicamente leer la textura sobre la que está posicionado el jugador y cambiar el valor de la variable apropiadamente. Para lo primero, utilizaremos el comando CheckActorFloorTexture, que consta de dos valores: El actor sobre el cual ejecutar el checkeo, y el nombre de la textura a comprobar. De nuevo se utilizará PlayerNumber() para indicar al actor. En cuanto a la textura, eso dependerá del mapa y el sonido que el mapper utilice. En el ejemplo utilizo la textura FLOOR4_5, por lo que se comprobará si dicha textura está efectivamente bajo el actor del jugador.

Todo esto lo haremos a través de un condicional, que es una función que permite ejecutar un bloque de script siempre y cuando se cumpla X condicion. Por ejemplo, con IF, podemos decirle al script que ejecute las siguientes lineas entre llaves sólo si se cumplen determinadas condiciones. Si se trata de una sola linea, las llaves no son necesarias. Así es como haremos lo segundo.


Código:

Script "footsteps_check_speed" ENTER

{

fst_speedfn = FixedSqrt (FixedMul(GetActorVelX(PlayerNumber()), GetActorVelX(PlayerNumber())) + FixedMul(GetActorVelY(PlayerNumber()), GetActorVelY(PlayerNumber())));

fst_speedfn = fst_speedfn >> 16;

fst_text_snd = "fs_rock";
         
if ( CheckActorFloorTexture (PlayerNumber(), "FLOOR4_5")) fst_text_snd = "fs_metal";

}


Nótese que la variable fst_text_snd se define dos veces. Esto es porque la primera vez no tiene ninguna condición, es decir que siempre que se ejecute el script se volverá a definir con el valor del sonido de concreto, a menos que el jugador esté encima de un piso con la textura FLOOR4_5. En ese caso, la textura vuelve a definirse con el nombre del sonido apropiado (Sonido de pasos en metal, o fs_metal).

Aqui termina el código para comprobar los valores básicos. Pero claro, es inútil que solo se compruebe una sola vez, puesto que dichos valores deben comprobarse en todo momento. Entonces hay que repetir indefinidamente el script. Para eso hay que añadir un Delay de 1 tic y utilizar el comando Restart (Lo del Delay es para evitar un error. Todo comando restart requiere que exista un delay de al menos 1 tic, de lo contrario el script falla y deja de ejecutarse al llegar al restart).


Código:

Script "footsteps_checks" ENTER

{

fst_speedfn = FixedSqrt (FixedMul(GetActorVelX(PlayerNumber()), GetActorVelX(PlayerNumber())) + FixedMul(GetActorVelY(PlayerNumber()), GetActorVelY(PlayerNumber())));

fst_speedfn = fst_speedfn >> 16;

fst_text_snd = "fs_rock";
         
if ( CheckActorFloorTexture (PlayerNumber(), "FLOOR4_5")) fst_text_snd = "fs_metal";

delay(1);
restart;

}


Por supuesto, deberemos replicar el if antes del delay con cada textura a la que le queramos asignar un sonido de pasos diferente.

Muy bien, ya tenemos un script que compruebe los valores que necesitamos. Sin embargo, no nos sirve sin otro script que los utilice. Entonces, procedemos a crearlo:

Código:

Script "footsteps_execute" ENTER

{

}


Dentro de este script (También de tipo ENTER), vamos a agregar primero otro condicional, que le permitirá saber si el jugador está tocando el piso (Para evitar sonidos de pasos mientras el jugador se sigue moviendo en el aire).

Para eso añadimos otro IF, con las funciones GetActorZ y GetActorFloorZ. La primera comprueba a qué altura se encuentra el jugador actualmente, mientras que la segunda comprueba a qué altura se encuentra el piso del jugador.
Lo que haremos con ambas será: Si la altitud del jugador es menor a 0.1, ejecutar el bloque de comandos entre las llaves. Para lograr eso debemos, a la altitud del jugador, restarle la altura del piso.

Es decir: Si el jugador está a una altitud de 64.0, y el piso se encuentra a 63.0, el calculo daría 1.0, por lo que la condicion no se cumple (Ya que el jugador está por encima de 0.1), y por lo tanto el sonido de los pasos no se reproduce.

Esto quedaría así:

Código:

Script "footsteps_execute" ENTER

{

if (GetActorZ(PlayerNumber()) - GetActorFloorZ(PlayerNumber()) < 0.1 )

   {

   }

}


Muy bien, ahora indicamos con el comando AmbientSound que se reproduzca el sonido adecuado. Para eso es que redefinimos la variable fst_text_snd con el nombre del archivo de sonido correspondiente en el script anterior.

Esto se hace sencillamente indicando en el primer valor de AmbientSound la variable fst_text_snd. Sin embargo, si indicamos un volumen fijo (Digamos, 100), los pasos se escucharían siempre al mismo volumen, sin importar la velocidad. Para eso utilizamos también otra variable ya asignada: fst_speedfn. Como esta variable nos deja un número de máximo 15 o 20, deberíamos multiplicarla por un número de forma tal que el resultado no supere los 100 puntos. Dicho número es 5.
De esta manera, el volumen de los pasos no solo es variable, si no también logarítmico (Es decir, que va a ser mucho mayor la diferencia entre el volumen de un paso a una velocidad de 2-3 -Agachado- y el volumen de un paso a una velocidad de 14-15 -Corriendo-). Si en vez de multiplicarlo por 5 le sumaramos 100, la diferencia de volumen sería: 103 (Agachado) - 115 (Corriendo), lo cual no es demasiado notorio, a diferencia de los 15 (Agachado) - 75 (Corriendo) que nos da la multiplicación.

Teniendo en cuenta lo anterior, nos quedaría algo como esto:

Código:

Script "footsteps_execute" ENTER

{

if (GetActorZ(PlayerNumber()) - GetActorFloorZ(PlayerNumber()) < 0.1 )

   {

   AmbientSound (fst_text_snd,  fst_speedfn * 5);

   }

}



Ahora bien, los pasos de una persona dependen de la velocidad a la que esta se mueva. No se escucha con la misma rapidez los pasos de una persona corriendo que los pasos de una persona en sigilo. Por eso, necesitamos crear un delay con un valor variable. Y para eso otra vez vamos a utilizar la variable fst_speedfn.
La lógica es la siguiente: Mientras mayor sea la velocidad del actor, menor debe ser la pausa (delay) que hay entre sus pasos. ¿Como logramos esto? Muy fácilmente. Primero, debemos calcular la velocidad máxima de nuestro actor. Yo estoy utilizando la velocidad original de Doom, por lo que si estás pensando en incluír esta funcion en un mod que aumente la velocidad máxima, deberás ajustarlo a medida.
Una forma práctica de hacerlo es la siguiente: Calcula cual será la velocidad máxima de tu actor y dividela por dos. Luego deberías escribir Delay ( *turesultadoennumeros* - (fst_speedfn / 2) ).

Como verás, se está restando el resultado de dos operaciones exactas. Y ese es precisamente el punto. Si el jugador va a su velocidad máxima (Digamos, 14, que luego de la operación esta quedara en 7), y se le resta el mismo resultado que se indicó al principio de la operación (7 nuevamente), no existirá retraso entre paso y paso.

Un punto importante es que debemos evitar que este primer delay se ejecute si la persona no está en movimiento, ya que de lo contrario podríamos retrasar demasiado los pasos iniciales (Puesto que a 7, en este caso, se le restaría 0, y serían 7 tics de retraso luego del primer movimiento antes de que los pasos se reproduzcan), junto con la posibilidad de generar un error que cerrará nuestro script y nos dejará sin pasos por el resto del juego.
Para evitar todo eso, crearemos otro IF, que compruebe dos cosas:

Que la velocidad del jugador no sea 0, y que la velocidad del jugador sea menor a 15. De esta forma, el delay no se ejecuta con una operación que daría -1 (Y por lo tanto un error de script) en caso de pasar los 15 puntos de velocidad.

Código:

Script "footsteps_execute" ENTER

{

if (GetActorZ(PlayerNumber()) - GetActorFloorZ(PlayerNumber()) < 0.1 )

   {

   AmbientSound (fst_text_snd,  fst_speedfn * 5);
   if (fst_speedfn > 0 && fst_speedfn < 15) delay (7 - (fst_speedfn / 2));

   }

}



Sin embargo, esto generaría una velocidad abrumante de pasos. Para eso se agrega otro delay fijo, fuera del condicional, que además de fijar un retraso base y mínimo para los pasos, servirá para evitar el error al reiniciar el script.

Junto con todo lo anterior, y traducido a código, quedaría algo así:

Código:

Script "footsteps_execute" ENTER

{

if (GetActorZ(PlayerNumber()) - GetActorFloorZ(PlayerNumber()) < 0.1 )

   {

   AmbientSound (fst_text_snd,  fst_speedfn * 5);
   if (fst_speedfn > 0 && fst_speedfn < 15) delay (7 - (fst_speedfn / 2));

   }

delay (9);
restart;

}



Por supuesto, todos estos valores pueden ser modificados y experimentados a gusto. Los que yo he representado en este tutorial están ajustado a mi criterio personal, y no son ningún tipo de tecnicidad objetiva.

Si se ha hecho todo correctamente, ya deberían de tener pasos en su mapa/mod, y se podrán seguir editando por medio de windows sin necesidad de recurrir a alguna otra herramienta más que su programa de mapeo favorito. Sin embargo, esto limita demasiadas opciones, por lo que también se puede utilizar un editor de lumps que maneje archivos PK3 para manipular los archivos (Sonidos, sprites, gráficos, text lumps) una vez que estos estén compactados.

Para ello deberemos utilizar WinZip o 7zip, y agregar los archivos (Excepto el .wad) sin ningún tipo de compresión.




Luego replicamos lo de añadir un recurso mediante edit -> map options, pero en vez de añadir un directorio añadiremos "From PK3 file". Obviamente, debemos borrar el anterior recurso (El cual apunta al directorio WAD) mediante el botón Remove, también en Map Options.

Yo recomiendo que si no se tiene experiencia con PK3s se comience como el tutorial lo indica, y luego se traslade a un editor como SLADE, que no solo es muy flexible, si no que además es bastante sencillo.

En caso de querer utilizar este mismo script para varios mapas en el wad (O si se quiere crear un pack de footsteps), sería recomendable utilizar el lump LoadACS y compilar manualmente el script mediante slade. Si alguien quiere hacerlo y no está seguro de como, que me avise por aquí mismo y le explico.

Espero que les haya resultado útil este tutorial, y que sea una interesante característica para añadir a sus futuros proyectos. Voy a dejar un zip con el PK3 de ejemplo, hecho exactamente como está explicado aqui mismo.

FootstepsDemo.zip

[Copypaste de mi post en Arcades3D]
_________________

Hexagon 1970 Dev

Volver arriba
Ver perfil del usuario Enviar mensaje privado Visitar sitio web del autor
el5emendechucky




Registrado: 25 Sep 2007
Mensajes: 490

MensajePublicado: Lun Ene 19, 2015 6:56 am    Título del mensaje: Responder citando

gracias por seguir haciendo estos tutoriales bro.
_________________


Volver arriba
Ver perfil del usuario Enviar mensaje privado
Mostrar mensajes anteriores:   
Publicar Nuevo Tema   Responder al Tema    Índice del Foro Diseño DooM -> Edición de mapas Todas las horas están en GMT + 2 Horas
Página 1 de 1

 
Saltar a:  
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas


Powered by phpBB

Todos los contenidos de esta página, salvo que conste un autor o licencia diferente, están licenciados bajo la Licencia Creative Commons
DOOM y DOOM II son marcas registradas de id Software, Inc.