2 --------------------------------------------------------
4 --------------------------------------------------------
5 Loop principal del juego
6 --------------------------------------------------------
37 volatile int speed_counter
= 0; /* contador de velocidad para frame skip */
38 volatile int frame_count
, fps
; /* para contar los fps en caso de debug... */
40 /* estos contadores son para medir los fps con mas precision, max, med y min */
41 volatile int fps_min
, fps_max
, fps_med
;
43 static PALETTE pal_game_oscura
; // paleta del juego 'oscura',
44 // sirve para cuando se ponen menus, etc
45 // de esa manera, hace un efecto 'oscuro'
48 // Funcion que llena la pal_game_oscura con la paleta actual oscurecida.
49 // Usara la paleta actual, asique setear primero la paleta adecuada
50 // Pasar en oscurecer la cantidad de oscurecimiento (0.01 a 1.00)
51 // NOTA: Ignora todos los colores que utiliza la GUI
52 // o sea, los colores definidos en guiprocs.c -> xset_gui_colors()
53 static void llenar_pal_game_oscura(float oscurecer
)
59 get_palette(pal_game_oscura
);
60 for (i
= 0; i
<256; i
++ )
63 // observad que if mas horrible!!!
64 if (i
== gui_text_color
||
65 i
== gui_back_color
||
66 i
== gui_white_color
||
67 i
== gui_light_color
||
68 i
== gui_dark_color
||
69 i
== gui_black_color
||
74 ignorar
= TRUE
; // ignorar el color porque es del GUI
81 r
= (int)pal_game_oscura
[i
].r
;
82 g
= (int)pal_game_oscura
[i
].g
;
83 b
= (int)pal_game_oscura
[i
].b
;
84 // multiplico por 4, porque el rango va de 0..63 en paleta y de 0..255 en la funcion de hsv
85 rgb_to_hsv(r
*4, g
*4, b
*4, &h
, &s
, &v
);
89 hsv_to_rgb(h
, s
, v
, &r
, &g
, &b
); // generar nuevo color
90 r
/= 4; g
/= 4; b
/= 4;
91 pal_game_oscura
[i
].r
= r
;
92 pal_game_oscura
[i
].g
= g
;
93 pal_game_oscura
[i
].b
= b
;
99 /* Cuenta las fps y saca promedio de fps*/
104 /* ir sacando promedio */
106 fps_med
= fps_med
/ 2;
110 END_OF_FUNCTION(fps_proc
);
112 /* Cuenta la velocidad del juego */
113 void increment_speed_counter()
117 END_OF_FUNCTION(increment_speed_counter
);
120 /*--------------------------------------------------------
121 Actualiza la logica del juego
122 --------------------------------------------------------*/
123 void update_game_logic()
125 ejecutar_poll_musica(); /* continuar ejecutando la musica */
127 rvideo_record(kfbufferbmp
, pal_game
); // grabar 'video' a disco - DEBUG
129 scroll_mapa
-= ABS(scroll_mapa_speed
);
134 /* ver, si no quedan mas enemigos, PASO de nivel!!! */
135 if (enemigo_1
== NULL
&& jugador
.vida
> 0) /* la lista esta vacia, no hay enemigos */
137 /* adelantar al jugador, llevarlo al borde superior, y hay si, salir */
138 if (ABS((fixtoi(jugador
.x
)+(jugador
.spr
[1]->w
/2)) - (ANCHO_FB
/2)) > jugador
.spr
[1]->w
*2) // evita un efecto raro al acercarse al centro
140 if ( ANCHO_FB
/2 < fixtoi(jugador
.x
)+jugador
.spr
[1]->w
/2 )
141 jugador
.dx
=fixsub(jugador
.dx
, ftofix(VEL_X_J
*1.2));
143 if ( ANCHO_FB
/2 > fixtoi(jugador
.x
)+jugador
.spr
[1]->w
/2 )
144 jugador
.dx
=fixadd(jugador
.dx
, ftofix(VEL_X_J
*1.2));
147 { jugador
.dx
= 0; } // avanzar recto...
149 if (fixtoi(jugador
.y
) > 5) // ir hacia la parte superior del nivel (la salida)
151 jugador
.y
= fixsub(jugador
.y
, ftofix(MAX_VEL_J_X
));
152 jugador
.dy
= fixsub(jugador
.dy
, ftofix(VEL_Y_J
*1.5));
156 paso_de_nivel
= TRUE
;
161 /* el jugador se tiene que mover con el mapa */
162 if (scroll_mapa
> 0) jugador
.y
= fixsub(jugador
.y
, itofix(1));
164 // obtener teclado si es necesario (algunas plataformas...)
165 if (keyboard_needs_poll()) poll_keyboard();
167 interpreta_teclado(); // teclado del jugador
168 mover_jugador(scroll_mapa
);
169 mover_bomba(); /* bomba especial del jugador */
170 mover_enemigos(scroll_mapa
);
171 mover_disparos_jug(scroll_mapa
);
172 mover_disparos_ene(scroll_mapa
);
174 if (nivel_detalle
> 0) mover_particulas(0, scroll_mapa
, ANCHO_FB
, ALTO_FB
);
176 mover_explosiones(&ptr_explo_fondo
);
177 mover_explosiones(&ptr_explo_arriba
);
178 mover_emisor_humo(0, scroll_mapa
, ANCHO_FB
, ALTO_FB
); // emisores de humo! wow!
179 mover_humo(0, scroll_mapa
, ANCHO_FB
, ALTO_FB
);
181 mover_premio(0, scroll_mapa
, ANCHO_FB
, ALTO_FB
); // premios...
183 if (nivel_detalle
> 1) mover_clima(kfbufferbmp
); // mover clima
185 /* ver si aparecen nuevos enemigos */
186 scan_nuevos_enemigos(scroll_mapa
/ H_GR
);
188 /* TECLADO ADICIONAL - FUNCIONES PROPIAS DEL JUEGO */
190 /* TECLA PAUSE o P, sirve para poner la PAUSA! */
191 if (key
[KEY_PAUSE
] || key
[KEY_P
])
195 key
[KEY_PAUSE
] = FALSE
;
198 set_palette(pal_game_oscura
);
200 alert(get_config_text("Pause"), NULL
, NULL
, get_config_text("Continue"), NULL
, 0, 0);
202 key
[KEY_PAUSE
] = FALSE
;
204 frame_count
= fps
= speed_counter
= 0; /* evita salto en los fps */
207 set_palette(pal_game
);
211 /* ESC: menu con varias opciones */
214 DIALOG esc_key_dlg
[] =
216 /* (proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
217 { xbox_proc
, 0, 0, 200, 128, 0, 0, 0, 0, 0, 0, NULL
, NULL
, NULL
},
218 { xbutton_proc
, 8, 8, 184, 32, 0, 0, 0, D_EXIT
, 0, 0, "Configuration", NULL
, NULL
},
219 { xbutton_proc
, 8, 48, 184, 32, 0, 0, 0, D_EXIT
, 0, 0, "Abort Game", NULL
, NULL
},
220 { xbutton_proc
, 8, 88, 184, 32, 0, 0, 0, D_EXIT
, 0, 0, "Resume game", NULL
, NULL
},
221 { NULL
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL
, NULL
, NULL
}
225 traducir_DIALOG_dp(esc_key_dlg
);
226 centre_dialog(esc_key_dlg
);
227 set_dialog_color(esc_key_dlg
, makecol(0,0,0), makecol(255,255,255));
228 key
[KEY_ESC
] = FALSE
;
231 set_palette(pal_game_oscura
);
233 /* mostrar dialogo */
234 switch (popup_dialog(esc_key_dlg
, 0))
236 case 1: // configurar - DEBUG, truchisimo lo del F5
240 case 2: // abortar juego
241 if (alert(get_config_text("Exit game"),
244 get_config_text("Yes"),
245 get_config_text("No"),
248 salir_del_juego
= TRUE
;
257 frame_count
= fps
= speed_counter
= 0; /* evita salto en los fps */
259 set_palette(pal_game
);
262 /* F5: menu de configuracion general, sonido, detalles, controles, etc */
265 int tmp1
= quiere_musica
;
268 set_palette(pal_game_oscura
);
271 menu_configuracion_al_vuelo();
272 frame_count
= fps
= speed_counter
= 0; /* evita salto en los fps */
274 reajustar_volumen_musica();
276 set_palette(pal_game
);
278 /* DEBUG: esto es para que si activa/desactiva la musica, tome efecto */
279 if (tmp1
!= quiere_musica
)
282 musica_play(info_nivel
.musica
);
287 /* F1: ayuda del programa */
291 set_palette(pal_game_oscura
);
295 frame_count
= fps
= speed_counter
= 0; /* evita salto en los fps */
298 set_palette(pal_game
);
301 /* F11 prende y apaga el modo DEBUG (muestra info extra) */
302 if (key
[KEY_F11
]) /* DEBUG, al distribuir, eliminar esto!!! */
304 key
[KEY_F11
] = FALSE
;
305 KRONO_QUIERE_DEBUG
= !KRONO_QUIERE_DEBUG
;
308 /* F12 sirve para capturar pantallas */
313 key
[KEY_F12
] = FALSE
;
315 capturar_la_pantalla("krap");
316 alert("Screen captured!", NULL
,NULL
,"OK", NULL
,0,0);
317 frame_count
= fps
= speed_counter
= 0;
318 // continuar_musica();
321 /* F10 sirve para prender/apagar la grabacion de videos - DEBUG! */
322 #ifdef SECCION_DESACTIVADA_PARA_EL_RELEASE
325 rvideo_is_recording
= !rvideo_is_recording
;
326 key
[KEY_F10
] = FALSE
;
333 /*--------------------------------------------------------
334 Actualiza la pantalla
335 --------------------------------------------------------*/
336 void update_display()
339 /* Tuberia de dibujado, en orden de abajo arriba */
341 set_clip(kfbufferbmp
, 0, 0, mapa_fondo
->w
-1, kfbufferbmp
->h
-1); /* clipping adecuado */
343 // solo dibuja si la bomba especial no esta activa, sino, es desperdiciar rendering
344 if (!bomba_esta_activa
)
347 blit(mapa_fondo
, kfbufferbmp
, 0, scroll_mapa
, 0, 0, mapa_fondo
->w
, kfbufferbmp
->h
);
349 if (nivel_detalle
> 3) dibujar_humo(kfbufferbmp
, 0, scroll_mapa
);
351 dibujar_explosion(ptr_explo_fondo
, kfbufferbmp
, 0, scroll_mapa
);
353 dibujar_disp_ene(kfbufferbmp
, 0, scroll_mapa
);
355 dibujar_enemigos(kfbufferbmp
, 0, scroll_mapa
);
357 dibujar_disp_jug(kfbufferbmp
, 0, scroll_mapa
);
359 dibujar_nave_jugador(kfbufferbmp
, 0, scroll_mapa
);
361 dibujar_premio(kfbufferbmp
, 0, scroll_mapa
);
363 if (nivel_detalle
> 0) dibujar_particulas(kfbufferbmp
, 0, scroll_mapa
);
365 dibujar_explosion(ptr_explo_arriba
, kfbufferbmp
, 0, scroll_mapa
);
367 if (nivel_detalle
> 1) dibuja_clima(kfbufferbmp
); // clima
368 } // fin de ver si esta detonando la bomba
371 dibujar_bomba(kfbufferbmp
);
374 /* DEBUG: info de FPS, cantidades, etc */
375 if (KRONO_QUIERE_DEBUG
)
379 /* DEBUG: lo saque, porque ya no lo preciso...
380 textprintf(kfbufferbmp, font, 0, kfbufferbmp->h - text_height(font)-2, makecol(255,255,255),
381 "|fps:%5d|ener:%3d|e:%5d|p:%5d|ex:%5d|" ,
385 cant_particulas_debug,
386 cant_explosion_debug );
389 // Solo fps... por ahora - DEBUG
390 textprintf(kfbufferbmp
, font
, 0, kfbufferbmp
->h
- text_height(font
)-2, makecol(255,255,255),
391 "fps:%5d fps_max:%5d fps_min:%5d fps_med:%5d",
392 fps
, fps_max
, fps_min
, fps_med
);
397 set_clip(kfbufferbmp
, 0, 0, kfbufferbmp
->w
-1, kfbufferbmp
->h
-1); /* clipping adecuado */
399 dibujar_tablero(kfbufferbmp
);
402 enviar_kfbuffer2screen();
406 Esta es la secuencia y loop principal del juego
407 Llamar para comenzar un juego nuevo
408 NOTA: si el parametro load_savegame != 0, se asume
409 que se esta cargando un juego de disco,
410 y no se alteran las variables del jugador!!
412 void comenzar_juego(int load_savegame
)
414 /* funcion interna que libera listas enlazadas */
415 void liberar_listas_interno()
417 /* LIBERAR LISTAS... */
418 liberar_lista_enemigos();
419 liberar_lista_disparos_ene();
420 liberar_lista_disparos_jug();
421 liberar_lista_particulas();
422 liberar_lista_explosion(&ptr_explo_fondo
);
423 liberar_lista_explosion(&ptr_explo_arriba
);
424 liberar_emisores_humo();
429 /* funcion interna que limpia los colores y bufferes
430 y coloca la paleta de juego, etc */
431 void hacer_cleanup_mapeos()
433 set_palette(pal_game
);
434 color_map
= &tabla_transparencia
; /* la rutina de sombras la precisa! */
435 rgb_map
= &tabla_RGB
; /* acelera la fabricacion de colores de 8 bits */
436 set_trans_blender(128, 128, 128, 128); /* Transparencia 50% para > 8 bits */
437 clear(kfbufferbmp
); clear(screen
); /* limpiar bufferes */
439 xset_gui_colors(); /* setea el GUI */
440 set_mouse_sprite(NULL
); /* acomoda puntero del mouse para que se ajuste a los colores */
441 llenar_pal_game_oscura(0.25); // prepara la paleta oscura para efectos en los menues
444 /* Funcion interna para instalar los timers */
445 void pone_timers_juego()
448 if (install_int_ex(increment_speed_counter
, BPS_TO_TIMER(30)))
449 levantar_error("ERROR: no hay espacio para instalar el timer a 30 fps\n"); /* a 30 fps el juego */
451 if (install_int(fps_proc
, 1000))
452 levantar_error("ERROR: no hay espacio para instalar el timer a 1000 milisegundos!\n"); /* a 1000 milisegundos (1 segundo) el contador de fps */
454 /* Reiniciar contadores de velocidad... */
455 frame_count
= fps
= speed_counter
= 0; /* evita salto en los fps */
458 /* Funcion interna para SACAR los timers */
459 void saca_timers_juego()
461 /* remover timers... */
462 remove_int(fps_proc
);
463 remove_int(increment_speed_counter
);
467 salir_del_juego
= FALSE
;
469 /* Reiniciar juego, solo si no esta cargando un juego de disco */
473 reset_total_jugador();
479 LOCK_VARIABLE(fps_med
);
481 /* Frameskip timer */
482 LOCK_VARIABLE(speed_counter
);
483 LOCK_FUNCTION(increment_speed_counter
);
486 LOCK_VARIABLE(frame_count
);
488 LOCK_FUNCTION(fps_proc
);
490 /* Inicia doble buffer */
491 kfbufferbmp
= create_system_bitmap(ANCHO_RFB
, ALTO_RFB
);
492 if (kfbufferbmp
== NULL
) levantar_error("ERROR: fallo la creacion del doble buffer! (falta RAM?)");
494 hacer_cleanup_mapeos(); /* limpiar pantalla y mapeos */
496 /* cinematica de introduccion al juego, solo si es el primer nivel */
497 if (nivel_actual
== 1) ejecutar_cinematica(game_intro_cine
);
499 /* iniciar engine de grabado de videos de promocion */
502 /* Loop principal de juego */
503 while (!salir_del_juego
) {
505 paso_de_nivel
= FALSE
;
507 reset_parcial_jugador(); /* reposicionar jugador, etc */
510 Verifico que el proximo nivel exista, si es asi,
511 paso a dibujar las cinematicas, y luego, cargo el nivel en RAM (para ahorrar RAM)
513 if (!cargar_nivel(nivel_actual
, -1))
515 liberar_listas_interno(); /* LIBERAR LISTAS... */
516 scroll_mapa
= H_FONDO
- ALTO_FB
; /* iniciar scrolling */
518 hacer_cleanup_mapeos();
521 do_shopping_principal();
523 /* cinematica de entrada al nivel */
524 ejecutar_cinematica(info_nivel
.cine_in
);
526 /* Luego de las cinematicas, es necesario restaurar mapa RGB,
527 mapa de transparencias y paleta de color... */
528 hacer_cleanup_mapeos();
530 if (cargar_nivel(nivel_actual
, 0)) /* cargar el nivel en RAM, en serio... */
531 levantar_error("Fallo la carga del nivel!"); /* shit! que paso - DEBUG */
533 scan_nivel_1era_vez(); /* scanear los enemigos en la pantalla por 1era vez */
535 /* Los timers deben ir EXACTAMENTE antes del while, caso contrario,
536 salta tantos frames como tiempo consuma todo lo anterior! */
537 pone_timers_juego(); /* instala los timers... */
540 musica_play(info_nivel
.musica
); /* comenzar a ejecutar musica - DEBUG */
542 // Iniciar efectos de clima
543 init_clima(kfbufferbmp
, info_nivel
.clima_c
, info_nivel
.clima_t
, info_nivel
.clima_d
);
545 while( !paso_de_nivel
&& !salir_del_juego
)
547 while (speed_counter
> 0)
549 update_game_logic(); // actualizar logica del juego
552 update_display(); // actualizar pantalla
554 frame_count
++; // contar los fps
556 /* DEBUG: conteo de fps mas preciso */
557 if (fps
> fps_max
) fps_max
= fps
;
558 if (fps
< fps_min
&& fps
> 0) fps_min
= fps
;
560 if (detalle_automatico
)
562 nivel_detalle
= (fps
* 10)/30;
563 if (nivel_detalle
> 10) nivel_detalle
= 10;
564 if (nivel_detalle
< 0) nivel_detalle
= 0;
567 } /* looping de juego en el nivel actual */
569 musica_stop(); /* parar musica - DEBUG */
571 saca_timers_juego(); /* desactiva los timers... */
573 /* eliminar los datos del nivel de RAM */
576 unload_datafile(datmapa
);
580 if (mapa_fondo
!= NULL
)
582 /* liberar RAM consumida por el nivel */
583 destroy_bitmap(mapa_fondo
); /* mapa de fondo */
588 if (jugador
.vida
<= JUG_MUERTO
) /* ahora si murio... */
590 paso_de_nivel
= FALSE
; /* sorry gordi, no pasas si estas muerto! */
591 salir_del_juego
= TRUE
;
593 /* cinematica de game over */
594 ejecutar_cinematica(game_over_cine
);
596 /* Luego de las cinematicas, es necesario restaurar mapa RGB,
597 mapa de transparencias y paleta de color... */
598 hacer_cleanup_mapeos();
600 clear(screen
); /* DEBUG, queda bien? */
604 alert(get_config_text("Game Over"), NULL
, NULL
, get_config_text("OK"), NULL
, 0, 0);
607 else /* no encontro el nivel */
609 /* DEBUG: si no encuentra el proximo nivel,
610 SIGNIFICA QUE TERMINO EL JUEGO! */
612 /* Luego de las cinematicas, es necesario restaurar mapa RGB,
613 mapa de transparencias y paleta de color... */
614 hacer_cleanup_mapeos();
616 clear(screen
); /* DEBUG, queda bien? */
620 alert(get_config_text("This is the end of the game"), NULL
, NULL
, get_config_text("OK"), NULL
, 0, 0);
622 salir_del_juego
= TRUE
;
625 if (paso_de_nivel
) /* funciones al pasar de nivel */
627 /* ejecutar cinematica salida nivel */
628 ejecutar_cinematica(info_nivel
.cine_out
);
633 } /* looping de juego a traves de los niveles */
635 /* Liberar memoria */
636 liberar_listas_interno(); /* LIBERAR LISTAS... */
637 destroy_bitmap(kfbufferbmp
); /* DOBLE BUFFER */