2. ESTRUCTURA
Tenéis el proyecto en: Tutorial de programación c++ (2/11)
Lo que definirá la dificultad de programar un videojuego es la primera estructura que le das al código. Si está bien planteado, programarlo será cosa de niños, pero si has ido escribiendo las cosas según se te ocurrían, te verás en el mismísimo infierno.
No te preocupes porque nos ha pasado a todos. A nuestro juego del Batiscafo le vamos a dar una estructura que de un primer vistazo te explica claramente dónde están todas las cosas, y en qué sitios puedes meter mano.
Antes de pasar al código vamos a pensarlo en esquema. Nuestro programa tendrá 3 modos de funcionamiento: modo MENU, modo JUEGO y modo PAUSA. En cada uno de esos modos nuestro programa reacciona de forma diferente y muestra en pantalla cosas diferentes.
Cada uno de esos modos utilizará 3 funciones: una para comprobar los botones, otra para actualizar lo que se muestra en pantalla y otra para dibujar en pantalla.
Podemos resumirlo así:
¿Para qué nos sirve esto? Para dejar cada cosa en su sitio. En la función Leer_botones_juego() sólo tendremos el chequeo de los botones y las acciones que produce cada pulsación. En Actualizar_juego() sólo estarán los procesos que hacen que el juego funcione: colisiones con paredes, toques con bichos, gravedad, etc... Y en Dibujar_juego() única y exclusivamente se dibuja todo lo que aparece en el desarrollo normal del juego.Código:BUCLE PRINCIPAL { SI MODO==MENU Leer_botones_menu(); Actualizar_menu(); Dibujar_menu(); SI MODO==JUEGO Leer_botones_juego(); Actualizar_juego(); Dibujar_juego(); SI MODO==PAUSA Leer_botones_pausa(); Actualizar_pausa(); Dibujar_pausa(); }
A veces, cuando estás dibujando los bichos es muy fácil pensar en hacer las comprobaciones de colisiones. ¡Eso sería un error! Al final tendrías código desperdigado haciendo cosas en lugares diferentes. Si hay que comprobar un evento de juego, hay que meter sólo en Actualizar_juego(). Esto es esencial a la hora de buscar un error, y hay que acostumbrarse a no mezclar cosas (repito: todos lo hemos hecho alguna vez).
Veamos qué cambios hay en main.cpp.
Lo primero que hemos metidos son las 3 constantes que definirán en qué modo se encuentra nuestro juego.Código://///////////////////////////////// /* Modo de programa */ /////////////////////////////////// #define PROGRAM_MODE_MENU 1 #define PROGRAM_MODE_GAME 2 #define PROGRAM_MODE_PAUSE 3
En la parte de las variables globales hemos añadido una nueva: program_mode. Esta nos indicará el modo actual del juego para que podamos llamar a las funciones de cada modo. La iniciamos a PROGRAM_MODE_MENU, porque lo primero que veremos será el menú.Código://///////////////////////////////// /* Variables globales */ /////////////////////////////////// int program_mode=PROGRAM_MODE_MENU;
Estas son las tres funciones del modo menú. En read_menu_keys() meteremos un bucle para leer todos los eventos del joystick. Si pulsamos el botón MENU saldremos del juego poniendo la variable done=1. Es exactamente lo mismo que el bucle principal del tutorial 1, sólo que esta vez lo hemos metido en una función propia.Código:void read_menu_keys() { SDL_Event event; // Comprueba los eventos de botones while (SDL_PollEvent(&event)) { switch (event.jbutton.button) { case GP2X_BUTTON_START: done=1; break; } } } void draw_menu() { } void update_menu() { read_menu_keys(); draw_menu(); }
draw_menu(); dibujará las opciones del menú y por ahora lo dejamos en blanco.
update_menu(); es la función principal del modo MENU. Desde ahí leeremos las pulsaciones de botones, cambiaremos la selección del menú y lo dibujaremos en pantalla. Por ahora sólo llamaremos a las funciones read_menu_keys() y draw_menu().
Las funciones del modo juego son exactamente iguales. La diferencia es que el menú dibujará en pantalla varias opciones de texto, como Jugar, Salir, etc... y el juego dibujará nuestra nave, los bichos...Código:void read_game_keys() { SDL_Event event; // Comprueba los eventos de botones while (SDL_PollEvent(&event)) { switch (event.jbutton.button) { case GP2X_BUTTON_START: done=1; break; } } } void draw_game() { } void update_game() { read_game_keys(); draw_game(); }
Y las 3 funciones del modo pausa, totalmente clavadas a las anteriores. Con estas funciones el bucle principal del programa va a sufrir un cambio que lo dejará un poco más claro de entender. El resto de la funcion main() permanece igual.Código:void read_pause_keys() { SDL_Event event; // Comprueba los eventos de botones while (SDL_PollEvent(&event)) { switch (event.jbutton.button) { case GP2X_BUTTON_START: done=1; break; } } } void draw_pause() { } void update_pause() { read_pause_keys(); draw_pause(); }
Como veis, lo que hacemos en el bucle principal es comprobar en qué modo estamos. Si estamos en modo menu llamamos a la función update_menu(), si estamos en modo juego llamamos a la función update_game() y si estamos en modo pausa llamamos a update_pausa(). La función apropiada dibujará en pantalla lo que toque y con SDL_Flip() se mostrará en pantalla.Código:while (!done) { switch (program_mode) { case PROGRAM_MODE_MENU: update_menu(); break; case PROGRAM_MODE_GAME: update_game(); break; case PROGRAM_MODE_PAUSE: update_pause(); break; } SDL_FillRect(screen, NULL, 0x000000); SDL_Flip(screen); }
Ahora mismo seguirá dibujándose en negro, pero eso lo cambiaremos en el tutorial número 3.
Marcadores