Construye un juego de aviones con SpriteKit: Explosiones y nubes
() translation by (you can also view the original English article)
Este tutorial te enseñará cómo usar el framework SpriteKit para crear un juego simple de aviones. En el camino, aprenderás todos los conceptos básicos de SpriteKit: 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 SpriteKit provisto con iOS 7.
- Construye un juego de aviones con SpriteKit: Configuración del proyecto
- Construye un juego de aviones con SpriteKit: Enemigos y emisores
- Construye un juego de aviones con SpriteKit: 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 tercera parte de nuestro juego de aviones con SpriteKit. En nuestra última publicación, nos enfocaremos en agregar enemigos y emisores al juego. En el tutorial de hoy, programarás la detección de colisiones, trabajarás con una textura atlas y crearás algunas explosiones para terminar el juego. ¡Empecemos!
1. Agregando la detección de colisiones
Las pruebas de intersección se utilizan con frecuencia en entornos donde existe más de un objeto. En SpriteKit, usarás Colisiones y Contactos para detectar si un objeto dado golpea a otro objeto.
En este juego, usarás la detección de colisiones. Cuando una bala hace contacto con un enemigo, tanto la bala como el enemigo serán eliminados de la pantalla.
Para hacer esto, necesitas definir los valores de máscara de categoría. Debe haber una categoría para cada objeto de física. En MyScene.h
, agrega el siguiente código:
1 |
static const uint8_t bulletCategory = 1; |
2 |
static const uint8_t enemyCategory = 2; |
Ahora, mientras todavía estás dentro de MyScene.h, agrega SKPhysicsContactDelegate
como lo hicimos antes con IAccelerometerDelegate
.
1 |
@interface MyScene : SKScene<UIAccelerometerDelegate, SKPhysicsContactDelegate> |
2 |
{
|
Antes de poder utilizar la física, debes iniciar la configuración de la física. En el condicional if (self = [super initWithSize:size])
, se instancia la gravedad con un valor 0 (es decir, sin gravedad) y luego el delegado de contacto:
1 |
self.physicsWorld.gravity = CGVectorMake(0, 0); |
2 |
self.physicsWorld.contactDelegate = self; |
Los dos cuerpos que necesitan física son la bala y los enemigos. Establezcamos varias propiedades para cada uno. Agreguemos el siguiente código dentro del método -(void)EnemiesAndClouds
:
1 |
enemy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:enemy.size]; |
2 |
enemy.physicsBody.dynamic = YES; |
3 |
enemy.physicsBody.categoryBitMask = enemyCategory; |
4 |
enemy.physicsBody.contactTestBitMask = bulletCategory; |
5 |
enemy.physicsBody.collisionBitMask = 0; |
El código anterior establece que el área de contacto del avión será un rectángulo del tamaño del sprite enemigo. La propiedad dinámica indica si la simulación física mueve el cuerpo físico. A continuación, categoryBitMask
es donde establece la categoría para el objeto, y contactTestBitMask
se refiere a los cuerpos con los que interactuarán los enemigos (en este caso, con balas).
Ahora definamos la física del objeto bala. Dentro del método de evento -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
, el código de la bala debe modificarse para agregar:
1 |
bullet.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:bullet.size]; |
2 |
bullet.physicsBody.dynamic = NO; |
3 |
bullet.physicsBody.categoryBitMask = bulletCategory; |
4 |
bullet.physicsBody.contactTestBitMask = enemyCategory; |
5 |
bullet.physicsBody.collisionBitMask = 0; |
Hasta ahora, has definido las propiedades de las colisiones. Sin embargo, debemos detectar si se realiza un contacto.
Debes utilizar el método didBeginContact
para saber qué objetos tienen contacto con otros objetos. Por lo tanto, el siguiente código calcula los dos cuerpos que han establecido contacto y simultáneamente los elimina de la escena:
1 |
-(void)didBeginContact:(SKPhysicsContact *)contact{ |
2 |
|
3 |
SKPhysicsBody *firstBody; |
4 |
SKPhysicsBody *secondBody; |
5 |
|
6 |
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) |
7 |
{
|
8 |
firstBody = contact.bodyA; |
9 |
secondBody = contact.bodyB; |
10 |
}
|
11 |
else
|
12 |
{
|
13 |
firstBody = contact.bodyB; |
14 |
secondBody = contact.bodyA; |
15 |
}
|
16 |
|
17 |
if ((firstBody.categoryBitMask & bulletCategory) != 0) |
18 |
{
|
19 |
|
20 |
SKNode *projectile = (contact.bodyA.categoryBitMask & bulletCategory) ? contact.bodyA.node : contact.bodyB.node; |
21 |
SKNode *enemy = (contact.bodyA.categoryBitMask & bulletCategory) ? contact.bodyB.node : contact.bodyA.node; |
22 |
[projectile runAction:[SKAction removeFromParent]]; |
23 |
[enemy runAction:[SKAction removeFromParent]]; |
24 |
|
25 |
}
|
26 |
|
27 |
}
|
Bastante simple, ¿verdad? Ahora, compila y ejecuta. Si todo salió bien, el enemigo y la bala desaparecerán cuando colisionen.
2. Incorporación de una textura atlas
Nuestro juego está casi completo, pero necesita algo de acción y animación. Los siguientes dos pasos agregarán explosiones y algunas animaciones de fondo hechas de nubes.
Hasta ahora, no hemos utilizado la textura atlas. SpriteKit incluye un generador de textura atlas que tiene varias características interesantes. En Xcode 5, puedes crear una textura atlas con los siguientes pasos:
- Coloca todos los sprites en una sola carpeta. Para nuestro proyecto, puedes encontrar todas las imágenes en la descarga adjunta dentro de la carpeta "EXPLOSION".
- Cambia la extensión de la carpeta a *.atlas. En nuestro caso, cambia el nombre de EXPLOSION a EXPLOSION.atlas.
- Arrastra y suelta la carpeta en el proyecto. Lo agregué a la carpeta "Supporting Files" dentro del navegador Xcode.
- Asegúrate de que la opción "Habilitar generación de texturas altas" esté activada. Para verificar esto, ve a la Configuración de compilación de tu proyecto.
Eso es. Una vez más, las imágenes de esta parte están disponibles en la carpeta "Resources" de la descarga adjunta.
Ahora, debes cargar la textura atlas en el proyecto.
Dentro de MyScene.h
agrega:
1 |
@property NSMutableArray *explosionTextures; |
Al final del condicional if (self = [super initWithSize:size])
, agrega el siguiente fragmento de código:
1 |
//load explosions
|
2 |
SKTextureAtlas *explosionAtlas = [SKTextureAtlas atlasNamed:@"EXPLOSION"]; |
3 |
NSArray *textureNames = [explosionAtlas textureNames]; |
4 |
_explosionTextures = [NSMutableArray new]; |
5 |
for (NSString *name in textureNames) { |
6 |
SKTexture *texture = [explosionAtlas textureNamed:name]; |
7 |
[_explosionTextures addObject:texture]; |
8 |
}
|
3. Agregar explosiones
Una vez que tengas las explosiones cargadas, se necesita otro paso para verlas en acción. Ahora crearás una explosión que se producirá cuando una bala golpee a un enemigo. Al final del if condicional if ((firstBody.categoryBitMask & bulletCategory) != 0)
, agrega el siguiente fragmento:
1 |
//add explosion
|
2 |
SKSpriteNode *explosion = [SKSpriteNode spriteNodeWithTexture:[_explosionTextures objectAtIndex:0]]; |
3 |
explosion.zPosition = 1; |
4 |
explosion.scale = 0.6; |
5 |
explosion.position = contact.bodyA.node.position; |
6 |
|
7 |
[self addChild:explosion]; |
8 |
|
9 |
SKAction *explosionAction = [SKAction animateWithTextures:_explosionTextures timePerFrame:0.07]; |
10 |
SKAction *remove = [SKAction removeFromParent]; |
11 |
[explosion runAction:[SKAction sequence:@[explosionAction,remove]]]; |
Compila y ejecuta el proyecto para probar la animación de colisión y explosión. Deberías ver algo como la siguiente figura:



4. Agregar nubes
¡Casi hemos terminado el juego! Este es solo el último toque. Ahora necesitas crear el atlas de nubes y luego cargar la textura Atlas en la memoria.
Antes de escribir el código para este paso, asegúrate de agregar la extensión .atlas a la carpeta "Clouds" en la descarga adjunta y de arrastrarla a tu proyecto.
Dentro del archivo MyScene.h
agrega lo siguiente:
1 |
@property NSMutableArray *cloudsTextures; |
Dentro del archivo MyScene.m
, debajo del código comentado que dice "load explosions", agrega lo siguiente:
1 |
//load clouds
|
2 |
SKTextureAtlas *cloudsAtlas = [SKTextureAtlas atlasNamed:@"Clouds"]; |
3 |
NSArray *textureNamesClouds = [cloudsAtlas textureNames]; |
4 |
_cloudsTextures = [NSMutableArray new]; |
5 |
for (NSString *name in textureNamesClouds) { |
6 |
SKTexture *texture = [cloudsAtlas textureNamed:name]; |
7 |
[_cloudsTextures addObject:texture]; |
8 |
}
|
El último paso es generar nubes de forma aleatoria y presentarlas en pantalla con algo de movimiento. Debes agregar el siguiente fragmento al final del método EnemiesAndClouds
:
1 |
//random Clouds
|
2 |
int randomClouds = [self getRandomNumberBetween:0 to:1]; |
3 |
if(randomClouds == 1){ |
4 |
|
5 |
int whichCloud = [self getRandomNumberBetween:0 to:3]; |
6 |
SKSpriteNode *cloud = [SKSpriteNode spriteNodeWithTexture:[_cloudsTextures objectAtIndex:whichCloud]]; |
7 |
int randomYAxix = [self getRandomNumberBetween:0 to:screenRect.size.height]; |
8 |
cloud.position = CGPointMake(screenRect.size.height+cloud.size.height/2, randomYAxix); |
9 |
cloud.zPosition = 1; |
10 |
int randomTimeCloud = [self getRandomNumberBetween:9 to:19]; |
11 |
|
12 |
SKAction *move =[SKAction moveTo:CGPointMake(0-cloud.size.height, randomYAxix) duration:randomTimeCloud]; |
13 |
SKAction *remove = [SKAction removeFromParent]; |
14 |
[cloud runAction:[SKAction sequence:@[move,remove]]]; |
15 |
[self addChild:cloud]; |
16 |
}
|
Compila y ejecuta el proyecto una vez más. Si todo va bien, deberías ver algo como la siguiente figura:



Conclusión
Con esto concluye el tercer y último tutorial que te enseña cómo crear un juego de aviones utilizando el nuevo framework SpriteKit disponible con el SDK de iOS 7. Si has seguido esta serie de principio a fin, ahora deberías tener el conocimiento suficiente para crear un juego simple en SpriteKit usando este nuevo motor de juego dinámico. Si tienes alguna pregunta o comentario, no dudes en dejarlos a continuación.
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.