Descarga la aplicación para disfrutar aún más
Vista previa del material en texto
Proyecto 02: Videojuego en 2D usando OpenGL. Elizabeth Amavizca Cuellar Gráficos por computadora Dr. Carlos Hugo García Capulín 9 de diciembre de 2022 e.amavizcacuellar@ugto.mx Gael Alexis Morales Flores Gráficos por computadora Dr. Carlos Hugo García Capulín 9 de diciembre de 2022 ga.moralesflores@ugto.mx Rogelio Manríquez Cobián Gráficos por computadora Dr. Carlos Hugo García Capulín 9 de diciembre 2022 r.manriquezcobian@ugto.mx Resumen— En este documento se realiza un videojuego 2D, esta aplicación es de escritorio ofreciendo al usuario un juego interactivo de hasta dos jugadores utilizando el teclado como método de entrada. Términos clave—juego, ping pong, colisión. I. INTRODUCCIÓN En este proyecto se emplea el uso de la API OpenGL, la cual es una herramienta de gráficos que especifica una interfaz de software estándar para hardware de procesamiento de gráficos 2D y 3D, de igual manera se utiliza la biblioteca GLUT para las utilidades de control de ventanas y el monitoreo de las entradas del teclado y ratón. Con estas herramientas de desarrollo, se implementará un videojuego 2D especialmente enfocado a un juego de "Ping Pong", el cual tendrá funcionalidades de un solo jugador o 2 jugadores mediante el uso del teclado; algunos de los elementos visuales que se utilizan son la creación de figuras geométricas y las colisiones que ocurren cuando la pelota choca con un elemento. Además, se agregaron funcionalidades como un botón para poder iniciar la partida o reiniciarla de acuerdo con el gusto que prefiera utilizar el usuario final. El desarrollo del proyecto fue escrito en el lenguaje de programación C y probado en el entorno de Windows. Por lo tanto, en las siguientes secciones se explica el desarrollo de cómo se ha realizado el videojuego, para luego observar los resultados obtenidos mediante un video y discutir sobre su funcionalidad. II. DESARROLLO A continuación, se describen las estructuras de datos creadas para la interacción con el usuario y la interfaz, a continuación, se describen las estructuras y sus atributos de forma breve. A. Estructura punto. Esta estructura de datos contiene los atributos que posee un punto, un conjunto de coordenadas (X, Y). typedef struct{ float x; float y; }PUNTO; B. Estructura de datos rectángulo. La estructura contiene un atributo pivote de tipo punto, además de dos valores de tipo flotante correspondientes al ancho y alto del rectángulo. typedef struct{ PUNTO piv; float ancho; float alto; COLOR color; }RECTANGULO; C. Estructura de datos círculo. Esta figura contiene un punto correspondiente al centro del círculo, un valor flotante para el radio y una variable para el color de la figura. typedef struct{ PUNTO c; float radio; COLOR color; }CIRCULO; A continuación se describen las funciones programadas en el código para el funcionamiento del videojuego, estas se explicaran en el orden de ejecución en el programa. A. Función main. En esta función se realizan las configuraciones necesarias para el programa, en este caso se inicializa la librería GLUT, se configuran parámetros de la ventana, título, funciones para el manejo del ratón y teclado, también se realiza la configuración de las figuras utilizadas para la interfaz de usuario. // FUNCIÓN MAIN int main(int argc, char **argv){ glutInit(&argc,argv); glutInitWindowSize(tamVentana, tamVentana); glutCreateWindow("Proyecto 2: Implementar un videojuego en 2D"); // CONFIGURACIÓN FIGURAS GUI setGame(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // DIVISIÓN DEL LIENZO EN 20x20 glOrtho(-10, 10, -10, 10, 1.0, -1.0); glMatrixMode(GL_MODELVIEW); // FUNCIÓN DE DISPLAY glutDisplayFunc(display); // FUNCIÓN DE ANIMAR glutIdleFunc(animar); // FUNCIONES PARA EL RATÓN glutMouseFunc(raton); // FUNCIONES PARA EL TECLADO glutSpecialFunc(teclasEspeciales); glutKeyboardFunc(teclasNormales); glutMainLoop(); return 0; } B. Función display. En esta función se realiza una limpieza del buffer y se ejecuta otra función encargada de mostrar todos los elementos visuales de la interfaz para el/los usuarios. mailto:e.amavizcacuellar@ugto.mx mailto:ga.moralesflores@ugto.mx mailto:r.manriquezcobian@ugto.mx void display(void){ glClearColor(0.3, 0.3, 0.4, 1); glClear(GL_COLOR_BUFFER_BIT); // MOSTRAR LOS ELEMENTOS GUI mostrarGUI(); glFlush(); } C. Función setGame. Esta función se encarga de iniciar y reiniciar las partidas durante la ejecución del programa, este reinicia las posiciones de los jugadores y de la bola, además reinicia la puntuación de los jugadores y pausa el juego. void setGame(void){ // INICIALIZACIÓN DE BOLA bola.c.x = 0; bola.c.y = 1; bola.color = GRIS; bola.radio = 0.5; // INICIALIZACIÓN DE JUGADOR 1 P1.piv.x = -9.7; P1.piv.y = -1; P1.ancho = 0.5; P1.alto = 3; P1.color = BLANCO; // INICIALIZACIÓN DE JUGADOR 2 P2.piv.x = 9.2; P2.piv.y = -1; P2.ancho = 0.5; P2.alto = 3; P2.color = BLANCO; puntos[0] = 0; puntos[1] = 0; play = 0; } D. Función mostrar GUI. Como su nombre lo indica esta función se encarga de mostrar todos los elementos gráficos necesarios para la interfaz de usuario, en este caso se dibujan rectángulos, círculos y líneas, además de mostrar los textos en la interfaz para el usuario. void mostrarGUI(){ float theta; // FONDO NEGRO PARA BOTONES AsignaColor(GRIS_OSCURO); // BORDE INFERIOR glRectf(-10.0, -10.0, 10.0, -8.8); // BOTÓN 1 JUGADOR AsignaColor(NEGRO); glRectf(-9.9, -9.8, -6.9, -9); AsignaColor(BLANCO); glRectf(-9.8, -9.7, -7.0, -9.1); // BOTÓN 2 JUGADORES AsignaColor(NEGRO); glRectf(-6.7, -9.8, -3.7, -9); AsignaColor(BLANCO); glRectf(-6.6, -9.7, -3.8, -9.1); ⋮ // TEXTOS DE VELOCIDAD Y REINICIO sprintf(cadena3,"SPEED: %i", modoVelocidad); dibujarTexto(cadena3, 4.25, -9.55); sprintf(cadena3,"RESET"); dibujarTexto(cadena3, 7.6 , -9.55); // BOTÓN DE INICIO if(!play){ AsignaColor(NEGRO); glRectf(-2.7, 0.3, 2.7, 1.7); AsignaColor(BLANCO); glRectf(-2.5, 0.5, 2.5, 1.5); AsignaColor(NEGRO); sprintf(cadena3,"PLAY"); dibujarTexto(cadena3, -0.6, 0.8); } glutPostRedisplay(); } Tras realizar una breve explicación del funcionamiento de las funciones que no interactúan directamente con el usuario se realiza una explicación de las funciones que sí interactúan con el usuario, específicamente se describirán las funciones correspondientes a la interacción utilizando el teclado y ratón. A. Función de ratón (botones). GLUT permite detectar si el usuario ha presionado un botón del ratón, esto se aprovecha para implementar la selección de modo de juego (1 o 2 jugadores), para ajustar la velocidad a la que la bola se mueve por el plano y a reiniciar el juego, en este caso solamente se implementa el botón izquierdo del ratón. void raton(int boton, int estado, int x, int y){ PUNTO pt = CVent_a_Cplano(x,y,tamVentana,tamVentana,-10,10,-10,10); if(estado == GLUT_DOWN) switch(boton){ case GLUT_LEFT_BUTTON: clicIzquierdo(pt); break; } } B. Función clic izquierdo. Este clic se encarga de comprobar las regiones donde el usuario hace clic para realizar interacciones como cambiar de modo de juego, cambiar la velocidad, reiniciar el juego y comenzarlo cuando está pausado. void clicIzquierdo(PUNTO pt){ // REGIONES DE BOTONES // REGIÓN DE 1 JUGADOR if(((pt.x>=-9.5)&&(pt.x<=-6.9))&&((pt.y>=-9.8)&&(pt.y <=-9))){ setGame(); modo = 1; } // REGIÓN DE 2 JUGADORES else if(((pt.x>=-6.7)&&(pt.x<=-3.7))&&((pt.y>=- 9.8)&&(pt.y <= -9))){setGame(); modo = 2; } ⋮ // REGIÓN DE REINICIO if(((pt.x>=6.9)&&(pt.x<=9.9))&&((pt.y>=-9.8)&&(pt.y <=-9))){ setGame(); } // REGIÓN DE PLAY if(!play) if(((pt.x>=-2.7)&&(pt.x<=2.7))&&((pt.y>=0.3)&&(pt.y <=1.7))) play = 1; glutPostRedisplay(); } A. Función teclas especiales. De la misma forma que se implementa el ratón se utiliza la configuración ofrecida por GLUT glutSpecialFunc para la interacción mediante el teclado con las teclas especiales, en este caso se implementa el movimiento vertical correspondiente al jugador situado a la izquierda del plano. void teclasEspeciales(int tecla, int x, int y){ switch(tecla){ case GLUT_KEY_UP: teclaArriba(); break; case GLUT_KEY_DOWN: teclaAbajo(); break;} glutPostRedisplay(); } B. Función tecla arriba. Esta función es invocada por las teclas especiales, comprueba si el juego está en ejecución y, en caso de estarlo, aumenta en 0.5 unidades la altura del jugador 1. void teclaArriba(void){ if(play) if(P1.piv.y < 6.5) P1.piv.y += 0.5; } C. Función tecla abajo. Esta función es invocada por las teclas especiales, comprueba si el juego está en ejecución y, en caso de estarlo, disminuye en 0.5 unidades la altura del jugador 1. void teclaAbajo(void){ if(play) if(P1.piv.y > -8.5) P1.piv.y -= 0.5; } A. Función de teclas normales. Para esta función se configura un total de tres teclas, estas son utilizadas para cerrar el programa (escape) y para cambiar la posición del jugador 2 en caso de estar en modo de 2 jugadores. void teclasNormales(unsigned char tecla,int x, int y){ switch(tecla){ case 27: exit(0); break; case 'w': if(play==1 && modo == 2) if(P2.piv.y < 6.5) P2.piv.y += 0.5; break; case 's': if(play==1 && modo == 2) if(P2.piv.y > -8.5) P2.piv.y -= 0.5; break; } glutPostRedisplay(); } B. Función coordenadas ventana a plano. Esta función se encarga de realizar una conversión de las coordenadas otorgadas del ratón a coordenadas que puedan interpretarse dentro del plano en el rango [-10, 10] para la interacción con el usuario, esta recibe las coordenadas de la ventana y regresa un punto con ambas coordenadas convertidas. PUNTO CVent_a_Cplano(int x, int y,int AnchoV, int AltoV, float xini, float xfin, float yini, float yfin){ PUNTO pos; float RangoX = xfin - xini; float RangoY = yfin - yini; float porcentaje; porcentaje = ((float)x/AnchoV); pos.x = (porcentaje*(RangoX)) - (RangoX)/2; porcentaje = ((float)y/AltoV); pos.y=((1-porcentaje)*(RangoY))-(RangoX)/2; return pos; } III. PRUEBAS Y RESULTADOS Para la demostración de pruebas y resultados se recurre a la visualización de un video grabado demostrando el funcionamiento del código implementado. Enlace al video de videojuego 2D en OneDrive: Video demostrativo. [2] Para analizar el código del proyecto y poder ejecutarlo junto con las instrucciones de compilación; este se encontrará en un repositorio de GitHub que se puede consultar en la sección de “REFERENCIAS”. [1] IV. CONCLUSIONES Gael Alexis Morales Flores. Para la implementación de un videojuego se ha recurrido a un videojuego clásico, este juego es conocido por ser uno de los más antiguos y ha sido la opción elegida porque puede ser considerado un código para principiantes y se ha logrado implementar sin problemas utilizando lo aprendido en clase respecto a colisiones, datos de entrada mediante teclado y ratón, animar objetos, entre otros. Aunque haya sido un juego simple es importante que la lógica debe cumplirse en todo momento utilizando correctamente las herramientas ofrecidas por GLUT y utilizando OpenGL. Ha sido una buena asignación final para el curso aunque hubiera deseado ver algo en 3D debido a la investigación realizada para anteriores entregas he podido observar algo de este contenido que ha sido muy llamativo en mi opinión. Elizabeth Amavizca Cuellar. La implementación de este proyecto nos ayudó para comprender mejor el tema de las colisiones, ya que la principal función del juego está hecha con estas, fue interesante también comprender el inicio de los videojuegos, como se logra que los objetos no se traspasen entre sí y puedan existir en un plano como figuras independientes, para la realización del proyecto fue relativamente sencillo ya que teníamos previos conocimientos gracias a la segunda práctica. Rogelio Manríquez Cobián. Realizar este proyecto tuvo sus puntos interesantes porque se aplicaron todos los conocimientos vistos en clase, desde la creación de figuras geométricas hasta el uso de funciones interactivas de teclado y ratón. También fue de suma importancia entender el funcionamiento correcto de las colisiones, ya que este tema es visto en mayor parte en la creación de videojuegos y se aplicó de manera exitosa para el desarrollo de este proyecto con la creación de un Ping Pong sencillo para un solo jugador o 2 jugadores. La creación del https://ugtomx-my.sharepoint.com/:v:/g/personal/ga_moralesflores_ugto_mx/EZePiUHTpl9DlvQXpi_jNeABrTXs0OB1euTs_LoTKDO9Dw?e=dlnRGe https://ugtomx-my.sharepoint.com/:v:/g/personal/ga_moralesflores_ugto_mx/EZePiUHTpl9DlvQXpi_jNeABrTXs0OB1euTs_LoTKDO9Dw?e=dlnRGe https://ugtomx-my.sharepoint.com/:v:/g/personal/ga_moralesflores_ugto_mx/EZePiUHTpl9DlvQXpi_jNeABrTXs0OB1euTs_LoTKDO9Dw?e=dlnRGe� entorno (vista) fue gracias al kit de herramientas de GLUT para poder dar color, y en conjunto con la herramienta de OpenGL se pudo mostrar todo desde una ventana dónde se corre el programa. Las funcionalidades dentro del juego como lo son los puntajes y el reseteo del juego, se utilizó la lógica de programación para su implementación. Para finalizar, con la ayuda de estas herramientas, se pueden lograr muchas cosas que se puedan imaginar, por lo tanto, me gustaría investigar más sobre estas funcionalidades para realizar aplicaciones que involucren una dimensión 3D. REFERENCIAS [1] Github. Repositorio GPC_Proyecto02. Enlace: clic aquí. [2] Video demostrativo: clic aquí. https://github.com/Pokilul/GPC_Proyecto02 https://ugtomx-my.sharepoint.com/:v:/g/personal/ga_moralesflores_ugto_mx/EZePiUHTpl9DlvQXpi_jNeABrTXs0OB1euTs_LoTKDO9Dw?e=dlnRGe I. Introducción II. Desarrollo A. Estructura punto. B. Estructura de datos rectángulo. C. Estructura de datos círculo. Esta figura contiene un punto correspondiente al centro del círculo, un valor flotante para el radio y una variable para el color de la figura. A continuación se describen las funciones programadas en el código para el funcionamiento del videojuego, estas se explicaran en el orden de ejecución en el programa. A. Función main. B. Función display. C. Función setGame. D. Función mostrar GUI. A. Función de ratón (botones). B. Función clic izquierdo. A. Función teclas especiales. B. Función tecla arriba. C. Función tecla abajo. A. Función de teclas normales. B. Función coordenadas ventana a plano. III. Pruebas y Resultados IV. Conclusiones Referencias
Compartir