Download Estudio y Análisis de algoritmos para la realización de
Document related concepts
no text concepts found
Transcript
! & " # ' $% $% ( ) * +,-./0 * 1 2 3 2 44- * 445 "There is no way to happiness. Happiness is the way. There is no way to peace. Peace is the way. There is no way to enlightenment. Enlightenment is the way." ...Thich Nhat Hanh-Buddha Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D El proyecto “O cavaleiro dos céus - Jogo de computador 2D”, tiene una parte práctica consistente en la realización de un juego de computador en 2 dimensiones, y una parte de investigación teórica en la que se estudian distintas técnicas y algoritmos que conduzcan a la realización de un juego 2D de computador. 2 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) 6 Jogo de computador2D 7& Quería agradecer toda su inestimable ayuda y apoyo en la realización del proyecto al orientador de éste: el Profesor Alexandre Carvalho, y a la profesora de la disciplina Renata Barbosa. A Luis Peralta [Peralta2005] por haberme cedido el software de creación propia WW2plane, para la generación de aviones de la segunda guerra mundial. También quería agradecer al ISMAI y a todos los responsables del curso de Tecnología da Comunicação Multimedia la oportunidad que se me ha brindado de estudiar este año académico aquí en Maia. A todos… ¡GRACIAS! Dedicado a mis padres y hermanos… 3 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 7 Sumario................................................................................................................................... 2 Agradecimientos..................................................................................................................... 3 Índice de ilustraciones ............................................................................................................ 8 1. Introducción........................................................................................................................ 9 1.1. Contexto ...................................................................................................................... 9 1.1.1 Proceso previo ....................................................................................................... 9 1.1.2. Motivación......................................................................................................... 10 1.2 Finalidad y Objetivos ................................................................................................. 11 1.3. Estructura del documento .......................................................................................... 12 2. Estado de conocimiento.................................................................................................... 13 2.1. Historia de los videojuegos Arcade ........................................................................... 13 2.2. Presentación del trabajo............................................................................................. 15 2.3. Conceptos .................................................................................................................. 15 2.3.1. Sprites ................................................................................................................. 15 2.3.2. Coordenadas polares. Distancia entre dos puntos y cambios de coordenadas polares – cartesianas ..................................................................................................... 16 2.3.3. Imágenes. Formatos de fichero........................................................................... 18 2.4. Técnicas de juegos arcade ......................................................................................... 19 2.4.1. Active Rendering (Rendering activo)................................................................. 19 2.4.2. Carga tardía......................................................................................................... 20 2.4.3. Doble Buffering.................................................................................................. 21 2.4.4. Page flipping....................................................................................................... 22 2.4.5. Animación: Fotogramas o Frames...................................................................... 23 2.4.6. Transformaciones Afines.................................................................................... 25 2.4.7. Gestión de eventos.............................................................................................. 25 2.4.8. Scroll................................................................................................................... 26 2.4.9. Detección de colisiones ...................................................................................... 27 2.4.10. Patrones de movimiento. Algoritmo Estándar.................................................. 30 4 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 2.4.11. Persecución y Evasión básicas ......................................................................... 32 2.4.12. Inteligencia Artificial en juegos ....................................................................... 34 3. Descripción....................................................................................................................... 36 3.1. Descripción General .................................................................................................. 36 3.2. Descripción por Bloques ........................................................................................... 38 3.3. Descripción de las Clases .......................................................................................... 39 3.3.1. Jerarquía de Clases ............................................................................................. 39 3.3.2. Class Jogo2D ...................................................................................................... 40 3.3.3. Clase GraficosCache........................................................................................... 41 3.3.4. Clase SonidoCache ............................................................................................. 42 3.3.5. Clase RecursosCache.......................................................................................... 42 3.3.6. Clase Escenario................................................................................................... 42 3.3.7. Clase Sprite......................................................................................................... 43 3.3.8. Clase Enemigo.................................................................................................... 44 3.3.9. Clase Jugador...................................................................................................... 45 3.3.10. Clase Tiros........................................................................................................ 45 3.3.11. Clase Bomba..................................................................................................... 45 3.3.12. Clase TirosEnemigo ......................................................................................... 46 3.3.13. Clase PuntosExtra............................................................................................. 46 3.3.14. Clase Fondos .................................................................................................... 46 3.3.15. Clase Scroller.................................................................................................... 46 3.3.16. Clase Comportamiento ..................................................................................... 47 4. Implementación ................................................................................................................ 49 4.1. Etapas más importantes seguidas para el desarrollo del juego.................................. 49 4.2. Herramientas.............................................................................................................. 51 4.2.1. Java 1.4.2_10 SDK ............................................................................................. 52 4.2.2. Abstracción......................................................................................................... 54 4.2.3. Encapsulación..................................................................................................... 54 4.2.4. Herencia.............................................................................................................. 55 5 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 4.2.5. Polimorfismo ...................................................................................................... 55 4.2.6. Eclipse 3.1 ......................................................................................................... 56 4.3 Técnicas usadas en la implementación del juego ....................................................... 57 4.3.1. Gestión de eventos.............................................................................................. 57 4.3.2. Fotogramas ......................................................................................................... 58 4.3.3. Transformaciones Afines.................................................................................... 59 4.3.4. Carga de imágenes.............................................................................................. 60 4.3.5. Imágenes Compatibles........................................................................................ 61 4.3.6. Doble Buffering.................................................................................................. 62 4.3.7. Colisiones ........................................................................................................... 63 4.4. Librerías..................................................................................................................... 64 4.4.1. javax.swing.JFrame ............................................................................................ 65 4.4.2 java.*.BufferedImage .......................................................................................... 65 4.4.3. java.*.BufferStrategy.......................................................................................... 65 4.4.4. java.util.HashMap............................................................................................... 66 4.4.5. java.awt.event.KeyEvent .................................................................................... 66 4.4.6. java.awt.Graphics2D .......................................................................................... 66 5. Desarrollo de la parte Gráfica del juego........................................................................... 68 5.1. Proceso de creación de los sprites ............................................................................. 68 5.2. Explosiones................................................................................................................ 71 5.3. Creación de los escenarios......................................................................................... 71 5.4. Creación de la pantalla de presentación de las fases ................................................. 72 6. Resultados......................................................................................................................... 73 7. Conclusiones..................................................................................................................... 76 8. Bibliografía....................................................................................................................... 79 9. Índice remisivo ................................................................................................................. 81 10. Anexos ............................................................................................................................ 82 10.1. Anexo I: Manual de Usuario ................................................................................... 82 10.1.1. Instalación......................................................................................................... 82 6 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 10.1.2. Comandos para el manejo del juego................................................................. 83 10.1.3. Reglas del juego ............................................................................................... 84 10.2. Anexo II: Imágenes y texturas del juego. ................................................................ 87 7 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) 87 Jogo de computador2D & 7 Figura 1 – Distancia entre dos puntos .................................................................................. 17 Figura 2 - Coordenadas polares de un punto ........................................................................ 17 Figura 3 - Scroll basado en baldosas descomponiendo un mapa de bits en pequeños objetos gráficos, creando un mapa del gráfico.......................................................................... 27 Figura 4 - Posibles cambios de estado de un objeto que se desplaza por la pantalla .......... 35 Figura 5 - Jerarquía de Clases............................................................................................... 39 Figura 6 – Ejemplo compiladores para distintas plataformas y de la JVM......................... 52 Figura 7- Intersección de los rectángulos de dos sprites. ..................................................... 63 Figura 8 - Logotipo de WW2plane....................................................................................... 68 Figura 9 - Macros creadas para Photoshop CS2.................................................................. 69 Figura 10 - Secuencia sprites de un avión japonés............................................................... 70 Figura 11 - Secuencia de sprites de un avión alemán........................................................... 70 Figura 12 - Secuencia de sprites de puntosExtra.................................................................. 70 Figura 13 - Secuencia de sprites de una explosión............................................................... 71 8 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) ,9 7 & Jogo de computador2D :7 El proyecto consiste en analizar y estudiar las técnicas y algoritmos que conduzcan a la realización de un Juego 2D de computador. Como parte práctica a complementar la realización del trabajo de investigación teórico, se ha desarrollado un juego de computador en dos dimensiones tipo arcade con scroll, recurriendo a la tecnología de desarrollo orientada a objetos y computación gráfica 2D. El lenguaje de programación que se consideró más adecuado para el desarrollo de este juego es el lenguaje Java. Algunas de las técnicas de estudio para la realización de la parte práctica de la monografía son: La translación de imágenes en la pantalla. La visualización de los sprites y su animación. La gestión de eventos. ,9,9 1 1.1.1 Proceso previo Una de las partes más complicadas y por ello más importantes de todas fue la elección del proyecto a realizar. Pero con la inestimable ayuda del orientador, el profesor Alexandre Carvalho, se pudo escoger el proyecto a realizar entre un abanico de posibilidades muy amplio: cortometrajes, video clips, animación, cine, fotografía, diseño Web, CD’s interactivos, documentales, etc. La dificultad de dicha elección radicaba en el desconocimiento global que tenía del Curso Tecnología da Comunicação Multimedia. Al ser un estudiante extranjero con una beca Erasmus, he tenido acceso a la realización de este proyecto sin haber cursado los 4 años 9 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D correspondientes al curso. Por ello desconocía hasta que punto estaba o no preparado para la realización del proyecto. Mi orientador y yo creímos oportuno compaginar los conocimientos del curso que estudio en España (Ingeniería Informática) con los de aquí. El siguiente paso fue elegir un juego en 2 dimensiones. Para ello usó un programa emulador de máquinas recreativas. El Multiple Arcade Machine Emulator (emulador múltiple de máquinas recreativas), también conocido por sus siglas MAME, es un emulador de máquinas recreativas; máquinas de videojuegos que funcionan con monedas y que suelen estar en lugares públicos (bares, boleras, salones recreativos...). Para hacer funcionar un juego, se requiere su correspondiente ROM (archivo con una imagen de la ROM de la máquina, que contiene el juego en sí). Es un programa libre y gratuito. De entre todos ellos se escogió un tipo de juegos de aviones (scroll) como base para comenzar a trabajar, y que dio pie a gran parte de los objetivos que se han marcado para la realización del proyecto. 1.1.2. Motivación Siempre he creído que los computadores son una herramienta para conseguir unos fines que nos marquemos, para facilitarnos la vida, un medio con el que poder desarrollar nuestro poder imaginativo, y nunca al contrario. Estudiando Ingeniería Informática en España mi sensación era la opuesta, es decir, yo era el siervo y esclavo del computador. Aquí se me ha brindado la oportunidad de comenzar a utilizar los ordenadores de una forma más creativa al realizar este curso; curso que por otra parte no tiene equivalencia en España. Poder realizar un proyecto de fin de curso con resultados tan visibles e inteligibles como es la creación de un juego de computador arcade, como aquellos con los que jugaba en la 10 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D infancia, me llenaba de satisfacción, y a la vez suponía un reto tener que manejar un lenguaje de programación hasta entonces desconocido para mí como Java, el manejo de programas de diseño gráfico para la parte gráfica del juego, y el hecho de tener que investigar en un área del conocimiento tan atrayente e interesante como es el mundo de los videojuegos y sus distintas técnicas de creación. Además todo esto se complementaba a la perfección con el resto de las disciplinas que estudio durante este año en el curso de Tecnologías de Comunicação Multimedia, ya que abarcan desde el manejo de programas enfocados al tratamiento de las imágenes y el diseño gráfico hasta el estudio del lenguaje Java. Otra motivación es la posibilidad inmediata de enfocar mi futuro laboral hasta este año incierto, en una de estas áreas creativas (diseño gráfico, computación gráfica, programación de videojuegos…) ,9 ; # <= 2 La finalidad de este proyecto es la iniciación en un mundo apasionante y desconocido para mí como el de la programación de videjuegos y conseguir encaminar mis conocimientos de programación anteriores a este año hacia las tecnologías multimedia; y todo ello mediante la creación de un juego de computador en dos dimensiones y el estudio de las técnicas y teorías necesarias para su creación. Algunos objetivos que se marcaron al comienzo del proyecto son: El tratamiento de las imágenes en los juegos (sprites) y su desplazamiento por la pantalla (trayectorias). La visualización de dichas imágenes y su animación (frames) La gestión de eventos en el juego 11 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D ,9>9 El documento se estructura en una parte inicial introductoria en la que se especifica el dominio o contexto del tema a tratar, las motivaciones así como finalidad, objetivos y resultados a alcanzar. En el siguiente bloque se pasa al cuerpo central del documento, hablando sobre la historia de los juegos arcade y haciendo una breve presentación del trabajo, su descripción (general y por bloques), y las técnicas y algoritmos estudiados para la realización de juegos en dos dimensiones. A continuación viene un bloque que trata sobre la implementación. Se dedica un capítulo a las herramientas usadas (lenguaje de programación Java y entorno de desarrollo integrado Eclipse) y a algunas características de los lenguajes Orientados a Objetos (abstracción, encapsulación, herencia y polimorfismo). Se comentando en todos estos apartados técnicas usadas para la realización de la práctica y alternativas a dichas técnicas. En el último apartado del documento se muestran los resultados y las conclusiones extraídas de la realización del proyecto. 12 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) 9 9,9 ? Jogo de computador2D & 7 2 7& = Un videojuego (llamado también juego de vídeo) es un programa informático, creado expresamente para divertir, basado en la interacción entre una persona y un aparato electrónico donde se ejecuta el videojuego. Éstos recrean entornos virtuales en los cuales el jugador puede controlar a un personaje o cualquier otro elemento de dicho entorno, para conseguir uno o varios objetivos por medio de unas reglas determinadas. [www_01] Los videojuegos pueden ser grabados en algún medio de almacenamiento (como un cartucho, una tarjeta, un disquete, un CD, etc.) para ser ejecutados en un aparato específico. El hardware que ejecuta los videojuegos puede ser desde una computadora a un artefacto especialmente creado para ello, como las videoconsolas o las máquinas arcade, pasando por teléfonos móviles (celulares) y otros dispositivos electrónicos. [www_01] Los videojuegos como arcade nacieron en 1971 cuando Nolan Bushnell comenzó a comercializar Computer Space, una versión de Space War, en Estados Unidos, aunque es posible que se le adelantara Galaxy War otra versión arcade de Space War aparecida a principios de los 70 en el campus de la universidad de Standford. “Arcade” es el término genérico usado por los angloparlantes y extendido para el resto del mundo, pero recibe distintas denominaciones dependiendo el país. Arcade son las grandes maquinas disponibles en sitios comerciales públicos como restaurantes, locales, centro comerciales, bares y sitios especializados para jugar videojuegos. Las máquinas son muebles con algunos controles como un joystick y botones, o una pistola o un volante dependiendo el juego. Una característica común, es la escasa duración de las partidas llamadas “creditos” (credit en inglés) que en el argot de este mundo significa las continuaciones posibles de seguir jugando por tiempo o por perder todas las vidas; la poca duración asegura que el jugador vaya introduciendo sus monedas o tarjetas. 13 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D También se evita la complejidad para enganchar a cualquier persona. Los primeros videojuegos salieron en arcade y computadoras (ordenador) antes que en las llamadas consolas, así que son parte esencial de la historia del videojuego. [www_02] En la década de los 80 y 90, los arcades eran considerados la “prueba de fuego” para mostrar todo el potencial gráfico de un videojuego o innovaciones, que eran limitadas por los controles de consolas y ordenador o simplemente para que mostrara una sensación más real y envolvente que la que se podría vivir manejando un teclado, en especial las cabinas hidráulicas de algunos simuladores aéreos, dos o más pantallas y cualquier otro accesorio difícil de implementar en el sector domestico. Debido a la rentabilidad y avance de tecnología en las consolas y computadoras que han llegado a tener un hardware superior al arcade, la posibilidad de jugar online y otros motivos, las maquinas de arcade han ido perdiendo popularidad hasta casi desaparecer. En otros usos, el término “arcade” se refiere a los videojuegos clásicos o que recuerdan a las maquinas del mismo nombre. También se usa para diferenciar a los simuladores; Algunos géneros en las maquinas de arcade son: deportivos, simuladores aéreos, de carreras, de acción, de peleas, plataformas, alfombras de baile, juegos de carta, aventuras y en menor medida puzzles. Los videojuegos tipo Side-Scrolling son una colección de videojuegos en los que las únicas direcciones permitidas son arriba, abajo, izquierda y derecha. Existe también un grupo de enemigos que pueden ser destruidos o esquivados, la acción es vista desde un único ángulo de cámara y los caracteres se mueven generalmente desde el lado izquierdo hacia el lado derecho de la pantalla para alcanzar sus metas. Tile-based game o videojuegos basados en baldosas, tienen su dominio dividido en un número discreto de baldosas – cuadrados, hexágonos, etc. – y la posición del jugador es 14 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D fijada en un azulejo concreto. El movimiento se hace azulejo a azulejo, y el número de direcciones en las que el jugador puede progresar es limitado. En un “entorno continuo”, la posición es representada por coordenadas en punto flotante, lo que puede representar cualquier localización en el dominio de un juego. El jugador también es libre de avanzar en cualquier dirección. En estos juegos las xs y las ys representan columnas y filas en una malla que abarca el dominio del juego. En un dominio discreto serían valores enteros y en un entorno contínuo, las xs y las yx (y zs si se hablase de un juego en 3 dimensiones) serían números reales representando las coordenadas en un sistema de coordenadas cartesianas. 9 9" <= Por tanto el tipo de juego que se ha desarrollado es un juego arcade de aviones con scroll de pantalla para simular el avance del avión por los distintos escenarios. En ese avance se dedica a luchar contra aviones o grupos de aviones enemigos que se desplazan por la pantalla con trayectorias aleatorias. Tanto el avión del jugador como los aviones enemigos tienen la capacidad de disparar. Cada vez que un avión enemigo es alcanzado por disparos del avión del jugador, explota, mientras que si el avión del jugador es alcanzado va perdiendo vida hasta perderla toda y explotar. 9>9 2.3.1. Sprites Se puede decir que un sprite es un elemento gráfico determinado (una nave, un coche, etc...) que tiene entidad propia y sobre la que se pueden definir y modificar ciertos atributos, como la posición en la pantalla, si es o no visible, etc. 15 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Un sprite es un gráfico que se mueve de manera independiente por la pantalla. Puede ser animado y moverse a la vez. Además de la animación, o de la imagen, un sprite estará compuesto por dos características principales: la posición y la velocidad. [Brackeen2004] Los sprites (en inglés ‘duendecillos’) son un invento de Jay Miner. Se trata de un tipo de mapa de bits dibujados en la pantalla de ordenador por hardware gráfico especializado sin cálculos adicionales de la CPU. [www_03] Típicamente, los sprites son usados en videojuegos para crear los gráficos de los protagonistas, o para producir una animación, como un personaje corriendo, alguna expresión facial o un movimiento corporal. Con el paso del tiempo el uso de este término se extendió a cualquier pequeño mapa de bits que se dibujase en la pantalla. Los sprites han ido evolucionando a lo largo de la historia de los videojuegos. En un principio, mientras algunos eran generados a computador, otros eran dibujados a mano para posteriormente ser traspasados al computador. Con la llegada de los videojuegos en 3D, el uso de sprites se ha comenzado a dejar de lado, al ocupar su puesto personajes poligonales. [www_03] 2.3.2. Coordenadas polares. Distancia entre dos puntos y cambios de coordenadas polares – cartesianas Para poder construir toda la parte referente a las trayectorias de los sprites y sus comportamientos, se hizo necesaria la compresión de conceptos matemáticos básicos para la computación gráfica como son el cálculo de distancias entre dos puntos, ángulos, conversión de coordenadas polares a cartesianas y viceversa, etc. 16 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Tal y como se representa en la Figura 2, la distancia horizontal entre dos puntos es c-a y la distancia vertical es d-b, por lo tanto, como la distancia entre los puntos es la hipotenusa, del triángulo formado: . [www_04] Figura 1 – Distancia entre dos puntos El sistema más utilizado para localizar un punto suele ser el de las coordenadas cartesianas, pero hay otro muy utilizado también: el de coordenadas polares. En este método se utiliza la distancia del punto al origen, medido sobre el segmento que los une, y el ángulo que forma dicho segmento con uno de los ejes. Véase la Figura 3: Figura 2 - Coordenadas polares de un punto 17 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Si (x,y) son las coordenadas cartesianas de un punto, las coordenadas polares de ese punto serán y = arctg y/x. [www_04] Si (r, ) son las coordenadas polares de un punto, las coordenadas cartesianas serán: x = r cos( ), y = r sen( ). [www_04] 2.3.3. Imágenes. Formatos de fichero A la hora de usar imágenes se ha de tener en cuenta la transparencia de éstas para su utilización. Existen tres tipos de transparencia de imagen: Opaca: Cada píxel de la imagen es visible. Transparente: Cada píxel en una imagen puede ser o completamente visible o completamente transparente con lo que el fondo blanco de un sprite podría ser transparente, que es como se mostraría. Traslúcida: Los píxeles pueden ser parcialmente transparentes. Opcionalmente se pueden hacer traslúcidos los bordes de una imagen para que ésta fuese anti-aliased. La java runtime soporta tres formatos raster diferentes, y se pueden leer con apenas esfuerzo. Estos tres formatos son GIF, PNG, y JPEG. [Knudsen1999] GIF: las imágenes GIF pueden ser u opacas o transparentes y tiene 8 bits de color o menos. Aunque GIF tienen alta compresión imágenes gráficas sin mucha variación de color, PNG supera la funcionalidad del formato GIF. PNG: Las imágenes PNG pueden tener cualquier tipo de transparencia: opaca, transparente o traslúcida. También, las imágenes PNG pueden tener cualquier profundidad de bit, hasta 24bits de color. El porcentaje de compresión para imágenes PNG de 8bits es similar al de imágenes GIF. 18 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D JPEG: las imágenes JPEG sólo pueden ser de 24bits de profundidad y opacas. JPEG tiene una alta compresión para imágenes fotográficas, pero es un algoritmo de compresión con pérdidas, con lo que la imagen no es una réplica exacta de la fuente original. [Brackeen2004] 9@9 &A = Se comentan a continuación algunas técnicas típicas a tener en cuenta en el desarrollo de juegos tipo arcade: 2.4.1. Active Rendering (Rendering activo) Para implementar una animación en java, se necesita una forma de actualizar continuamente la pantalla de una manera eficiente. Confiar en el método paint() para hacer cualquier tipo de rendering implica llamar al método repaint() para crear el evento AWT que envía un hilo o thread para repintar la pantalla, pero esto puede causar retrasos porque el hilo AWT puede estar ocupado haciendo otras cosas. [Brackeen2004] Otra opción es usar Active Rendering. Active Rendering es un término para describir el hecho de pintar directamente sobre la pantalla en el hilo principal. De esta manera se tiene el control cuando la pantalla realmente se pinta, simplificándose el código bastante. Para usar la técnica de active rendering, se usa el método Component’s getGraphics () para obtener el contexto gráfico de la pantalla: Graphics g = screen.getFullScreenWindow().getGraphics(); Draw(g); g.dispose(); 19 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 2.4.2. Carga tardía Cargar una imagen dentro del propio método paint() sería una manera muy ineficiente de cargar imágenes ya que lo que se está haciendo es cargar la imagen cada vez que se redibuje (repaint()). public void paint(Graphics g) { BufferedImage imagenSprite = loadImage("res/imagenSprite.gif"); g.drawImage(imagenSprite, x, y,this); } Se podría pensar que lo ideal es cargar la imagen en el constructor de la clase, pero si el juego fuese un applet y se tuviese una gran cantidad de imágenes de distintos sprites y niveles, cuando el usuario descargase las clases Java del juego, se quedaría esperando mucho tiempo a que se efectuase dicha descarga, pudiendo darse el caso de que muchas de esas imágenes descargadas nunca llegasen a utilizarse porque el jugador no alcance el nivel en que aparecen. Por este motivo se suele utilizar una técnica llamada carga tardía, que consiste en cargar la imagen una única vez, pero aplazar este instante hasta el momento en que realmente se hace necesario visualizar esa imagen. Un ejemplo podría ser el siguiente: public BufferedImage imagenSprite = null public void paint(Graphics g) { if (imagenSprite==null) imagenSprite = loadImage("res/imagenSprite.gif"); g.drawImage(imagenSprite, x, y,this); } 20 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Aun así, comprobar en todas las posibles situaciones donde pueda surgir la necesidad de utilizar una imagen, si está cargada o no, es ineficiente. Para evitar esta situación lo ideal es utilizar una HashMap. [www_06] Una HashMap (tabla hash) es una es una colección de listas enlazadas. Nos permite guardar pares clave-valor de distintos tipos, y luego recuperar esos datos utilizando la clave. [www_06] Se podrían tener estos métodos dentro de cada sprite u objeto del juego para que él mismo se autoabasteciese, pero eso sería ineficiente puesto que podría realizar múltiples cargas de la misma imagen, mientras que de esta manera sólo se carga una imagen una vez, comprobando antes de cargarla si ya está cargada, y manteniendo actualizada la caché de gráficos. 2.4.3. Doble Buffering Al mostrar gráficos con las técnicas estándar, las imágenes suelen aparecer a trozos o con parpadeo. El parpadeo de una imagen en la pantalla ocurre porque se está pintando directamente sobre la pantalla de manera constante. Durante unos instantes el ojo está viendo la pantalla recién borrada en la que todavía no se ha pintado ningún objeto. Un buffer es simplemente un área fuera de memoria fuera de pantalla usada para dibujar. Las aplicaciones Java permiten que los programas dibujen en memoria, para luego ir mostrando la imagen completa de forma suave. Este es el proceso conocido como doblebuffering, y tiene dos ventajas fundamentales sobre el proceso normal de pintar o dibujar directamente sobre la pantalla. [Brackeen2004] 21 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Primera, el usuario ve aparecer de golpe la imagen en la pantalla. Mientras el usuario está viendo esa imagen, el programa está generando la siguiente para mostrarla a continuación, y así una y otra vez. Segunda, la técnica de doble-buffering involucra un objeto Image, que se puede pasar directamente a varios métodos. Esta capacidad para manipular objetos Image permite descomponer las rutinas de dibujo en componentes funcionales, en lugar de un enorme método paint(). Por tanto se puede tener en memoria una imagen del mismo tamaño que el escenario en la cual se hacen todas las operaciones gráficas. Una vez que el escenario ha sido pintado “fuera de la pantalla” (off-screen), esa imagen en memoria es volcada encima de la ventana. La técnica del doble buffer es tan extendida que en el JDK 1.4 se incluyó un mecanismo automático para realizar este tipo de operaciones, permitiendo además que la visualización del buffer se hiciese mediante mecanismos más acelerados dependientes de la plataforma (como por ejemplo, mover el puntero de memoria de la tarjeta gráfica que indica dónde comienza el buffer de vídeo en lugar de copiar ese buffer a otra zona de memoria). [Brackeen2004] 2.4.4. Page flipping Dibujar usando double buffering dura el tiempo que se tarda en copiar la imagen del buffer a la pantalla. Con una resolución de 800x600 y una profundidad de 16 bits se tendrían 800x600x2 bytes, o 938KB. Esto es cercano al megabyte de memoria que tiene que ser arrastrado a una velocidad cercana a los 30 frames por segundo. Aunque copiar esa cantidad de memoria es una tarea suficientemente rápida para muchos juegos, se asume el riesgo de actualizar el buffer sin haber terminado de copiar dicho buffer a la pantalla. 22 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Para evitar esto se utiliza una técnica conocida como Page Flipping, en la que se usan dos buffers, uno como “back buffer” o buffer de dibujo, y otro como “display buffer” o buffer visible. [Brackeen2004] Se usa un puntero de muestra que apunta al buffer que está siendo mostrado. Este puntero de muestra puede ser cambiado en la mayoría de los sistemas modernos. Cuando se termina de dibujar en el buffer de dibujo, el puntero de muestra puede cambiarse desde el buffer visible actual, al buffer de dibujo, con lo que en el instante en que el puntero cambia, el buffer visible pasa instantáneamente a ser el buffer de dibujo y viceversa. [Brackeen2004] Por supuesto, cambiar la dirección a la que apunta un puntero es mucho más rápido que copiar un enorme bloque de memoria a la pantalla con lo que se tiene una gran mejora. La frecuencia de refresco de un monitor está alrededor de los 75Hz más o menos, lo que significa que el monitor es refrescado 75 veces por segundo. Podría ocurrir que el buffer visible fuese copiado en mitad de un refresco de pantalla con lo que parte del antiguo buffer se mostraría simultáneamente con el nuevo. Este efecto, similar al parpadeo, se conoce como “tearing”. Ocurre tan rápido que podría no notarse, pero cuando se nota, parece como lágrimas en algún lugar de la pantalla. Es posible llevar a cabo el cambio de página en el momento exacto, justo cuando el monitor está apunto de ser refrescado. La clase que permite implementar este tipo de operación se llama BufferStrategy y se encuentra en el paquete java.awt.image. 2.4.5. Animación: Fotogramas o Frames Existe un tipo de animación que sigue el estilo de los dibujos animados (cartoon). Este tipo de animación es mostrada como una secuencia de imágenes, una tras otra, que es como los dibujos animados funcionan. 23 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Las imágenes en una animación pueden ser referidas como “frames”. Cada frame se muestra durante cierto periodo de tiempo, aunque no necesariamente tienen que ser mostrados el mismo periodo de tiempo. La misma imagen puede ser mostrada más de una vez. Además, cuantos más fotogramas o frames hay, más suave es la animación del propio objeto. Las animaciones también pueden formar parte de un bucle indefinido en lugar de ejecutarse una vez. [Brackeen2004] El bucle de animación (animation loop) sigue los siguientes pasos: 1.- Actualiza la animación 2.- Dibuja en la pantalla 3.- Opcionalmente duerme durante un cierto periodo de tiempo 4.- Vuelve al paso 1. En código Java, Un bucle de animación podría ser algo así: while (true){ // Actualizar cualquier animación actualizarAnimacion(); // Dibujar en la pantalla Graphics g = screen.getFullScreenWindow().getGraphics(); draw(g); g.dispose(); //hacer una pausa try{ Thread.sleep(20); } catch (InterruptedException ex){} } 24 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Obviamente en un ejemplo real, el bucle de animación no debería estar repitiendo ciclos indefinidamente, con lo que faltaría una condición de salida del bucle. Para implementar una animación, se necesita una vía para actualizarla pantalla de una manera eficiente. … 2.4.6. Transformaciones Afines Un efecto gráfico interesante a la hora de desarrollar juegos en dos dimensiones en Java, es rotar, trasladar o cambiar la escala de una imagen. A esto se le conoce como Image Transform o transformación de la imagen. Translaciones, rotaciones y escalamientos son transformaciones afines. [Brackeen2004] Para conseguir todas estas transformaciones se dispone de la clase AfineTransform. Esta clase transforma los ejes y el origen del sistema de coordenadas en lugar de las formas 2D en él referenciadas. En este sentido rasterizar una forma 2D antes y después de una transformación afín produce resultados gráficos distintos. La clase Graphics2D es donde la transformación realmente se sitúa. Existe un método especial drawImage() en esta clase que puede tomar una AffineTransform como parámetro. [Knudsen1999] 2.4.7. Gestión de eventos Los eventos sólo los reciben aquellos componentes que están interesados en ellos. Para conseguir esto, se implementa un sistema de “clases escucha” (listeners). Una clase de escucha es una clase que implementa una interfaz de escucha genérico de un tipo de evento concreto y que se registra con el objeto productor de eventos. 25 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Por cada tipo de evento existe una interfaz de escucha para los objetos interesados en dicho evento. El inconveniente de implementar la interfaz es que, necesariamente, se tienen que sobrecargar todos y cada uno de los métodos de ella. Para evitar este inconveniente, existen los adaptadores (Adapters), que son unas clases que implementan estos interfaces con todos los métodos vacíos. Por cada interfaz existe un adaptador. [www_08] En todo programa que tenga un manejador de eventos se pueden ver las siguientes porciones de código: 1.- En la declaración de la clase de la clase escucha, la declaración de que dicha clase implementa una interfaz de escucha: public class MiClase implements KeyListener{ 2.- La implementación de los métodos del interfaz de escucha. 2.4.8. Scroll Muchos juegos ofrecen un aspecto visual muy efectista gracias a un fondo con scroll sobre el que se desarrolla la acción. Este efecto se consigue de forma sencilla si simplemente en lugar de borrar la pantalla con un color sólido se rellena con una textura. El scroll se puede alcanzar modificando el rectángulo que actúa como ancla de la textura, ya que si se aumenta la coordenada Y [(0, 0, 256, 256), (0, 20, 256, 256)], es decir, aumentamos la coordenada Y en 20 unidades, el efecto es como si todo el decorado se hubiese desplazado hacia abajo 20 unidades. Por supuesto, dado que se desea un desplazamiento suave, se debe aumentar la coordenada en un píxel cada vez. Esto se puede realizar con una única textura, o con varias texturas manteniendo un vector de imágenes almacenado en memoria y en vez de actualizar los límites superior e inferior de una única textura, actualizando los límites de dos texturas. Se han de tener siempre las 26 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D dos texturas en la pantalla pero comprobando que cuando el límite superior de una de ellas llegue al principio de la pantalla, entra la siguiente textura a continuación, y cuando llegue a su fin se va fuera de la pantalla. Para el caso de los juegos basados en baldosas, tiled-based games, se tiene otro tipo de scroll. La técnica consiste en descomponer un mapa de bits en pequeños objetos gráficos y a continuación en un mapa del gráfico. Figura 3 - Scroll basado en baldosas descomponiendo un mapa de bits en pequeños objetos gráficos, creando un mapa del gráfico. Si la imagen fuese mucho mayor que el área de visión, todo lo que se tendría que hacer es recrear el mapa de bits al tamaño del área de visión y dibujar una columna (o una fila dependiendo del sentido del scroll) de baldosas adicionales. Una vez que la imagen se ha desplazado una cantidad píxels, se borraría la primera columna del mapa de bits (o la primera fila dependiendo del sentido) y se redibujaría otra en el lado opuesto del mapa de bits. Esto implica que se redibuja una pequeña porción de la imagen en cada actualización. 2.4.9. Detección de colisiones Al realizar un juego es bastante habitual la necesidad de detectar las colisiones entre los distintos sprites. Este proceso debe ser tan rápido como sea posible ya que normalmente deberá ejecutarse bastantes veces en un tiempo muy corto, como un frame. 27 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Un acercamiento habitual es comprobar si los rectangulos que forman el sprite se intersectan. La clase Rectangle de Java incorpora el método intersects() que permite comprobar si un rectángulo intersecta con otro. Para ello habría que implementar un método que nos devolviese el rectángulo que envuelve el sprite en coordenadas absolutas sobre la pantalla. Esto conlleva a una gran falta de precisión si la imagen significativa del sprite no cubre todo el rectángulo, es decir tienen una parte transparente. En esos casos cabe la posibilidad de que lo que se este superponiendo sea la parte transparente de cada uno de los sprites, lo que no implicaría ninguna colisión. [www_07] Por tanto se puede buscar una mejora a la técnica anterior. El primer paso es obtener los Rectangle que forman cada uno de los sprites. Se supone que sprite1 y sprite2 son los objetos que modelan los sprites y que ofrecen el método: Rectangle getRectangle(); Que permite obtener el rectangulo que ocupa el sprite y BufferedImage getImagen(); Que permite obtener la imagen del sprite con partes transparentes. Rectangle r1=sprite1.getRectangle(); Rectangle r2=sprite2.getRectangle(); Ahora se comprobaría si los rectángulos se solapan: r1.intersect(r2); Esta función devuelve verdadero si hay superposición. Si devuelve falso la rutina habrá terminado ya que no hay colisión. En el caso de que la función devuelva verdadero, implica 28 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D que los rectángulos se sobreponen pero aun no se sabe si lo hacen las zonas no transparentes del mismo. [www_07] Para cada uno de los dos Rectangle se obtiene el Rectangle que intercepta con el otro. Rectangle ir1=r1.intersection(r2); Rectangle ir2=r2.intersection(r1); Ahora se obtienen las zonas afectadas de cada uno de los rectángulos. int dx=ir1.x-r1.x; int dy=ir1.y-r1.y; ir1.setLocation(0,0); ir1.translate(dx,dy); dx=ir2.x-r2.x; dy=ir2.y-r2.y; ir2.setLocation(0,0); ir2.translate(dx,dy); Ya se tienen los Rectangle ir1,ir2 del mismo tamaño y apuntan a las zonas de la imagen superpuestas de cada uno de los sprites. Se obtienen los Raster del canal alpha de cada sprite. WritableRaster ras1=sprite1.getImagen().getAlphaRaster(); WritableRaster ras2=sprite2.getImagen().getAlphaRaster(); Y a continuación se obtienen los int correspondientes a todos los pixels superpuestos de cada sprite. int[] dat1=(int[]) ras1.getDataElements(ir1.x,ir1.y,ir1.width,ir1.height,null); int[] dat2=(int[]) ras2.getDataElements(ir2.x,ir2.y,ir2.width,ir2.height,null); 29 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Ya se pueden recorrer los vectores y comprobar si en algún caso se cumple que en ambos vectores el elemento correspondiente al mismo índice es distinto de 0, en cuyo caso existe una colisión real. Si no se cumple para ninguna pareja de elementos significa que no existe colisión. [www_07] int size=dat1.length; boolean hayColision=false; for(int nn=0;nn<size; nn++) if((dat1[nn]!=0)&&(dat2[nn]!=0)) { haycolision=true; break; } 2.4.10. Patrones de movimiento. Algoritmo Estándar Los patrones de movimiento es una manera simple de crear la ilusión de comportamiento inteligente. Básicamente, los caracteres se mueven de acuerdo a algún patrón predefinido que simulan actuaciones más complejas. El algoritmo de patrones de movimiento estándar usa listas de vectores de instrucciones codificadas o instrucciones de control, que le indican al carácter cómo se debe mover a cada paso en el bucle del juego. El vector es indexado cada vez a través del bucle principal para que un nuevo conjunto de instrucciones sea procesado cada vez. [Bourg2004] Ejemplo de un típico conjunto de instrucciones de control: ControlData{ double turnRight; double turnLeft; double stepFoward; double stepBackward; }; 30 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D En este ejemplo, turnRight y turnLeft podrían contener el número de grados para torcer a la derecha o a la izquierda, o si fuese un juego tipo Tile (baldosas), en el que el número de direcciones en el que el carácter podría avanzar está limitado, turnRight y trunLeft podría significar torcer a la derecha o a la izquierda un incremento. stepFoward y stepBackward podrían contener el número de unidades de distancia, o baldosas, que se avanzaría adelante o atrás. La estructura de control podría también tener otras instrucciones como armas de fuego, lanzamiento de bombas, no hacer nada, acelerar, decelerar, entre muchas otras acciones apropiadas para el juego. Los datos usados para inicializar estos vectores de patrones pueden ser cargados desde un fichero de datos o pueden ser codificados dentro del código del juego, todo dependerá del estilo de programación y del los requerimientos del juego. [Bourg2004] La inicialización de un vector de patrones podría ser algo así: Pattern[0].turnRight = 0; Pattern[1].turnRight = 0; Pattern[0].turnLeft = 0; Pattern[1].turnLeft = 10; Pattern[0].stepFoward = 2; Pattern[1].stepFoward = 0; Pattern[0].stepBackward = 0; Pattern[1].stepBackward = 0; ... Para procesar este patrón, se necesitará mantener e incrementar un índice al vector de patrones, cada vez en el bucle principal del juego. Más adelante, cada vez a través del bucle, las instrucciones de control correspondientes al índice actual en el vector de patrones deben ser leídas y ejecutadas. Void GameLoop(void){ ... 31 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Oject.Orientation += Pattern[currentIndex].turnRight; Oject.Orientation -= Pattern[currentIndex].turnLeft; Object.x += Pattern[currentIndex].stepForward; Object.x -= Pattern[currentIndex].stepBackward; ... } Como se puede observar, el algoritmo es bastante simple. Por supuesto, los detalles de implementación variarán dependiendo de la estructura de cada juego. 2.4.11. Persecución y Evasión básicas El algoritmo más simple de persecución supone corregir las coordenadas del depredador con respecto a las coordenadas de la presa, de manera que se reduzca la distancia entre sus posiciones. Este es un método muy común para implementar persecución y evasión básicas. (En este método, la evasión es virtualmente lo opuesto a la persecución, por lo que en vez de intentar decrementar la distancia entre las coordenadas del depredador y la presa, se puede intentar incrementarlas). [Bourg2004] En código, el método sería algo parecido a lo que se muestra a continuación: if (predatorX > preyX) predatorX--; else if (predatorX < preyX) predatorX++; if (predatorY > preyY) predatorY--; else if (predatorY < preyY) predatorY++; En este ejemplo, la presa está localizada en las coordenadas preyX y preyY, mientras que el predador está localizado en las coordenadas predatorX y predatorY. 32 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Durante cada ciclo a través del bucle principal del juego (game loop), las coordenadas del depredador son chequeadas frente a las de la presa. Si las coordenada x del depredador es mayor que la coordenada x de la presa, dicha coordenada se decrementa, acercándolo a la posición x de la presa, y viceversa. El resultado final es que el depredador se va acercando cada vez más a la presa a cada ciclo del bucle principal. [Bourg2004] Usando la misma metodología se puede implementar la evasión: if (preyX > predatorX) preyX++; else if (preyX < predatorX) preyX--; if (preyY > predatorY) preyY++; else if (preyY < predatorY) predatorY--; En un Tiled-based game o juego basado en baldosas, un algoritmo básico de persecución sería el siguiente: if (predatorCol > preyCol) predatorCol--; else if (predatorCol < preyCol) predatorCol++; if (predatorRow > preyRow) predatorRow--; else if (predatorRow < preyRow) predatorRow++; El problema con estas implementaciones tan básicas es que con frecuencia la persecución o la evasión parecen muy mecánicas ya que no se persigue a la presa en línea recta que es la dirección más corta. [Bourg2004] 33 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 2.4.12. Inteligencia Artificial en juegos Existen múltiples técnicas relacionadas con la inteligencia artificial (IA) y que son ampliamente utilizadas en programación de juegos. El algoritmo estándar o las técnicas básicas de persecución y evasión serían una forma de simular comportamientos inteligentes en un juego. [www_05] Hay, al menos, tres tendencias dentro del campo de la inteligencia artificial. Redes neuronales Algoritmos de búsqueda Sistemas basados en conocimiento Son tres enfoques diferentes que tratan de buscar un fin común. No hay un enfoque mejor que los demás, la elección de uno u otro depende de la aplicación. [www_05] Una red neuronal trata de simular el funcionamiento del cerebro humano. El elemento básico de una red neuronal es la neurona. En una red neuronal, un conjunto de neuronas trabajan al unísono para resolver un problema. Al igual que un niño tiene que aprender al nacer, una red de neuronas artificial tiene que ser entrenada para poder realizar su cometido. Este aprendizaje puede ser supervisado o no supervisado, dependiendo si hace falta intervención humana para entrenar a la red de neuronas. Este entrenamiento se realiza normalmente mediante ejemplos. La aplicación de las redes neuronales es efectiva en campos en los que no existen algoritmos concretos que resuelvan un problema o sean demasiado complejos de computar. Donde más se aplican es en problemas de reconocimiento de patrones y pronósticos. El segundo enfoque es el de los algoritmos de búsqueda. Es necesario un conocimiento razonable sobre estructuras de datos como árboles y grafos. Una de las aplicaciones interesantes, sobre todo para videojuegos, es la búsqueda de caminos (pathfinding). Este 34 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D algoritmo de búsqueda en grafos es llamado A*. El algoritmo A* además de encontrar un nodo objetivo, se asegura que es el camino más corto. [www_05] Por último, los sistemas basados en reglas se sirven de conjuntos de reglas y hechos. Los hechos son informaciones relativas al problema y a su dominio de conocimiento. Las reglas son aplicables a los elementos del universo y permiten llegar a deducciones simples. Una máquina de estados está compuesta por una serie de estados y una serie de reglas que indican en qué casos se pasa de un estado a otro. Estas máquinas de estados nos permitirían modelar comportamientos complejos en los personajes y elementos de un juego. Figura 4 - Posibles cambios de estado de un objeto que se desplaza por la pantalla 35 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) >9 Jogo de computador2D " :7 En este capítulo se describe y explica la práctica realizada, su código y agrupamiento lógico. >9,9 6 El hecho ya comentado de que cualquier aplicación Java pueda ejecutarse en cualquier plataforma de ejecución para la que exista una implementación de la JVM (Java Virtual Machine), y que el lenguaje Java sea un lenguaje de programación Orientado a Objetos, hacían de éste el lenguaje idóneo para el desarrollo del juego. El primer paso en cualquier programa de java es la clase principal con el punto de entrada al programa. La clase principal encargada de gestionar todo el programa, creando, manejando y destruyendo todas las instancias de clase, es la Clase Jogo2D. Dicha clase contendrá la función main(). La clase Jogo2D inicializa el programa y todos los objetos que usa el programa, y a continuación llama a la función Game() que no es más que un bucle que se ejecuta hasta que la partida termine, caso que se da cuando ocurra alguna condición de salida. Dentro de ese bucle se realizan todos los cálculos necesarios y se diseña en pantalla las imágenes que se van a mostrar. Aprovechando las características de la POO se pudieron clasificar todos los entes que aparecían en el juego en objetos, y a un nivel superior, en jerarquías de clases. Objetos obvios que hay que representar serían todos aquellos que aparecen en la pantalla, es decir las imágenes. Por tanto una primera clase de la cual heredarían todos los objetos que apareciesen en la pantalla sería la clase Sprite. De ella heredarían otras clases como Jugador, Enemigo, Tiros, etc. 36 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Por lo tanto ya se tiene la clase principal Jogo2D con la función main(), que controla todo el programa, y una jerarquía de clases que define y representa todos los objetos con vida en la pantalla. Más clases necesarias son aquellas que gestionan el acceso a los gráficos y el sonido: GraficosCache y SonidoCache, de actualizar y controlar la sucesión de imágenes de fondo del escenario a implementar, como sería la clase Scroll, otra clase para capturar dichas imágenes de fondo y por último una interfaz que sería Escenario, para que pueda ser accedida desde cualquier clase que lo desee y permitir así que distintas jerarquías presenten características comunes, puesto que en Java no se permite la herencia múltiple. Para la creación del juego de aviones 2D ha sido preciso la construcción de 15 clases: Clase Bomba Clase Comportamiento Clase Enemigo Clase Escenario Clase Fondos Clase GraficosCache Clase Jogo2D Clase Jugador Clase PuntosExtra Clase RecursosCache Clase Scroller Clase SonidoCache Clase Sprite Clase Tiros Clase TirosEnemigo Esta división hecha en clases se puede hacer a un nivel más alto de abstracción, agrupando distintas clases en bloques de clases dependiendo de su funcionalidad. 37 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) >9 9 Jogo de computador2D B C Existen 5 grandes bloques bien diferenciados: Un primer bloque compuesto por la clase principal Jogo2D y la clase Escenario. La primera controla y coordina todo el funcionamiento del juego, y la segunda hace de interfaz para simular la herencia múltiple, que no está permitida en Java, con lo que distintas clases podrán acceder a funciones y características comunes. Un segundo bloque sería el compuesto por todos los sprites que aparecen en la pantalla. Para ello se tiene la superclase Sprite de la que heredan 6 clases más (Jugador, Tiros, Enemigos…). Otro bloque lo compondrían las clases Fondo y Scroll, que son las encargadas de capturar las distintas imágenes que compondrán los escenarios y de producir el efecto de scroll o desplazamiento de la imagen en pantalla mediante la mudanza de imágenes y sus coordenadas de diseño en la pantalla. El siguiente bloque abarca todo lo referente a la captura de gráficos y sonidos. Está compuesto por las clases GraficosCache y SonidosCache, la cuales heredan un comportamiento común de la clase RecursosCache. Para finalizar una de las clases más importantes y que compone por sí sola un bloque, es la clase Comportamiento, encargada de controlar todas las trayectorias de los sprites por la pantalla. 38 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D >9>9 Muchos de los conceptos orientados a objetos de Java son heredados de C++, el lenguaje en el que está basado, pero también toma prestados muchos conceptos de otros lenguajes orientados a objetos. Todo en Java son clases. Una clase en Java encapsula un conjunto de datos y un conjunto de operaciones. Los valores son representados por los atributos de la clase, y las operaciones por los métodos de la clase. En java una definición de una clase introduce un nuevo tipo. Las instancias de ese tipo se llaman Objetos. [Coelho2003]. 3.3.1. Jerarquía de Clases Figura 5 - Jerarquía de Clases 39 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D 3.3.2. Class Jogo2D Un juego básicamente de forma continua está haciendo lo siguiente: Actualizar el “estado del mundo” o el “escenario” (realizarCalculos ()) Si es preciso, refrescar la pantalla (diseñar ()) Volver a actualizar el escenario. Y eso es lo que hace la rutina principal del juego: game(), actualizar las coordenadas de los fondos que componen los escenarios, y actualizar la pantalla, todo ello dentro de un bucle controlado por un contador de tiempo. Tenemos el método ini() que inicializa el programa y el bucle principal estará en una rutina game(). El método que pinta la pantalla es el método paint(), que siempre realizará dos funciones independientes dentro de él: realizarCalculos() y desenhar(). En el primer paso (realizarCalculos()) se efectúan todos los cálculos necesarios para actualizar el estado del juego. Por supuesto todo esto no se hace en la misma rutina, pero sí se puede pensar que constituye una etapa claramente diferenciada de la siguiente, en la que, si ha habido cambios en lo que el jugador está viendo, entonces se dibuja de nuevo: Es donde se cambian y calculan todas las trayectorias de los enemigos, de los disparos, bombas y en definitiva donde se actualiza la posición de todos los sprites que aparecen en pantalla. Se efectúan las acciones del jugador (movimientos por la pantalla). Se controla la aparición o desaparición de nuevos elementos en el juego (bolas de puntos extra, nuevos disparos, bombas…). Se controla si hay un cambio de fase y si se ha terminado el juego. Se chequean todas las colisiones entre los distintos sprites del juego. 40 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D La segunda parte del diseño se encarga de pintar todo lo que vemos en pantalla: La pantalla inicial que hay al principio de cada fase. La barra de estado del juego, que está compuesta por la puntuación del jugador, la vida que le queda y el número de bombas del que dispone. Los Escenarios del juego. Todos los sprites del juego. Los mensajes de fin de partida, fin del juego, fin de fase… También se lleva a cabo en esta clase la gestión de los eventos para controlar el teclado y los mandos del juego. 3.3.3. Clase GraficosCache Esta clase es la parte del programa independiente de las demás que se dedica gestionar una “caché de gráficos”. Su única interacción es cargar y proporcionar gráficos a quien lo necesite. Ambos métodos son heredados de la clase RecursosCache. Además posee un método llamado createCompatible(), que permite usar imágenes en formato compatible. Una imagen compatible es una imagen en memoria que tiene las mismas características (o al menos muy similares) al modo de vídeo nativo que se está mostrando en ese momento, en términos de bits por píxel, transparencia, etc. Las imágenes compatibles son mucho más rápidas para dibujar que cualquier otro formato. 41 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 3.3.4. Clase SonidoCache Los sonidos son un recurso más para el programa, de forma que lo que necesitamos es una clase que gestione una “caché de gráficos” de forma muy similar a la caché de sprites que gestiona la clase GraficosCache. Será la encargada de localizar y cargar los archivos de sonido. Su código es muy similar a GraficosCache, pero devuelve AudioClips en lugar de BufferedImages. También proporciona dos métodos adicionales que son playSound(), para reproducir un sonido una única vez y loopSound() para reproducir un sonido cíclicamente. 3.3.5. Clase RecursosCache Dado que ambas clases, GraficosCache y SonidoCache, comparten gran parte de su funcionalidad, se generaliza el comportamiento de ambas en la clase RecursosCache. Se tiene la rutina cargarRecurso(), que recibirá como parámetro un nombre de un sprite o sonido que se necesite y devolverá el recurso (imagen o sonido), cargándolo si es necesario. Puesto que puede haber muchas imágenes o sonidos, la rutina tendrá que recordar qué recursos están cargados y cuáles no. Para ello nada mejor que una HashMap que asocie el nombre de cada sprite o sonido con su imagen o sonido en memoria 3.3.6. Clase Escenario El escenario es el que de alguna forma coordina las cosas que ocurren en el juego, sabe cuántos enemigos hay, cuantas balas, en qué nivel se está, etc... Contiene las constantes generales del juego (largura, altura, altura_juego, velocidad) y métodos para acceder a los gráficos, sonidos, al jugador y para añadir un sprite al vector de sprites desde cualquier localización en el juego. 42 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Java no permite la herencia múltiple, por lo que una clase tan sólo puede heredar de una única clase. Existen situaciones en las que sería deseable que clases de varias jerarquías presenten características, comportamientos comunes, de ahí la necesidad de las interfaces, que no son más que una plantilla con métodos y atributos que será usada por clases distintas a la vez. La clase Escenario es una interfaz. Si la interfaz presenta el modificador de acceso public, podrá ser accedida desde cualquier clase o interfaz en cualquier paquete, como es el caso de Escenario. Si no, tendrá acceso por defecto, es decir, será visible para las clases e interfaces de su paquete. Una interfaz puede declarar en su cuerpo métodos abstractos y/o variables constantes. Todos los métodos declarados en una interfaz son implícitamente públicos y abstractos y todas las variables declaradas en una interfaz son implícitamente públicas, estáticas y finales. Una interfaz proporciona la descripción de un comportamiento común a un conjunto de clases. Son las clases las encargadas de implementar dicho comportamiento, a lo que se denomina implementación de una interfaz. 3.3.7. Clase Sprite Ya se ha comentado en el estado del conocimiento qué es un sprite y cuáles sus características principales. Existen ciertas características comunes a todos los sprites del juego por lo que esta clase será capaz de encapsular prácticamente cualquier cosa “activa” o “viva” sobre el escenario. Los principales atributos de esta clase son todos aquellos que permitirán situar a un sprite en la pantalla y realizar cualquier tipo de trayectoria: posX, posY: Posición vx, vy: del objeto sobre la pantalla. velocidad de desplazamiento en cada coordenada 43 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) ox, oy, cx, cy: Jogo de computador2D origen del objeto y centro de trayectorias curvilíneas. angulo, radio, tipoTrayectoria: ángulo, radio y tipo de trayectoria. Largura, altura: tamaño del objeto. nombresSprites: vector de nombres de imágenes que identifiquen al objeto sobre la pantalla para hacer animación. Dado que los fotogramas es algo que queremos que tenga cualquier objeto del juego (disparos, nave, enemigos, colisiones…) se añade esa funcionalidad a la clase Sprite. El atributo nombresSprites es una matriz de nombres de gráficos (los distintos fotogramas que dotarán de movimiento a nuestro objeto) en lugar de un único gráfico. Adicionalmente, el método actuar() se encarga de incrementar el número de fotograma cada vez. Se rellena la matriz de sprites con las distintas imágenes y cada vez que se pinta aumenta el índice del vector (frame actual) para capturar y pintar la imagen siguiente. Cuando el índice llegase al final del vector se volvería a inicializar con el primer elemento del vector. 3.3.8. Clase Enemigo El enemigo va a ser cualquier objeto enemigo, que en este caso serán los aviones contra los que se enfrente el jugador, pero se podría ampliar su funcionalidad a cualquier tipo de objeto, ya que en esencia serían lo mismo con distintas velocidades y posiciones. Tienen una posición sobre la pantalla Tienen un tamaño (una anchura y una altura) Tienen una trayectoria Ejecutan un comportamiento, una acción. Entre sus métodos cabe reseñar el método expandir(), que genera un objeto de tipo PuntosExtra cuando un enemigo muere y tiene su atributo booleano puntosExtra a “verdadero”. Dicho atributo ha sido puesto a verdadero de forma aleatoria por lo que no todos los enemigos crean una instancia de PuntosExtra al desaparecer. 44 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 3.3.9. Clase Jugador El jugador es un sprite que además puede ser controlado por el usuario mediante el teclado. Se puede desplazar por la pantalla mediante la pulsación de las teclas cursores. Las direcciones toma son los ocho puntos cardinales resultado de las cuatro teclas cursores y la combinación de ellas dos a dos. Siempre que la tecla “espacio” sea pulsada se genera una nueva instancia de Tiros que se añade al vector de sprites del juego. Si la tecla pulsada es la “b” genera una ocho instancia de Bombas en las ocho direcciones de los puntos cardinales. Como atributos a destacar tiene tres sprites llamados cima, esquerda y direita, que serán los que se desplacen cuando los cursores de arriba o abajo, izquierda y derecha sean pulsados. 3.3.10. Clase Tiros Esta clase representa los disparos provenientes del avión del jugador. Por ser los tiros objetos que se mueven por la pantalla también descienden de la clase Sprite. Los disparos aparecen cuando se pulsa la barra espaciadora. Esto provoca un evento que crea un objeto disparo. Los disparos del jugador se mueven en línea recta y desparecen al salir de la pantalla por su borde superior. 3.3.11. Clase Bomba La clase Bomba también desciende de Sprite y será el otro tipo de armamento del que disponga el jugador. Responde a la pulsación de la tecla “B”, y en ese instante se disparan ocho bombas en las ocho direcciones cardinales. 45 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 3.3.12. Clase TirosEnemigo La clase TirosEnemigo, descendiente de Sprite, va a depender del ángulo del enemigo porque esa será la dirección que tome. Por tanto en la creación aleatoria de un tiro por parte de los enemigos se le ha de pasar al objeto TirosEnemigo el ángulo del enemigo y el tipo de trayectoria. Si un objeto de esta clase sale de los límites de la pantalla, se elimina. Las posiciones de los tiros según avanzan se hayan con coordenadas polares, y para pintar dicho tiro se necesita hacer una transformación. 3.3.13. Clase PuntosExtra Descendiente de la clase Sprite, crea un objeto que se moverá por la pantalla y que incrementará en 100 los puntos del jugador si éste es capaz de interceptarlo. Dicho objeto es creado al morir aviones enemigos elegidos aleatoriamente. El sprite de puntos extra aparecerá en la misma posición en la que estaba el avión al desaparecer y será trayectoria, al igual que la de los enemigos, será gestionada por la clase Comportamiento. 3.3.14. Clase Fondos La clase Fondos se encarga de capturar y devolver las imágenes que serán utilizadas como escenarios del juego. También almacena los límites inferior y superior mostrados en pantalla de dichas imágenes para poder desplazarlas por la pantalla y conseguir el efecto de scroll. 3.3.15. Clase Scroller Esta clase mantiene un vector que almacenará todas las imágenes que compondrán los escenarios de cada fase del juego. Por tanto tiene los siguientes atributos vectorFondos, indice, fondos, que indexará el siguiente fondo a aparecer en pantalla, y dos variables de tipo que serán las que estén siempre visibles. 46 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Los métodos más importantes de la clase son los métodos actBufferFondos(), actLimitesFondos(), y update(). actBufferFondos(),Va mostrando imágenes nuevas del vector de fondos. Para ello juega con las dos variables fondo1 y fondo2, que se usan para mostrar dos fondos distintos de forma simultánea en la pantalla, manteniendo el último fondo que se mostraba, y añadiendo el nuevo. 3.3.16. Clase Comportamiento La clase Comportamiento es la encargada de controlar todas las trayectorias de los aviones enemigos y los objetos de puntos extra. Existen dos tipos de trayectorias: trayectorias rectilíneas y trayectorias curvilíneas. Las trayectorias rectilíneas tienen su origen en la posición actual del avión enemigo, y su destino en la posición donde se encontrase el avión del jugador en el momento que se mudó la trayectoria. Las trayectorias curvilíneas pueden ser en los dos sentidos, izquierda o derecha con un centro aleatorio dentro de la pantalla. El cambio entre las posibles trayectorias es aleatorio y con un contador de tiempo también aleatorio. Contiene además una variable contadorGrupo agrupar los aviones enemigos en formación. Por lo tanto aparecerán al inicio, los aviones en diferentes escuadrones con tantos componentes como el atributo contadorGrupo indique. 47 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D A partir del primer cambio de trayectoria en la partida, dichas formaciones se rompen, pero se siguen asignando distintas trayectorias a los grupos a pesar de que estos no puedan mantener la formación inicial. Para conseguir esas formaciones en escuadrón al inicio de cada fase, se establece un origen imaginario de los distintos aviones de forma ordenada, para que vayan entrando en formación. El método que consigue esto es public void establecerOrigen(Sprite s,int i). 48 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) @9 " @9,9 7& Jogo de computador2D :7 ! = Fase1: En una primera fase de desarrollo lo primero que se planteó fue la creación de un programa en java que permitiese que una imagen se trasladase por la pantalla, es decir, un programa que consiguiese el scroll o desplazamiento. Scroll consiste en desplazar una imagen sobre sí misma o bien varias imágenes que den paso las unas a las otras para alcanzar así el efecto de desplazamiento del escenario deseado. Además se crearon otros dos programas. Uno que gestionase los eventos de pulsación de teclas para trasladar un sprite en función de los cursores; y otro que consiguiese animar los sprites. Fase 2: En una segunda fase se centró el estudio en las técnicas de scroll para simular el avance a través de los distintos escenarios. Para conseguir esto se siguieron varias etapas puesto que en un principio se consiguió el scroll pero con una única textura. A continuación se cambió la metodología usada para alcanzar este efecto. En lugar de usar una única imagen que se desplazaba sobre sí misma, se pasó a usar dos imágenes cargadas en memoria. Como el salto se hacía entre dos imágenes distintas, se creyó oportuno tener dos tipos diferenciados de imágenes que nos permitiesen una transición limpia de fondos sin que se notase el salto de imagen; una imagen sería sólo agua y la otra sería tierra pero con agua en la parte superior y en la parte inferior de la imagen para que al pasar de una imagen a otra la transición fuese siempre del tipo agua-agua. 49 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D La filosofía cambió, pero esto permitió con facilidad pasar a un nivel más alto en el que cabían dos opciones: Creación de un vector de imágenes de tierra, siempre guardando las características especiales ya comentadas para ese tipo de imágenes, donde ambos extremos superior e inferior de la imagen son agua, y aparte fuera del vector una imagen que fuese. A continuación bastaba tener una variable aleatoria que indexase el vector para ir alternando las imágenes del vector con la de agua. Obviamente con esta opción tendríamos la gran ventaja de tener escenarios distintos (al menos en la sucesión de imágenes) en cada ejecución del programa ya que la variable que iba eligiendo la siguiente textura era aleatoria, y la desventaja de que siempre tendría que ser mediante una alternancia de agua-tierra-agua. La otra opción, que además ha sido la opción escogida, consistía en tener un vector de texturas ordenado según su secuencia de aparición. Con ello se podría también tener tantos vectores como escenarios creados para después cargar los distintos vectores según fuese interesando (por ejemplo se va cargando un nuevo vector de imágenes en memoria al pasar a una nueva fase en el juego). Escoger la primera opción o la segunda no implicaba grandes variaciones puesto que al final lo más importante era tener conseguida la transición entre dos imágenes. Por lo tanto el bloque encargado de conseguir el efecto scroll dentro del juego estará formado por las clases Scroller y Fondos. La clase Scroller gestiona el fondo que va a aparecer y la clase Fondos va creando los distintos objetos texturas, tantos como fondos distintos haya. Se va modificando la componente, teniendo siempre dos texturas en la pantalla, pero se ha de comprobar siempre que cuando el límite superior de una de ellas llegue al principio de la pantalla ha de entrar la siguiente textura a continuación, y cuando llegue a su fin se va fuera de la pantalla. 50 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Fase 3: Sustitución de hilos o threads cuando se pulsa una tecla para que un sprite se desplace hacia un lado u otro, por la contención de sprites dentro de sprites. Usamos objetos sprites a modo de atributos. Esto se ha usado en la clase jugador. Para las colisiones se hizo mismo, es decir, llamar un vector de colisiones dentro de cada sprite para que se despliegue a modo de fotogramas a la muerte de un objeto. Con esto se evita la utilización de hilos en el programa. La última etapa de construcción, se centró en el control de las trayectorias y desplazamientos de los distintos sprites por la pantalla. Para ello se implementó la clase Comportamiento. @9 9 ? El lenguaje de programación escogido para el desarrollo del juego es el lenguaje Java 1.4.2_10 SDK, por su sencillez y potencia. El Java Runtime Enviroment (JRE) es el entorno de ejecución de Java. Proporciona API.s de Java, la máquina virtual de java y los componentes necesarios para ejecutar aplicaciones y applets escritos en ele lenguaje de programación Java. El Java 2 Software Development Kit (SDK) o kit de Desarrollo de Software en Java, es un “superconjunto” del JRE, conteniendo todos los elementos del JRE, pero además añade las herramientas necesarias para el desarrollo de applets y aplicaciones Java. Durante las primeras semanas, todo el trabajo realizado para el aprendizaje del lenguaje y para la implementación de la parte práctica del proyecto se hizo mediante comandos y en modo consola, utilizando un editor de textos (Ultraedit-32 v10.10b) para escribir los programas, compilando (javac jogo2d.java) y ejecutándolos (java Jogo2D) desde la consola (MSDOS). 51 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Más adelante, y una vez se tuvieron los conceptos básicos del lenguaje asimilados, y la estrategia de implementación de la práctica a seguir, se decidió usar un entorno de desarrollo integrado gráfico para Java llamado Eclipse 3.1. 4.2.1. Java 1.4.2_10 SDK Java es un innovador lenguaje de programación orientada a objetos desarrollado por Sun Microsystems basado en los lenguajes C y C++, que se ha convertido en el lenguaje elegido para los programas que necesiten ser ejecutados en una gran variedad de sistemas de computadores. Por tanto permite crear grandes aplicaciones que corran bajo cualquier sistema operativo independientemente de la máquina en que se ejecuten. [Horton2003] Esto es posible ya que un programa Java no se ejecuta directamente sobre nuestra computadora, sino sobre una hipotética máquina estandarizada llamada Java Virtual Machine o JVM, que es emulada dentro de nuestro computador por un programa. Figura 6 – Ejemplo compiladores para distintas plataformas y de la JVM Un compilador Java convierte el código fuente Java escrito en un programa binario consistente en una serie de Byte codes. Los Byte codes son instrucciones máquina para la Java Virtual Machine. Cuando ejecutamos un programa Java, otro programa llamado Java Interpreter inspecciona y descifra los byte codes para él y se asegura de que no haya fallos y sea seguro ejecutarlos, para ejecutar a continuación las acciones especificadas en los byte codes con la Java Virtual Machine. [Horton2003] 52 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Un intérprete de Java puede ejecutarse solo o ser parte de un navegador Web como Netscape Navigator, Microsoft Internet Explorer o Mozilla Firefox, donde puede ser invocado automáticamente para ejecutar applets en una página Web. Los Applets son pequeños programas incluidos en los navegadores. Esto provee de una amplia gama de posibilidades a la computación Web Como nuestro programa Java consiste en byte codes en vez de instrucciones máquina nativas, está completamente aislado del hardware particular sobre el que se vaya a ejecutar. Cualquier computadora que tenga el entorno java implementado podrá manejar nuestro programa tan bien como cualquier otra, y todo ello gracias a que el Java Interpreter hace de intermediario entre nuestro programa y la capa física de la máquina. En el pasado se penalizaba esta flexibilidad y protección con la velocidad de ejecución (un programa interpretado de Java se ejecutaba a un 10% de la velocidad de otro programa en instrucciones máquina equivalente) pero con las implementaciones actuales de las máquinas Java, la mayoría de la penalización en el desarrollo ha sido eliminada. Otra característica importante del lenguaje Java es que es un lenguaje Orientado a Objetos, haciendo los programas más potentes, fáciles de entender, mantener y de extender en futuras ampliaciones. Otras características notables de éste lenguaje de programación son las siguientes: Es un lenguaje simple, interpretado, distribuido, robusto, seguro, no dependiente de la arquitectura, portable, de alto rendimiento, multitarea y dinámico. Algunas características importantes de los lenguajes Orientados a Objetos y por ende de Java son: 53 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 4.2.2. Abstracción La abstracción puede ser vista como un mecanismo mediante el cual se obvian los detalles irrelevantes para fases posteriores y se enfatizan los relevantes. Esto facilita al programador pensar en el problema a resolver. Existen muchos niveles y tipos distintos de abstracción (abstracción procedural, abstracción de datos…). Los niveles más altos de la abstracción esconden más detalles al contrario que los más bajos. La técnica que se utiliza para obtener la abstracción de datos es la encapsulación de los mismos en una estructura conocida como clase. [Horton2003] Al ser la abstracción una característica más genérica e implícita a toda la Programación Orientada a Objetos, la tenemos presente a lo largo del desarrollo del juego, desde el momento en que usamos una jerarquía de clases, con sus métodos y atributos. 4.2.3. Encapsulación La encapsulación u ocultación de la información, permite definir qué atributos y qué operaciones serán accesibles o visibles para el resto de objetos en el sistema. Se pueden ocultar atributos y operaciones internas de una clase para que no puedan ser accedidos, protegiendo las propiedades de un objeto contra su modificación por quien no tenga derecho a acceder a ellas, solamente los propios métodos internos del objeto pueden acceder a su estado. [Coelho2003] Se evitan accesos indebidos y errores difíciles de detectar y solucionar. Durante el desarrollo del juego aplicamos la encapsulación a la gran mayoría de los atributos o estructuras de datos de las clases al ser declarados todos ellos como privados a la clase. Esto implica que no se puede acceder a ellos directamente, si no a través de métodos que los manejen, siempre y cuando sean definidos. 54 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 4.2.4. Herencia La herencia permite a una clase heredar un comportamiento y estado de otra clase para especializarlo de manera adecuada. De esta forma, se permite reutilizar el estado y comportamiento común de una clase, con lo que tan sólo se tendrá que añadir el comportamiento específico de la clase que hereda. La clase derivada hereda todos los atributos y métodos de la clase o clases base. Además los métodos heredados pueden ser sobrescritos en la clase derivada con nuevos atributos y funciones. Java permite que una clase herede el comportamiento y estado de otra clase utilizando en la declaración de dicha clase la palabra reservada “extends” seguida del identificador de la clase de la cual se hereda. Java tan solo permite heredar de una única clase, lo que se denomina herencia simple. En el desarrollo del juego se han creado dos jerarquías de clases en las que las sublclases herendan las características de la superclase. Por ejemplo tenemos una superclase denominada Sprite que contiene las características comunes, es decir, todos los métodos y atributos comunes a los Sprites que luego son heredados por seis clases que especializan el comportamiento de la superclase sprite. Esas cinco clases que heredan de sprite son: Jugador, Enemigo, Tiros, TirosEnemigo, Bomba y PuntosExtra. 4.2.5. Polimorfismo La idea es que una abstracción dada puede tener muy diferentes formas. El polimorfismo permite tratar distintos tipos de objetos, como si fueran del mismo tipo. [Horton2003] En Java el polimorfismo está siempre activo. Se resuelve en tiempo de ejecución según el parámetro que tenga una función. Para ello el lenguaje proporciona el operador 55 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D “instanceof” que permite conocer el tipo de una referencia en tiempo de ejecución. Se usa el polimorfismo en el Juego mediante la técnica de Casting o molde, consiguiendo con ello que un objeto de la clase Sprite se pueda comportar en un momento dado como un enemigo, un tiro, etc, simplemente amoldando su tipo al de la clase que interesa. 4.2.6. Eclipse 3.1 Eclipse es una plataforma de desarrollo extensible, basada en Java, de código abierto (Open Source), diseñada para que se ejecute en múltiples sistemas operativos. Por si mismo es un marco de trabajo con un conjunto de servicios para la construcción de entornos de desarrollo de programación, con componentes plug-in; es decir, un contenedor sobre el que montar herramientas de desarrollo para cualquier lenguaje sin más que desarrollar los plugins correspondientes. Afortunadamente Eclipse viene con un conjunto estándar de plug-ins entre los que se encuentra el Java Development Tool. [OTI2005] Mientras la mayoría de los usuarios nos conformamos con usar Eclipse como un Integrated Development Environment (IDE) para Java, sus ambiciones no acaban aquí. Eclipse también incluye el Plug-in Development Environment (PDE), que es del mayor interés para desarrolladores de software que quieran extender Eclipse. La plataforma Eclipse está estructurada alrededor del concepto de Extension points. Extension points son sitios en el sistema bien definidos donde otras herramientas (plug-ins) pueden añadir funcionalidad. [OTI2005] 56 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D @9> &A = 4.3.1. Gestión de eventos Un objeto KeyListener es instanciado y registrado para recibir los eventos del teclado KeyPressed(), KeyReleased(). Cuando se pulsa una tecla, el objeto que tenga el foco en ese momento generará un evento Keypressed(). public void keyPressed(KeyEvent e){ jugador.keyPressed(e);} public void keyReleased(KeyEvent e){ jugador.keyReleased(e);} public void keyTyped(KeyEvent e){} La clase Jogo2D recibirá todos los eventos de teclado. Cuando ocurra un evento, la clase primero procesará las teclas que tengan que ver con el juego en general como la tecla “escape” o similares. Cuando se haya determinado que la tecla pulsada no interesa al juego en general, se le pasan los datos de esa tecla Jugador para que actúe como crea oportuno. Esto ocurre cuando se pulsan los cursores, la barra espaciadora o la tecla “B”. public void keyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_ESCAPE) System.exit(0); else jugador.keyPressed(e); } 57 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Se definirán los dos nuevos método en la clase Jugador, keyPressed(...) y keyReleased(...), que serán los encargados de recibir las notificaciones de que ha sido pulsada / soltada una tecla. 4.3.2. Fotogramas Como la animación es una característica que se desea que tengan todos los objetos del juego, se añade esta funcionalidad a la clase Sprite. nombresSprites, es una matriz de nombres de gráficos que identifican la animación del sprite. El método setnombresSprite actualiza la variable nombresSprite, con todos los nombres de las imágenes que se van a utilizar para la animación, y almacena como altura y largura del sprite, la altura y la largura de la imagen mayor: public void setnombresSprite(String [] nombres){ nombresSprites = nombres; largura = 0; altura = 0; for (int i = 0; i < nombres.length; i++ ){ BufferedImage image = grafico.getGrafico(nombresSprites[i]); largura = Math.max(largura,image.getHeight()); altura = Math.max(altura,image.getWidth()); } } Adicionalmente, el método actuar(), que es llamado cada vez que se realizan cálculos en el bucle principal del juego, se encarga de incrementar el número de fotograma cada vez que se actúa: . 58 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D public void actuar(){ t++; if (t % velocidadFrame == 0){ t=0; frameActual = (frameActual + 1) % nombresSprites.length; if(getColision()){ explosao.frameActual=(explosao.frameActual+1); } } } Se utiliza % spriteNames.length para asegurarse que el valor del frame actual siempre esté entre 0 y el número de fotogramas – 1. Además se mantiene dentro de la clase Sprite un contador de tiempos para actualizar el fotograma sólo cuando este contador sea divisible por una cantidad llamada velocidadFrame. Con ello se consigue que la velocidad con la que se animan los sprites sea independiente entre distintos sprites, e independiente de la velocidad del bucle principal. Hay que tener en cuenta que debido a la funcionalidad del método actuar() de la clase sprite, las subclases de sprite no pueden sobrescribir el método sin más, sino que deben llamar al método de la superclase antes de realizar sus propias acciones: super.actuar(); 4.3.3. Transformaciones Afines Se usan las transformaciones afines en los métodos paint() de las clases Enemigo, y tirosEnemigo porque es necesario rotar los sprites conforme la trayectoria y dirección en la que se desplazan. 59 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D Después de realizar una transformación afín, se pinta el sprite y a continuación se deshace la transformación para que no afecte a los ejes de referencia y el sistema de coordenadas de manera global y sólo al sprite en cuestión. Para deshacer la rotación se aplica la transformación con el ángulo inverso. AffineTransform mov; mov=AffineTransform.getRotateInstance(angulo,getPosX(),getPosY()); g.transform(mov); super.paint(g); mov=AffineTransform.getRotateInstance(-angulo,getPosX(),getPosY()); g.transform(mov); 4.3.4. Carga de imágenes Los gráficos que se usen en el juego serán imágenes externas que se irán cargando según se vayan necesitando Para poder tener transparencias sin complicaciones se usarán imágenes en formato .GIF o .PNG. Para cargar la imagen se utliza la clase ImageIO. Las imágenes a cargar están en un directorio llamado “res” (resources) que cuelga del directorio del proyecto. (Un ejemplo podría ser este: C:\Documents and Settings\Administrador\workspace\Jogo2D\res). Se encapsula todo en una jerarquía de clases. Las clases encargadas de la carga de imágenes son la clase GraficosCache y su superclase, RecursosCache. En ella existen tres métodos diferenciados: cargarRecurso(URL url), getGrafico(String nombre) y createCompatible(int width,int height,int transparency). La clase es sencilla y su única motivación es la de dar gráficos a quien los necesite. La clase precisará de un mapa de sprites y el método para cargar una imagen en memoria. 60 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) getGrafico(String nombre), Jogo de computador2D este método recibirá como parámetro de entrada un nombre de sprite que se necesite y devolverá la imagen, cargándola si es necesario. Puesto que puede haber muchas imágenes, la rutina tendrá que recordar qué sprites están cargados y cuáles no. Para ello nada mejor que una HashMap que asocie el nombre de cada sprite con su imagen en memoria. getClass().getClassLoader().getResource(...), permite obtener una URL apuntando a un subdirectorio relativo al sitio del cual fue cargada la clase. 4.3.5. Imágenes Compatibles Una imagen compatible, es una imagen en memoria que tiene las mismas características (o al menos muy similares) al modo de vídeo nativo que se está mostrando en ese momento (en términos de bits por píxel, transparencia, etc.). Las imágenes compatibles son mucho más rápidas de dibujar que cualquier otro formato. Antes de usarlas, lo que se hacía era utilizar el formato que a ImageIO le apeteciese devolver. Se puede optimizar esto de la siguiente forma: Se lee la imagen de disco utilizando ImageIO. Se crea una imagen compatible del mismo tamaño que la imagen leída. Se pinta la imagen recién cargada encima de la imagen compatible. De esta forma se obtiene una “versión compatible” de una imagen situada en el disco: public BufferedImage createCompatible(int width,int height,int transparency){ GraphicsConfiguration gc; gc=GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().get DefaultConfiguration(); BufferedImagecompatible=gc.createCompatibleImage(width,height,transparency); return compatible; } 61 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 4.3.6. Doble Buffering En primer lugar, se decide qué ventana o componente es la que presentará este tipo de comportamiento. Se ha de escoger aquel componente sobre el que se va a pintar. Se llama al método createBufferStrategy(n) de esa ventana, pasando como parámetro el número de buffers que se desean tener. Se crean 2 búferes. Se utliza el método getBufferStrategy() de la ventana para obtener un objeto de tipo BufferStrategy, que representa básicamente una ristra de buffers de memoria, tantos como indique el parámetro que se pasó al método createBufferStrategy(). Para poder pintar encima del buffer de dibujo, se llama al método getDrawGraphics() del objeto BufferStrategy obtenido anteriormente. Cuando se termine de pintar, se llama al método show() del objeto BufferStrategy para indicar que el buffer está listo y que se quiere mostrar el siguiente buffer. ... private BufferStrategy strategy; ... createBufferStrategy(2); strategy = getBufferStrategy(); ... g.drawString(“…”, x, y); strategy.show(); ... 62 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 4.3.7. Colisiones Habrá una colisión cuando los rectángulos que encierran cada sprite se intersecten. Figura 7- Intersección de los rectángulos de dos sprites. Esta comprobación habrá que hacerla para todas las posibles parejas de sprites, y además habrá que hacerla para cada sprite con el jugador. Puesto que ello involucra manejar el vector global de sprites, se lleva a cabo en la clase principal, Jogo2D. La clase Rectangle de Java incorpora el método intersects() que permite comprobar si un rectángulo intersecta con otro. Como se necesita saber los rectángulos que engloban cada sprite, se añade un método getRectangulo() en la clase Sprite que ya devuelva el objeto Rectangle construido, con las dimensiones y coordenadas del sprite. public Rectangle getRectangulo(){ return new Rectangle((int)posX,(int)posY,(int)largura,(int)altura); } Cuando se detecta una colisión se notifica a cada sprite (mediante polimorfismo) que se ha producido una colisión con otro sprite, siendo estos los que deciden qué hacer en consecuencia. Esto significa que aparece un nuevo método en la clase Sprite llamado colision(). Por defecto este método no hace nada, siendo las subclases las responsables de sobreescribirlo como consideren oportuno. La clase Enemigo se actúa cuando la colisión 63 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D es contra un objeto de tipo Tiro, o Bomba, y en tal caso se marca como eliminado el objeto Enemigo. G En la clase principal se crea el método que chequea las colisiones: public void chequearColisiones() { Rectangle rectanguloJugador = jugador.getRectangulo(); for (int i = 0; i < vectorSprites.size(); i++) { Sprite s1 = (Sprite)vectorSprites.get(i); Rectangle r1 = s1.getRectangulo(); if (r1.intersects(rectanguloJugador)) { jugador.colision(s1); s1.colision(jugador); } for (int j = i+1; j < vectorSprites.size(); j++){ Sprite s2 = (Sprite)vectorSprites.get(j); Rectangle r2 = s2.getRectangulo(); if (r1.intersects(r2)) { s1.colision(s2); s2.colision(s1); } } } } @9@9 < ' Como la mayoría de los lenguajes orientados a objetos, Java incluye un conjunto de librerías de clase que proveen de tipos de datos básicos, capacidades de entradas y salidas al sistema y otras funciones de utilidad. Las clases básicas forman parte del JDK (Java Development Kit). Al ser estas librerías escritas en Java, son portables entre plataformas al igual que lo son las aplicaciones escritas en Java. Algunas librerías importantes usadas son: 64 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 4.4.1. javax.swing.JFrame java.lang.Object java.awt.Component java.awt.Container java.awt.Window java.awt.Frame javax.swing.JFrame El paquete Swing es parte de la JFC (Java Foundation Classes) en la plataforma Java. La JFC provee facilidades para ayudar a la gente a construir GUIs. Swing abarca componentes como botones, tablas, marcos, etc... 4.4.2 java.*.BufferedImage java.lang.Object java.awt.Image java.awt.image.BufferedImage La subclase BufferedImage describe una imagen con un buffer de datos de imágenes accesibles. Un BufferedImage está comprendido por un Color Model y un raste de cada datosde imagen. 4.4.3. java.*.BufferStrategy java.lang.Object java.awt.image.BufferStrategy 65 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Usamos esta librería para usar la técnica del doble buffering. Las limitaciones de Hardware y Software determinan cómo un Buffer Strategy puede ser implementado. Un buffer no deja de ser un área de memoria contigua, tanto en una memoria de un dispositivo de vídeo como en un sistema de memoria. 4.4.4. java.util.HashMap java.lang.Object java.util.AbstractMap java.util.HashMap 4.4.5. java.awt.event.KeyEvent java.lang.Object java.util.EventObject java.awt.AWTEvent java.awt.event.ComponentEvent java.awt.event.InputEvent java.awt.event.KeyEvent Un evento que indica cuando una pulsación de tecla ha ocurrido en un componente. 4.4.6. java.awt.Graphics2D java.lang.Object java.awt.Graphics java.awt.Graphics2D 66 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D El API 2D de Java presenta java.awt.Graphics2D, un tipo de objeto Graphics. Graphics2D desciende de la clase Graphics para proporcionar acceso a las características avanzadas de renderizado del API 2D de Java. 67 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) -9 Jogo de computador2D " & 6 D; 6 -9,9 " Para la creación de los sprites de los aviones se ha utilizado un programa generador de aviones de la segunda guerra mundial codificado en javar [Peralta2005]. WW2plane: es una Clase en Java 2D para el diseño gráfico de aviones de la Segunda Guerra Mundial. Sólo tiene la posibilidad de diseñar cazas de motor de una única ala. También es posible el diseño de bombarderos. El diseño de los aviones se efectúa recurriendo a la API gráfica de Java de tal modo que, a través de llamadas a métodos, un usuario de la clase WW2plane podrá construir aviones a su gusto. Todas las características de los aviones están completamente parametrizadas con lo que se puede diseñar cualquier tipo de avión con las características que se deseen, hasta inventados. [Peralta2005] Figura 8 - Logotipo de WW2plane Una vez que se ha decidido qué tipos de aviones son los se quieren, y son diseñados con el programa, se hacen capturas de pantalla mediante el comando ALT + PRINT SCREEN, que 68 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D en vez de capturar toda la pantalla, captura sólo la ventana activa, o sea la ventana del applet con las vista de nuestro avión. Se abre un nuevo archivo con el Adobe Photoshop CS2 y se pega la captura de pantalla. A continuación se crearon 2 macros que permitirán recortar los aviones, quitar el fondo blanco para dejarlo transparente, y reducir el tamaño del avión un 75%. Las 2 macros creadas son separaAviao y reduz75. A partir de ahí sólo restaría guardarlas en formato PNG, para que se mantengan todas las características de las capas, y también la transparencia. Figura 9 - Macros creadas para Photoshop CS2 69 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Se ha diseñando un avión split de la RAF (Royal Air Force) y para los enemigos aviones creados aleatoriamente. Entre ellos se distinguen claramente aviones con emblemas alemanes o japoneses; todo ello creado mediante la manipulación de parámetros de la clase WW2plane. Figura 10 - Secuencia sprites de un avión japonés Figura 11 - Secuencia de sprites de un avión alemán También han sido creados con el Photoshop CS2 otros sprites como las bolas que aparecen aleatoriamente al ser destruidos algunos aviones y que contienen un incremento de puntos extra si son alcanzadas por el jugador. Figura 12 - Secuencia de sprites de puntosExtra 70 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D -9 9 1 Las explosiones han sido diseñadas en el Photoshop CS2 pintando cada frame de la explosión con la herramienta “brush”, y con el modo “disolve”. Figura 13 - Secuencia de sprites de una explosión -9>9 Para la creación de los escenarios se ha optado por dar un aire realista a las texturas de los fondos. Para ello se han ido capturando imágenes sucesivas de distintas zonas del globo terráqueo con el GoogleEarth, un programa que permite visionar cualquier parte del planeta vía satélite a distintas resoluciones dependiendo de la altura. Las imágenes visionadas no son en tiempo real. GoogleEarth tiene una opción que permite guardar las imágenes con distintas resoluciones. A continuación se pasan al Photoshop CS2 para poder manipularlas. La manipulación consiste en conseguir que todas tengan la misma resolución y cortarlas para por el sitio exacto para que no se distinga la frontera entre dos texturas consecutivas a la hora de desplazar los escenarios. Para ello se crea una canvas de 1024 píxels de resolución de anchura y con una longitud igual al total de las imágenes capturadas. Se pone cada imagen en capas distintas y jugando con las máscaras en las fronteras de las imágenes para suavizar el corte, se consigue una imagen general del escenario de una fase. A continuación se seleccionan y copian zonas del escenario para crear texturas independientes con el tamaño y resolución deseado: 1024 x 768 píxels. Se usa la 71 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D herramienta crop del Photoshop para obtener el área a copiar en un nuevo fichero, con las dimensiones exactas. Para finalizar se guardan todas las texturas en formato PNG. -9@9 ( Al principio de cada una de las fases hay una pantalla de presentación con el nombre del juego y la fase. En medio aparece un avión que previamente ha sido procesado con el Photoshop y que hemos obtenido al igual que los sprites, haciendo una captura de pantalla del avión generado por el programa WW2plane. El resto de la pantalla es una textura creada con el Photoshop. Por tanto se han creado para el juego dos texturas, una simulando el efecto de la lluvia por la noche y la otra un efecto de niebla. Para el efecto de noche nublada se escogen dos colores (negro y azul oscuro) como foreground y background de la imagen. A continuación se aplica un filtro: Filter / Render /Clouds, que de forma automática y aleatoria mezcla los dos colores escogidos creando nubes. Este proceso se repite para crear la textura con efecto de niebla, pero escogiendo como colores un gris medio y blanco. A continuación se crean dos nuevas capas en las que se pintan unas gotas de agua con la herramienta brush. Esas gotas se seleccionan y se definen como patrón: Edit / Define Pattern, con lo que se tienen dos patrones. Ahora se rellena una nueva capa con el patrón de la lluvia y se le aplica un efecto blur para alargar las gotas de agua y cambiar su ángulo de inclinación. Filter / Blur / Motion Blur. Repetimos el proceso para el otro patrón de lluvia definido, y con la mezcla de ambos tipos de gotas se obtiene un efecto de lluvia realista para la textura. 72 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) 59 “Cavaleiro dos Céus” Jogo de computador2D & Los objetivos planteados al inicio del proyecto están sobradamente conseguidos. Se ha logrado construir un juego en dos dimensiones tipo arcade, en el que el lenguaje utilizado y aprendido para su creación ha sido el lenguaje Java. En éste, las imágenes se tratan correctamente y se trasladan por la pantalla. Ha sido necesario un estudio pormenorizado del tratamiento de las imágenes por el lenguaje Java, y de las propiedades de distintos formatos de imagen, como las transparencias, para utilizar las más adecuadas. Así como la utilización de programas especializados en el tratamiento de imágenes como Photoshop CS2, para la creación de la parte gráfica del juego. Además se ha conseguido un efecto correcto de desplazamiento de los escenarios pudiendo cargar todas las texturas distintas que se crean oportunas y dando pie esto a tener distintas fases por las que evolucione el juego. Se gestionan distintos eventos como la pulsación de teclas, que permitirán desplazar por la pantalla el avión del jugador, generar nuevos sprites como los disparos y bombas, o escapar del juego pulsando la tecla de escape. Se consigue animar distintos sprites mediante la sucesión de frames o fotogramas. Se profundiza en conocimientos de computación gráfica en 2 dimensiones utilizando la Graphics2D de java (transformaciones afines…) Y en definitiva, se ha profundizado en la filosofía de creación de un juego de computador en dos dimensiones, adquiriendo unas nociones y metodologías para afrontar futuros problemas y retos de este tipo y sucesivos proyectos de creación de juegos en 2D. También adquirimos una base fundamental de conocimientos para dar el salto a la programación de juegos en 3D. 73 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Por lo tanto el juego cumple unos objetivos mínimos de jugabilidad, pero puede ser mejorado y ampliado. Se puede depurar mucho más el código de tal forma que sea más eficiente y eso se refleje a la hora de jugar, ya que se nota el peso de las imágenes si se muestran demasiados sprites en la pantalla. Además las trayectorias de los aviones están limitadas y se puede ampliar a muchas más sin demasiada complicación, creando patrones de trayectorias no aleatorios que embellezcan el juego, creando nuevos tipos de trayectorias, persecuciones, etc. Dotar al juego de una mayor inteligencia artificial de la que posee actualmente, con persecuciones por parte de los aviones enemigos al avión del jugador y evasiones de éste, disparos de los aviones enemigos cuando el avión del jugador estuviese en su ángulo de tiro, etc. Crear escenarios originales con programas de diseño que dotasen de otra visión al juego. Crear un guión y una historia con unos objetivos. Misiones que hiciesen más interesante jugar, dando un sentido y una motivación extra al tener que cumplir estas misiones y al poder situarse dentro de un contexto, ya sea real o imaginado. Para mejorarlo se pueden crear “monstruos” finales, donde al final de cada fase se luchase contra un enemigo más difícil. Podrían ser simplemente aviones más grandes y que en lugar de explotar al recibir un único disparo del jugador, tuviese un nivel de vida que fuese descendiendo conforme recibiese impactos de tiros. Además podría disparar el mismo tipo de bomas que dispara el jugador. En definitiva consistiría en añadir un nivel más alto de dificultad al juego. 74 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Se podrían crear nuevos objetos similares a los objetos de PuntosExtra, que proporcionasen vida al jugador si éste los interceptase. Se podría simular una nueva dimensión creando distintos niveles de altura, simplemente haciendo los sprites más grandes cuando subiesen de altura y por consiguiente más pequeño el fondo puesto que nos alejamos de él, y más pequeños cuando bajasen y más grande el fondo del escenario. Se podría crear una pantalla de presentación de cada nivel con una animación presentando la historia y misión a conseguir en la siguiente fase. También se podrían crear objetos que se desplazasen a la misma velocidad que el escenario para simular que están fijos en la tierra, como cañones antiaéreos, tanques, etc. Además no sería difícil hacer que rotasen hacia el avión del jugador y siempre le disparasen a hacia él. Incluso también se podría animar el fondo del escenario cuando se desplaza. Por lo tanto se observa cómo las mejoras del juego son muchas y que el juego no es perfecto, pero no era objetivo de este proyecto crear un juego profesional con muchos niveles, sprites y gráficos, sino crear una base sólida y adquirir los conocimientos suficientes para poder ampliar esa base sin demasiada complicación. 75 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) E9 7 Jogo de computador2D 7 El proyecto consiste en analizar y estudiar técnicas y algoritmos que lleven a la realización de un juego de computador en dos dimensiones. Como parte práctica que complemente el trabajo de investigación teórico, se ha desarrollado un juego de computador, recurriendo a la tecnología orientada a objetos, y computación gráfica en dos dimensiones; utilizando el lenguaje Java como lenguaje de desarrollo. Los objetivos marcados al inicio fueron: La traslación de imágenes por la pantalla La visualización de sprites. La gestión de eventos. Y la programación multihilo para poder hacer varias acciones en paralelo e independientes unas de otras. Todos los objetivos se han cumplido. Se ha conseguido que las distintas imágenes que forman el escenario se desplacen en vertical por la pantalla para conseguir la sensación de avance por parte del avión del jugador. Además los distintos sprites (avión del jugador, aviones enemigos, bombas, etc) también se desplazan por la pantalla siguiendo distintas trayectorias rectilíneas o curvilíneas aleatorias, o respondiendo a eventos generados por la pulsación de teclas, como es el caso del avión del jugador. También se consigue visualizar los sprites y animarlos. Para ello se dispone de una Hasmap que permite guardar pares nombre-imagen, o clave-valor, y luego recuperar esas imágenes utilizando el nombre. Por tanto mediante un índice que indica cuál es el fotograma actual se va recorriendo el vector de nombres y actualizando el índice a la hora de pintar. 76 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Además se realiza la gestión de eventos de pulsación de teclas por parte del jugador. Se ha utilizado Java2D como lenguaje de desarrollo del juego por ser un Lenguaje Orientado a Objetos, que permite abstracción, encapsulación, herencia y polimorfismo; por su sencillez y potencia, y porque permite crear grandes aplicaciones que corran bajo cualquier sistema operativo, independientemente de la máquina en que se ejecuten, es decir, por su portabilidad. He acertado con la elección del proyecto puesto que compaginaba de alguna forma la base formativa que ya traía del curso que estoy estudiando en España, con todo lo que iba a aprender este año; Realimentando y fortaleciendo conocimientos de unas asignaturas con otras. Por tanto la realización de este proyecto ayuda de forma considerable a asentar los conocimientos adquiridos y a ver el curso de multimedia de una forma global. El descubrimiento del curso de TCM, y la posibilidad de realizar este proyecto ha abierto un nuevo universo con infinitas posibilidades ante mis ojos, donde poder enfocar de alguna manera mi futuro profesional, a pesar de no tener mucho que ver con lo que estudio en España Tener un resultado tan gráfico y visual del trabajo mientras uno lo va desarrollando es una motivación extra para avanzar, y a pesar de la falta de tiempo para optimizar más aun el juego, han sido muchas las ideas que se me iban ocurriendo, conforme se adquirían conocimientos, para mejorarlo y darle un aspecto más espectacular. Por lo tanto el juego se puede mejorar sin mucho esfuerzo sobre todo en su parte gráfica ya que la base de programada es bastante sólida y permite agregar elementos sin dificultad. Creación de escenarios propios, de nuevos objetos tanto voladores como fijos en tierra, distintos niveles de altura para que los aviones suban y bajen, incremento de fases del juego con un guión. Etc. 77 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Considero que ha sido una experiencia muy gratificante el ir afrontando problemas que surgían durante la creación del juego, y alcanzar la solución a los mismos. Se aprende con ello a trabajar organizadamente y cumpliendo unos plazos, a trabajar en equipo con tu orientador o profesores que hayan ayudado, a investigar en libros, en internet, pero sobretodo, se aprende a conocer el potencial que tiene uno mismo y hasta dónde puede llegar. 78 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) .9 B B 6 Jogo de computador2D ;8 [Knudsen1999] Jonathan Knudsen, Java 2D Graphics, O’Reilly. ISBN: 1-56592-484-3 [Brackeen2004] David Brackeen With Bret Brackeen and Laurence Vanhelsuwé, Developing Games in Java , NRG. ISBN: 1-5927-3005-1 [Bourg2004] David M. Bourg & Glenn Seemann, AI for Game Developers, O’Reilly. ISBN: 0-596-00555-5 [McShaffry2003] Mike McShaffry, Game Coding Complete, Paraglyph press. ISBN: 1-932111-75-1 [Coelho2003] Pedro Coelho, Programaçao en JAVA 2 (curso completo), FCA ISBN: 972-722-348-6 [Flanagan2005] David Flanagan, JAVA in a nutshell, O’Reilly. ISBN: 0-596-00283-1 [Martins2006] José Martins, CG2D_Java2D, 2006-ISMAI [Horton2003] Ivor Horton, Beginning Java 2,SDK 1.4 Edition , Wrox Press ISBN: 0764543652 [OTI2005] OTI Employee, Eclipse – Platform Plug-in Developer Guide ISBN: I20050627-1435 79 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D [Peralta2005] Luís Miguel Guerra Figueira Peralta, WW2plane. Classe JAVA2D para desenho de aviões da Segunda Grande Guerra. [www_01] http://es.wikipedia.org/wiki/Videojuego [www_02] http://es.wikipedia.org/wiki/Arcade [www_03] http://es.wikipedia.org/wiki/Sprite_(videojuegos) [www_04] http://es.wikipedia.org/wiki/Coordenadas_polares [www_05] http://www.programacion.com/java/tutorial/ags_j2me/8/ [www_06] http://www.docjar.com/docs/api/java/util/HashMap.html [www_07] http://www.programacion.com/blogs/80_tecnicas_de_programacion/categories/200_de sarrollo_de_juegos.html [www_08] http://www3.uji.es/~vcholvi/teaching/java/cap.05.1/Cap.05.1.html 80 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D /9 87 Animación, 9, 11, 16, 19, 23, 24, 25, 44, 75 Avión, 15, 45, 46, 47, 68, 69, 70, 72, 73, 75, 76, 83, 84, 85 Buffering, 21, 64 Clases, 20, 36, 37, 38, 39, 42, 43, 50, 54, 55, 64 Imagen, 10, 16, 18, 19, 20, 21, 22, 24, 25, 27, 28, 29, 38, 41, 42, 44, 49, 50, 58, 60, 61, 65, 71, 72, 73, 76 Java, 51, 52, 53, 56, 79, Véase Juego, 2, 9, 10, 11, 13, 15, 36, 37, 40, 42, 44, 50, 51, 68 Jugador, 13, 14, 15, 20, 36, 37, 38, 40, Colisiones, 4, 27, 40, 44, 51, 63, 64 41, 42, 44, 45, 46, 47, 51, 55, 57, 63, Enemigo, 15, 44, 46, 47, 56, 74, 85 64, 70, 73, 74, 75, 76, 77, 83, 84, 85 Evasión, 32, 33, 34 Persecución, 32, 33, 34 Eventos, 9, 11, 25, 26, 41, 49, 57, 73, 76, Photoshop, 69, 70, 71, 72, 73 77 Fotogramas, 24, 44, 51, 73 Gráfica, 9, 11, 16, 22, 68, 73, 77 Scroll, 10, 26, 27, 37, 38 Sprites, 9, 11, 15, 16, 20, 27, 28, 29, 38, 40, 41, 42, 43, 44, 45, 49, 51, 68, 70, 71, 72, 73, 74, 75 81 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D ,49 7 F ,49,9 1 0 10.1.1. Instalación El juego “Cavaleiro dos Céus” se proporciona en un CD con lo que se puede ejecutar desde la unidad de CD-ROM, o copiar la carpeta /deploy al disco duro del computador, que es lo más aconsejable, ya que ejecutar la aplicación desde un dispositivo periférico puede relantizar su velocidad. A continuación basta con ejecutar el fichero de procesamiento por lotes cavaleiro.bat y comenzaría el juego. Es importante ejecutar dicho archivo dentro del directorio en el que se encuentra puesto que en él se encuentra la carpeta /deploy/res donde están todas las imágenes, texturas, sonidos y en definitiva recursos utilizados por la aplicación, y también todos los ficheros *.class. Se tienen tres ficheros ejecutables distintos con las siguientes resoluciones: 800x600px, 1024x768 y 1280x800. Si se desease ver el juego en pantalla completa, tendrían que coincidir la resolución del archivo ejecutable con la resolución de la pantalla. Cada ejecutable se encuentra en la carpeta: /cavaleiro800x600, /cavaleiro1024x768, /cavaleiro1280x800. Si no se dispusiese del fichero autoejecutable, habría que tener en cuenta que Java es un lenguaje interpretado. Por lo tanto un requisito imprescindible para la ejecución del juego “Cavaleiro dos Ceus” sería tener instalada la Máquina Virtual de Java para interpretar los BytesCodes, que como ya se ha comentado es una representación intermedia. El programa compilado se podría interpretar desde cualquier editor o entorno de trabajo preparado para ello como el Eclipse 3.1, o también desde consola vía comandos. Si no se 82 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) Jogo de computador2D hubiese compilado anteriormente el fichero principal (el que contiene la función Main()) habría que hacerlo antes de interpretarlo. Para acceder a las herramientas proporcionadas por el JSDK, se debe acceder al directorio /JavaHome/BIN. Una forma de hacer dichas herramientas accesibles desde cualquier directorio es insertándolo dentro del PATH del sistema, ya que esa variable especifica las rutas alternativas en las que el intérprete de comandos debe buscar una aplicación cuando ésta sea ejecutada desde de línea de comandos: SET PATH=%PATH%;JavaHome\bin; El comando para compilar la aplicación en modo consola sería: Javac [options] [NombreFichero.java] [argfiles] Por defecto el compilador generará cada fichero .class en el mismo directorio del fichero de su código fuente correspondiente. Para interpretar desde la consola habría que usar la siguiente sintaxis: Java [options] [NombreFicher] 10.1.2. Comandos para el manejo del juego El juego comienza con la presentación del mismo, es decir, título del juego y fase en la que nos encontramos, y a continuación se presenta la pantalla inicial con aviones enemigos en distintas trayectorias disparando, y con el avión del jugador centrado en la parte inferior de la pantalla. Las teclas para manejar el juego son las siguientes: ESC: pulsando esta tecla se permite abortar la aplicación y abandonar el juego antes de su finalización. También es necesario pulsarla a la finalización del juego. 83 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Cursores: Permiten desplazar el avión por la pantalla en las cuatro direcciones que apuntan las flechas. La combinación de dos cursores a la vez, permite desplazar el avión del jugador trazando una diagonal con lo que el número de direcciones permitidas para el jugador pasa a ser 8 (norte, noreste, este, sureste, sur, suroeste, oeste y noroeste). Espacio: Pulsando la barra espaciadora dispara el avión del jugador. B: Pulsando la tecla “B” el avión del jugador dispara 8 bombas en las 8 direcciones: norte, noreste, este, sureste, sur, suroeste, oeste y noroeste. El jugador dispondrá de un número limitado de bombas para toda la partida. 10.1.3. Reglas del juego El Barón Rojo es un mito que inspira cierto romanticismo, y en nuestro caso el nombre del juego, puesto que también era conocido como “El Caballero de los Cielos”. Su historia es la historia de un piloto invencible, amable con sus enemigos y que seguía un estricto código de honor, todo un caballero andante de los cielos europeos. Pero es también la historia del fin de una era, la era de las individualidades, de la guerra caballerosa. Con la muerte del Barón Rojo se entró de lleno en la nueva era de guerra total, de atrocidades y de fanatismo, la guerra de esta era la gana quien tiene más material, más masa, más poder de destrucción, más fanáticos… Bajo estas condiciones recuperamos ese aire romántico para la segunda guerra mundial puesto que el jugador tendrá que enfrentarse solo, a un gran número de aviones enemigos El juego está compuesto por dos fases. La primera fase se llama “Mission Taiwan”, y si se finalizase esta fase satisfactoriamente se pasaría a la segunda y definitiva: “Mission Berlín”. 84 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D El jugador manejará un avión cazabombardero “Spitfire” característico de la Segunda Guerra Mundial, y que pertenecerá a la RAF (Royal Air Force) Británica, y por consiguiente al eje aliado durante la guerra. Mission Taiwan: en esta primera fase se hace una incursión en la costa de Taiwan, donde el Spitfire del usuario se tendrá que enfrentar a varios escuadrones de aviones enemigos pertenecientes a distintos ejércitos. Los aviones enemigos sólo disparan con ametralladoras características de ese tipo de aviones, mientras que el usuario dispondrá de dos tipos distintos de armamentos: misiles y bombas. Los misiles sólo se disparan en una única dirección norte al “pulsar la barra espaciadora”, y las bombas en todas las direcciones (8) al pulsar la tecla “b”. Esas serán las armas con las que contará el jugador para derrotar los escuadrones enemigos. Por cada avión derribado el jugador va obteniendo 20 puntos. Algunos aviones al ser derribados se convierten en una bola que se mueve libremente por la pantalla. La intercepción de esa bola por el jugador supondrá un incremento de 100 puntos en su casillero. Por otro lado cada vez que el avión del jugador sea alcanzado con algún proyectil enemigo, sufrirá daños con lo que su nivel de vida irá bajando. Si el nivel de vida se pone a 0, el jugador muere y acaba la partida. Si el avión del jugador se colisiona con algún avión enemigo, también explota acabándose la partida. Para pasar a la siguiente fase hay que eliminar todo escuadrón enemigo o aguantar sin ser derribado hasta el último escenario de la fase. 85 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D Mission Berlin: La siguiente fase tendría las mismas condiciones que la anterior cambiando el escenario. El campo de batalla se aleja de la costa para desarrollarse en el interior de Europa. Si se eliminan todos los escuadrones se habrá llegado al final del juego con una cantidad de puntos que dependerá de los aviones enemigos derribados durante el transcurso de las dos fases. 86 Rafael Campillo Lorenzo. “Cavaleiro dos Céus” TCM-SPC (2005-2006) ,49 9 1 0 ! Jogo de computador2D # 1 = 9 87 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 88 Rafael Campillo Lorenzo. TCM-SPC (2005-2006) “Cavaleiro dos Céus” Jogo de computador2D 89