Nuevos objetivos :: Cocos2D

Bueno …. realmente tras muchos quebraderos de cabeza con el xcode en general (y con el Interface Builder en particular) puedo decir que ya me he cansado. Hace tiempo descubrí cocos2d y aunque al principio no me pareció interesante tengo que decir que ya ha llegado a un nivel de madurez notable y hoy vamos a pasarnos a usar este framework:

Descarga e instalación

Empezamos por ir a la web del cocos2D y dentro de la sección Descargas podemos encontrar la ultima versión, a fecha de hacer esta entrada era la 0.99.5 Release candidate 0 y como esto suele cambiar bastante rápido aquí os cuelgo un mirror:
 cocos2d-iphone-0.99.5-rc0.tar.gz (19.51 Mb)

Actualización 16/11/2010 – Acaban de publicar la Release Candidate 1, que según especifican será la ultima RC antes de la versión Final, asi que ya que estamos nos pasamos a esta versión
 cocos2d-iphone-0.99.5-rc1.tar.gz (29.15 Mb)

Otra actualización 16/12/2010 – Versión oficial 0.99.5
 cocos2d-iphone-0.99.5.tar.gz (29.82 Mb)

Una vez descargado lo descomprimimos en cualquier sitio (es decir, en el escritorio) y vamos a instalarlo … de momento la instalación se hace desde línea de comandos, no se si esto lo cambiarán alguna vez, aunque tampoco nos va a suponer ninguna complicación: Abrimos un terminal y vamos al directorio donde hayamos descomprimido el paquete, y lanzamos el script de instalación, en nuestro caso:

 C |  copy code |? 
1
cd Desktop/cocos2d-iphone-0.99.5-rc0 
2
 sudo ./install_templates.sh

Nos deberá salir un log de todo el copiado de archivos que hace, según la documentación se le puede pasar a esto un parámetro para especificar un directorio distinto de instalación en caso que vuestro Xcode esté en otro sitio.

Actualización 16/11 – Con la nueva Release Candidate será necesario reinstalar los templates, para ello debéis ejecutar el script install_templates.sh con el parámetro -f para forzar la instalación. Sino detecta que ya tenéis esta versión y no hará nada

 C |  copy code |? 
1
cd Desktop/cocos2d-iphone-0.99.5-rc1 
2
 sudo ./install_templates.sh -f

Si todo ha funcionado correctamente podemos abrir el Xcode y veremos que al crear un nuevo proyecto tendremos unos simpáticos templates nuevos:

Hello World

Ok … el siguiente paso será crear un proyecto y compilar para ver el resultado, por defecto el template base de cocos2d es un Hello World así que los pasos hasta aquí van a ser fáciles:

Empezamos por crear un proyecto partiendo del template base que nos da cocos2d y lo llamamos HelloWorld, luego cuando se nos abra el proyecto deberemos ajustar el SDK con el que queremos compilar, por defecto el cocos2d nos marca los proyectos para compilar con el SDK 4.1, y en mi caso no hay problema, pero en caso de no tener este SDK veremos este error con lo que no podremos compilar. Deberemos modificar el SDK base para especificar otro que si tengamos:

Para ello vamos a propiedades del proyecto, y en la pestaña Build modificamos el Base SDK, en esta misma ventana que nos aparece ya nos indica que SDK tenemos disponibles. Una vez modificado ya nos aparecerá correcto en la ventana del proyecto y podremos seleccionar que nos lo ejecute en el simulador.

Una vez ajustado esto podemos compilar el ejemplo, y si todo sale bien deberíamos obtener algo parecido a esto:

Pronto nos acostumbraremos al contador de Frames que pone el cocos2d en sus proyectos (y ya veremos luego como desactivarlo).

Primera pruebas

Como esto compila y hasta funciona vamos a hacer una pequeña modificación para ver lo sencillo que nos va a resultar jugar con este framework:

Solo haremos 2 modificaciones. Empezaremos por ir al archivo HelloWorld.h y añadimos una variable a la clase:

 C |  copy code |? 
1
@interface HelloWorld : CCLayer 
2
 { 
3
 CCSprite *player; 
4
 }

A continuación nos vamos a la clase ‘HelloWorld.m’ y modificamos el metodo init dejando esto:

 C |  copy code |? 
01
-(id) init { 
02
 if( (self=[super init] )) { 
03
 CGSize winSize = [[CCDirector sharedDirector] winSize]; 
04
 
05
 // Creamos un Sprite a partir de 'Icon.png' y lo ponemos en el centro de la pantalla 
06
 player = [CCSprite spriteWithFile:@"Icon.png"]; 
07
 player.position = ccp(winSize.width/2, winSize.height/2); 
08
 [self addChild:player]; 
09
 
10
 // Activamos el Touch 
11
 self.isTouchEnabled = YES; 
12
 } 
13
 return self; 
14
 }

Con esto ya podríamos compilar y veríamos nuestro sprite en el centro de la pantalla … pero ya que estamos vamos a hacer un poquito mas … añadimos un metodo para controlar el Touch

 C |  copy code |? 
01
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
02
 
03
 // Sacamos un touch de la pila, el primero 
04
 UITouch *touch = [touches anyObject]; 
05
 CGPoint location = [touch locationInView:[touch view]]; 
06
 
07
 // lo convertimos a coordenadas GL 
08
 location = [[CCDirector sharedDirector] convertToGL:location]; 
09
 
10
 // determinamos el punto destino donde movernos y la velocidad 
11
 CGPoint pointDest = ccp(location.x, location.y); 
12
 float MoveDuration = 0.5f; 
13
 
14
 // Creamos la accion y se la damos al player 
15
 id action = [CCMoveTo actionWithDuration:MoveDuration position:pointDest]; 
16
 [player runAction:action]; 
17
 }

Como el código ya tiene comentarios no hace falta explicar mucho mas … solo que los Actions parecen complicados y por lo poco que he trasteado con ellos os puedo decir que lo son. Y ahora el video !!!

ala, fin!!! solo falta el proyecto para los mas vagos
 cocos2d FirstApplication (689.5 Kb)

Como todo ha sido facil vamos a ver que pasa si añadimos algún detalle nuevo, hemos creado una acción simple, diciéndole al sprite el movimiento que debe hacer, pero a partir de ese momento ya no controlamos el movimiento ni sabemos donde está ni sabemos cuando termina. Vamos a modificar el método para añadir un evento y decirle al sprite que nos llave a un evento cuando este termine su movimiento:

 C |  copy code |? 
01
 
02
 // Creamos la acción, exactamente igual que antes 
03
 id action = [CCMoveTo actionWithDuration:MoveDuration position:pointDest]; 
04
 
05
 // creamos este evento para que nos llame a 'spriteMoveFinished' 
06
 id evento  = [CCCallFuncN actionWithTarget:self selector:@selector(spriteMoveFinished:)]; 
07
 
08
 // y le decimos al sprite que se mueva 
09
 [player runAction:[CCSequence actions:action,evento,nil]]; 
10
 

Ahora al runAction del sprite le vamos a dar una secuencia de acciones, el sprite las ejecutará en el orden que se las demos, primero el movimiento y cuando este termine lanzará el evento que le hemos dado. De esta forma podemos implementar el metodo ‘spriteMoveFinished’

 C |  copy code |? 
01
 
02
 -(void)spriteMoveFinished:(id)sender { 
03
 // Este metodo nos pasa como parametro el SPRITE que lo llama, aunque nosotros 
04
 // ya sabemos que es nuestro player, pero en condiciones normales estos metodos 
05
 // se usarán para muchos mas sprites 
06
 CCSprite *sprite = (CCSprite *)sender; 
07
 
08
 // sacamos las coordenadas X Y del sprite 
09
 int x = sprite.position.x; 
10
 int y = sprite.position.y; 
11
 }

Vamos a añadir algún efecto cuando el sprite termine su movimiento … para ello en el momento que termine su animación crearemos nuevos objetos .. con sus acciones y con su correspondiente evento:

 C |  copy code |? 
01
 
02
 -(void)spriteMoveFinished:(id)sender { 
03
 CCSprite *sprite = (CCSprite *)sender; 
04
 int x = sprite.position.x; 
05
 int y = sprite.position.y; 
06
 
07
 // creamos 6 Stars 
08
 [self BuildStars:5 x:x y:y radius:100]; 
09
 } 
10
 
11
 -(void) BuildStars:(int)count x:(int)x y:(int)y radius:(int)radius 
12
 { 
13
 int angle; 
14
 for(angle=0;angle<count;angle++) 
15
 { 
16
 CCSprite *star = [CCSprite spriteWithFile:@"Star.png"]; 
17
 star.position = ccp(x,y); 
18
 star.scale = 0.5f; 
19
 
20
 float fx = cosf(angle*(360/count)*0.0174) * radius; 
21
 float fy = sinf(angle*(360/count)*0.0174) * radius; 
22
 
23
 CGPoint pointDest = ccp(x+fx,y+fy); 
24
 
25
 id action  = [CCMoveTo actionWithDuration:1 position:pointDest]; 
26
 id ease    = [CCEaseExponentialOut actionWithAction:action]; 
27
 id fadeout = [CCFadeOut actionWithDuration:0.2f]; 
28
 id evento   = [CCCallFuncN actionWithTarget:self selector:@selector(starMoveFinished:)]; 
29
 
30
 [star runAction:[CCSequence actions: ease, fadeout, evento, nil]]; 
31
 [self addChild:star]; 
32
 } 
33
 } 
34
 
35
 -(void)starMoveFinished:(id)sender { 
36
 CCSprite *star = (CCSprite *)sender; 
37
 [self removeChild:star cleanup:YES]; 
38
 } 
39
 

Cosas interesantes que podemos ver aqui … vereis como se crean 6 estrellas y se les añaden acciones nuevas, de esta forma creamos el movimiento decelerado que tiene la estrella:

 C |  copy code |? 
1
id action  = [CCMoveTo actionWithDuration:1 position:pointDest]; 
2
 id ease    = [CCEaseExponentialOut actionWithAction:action];

Si consultais los CCEase veréis que hay muuuucha variedad de movimientos, probar los Elastic y veréis que vicio. (Nota!!! no todos los CCEase tienen los mismos parámetros).

Tras el movimiento hacemos que la estrella desaparezca mediante un FadeOut

 C |  copy code |? 
1
id fadeout = [CCFadeOut actionWithDuration:0.2f];

Y tras estas acciones le añadimos un evento para que la estrella se elimine de nuestro juego

 C |  copy code |? 
1
CCSprite *star = (CCSprite *)sender; 
2
 [self removeChild:star cleanup:YES];

Aquí el resultado:

Y a continuación el proyecto
 cocos2d FirstApplication + Stars !! (714.95 Kb)

4 Comments

Pedro Garrido  on January 21st, 2011

Esta realmente excelente tu pagina. Me ha servido de muuuuuuuuuucho. Muchas gracias por compartir tus conocimientos.

neofar  on January 22nd, 2011

jeje .. me alegra que te sea de utilidad, a mi realmente el cocos2d me ha impresionado bastante, así que de ahora en adelante la mayoría de tutoriales de la web será sobre cocos2d.

Un saludo

cloyd  on February 8th, 2011

saludos muy buenos tutos gracias aunque creo haria falta una introduccion del entorno de cocos y como se implementan las librerias por decir hay veces en el tuto que no se distingue que es codigo para anexar al proyecto y cual es a modo comentario por que ambos tienen opcion copiar y me gustaria pudieras anexar a que file corresponde cada fragmento de codigo nuevamente gracias por el post

neofar  on February 10th, 2011

Pues en teoría todo es código por añadir. Este ejemplo era muy básico … en teoría cuando hago algún tutorial mas complejo detallo mejor donde va cada parte del código, de todos modos también suelo incluir el proyecto para descargar.

Pero me anoto el consejo, gracias por el mensaje

Leave a Comment