César López de Felipe Abad

Consultor tecnológico de desarrollo de proyectos informáticos.

Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación

Somos expertos en Java/JEE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2011-04-11

Tutorial visitado 4.207 veces Descargar en PDF
Crear un juego con Cocos2D para IPhone/IPad en Xcode

Puedes descargar el código fuente aquí.

Crear un juego con Cocos2D para IPhone/IPad en Xcode


0. índice de contenidos.


1. Introducción.

Hola a todos, he empezado unas prácticas en autentia la semana pasada y cómo primera tarea me han encargado hacer una aplicación para iPhone similar a Space invaders. Para los que no conozcan el juego, básicamente consiste en controlar una nave que se encuentra en la parte baja de la pantalla y disparará a unos alienijenas que van avanzando poco a poco. El objetivo del juego es cargarse a los aliens antes de que lleguen a la posición de la nave. Nosotros vamos a usar la cabeza de la mosca de autentia, que disparará a unas naves que avanzarán por un fondo estrellado.

El objetivo de este tutorial es aprender a hacer un juego para iPhone usando un framework existente (cocos2d). Como el diseño del juego lo he hecho yo mismo, puede que haya algún fallo en el mismo. Por ejemplo, al principio pense en separar los actores (Nave,Mosca y Disparo) en tres clases distintas, porque iban a tener atributos característicos propios, pero al acabar la aplicación he visto que podría haber usado una única clase. Además la primera vez que hice la aplicación (aprendiendo a usar cocos2d mientras la hacía), la mayoria de las variables eran globales al fichero (lo hice así porque en uno de los tutoriales de cocos2d ponía que se podía hacer para aplicaciones simples), lo que al final trajó más problemas que soluciones. Para hacer este tutorial, he vuelto a hacer el proyecto desde cero, y esta vez he optado por identificar a los actores con un id y recuperarlos a través de ese id cuando sea necesario. Me hubiese gustado hacer un menu principal desde el que pudiesemos acceder a la aplicación, pero me dio más problemas de los que pensaba (creo que ahora si sabría hacerlo), por lo que el juego se lanza al empezar la aplicación y se reinicia cuando se gana o se pierde.

Para poder hacer la aplicación me leí varios tutoriales y manuales (podeís encontrarlos en lecturas recomendadas), ya que no había programado antes en Objetive-C, no me ha parecido un lenguaje díficil una vez que te acostumbras, aunque tuve varios problemas al principio por no acordarme de poner los imports (la mala costumbre del autocompletar). Y bueno, ya me he alargado bastante en la presentación, asi que vamos a empezar con el tutorial en sí.


2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: MacBookPro8,2 (2 GHz Intel Core i7, 4GB DDR3 SDRAM).
  • AMD Radeon HD 6490M 256MB.
  • Sistema Operativo: Mac OS X Snow Leopard 10.6.7.
  • IDE: Xcode Versión 3.2.6.
  • iPhone OS: Versión 4.3.

3. Lecturas recomendadas.

Antes de empezar con este tutorial, sería recomendable leerse los tutoriales relacionados con el tema que podeís encontrar en AdictosAltrabajo.com.

Hay varios, yo para trabajar en este tutorial he seguido varios. Para montar el sdk junto con Xcode he seguido este tutorial, que además sirve para hacer una pequeña aplicación y familiarizarse con Xcode. Después de ese tutorial, seguí este otro, en el que podemos desarrollar una aplicación un poco más compleja y seguir familiarizandonos un poco más con Xcode. Y por último como introducción a Cocos2D tenemos este.

Otra lectura recomendable mientras se trabaja con Cocos2d (incluso antes de empezar) es la documentación que ofrecen en la página de Cocos2D para IPhone. Dentro de la sección programming Guide podemos encontrar tambien una pequeña guía para novatos (Beginners' Guide) con tres lecciones en la que nos enseñan la funcionalidad básica que ofrece cocos2D.

Se puede intentar seguir este tutorial sin leer antes los anteriores, pero sería recomendable por lo menos echarles un ojo por encima.

Bueno, creo que ya estamos listos para ponernos manos a la obra


4. Creando el proyecto en Xcode.

Para crear el proyecto le damos a File > New Project. En la ventana que nos sale tenemos que seleccionar que vamos a usar la template de una cocos2d Application.

Le damos a Choose… y nos pedirá el nombre del proyecto (en mi caso le voy a llamar AutentiaInvaders) y el lugar en el disco en el que lo queremos guardar (lo dejo a vuestra elección).

La verdad es que al crear el proyecto ya te da practicamente todo hecho. Vamos a ejecutarlo tal y como esta. Para ejecutarlo vamos a cambiar el ejecutable a iPhone Simulator 4.2 (en el 4.3 no he conseguido que funcione de momento, tendría que mirar si esta soportado en la versión que uso de cocos2d).

Ejecutamos, podemos pinchar en el martillito y el play (clean and build) o directamente pinchar en el editor y darle a (cmd + r). Como es la primera vez tarda un poquito porque tiene que instalar la aplicación en el simulador.

Una vez visto que funciona vamos a analizar un poquito las clases que ha creado.

Vamos a ver el método applicationDidFinishLaunching de la clase AutentiaInvadersAppDelegate.m. De momento no he estudiado mucho esta clase (que es la que se encarga de gestionar el ciclo de vida de la aplicación), pero podemos ver que la última linea de este metodo, que es el que se llama cuando la aplicación acaba de lanzarse, llama al método runWithScene del objeto sharedDirector pasandole la lo que devuelve el método scene de la clase HelloWorld.

Esto último que he dicho, puede que haya sonado a chino, pero bueno, básicamente es que al acabar de lanzarse la aplicación se llama al método scene de HelloWorld. Vamos a ver que hace este metodo:

Bueno, pues parece que lo que tenemos cuando se acaba de lanzar la aplicación en nuestro iPhone es una escena que tiene como hija una capa de la clase HelloWorld. Nuestra aplicación, como va a ser muy simple, utilizará esta unica escena, y en ella se desarrollará toda la lógica del juego y la presentación.

Vamos a empezar por crear las tres clases principales de la aplicación, Mosca, Nave y Disparo. Las tres clases serán hijas de la clase de cocos2d CGSprite. Le damos a File > New File … en la ventana que se abre, vamos a las clases de cocos2d, elegimos una CCNode class y le decimos que será una subclase de CCSprite y le damos a next.

Elegimos el nombre y le damos a finish.

En la documentación de cocos2d dicen que hay que implementar al menos el método initWithTexture cuando se crea una subclase de CGSprite, así que una vez que tenemos creadas las tres clases, vamos a implementarlo. Además de este método, implementaremos el metodo spriteWithFile, que es el método que vamos a usar para crear nuestros actores (mosca, naves y disparos) asociandoles una imagen. Así nos quedarian los archivos de la interfaz y la implementación:

Como recomendación os diria que vayais probando que el proyecto sigue funcionando despues de realizar cambios. También combiene guardar snapshots cada cierto tiempo (Roberto os dice como en su tutorial ( http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=oop_con_objetiveC_Iphone )). Así será más fácil detectar posibles fallos y restaurar el proyecto a una versión anterior que funcionase.

Una vez hemos visto que el proyecto sigue funcionando, vamos a poner a nuestros actores dentro de la escena. Para ello nos vamos a la clase HelloWorldScene, y vamos a cambiar el método init.

He añadido unas imagenes al proyecto para poder asociarlas a los actores (acordaros de añadirlas tanto en el directorio como en Xcode), además de añadir una constante (TAM_IMAGEN) que guarda el tamaño de la imagen. Para añadir la constante, simplemente teneis que añadir este linea antes de el @implementation.

Nos quedaría algo asi:

Con esto ya tendriamos a nuestra mosca enfrentandose a una nave. Pero lo que queremos es que se enfrente a varias naves. Podríamos hacer un NSMutableArray de naves, pero a mí me dio problemas a la hora de moverlas por la pantalla, así que lo solucione poniendoles una etiqueta a la hora de añadirlas a la capa. Vamos a crear un método que nos añada las naves a la capa, una variable para saber el número de naves que hay y un par de constantes para saber cuantas filas y columnas de naves tenemos.

Nos debería quedar algo así cuando lo ejecutemos:

Ahora que tenemos nuestros actores en escena, vamos a poner un par de botones para poder mover nuestra mosca. Lo vamos a hacer usando un objeto menu de cocos2d, que estará compuesto por los dos botones que serán objetos de la clase CCMenuItemImage. Creamos el metodo addBotones, una constante para guardar el tamaño del boton y los métodos a los que se llamará cuando se pulsen (me hubiese gustado hacer un unico método, pero después de pelearme un buen rato no lo conseguí, así que lo solucione haciendo dos métodos). También vamos a añadirle una tag a la mosca (que será una constante) a la hora de crearla para poder encontrarla desde el método que la va a mover.

Nos quedará algo así:

Podemos ver en el log que al pulsar los botones se esta llamando al método correspondiente. Para abrir el log podeís darle a Run > Console o podeís darle a (cmd + shift + r) desde el editor.

Como ahora añadimos a la mosca con un id, podemos hacer un método addMosca y otro addComponentes, para que el método init quede un poco más limpio:

Vamos a mover a las naves, para hacer el juego algo más emocionante. Para ello, vamos a crear un evento periódico que se encargue de mover a las naves, en este método tambien gestionaremos las colisiones en el futuro. Para saber en que dirección se estan moviendo las naves vamos a añadir el atributo isMovingRight a la clase Nave. Este atributo será YES si se mueve a la derecha y NO si se mueve a la izquierda.

Descomentamos la linea que habia en el metodo addNaves, para que al crearlas tengan el atributo isMovingRight a NO. Creamos el método periódico logicaJuego, y le añadimos al método init una llamada al método logicaJuego. Me hubiese gustado hacer el movimiento de las naves en un método aparte, pero no conseguí que funcionase.

Ahora que ya tenemos las naves moviendose, sólo nos falta poder dispararlas. Para ello vamos a hacer que cada vez que se toque la pantalla en cualquier sitio que no sean los botones de dirección, se dispare. Para hacer esto, hay que decirle a nuestra clase que admita toques. En cocos2d hay dos tipos de toque, los normales (standard touches) y los targeted touches (no se muy bien como traducirlo). Nosotros vamos a usar los segundos, la diferencia la explican en esta página de la documentación de cocos2d (http://www.cocos2d-iphone.org/wiki/doku.php/tips:touchdelegates), explicándolo brevemente, los targeted touch, sólo recuperan un toque cada vez mientras que los standard recuperan todos los toques que haya.

Volviendo a nuestro juego, tenemos que sobreescribir el metodo registerWithTouchDispatcher (hay que importar CCTouchDispatcher.h) de la siguiente forma:

Esta forma de activar los toques es valida para todas las subclases de CCLayer, si quisiesemos activar los toques en otra clase, requiere un poco más de trabajo (explican como hacerlo en el link anterior.

Ahora que ya podemos gestionar los toques, vamos a hacer algo con ellos, le decimos al método init que los toques estan activados y sobreescribimos estos dos métodos:

Ahora vamos a cambiar el método ccTouchEnded para que llame al método disparar (que vamos a crear ahora). El método disparar creará un disparo que se moverá verticalmente. Para mover el disparo, en vez de usar el método periódico que tenemos, vamos a crearlo y asignarle una acción (moverse hacia arriba).

Ahora que ya podemos disparar, vamos a gestionar las colisiones entre disparos y naves. Para ello, vamos a usar la funcion CGRectIntersectsRect, que nos devuelve YES si dos rectangulos interseccionan y NO si no lo hacen. Pero antes, tenemos que hacer que nuestras clases disparo y nave nos devuelvan un CGRect. Vamos a crear un protocolo con el método getRect.

Ahora hacemos que nuestras clases usen ese protocolo e implementamos el método:

Creemos un método gestionarColosiones que llamaremos desde nuestro método logicaJuego:

Si probáis el juego ahora que se pueden destruir naves, vereís que cuando fallamos un disparo, si seguimos disparando no se destruyen las naves. Esto es porque el disparo se queda en la parte superior de la pantalla (aunque no se ve, podeís bajarle la altura un poco a la hora de crearlo y vereís como se queda ahí). Para arreglar esto, vamos a destruir los disparos que superen esa altura en un método que llamaremos desde logicaJuego.

Por último vamos a añadirle un fondo para que quede más bonito y vamos a crear un método que nos ponga un mensaje y reinicie la partida cuando se acabe. El fondo lo voy a añadir como si fuese otro CGSprite (seguramente se puede hacer de alguna forma mejor, pero se me acaba el tiempo para hacer el tutorial).

En el caso de perder, la transición no funciona porque las naves siguen moviendose, para arreglar esto, vamos a destruir todos los hijos de la capa antes de añadir el mensaje de fin de partida.

Pues ya hemos terminado nuestra aplicación, combiene borrar los mensajes que estabamos poniendo en el log para depurarla, ya que no los vamos a seguir usando. Y tambien sería conveniente mirar la gestión de memoria, y arreglar algún bug que sigue teniendo la aplicación.


5. Conclusiones.

Como dije al principio, la aplicación era sencilla pero espero que os haya servido para obtener unos conocimientos básicos de cocos2d. Y todavía habría que aprender a gestionar la memoria, que es algo muy importante cuando se programa para moviles. Pero bueno, como primera aplicación tampoco esta del todo mal.

Si quereís hacer algún comentario, sugerencia o preguntar alguna duda podeís hacerlo en la zona de comentarios.

Un saludo.

César López.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Fecha publicación: 2011-05-27-13:39:39

Autor: Cafar

Genial, maravilloso, estaba que me tiraba de los pelos buscando algún tutorial en cocos2d para crear juegos, todos los que he visto son en inglés y no me enteraba a penas... Hoy es la primera vez que he visitado la página y tengo que felicitaros, enhorabuena y seguiré por aquí.