¿Cómo hacer un juego sencillo para iPhone utilizando Cocos2D?

Ray Wenderlich

Esta entrada está disponible también en: Chino simplificado, Inglés, Ruso

Ninjas Going Pew-Pew!

Ninjas Going Pew-Pew!

Cocos2D es una poderosa librería que puede ahorrarle muchísimo tiempo a la hora de construir un juego el iPhone. Tiene soporte para sprites, efectos de gráficos, animaciones, librerías para simulación de física, motores de sonido, y mucho más.

Estoy empezando a aprender Cocos2D, aún cuando existen varios tutoriales útiles sobre cómo empezar con Cocos2D, no pude encontrar alguno acorde a lo que estaba buscando – hacer un juego muy sencillo pero funcional, con animaciones, colisiones y audio, sin utilizar muchos elementos avanzados. Terminé por hacer un juego simple por mi mismo y pensé en escribir esta serie de tutoriales basado en mi propia experiencia en caso de que pudiese serle útil a nuevos principiantes.

Esta serie de tutoriales le guiará a través del proceso de creación de un juego sencillo para su iPhone utilizando Cocos2D, de principio a fin. Usted puede seguir la serie en orden o ir directamente a el proyecto de ejemplo al final del artículo. Y sí. Habrá ninjas.

(Saltar a la Parte 2 o a la Parte 3 de la serie.)

Descargando e Instalando Cocos2D

Puede descargar Cocos2D desde la página de Cocos2D en Google Code

Después de descargar el código, tendrá que instalar las plantillas de proyecto, las cuales le serán muy útiles. Abre una ventana de Terminal en el directorio donde has descargado Cocos2D e introduzca el siguiente comando: ./install-templates.sh -f -u

Note que opcionalmente, puede pasar un parámetro al script de instalación si tiene Xcode instalado en un directorio no estándar (como lo podría haber hecho si tiene más de una versión del SDK en su equipo).

¡Hola, Cocos2D!

Vamos a empezar por poner en funcionamiento un proyecto sencillo “Hola Mundo” mediante el uso de la plantilla de Cocos2D que acabamos de instalar. Abre Xcode y crear un proyecto Cocos2D nuevo seleccionando la plantilla “cocos2d Application”, y nombra el proyecto como “Cocos2DSimpleGame”.

Cocos2D Templates

Ahora puede compilar y ejecutar el proyecto creado con la plantilla tal y como está. Si todo funciona bien, debería ver lo siguiente:

HelloWorld Screenshot

Cocos2D está organizado sobre el concepto de “escenas”, que son algo así como “niveles” o “pantallas” para un juego. Por ejemplo, usted podría tener una escena para el menú inicial del juego, otra para la acción principal del juego, y para finalizar, una escena para juego terminado. Dentro de las escenas, se puede tener un número de capas “layers” (algo así como en Photoshop), y las capas pueden contener nodos tales como sprites, etiquetas “labels”, menús, o más. Y los nodos, a su vez, pueden contener otros nodos (o sea, un sprite puede tener un sprite hijo dentro de él).

Si echa un vistazo al proyecto de ejemplo, verá que hay una sola capa – HelloWorldLayer – y vamos a empezar a implementar nuestro principal modo de juego “gameplay” en dicha capa. Abre la capa HelloWorldLayer – podrá ver que en estos momentos en el método init se está agregando una etiqueta que dice “Hello World” a la capa. Vamos a tener que quitar eso, y poner un sprite en su lugar.

Adicionando un Sprite

Antes de poder adicionar un sprite, vamos a necesitar algunas imágenes para poder trabajar. Usted puede crear las suyas propias, o utilizar las que a mi bella esposa ha creado para el proyecto: imagen del jugador, imagen de proyectil,, y una imagen de un objetivo.

Una vez que hayas obtenido las imágenes, arrástralas a la carpeta de recursos en Xcode, y asegúrese de que “Copy items into destination group’s folder (if needed)” está marcada.

Ahora que tenemos nuestras imágenes, debemos decidir dónde queremos colocar al jugador. Tenga en cuenta que en Cocos2D la esquina inferior izquierda de la pantalla tiene las coordenadas (0,0) y los valores X e Y aumentará a medida que se desplaza a la parte superior derecha. Dado que este proyecto está en modo horizontal, esto significa que la esquina superior derecha es (480, 320).

También note que por defecto cuando se establece la posición de un objeto, la posición es con respecto al centro del sprite que está adicionando. Así que si queríamos que el sprite de nuestro jugador estuviese alineado con el borde izquierdo de la pantalla en sentido horizontal, y centrado verticalmente:

  • La coordenada x de la posición, la establecimos en [ancho del sprite del jugador]/2.
  • La coordenada y de la posición, la establecimos en [altura de la ventana]/2.

La siguiente imagen lo ayudará a ilustrar esto mejor:

Screen and Sprite Coordinates

¡Ok, vamos a probarlo! Abra la carpeta Classes y haga clic en HelloWorldLayer.m, reemplace el método init con lo siguiente:

-(id) init
{
  if( (self=[super init] )) {
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    CCSprite *player = [CCSprite spriteWithFile:@"Player.png" 
      rect:CGRectMake(0, 0, 27, 40)];
    player.position = ccp(player.contentSize.width/2, winSize.height/2);
    [self addChild:player];		
  }
  return self;
}

Puede compilar y ejecutar el juego y el sprite debe aparecer muy bien, pero note que el color por defecto del fondo es negro. Para este artwork, blanco debe verse mucho mejor. Una forma fácil de establecer el color de fondo de una capa en Cocos2D a un color personalizado es utilizando la clase CCLayerColor. Así que vamos a intentarlo. Haga clic en HelloWorldLayer.h y cambie la declaración de interfaz de HelloWorld para lo que sigue:

@interface HelloWorldLayer : CCLayerColor

Luego haga clic en HelloWorldLayer.m y haga esta pequeña modificación al método init para que podamos establecer el color de fondo a blanco:

if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {

Compile y ejecute el juego y debería ver el sprite sobre un fondo blanco. ¡perfecto, nuestro Ninja parece estar listo para la acción!

Sprite Added Screenshot

Objetivos en movimiento

A continuación vamos a adicionar algunos objetivos a la escena para que nuestro ninja para combatir. Para hacer las cosas más interesantes, queremos que los objetivos se muevan – ¡de lo contrario no sería un gran desafío! Así que vamos a crear los objetivos un poco fuera de la pantalla a la derecha, y establecer una acción para decirles que se muevan hacia la izquierda.

Agregue el siguiente método justo antes del método init:

-(void)addTarget {
 
  CCSprite *target = [CCSprite spriteWithFile:@"Target.png" 
    rect:CGRectMake(0, 0, 27, 40)]; 
 
  // Determina donde producir un objetivo a lo largo del eje Y
  CGSize winSize = [[CCDirector sharedDirector] winSize];
  int minY = target.contentSize.height/2;
  int maxY = winSize.height - target.contentSize.height/2;
  int rangeY = maxY - minY;
  int actualY = (arc4random() % rangeY) + minY;
 
  // Crea un objetivo ligeramente fuera de la pantalla hacia la derecha,
  // y en una posicion aleatoria en el eje Y calculado arriba
  target.position = ccp(winSize.width + (target.contentSize.width/2), actualY);
  [self addChild:target];
 
  // Determina la velocidad del objetivo
  int minDuration = 2.0;
  int maxDuration = 4.0;
  int rangeDuration = maxDuration - minDuration;
  int actualDuration = (arc4random() % rangeDuration) + minDuration;
 
  // Crea las acciones
  id actionMove = [CCMoveTo actionWithDuration:actualDuration 
    position:ccp(-target.contentSize.width/2, actualY)];
  id actionMoveDone = [CCCallFuncN actionWithTarget:self 
    selector:@selector(spriteMoveFinished:)];
  [target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
 
}

He escrito de una manera detallada para hacer que las cosas sean tan fáciles de entender como sea posible. La primera parte debe tener sentido sobre la base de lo que hemos discutido hasta ahora: hacemos algunos cálculos sencillos para determinar donde queremos crear el objeto, establecemos la posición del objeto, y lo agregamos a la escena de la misma manera que hicimos para el sprite del jugador.

El elemento nuevo aquí es la adición de acciones. Cocos2D ofrece una gran cantidad de acciones útiles ya integradas que puede utilizar para animar sus sprites, tales como acciones de movimiento, acciones de salto, acciones se desvanecimiento, acciones de animación y muchas más. Aquí usamos tres acciones sobre el objetivo:

  • CCMoveTo: Usamos la acción CCMoveTo para dirigir al objeto a que se mueva fuera de la pantalla a la izquierda. Tenga en cuenta que podemos especificar el tiempo de duración que el movimiento debe tener, y estamos variando la velocidad de forma aleatoria desde 2 a 4 segundos.
  • CCCallFuncN: CCCallFuncN nos permite especificar una devolución de llamada “callback” a producirse en nuestro objeto, cuando se termina de realizar la acción. Estamos especificando un callback llamado “spriteMoveFinished” que aún no hemos escrito – lo veremos más abajo.
  • CCSequence: La acción CCSequence nos permite encadenar una secuencia de acciones que se realizan en orden, una a la vez. De esta manera, podemos realizar la acción CCMoveTo en primer lugar, y una vez que se haya completado realizar la acción CCCallFuncN.

A continuación, agregue la función callback que nos referimos en la acción CCCallFuncN. Puede agregarla justo antes de addTarget:

-(void)spriteMoveFinished:(id)sender {
  CCSprite *sprite = (CCSprite *)sender;
  [self removeChild:sprite cleanup:YES];
}

El propósito de esta función es eliminar el sprite de la escena una vez que está fuera de la pantalla. Esto es importante para no tener fugas de memoria con el tiempo al tener toneladas de sprites no utilizados que se sientan fuera de la pantalla. Tenga en cuenta que hay otras (y mejores) formas de abordar este problema, tales como tener arreglos reutilizables de sprites, pero para este tutorial para principiantes, estamos tomando el camino fácil.

Una última cosa antes de seguir. ¡Tenemos que en realidad llamar al método para crear objetivos! Y para hacer las cosas divertidas, vamos a tener objetivos apareciendo constantemente en el tiempo. Podemos lograr esto en Cocos2D mediante la programación de una función callback que se ejecuta periódicamente. Una vez por segundo debe ser suficiente para ello. Así que añade la siguiente llamada en el método init antes del return:

[self schedule:@selector(gameLogic:) interval:1.0];

Y a continuación, implementamos la función callback de la siguiente manera:

-(void)gameLogic:(ccTime)dt {
  [self addTarget];
}

¡Eso es! Así que ahora, si se compila y ejecuta el proyecto, debería ver objetivos moviéndose felizmente a través de la pantalla:

Targets Screenshot

Proyectiles

En este punto, el ninja está suplicando por algo de acción – ¡así que vamos a agregar los disparos! Hay muchas formas en que podríamos implementar los disparos, pero para este juego vamos a hacerlo de forma tal que cuando el usuario toque la pantalla, dispara un proyectil desde el jugador en dirección al toque.

Quiero utilizar una acción CCMoveTo para implementar esto para mantener las cosas en un nivel principiante, pero con el fin de realizarlo tenemos que hacer un poco de matemática. Esto es debido a que CCMoveTo nos obliga a darle un destino para el proyectil, pero no podemos usar el punto del toque en la pantalla debido a que dicho punto representa sólo la dirección para disparar en relación con el jugador. En realidad, queremos mantener la bala en movimiento a través del punto de toque hasta que salga de la pantalla.

La siguiente imagen ilustra mejor lo que queremos lograr:

Projectile Triangle

Como puede ver, tenemos un pequeño triángulo creado por el desplazamiento X e Y desde el punto de origen hasta el punto de toque. Sólo tenemos que hacer un gran triángulo con la misma proporción – y sabemos que queremos que uno de los extremos quede fuera de la pantalla.

Ok, así que en el código. En primer lugar tenemos que permitir toques en nuestra capa. Agregue la siguiente línea al método init:

self.isTouchEnabled = YES;

Como hemos permitido recibir toques en nuestra capa, ahora vamos a recibir callbacks de eventos de toque. Así que vamos a implementar el método ccTouchesEnded, que se llama cuando el usuario completa un toque, de la siguiente manera:

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 
  // Selecciona uno de los toques para trabajar
  UITouch *touch = [touches anyObject];
  CGPoint location = [touch locationInView:[touch view]];
  location = [[CCDirector sharedDirector] convertToGL:location];
 
  // Establece la posicion inicial del proyectil
  CGSize winSize = [[CCDirector sharedDirector] winSize];
  CCSprite *projectile = [CCSprite spriteWithFile:@"Projectile.png" 
    rect:CGRectMake(0, 0, 20, 20)];
  projectile.position = ccp(20, winSize.height/2);
 
  // Determina los desplazamientos hasta la posicion del proyectil
  int offX = location.x - projectile.position.x;
  int offY = location.y - projectile.position.y;
 
  // Salir si se está disparando hacia abajo o hacia atrás
  if (offX

En la primera parte, elegimos uno de los toques para trabajar, obtenemos la ubicación en la vista actual, a continuación, llamamos convertToGL para convertir las coordenadas hacia nuestro diseño actual. Esto es muy importante, ya que estamos en modo horizontal.

A continuación cargamos el sprite del proyectil y como de costumbre definimos la posición inicial. Luego, determinamos a dónde se desea mover el proyectil, utilizando como guía el vector entre el jugador y el toque, de acuerdo con el algoritmo descrito anteriormente.

Nótese que el algoritmo no es ideal. Estamos obligando al proyectil a mantenerse en movimiento hasta que alcanza la posición X fuera de la pantalla – ¡incluso si hubiera ido fuera de la pantalla en la posición Y primero! Hay varias maneras para hacer frente a esto incluyendo la comprobación de la longitud más corta para ir fuera de la pantalla, teniendo un callback de chequeo para proyectiles fuera de la pantalla en nuestra lógica de juego y eliminarlos en lugar de utilizar el método de devolución de llamada, etc, pero para este tutorial para principiantes vamos a mantenerlo como está.

Lo último que tenemos que hacer es determinar la duración del movimiento. Queremos que la bala sea disparada a una velocidad constante a pesar de la dirección del tiro, por lo que una vez más tenemos que hacer un poco de matemática. Podemos averiguar hasta donde nos estamos moviendo utilizando el Teorema de Pitágoras. Recordando de geometría, esta es la regla que dice que la longitud de la hipotenusa de un triángulo rectangulo es igual a la raíz cuadrada de la suma de los cuadrados de los catetos.

Una vez que tenemos la distancia, simplemente la dividimos por la velocidad con el fin de obtener la duración. Esto se debe a que la distancia = velocidad sobre el tiempo, o en otras palabras, el tiempo = distancia sobre la velocidad.

El resto es establecer las acciones al igual que hicimos con los objetivos. Compila y ejecuta el proyecto, ¡y ahora tu ninja debe ser capaz de disparar a las hordas que se aproximan!

Projectiles Screenshot

Detección de colisiones

Así que ahora tenemos shurikens volando por todas partes – pero lo que nuestro ninja realmente quiere hacer es derrotar algunos enemigos. Así que vamos a añadir algún código para detectar cuando nuestros proyectiles intersectan a nuestros objetivos.

Hay varias maneras de solucionar esto con Cocos2D, incluyendo el uso de una de las librerías de física incluidas: Box2D o Chipmunk. Sin embargo, para simplificar las cosas, vamos a implementar nosotros mismos una detección de colisiones sencilla.

Para ello, primero tenemos que hacer un mejor seguimiento de los objetivos y proyectiles actualmente en la escena. Agregue lo siguiente a la declaración de clase HelloWorldLayer:

NSMutableArray *_targets;
NSMutableArray *_projectiles;

E inicializar las arreglos en el método init:

_targets = [[NSMutableArray alloc] init];
_projectiles = [[NSMutableArray alloc] init];

Y mientras pensamos en ello, limpiamos la memoria en el método dealloc:

[_targets release];
_targets = nil;
[_projectiles release];
_projectiles = nil;

Ahora, modifique el método addTarget para adicionar el nuevo objetivo al arreglo de objetivos y establecer una etiqueta “tag” para su uso futuro:

target.tag = 1;
[_targets addObject:target];

Y modifique el método ccTouchesEnded para agregar el nuevo proyectil al arreglo de proyectiles y establecer una etiqueta para su uso futuro:

projectile.tag = 2;
[_projectiles addObject:projectile];

Por último, modificar el método de spriteMoveFinished para eliminar el sprite del arreglo apropiado basada en la etiqueta:

if (sprite.tag == 1) { // target
  [_targets removeObject:sprite];
} else if (sprite.tag == 2) { // projectile
  [_projectiles removeObject:sprite];
}

Compile y ejecute el proyecto para asegurarse de que todo sigue funcionando bien. No debería haber ninguna diferencia notable en este punto, pero ahora tenemos lo necesario para implementar la detección de colisiones.

Ahora agregue el siguiente método en HelloWorldLayer:

- (void)update:(ccTime)dt {
 
  NSMutableArray *projectilesToDelete = [[NSMutableArray alloc] init];
  for (CCSprite *projectile in _projectiles) {
    CGRect projectileRect = CGRectMake(
      projectile.position.x - (projectile.contentSize.width/2), 
      projectile.position.y - (projectile.contentSize.height/2), 
      projectile.contentSize.width, 
      projectile.contentSize.height);
 
    NSMutableArray *targetsToDelete = [[NSMutableArray alloc] init];
    for (CCSprite *target in _targets) {
      CGRect targetRect = CGRectMake(
        target.position.x - (target.contentSize.width/2), 
        target.position.y - (target.contentSize.height/2), 
        target.contentSize.width, 
        target.contentSize.height);
 
      if (CGRectIntersectsRect(projectileRect, targetRect)) {
        [targetsToDelete addObject:target];				
      }						
    }
 
    for (CCSprite *target in targetsToDelete) {
      [_targets removeObject:target];
      [self removeChild:target cleanup:YES];									
    }
 
    if (targetsToDelete.count > 0) {
      [projectilesToDelete addObject:projectile];
    }
    [targetsToDelete release];
  }
 
  for (CCSprite *projectile in projectilesToDelete) {
    [_projectiles removeObject:projectile];
    [self removeChild:projectile cleanup:YES];
  }
  [projectilesToDelete release];
}

Lo anterior debe ser bastante claro. Acabamos de iterar a través de nuestros proyectiles y objetivos, creando los rectángulos correspondientes a las dimensiones creadas por los limites de las cajas que los contiene, y usamos CGRectIntersectsRect para encontrar intersecciones. Si se encuentra alguna, eliminamos el proyectil y el objetivo de la escena y de los arreglos. Tenga en cuenta que hay que añadir los objetos a un arreglo “toDelete” porque no se puede eliminar un objeto de un arreglo mientras se está iterando a través de él. Nuevamente, hay formas más óptimas para poner en práctica este tipo de cosas, pero voy por el enfoque simple.

Sólo necesita una cosa más antes de que esté listo – programar este método para ejecutarse tan a menudo como sea posible, añadiendo la siguiente línea a su método init:

[self schedule:@selector(update:)];

Compila y ejecuta, y ahora, cuando los proyectiles intersecten los objetivos, ¡deben desaparecer!

Toques finales

Estamos ahora bastante cerca de tener un juego completo (pero extremadamente simple). Sólo tenemos que añadir algunos efectos de sonido y música (¡pues que tipo de juego no tiene sonido!) y también un poco de lógica de juego sencilla.

Si has estado siguiendo mi serie sobre programación de audio para el iPhone, estarás enormemente satisfecho de escuchar lo simple que los desarrolladores de Cocos2D han hecho para reproducir efectos básicos de sonido en su juego.

Primero, arrastre un poco de música de fondo y un efecto de sonido de disparo hacia la carpeta de recursos. Siéntase libre de utilizar la música de fondo que hice o mi asombroso efecto de sonido “pew-pew”, o hacer el suyo propio.

A continuación, agregue el siguiente import al principio de HelloWorldLayer.m:

#import "SimpleAudioEngine.h"

En el método init, pon en marcha de la música de fondo de la siguiente manera:

[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background-music-aac.caf"];

Y en el método ccTouchesEnded reproduzca el efecto de sonido de la siguiente manera:

[[SimpleAudioEngine sharedEngine] playEffect:@"pew-pew-lei.caf"];

Ahora, vamos a crear una nueva escena que nos servirá como indicador de “Has Ganado” o “Has Perdido”. Haga clic en la carpeta Classes y vaya a FileNew File, y selecciona “Objective-C class”, asegúrese que esté seleccionado como subclase NSObject. Haga clic en Next, a continuación, escriba GameOverScene como nombre de archivo, y asegúrese de que “Also create GameOverScene.h” está marcado.

Luego, reemplace GameOverScene.h con el siguiente código:

#import "cocos2d.h"
 
@interface GameOverLayer : CCLayerColor {
  CCLabelTTF *_label;
}
@property (nonatomic, retain) CCLabelTTF *label;
@end
 
@interface GameOverScene : CCScene {
  GameOverLayer *_layer;
}
@property (nonatomic, retain) GameOverLayer *layer;
@end

A continuación, reemplace GameOverScene.m con el siguiente código:

#import "GameOverScene.h"
#import "HelloWorldLayer.h"
 
@implementation GameOverScene
@synthesize layer = _layer;
 
- (id)init {
 
  if ((self = [super init])) {
    self.layer = [GameOverLayer node];
    [self addChild:_layer];
  }
  return self;
}
 
- (void)dealloc {
  [_layer release];
  _layer = nil;
  [super dealloc];
}
 
@end
 
@implementation GameOverLayer
@synthesize label = _label;
 
-(id) init
{
  if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {
 
    CGSize winSize = [[CCDirector sharedDirector] winSize];
    self.label = [CCLabelTTF labelWithString:@"" fontName:@"Arial" fontSize:32];
    _label.color = ccc3(0,0,0);
    _label.position = ccp(winSize.width/2, winSize.height/2);
    [self addChild:_label];
 
    [self runAction:[CCSequence actions:
      [CCDelayTime actionWithDuration:3],
      [CCCallFunc actionWithTarget:self selector:@selector(gameOverDone)],
      nil]];
 
  }	
  return self;
}
 
- (void)gameOverDone {
 
  [[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
 
}
 
- (void)dealloc {
  [_label release];
  _label = nil;
  [super dealloc];
}
 
@end

Tenga en cuenta que hay dos objetos diferentes aquí: una escena y una capa. La escena puede contener cualquier número de capas, sin embargo, en este ejemplo sólo contiene una. La capa sólo coloca una etiqueta en el centro de la pantalla y programa una transición a ocurrir 3 segundos en el futuro, de vuelta a la escena de Hello World.

Por último, vamos a añadir un poco de la lógica de juego muy básica. En primer lugar, vamos a mantener un seguimiento de los proyectiles que el jugador ha destruido. Adiciona una variable miembro de la clase HelloWorldLayer en HelloWorldLayer.h de la siguiente manera:

int _projectilesDestroyed;

Dentro de HelloWorldLayer.m, agregue un import para la clase GameOverScene:

#import "GameOverScene.h"

Incrementa el contador y comprueba la condición de victoria en el método update dentro del ciclo targetsToDelete justo después de removeChild:target:

_projectilesDestroyed++;
if (_projectilesDestroyed > 30) {
  GameOverScene *gameOverScene = [GameOverScene node];
  _projectilesDestroyed = 0;
  [gameOverScene.layer.label setString:@"You Win!"];
  [[CCDirector sharedDirector] replaceScene:gameOverScene];
}

Y finalmente vamos a hacerlo de modo tal que si un objetivo logra cruzar, pierdes. Modifique el método spriteMoveFinished añadiendo el siguiente código dentro de la etiqueta == 1 derecho de caso después de removeChild: sprite:

GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:@"You Lose :["];
[[CCDirector sharedDirector] replaceScene:gameOverScene];

Ok, compila y ejecuta, ¡ahora debe tener condiciones de ganar y perder y ver la escena de juego terminado cuando sea apropiado!

¡Dame el código!

Y eso es todo! Aquí está el código completo para el sencillo juego de iPhone utilizando Cocos2D que hemos desarrollado hasta el momento.

¿A dónde ir desde aquí?

Este proyecto podría ser una buena base para probar un poco más con Cocos2D adicionando algunas características nuevas en el proyecto. Tal vez puede intentar añadir en un barra que muestre cuantos objetivos le quedan por destruir antes de ganar (vea el proyecto de ejemplo drawPrimitivesTest como muestra de cómo hacerlo). Pudiese agregar animaciones de muerte para cuando sean destruidos los monstruos (vea los proyectos ActionsTest, EffectsTest y EffectsAdvancedTest para eso). Quizás añadir más sonidos, arte o lógica de juego sólo por diversión. ¡El cielo es el límite!

Si desea seguir adelante con esta serie de tutoriales, eche un vistazo a la segunda parte, Cómo agregar una torreta giratoria, o la tercera parte, ¡Monstruos más fuertes y más niveles!

Además, si le gustaría seguir aprendiendo más acerca de Cocos2D, echa un vistazo a mis tutoriales sobre cómo crear botones en Cocos2D, introducción a Box2D, o cómo crear un juego sencillo de la reacción.

Siéntase libre de dejarnos saber de alguna manera mejor y diferente de hacer las cosas en este proyecto o si hay algún problema – como he dicho, ¡esta es la primera vez que he jugado con cocos2d así que tengo mucho por aprender!

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

Comentarios de los Usuarios

1 Comment

  • Hi Ray. I have recently configured cocos2d-x omy computer with Windows7. I'd like to deploy some of your sources code's examples but I amazed that those examples are only for Ios/XCode. can you please let me know how could I move forward with same examples but for Windows7/C++ ?? Thanks!
    FAVIO007

Other Items of Interest

Newsletter Mensual de Ray

Suscríbete para recibir un boletín mensual con mis enlaces favoritos sobre programación, ¡y recibe un tutorial de longitud épica gratis como bonus!

¡Anúnciate con nosotros!

Nuestros libros

Nuestro Equipo

Equipo de totorales

  • Julian Meyer
  • Matt Luedke

... 50 en total!

Update Team

... 15 en total!

Equipo Editorial

... 23 en total!

Code Team

  • Orta Therox

... 3 en total!

Equipo de Traducción

  • Takeichi Kanzaki Cabrera
  • David Xie
  • Sonic Zhao

... 33 en total!

Expertos en la Materia

  • Richard Casey

... 4 en total!