programar nds

49
Desarrollo de un videojuego para Nintendo DS TITULACIÓN: Ingeniería Técnica en Informática de Gestión. AUTORA: Noemí Ferrer Ortiz. DIRECTOR: Pere Millán Marco. FECHA: Junio / 2010 Departament d’Enginyeria Informàtica i Matemàtiques

Upload: esteban-garcia-monsalve

Post on 12-Jan-2016

63 views

Category:

Documents


2 download

DESCRIPTION

Como aprender a programar en nds.

TRANSCRIPT

Page 1: Programar Nds

Desarrollo de un videojuego para Nintendo DS

TITULACIÓN: Ingeniería Técnica en Informática de Gestión.

AUTORA: Noemí Ferrer Ortiz.DIRECTOR: Pere Millán Marco.

FECHA: Junio / 2010

Departament d’Enginyeria Informàtica i Matemàtiques

Page 2: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

1

Índice 1 – Objetivos del proyecto 2 2 – Especificaciones del proyecto 3

2.1 – Especificación del Hardware de la Nintendo DS 3 2.2 – SDK disponibles 3 2.3 – Librería Palib 4

2.3.1– Entrada / Salida 6 2.3.2– Sonido 7 2.3.3– Sprites 9 2.3.4– Backgrounds 13 2.3.5– Texto 16bit y Custom Font 14 2.3.6– Sistema de ficheros FAT 15

3 – Diseño 17

3.1 – Desarrollo de la partida 17 3.2 – Evolución de la mascota 23 3.3 – Minijuego del Simón 27

4 – Desarrollo 31 4.1 – Estructura de ficheros 31

4.1.1 – Fichero main.cpp 32 4.1.2 – Clase partida 34 4.1.3 – Clase botones 36 4.1.4 – Clase pantalla 37 4.1.5 – Clase de idiomas 39

5 – Evaluación 40 5.1 – Posibles ampliaciones 40 6 – Conclusiones 41 7 – Recursos utilizados 42 8 – Anexos 44

Page 3: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

2

1- OBJETIVOS DEL PROYECTO

El objetivo de este proyecto de final de carrera es desarrollar un juego para Nintendo DS. En concreto, el juego consiste en una mascota virtual, a la que se ha de alimentar y jugar con ella para que se desarrolle.

La idea está basada en uno de los primeros juegos de mascotas virtuales llamado Tamagotchi, que fue creado en 1996 por Aki Maita y comercializado por Bandai.

En este juego se utilizará básicamente la touch screen, para mostrar el potencial de una consola portátil con capacidad táctil. El juego está disponible en 3 idiomas: Inglés, Castellano y Catalán. De esta manera el juego es accesible a más personas. En un futuro pueden añadirse más idiomas al juego modificando una clase. El nombre del video juego es Virtual Kachiku, donde Kachiku significa mascota en japonés.

Page 4: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

3

2 – Especificaciones del proyecto En este juego el usuario deberá escoger una de las cuatro mascotas disponibles, darle un nombre y así empezará el juego. Todos los gráficos del juego son de diseño propio y están realizados en Flash y retocados con Photoshop para adaptarlos a la paleta de colores de NDS. Uno de los objetivos de utilizar estos gráficos es que el juego tenga una interfaz amigable para cualquier tipo de jugador, ya sea niño, adulto o anciano. El sistema de sonido avisa cuando a la mascota le falta algún cuidado, como por ejemplo si tiene hambre, es feliz o no, o si está mal de salud. El jugador puede interactuar con su mascota dándole de comer escogiendo entre una gran variedad de platos, cada uno con unas características únicas que hacen que se tenga que ser cuidadoso a la hora de alimentarlo, si se quiere que la mascota tenga buena salud y crezca bien. Para que la mascota sea feliz y ayudarla a tener una vida saludable, el usuario podrá jugar a un minijuego incorporado, que consiste en repetir con la pantalla táctil una secuencia de colores que se mostrarán por pantalla. Tiene 3 rondas y la dificultad es progresiva. Finalmente, dependiendo de la salud, el hambre y la felicidad de la mascota, ésta evolucionará de una forma u otra y su aspecto cambiará entre dos estados diferentes. A lo largo del día el escenario cambiará dependiendo de si es de día o de noche. Esto se consigue gracias a las funciones de interacción con el hardware que ofrece Palib, estas funciones nos indican la hora real en la que nos encontramos.

2.1 - Especificación de hardware de la Nintendo DS Nintendo DS es una consola portátil creada por la compañía Nintendo en el año 2004. Desde el lanzamiento de su primer modelo (DS), han aparecido nuevas versiones: DS Lite, Dsi, Dsi XL, y 3DS (que está en desarrollo y fue anunciada el 23 de marzo de 2010). La consola es capaz de procesar operaciones gráficas 3D por hardware. Podemos elegir entre diversas librerías para el desarrollo del juego. En este caso utilizaremos una librería opensource. Las librerías opensource disponibles son Libnds y Palib. Libnds es una librería que trabaja a más bajo nivel. Palib utiliza Libnds e implementa una librería de más alto nivel. Este proyecto ha sido desarrollado con una DS Lite utilizando la librería Palib.

2.2 – SDK Disponibles Para empezar a programar el proyecto, se ha de elegir un SDK (software development kit). Podemos elegir entre dos bien diferenciados:

� El SDK oficial llamado CodeWarrior Development Studio de la compañía Metroworks. − Ventajas:

• Acceso total a los recursos de la consola.

Page 5: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

4

• Soporte oficial de Nintendo y Metroworks. • Genera software de calidad profesional.

− Desventajas • Hay que solicitar a Nintendo ser desarrollador. • Hay que pagar el precio de la licencia del SDK a Metroworks.

� DevKitARM + PALib:

− Ventajas: • Es gratuito. • Es compatible con Windows, Linux y Mac Os X.

− Desventajas • No aprovecha al máximo los recursos de la consola. • No tiene soporte oficial. • Se necesita un emulador para probar el juego, y una tarjeta flash card para poder

utilizar el juego en la consola.

2.3 - Librería Palib PALib es una librería especial para Nintendo DS creada para poder desarrollar aplicaciones de homebrew. Se denomina homebrew a todas aquellas aplicaciones y juegos programados por aficionados. PALib esta basada en la librería Libnds, que trabaja a más bajo nivel. Para poder ejecutar nuestros juegos y aplicaciones desarrollados en PALib, necesitaremos una tarjeta flashcard compatible con nuestra consola. Para empezar a trabajar con PALib, instalaremos DevKitPro. DevKitPro es un paquete de herramientas para el desarrollo de homebrew, en el que se incluyen las librerías necesarias para programar en diferentes consolas, tales como GameBoy Advance (GBA), Nintendo DS, Nintendo Wii, GameCube, PSP y GP32. DevKitPro está disponible en diferentes sistemas operativos: Windows, Mac y Linux. A la hora de instalar DevKitPro, tendremos la opción de instalar las librerías para Nintendo DS y GBA (devkitARM), las de GameCube y Wii (devkitPPC) y las dedicadas a PSP (devkitPSP). En este caso escojeremos el paquete de desarrollo para Nintendo DS (devkitARM) tal y como muestra la siguiente imagen:

Page 6: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

5

Figura 1- Instalación de DevkitPro

Es importante también tener instalado .NET Framework, ya que sin esto, PALib no funcionará correctamente. Debemos tener en cuenta que DevKitPro y PALib no podemos instalarlos en carpetas cuyos nombres contengan espacios, ya que sinó no funcionarán. La mejor opción es instalar ambas herramientas en la ruta C:\devkitPro en el caso de Windows. Al ejecutar el instalador de PALib podremos elegir qué queremos instalar y qué no, tal y como se muestra a continuación:

Page 7: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

6

Figura 2 – Instalación de PALib

Es recomendable instalar la documentació de PALib y sus ejemplos, aunque no sean necesarios para su funcionamiento, ya que son una gran ayuda para el desarrollo de las aplicaciones. Cuando tengamos todo instalado, deberíamos tener una carpeta como la siguiente:

Figura 3 – Carpeta de devkitPro

2.3.1 - Entrada/Salida En Nintendo DS disponemos de varias opciones de entrada y salida de datos: el stylus (lápiz o puntero), Pad (botones), micrófono, pantalla, etc. Palib nos permite utilizar todos estos recursos para poder elaborar juegos con una alta

Page 8: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

7

capacidad de interacción con el usuario. En nuestro juego tendremos que comprobar los estados de los dispositivos de entrada y salida en cada frame. Se denomida frame a una iteración del bucle de nuestro juego. Pad: es el conjunto de botones de la consola (A, B, X, Y, R, L, up, down, left, right, select y start). El pad se actualiza a cada frame y utiliza los estados Held, Released y Newpress. Held tiene como valor inicial 0 y cambia al valor 1 cuando se presiona el botón. Released toma el valor 1 cuando se deja de apretar un botón y Newpressed toma el valor 1 cuando se presiona un botón (estos dos últimos casos permanecen con el valor 1 un solo frame). Un ejemplo de utilización del pad con las funciones de Palib. if(Pad.Held.Up)

{

MoveUp();

}

if(Pad.Held.Down)

{

MoveDown();

}

Stylus: al igual que el pad, se actualiza en cada frame y tiene los estados Held, Released y Newpressed, que funcionan igual que con el pad. Además tiene los atributos X e Y que nos informa de las coordenadas donde se ha producido el evento. Un ejemplo de utilización del stylus con funciones Palib: if (Stylus.Held)

{

PA_OutputSimpleText(1,0,0,"Stylus activo");

}

2.3.2– Sonido Palib no puede reproducir sonidos mp3 o wav directamente, por lo que tendremos que utilizar una de las dos librerías que ofrece: ASlib o Maxmod. En este caso se ha utilizado la librería Aslib, con la que se pueden llegar a reproducir sonidos mp3 y raw. En un principio podríamos pensar que el formato mp3 sería un buen candidato para reproducir nuestros sonidos, pero en realidad es mejor no utilizar mp3 en nuestras aplicaciones para Nintendo DS ya que su reproducción ocupa mucha memoria y no es óptimo. En vez de mp3, utilizaremos sonidos en formato raw. Para conseguir un sonido en raw utilizaremos Switch, un programa para convertir sonidos entre diferentes formatos. A continuación se puede observar una imagen del programa:

Page 9: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

8

Figura 4 - Switch

Haremos click en Encoder Options y pondremos la siguiente configuración. De esta manera optimizaremos el espacio y la calidad que tendrá el fichero de acuerdo a las características de la consola.

Figura 5 – Características del formato raw

Cuando ya tenemos el archivo de sonido convertido al formato raw, lo copiamos a la carpeta /data de nuestro proyecto. Para poder utilizar el sonido tendremos que inicializar el sistema de sonido de la consola en nuestro código, además de incluir el sonido como si de una librería se tratara: #include "simon1.h"

sonido::sonido(){

//Inicializamos el sonido del juego (raw)

AS_Init(AS_MODE_SURROUND | AS_MODE_16CH);

AS_SetDefaultSettings(AS_PCM_8BIT, 11025, AS_SURROUND);

canal = AS_SoundDefaultPlay((u8*)musica1,musica1_size, 127, 64,

true, 0);

}

Para reproducir el sonido, simplemente tendremos que utilizar la función AS_SoundQuickPlay que nos ofrece Palib:

Page 10: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

9

void sonido::Play(int opcion){

switch(opcion){

case BOTON: AS_SoundQuickPlay(boton); break;

case SONIDO_BOTON_AMARILLO: AS_SoundQuickPlay(simon1); break;

case SONIDO_BOTON_ROJO: AS_SoundQuickPlay(simon2); break;

case SONIDO_BOTON_AZUL: AS_SoundQuickPlay(simon3); break;

case SONIDO_BOTON_VERDE: AS_SoundQuickPlay(simon4); break;

case INCORRECTO: AS_SoundQuickPlay(incorrecto); break;

case JUEGO_GANADO: AS_SoundQuickPlay(ganar); break;

case SONIDO_EVOLUCION: AS_SoundQuickPlay(evolucion); break;

case ATENCION: AS_SoundQuickPlay(atencion); break;

}

}

Para reproducir la música de fondo del juego también utilizamos la librería Aslib y el formato raw. En concreto se utiliza un archivo de sonido que puede repetirse formando un bucle. Aslib nos ofrece una función para la reproducción continua de un archivo, donde si marcamos loop como true, hará un blucle con el archivo de sonido; si loop es false, el archivo sólo se reproducirá una vez: AS_SoundDefaultPlay(u8 *data, u32 size, u8 volume, u8 pan, u8 loop, u8 prio)

Si queremos parar la reproducción, simplemente tendremos que utilizar la función: AS_SoundStop(canal);

2.3.3 – Sprites Los sprites son un tipo de mapa de bits, generalmente de pequeño tamaño, de forma rectangular o cuadrada y que contiene espacios transparentes. De esta manera podemos hacer cualquier dibujo dentro de este rectángulo. En Nintendo DS son muy utilizados los sprites, ya que ocupan poca memoria y son más óptimos que si crearamos nuestros personajes y objetos en 3D. La consola puede mostrar hasta 128 sprites a la vez por cada pantalla, lo que hace un total de 256 sprites. Además cada sprite puede ser rotado, movido, escalado, etc. Por cada modificación del sprite (rotación, escalado) se creará un rotset. La memoria de la consola tiene la limitación de que sólo puede almacenar 32 rotsets diferentes. Varios sprites pueden asociarse al mismo rotset. Se denomina rotset a un conjunto de funciones que modifican un sprite, un rotset puede contener funciones de escalado y/o rotación. Como hemos dicho antes, los sprites son rectangulares y de pequeño tamaño. En Nintendo DS además contamos con una tabla que nos dice qué tamaños pueden usarse para crear nuestros sprites:

Page 11: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

10

8 16 32 64

8 8x8 16x8 32x8

16 8x16 16x16 32x16

32 8x32 16x32 32x32 64x32

64 32x64 64x64

Además del tamaño del sprite, también tenemos que elegir el modo de color del mismo, pudiendo elegir entre sprites con paletas de 16 o 256 colores, o sprites de 16 bits (65536 colores) sin paleta. Los sprites con paletas de 16 colores consumen menos memoria y eran muy utilizados en GBA (Game Boy Advance), pero con Nintendo DS ya no son tan utilizados ya que disponemos de más memoria. Este tipo de sprites admite hasta 16 paletas diferentes por pantalla. Normalmente utilizaremos los sprites con paletas de 256 colores. Al igual que los de 16 colores, también podemos contar con hasta 16 paletas diferentes por pantalla. Los sprites de 16 bits no tienen una paleta de colores asignada y no son muy utilizados ya que consumen mucho espacio y memoria de vídeo, por lo que no son óptimos en comparación con los anteriores mencionados. A continuación se muestra una imagen de la Nintendo DS donde se especifica el tamaño en píxeles y tiles de ambas pantallas. La imagen nos servirá de referencia a la hora de elegir el tamaño de nuestros sprites y colocarlos en la pantalla. Se denomina tile a un conjunto de 8x8 píxeles, que se utilizan para definir imágenes de fondo de pantalla.

Figura 6 – Nintendo DS

Al crear nuestros sprites deberemos tener en cuenta que también crearemos una paleta de

colores. Pero deberemos tener cuidado de no crear una paleta por cada sprite, ya que si tenemos más de 16 sprites, habremos gastado la memoria de paletas. Lo más optimo es compartir paletas entre

Page 12: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

11

sprites. En Nintendo DS no podemos crear sprites en formato bmp y cargarlos directamente. Antes tendremos que convertirlos a un formato específico para que la consola los entienda y sepa interpretarlo. Para ello utilizaremos un programa llamado PAGfx, en el que fácilmente cargamos los sprites que deseamos convertir y le indicamos qué nombre de paleta queremos que tenga. Si ponemos el mismo nombre de paleta para diferentes sprites querrá decir que comparten esa paleta. En la siguiente imagen se muestra como hemos cargado los sprites de comida que posteriormente se utilizarán en el juego. Se le asigna la paleta de 256 colores y además, para todos los sprites, les asignamos la paleta comida, ya que con una sola paleta de 256 colores tenemos suficientes colores para todos estos sprites.

Figura 7 - PAGfx Tendremos que especificar cuál será nuestro color transparente. En éste caso se ha elegido el

magenta, que suele ser el más utilizado, aunque también se puede especificar otro color. Cuando ya tenemos todos los sprites en el programa, seleccionamos Save and Convert y nos aparecerá una lista de ficheros en la carpeta /bin de PAGFx.

Page 13: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

12

Figura 8 - Sprites Se nos habrán creado ficheros con extensión bin, de los cuales, comida_Pal.bin es la paleta

correspondiente para todos nuestros sprites. Lo último que nos quedará por hacer será cargar los sprites al juego con las funciones de PA_LoadSpritePal, que carga una paleta de colores asociada al identificador del sprite. Posteriormente, cargaremos el sprite con PA_CreateSprite que asigna al identificador del sprite el fichero bin correspondiente (se especifica su tamaño): PA_LoadSpritePal(0, PIZZA, (void*)Pal_Pal);

PA_CreateSprite(0,PIZZA,(void*) pizza_Sprite, OBJ_SIZE_64X64, 1, 0, x, y);

En ocasiones necesitaremos sprites animados que simulen el movimiento de un personaje, o también como en el caso de este juego, botones animados para que cambien de color cuando se activen.

Figura 9 – Sprites animados

Estos sprites se cargan igual que los simples, sólo tendremos que utilizar una función extra que nos ofrece PALib para indicar cuál será la animación del sprite y cómo será. En el caso de los botones tendremos 3 frames diferentes, cada uno de 32x32 píxeles respetando los tamaños posibles. En el caso de las mascotas, tendremos 2 frames diferentes de 64x64 píxeles.

Page 14: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

13

2.3.4 – Backgrounds Para cargar backgrounds en el juego, utilizaremos el mismo programa que para los sprites, el Pagfx, con la diferencia de que añadiremos la imagen de fondo a convertir en la pestaña de backgrounds y no en la de sprites. Nintendo DS puede mostrar hasta 4 fondos diferentes por cada pantalla. En el caso de los fondos, no se pueden compartir paletas de colores como en los sprites, por lo que tendremos que tener este detalle en cuenta. La consola también puede mostrar hasta dos fondos rotándose o escalándose por pantalla. PALib nos ofrece seis modos diferentes de fondos, el modo de fondo lo tendremos que especificar en el conversor PAGfx en la columna BbMode. Los diferentes modos son los listados a continuación:

· 8bit: utiliza una imagen de mapa de bit de 8 bits. · 16bit: utiliza una imagen de mapa de bit de 16 bits. · TiledBg: se utiliza en fondos planos. Los tamaños posibles son: 256×256, 512×256,

256×512 y 512×512. · LargeMap: es un modo similar a TiledBg, pero permite tamaños de fondo más grandes,

como cualquier tipo de tamaño. · RotBg: se utiliza con fondos rotativos con diferentes tamaños: 128×128, 256×256,

512×512 y 1024×1024. · EasyBg: automáticamente selecciona entre TiledBg y LargeBg, por lo que es el modo más

utilizado.

Podemos utilizar fondos de 8 y 16 bits, pero tienen varios inconvenientes en comparación con TiledBg y LargeMap. Estos ocupan mucho espacio en la memoria de vídeo, los fondos 8bit ocupan aproximadamente un 37,5% de la VRAM y los 16bit un 75%, por lo que no son muy óptimos. Además son muy lentos de pintar en pantalla porque se pintan pixel a pixel, mientras que los TiledBg y los LargeMap se pintan por tiles.

También tienen algunas ventajas respecto a los TiledBg y LargeMap, y es que al poder usar fondos de 16 bits no tendremos limitación de paleta de colores y podremos representar todos los colores que queramos.

Figura 10 - PAGfx

Page 15: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

14

A diferencia de los sprites, los fondos no pueden compartir paletas, por lo que cada fondo tendrá su propia paleta de 256 colores.

Figura 11 – Archivos de fondo

PAGfx nos genera este código que tendremos que añadir a nuestra cabecera all_gfx.h: // Backgrounds:

extern const int simon_Info[3] __attribute__((aligned (4)));

extern const unsigned int simon_Map[768] __attribute__((aligned (4)));

extern const unsigned char simon_Tiles[13888] __attribute__((aligned

(4)));

// Palettes:

extern const unsigned short simon_Pal[256] __attribute__((aligned (4)));

2.3.5 – Texto de 16bit y Custom Font En PALib tenemos varias opciones para mostrar texto por la pantalla de la consola. En este proyecto utilizaremos texto de 16bit, que permite fácilmente mostrar un texto con un tamaño, un color y una posición en la pantalla específica. La ventaja de este texto respecto al texto simple, es que podemos definir un color y un tamaño, mientras que el otro tipo de texto no puede ser modificado. PA_Init16cBg(PANTALLA_INFERIOR, 2);

PA_16cText(0,30, 50, 230,250,"Texto en 16bit”,10, 2,1000);

PA_16cText(pantalla,x, y, x_max,y_max,texto,color, tamaño,limite_texto);

Los parámetros que utiliza la función PA_16cText son los siguientes:

- Pantalla: indicamos la pantalla en la que queremos mostrar el texto: 1 para la pantalla superior y 0 para la inferior.

- X: coordenada X donde comenzará el texto. - Y: coordenada Y donde comenzará el texto. - X_max: coordenada X límite del texto.

Page 16: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

15

- Y_max: coordenada Y límite del texto. - Texto: texto que queremos mostrar. - Color: indicamos el color que deseamos con un número entre 1 y 10. - Tamaño: indicamos el tamaño que deseamos para la fuente del texto con un número

entre 0 y 4. - Límite_texto: indica cuál será el número máximo de carácteres que se mostrarán del

texto

Custom font permite personalizar la fuente básica que nos ofrece PALib. Para ello importaremos los gráficos de la fuente custom a nuestro proyecto. Los gráficos de las fuentes se han de convertir a un formato compatible con Nintendo DS tal y como hacemos con los backgrounds. La fuente custom que se ha utilizado en el proyecto es la siguiente:

Figura 12 – Imagen de fuente

Si queremos crear nuestra propia fuente custom, es importante que editemos cada letra dentro de su correspondiente celda de 8x8 píxeles.

Figura 13 – Imagen de fuente con rejilla para edición

Una vez convertida la imagen, tendremos que indicar en el código que queremos la custom font asociada con el texto normal de PALib. //Inicializamos la fuente custom en la pantalla superior

//nuestra fuente custom se llama "font"

PA_InitCustomText(1,0,font);

2.3.6 – Sistema de ficheros FAT

En PALib disponemos de dos opciones a la hora de guardar información en la memoria: FAT y EFS. Con FAT podremos guardar ficheros en la flashcard, a los cuales podremos acceder posteriormente desde el ordenador. EFS incrusta datos en la rom del juego, por lo que no serán accesibles desde cualquier otro sitio. La FAT (File Allocation Table) es un sistema de ficheros, que fue desarrollado en 1977 por Bill Gates y Marc McDonald, para MS-DOS. Al ser un sistema de ficheros relativamente sencillo, se ha incorporado en diferentes sistemas, tales como sistemas operativos varios, tarjetas de memoria y dispositivos similares.

Page 17: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

16

En el caso de este proyecto, se ha escogido el sistema FAT para crear el fichero de partidas del juego. Para inicializar el sistema FAT, utilizaremos la función correspondiente de la librería: fatInitDefault();

La lectura y escritura en el sistema FAT de Nintendo DS se realiza con las funciones habituales del lenguaje C de lectura y escritura en ficheros. En la clase partida realizaremos una lectura del fichero binario de la siguiente manera: void partida::Init(){

FILE *f;

f = fopen("NDS/VirtualKachiku.sav", "rb");

if(f==NULL){

//El fichero no existe, crearemos uno nuevo con partidas

//vacías

f = fopen("NDS/VirtualKachiku.sav", "wb");

fwrite(&buffer, sizeof(save), MAX_PARTIDA, f);

fclose(f);

}

else{

//Existe un fichero de partidas guardadas

//Cargamos la información del fichero a nuestro búffer de

//partidas

fread(&buffer, sizeof(save), MAX_PARTIDA, f);

MostrarPartidas();

fclose(f);

}

}

Page 18: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

17

3 – DISEÑO

3.1 – Desarrollo de la partida Cuando carguemos la rom en nuestra consola nos aparecerá la siguiente pantalla, donde deberemos escojer el idioma en el que deseamos jugar:

Figura 14 – Pantalla de inicio

Una vez escojido el idioma, tendremos la opción de escojer una nueva partida o de cargar una partida anterior. Si escojemos la opción de continuar, nos aparecerá una lista con 3 slots para guardar partidas. Si no teníamos ninguna partida guardada, nos aparecerá el mensaje Ninguna partida guardada, pero si ya teníamos alguna partida, nos saldrá una breve información de ella, tal como el nombre del usuario y el nombre de la mascota.

Page 19: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

18

Figura 15 – Pantalla de nuevo juego/continuar Figura 16 – Pantalla de partidas guardadas

Si escojemos la opción Continuar y seleccionamos una de las partidas guardadas, el juego cargará los datos almacenados en el fichero binario en la clase partida. La función utilizada es muy sencilla: se trata de la función Load de la clase partida, a la que le pasaremos el número del slot (0 para el primero, 1 para el segundo y 2 para el tercero) y nos cargará la información del fichero binario en la clase partida. La función devuelve 1 si todo ha ocurrido correctamente, 0 en el caso contrario. int partida::Load(int i){

if(buffer[i].idpartida!=-1){

setIdPartida(buffer[i].idpartida);

setIdMascota(buffer[i].idmascota);

setEdad(buffer[i].edad);

setPeso(buffer[i].peso);

setHambre(buffer[i].hambre);

setFelicidad(buffer[i].felicidad);

setNombre(buffer[i].mascota);

setUser(buffer[i].nombre);

return 1;

}

else{

return 0;

}

}

Si escojemos la opción de nuevo juego, nos aparecerá un teclado para introducir nuestro nombre de usuario y el nombre de la mascota. El nombre de ambos ha de tener un mínimo de tres letras para que se considere correcto y se pueda continuar. Si se introduce uno de los dos nombres con menos de 3 letras, se le informa al usuario y se espera a que se introduzca un nombre de tres letras o más.

El teclado que aparece en la pantalla, es un teclado proporcionado por la librería de PALib.

Page 20: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

19

La decisión de utilizar este teclado de la librería y no uno propio es que el diseño del teclado de PALib es mucho más logrado. Al hacer un teclado propio, se han de programar todas las teclas y carácteres especiales, lo que complica su realización.

Figura 17– Nuevo jugador Figura 18 – Nombre de jugador mal introducido

Para utilizar el teclado de PALib simplemente tendremos que inicializarlo y posteriormente mostrarlo por pantalla, con la función PA_SetKeyboardColor(1,0). Además podremos modificar el esquema de colores del teclado: PA_InitKeyboard(1);

PA_KeyboardIn(23, 90);

PA_SetKeyboardColor(1, 0);

Una vez escojido el nombre de usuario y de la mascota, tendremos que elegir una de entre 4 mascotas diferentes. La que elijamos será la que deberemos alimentar y cuidar para que evolucione a una mascota buena.

Page 21: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

20

Figura 19 – Selección de mascota

Cuando seleccionamos una de las mascotas, o en el caso de que hayamos cargado una partida, nos aparecerá la pantalla de juego principal, donde estará nuestra mascota moviéndose por la habitación. El fondo del juego cambia según la hora del día.

Figura 20 – Pantalla de juego

Entre las 7 de la mañana y las 8 de la tarde se mostrará el fondo de día, y desde las 8 de la tarde hasta las 7 de la mañana siguiente se mostrará el fondo de noche. Para saber qué fondo debemos cargar según la hora, utilizaremos las herramientas que PALib nos ofrece para recojer información del Hardware de la Nintendo DS. La variable de PALib PA_RTC.Hour nos indica la hora del sistema:

Page 22: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

21

/*

Pantalla del juego

Habitación de la mascota

*/

void pantalla::FondoJuego(){

c.cls(PANTALLA_INFERIOR);

PA_Init16cBg(PANTALLA_SUPERIOR, 2);

c.cls(PANTALLA_SUPERIOR);

PA_EasyBgLoad(PANTALLA_SUPERIOR, 3, fondo3);

if(PA_RTC.Hour<20){

if(juego.getIdioma()==SPANISH){

PA_EasyBgLoad(PANTALLA_INFERIOR, 3, habitacion_dia);

}

else if(juego.getIdioma()==ENGLISH){

PA_EasyBgLoad(PANTALLA_INFERIOR, 3, habitaciondia_en);

}

else if(juego.getIdioma()==CATALAN){

PA_EasyBgLoad(PANTALLA_INFERIOR, 3, habitaciondia_ca);

}

}

else{

if(juego.getIdioma()==SPANISH){

PA_EasyBgLoad(PANTALLA_INFERIOR, 3, habitacion_noche);

}

else if(juego.getIdioma()==ENGLISH){

PA_EasyBgLoad(PANTALLA_INFERIOR, 3, habitacionnoche_en);

}

else if(juego.getIdioma()==CATALAN){

PA_EasyBgLoad(PANTALLA_INFERIOR, 3, habitacionnoche_ca);

}

}

Stylus.X=0;

Stylus.Y=0;

PA_SetTextCol(PANTALLA_SUPERIOR, 31, 31, 31);

PA_SetTextCol(PANTALLA_INFERIOR, 31, 31, 31);

PA_SetSpriteXY(PANTALLA_INFERIOR, PJ1BEBE, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, PJ2BEBE, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, PJ3BEBE, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, PJ4BEBE, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, PIZZA, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, HOTDOG, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, ENSALADA, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, HAMBURGUESA, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, SOPA, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, HELADO, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, PUDDING, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, SUSHI, -128, -128);

PA_SetSpriteXY(PANTALLA_INFERIOR, PASTEL, -128, -128);

PA_SetSpriteXY(0, juego.getIdMascota(), 30, 100);

}

En el lado izquierdo de la pantalla aparecen unos iconos que indican si la mascota tiene hambre, si quiere jugar o si no está muy sana. Al mostrar los iconos, además sonará un sonido para avisar al usuario de que la mascota necesita cuidados. Los iconos son los siguientes:

Page 23: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

22

Figura 21 – Iconos de estados

Cuando se muestra el corazón en la pantalla quiere decir que la mascota tiene poca salud y

que el usuario ha de jugar con ella para que mejore su salud. Si se muestra el dibujo de la cara se refiere a que la mascota no está del todo feliz y el usuario tendrá que jugar con ella para que su nivel de felicidad aumente. El pastelito nos indicará que la mascota tiene hambre y tendremos que alimentarla con alguno de los alimentos disponibles que tenemos. Dependiendo de la comida que suministremos a nuestra mascota, el nivel de sus estados variará. Cuando seleccionemos el alimento en cuestión, un texto nos indicará una breve descripción de la comida y los estados que modifica. En el caso siguiente se muestra la información del Helado:

Figura 22 – Pantalla de selección de comida

En el caso del Helado veremos que aumenta el estado de alimentación de nuestra mascota en 1 punto, le aumenta 3 puntos de felicidad, pero le quitará 2 puntos de salud, lo que querrá decir que no es tan bueno para su salud como si comiera la ensalada, pero a cambio le hará más feliz. Gracias a los diferentes estados que modifica cada alimento, conseguimos una manera más dinámica y divertida de jugar, ya que deberemos saber escojer qué alimentos suministrar a nuestra mascota para que crezca sana y feliz.

Page 24: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

23

3.2 – Evolución de la mascota

Durante el desarrollo del juego, se comprobará el estado de la mascota y el tiempo de juego transcurrido. Todas las funciones relacionadas con el control de la mascota se encuentran en el fichero control.cpp. En todos los videojuegos deberemos implementar una función, normalmente llamada Idle(), que se ejecuta en cada iteración del programa. En esta función llevamos a cabo todo el control de la evolución de la mascota y la modificación de sus estados. void control::Idle(){

if(fondo==JUEGO){

tiempo++;

juego.setEdad(juego.getEdad()+1);

}

/*

Cada 2 minutos actualizamos el estado de la mascota

disminuyendo los estados de hambre y felicidad.

*/

if(tiempo>=(MINUTO*2)){

tiempo=0;

if(juego.getHambre()>0)

juego.setHambre(juego.getHambre()-1);

if(juego.getFelicidad()>0)

juego.setFelicidad(juego.getFelicidad()-1);

}

/*

Han pasado 3 minutos. La mascota crecerá y evolucionará

con un aspecto u otro dependiendo de si estaba bien

cuidada o no.

*/

if(juego.getEdad()==MINUTO){

s.Play(ATENCION);

waitS(3);

PA_SetSpriteXY(0, EVOLUCION, PA_GetSpriteX(0,

juego.getIdMascota()), PA_GetSpriteY(0, juego.getIdMascota()));

//Empieza la animación de la evolución

s.Play(SONIDO_EVOLUCION);

PA_SetSpriteAnim(0, EVOLUCION, 5);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 4);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 3);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 2);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 1);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 0);

PA_SetSpriteXY(0, juego.getIdMascota(), -128, -128);

//Cambiamos el sprite de la mascota según su estado

if((juego.getFelicidad()*juego.getHambre())>=9){

PA_SetSpriteXY(0, juego.getIdMascota(), -128, -128);

Page 25: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

24

switch(juego.getIdMascota()){

case PJ1BEBE: juego.setIdMascota(PJ1BUENO); break;

case PJ2BEBE: juego.setIdMascota(PJ2BUENO); break;

case PJ3BEBE: juego.setIdMascota(PJ3BUENO); break;

case PJ4BEBE: juego.setIdMascota(PJ4BUENO); break;

}

}

else{

switch(juego.getIdMascota()){

case PJ1BEBE: juego.setIdMascota(PJ1MALO); break;

case PJ2BEBE: juego.setIdMascota(PJ2MALO); break;

case PJ3BEBE: juego.setIdMascota(PJ3MALO); break;

case PJ4BEBE: juego.setIdMascota(PJ4MALO); break;

}

}

PA_SetSpriteXY(0, juego.getIdMascota(), PA_GetSpriteX(0,

EVOLUCION), PA_GetSpriteY(0, EVOLUCION));

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 1);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 2);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 3);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 4);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 5);

PA_SetSpriteXY(0,EVOLUCION, -128, -128);

waitS(1);

}

}

A continuación se describe el código anterior, explicando qué hace exactamente cada parte de la función. Si estamos jugando con la mascota, es decir, si nos encontramos en la pantalla de juego, la mascota se irá haciendo mayor, por lo que su edad debe aumentar: if(fondo==JUEGO){

tiempo++;

juego.setEdad(juego.getEdad()+1);

}

Cada dos minutos modificaremos el hambre y la felicidad, disminuyéndolos en una unidad. De esta manera el juego será más interactivo y el usuario tendrá que estar pendiente del estado de su mascota: if(tiempo>=(MINUTO*2)){

tiempo=0;

if(juego.getHambre()>0)

juego.setHambre(juego.getHambre()-1);

if(juego.getFelicidad()>0)

juego.setFelicidad(juego.getFelicidad()-1);

}

Page 26: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

25

Cuando pasen tres minutos de tiempo jugado, la mascota evolucionará, y dependiendo de su estado, se convertirá en una mascota evolucionada u otra. Se han elegido tres minutos para poder hacer pruebas sin tener que esperar mucho tiempo a comprobar la evolución. Al evolucionar la mascota, aparece la animación de una especie de humo, con la que desaparecerá la mascota antigua, y aparecerá la nueva evolución: if(juego.getEdad()==MINUTO*3){

s.Play(ATENCION);

waitS(3);

PA_SetSpriteXY(0, EVOLUCION, PA_GetSpriteX(0,

juego.getIdMascota()), PA_GetSpriteY(0, juego.getIdMascota()));

//Empieza la animacion de la evolucion

s.Play(SONIDO_EVOLUCION);

PA_SetSpriteAnim(0, EVOLUCION, 5);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 4);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 3);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 2);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 1);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 0);

PA_SetSpriteXY(0, juego.getIdMascota(), -128, -128);

Una vez ejecutada la primera parte de la evolución, se comprueba qué mascota será la evolucionada que aparecerá al final de la animación del humo. La condición con la que sabremos si la mascota evolucionará bien o mal es muy sencilla: comprobaremos que su felicidad está como mínimo a la mitad de su valor posible, igual que el hambre que tenga, y que su peso no sea muy alto y esté en un valor medio. Los valores de felicidad, hambre y peso pueden variar de 0 a 10. //Cambiamos el sprite de la mascota según su estado

if((juego.getFelicidad()>4) && (juego.getHambre()>4) &&

(juego.getPeso()<5) ){

PA_SetSpriteXY(0, juego.getIdMascota(), -128, -128);

switch(juego.getIdMascota()){

case PJ1BEBE: juego.setIdMascota(PJ1BUENO); break;

case PJ2BEBE: juego.setIdMascota(PJ2BUENO); break;

case PJ3BEBE: juego.setIdMascota(PJ3BUENO); break;

case PJ4BEBE: juego.setIdMascota(PJ4BUENO); break;

}

}

else{

switch(juego.getIdMascota()){

case PJ1BEBE: juego.setIdMascota(PJ1MALO); break;

case PJ2BEBE: juego.setIdMascota(PJ2MALO); break;

case PJ3BEBE: juego.setIdMascota(PJ3MALO); break;

case PJ4BEBE: juego.setIdMascota(PJ4MALO); break;

}

}

Para acabar, una vez escojida la mascota evolucionada, se termina la animación de la evolución:

Page 27: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

26

PA_SetSpriteXY(0, juego.getIdMascota(), PA_GetSpriteX(0,

EVOLUCION), PA_GetSpriteY(0, EVOLUCION));

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 1);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 2);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 3);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 4);

wait(40);

PA_SetSpriteAnim(0, EVOLUCION, 5);

PA_SetSpriteXY(0,EVOLUCION, -128, -128);

waitS(1);

}

}

Una de las funciones principales para controlar los estados de la mascota y si se ha de modificar el fondo de pantalla según la hora de la consola, será la función Time de la clase control. En esta función actualizaremos el reloj en cada iteración (éste reloj se muestra en la pantalla del juego). Posteriormente comprobamos la hora actual para saber si hemos de cambiar el fondo de pantalla de día al fondo de noche y viceversa int control::Time(){

int hora=0;

PA_OutputText(0,26, 23, "%02d:%02d", PA_RTC.Hour, PA_RTC.Minutes);

//Comprobamos si hay algun cambio de hora, para saber si hemos

//de cambiar el fondo del juego

if((PA_RTC.Hour==20)&&(PA_RTC.Minutes==0)&&(PA_RTC.Seconds==0)){

hora=1;

}

if((PA_RTC.Hour==7)&&(PA_RTC.Minutes==0)&&(PA_RTC.Seconds==0)){

hora=1;

}

if(fondo==JUEGO){

//Comprobamos si la mascota tiene hambre, está triste o

//tiene poca salud. Si es así, mostramos el sprite

//correspondiente a su estado

if(juego.getHambre()<5){

PA_SetSpriteXY(PANTALLA_INFERIOR, HAMBRE, 3, 30);

}

if(juego.getFelicidad()<5){

PA_SetSpriteXY(PANTALLA_INFERIOR, FELICIDAD, 3, 65);

}

if(juego.getPeso()>10){

PA_SetSpriteXY(PANTALLA_INFERIOR, SALUD, 3, 90);

}

//Si necesita alguna atención y hace más de 2 minutos

//que sonó el último aviso, activamos el sonido

//de aviso

if( (juego.getHambre()<5) || (juego.getFelicidad()<5) ||

(juego.getPeso()>5) ){

sonidoatencion++;

if(sonidoatencion>=2*MINUTO){

sonidoatencion=0;

s.Play(ATENCION);

}

}

Page 28: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

27

}

return hora;

}

3.3 – Minijuego del Simón Para que nuestra mascota se ponga contenta, se ha de jugar con ella. Por ello se ha implementado un minijuego para interactuar con la mascota, el del Simón. El juego consistirá en apretar los botones de colores en el mismo orden que aparecen en la pantalla, durante una serie de turnos. Si el usuario acierta una cantidad específica de turnos, se considera que ha ganado la partida, por lo cual la mascota aumentará su nivel de felicidad en función de la cantidad de turnos que el usuario haya acertado.

Figura 23 – Pantalla de juego de Simón

El juego tendrá cuatro turnos, cada uno con un nivel de dificultad progresivo. Al empezar el turno, se verá la secuencia de botones a introducir. El número de botones que se iluminarán en cada turno es:

- Primer turno: 4 botones. - Segundo turno: 5 botones. - Tercer turno: 6 botones. - Cuarto turno: 8 botones.

En un futuro podría modificarse fácilmente el número de botones de cada turno, además del número de turnos, ya que la función básica que implementa el minijuego del Simón es muy sencilla y fácilmente modificable, tal y como podemos comprobar en el código siguiente: void simon::Start(){

Page 29: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

28

//Por cada turno crearemos unos números aleatorios que

//corresponderán a los botones de colores.

msg(1);

Turno(4);

msg(2);

Turno(5);

msg(3);

Turno(6);

msg(4);

Turno(8);

if(aciertos>2){

//Juego ganado

juego.setFelicidad(juego.getFelicidad()+2);

ganar(1);

}

if(aciertos==2){

//Juego ganado

juego.setFelicidad(juego.getFelicidad()+1);

ganar(1);

}

if(aciertos==4){

//Juego ganado

juego.setFelicidad(juego.getFelicidad()+4);

ganar(1);

}

if(aciertos<2){

//Juego perdido

juego.setFelicidad(juego.getFelicidad()-1);

ganar(0);

}

aciertos=0;

c.waitS(1);

s.PlayMusic();

}

En el futuro, si deseáramos modificar el número de botones de cada turno, sólo deberíamos modificar su parámetro, es decir, Turno(1) crea un turno con un único boton en su secuencia, Turno(30) crearía un turno con una secuencia de 30 botones. Cada botón de la secuencia se calcula de manera aleatoria. Con la función Turno, creamos un turno de la partida con tantos botones en la secuencia como indiquemos en el parámetro, y esperamos a que el usuario presione los botones. Esta función además se encarga de controlar cuántos botones acierta el usuario. El código de la función Turno es el siguiente: void simon::Turno(int pulsaciones){

int i=0;

int j=0;

PartidaAcabada=0;

//Generamos la secuencia de colores del juego

while(i<pulsaciones){

//Haremos un random para saber qué botón se iluminará

opciones[i]=PA_Rand()%4;

switch(opciones[i]){

case 0: boton_amarillo(); break;

Page 30: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

29

case 1: boton_rojo(); break;

case 2: boton_azul(); break;

case 3: boton_verde(); break;

}

i++;

}

i=0;

while((i<pulsaciones)&&(PartidaAcabada==0)){

while(!Stylus.Newpress) c.wait();

if(PA_SpriteTouched(BOTON_ROJO)){

s.Play(SONIDO_BOTON_ROJO);

PA_SetSpriteAnim(0, BOTON_ROJO, 2);

while(!Stylus.Released) c.wait();

PA_SetSpriteAnim(0, BOTON_ROJO, 0);

if( (opciones[i]+13)!=BOTON_ROJO) {

s.Play(INCORRECTO);

c.waitS(1);

PartidaAcabada=1;

}

i++;

}

if(PA_SpriteTouched(BOTON_AZUL)){

s.Play(SONIDO_BOTON_AZUL);

PA_SetSpriteAnim(0, BOTON_AZUL, 2);

while(!Stylus.Released) c.wait();

PA_SetSpriteAnim(0, BOTON_AZUL, 0);

if((opciones[i]+13)!=BOTON_AZUL){

s.Play(INCORRECTO);

c.waitS(1);

PartidaAcabada=1;

}

i++;

}

if(PA_SpriteTouched(BOTON_AMARILLO)){

s.Play(SONIDO_BOTON_AMARILLO);

PA_SetSpriteAnim(0, BOTON_AMARILLO, 2);

while(!Stylus.Released) c.wait();

PA_SetSpriteAnim(0, BOTON_AMARILLO, 0);

if((opciones[i]+13)!=BOTON_AMARILLO){

s.Play(INCORRECTO);

c.waitS(1);

PartidaAcabada=1;

}

i++;

}

if(PA_SpriteTouched(BOTON_VERDE)){

s.Play(SONIDO_BOTON_VERDE);

PA_SetSpriteAnim(0, BOTON_VERDE, 2);

while(!Stylus.Released) c.wait();

PA_SetSpriteAnim(0, BOTON_VERDE, 0);

if((opciones[i]+13)!=BOTON_VERDE){

s.Play(INCORRECTO);

c.waitS(1);

PartidaAcabada=1;

}

i++;

}

Page 31: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

30

}

//Si ha acertado la secuencia de botones sumamos un punto

if(i>=pulsaciones) aciertos++;

}

Al acabar todos los turnos evaluaremos el número de aciertos o fallos que haya hecho el usuario. Cuantos más aciertos hagamos, más feliz será nuestra mascota, como podemos observar en las siguientes condiciones. Si el jugador acierta un mínimo de tres turnos, la felicidad de la mascota aumentará en dos unidades: if(aciertos>2){

//Juego ganado

juego.setFelicidad(juego.getFelicidad()+2);

ganar(1);

}

Si el usuario sólo acierta la mitad de los turnos, su mascota sólo obtendría una unidad de felicidad, como se puede observar en el codigo.

if(aciertos==2){

//Juego ganado

juego.setFelicidad(juego.getFelicidad()+1);

ganar(1);

}

La mayor cantidad de felicidad, cuatro unidades, la recibirá cuando el usuario haga una partida perfecta. Esto quiere decir que no cometa ningun fallo en los cuatro turnos en los que se desarrolla el juego. if(aciertos==4){

//Juego ganado

juego.setFelicidad(juego.getFelicidad()+4);

ganar(1);

}

Si el usuario sólo acertase un turno, se considerará el juego como perdido y su mascota disminuirá su felicidad en una unidad, como se observa en el código. En consecuencia, el usuario debería volver a jugar con ella para aumentar su felicidad. if(aciertos<2){

//Juego perdido

juego.setFelicidad(juego.getFelicidad()-1);

ganar(0);

}

Page 32: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

31

4 – DESARROLLO

4.1– Estructura de ficheros El lenguaje en el que se ha desarrollado el juego es C++, ya que obtendremos las ventajas de trabajar con un lenguaje orientado a objetos. C++ es un lenguaje de programación orientado a objetos fruto de la evolución del lenguaje C. Fue creado en 1980 por Bjarne Stroustrup con la intención de obtener un lenguaje que permitiera a los usuarios manipular objetos, cosa que con el lenguaje C no se podía entonces y así mejorar sustancialmente ese lenguaje. Al principio su autor llamo a su obra “C con clases” pero fue en 1983 cuando este lenguaje fue utilizado por primera vez en un laboratorio científico donde empezaron a llamarlo como se le conoce hoy en dia, C++, siendo este “++” un significado de incremento de C, refiriéndose a que este lenguaje es una extensión del C. La estructura de ficheros utilizada es la que aparece en la imagen:

Figura 24 – Estructura de ficheros

Dispondremos de diferentes carpetas y ficheros, las cuales se describen a continuación: · build: contiene ficheros que genera el compilador. · data: en esta carpeta se guardan los sonidos del juego, el logo de la rom, y archivos de recurso que posteriormente serán utilizados en el juego. · source: la carpeta contiene todos los ficheros de código fuente, cabeceras, ficheros binarios de sprites y backgrounds (fondos).

Page 33: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

32

4.1.1 – Fichero main.cpp El fichero main indica qué funciones serán las primeras en ejecutarse y su orden. Como en todos los juegos, necesitaremos un bucle infinito, donde en cada iteración comprobaremos el estado de la mascota. int main(){

InitGame();

p.SeleccionarBackground(IDIOMAS);

while (1){

b.BotonPresionado();

switch(fondo){

case JUEGO: m.MoverMascota(juego.getIdMascota());

if(c.Time()==1)

p.SeleccionarBackground(JUEGO);

break;

case NUEVO_JUGADOR: b.Teclado();

break;

case MINIJUEGO: minijuego.Start();

b.Minijuego();

break;

}

c.Idle();

PA_WaitForVBL();

}

return 0;

}

Las variables p, b, m y c hacen referencia a las clases que utilizamos y están definidas en el fichero main.h de la siguiente manera: //Declaramos los objetos de clase

pantalla p;

sonido s;

botones b;

movimiento m;

partida juego;

control c;

simon minijuego;

lang idioma;

La primera función que se ejecuta es InitGame() que se encargará de llamar a todas las funciones de inicialización del sistema de librerías de PALib y nuestras propias funciones de inicialización. void InitGame(){

//Inicializa la libreria PALib

PA_Init();

//Inicializa el sistema de PALib para su sincronismo

//en cada iteración

Page 34: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

33

PA_InitVBL();

//Inicializa el sistema de ficheros FAT

fatInitDefault();

//Inicia el sistema random

PA_InitRand();

//Inicializa las partidas del juego

juego.Init();

//Inicializa el texto con la fuente elegida

PA_InitCustomText(1,0,font);

PA_InitCustomText(0,0,font);

//Inicializa el texto de 16bit

PA_Init16cBg(PANTALLA_INFERIOR, 2);

nomuser = (char*) malloc(sizeof(char)*50);

nommascota = (char*) malloc(sizeof(char)*50);

//Cargamos los sprites del juego

p.Init();

}

Page 35: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

34

4.1.2 – Clase partida En esta clase guardaremos la información de la partida actual, los estados de la mascota, su nombre y el del usuario. Según se avance en el juego, los datos del estado de la mascota se actualizarán en esta clase. class partida{

save buffer[MAX_PARTIDA];

int idpartida;

int idmascota;

int edad;

int peso;

int hambre;

int felicidad;

char* nombre;

char* user;

int idiomaJuego;

public:

partida();

void setIdPartida(int);

void setIdMascota(int);

void setEdad(int edad);

void setPeso(int peso);

void setHambre(int hambre);

void setFelicidad(int felicidad);

void setNombre(char* nombre);

void setUser(char* user);

void setIdioma(int);

int getIdPartida() const;

int getIdMascota() const;

int getEdad() const;

int getPeso() const;

int getHambre() const;

int getFelicidad() const;

char* getNombre() const;

char* getUser() const;

int getIdioma() const;

void Init();

void MostrarPartidas();

int Load(int);

void Save(int);

void Alimentar(int);

~partida();

protected:

void IniBuffer();

};

Cuando empieza el juego, la función Init() de la clase partida es llamada en el fichero main.cpp. Ésta función se encarga de cargar datos de partidas anteriores a la memoria. Comprueba si ya existe un fichero del juego con datos guardados; si este existe, leerá el fichero y cargará los datos a memoria, mostrándolos posteriormente por pantalla con la función MostrarPartidas(). Si no hay ningún fichero con partidas anteriores guardadas, entonces procederá a crear un nuevo fichero en el que posteriormente serán guardados los datos de nuestra partida.

Page 36: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

35

void partida::Init(){

FILE *f;

f = fopen("NDS/VirtualKachiku.sav", "rb");

if(f==NULL){

//El fichero no existe, crearemos uno nuevo con partidas vacias

f = fopen("NDS/VirtualKachiku.sav", "wb");

fwrite(&buffer, sizeof(save), MAX_PARTIDA, f);

fclose(f);

}

else{

//Existe un fichero de partidas guardadas

//Cargamos la información del fichero a nuestro buffer de partidas

fread(&buffer, sizeof(save), MAX_PARTIDA, f);

MostrarPartidas();

fclose(f);

}

}

Page 37: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

36

4.1.3 – Clase botones Ésta será la clase encargada de gestionar el funcionamiento de la interacción del usuario con el juego. class botones{

public:

botones();

void BotonPresionado();

void Alimentar();

void Minijuego();

void Teclado();

~botones();

private:

void Idiomas();

void BotonesJuego();

void BotonesInicio();

void BotonesSeleccion();

void CargarPartida();

void Estado();

void FuncionComida(int);

};

En el fichero main.cpp utilizamos la función BotonPresionado() dentro del bucle infinito para comprobar en cada iteración si se aprieta alguno de los botones de la consola. Según la pantalla en la que nos encontremos (en inicio, en selección de idioma, en cargar partida, etc.) en la función BotonPresionado llamaremos a una función u otra de la clase Botones, para controlar las acciones que se deban llevar a cabo. void botones::BotonPresionado(){

if(Stylus.Newpress){

switch(fondo){

case JUEGO: BotonesJuego(); break;

case INICIO: BotonesInicio(); break;

case SELECCION: BotonesSeleccion(); break;

case ESTADO: Estado(); break;

case CARGAR_PARTIDA: CargarPartida(); break;

case MINIJUEGO: Minijuego(); break;

case IDIOMAS: Idiomas(); break;

case COCINA: Alimentar(); break;

}

}

}

Page 38: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

37

4.1.4 – Clase pantalla Es la clase encargada de gestionar los cambios de las imágenes de fondo de las 2 pantallas de la consola. class pantalla{

public:

pantalla();

void SeleccionarBackground(int fondo);

void Init();

~pantalla();

private:

void FondoInicio();

void FondoSeleccion();

void FondoJuego();

void Estado();

void NuevoJugador();

void CargarPartida();

void Idiomas();

void FondoCocina();

void FondoMinijuego();

void CargarMascota(int id_mascota, void* sprite, int x, int y);

void CargarEvolucion(int id_evolucion, void* sprite, int x, int y);

void CargarComida(int id_comida, void* sprite, int x, int y);

void CargarCuadroTexto(int id_cuadro, void* sprite, int x, int y);

void CargarBoton(int id_boton, void* sprite, int x, int y);

void CargarFondo(int);

};

En la función InitGame() del fichero main.cpp llamamos a la función Init() de la clase pantalla, que se encargará de cargar los sprites a memoria para poderlos utilizar más adelante: void pantalla::Init(){

CargarMascota(PJ1BEBE, (void*)m1bebe_Sprite, -128, -128);

CargarMascota(PJ1BUENO, (void*)m1bueno_Sprite, -128, -128);

CargarMascota(PJ1MALO, (void*)m1malo_Sprite, -128, -128);

CargarMascota(PJ2BEBE, (void*)m2bebe_Sprite, -128, -128);

CargarMascota(PJ2BUENO, (void*)m2bueno_Sprite, -128, -128);

CargarMascota(PJ2MALO, (void*)m2malo_Sprite, -128, -128);

CargarMascota(PJ3BEBE, (void*)m3bebe_Sprite, -128, -128);

CargarMascota(PJ3BUENO, (void*)m3bueno_Sprite, -128, -128);

CargarMascota(PJ3MALO, (void*)m3malo_Sprite, -128, -128);

CargarMascota(PJ4BEBE, (void*)m4bebe_Sprite, -128, -128);

CargarMascota(PJ4BUENO, (void*)m4bueno_Sprite, -128, -128);

CargarMascota(PJ4MALO, (void*)m4malo_Sprite, -128, -128);

CargarBoton(BOTON_AMARILLO,(void*)boton_amarillo_Sprite,-128,-128);

CargarBoton(BOTON_ROJO, (void*)boton_rojo_Sprite, -128, -128);

CargarBoton(BOTON_AZUL, (void*)boton_azul_Sprite, -128, -128);

CargarBoton(BOTON_VERDE,(void*)boton_verde_Sprite, -128, -128);

CargarBoton(SALUD, (void*)salud_Sprite, -128, -128);

CargarBoton(HAMBRE, (void*)hambre_Sprite, -128, -128);

CargarBoton(FELICIDAD,(void*)felicidad_Sprite, -128, -128);

CargarEvolucion(EVOLUCION, (void*) evolucion_Sprite, -128, -128);

Page 39: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

38

CargarComida(PIZZA, (void*) pizza_Sprite, -128, -128);

CargarComida(HAMBURGUESA, (void*) hamburguesa_Sprite, -128, -128);

CargarComida(HOTDOG, (void*) hotdog_Sprite, -128, -128);

CargarComida(ENSALADA, (void*) ensalada_Sprite, -128, -128);

CargarComida(SOPA, (void*) sopa_Sprite, -128, -128);

CargarComida(HELADO, (void*) helado_Sprite, -128, -128);

CargarComida(PUDDING, (void*) pudding_Sprite, -128, -128);

CargarComida(SUSHI, (void*) sushi_Sprite, -128, -128);

CargarComida(PASTEL, (void*) pastel_Sprite, -128, -128);

}

Page 40: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

39

4.1.5 – Clase de idiomas En esta clase gestionaremos los textos de los diferentes idiomas que tiene el juego: Inglés, Castellano y Catalán. class lang{

public:

lang();

void InstruccionesSimon(int,char*);

void Ronda(int,int);

void NoPartida(int,int);

void NomUserShort(int);

void NomMascotaShort(int);

void NomUser(int);

void NomMascota(int);

void Comida(int, int);

void Estado(int,char*,int,int,int);

~lang();

};

En esta clase tendremos funciones como la siguiente, con la que podríamos modificar el texto en cada uno de los idiomas: void lang::NomUserShort(int idioma){

PA_Init16cBg(PANTALLA_INFERIOR, 2);

switch(idioma){

case SPANISH:

PA_16cText(0,45, 30, 230,250,"El nombre de usuario es muy

corto. Debe tener al menos 3 letras.",10, 2,1000);

break;

case ENGLISH:

PA_16cText(0,45, 30, 230,250,"User name is too short. It

should have 3 letters or more.",10, 2,1000);

break;

case CATALAN:

PA_16cText(0,45, 30, 230,250,"El nom d'usuari és massa curt.

Ha de tenir 3 lletres o més.",10, 2,1000);

break;

}

}

Page 41: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

40

5 – EVALUACIÓN A lo largo del desarrollo del proyecto ha surgido algún que otro problema. El primer problema que surgió fue la falta de memoria para las paletas de los sprites, ya que en un primer diseño se creaba una paleta por cada sprite y PALib sólo ofrece 16 paletas diferentes por pantalla. La solución fue fácil: compartir paletas entre diferentes sprites con ayuda del programa PAGfx. De esta manera, tendremos una sola paleta donde almacenar hasta 256 colores, que serán los que se utilizarán en los sprites asociados a esa paleta. Se han hecho varios test del juego para asegurarnos de que todo funcionase correctamente, como crear varias partidas para comprobar que no se podían crear más de tres (que es el número máximo de partidas que se puede guardar). También se verifica que el jugador no pueda introducir su nombre de usuario o el de su mascota vacío, ha de contener como mínimo tres letras. 5.1 – Posibles ampliaciones Ha habido alguna decisión de diseño que no se ha podido llevar a cabo debido, a la falta de tiempo, como mostrar a la mascota durmiendo a ciertas horas. Para implementar a la mascota durmiendo, se debería de haber creado un sprite más por cada mascota. Contamos con 12 mascotas diferentes: cuatro mascotas infantiles, cuatro evolucionadas en adultos buenos y cuatro evolucionadas en adultos malos. En un futuro podrían añadirse algunas mejoras, que para este proyecto no se han podido incluír, como por ejemplo: interacción del usuario con la mascota a través del micrófono, o conexión de dos juegos en diferentes consolas a través de Wi-Fi para comunicar ambas mascotas.

Page 42: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

41

6 – CONCLUSIONES La programación en dispositivos de memoria limitada, como es la Nintendo DS y otras consolas portátiles, ha de ser más óptima que si estubiéramos programando para un ordenador, donde disponemos de memoria prácticamente ilimitada. Si en Nintendo DS queremos cargar muchas imágenes o sonidos, deberemos hacer uso de librerías adicionales como EFS, en la que se pueden añadir recursos para utilizarlos posteriormente. Es importante también, saber que no se ha de utilizar MP3 para reproducir música durante un juego, ya que consume mucha memoria y podría ralentizar el juego en si. Es importante optimizar el uso de variables y objetos de clase. Por ejemplo, no sería muy óptimo crear muchas instancias de una misma clase. Lo mejor es tener el mínimo de objetos posibles. En este proyecto se ha tenido en cuenta la optimización de la memoria y se ha procurado crear una sola instancia de cada clase. Una vez finalizado el proyecto, creo que se ha logrado el objetivo de éste, que era crear un videojuego para Nintendo DS, jugable y divertido. Se ha intentado conseguir que su apariencia fuera lo más parecida a un juego comercial.

Page 43: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

42

7 – RECURSOS UTILIZADOS - Página web oficial de documentación de PALib http://palib.info/wiki/doku.php - Página web oficial de DevKitPro http://www.devkitpro.org/ - Página web oficial del emulador NDesMuMe http://www.desmume.com/ - Página web oficial del conversor de sonidos Switch http://www.nch.com.au/switch/ - Página web: foro dedicado al desarrollo de scene en Nintendo DS http://www.elotrolado.net/foro_nds-scene_130 - Página web dedicada al desarrollo de scene en Nintendo DS http://nds.scenebeta.com/ - Página web oficial de Visual C++ Express Edition http://www.microsoft.com/spanish/msdn/vstudio/express/VC/default.mspx - Página web oficial de Flash http://www.adobe.com/es/products/flash/ - Página web oficial de Photoshop CS5 http://www.adobe.com/es/products/photoshop/photoshop/

Page 44: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

43

- Página web oficial de la librería Libnds http://www.libnds.devkitpro.org/ - Ejemplos de PALib incluídos con la librería - Página web de referencia de C++ http://www.cplusplus.com/ - Página web oficial de Audacity http://audacity.es/ - API de PALib http://www.palib.info/Doc/PAlibDoc%20Eng/modules.html - Página web oficial de descarga de .NET Framework http://www.microsoft.com/downloads/details.aspx?displaylang=es&familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5

Page 45: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

44

8 – ANEXOS Imágenes utilizadas: Mascotas:

Botones:

Comida:

Page 46: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

45

Fondos de pantalla:

Page 47: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

46

Page 48: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

47

Page 49: Programar Nds

Noemí Ferrer Ortiz ____..............................................PFC: Videojuego para Nintendo DS

48

Evolución de la mascota: