3

As you may know when using SpriteKit, applyImpulse does not work well on all screens.

On an iPhone SE, my ball moves extremely fast, but on the iPad Pro 2nd gen the ball goes really slow.

Is there a way I can make this equal on all screens, in comparison to something like the width of the screen?

Say for example, I want my ball to move across the screen in 5 seconds on EVERY device, what formula would I use?

I have tested out the relation between screen sizes and time for my applyImpulse to make the ball move to the edge of the screen:

enter image description here

Note: Points per second is calculated by Half screen size divided by Time to move. The graph shows that the pixels per second decreases with a bigger screen size.

How could I change my applyImpulse to work on all screens? (not including making it specifically for every device, as I want this to be sustainable for the future)

If this is possible, please show a small swift function, or if this cannot be done, please give me any suggestions (links to docs, forums, etc).

I appreciate any help by anyone.

EDIT: My GameViewController.swift override for loading the scene:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()


    // Layout guides
    guide = UIApplication.shared.keyWindow?.safeAreaInsets


    if let view = self.view as! SKView? {

        // Load scene
        let scene = GameScene(size: view.frame.size)

        // Set the scale mode to scale to fit the window
        scene.scaleMode = .aspectFill

        // Set (0, 0) as the centre of the screen
        scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)

        // Present the scene
        view.presentScene(scene)


        view.ignoresSiblingOrder = true
        view.showsFPS = true
        view.showsNodeCount = true
        view.showsPhysics = true

    }
}
George
  • 25,988
  • 10
  • 79
  • 133
  • if you are working in any scaleMode besides resizeFill, you do not need to worry about this, since the point of scaleMode is to design in 1 size. Otherwise `150 points == 1 meter` in spritekit – Knight0fDragon May 02 '18 at 20:57
  • I am using `.aspectFill` and my code for loading the scene is `let scene = GameScene(size: view.frame.size)`... Funnily enough you have commented on quite a few of my questions before – George May 02 '18 at 21:59
  • setting the game scene to view.frame.size is counter intuitive to how scenes work, it completely ignores the scaleMode, which is where a lot of convenience lies in Sprite Kit. Also, there is nothing funnily about it, I am one of the most active contributors to the SK framework here on SO – Knight0fDragon May 02 '18 at 22:02
  • @Knight0fDragon I am trying to make it so I can programmatically create my scenes - what do you suggest so I can programmatically create a scene **keeping** the scale factor then? – George May 02 '18 at 22:04
  • I am not sure what you mean by programmatically create scenes and keeping scale factor. First I need to ask, what kind of experience are you planning on offering your customers, do you want them to all have as close to the experience as you possibly can? Or do you plan on the 4:3 devices to behave different than the 16:9 devices? – Knight0fDragon May 02 '18 at 22:14
  • @Knight0fDragon I am trying to make a scene created only by programming, using no `.sks` file. I want objects to do adapt to the sizes – George May 03 '18 at 13:39
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170294/discussion-between-knight0fdragon-and-george-e-2). – Knight0fDragon May 03 '18 at 13:40

1 Answers1

0

Sprite kit is designed in a way that you only have to create your game once.

The concept of a "Screen" should not really exist, Your scene is your screen, and your screen is just how you are viewing it.

As we discussed in the chat, you wanted to have a play area of 7:9, and you wanted the scene to flush along the sides of it.

To do this, pick a scene size that is taller then wide. I would recommend using 375:812 since that is iPhone X .@1x. Then place a node inside of it at size 375:482 since that is 7:9.

What will happen is on a regular 9:16 device, the top and bottom areas will get cropped, but it will still show the entire playing field since a 9:16 device has a height of 667.

This means 145 points will be cropped vertically from your main playing area.

Now we come across the issue of iPad, where it is fatter than a 9:16 device.

Our visible scene area becomes 375:500, which our play area barely fits into.

We only have 18 points to work with for a hud or what not.

To combat this, we need to go into the storyboard and change the constraints of the view.

We basically need to force the view to not exceed a certain aspect ratio.

By restricting the size the view is allowed to become, we can control how much cropping will happen on an iPad. We can then add another view behind the SKView to control whatever graphics we want the user to see.

We now have the game setup in a way where we can place all of our play area content inside of the 375:482 play area node.

These dimension will carry across all devices, and the hardware will do the scaling for you, meaning you will have less code and less math to do. less code and less math means less chance for bugs to get into your game, plus the game is exactly the same gameplay wise, meaning iPad users do not get an advantage over iPhone users because you gave them a bigger play area.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44