Moving from Cocos2D to SpritKit
We have recently moved from Cocos2D to using SpriteKit as our game development framework. In the process we have been experimenting with the various aspects of developing with SpriteKit. This will be the first in a series of posts sharing what we have learned along the way.
What is scaleMode?
The scaleMode of a scene determines how the scene will be updated to fill the view when the iOS device is rotated. There are four different scaleModes defined:
- SKSceneScaleModeFill – the x and y axis are each scaled up or down so that the scene fills the view. The content of the scene will not maintain its current aspect ratio. This is the default if you do not specify a scaleMode for your scene.
- SKSceneScaleModeAspectFill – both the x and y scale factors are calculated. The larger scale factor will be used. This ensures that the view will be filled, but will usually result in parts of the scene being cropped. Images in the scene will usually be scaled up but will maintain the correct aspect ratio.
- SKSceneScaleModeAspectFit – both the x and y scale factors are calculated. The smaller scale factor will be used. This ensures that the entire scene will be visible, but will usual result in the scene being letterboxed. Images in the scene will usually be scaled down but will maintain the correct aspect ratio.
- SKSceneScaleModeResizeFill – The scene is not scaled. It is simply resized so that its fits the view. Because the scene is not scaled, the images will all remain at their original size and aspect ratio. The content will all remain relative to the scene origin (lower left).
For these examples we will use the default spritekit template that is generated when you start a new spriteKit project. I named my project ExporingScaleMode and setup to be an iPad only project.
Next we will go to myScene.m and remove the touchBegins event handler since we are not going to be using that. We will then add code to the initWithSize method to add two copies of the spaceship sprite. One in the lower left corner of the screen and the other in the upper right.
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@”Spaceship”];
sprite.anchorPoint = CGPointMake(0.0,0.0);
sprite.position = CGPointMake(0,0);
SKSpriteNode *sprite2 = [SKSpriteNode spriteNodeWithImageNamed:@”Spaceship”];
sprite2.anchorPoint = CGPointMake(1.0,1.0);
sprite2.position = CGPointMake(self.frame.size.width, self.frame.size.height);
Now go ahead an run the project in the iPad simulator. You should see a screen like this, with one spaceship in the lower left, another in the upper right, and the “Hello, World!” text in the center.
Now lets try each of the different scaleModes and see what happens when we change from portrait to landscape view. Go to the viewController.m and update the scene.scaleMode to each of the modes listed below, run the simulator, and then rotate the simulator so you are looking at the results in landscape rather then portrait.
SKSceneScaleModeFill – As you can see SKSceneScaleModeFill does not maintain the aspect ration when the scene is scaled. But, it does ensure that everything in the scene is shown.
SKSceneScaleModeAspectFill – this was the mode that was originally set in the project template. With this mode the spaceship images are slightly larger then the originals. This is because the scene was scaled up so that the portrait width matches the landscape width. The scene does completely fill the view but the images on the top and bottom are now cropped.
SKSceneScaleModeAspectFit – This scale mode does enable you to see the entire scene. The scene has been scaled down so that the portrait height now equals the landscape hight. As a result the images are smaller and we now have letterboxing on the left and right of the scene.
SKSceneScaleModeResizeFill – This final scale mode is the only one in which the original images are the same size and aspect in both portrait and landscape. But, as you can see the content is positioned relative to the origin (lower left) so the image that was in the upper right is now partially cropped and no longer on the far right. Additionally the text is not centered in the screen.
Well that is all very interesting but, what conclusion can we draw from this. The first conclusion is that it would be very challenging to build a game that worked in both portrait and landscape. It can be done but you would probably need to rearrange the content whenever the user rotated the view. I also think that the best scale mode to be using is SKSceneScaleModeResizeFill. This mode maintains the size and aspect ratio of your content in both portrait and landscape views.
I believe this also gives some insight in how to setup your scene when you want to maintain the landscape only view. But, I will save that for the next post.