Construye un juego de aviones con Sprite Kit: Enemigos y emisores
() translation by (you can also view the original English article)
Este tutorial te enseñará cómo usar el framework Sprite Kit para crear un juego simple de aviones. En el camino, aprenderás todos los conceptos básicos de Sprite Kit: animaciones, emisores, detección de colisiones y más.
Formato de la serie
El tutorial del juego de aviones se dividirá en tres partes para cubrir completamente cada sección. Después de leer el tutorial de tres partes, los lectores podrán crear un juego 2D interesante utilizando el nuevo framework Sprite Kit provisto con iOS 7.
- Construye un juego de aviones con Sprite Kit: Configuración del proyecto
- Construye un juego de aviones con Sprite Kit: Enemigos y emisores
- Construye un juego de aviones con Sprite Kit: Explosiones y nubes
Cada parte producirá un resultado práctico y la suma de todas las partes producirá el juego final. Si bien cada parte de la serie se puede leer de forma independiente, recomendamos seguir la serie paso a paso para una comprensión completa del tema presentado. El código fuente del juego se proporciona de forma incremental con cada publicación.
Vista previa del final



Donde lo dejamos...
Bienvenido de nuevo a la segunda parte de nuestro juego de aviones con Sprite Kit. En el tutorial de hoy, programarás un emisor que formará la estela de humo de un avión. Esta parte del tutorial se centra en varias cosas como movimientos, toques, etc., pero explicaremos todo más adelante. Si aún no has completado la parte 1 de la serie, puedes descargar el proyecto de la parte 1 y continuar exactamente donde lo dejamos.
1. Agregar un rastro de humo
Las partículas se utilizan para lograr diferentes tipos de efectos como fuego, humo, magia, lluvia, nieve o cascadas. En este caso, los usaremos para crear un rastro de humo para tu avión. La partícula permanecerá activada durante la duración del juego.
Afortunadamente, Xcode 5 introdujo un editor de emisores como función incorporada. Esta es una herramienta extremadamente útil y nos permitirá editar fácilmente propiedades como textura de partículas, color de fondo, partícula de tasa de nacimiento, partículas máximas, vida útil, posición, rango, ángulo, velocidad, aceleración, escala, rotación y más. De forma predeterminada, Xcode 5 también proporciona varios emisores llave en mano listos para usar. Bien, comencemos y agreguemos un emisor a nuestro juego.
Para agregar un emisor a tu juego, debes ir a Archivo > Nuevo > Archivo...
Verás algo como la siguiente imagen:



Selecciona la opción iOS > Recurso y archivo de partículas SpriteKit
(como en la figura mencionada anteriormente). Haz clic en Siguiente. Ahora, se te preguntará qué plantilla deseas utilizar. Hay 8 plantillas diferentes disponibles. Selecciona la plantilla de humo y haz clic en Siguiente, luego asígnale un nombre (llamamos al nuestro "trail") y haz clic en Crear. Xcode agregará dos archivos nuevos a tu proyecto (trail.sks y spark.png). Necesitas cambiar el número de partículas, la textura, el rango de posición, el ángulo y la escala para obtener mejores resultados. Echa un vistazo a nuestra configuración:

Ahora, agreguemos el humo a nuestro avión.
Dentro de MyScene.h
, agrega una propiedad de rastro de humo:
1 |
@property SKEmitterNode *smokeTrail; |
Al final del condicional if (self = [super initWithSize:size])
en My Scene.m
, agrega el siguiente fragmento:
1 |
//adding the smokeTrail
|
2 |
NSString *smokePath = [[NSBundle mainBundle] pathForResource:@"Smoke" ofType:@"sks"]; |
3 |
_smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath]; |
4 |
_smokeTrail.position = CGPointMake(screenWidth/2, 15); |
5 |
[self addChild:_smokeTrail]; |
Por supuesto, cuando el avión se mueve, el camino también debe moverse. Al final del método -(void)update:(NSTimeInterval)currentTime
, agrega esta línea:
1 |
_smokeTrail.position = CGPointMake(newX,newY-(_plane.size.height/2)); |
¡Compila y ejecuta el proyecto y si todo salió bien, será increíble!
Deberías ver algo como lo siguiente:



2. Agregar y mover enemigos
Hasta ahora, solo tienes el avión moviéndose alrededor de la pantalla. Pero la diversión comienza cuando hay más aviones disponibles. Así que, ¡agreguemos algunos aviones enemigos!
No solo necesitas crear enemigos, sino que también necesitas definir una ruta aleatoria para cada uno con el fin de simular un campo de batalla real. Para lograr esto, utilizarás la acción followPath
. Crearás caminos aleatorios (con CGPath) y luego cada enemigo se moverá por ese camino.
Un gran método que tuvimos para hacer esto con Cocos2D fue schedule:interval:
. Desafortunadamente, Apple no agregó un método similar a Sprite Kit, pero es fácil crear uno similar usando SKActions
. Para lograr este programa, necesitamos crear una llamada SKAction
para un método waitForDuration
. Después de eso, crearemos un SKAction que puede ejecutar un bloque y usarlo para llamar al método que agrega enemigos. Luego, colocaremos estas dos acciones en una secuencia y solo diremos que las repitas con el tiempo.
Para recrear la explicación, solo necesitarás el siguiente fragmento. Agrégalo al final del condicional "if" if (self = [super initWithSize:size] )
:
1 |
//schedule enemies
|
2 |
SKAction *wait = [SKAction waitForDuration:1]; |
3 |
SKAction *callEnemies = [SKAction runBlock:^{ |
4 |
[self EnemiesAndClouds]; |
5 |
}];
|
6 |
|
7 |
SKAction *updateEnimies = [SKAction sequence:@[wait,callEnemies]]; |
8 |
[self runAction:[SKAction repeatActionForever:updateEnimies]]; |
¿Suficientemente fácil? Si tienes alguna duda, no dudes en plantearla dentro de la sección de comentarios.
Ahora debes agregar el método que crea las rutas de movimiento para que las sigan los enemigos. Elegimos utilizar CGPathAddCurveToPoint
, ya que este método crea una curva de Bézier con dos puntos de control. La siguiente imagen explica cómo funciona esto:

Por lo tanto, debes agregar el siguiente código a nuestro archivo MyScene.m
:
1 |
-(void)EnemiesAndClouds{ |
2 |
//not always come
|
3 |
int GoOrNot = [self getRandomNumberBetween:0 to:1]; |
4 |
|
5 |
if(GoOrNot == 1){ |
6 |
|
7 |
SKSpriteNode *enemy; |
8 |
|
9 |
int randomEnemy = [self getRandomNumberBetween:0 to:1]; |
10 |
if(randomEnemy == 0) |
11 |
enemy = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 1 N.png"]; |
12 |
else
|
13 |
enemy = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 2 N.png"]; |
14 |
|
15 |
|
16 |
enemy.scale = 0.6; |
17 |
|
18 |
enemy.position = CGPointMake(screenRect.size.width/2, screenRect.size.height/2); |
19 |
enemy.zPosition = 1; |
20 |
|
21 |
|
22 |
CGMutablePathRef cgpath = CGPathCreateMutable(); |
23 |
|
24 |
//random values
|
25 |
float xStart = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ]; |
26 |
float xEnd = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ]; |
27 |
|
28 |
//ControlPoint1
|
29 |
float cp1X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ]; |
30 |
float cp1Y = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.height ]; |
31 |
|
32 |
//ControlPoint2
|
33 |
float cp2X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ]; |
34 |
float cp2Y = [self getRandomNumberBetween:0 to:cp1Y]; |
35 |
|
36 |
CGPoint s = CGPointMake(xStart, 1024.0); |
37 |
CGPoint e = CGPointMake(xEnd, -100.0); |
38 |
CGPoint cp1 = CGPointMake(cp1X, cp1Y); |
39 |
CGPoint cp2 = CGPointMake(cp2X, cp2Y); |
40 |
CGPathMoveToPoint(cgpath,NULL, s.x, s.y); |
41 |
CGPathAddCurveToPoint(cgpath, NULL, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y); |
42 |
|
43 |
SKAction *planeDestroy = [SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:5]; |
44 |
[self addChild:enemy]; |
45 |
|
46 |
SKAction *remove = [SKAction removeFromParent]; |
47 |
[enemy runAction:[SKAction sequence:@[planeDestroy,remove]]]; |
48 |
|
49 |
CGPathRelease(cgpath); |
50 |
|
51 |
}
|
52 |
|
53 |
}
|
54 |
|
55 |
-(int)getRandomNumberBetween:(int)from to:(int)to { |
56 |
|
57 |
return (int)from + arc4random() % (to-from+1); |
58 |
}
|
El método enemiesAndClouds
solo agrega enemigos por ahora. Esperaremos para agregar nubes en la tercera y última parte de esta serie.
La esencia de este método es generar valores aleatorios. Primero, decidirá si se liberará a un nuevo enemigo, luego creará su posición. Después, crea los puntos de control enemigos y, finalmente, se crean las acciones.
removeFromParent
se encarga de esto por nosotros. Ahora, compila y ejecuta el proyecto y observa cómo los enemigos comienzan a aparecer en la pantalla.



3. Crear balas para el avión
Para que el juego sea divertido, nuestros enemigos deben ser destruibles. Para eso vamos a agregar algunas balas a tu avión para lograrlo, y necesitaremos hacer lo siguiente:
- Obtener la posición actual del avión.
- Crear el sprite de la bala.
- Crear la acción para mover la bala.
- Crear la acción para eliminar la bala.
- Agrega la bala a la pantalla.
Reemplaza el método touchesBegan
con el siguiente fragmento:
1 |
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { |
2 |
/* Called when a touch begins */
|
3 |
|
4 |
CGPoint location = [_plane position]; |
5 |
SKSpriteNode *bullet = [SKSpriteNode spriteNodeWithImageNamed:@"B 2.png"]; |
6 |
|
7 |
bullet.position = CGPointMake(location.x,location.y+_plane.size.height/2); |
8 |
//bullet.position = location;
|
9 |
bullet.zPosition = 1; |
10 |
bullet.scale = 0.8; |
11 |
|
12 |
SKAction *action = [SKAction moveToY:self.frame.size.height+bullet.size.height duration:2]; |
13 |
SKAction *remove = [SKAction removeFromParent]; |
14 |
|
15 |
[bullet runAction:[SKAction sequence:@[action,remove]]]; |
16 |
|
17 |
[self addChild:bullet]; |
18 |
}
|
Compila y ejecuta tu proyecto. ¡Si quieres disparar una bala solo necesitas tocar la pantalla!
Conclusión
Has llegado al final del segundo tutorial de nuestra serie.
En este punto, debes comprender y poder realizar las siguientes tareas:
- Crear un emisor
- Agregar balas a los sprites
- Crear caminos bézier para el movimiento de los sprites
¡Estén atentos para la próxima entrega de esta serie, donde continuaremos construyendo nuestro juego de aviones!
Agradecimientos y recomendaciones
Nos gustaría agradecer a Daniel Ferenčak por proporcionarnos el arte del juego utilizado para producir esta serie de tutoriales.
Para apreciar completamente la serie de tutoriales, te recomendamos que pruebes nuestro código implementándolo en un dispositivo real con iOS 7. Necesitarás Xcode 5 y el último SDK de iOS 7. Si aún no tienes estas herramientas, puedes descargarlas desde el Centro de desarrolladores de Apple. Una vez descargado, instala el software y estarás listo para comenzar.