..:: QUAKE ::..
 
 

Programacion

Bueno, como yo no conozco mucho del tema, el texto que explica un poco sobre la programacion del Quake-C lo he exrtaido del numero 49 de la revista PCMANIA.
Lamentablemente no tengo el numero siguiente donde quien escribe iba a comenzar a crear un personaje nuevo, pero voy a tratar de conseguir el articulo con la continuacion.


Para poder hacer nuestras pruebas necesitaremos el codigo fuente (ver. 1.06) con los comportamientos de todo lo que hay en QUAKE y el compilador QCC (115 Kb) o tambien PROQCC (87 Kb)

Quake-C, creado por John Carmack, no pasara a la historia como un lenguaje de multiples aplicaciones ni por ser especialmente eficaz (como reconoce el propio autor), ni por presentar caracteristicas nuevas con respecto al al lenguaje del cual desciende. El proposito de Quake-C es exclusivamente ludico.
Con Quake-C la posibilidad de modificar o crear comportamientos "inteligentes" para personajes virtuales esta al alcance de cualquier programador. Si a ello, a�adimos el hecho de que dichos personajes pertenecen al entorno virtual para PC mas atractivo del momento, comprenderemos un poco mas la peque�a revolucion que supone "Quake".
Por esta razon, estudiaremos este tema con el deseo de aprender lo suficiente para llegar a dise�ar personajes propios para este juego.
No debeis esperar excesivas precisiones en el contenido de este articulo.
Para empezar no hay demasiada informacion sobre Quake-C o sobre el Qcc (Quake-C Compiler). Carmack adjunta algunos datos en el fichero "readme" que acompa�a al compilador y en el archivo qcc.h que forma parte de los fuentes del compilador, los cuales, al igual que los fuentes con los comportamientos del juego, pueden ser hallados en Internet. Otra funte de informacion son los diversos faqs que, en numero aun escaso, existen sobre este particular.


Quake-C presenta muchas similitudes con C pero las semejanzas se presentan mas a nivel sintactico que en lo relativo a filosofia de programacion. Asi, Quake-C emplea los mismos caracteres para escribir comentarios, y usa los mismos operadores y sentencias
if y while pero, en cambio, presenta una serie de diferencias y limitaciones con respecto al C estandar. No se puede, por ejemplo, definir nuevos tipos partiendo de otros ya existentes, ni asignar un nuevo nombre a un tipo, ni definir nuevas estructuras. Todas las variables son globales por defecto y pueden ser accedidas desde cualquier funcion. (Pero si anteponemos la palabra local, la variable solo sera accesible desde la funcion en la que se haya declarado). El lenguaje esta fuertemente tipado y no se usan casts.
En cuanto a las funciones, tambien hay algunas diferencias con respecto a las del C estandar. Comencemos con los prototipos. Estos, en Quake-C, son del modo:


tipo (tipo param1, tipo param2,...) nombre_funcion;
...y para la estuctura general de la funcion, tenemos que...

tipo (tipo param1, tipo param2,..) nombre_funcion=
{
...
codigo
...
};

En qcc.h, Carmack ofrece el siguiente ejemplo...

void() MyFunction;
// El prototipo
void() MyFunction=
//sigue el cuerpo de la funcion
{
dprint ("we're here\n");
};

Las funciones de Quake-C no pueden tener mas de 8 parametros. Por otro lado, en este lenguaje existen dos tipos adicionales de funciones; las funciones frame y las llamadas funciones
built. Las primeras han sido dise�adas por conveniencia para facilitar la creacion de secuencias de annimacion, y las siguientes se emplean para cambiar valores de datos que no debemos intentar modificar directamente bajo pena de cuelgue.
Naturalmente, Quake-C tiene sus limitaciones. El dialecto no puede ser usado, por ejemplo, para permitirnos cambiar el potente motor 3D de "Quake". Realmente en el juego podemos distinguir entre dos tipos de codigo; el que forma parte Quake.exe, que no es modificable y que contiene el motor 3D y las funciones de bajo nivel, y el que forma parte de progs.dat, el cual es el resultado de la compilacion de los fuentes con la IA modificada de los personajes y se apoya en Quake.exe.

ENTIDADES
Los tipos simples de datos permitidos por Quake-C son
void, float, string, vector y entity. El tipo vector se emplea para especificar posiciones o direcciones en el espacio virtual de "Quake". Emplea tres valores en flotante que deben separarse con espacios y englobarse como en los siguientes ejemplos:

'0 0 0'
'20.5 -10 0.00001'


Las entidades son estructuras de datos. Los monstruos, los jugadores y los niveles son cosiderados como entidades cuyo estado podemos, a veces, alterar. Hay tres tipos de entidades; las estaticas, las temporales y las dinamicas. Las primeras se emplean para referenciar a objetos, tales como luces, que no interaccionan con el resto de los elementos del juego. El maximo numero permitido de entidades estaticas es de 127 y podemos crearlas usando la funcion markestatic(). Sin embargo, una vez creadas, las entidades estaticas no pueden ser borradas. Las entidades temporales, por otro lado, son cualquier cosa que tenga un limitado tiempo de vida en el universo virtual de "Quake". Son entidades temporales las balas de rifle, los clavos del lanzador, los rayos del lanzarayos, etc. Estas entidades no nesecitan ser borradas por el programador y desaparecen por si mismas.
Por ultimo, las entidades dinamicas son aquellos elementos que exhiben cambios en su comportamiento o apariencia, al interaccionar con otras entidades del juego. Podemos estudiar los campos que forman una estructura dinamica en el fichero defs.qc, a partir del texto "
SOURCE FOR ENTVARS_TC STRUCTURE".
Y podemos a�adir nuestros propios campos al final de esta estructura, despues de
end_sys_fields (para, por ejemplo, guardar un nuevo tipo de dato para un arma nueva o lo que sea). Los campos de esta estructura son compartidos por Quake.exe y Quake.c y pueden leerse libremente pero no deben ser escritos directamente. Notese que Quake-C no proteje la escritura directa en estos campos a pesar de que dicha operacion puede condusir al desastre. (Esta escritura solo debe realizarse empleando funciones built). Veamos ahora algunos de los campos que pueden modificarse:

CAMPOS DE ENTIDADES DINAMICAS
El nombre del fichero que contiene el modelo de la entidad se especifica en:
string model;
Para apuntar al frame adecuado dentro del indice de modelos se usa la variable frame. Aqui la palabra frame no alude a un bitmap sino a un modelo 3D que corresponde a una de las posturas de alguna de las secuencias animadas del modelo (quiza model-frame sea una palabra mas adecuada para designar a una de estas posturas). Los frames deben ser definidos por un contructor & frame en el fichero de modelos y pueden ser referenciados por el codigo como $xxx (siendo xxx el nombre del frame).
Por otro lado puede ocurrir que se disponga de varias texturas para recubrir al modelo. Si este es el caso, entonces el valor que sigue a la variable
skin se empleara como indice a la lista de skins (pieles). El valor debera estar comprendido en el rango correcto.
Otra variable que afecta a la apariencia de los personajes es
effects. Esta variable indica el efecto luminoso a que esta sujeta la entidad. Effects puede ser empleada para crear entidades luminosas (como en el mod Cujo) o campos de puntos de luz.
En cuanto a la posicion y orientacion de los personajes, la estructura dispone de las variables
origin, mins, maxs, size, absmin, absmax, oldorigin y angles. Origin tiene la posicion del model-frame y podemos conocer las coordenadas de cada eje usando origin_x, origin_y y origin_z. Mins y max controlan la extencion, relativa al origen, de la caja bounding del personaje.
Estas "bounding" son cajas invisibles que recubren a los personajes y se emplean para efectuar las detecciones (con paredes, disparos, etc.). Esto implica que las deteciones no son excesivamente precisas pero si muy rapidas.
Como antes, para conocer los valores en cada eje, usaremos los sufijos
_x, _y y _z (o sea, por ejemplo, mins_x, mons_y y mins_z). "Oldorigin" guarda la posicion anterior y "angles" la orientacion del personaje.
Ademas, podemos especificar detalles adicionales tales como si la entidad puede bloquearnos el paso o no (
solid), el tipo de movimiento (movetype), la velocidad (velocity), la velocidad de rotacion (yaw_speed) y muchas mas que veremos en detalle mas adelante.

FUNCIONES BUILT
Entre las funciones
built hay funciones matematicas, de trabajo con vectores, de uso de sonidos, de manejo y movimiento de entidades, el chequeo de colisiones y control de luchas y disparos, de depuracion del programa y de otro tipo. El conocimiento de la existencia de estas funciones es el punto mas basico en la programacion de ficheros mod. Entre las funciones matematicas existen floor(), cel() y fabs(), que funcionan como sus equivalentes en C estandar, y random(), que devuelve un numero aleatorio que oscila entre 0 y 1.
Entre las funciones para trabajo con vectores tenemos por ejemplo:


float vlen(vector v)

...que retorna a la longitud del vector v (nunca inferior a 0). Podemos encontrar un ejemplo de vlen() en la funcion CUJO_bite() (mordisco de perro cujo) en el fichero cujoai.qc del mod cujo10. Alli se define unn vector llamado delta que se hace igual a la diferencia entre la posicion del enemigo y la de nuestro fiel chucho:

delta = self.enemy.origin -
self.origin;

Despues, en la siguiente linea, se comprueba si la distancia es superior a 100 unidades y, de ser asi, se abandona la funcion:

if(vlen(delta) > 100) return;

De lo contrario la distancia entre ambos luchadores esta dentro del rango previsto y Cujo procede a morder a su contrincante causandole un da�o que dependera del valor aleatorio devuelto por la funcion
random(). Otra funcion util es;

float vectoryaw(vector v)


La cual calcula el angulo correspondiente entre posicion y orientacion del personaje y el vector v. (Se entiende que este angulo es el usado en el plano del suelo sobre el que se halla la entidad).

SOUND()
La funcion sound tiene el prototipo:

void sound (entity souse, float channel, string sample, float volume, float attenuation)

Entity es la entidad que emite el sonido, channel es el canal empleado para la emision, sample es el nombre del fichero wav que contiene el sonido (ejemplo: "dog/idle.wav") , volume es el control de volumen -que puede osilar de 0 (nada) a 1 (maximo volumen) y attenuation es un factor de atenuacion del sonido (podemos encontrar valores para attenuation y otros paramentros en el fichero deft.qc).
El sonido no es esencial para el funcionamiento de la entidad pero contribuye a darle mas realismo. Algunos programadores de mods no se molestan en poner sonidos a sus creaciones pero Cujo y Wisp si los tienen.


FUNCIONES BUILT DE MANEJO Y MOVIMIENTO DE ENTIDADES
Con
spawn() podemos crear una nueva entidad vacia. Sus campos podran ser llenados o manualmente, o bien llamando alguna de las funciones setup de entidades. La entidad asi creada podra ser eliminada mas adelante con remove(num_entidad)
Otras funciones nos permitiran manipular diversos modos a las entidades, por ejemplo findradius(), cuyo prototipo es: entity findradius (vector origin, float radius)
Retorna una cadena de entidades cuyos origenes estan dentro de unn area esferica cuyo centro y radio son origin y radius respectivamente. La entidad devuelta es el primer elemento de la cadena y findradius() se utiliza normalmente pare decir cuales son las entidades victimas de una explosion y proceder a su tratamiento. El siguiente ejemplo ha sido tomado de qc_built.htm:

e = findradius( origin, radius)
while(e)
{
T_Damage(e, ...) // Let God sort his ones!
e = e.chain
)

En caso de que no haya ninguna victima el valor devuelto por la funcion es "false", con lo que no se llega a entrar en el bucle de tratamiento. Para el movimiento de las entidades podemos usar las funciones walkmove(), setorigin() o movetogoal(). La primera retorna "false" si el movimiento no es posible, lo cual se emplea para detectar monstruos. Setorigin() cambia la posicion de una entidad. Sus parametros son, en este orden, el numero de la entidad y el vector con la nueva posicion. Esta funcion es empleada para teletransporte y es el unico metodo alternativo al movimiento fisico. (Cambiar directamente el valor de posicion origin, no es recomendable). Por ultimo, movetogoal() se emplea para recorrer una distancia especificada, en el sentido del movimiento.
Otra funcion de uso frecuente, aunque esta vez para trazar lineas de tiro, es
trace line() cuyo prototipo es;

traceline (vector v1, vector v2, float nomonsters, entity fornet)

Los dos primeros parametros son el principio y el final de la linea a trazar. El siguiente parametro "nomonster", debera ponerse TRUE si la linea puede atravesar monstruos y a FALSE si no va a ser asi. La linea trazada puede ser bloqueada por cajas bounding (personajes) y entidades bsp (arquitectura del nivel). Finalmente, el parametro forent indica la entidad que debe ignorarse en el trazado (la que dispara, claro). La funcion devuelve algunos valores en variables globales. Por ejemplo, en trace_fraction se devolvera un porsentaje que indica la fraccionde linea que puede recorrerse sin hallar obstaculos, siendo su valor igual a 1 si no se encuentra ninguno.
Para crear efectos de particulas Quake-C nos ofrece la funcion
particle() cuyo prototipo es;

void particle(vector origin, vector dir, float color, float count)

Origin es la posicion inicial , dir la direccion inicial, color el indice de colores y count el tiempo de vida en segundos. El valor de color puede ser de 0 (para trozos), 75 para amarillo, 73 para sangre y 225 para representar a la entidad da�ada.

Jose Manuel Mu�oz

..:: CONTINUACION DE "SONIDOS NUEVOS" ::..
 

Para agrgar el sonido nuevo que habiamos creado necesitamos el
codigo fuente (ver. 1.06) con el comportamiento de todos los objetos del mundo quake, son unos archivos con la extencion *.QC.
Una vez que tengamos los archivos buscamos uno que se llama
PROGS.SRC lo abrimos en el NOTEPAD o el WORD y agregamos una linea de nombre por ejemplo SONIDOS.QC (para no modificar el que existe y hacernos un lio)
Usando el
NOTEPAD copiamos todo este codigo (abajo), y lo guardamos con la extencion QC en el directorio donde estan los otros.

/*
===========================

Titulo por ejemplo: Sonidos

===========================

/*QUAKED ambient_
nombre (0.3 0.1 0.6) (-10 -10 -8) (10 10 8)
*/
void() ambient_
nombre =
{
precache_sound ("ambience/
nombre.wav");
ambientsound (self.origin, "ambience/
nombre.wav", 0.5, ATTN_STATIC);
};


Hecho todo esto nesecitamos compilar estos archivos usando un programa que se llama PROQCC
(87 Kb).
Compilado todo creara un archivo de nombre
PROGS.DAT que debemos copiar dentro del PAK que habiamos hecho. Y no olviden copiar el sonido nuevo tambien dentro del PAK.
Recordando que hicimos todo esto para que nuesrto "mapa nuevo" tenga sonidos nuevos y suponiendo que estamos usando el editor de mapas
WORLDCRAFT solo tenemos que agregar un sonido como lo acemos normalmente pero en las propiedades del mismo cambiar el nombre por el del nuestro.
Buff!!! que dificil es explicar esto!!! ;-)
Cuando este todo terminado entramos en Quake como ya dije antes.
Luego voy a explicar algunos de los posibles errores que pueden pasar.

 
 
| INICIO | EDICION MAPAS | TEXTURAS Y GRAFICOS | SONIDOS | MODELOS | PROGRAMACION | MIS MAPAS | OTROS MAPAS
EDITORES | PORTS | QUAKE-C | TUTORIALES
| LEE EL LIBRO DE VISITAS | FIRMA EL LIBRO DE VISITAS | MAPA DEL SITIO |

� Todos los graficos dise�ados por el
|2aToN - 2001 - 2005
Si no pudes ver el menu debes habilitar JavaScript y recargar la pagina.