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;
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"airPlanesBackground.png"];
background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
//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);
NSString *smokePath = [[NSBundle mainBundle] pathForResource:@"Smoke" ofType:@"sks"];
_smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile:smokePath];
_smokeTrail.position = CGPointMake(shadowDiff, -1*_plane.size.height);
//add shadow (now contains the plane image instead)
_planeShadow = [SKSpriteNode spriteNodeWithImageNamed:@"PLANE 8 N.png"];
_planeShadow.position = CGPointMake(shadowDiff, shadowDiff);
_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];