PDA

Ver la versión completa : Rutinas para actualizar pantalla.



Locke
20/08/2004, 16:57
Wenas, esto siempre se me ha atragantado cuando intento programar algun jueguecillo, es a la hora de refrescar la imagen de la pantalla. Lo que suelo hacer (chapuza total) es refrescar la pantalla una vez por cada ciclo del juego, y si veo que va muy rapido pues le meto un delay y listo, pero asi en equipos mas viejos e vuelve lento.

Se que lo que se suele hacer es usar un contador, y cada vez que haya que dibujar, ejecutar las rutinas de movimiento de los sprites y demas y mostrar la imagen actualizada. He mirado varios codigos, pero no se por que algo tan simple no me termina de entrar en la cabeza.

Si alguno fuera tan amable de explicarme en pseudocodigo como funcionan esas rutinas se lo agradeceria mucho.

Un saludo.

K-teto
20/08/2004, 17:42
Hombre, se me ocurre usar un timer que tome el tiempo en ticks antes de hacer nada y despues de ello, y luego comparas el tiempo y si es menor del que quieres esperar haces un delay hasta que eso se cumpla, y vuelta a empezar.
No se si me he explicado bien porque no tengo mucho tiempo XDDDDD

Otro factor a tener en cuenta es que con la gp la velocidad va fija, a no ser que la cambies tu, y eso te da mas control, no es como en un pc que hay miles de configuraciones posibles, al tener un hardware fijo, hay mucho menos que tener en cuenta a la hora de trabajar con el que con uno que puede cambiar como sea.

Locke
20/08/2004, 18:10
Claro, pero mi intencion es hacerlos portables con el minimo esfuerzo.

Se que necesito meter un timer, pero no se exactamente como usarlo si quiero que el juego vaya a X fps.

Entiendo que tu me dices algo asi (tomando 60fps, por ejemplo, lo que serian 17ms por frame):

bucle principal

operaciones principales del juego
.
.
.
fin operaciones

if tiempo_transcurrido < 17ms
delay (17 - tiempo_transcurrido)
comienza de nuevo a contar el tiempo
pinta_pantalla
else
???????????????

fin del bucle principal


Si no me equivoco seria algo asi a grandes rasgos. Mi duda es que pasaria en el caso de que por haber demasiados elementos en pantalla, o por algun otro motivo, algun calculo superase el tiempo estimado para ese frame. Si no me he explicado claro decidmelo y doy mas detalles.

Muchas cenkius

K-teto
20/08/2004, 18:48
Que el juego iria lento, pero eso ya no es problema del contador, sino de potencia de la maquina u optimizacion del codigo, el contador no consume apenas recursos.

Piensa que aunque no metas el contador, si pasa eso mismo, el juego seguira siendo lento.

Nuak
20/08/2004, 20:36
Buenas Locke, pos aquí te va la ayuda de un compañero de facultad jeje, estas son las rutinas que he desarrollado para el juego que estoy programando (Freestyle Frisbee), a ver si cuando acaben los examenes le meto un poco de caña. Uso la técnica double buffering, supongo que sabrás como funciona el tema, y está programado usando el SDK de Mr. Mirko, si usas otro SDK supongo que no te será dificil implementarlas


/* SCREEN MANAGEMENT *************************************************/

/* DOUBLE BUFFERING
* To use double buffering you need:
* - the framebuffers pointers
* - the main framebuffer pointer
* - the init function
* - the flip function
* Firstly init the framebuffers with the fb_init function.
* Into the game loop, write always to the *main_fb, and
* call flip() in the end of the loop.
*/

u16 *framebuffer1;
u16 *framebuffer2;
u16 *main_fb; /* Points to the main framebuffer */

/* VSYNC: 1 for yes, 0 for no. IMPORTANT: With double buffering set to
* yes */
int vsync = 0;

void fb_init() {
framebuffer1 = (u16*) FRAMEBUFFER1; /* 0x0C7B4000 */
framebuffer2 = (u16*) FRAMEBUFFER2; /* 0x0C7DA000 */
gp_initFramebuffer(framebuffer1,16,85);
gp_initFramebuffer(framebuffer2,16,85);
gp_clearFramebuffer16(framebuffer1,0x0000); /* Clear Framebuffer1 */
gp_clearFramebuffer16(framebuffer2,0x0000); /* Clear Framebuffer2 */
main_fb = framebuffer1;
}

void flip() {
if (main_fb == framebuffer1) {
gp_setFramebuffer(framebuffer1,vsync); /* Display of Screen 1 */
main_fb = framebuffer2;
gp_clearFramebuffer16(main_fb,0x0000); /* Clear Framebuffer2 */
}
else if (main_fb == framebuffer2) {
gp_setFramebuffer(framebuffer2,vsync); /* Display of Screen 2 */
main_fb = framebuffer1;
gp_clearFramebuffer16(main_fb,0x0000); /* Clear Framebuffer1 */
}
}


Los comentarios están en inglés porque el código lo escribo todo en inglés, pero amos no habrá problema con eso jejeje.

Y aquí va el bucle principal del juego:


/* MAIN LOOP ************************************************** *******/

int main() {

int fps;
int frames = 0;
char sbuffer[16];

/* Set the GP32 CPU to 66 MHz and init the framebuffers */
gp_setCpuspeed(66);
fb_init();

gp_initRTC(); /* Init the timer */

/* Main game loop */
while (1) {

/* Hacemos las cosillas */
/* fps counter */
gp_drawString(300,5,2,sbuffer,0xF800,main_fb);

/* Change the main framebuffer */
flip();

/* fps count stuff */
frames++;
if (gp_getRTC() >= 63) {
fps = frames;
frames = 0;
sprintf(sbuffer,"%d",fps);
gp_clearRTC();
gp_initRTC();
}

/* GP32 pause and reset stuff (son funciones propias) */
check_pause();
check_reset();

}
}


Si tienes alguna pregunta pos ya sabes ;)

Nuak
20/08/2004, 20:43
Bueno por si no entiendes el contador de FPS, el RTC del SDK de Mr. Mirko funciona llama al timer 64 veces por segundo, de ahí la comprobacion de >= 63.

Si lo que quieres es limitar los FPS a 60 fps por ejemplo, lo que hay que hacer es lo que dices, tienes que tomar tiempos al comienzo del bucle y al final del bucle, haciendo el delay de la diferencia cuando termina el bucle, si te excedes de ese tiempo pos sólo te queda ajo y agua, el juego irá a pedetes y te toca optimizar ;)

K-teto
21/08/2004, 01:22
Bueno, y si quieres codigo de las funciones para esperar al retrazado de la pantalla (imprescindible si quieres suavidad), un delay, aunque eso es mas simple que nah... y lo basico para iniciar y dibujar, solo dimelo y te voy pegando codigo comentado, de todos modos todo lo puedes encontrar en ejemplos por ahi repartidos, aunque yo lo de esperar al retrazado no lo sabia y me lo dijeron por #gp32dev (Gracias tito rlyeh, todos te amamos y veneramos XD)

Edit: ah, se me olvidaba, esto te lo digo para el sdk oficial, fui a usar el de mr mirko una vez, pero como no me convencia me puse con el sdk de gamepark.

mortimor
21/08/2004, 08:20
El SDK de MrMirko esta muy bien la verdad, es muy completo y permite cosas tan bonitas como manejo de los controles mediante interrupciones, sound ring integrado, reproducir mods con solo unas lineas...

Lo ideal es utilizar interrupciones en la medida de lo posible (sonido, controles y control de frames), esto nos permite aprobechar la cpu de verdad y por ejemplo utilizar un triple buffer para conseguir suavidad de verdad (eso se tiene con el doble buffer, pero el triplebuffer permite aprobechar los tiempos de espera para calcular mas frames u otras cosas).

Ojala tenga vacaciones pronto... :D:D:D

Nuak
21/08/2004, 09:00
Triple buffer, madre mia :)
Probaré a implementarlo, en todo caso con double buffering va completamente suave, y bueno, implementar las funciones es igual en tos laos solo cambian los nombres y parametros de las funciones llamadas.

Locke
21/08/2004, 13:19
Ok, muchas gracias. De momento estoy con los examenes, pero cuando los acabe lo pruebo y os comento que tal. ;)