DevZing

Blog sobre desarrollo de videojuegos y programación

Archive for November, 2006

Programación 2D en SDL - Juego isométrico ( VIII )

Por fin, esta vez me ha llevado bastante tiempo (más que nada, por falta de tiempo libre), pero aquí tenéis otra nueva entrega de la serie:

Programación Gráfica 2D (VIII) - Bichos y tochos

Y como siempre, el enlace en PDF

Espero que os guste!

Supreme Commander y el futuro de la estrategia

Supreme Commander es el nuevo juego de Chris Taylor, que aspira a convertirse en el sucesor de Total Annihilation y un nuevo referente para el género de la estrategia en tiempo real.

Parece ser que lo que quiere hacer Supreme Commander es “alejar la cámara”. En los últimos RTS cada vez se ha ido acercando más y más la cámara a los personajes. Al final hemos acabado controlando a 4 tíos, con un grado de detalle como si fueran juegos de rol (subiendo habilidades y todo!), y en unos mapas minúsculos.

Cuando yo pienso en un RTS que me gustaría, es prácticamente lo contrario a lo que hay. Quiero controlar cientos de unidades, batallones enteros, en batallas épicas que se libren sobre mapas gigantes de kilómetros de extensión, donde simplemente el cómo trasladar las tropas desde mi base hasta el frente (o evitar que el enemigo lo haga) sea uno de los puntos más importantes a tener en cuenta.

En fin, que si eso es lo que Supreme Commander va a traer, ya está tardando :D

Un temporizador más preciso

El control del tiempo en cualquier tipo de programa que funcione en tiempo real es fundamental, y más en un juego, donde tenemos tiempos de fotogramas del orden de unos pocos milisegundos, y que si no calculamos bien puede provocar errores, o movimientos poco fluidos, etc…

Por regla general, se puede usar una función como GetTickCount (), que devuelve el número de milisegundos transcurridos desde el arranque del sistema, y olvidarse del tema.

El problema de GetTickCount () es que, para valores muy pequeños, no suele ser preciso, pues su resolución puede ser de hasta varios ms. En el caso de los juegos, donde un fotograma puede durar menos de 15ms, este error puede ser muy significativo.

Así que necesitamos un temporizador con una resolución mayor. Y eso es precisamente lo que nos dan QueryPerformanceCounter () y QueryPerformanceFrequency (), un método para medir el tiempo con una precisión de menos de 1ms.

QPC devuelve el valor del contador de alta precisión, y QPF su frecuencia (en nº de ciclos por segundo). Ambas usan LARGE_INTEGERs, enteros de 64 bits que dependiendo del compilador son o no soportados nativamente.

El proceso para medir el tiempo usando estas funciones es bastante sencillo:


LARGE_INTEGER a, b, frecuencia;

//Obtenemos el valor de la frecuencia
QueryPerformanceFrequency (&frecuencia);

//Tomamos la medida inicial
QueryPerformanceCounter (&a);

//CODIGO

//Tomamos la medida final
QueryPerformanceCounter (&b);

//Calculamos la diferencia, y la dividimos por la frecuencia
double segundos = (b.QuadPart - a.QuadPart) / frecuencia.QuadPart;

El campo “QuadPart” es un entero de 64 bits, y si el compilador no lo acepta habrá que trabajar en su lugar con LowPart y HighPart. En cualquier caso, yo nunca he tenido ese problema.

Otra cosa a tener en cuenta si estais adaptando desde GetTickCount () es que la frecuencia de QPF va en ciclos / segundo. Por lo que al dividir, la medida de tiempo que se obtiene viene en segundos, y no en ms como la de GetTickCount ().

Y una última observación: La frecuencia se suele calcular al principio y dejar guardada en una variable, porque se supone que no va a cambiar. Normalmente es así, pero no siempre. Pensad en los portátiles con sistemas que reducen el consumo de energía precisamente variando la frecuencia del micro, en esos casos puede que sea interesante controlar si la frecuencia ha cambiado o no.

Un sistema que funciona es tomar la medida tanto con QPC/QPF como con GetTickCount (), y comparar los resultados. Si son demasiado distintos (por ejemplo, medio segundo de diferencia entre uno y otro), entonces se puede suponer que QPC/QPF ha fallado, y sería momento de volver a calcular la nueva frecuencia.