Pro Yec to Final

11

Click here to load reader

Transcript of Pro Yec to Final

Page 1: Pro Yec to Final

Licenciatura en Arte Digital

Fundamentos de Programación

Otoño 2013

Proyecto Final

PAC-MAN

FECHA DE ENTREGA:

Miércoles 8 de enero de 2014

Page 2: Pro Yec to Final

Fundamentos de Programación Proyecto Final

2

Objetivo:

Desarrollar un programa en C++ que simule el funcionamiento del juego Pacman (Namco,

1980), con las siguientes restricciones:

El programa será una aplicación de consola Win-32, el mapa y los personajes serán

representados con caracteres de texto.

Los fantasmas no perseguirán a pacman ni escaparán de él, se moverán

aleatoriamente por el terreno.

El jugador pierde si es tocado por un fantasma, excepto si ha recogido una cápsula

de poder, en cuyo caso el jugador puede comer fantasmas por un tiempo

determinado.

El jugador gana si se come todos los puntos del tablero.

Requisitos:

Para desarrollar el programa se necesita los siguiente:

El archivo de encabezado “consola.h” utilizado en clase.

Dominio de todos los temas vistos en el curso.

Criterios de Evaluación:

El proyecto vale el 30% de la calificación final. Se utilizarán los siguientes criterios:

Porcentaje Descripción

5% Asistencia a la cita programada para evaluar el proyecto

10% Funcionamiento del programa.

15% Evaluación personal (Examen oral y práctica de programación)

El equipo contará con 30 minutos para presentar el proyecto. Durante los primeros 5

minutos deberá instalar y preparar su programa. Tendrá 5 minutos para ejecutar y

demostrar el funcionamiento. Luego, cada integrante del equipo será evaluado

personalmente con una sesión de preguntas de 5 minutos.

Page 3: Pro Yec to Final

Fundamentos de Programación Proyecto Final

3

Instrucciones

El flujo del programa debe ser el siguiente:

Page 4: Pro Yec to Final

Fundamentos de Programación Proyecto Final

4

Declaración de Variables

Tanto Pacman como los fantasmas serán definidos con un nuevo tipo de variable llamado

Figura.

Este tipo de datos se definirá como una estructura que contendrá los siguientes datos:

Su posición en el terreno (x, y).

El carácter que será usado para dibujar la figura (WCHAR).

La velocidad a la que se mueve la figura (float).

El número de posiciones en el terreno que se calcula debería moverse (float).

La dirección en la que se mueve (ARRIBA, ABAJO, IZQUIERDA o DERECHA).

En main se deben declarar las siguientes variables:

Figura pacman;

Figura fantasmas[NUM_FANTASMAS];

bool encuentraPildora = false;

float tiempoTranscurrido = 0;

Donde NUM_FANTASMAS es una constante entera global que define cuántos fantasmas

estarán presentes en el terreno.

Deberá definir globalmente una matriz de enteros,

int mapa[FILAS][COLUMNAS];

Donde FILAS y COLUMNAS son constantes enteras globales y definen el ancho y alto del

terreno.

Inicialización

Pacman debe inicializarse al ser declarado utilizando una lista de inicialización que

contenga:

Su posición (x, y).

El carácter que lo representa en la pantalla (defina una constante global para

cambiar este carácter de ser necesario).

Su velocidad (también definida como una constante global).

El número de posiciones en cero.

Page 5: Pro Yec to Final

Fundamentos de Programación Proyecto Final

5

Su dirección de movimiento (la dirección debe ser un valor de una enumeración

definida globalmente que contenga los valores ARRIBA, ABAJO, IZQUIERDA y

DERECHA).

Para los fantasmas escriba una función para crearlos. El prototipo debe ser:

Figura CreaFantasma();

La función debe declarar una variable de tipo Figura y establecer su posición (x, y) en el

punto de creación de los fantasmas (definido por constantes globales), su velocidad como

un valor aleatorio entre un valor mínimo y máximo (definidos como constantes globales) y

el número de posiciones para moverse en cero.

En main deberá crear cada uno de los fantasmas utilizando esta función y guardando cada

nuevo fantasma en el arreglo fantasmas.

La matriz de enteros llamada mapa debe inicializarse leyendo los datos de un archivo

externo. Este archivo debe contener el mismo número de líneas que el número de filas de

la matriz y el mismo número de valores por línea que el número de columnas. Por

ejemplo, si la matriz es de 4 X 5 (4 filas, 5 columnas), el archivo contendrá lo siguiente:

1 1 1 1 1

1 0 2 0 1

1 0 0 0 1

1 1 1 1 1

Donde cada número representa:

0 – punto

1 - pared

2 - píldora

Defina una función que lea este archivo y guarde los valores en la matriz mapa. Su

prototipo debe ser:

void LeeArchivo();

Recuerde que la matriz mapa debe ser declarada globalmente, al igual que las constantes

que definen el número de filas y columnas de la matriz.

Page 6: Pro Yec to Final

Fundamentos de Programación Proyecto Final

6

Defina también una constante de tipo string que defina el nombre del archivo que será

leído. Por ejemplo,

const string NOMBRE_ARCHIVO = “mapa.txt”;

La función debe:

Abrir el archivo NOMBRE_ARCHIVO y verificar que se pudo abrir. Si el archivo no se

puede leer el programa debe terminar inmediatamente.

Leer del archivo todos los valores y guardarlos en la matriz.

Cada vez que se lea un valor, imprimir en pantalla el carácter correspondiente

utilizando la función printConsole. Por ejemplo, si la variable i recorre las filas de la

matriz y la variable j recorre las columnas se haría lo siguiente:

if (mapa[i][j] == 1)

printConsole(PARED, j, i);

Donde PARED es una constante de tipo WCHAR que define el carácter que se

utiliza para imprimir las paredes. Debe definir también los caracteres para la

píldora y los puntos.

Colisiones

Escriba una función con este prototipo:

bool Come(Figura pacman, Figura fantasmas[], bool& encuentraPildora,

float& tiempoTranscurrido);

La función regresa true si el jugador puede seguir jugando o false si ya perdió (se lo comió

un fantasma).

La función debe hacer lo siguiente:

Revisar si en la posición donde se encuentra pacman hay un punto en la matriz

mapa (si hay un 0), en ese caso, pacman se come el punto (se coloca un -1 en la

matriz). Una vez que se lo coma, se debe buscar en la matriz si no hay más puntos,

si no los hay, quiere decir que el jugador gana, en este caso se debe imprimir el

mensaje de que ganó el jugador y regresar false para impedir que siga jugando.

Page 7: Pro Yec to Final

Fundamentos de Programación Proyecto Final

7

Revisar si en la posición donde se encuentra pacman hay una píldora en la matriz

mapa (si hay un 2), en ese caso, pacman se come la píldora (se coloca un -1 en la

matriz) y la variable encuentraPildora se establece en true y la variable

tiempoTranscurrido en cero.

Revisar si la posición de alguno de los fantasmas coincide con la posición de

pacman, si es así, revisar si el efecto de la píldora está activo (recuerde que cuando

pacman se come la píldora, se puede comer a los fantasmas por un tiempo

determinado), si está activo, se debe destruir el fantasma, llamando a la función

CreaFantasma() para asignarle de nuevo la posición de inicio a ese fantasma. En

caso de que no esté activo y pacman choque con un fantasma, se debe notificar al

jugador que perdió y se debe regresar false para impedir que siga jugando.

Al final de la función regrese true.

Entrada del usuario

El jugador puede cambiar la dirección de pacman utilizando las flechas del teclado. Para

saber si un jugador presionó una flecha utilice la función arrowPressed(), de esta forma,

int tecla = arrowPressed(false);

La variable tecla tendrá uno de los siguientes valores: VK_UP, VK_DOWN, VK_LEFT,

VK_RIGHT o -1 si no se presionó ninguna flecha.

Dependiendo de la tecla presionada se debe revisar si pacman puede cambiar de

dirección, es decir, si no hay una pared en esa dirección, si no hay pared entonces se

cambia la dirección, en caso contrario no se hace nada.

Actualiza Pacman

En cada iteración del ciclo infinito se debe mover y dibujar a pacman.

Escriba una función con el siguiente prototipo,

void Mueve(Figura& figura);

Esta función debe:

Page 8: Pro Yec to Final

Fundamentos de Programación Proyecto Final

8

Calcular el movimiento real de la figura, recuerde que estamos en un espacio

discreto pero el movimiento se calcula en un espacio continuo. El cálculo se hace

de la siguiente manera,

// se calcula el cambio de posición en el espacio contínuo

// que sucedió en el último frame, MILISEGUNDOS es una constante global

// que define la tasa de refresco del juego, MILISEGUNDOS = 33

// recuerde que velocidad = distancia / tiempo, luego,

// distancia = velocidad * tiempo

figura.numeroPosiciones += figura.velocidad * (MILISEGUNDOS / 1000.0);

// se calcula el cambio de posición en el espacio discreto de la pantalla

int movimiento = floor(figura.numeroPosiciones);

// si no hay movimiento perceptible en la pantalla se abandona la función

if (movimiento <= 0)

return;

else // si sí lo hay, entonces se continúa y se resta ese cambio a la variable global

figura.numeroPosiciones -= movimiento;

// se calcula la siguiente posición

int x = figura.x;

int y = figura.y;

// dependiendo de la dirección en la que se mueve

switch (figura.direccion)

{

case ARRIBA: y -= movimiento; break;

case ABAJO: y += movimiento; break;

case IZQUIERDA: x -= movimiento; break;

case DERECHA: x += movimiento; break;

}

Se debe verificar si en la siguiente posición no hay una pared, esto se puede hacer

preguntando si en la matriz mapa en la siguiente posición hay un 1, en ese caso se

abandona la función y la figura no se mueve.

Page 9: Pro Yec to Final

Fundamentos de Programación Proyecto Final

9

Si el movimiento es válido, antes de cambiar la posición se debe borrar la figura

que se dibujó en la posición actual utilizando la función Borra(figura); (ver más

adelante).

Después de borrar la figura, se le asigna la nueva posición a la figura.

La función Borra tiene el siguiente prototipo,

void Borra(Figura figura);

Esta función debe utilizar la función printConsole para dibujar un carácter en la posición

de la figura. Normalmente, se dibujaría un espacio en blanco para borrar la figura, por

ejemplo,

printConsole(‘ ‘, figura.x, figura.y);

Pero esto provocaría que los fantasmas también se coman los puntos y las píldoras al

pasar encima de ellos, cuando solo pacman se los puede comer. Para solucionar esto, se

debe preguntar qué hay en la matriz mapa en esa posición,

Si hay un 0 (punto), se debe imprimir un punto.

Si hay un 2 (píldora), se debe imprimir una píldora.

Si hay un -1 (nada), se debe imprimir un espacio en blanco.

Recuerde que cuando pacman pasa encima de un punto o una píldora se los come

(asignando un -1 a la matriz en esa posición), por lo que solo pacman puede borrar los

puntos y las píldoras.

Dentro del ciclo infinito de main, después de llamar a la función Mueve(pacman); se debe

dibujar a pacman, utilizando la función Dibuja(pacman); que tiene el siguiente prototipo,

void Dibuja(Figura figura);

Esta función simplemente dibuja el carácter de la figura en su posición. Por ejemplo,

printConsole(figura.caracter, figura.x, figura.y);

Actualiza Fantasmas

Dentro del ciclo infinito se debe mover y dibujar a cada uno de los fantasmas del arreglo.

Page 10: Pro Yec to Final

Fundamentos de Programación Proyecto Final

10

Defina una función con el siguiente prototipo,

void Decide(Figura& figura);

Esta función se encarga de definir el movimiento de los fantasmas y debe hacer lo

siguiente:

A partir de su posición actual, el fantasma debe revisar cuántos caminos puede

tomar (ARRIBA, ABAJO, IZQUIERDA o DERECHA), sin tomar en cuenta el camino de

donde viene. Por ejemplo, si su dirección actual es ARRIBA, el camino de donde

viene está ABAJO.

Si no hay caminos, el fantasma debe regresar por donde viene, es decir su

dirección se debe invertir (ARRIBA ABAJO, IZQUIERDA DERECHA).

Si se encontraron caminos, se debe seleccionar uno de ellos de manera aleatoria

(recuerde que no se está tomando en cuenta el camino por donde viene, por lo

que el fantasma solo regresará por donde viene si no tiene otra opción).

Seleccionar un camino significa cambiar la dirección del fantasma hacia ese

camino.

En main se debe hacer un ciclo para actualizar cada uno de los fantasmas,

for (int i = 0; i < NUM_FANTASMAS; i++)

{

Decide(fantasmas[i]);

Mueve(fantasmas[i]);

Dibuja(fantasmas[i]);

}

Actualiza juego

Además de actualizar a pacman y los fantasmas, se debe procesar el tiempo que dura el

efecto de la píldora, para hacerlo, defina la siguiente función,

void EfectoPildora(bool& encuentraPildora, float& tiempoTranscurrido);

La cual se llamará solo si encuentraPildora es igual a true.

Page 11: Pro Yec to Final

Fundamentos de Programación Proyecto Final

11

Dentro de la función, sume al tiempoTranscurrido el tiempo que ha pasado desde el

último ciclo, esto es,

tiempoTranscurrido += MILISEGUNDOS / 1000.0;

Donde MILISEGUNDOS = 33, definida como constante global.

Defina otra constante global float llamada TIEMPO_PILDORA, que dirá cuántos segundos

dura el efecto de la píldora.

Dentro de la función EfectoPildora(), después de sumar el tiempo transcurrido pregunte si

tiempoTranscurrido >= TIEMPO_PILDORA, de ser así, el efecto de la píldora ha expirado y

la variable encuentraPildora se debe establecer en false y tiempoTranscurrido en cero.

Duerme

La última instrucción del ciclo infinito debe ser Sleep(MILISEGUNDOS); esto simula una

tasa de refresco de 30 cuadros por segundo (frames per second).