iOS7’s SpriteKit and Real 2.5D

An app I’ve been working on recently required a user interaction/experience similar to a Rolodex, as you swipe a view down it pulls out slightly and flips over and around exposing the next view below, while anchored to a central cylinder at the base.

Seeing as most developers are moving away from Cocos2D (which usually would have been my framework of choice for a fancy effect like this) in favour of iOS’s native SpriteKit, I decided to get my hands dirty with a bit of iOS7.

Generally this effect would be a pretty straight forward task with any kind of 2.5D engine. We move the anchor point to the base of the sprite, then rotate the sprite on the x-axis giving the effect of a page moving out towards the user and then back away as it flips.

Even though Apple themselves tout SpriteKit as being a 2.5D framework, it is not. What do I mean by 2.5D? Generally 2.5D suggests X, Y and Z axes upon which flat 2D sprites can rotate around and translate along, it’s not a real 3D space, just planes being manipulated to look like they have perspective. SpriteKit has no exposed Z axis, and no rotational capabilities along the X or Y axes. Sure it has a property called zPosition, but this shouldn’t be mistaken for a z axis, it’s simply an index of the visual display hierarchy. It doesn’t adjust the scale relative to the sprites position along it. It is possible to just use an X or Y scale from 1 to -1 to fake a flip of the sprite, but this too would not effect scale of the edges of the sprite giving them perspective in a 3D space. This is not 2.5D, hopefully Apple adds real 2.5D in a future release or someone has time to build a little 2.5D wrapper for SpriteKit, but until then if you want fancy 2.5D effects right now like parallax or 3D flipping, you’ll have to roll your own.  Currently SpriteKit is NOT 2.5D.

So why not just do the flip effect with views in UIKit, we can already do this using CATransform3D? Because I still need SpriteKit to do the heavy lifting of some bitmap animations in each of the Rolodex’s pages, and CATransform3D transforms the layer of a view, not a SKSpriteNode. However, there is a solution. All SKSpriteNodes live in scenes and all scenes live in SKViews, which is a subclass of UIView, so we can apply the transform to the SKView. It’s a sneaky little workaround, I wasn’t even sure it would work until I tried it, but it does.

Checkout the main chunks of code below and download the project file here. It’s simply the template Xcode SpriteKit project adjusted so has two views to create the two scenes. When you run the project tap the screen to add spaceships to the two planes (scenes), you’ll notice one of them rotating in 2.5D space.

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.rotAngle = 10;
    
    // Configure the back view.
    SKView * skViewBack = self.backView;
    
    // Create and configure the back scene.
    SKScene * sceneBack = [MyScene sceneWithSize:skViewBack.bounds.size];
    sceneBack.scaleMode = SKSceneScaleModeAspectFill;
    
    // Present the back scene.
    [skViewBack presentScene:sceneBack];
    
    
    // Configure the front view.
    SKView * skViewFront = self.frontView;
    
    // Create and configure the front scene.
    SKScene * sceneFront = [MyScene sceneWithSize:skViewFront.bounds.size];
    sceneFront.scaleMode = SKSceneScaleModeAspectFill;
   
    // Present the front scene.
    [skViewFront presentScene:sceneFront];
    
    //schedule a rotation method to animate the movement
    [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(rotateFrontViewOnXAxis) userInfo:nil repeats:YES];
}


- (void)rotateFrontViewOnXAxis
{
    self.rotAngle -= 10;
    
    float angle = (M_PI / 180.0f) * self.rotAngle/10;
    
    CATransform3D transform3DRotation = CATransform3DMakeRotation(angle, 1.0, 0.0, 0.0);
    
    self.frontView.layer.transform = transform3DRotation;
}

2 comments

  1. 2.5D in SpriteKit would be awesome.
    Two SKScene’s cannot really work together

    Reply

    1. Clearly this is more of an interesting approach I wanted to highlight than best practise. I agree 2.5D would be awesome. I do not recommend developers make games using multiple SKViews, however it does work and accomplished the goal described in the post.

      Reply

Leave a Reply to SDKBoy Cancel reply

Your email address will not be published. Required fields are marked *