Sunday, 1 December 2013

Slight improvement to the Airplane Tutorial by Jorge Costa and Orlando Pereira

Was learning Sprite Kit and found this excellent tutorial Build An Airplane Game with Sprite Kit by Jorge Costa and Orlando Pereira.

However, I don't quite like the idea of treating the plane, the plane shadow, the propeller and the smoke as 4 separate SpriteNode objects. As with every movement of the plane, you have to calculate and adjust the positions 4 times.

I made some adjustment to add the plane shadow, the propeller and the smoke all as child of the plane. This way, when the plane moves, all it's child will also move accordingly.

However there are some slight issues:
(a) the child SpriteNode will also scale accordingly when the main SpriteNode was scaled
(b) don't know how to adjust the "zPosition" of the child SpriteNode, they seems to just add on top of each order according to the order it's been added. So I have to swap the plane and the plane shadow, and add the smoke before the plane image so that the smoke is under the plane image, and add the propeller last. ==> This would obviously have some impact to the collision detection part if the shadow is too far apart from the plane, as they have now been swapped, and the collision has to be adjusted too.

The modified code in -(id)initWithSize:(CGSize)size as below, note that as I was using iPhone instead of iPad, you might have to change the parameters a bit to fit into iPad screen.

Best part of this change is, I can now remove all those codes for updating propeller/shadow/smoke position from the "update()" method and would definitely make the plane movement more responsive.

        float planeScale = 0.3;
        shadowDiff = 20.0;
        propellerDiff = 30.0;
        //background image
        SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"airPlanesBackground.png"];
        background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
        [self addChild:background];
        //add plane (now contains the shadow image instead)
        _plane = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 8 SHADOW.png"];
        _plane.scale = planeScale;
        _plane.position = CGPointMake(screenWidth/2, 1+_plane.size.height * 0.5);

        //add smoke
        NSString *smokePath = [[NSBundle mainBundle] pathForResource:@"Smoke" ofType:@"sks"];
        _smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath];
        _smokeTrail.position = CGPointMake(shadowDiff, -1*_plane.size.height);
        [_plane addChild:_smokeTrail];
        //add shadow (now contains the plane image instead)
        _planeShadow = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 8 N.png"];
        _planeShadow.position = CGPointMake(shadowDiff, shadowDiff);
        [_plane addChild:_planeShadow];
        //add propeller
        _propeller = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE PROPELLER 1.png"];
        _propeller.position = CGPointMake(shadowDiff, shadowDiff+_plane.size.height*1.4);
        SKTexture *propeller1 = [SKTexture textureWithImageNamed:@"PLANE PROPELLER 1.png"];
        SKTexture *propeller2 = [SKTexture textureWithImageNamed:@"PLANE PROPELLER 2.png"];
        SKAction *spin = [SKAction animateWithTextures:@[propeller1, propeller2] timePerFrame:0.1];
        SKAction *spinForever = [SKAction repeatActionForever:spin];
        [_propeller runAction:spinForever];
        [_plane addChild:_propeller];

        [self addChild:_plane];


  1. Thank you for posting!

    However, children and zPosition is really straight forward and logical. The children simply inherits the position off of their parents, so to put the shadow below the plane, just call:

    _planeShadow.zPosition = -1;

    Problem solved!

  2. I was checking the original tutorial comments to see if anyone else had suggested making the plane components child objects to the plane and saw that you already did. Good catch. I tried this myself first and understand why you switched the plane and the shadow images (the shadow was on top of the plane). I did want to suggest that you could leave the plane image in the first node and just set the zPosition of the shadow to -1 in the second node. This worked for me.

    1. thanks for the info, same as above, that's a good idea.