Tcnica Del Estado De Veracruz #165 Lic. Jesus Reyes Heroles Modulo: Povi-02 P.S.P Miguel ngel Ramos Grande Alumnos Brenda Cruz Mata Jorge Alberto Hernndez Rojas Francisco Javier flores Romn Practica 11
Practica 8: Aplicacin de matemticas para Juego: TiroAlPlato. usando lenguaje de programacin Propsito de prctica: Elabora una aplicacin de videojuego de TiroAlplato usando lenguaje de programacin para la aplicacin de conceptos de geometra plana. Materiales, Herramientas, Instrumental, Maquinaria y Equipo Desempeos Equipo de cmputo Core Duo o superior. Dispositivo de almacenamiento (USB). Windows Compilador de lenguaje seleccionado. (C, C++ o Java). Un poco de matemticas para juegos. Sexto Juego: TiroAlPlato. Siempre que queramos imitar fenmenos fsicos, necesitaremos tener unos ciertos conocimientos de matemticas, saber qu frmulas nos permitirn representar esos fenmenos de una forma creble. De momento veremos unas primeras operaciones bsicas (distancias, crculos, parbolas y su utilizacin); otras operaciones algo ms avanzadas las dejamos para ms adelante (por ejemplo, la forma de representar figuras 3D y de rotarlas). Distancias . La ecuacin que nos da la distancia entre dos puntos procede directamente del teorema de Pitgoras, aquello de "el cuadrado de la hipotenusa es igual a la suma de los cuadrados de los catetos". Si unimos dos puntos con una lnea recta, podramos formar un tringulo rectngulo: su hipotenusa sera la recta que une los dos puntos, el tamao de un cateto sera la diferencia entre las coordenadas horizontales (x) de los puntos, y el tamao del otro cateto sera la diferencia entre las coordenadas verticales (y), as:
Por tanto, la forma de hallar la distancia entre dos puntos sera d = raz ( (x2 - x1)2 + (y2 - y1)2 ) As, en nuestro ltimo juego (puntera) podramos haber usado un blanco que fuera redondo, en vez de rectangular. Comprobaramos si se ha acertado simplemente viendo si la distancia desde el centro del crculo hasta el punto en el que se ha pulsado el ratn es menor (o igual) que el radio del crculo. Crculo . La ecuacin que nos da las coordenadas de los puntos de una circunferencia a partir del radio de la circunferencia y del ngulo en que se encuentra ese punto son
x = radio * coseno (ngulo) y = radio * seno (ngulo) - Nota: eso es en el caso de que el centro sea el punto (0,0); si no lo fuera, basta con sumar a estos valores las coordenadas x e y del centro del crculo - Normalmente no necesitaremos usar estas expresiones para dibujar un crculo, porque casi cualquier biblioteca de funciones grficas tendr incluidas las rutinas necesarias para dibujarlos. Pero s nos pueden resultar tremendamente tiles si queremos rotar un objeto en el plano. Lo haremos dentro de poco (y ms adelante veremos las modificaciones para girar en 3D). Parbola . La forma general de un parbola es y = ax2 + bx + c. Los valores de a, b, y c dependen de cmo est de desplazada la parbola y de lo "afilada" que sea. La aplicacin, que veremos en la prctica en el prximo ejemplo, es que si lanzamos un objeto al aire y vuelve a caer, la curva que describe es una parbola (no sube y baja a la misma velocidad en todo momento):
Eso s, al menos un par de comentarios: En "el mundo real", una parbola como la de la imagen anterior debe tener el coeficiente "a" (el nmero que acompaa a x2) negativo; si es un nmero positivo, la parbola sera "al revs", con el hueco hacia arriba. Eso s, en la pantalla del ordenador, las coordenadas verticales (y) se suelen medir de arriba a abajo, de modo que esa ecuacin ser la til para nosotros, tal y como aparece. Nos puede interesar saber valores ms concretos de "a", "b" y "c" en la prctica, para conseguir que la parbola pase por un cierto punto. Detallar slo un poco ms: Una parbola que tenga su vrtice en el punto (x1, y1) y que tenga una distancia "p" desde dicho vrtice hasta un punto especial llamado "foco" (que est "dentro" de la parbola, en la misma vertical que el vrtice, y tiene ciertas propiedades que no veremos) ser: (x-x1)2 = 2p (y-y1) Podemos desarrollar esta expresin y obtener cuanto tendra que ser la "a", la "b" y la "c" a partir de las coordenadas del vrtice (x1, y1) y de la distancia "p" (de la que slo dir que cuanto menor sea p, ms "abierta" ser la parbola): a = 1 / 2p b = -x1 / p c = (x1 2 / 2p ) + y1 Un ejemplo de cmo se usa esto? Claro, en el siguiente juego... 13b. Sexto Juego: TiroAlPlato. Ahora ya sabemos cmo utilizar el ratn, como medir el tiempo y conocemos algunas herramientas matemticas sencillas. Con todo esto, podemos mejorar el juego de puntera, hacerlo "ms jugable". Ahora los blancos estarn en movimiento, siguiendo una curva que ser una parbola, y sern circulares. La puntuacin depender del tiempo que se tarde en acertar. Habr un nmero limitado de "platos", tras el cual se acabar la partida. Con todo esto, la mecnica del juego ser: Inicializar variables Repetir para cada plato: Dibujar plato a la izqda de la pantalla Repetir Si se pulsa el ratn en plato Aumentar puntuacin Si no, al cabo de un tiempo Calcular nueva posicin del plato Redibujar Hasta que el plato salga (dcha) o se acierte Hasta que se acaben los platos Mostrar puntuacin final No suena difcil, no? La apariencia (todava muy sobria) podra ser Construir un algoritmo para juego de Mini serpiente 3 Iniciamos nuestro proyecto nos dirigimos a archivo, Proyecto y aceptamos
Seleccionamos alegrosGL application y si gustamos podemos cambiarle el nombre de nuestro proyecto y aceptamos.
Y empezramos a programar. Inicio #include <stdlib.h> // Para "rand" #include <math.h> // Para "sqrt" #include <allegro.h> /* Existir unas contante por lo que debemos de seleccionar nuestras globales*/ #define ANCHOPANTALLA 320 #define ALTOPANTALLA 200 #define MAXRADIODIANA 25 #define MINRADIODIANA 5 #define NUMDIANAS 12 #define MAXINCREMXDIANA 20 #define MININCREMXDIANA 10 #define RETARDO 7 /* Por lo que ahora continuaremos a declarar las variables que sern utilizadas de acuerdo a las que utilizaremos */ int TamanyoDianaActual, numDianaActual, posXdiana, posYdiana, radioDiana, incremXdiana, incremYdiana, acertado = 0; // Si se acierta -> plato nuevo long int puntos = 0, contadorActual = 0; float a,b,c; // Para la parbola del plato /* la rutina inicara a qui de inicializacin de nuestro programa */ int inicializa() { allegro_init(); // Inicializamos Allegro install_keyboard(); install_timer(); install_mouse();
// Intentamos entrar a modo grafico if (set_gfx_mode(GFX_SAFE, ANCHOPANTALLA, ALTOPANTALLA, 0, 0) != 0) { set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message( "Incapaz de entrar a modo grafico\n%s\n", allegro_error); return 1; }
// Si he podido entrar a modo gr?fico, // ahora inicializo las variables numDianaActual = 1; srand(time(0)); show_mouse(screen);
// Y termino indicando que no ha habido errores return 0; } /* Iniciaremos la nueva rutina de nuestro nuevo plato */ void nuevoPlato() { int xVerticeParabola, yVerticeParabola; float pParabola; /* Crearemos el radio entre el valor mximo y el mnimo que deseamos obtener*/ radioDiana = (rand() % (MAXRADIODIANA - MINRADIODIANA)) + MINRADIODIANA; // La velocidad (incremento de X), similar incremXdiana = (rand() % (MAXINCREMXDIANA - MININCREMXDIANA)) + MININCREMXDIANA; /* el vrtice de la nueva parbola cerca de nuestro centro que deseamos obtener*/ xVerticeParabola = ANCHOPANTALLA/2 + (rand() % 40) - 20; /*y la mitad superior de la nuestra pantalla en un nuevo vrtice */ yVerticeParabola = (rand() % (ALTOPANTALLA/2)); /*calcular el a,b,c de nuestra parbola que utilizaremos*/ pParabola = ALTOPANTALLA/2; a = 1 / (2*pParabola); b = -xVerticeParabola / pParabola; c = ((xVerticeParabola*xVerticeParabola) / (2*pParabola) ) + yVerticeParabola; /*las posiciones horizontal: juntos al margen izquierdo*/ posXdiana = radioDiana; /*las posicin vertical : segn nuestras parbolas*/ posYdiana = a*posXdiana*posXdiana + b*posXdiana + c; }
/* -------------- Rutina de redibujar pantalla ---- */ void redibujaPantalla() { // Oculto ratan scare_mouse(); // Borro pantalla clear_bitmap(screen); // Sincronizo con barrido para menos parpadeos vsync(); /*y nuestro dibujo tendr lo correspondiente a lo que debamos de crear*/ rectfill(screen,0,0,ANCHOPANTALLA,ALTOPANTALLA-40, makecol(70, 70, 255)); //Cielo textprintf(screen, font, 4,4, palette_color[13], "Puntos: %d", puntos); // Puntuaci?n rectfill(screen,0,ALTOPANTALLA-40,ANCHOPANTALLA,ALTOPANTALLA, makecol(0, 150, 0)); //Suelo circlefill(screen, posXdiana, posYdiana, radioDiana, palette_color[15]); // Diana if (numDianaActual <= NUMDIANAS) { textprintf(screen, font, 4,190, palette_color[13], "Platos: %d", NUMDIANAS-numDianaActual); } // Restantes, si no acab?
unscare_mouse(); } /*la distancia de nuestra diferentes distancia de nuestros 2 puntos son */ float distancia(int x1, int x2, int y1, int y2) { return (sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)) ); } /*ahora seleccionaremos a nuestro rutina de tiempo que tendr para lo que es el movimiento de cada plato*/ volatile long int contador = 0; void aumentaContador(void) { contador++; } END_OF_FUNCTION(aumentaContador);
Inicio de nuestro cuerpo del programa. int main() { /*iniciara nuestro programa a qui.*/ if (inicializa() != 0) exit(1); /**el bloqueo de nuestras variables de acuerdo a nuestras necesidades y el funcionamiento del temporizador */ LOCK_VARIABLE( contador ); LOCK_FUNCTION( aumentaContador ); /* por lo que debemos que realizar un cambio de nuestro tiempo en milisegundo que deseamos por lo que debemos de ponerle 30 en nuestro caso para que no sea demasiado rapido*/ install_int(aumentaContador, 30); do { /* Por la parte que se repite cada uno de nuestros platos tienen que ser nuevamente*/
nuevoPlato(); /*se calculara la posicin inicial de nuestro plato*/ redibujaPantalla(); /* lo dibujara en nuestra pantalla el nuevo plato*/ acertado = 0; /* todava no se acercara el nuevo plato aun*/// do { // Parte que se repite mientras se mueve /*comprovacion de nuestro raton*/ if (mouse_b & 1) { if (distancia(mouse_x, posXdiana, mouse_y,posYdiana) <= radioDiana) { puntos += ANCHOPANTALLA-posXdiana; acertado = 1; } } /*si ya ha pasado el retado se mover de nuevo sin motivo alguno*/ if (contador >= contadorActual+RETARDO) { contadorActual = contador+RETARDO; posXdiana += incremXdiana; posYdiana = a*posXdiana*posXdiana + b*posXdiana + c; redibujaPantalla(); } } while ((posXdiana <= ANCHOPANTALLA - radioDiana) && (acertado == 0)); numDianaActual ++; } while (numDianaActual <= NUMDIANAS); redibujaPantalla(); scare_mouse(); textprintf(screen, font, 40,100, palette_color[15], "Partida terminada"); unscare_mouse(); readkey(); return 0; } /* se terminara con la macro que se debio de crear a travs de lo que fue nuestra programacion*/ END_OF_MAIN();
Conclusin: En esta prctica resulto algo enredada al crear nuestros platos que se reventaran y el temporizador para el tiempo que tardara en llegar a un lado de cada uno de ellos, por lo que fue demasiado enredado entenderlo con tantos ciclos que tiene.