Advertisement

Build an Airplane Game with Sprite Kit - Enemies & Emitters

This tutorial will teach you how to use the Sprite Kit framework to create a simple Airplanes game. Along the way, you'll learn all the core concepts of Sprite Kit: animations, emitters, collision detection, and more!


Series Format

The Airplanes tutorial will be divided into three parts in order to completely cover each section. After reading the three part tutorial, the readers will be able to create an interesting 2D game using the new Sprite Kit framework provided with iOS 7.

Each part will produce a practical result, and the sum of all parts will produce the final game. While each part of the series can be read independently, we recommend following along step-by-step for a complete understanding of the topic presented. The source code for the game is provided incrementally with each post.


Final Preview

Figure 1: Final Result!

Illustration of Final Result - Sprite Kit.

Where We Left Off...

Welcome back to the second part of our Airplanes game with Sprite Kit. In today's tutorial, you will program one emitter that will form the smoke trail of an airplane. This tutorial part focuses on several things like movements, touches, and so on, but we'll explain everything further below. If you haven't yet completed Part 1 of the series, you can download the project from part 1 and pickup exactly where we left off.


1. Adding a Smoke Trail

Particles are used to achieve many different types of effects like fire, smoke, magic, rain, snow, or waterfalls. In this case, we will use them to create a smoke trail for your airplane. The particle will stay activated for the duration of the game.

Fortunately, Xcode 5 introduced an Emitter Editor as a builtin feature. This is an extremely useful tool and will allow us to easily edit properties like particle texture, background color, birthrate particle, maximum particles, lifetime, position, range, angle, speed, acceleration, scale, rotation, and more. By default, Xcode 5 also provides several turnkey Emitters ready for use. So, lets start and add one emitter to our game.

The particle images needed are available within the Resources folder of the attached download.

To add one emitter to your game, you need to go to File > New > File... You will see something like the following image:

Figure 1: Creating SpriteKit Emitter File

Illustration of the Creation of SpriteKit Emitter File (Xcode).

Select the iOS > Resource and SpriteKit Particle File option (as in the aforementioned figure). Click Next. Now, you will be asked what template you want to use. That are 8 different templates available. Select the smoke template and click on Next, then give it a name (we named ours "trail") and click Create. Xcode will add two new files to your project (trail.sks and spark.png). You need to change the number of particles, the texture, the position range, the angle, and the scale for best results. Take a look at our configuration:

Figure 2: Emitter properties

Illustration of the Emitter Properties (Xcode).

Now, let's add the smoke to our plane.

Within MyScene.h, add a smoke trail property:

@property SKEmitterNode *smokeTrail;

At the end of the if (self = [super initWithSize:size]) conditional in MyScene.m, add the following snippet:

        //adding the smokeTrail
        NSString *smokePath = [[NSBundle mainBundle] pathForResource:@"Smoke" ofType:@"sks"];
        _smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath];
        _smokeTrail.position = CGPointMake(screenWidth/2, 15);
        [self addChild:_smokeTrail];

Of course, when the airplane moves, the trail needs to move too. At the end of the -(void)update:(NSTimeInterval)currentTime method, add this line:

_smokeTrail.position = CGPointMake(newX,newY-(_plane.size.height/2));

Build and run the project and if everything went well it will be awesome!

You should see something like the following:

Figure 3: Emitter properties

Illustration of the Emitter Properties (Xcode).

2. Add & Move Enemies

So far, you just have the airplane moving around the screen. But the fun starts when more airplanes become available. So, let's add some enemy airplanes!

Not only do you need to create enemies, but you also need to define a random path for each in order to simulate a real battlefield. To achieve this, you will use the action followPath. You will create random paths (with CGPath) and then each enemy will move over that path.

One great method that we had to do this with Cocos2D was schedule:interval:. Unfortunately, Apple did not add a similar method to Sprite Kit, but it is easy to create a similar one using SKActions. To achieve this schedule, we need to create an SKAction calling for a method waitForDuration. After that, we will create an SKAction that can run a block and use it to call the method that adds enemies. Then, we'll put these two actions on a sequence and just say to repeat it over time.

To recreate the explanation you will only need the following snippet. Add it to the end of the if conditional if (self = [super initWithSize:size] ):

//schedule enemies
SKAction *wait = [SKAction waitForDuration:1];
SKAction *callEnemies = [SKAction runBlock:^{
    [self EnemiesAndClouds];
}];
        
SKAction *updateEnimies = [SKAction sequence:@[wait,callEnemies]];
[self runAction:[SKAction repeatActionForever:updateEnimies]];

Easy enough? If you have any questions, do not hesitate to ask them within the comments section.

Now you must add the method that creates the movement paths for the enemies to follow. We choose to use the CGPathAddCurveToPoint, since this method creates a Bézier curve with two control points. The following image explains how this works:

Figure 3: Bezier Curve

Illustration of the Bézier Curve Creation (Xcode).

So, you need to add the following code to our MyScene.m file:

-(void)EnemiesAndClouds{
    //not always come
    int GoOrNot = [self getRandomNumberBetween:0 to:1];
    
    if(GoOrNot == 1){
        
        SKSpriteNode *enemy;
        
        int randomEnemy = [self getRandomNumberBetween:0 to:1];
        if(randomEnemy == 0)
            enemy = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 1 N.png"];
        else
            enemy = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 2 N.png"];
        
        
        enemy.scale = 0.6;
        
        enemy.position = CGPointMake(screenRect.size.width/2, screenRect.size.height/2);
        enemy.zPosition = 1;
        
        
        CGMutablePathRef cgpath = CGPathCreateMutable();
        
        //random values
        float xStart = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
        float xEnd = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
        
        //ControlPoint1
        float cp1X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
        float cp1Y = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.height ];
        
        //ControlPoint2
        float cp2X = [self getRandomNumberBetween:0+enemy.size.width to:screenRect.size.width-enemy.size.width ];
        float cp2Y = [self getRandomNumberBetween:0 to:cp1Y];
        
        CGPoint s = CGPointMake(xStart, 1024.0);
        CGPoint e = CGPointMake(xEnd, -100.0);
        CGPoint cp1 = CGPointMake(cp1X, cp1Y);
        CGPoint cp2 = CGPointMake(cp2X, cp2Y);
        CGPathMoveToPoint(cgpath,NULL, s.x, s.y);
        CGPathAddCurveToPoint(cgpath, NULL, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y);
        
        SKAction *planeDestroy = [SKAction followPath:cgpath asOffset:NO orientToPath:YES duration:5];
        [self addChild:enemy];
        
        SKAction *remove = [SKAction removeFromParent];
        [enemy runAction:[SKAction sequence:@[planeDestroy,remove]]];
        
        CGPathRelease(cgpath);
        
    }
    
}

-(int)getRandomNumberBetween:(int)from to:(int)to {
    
    return (int)from + arc4random() % (to-from+1);
}

The enemiesAndClouds method only adds Enemies for now. We'll wait to add clouds in the third and final part of this series.

The essence of this method is generating random values. First, it will decide if a new enemy will be released, then it creates its position. Afterward, it creates the enemy control points, and, finally, the actions are created.

When we add or remove a sprite to the screen, we need to make sure the memory allocation and deallocation is treated with care and success. The action removeFromParent takes care of this for us.

Now, build and run the project and watch as enemies begin to appear on the screen.

Figure 3: Enemies

Illustration of the Enemies (Xcode).

3. Create Airplane Bullets

To make the game fun, our enemies need to be destroyable. You will add some bullets to your airplane to achieve this. To do this, we'll need to do the following:

  • Get the current airplane position
  • Create the bullet sprite
  • Create the action to move the bullet
  • Create the action to remove the bullet
  • Add the bullet to the screen

Replace the touchesBegan method with the following snippet:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */
    
    CGPoint location = [_plane position];
    SKSpriteNode *bullet = [SKSpriteNode spriteNodeWithImageNamed:@"B 2.png"];
    
    bullet.position = CGPointMake(location.x,location.y+_plane.size.height/2);
    //bullet.position = location;
    bullet.zPosition = 1;
    bullet.scale = 0.8;
    
    SKAction *action = [SKAction moveToY:self.frame.size.height+bullet.size.height duration:2];
    SKAction *remove = [SKAction removeFromParent];
    
    [bullet runAction:[SKAction sequence:@[action,remove]]];
    
    [self addChild:bullet];    
}

Build and run your project. If you want to fire a bullet you only need to tap the screen!


Conclusion

You've reached the end of the second tutorial in our series.

At this point, you should understand and be able to perform the following tasks:

  • Create an Emitter
  • Add bullets to sprites
  • Create bézier paths for sprite movement

Stay tuned for the next installment in this series, where we will continue to build our airplane game!


Acknowledgements & Recommendations

We would like to thank Daniel Ferenčak for providing us with the game art used to produce this tutorial series.

In order to fully appreciate the tutorial series, we advise that you test our code by deploying it to a real device running iOS 7. You will need Xcode 5 and the latest iOS 7 SDK. If you don't already have these tools, you can download them from the Apple Developer Center. Once downloaded, install the software and you'll be ready to begin.

Advertisement