Wednesday, February 27, 2019

How To: Update Your old SpriteKit Game to be Compatible with iPhone X, XS, XR, XS Max

Yoooo wazaaaaapppppp...

Ok, first, a witty intro (again?).

We often hear people say do not disturb a developer or programmer. But often we do not understand why. It is not the same as disturbing someone who is doing a regular office job. When a programmer is coding, he is actually building a Millenium Falcon lego model in his head. All the parts are assembled in his head in groups. Once you disturb a programmer, all the groups that are built in his head (but not yet assembled), will crumble and he will have to start over from zero.

Take my advice: If you see programmer coding, DO NOT SAY ANYTHING TO HIM. DO NOT EVEN COME NEAR. 

Anyway, lets go on with the tutorial:

I actually have 2 blog posts that are WIP. Haven't got the time to finish them yet. But, as I update my SpriteKit game, I notice something weird that is happening to the Scenes in iPhone Notch. iPhone Notch is what I call all the iPhones that have notch in them like - iPhone X, XS, XR, XS Max. Check out one of my game screen when run on iPhone Notch:

Basically, the whole scene get stretched and the bottom bar and title overlapped with notch and bottom line (i think it is the control center slide up menu). I saw many people on the Stackoverflow were asking similar questions, and most resort to REPOSITIONING all the sprites. This is crazy! No way in hell I am going to do so much work! There are not just one scene! 

As a lazy ass bum developer, I went ahead and try a few things in ViewController instead without touching any of the Scenes. Lo and behold, I found solution:

-(void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    if (!layoutDone) {
        layoutDone = YES;
        // Configure the view.
        SKView * skView = (SKView *)self.view;
        skView.multipleTouchEnabled = NO;

        // Create and configure the scene.
        SKScene * scene = [GameScene sceneWithSize:skView.bounds.size];    // LINE 1
        scene.scaleMode = SKSceneScaleModeAspectFill;                      // LINE 2
        // Present the scene.
        [skView presentScene:scene];


The above is the original SpriteKit code. I added layoutDone boolean check so that the scene gets drawn once. I think this code used to be in viewDidLoad in earlier versions of XCode spritekit template. But since autolayout, it has been put into viewWillLayoutSubviews.

Anyways, the solution, replace LINE 1 and LINE 2 with the lines below:

SKScene * scene = [GameScene sceneWithSize:skView.safeAreaLayoutGuide.layoutFrame.size]; // LINE 1
scene.scaleMode = SKSceneScaleModeAspectFit;                                             // LINE 2

Basically, we init the scene with the safeArea layout size, and set the scalemode to aspectFit. Just these two lines and voila:

I have also tested the code against iPhone 8 (a Non-Notch iPhone), and it appears normal. So this is pretty much a perfect easy solution. But of course, to use the safeArea, you need at least iOS11, which I think is a good minimum iOS requirement as of now. iOS version adoption rate is quite high.

But ah... just noticed the admob banner is covering the menu bar at the bottom :D that is another issue that I need to fix. You see why it is good to write a blog now, you get to debug your code at the same time too. Hahaha!

This tutorial has no downloadable Project because.... it's just some code sharing really.

Ok guys. That's all. Thanks for reading.

1 comment: