DropCharge wrong playable boundaries?

Hi, I’ve just completed the first two games of the book and I have to tell that I’ve learned a lot, but I also noticed something weird while I’m following the tutorial for the third game.

It seems like the left and right boundaries of the game aren’t right for different platforms. I don’t know if it’s my mistake, but I also tried playing the already finished game and I still see this problem (I used the simulator).

For example to check when to place the player on the right side of the scene we do:

var playerPosition = convertPoint(player.position, fromNode: fgNode)
if playerPosition.x < -player.size.width/2 {…}

The problem is that when I move the player to the left part (or right) of the scene, it stays a lot of time offscreen until it appears on the right side. This means that the scene is “scaled”, by this I mean that the left boundary (end visible area) isn’t the same as “x=0” but it has to go more to the left until it reaches that point of the scene (and we already used the conversion from the fgNode, so we’re calculating on scene coordinates with anchor point on bottom-left). Is there a way to solve this problem? (I noticed the problem on different devices, e.g iphone 6)

I tried to use the method used for the Zombie Conga (using a CGRect) but for larger devices the rectangle appears smaller than the visible area (and you see the player going from left to right while visible on screen). So this isn’t a nice solution.

Did I miss something (even though I also checked on already finished file) or is it just something to fix, if so, how can I fix this?

PS: I know that we check when x is smaller than -player.size.width/2, but this isn’t the problem, even if I check for x<0 it has this problem.

An answer would be nice, also just some hints…

You are correct, this is a bug. Good find! We have a fix for this in the iOS 10 version of the book which will be released soon.

I’ll post a more detailed explanation of the issue and solution tomorrow.

The issue, as you suggested, has to do with how the scene is scaled, which can result in some cropping on the right and left-hand sides depending on the screen’s aspect ratio.

Here is a solution in Swift 2.3, taking advantage of the already defined helper method overlapAmount():

// Wrap player around edges of screen
var playerPosition = convertPoint(player.position, fromNode: fgNode)
let leftLimit = overlapAmount()/2 - player.size.width/2
let rightLimit = size.width - overlapAmount()/2 + player.size.width/2
if playerPosition.x < leftLimit {
  playerPosition = convertPoint(CGPoint(x: rightLimit, y: 0.0), toNode: fgNode)
  player.position.x = playerPosition.x
}
else if playerPosition.x > rightLimit {
  playerPosition = convertPoint(CGPoint(x: leftLimit, y: 0.0), toNode: fgNode)
  player.position.x = playerPosition.x
}

With this code, the player should wrap to the other side once he is completely offscreen.

The overlapAmount() method calculates how much total width of the scene is cropped off. So, dividing in half yields the amount chopped off on each edge.

This is the meat of the overlapAmount() method:

let scale = view.bounds.size.height / self.size.height
let scaledWidth = self.size.width * scale
let scaledOverlap = scaledWidth - view.bounds.size.width

return scaledOverlap / scale

We can safely assume here that the scene height will be scaled to fit the parent view (aka visible area). That’s because the scene aspect ratio is 3:4 and the iPhone aspect ratios are all 3:4 or skinnier.

So first, you find out that scale. Then use that scale to determine how wide the scene is in the units of the parent view. Subtract the actual width of the viewable area and you get the total amount cropped off.

But that amount is still in the parent view’s units, so scale it back to scene units.

This solution avoids the issue with larger devices that you mentioned when using the method from Zombie Conga. However, there is a drawback in that the playable area differs for different devices. If you were making a game like this and consistent play-experiences were important (say, to avoid handicaps on wider devices), then you’d probably want to go with the defined playable area. You could perhaps add some special effects indicating when the player reaches the edge of the playable boundary so it doesn’t look as silly. Or, you could set the scene’s scale mode to .AspectFit but that would result in letterboxing on the top and bottom of 9:16 devices.

Let me know if I made a mistake or didn’t make sense. Thanks!

Hi kgorlick,

I’ve similar problem.

My game scene takes place in the Playable rectangle only. After I upgrade to iOS 10, the whole Playable rectangle is moved to the right on my iPhone 6. I use camera node in this game to follow the character

On the other game where I also used “Playable Area” introduced in the book, the coordination is fine and centered. And I don’t use camera node in this game

I think the get/setCameraPosition(), which use the overlapAmount() method above may lead to this issue. I am converting the code to Swift 3 and will try to see how to fix this. But it would be nice if the team already have a solution that you can share here

Thanks

You are correct. There was previously a SpriteKit bug that caused the camera to be off-center. Chapter 5 of the book (the iOS 9 / Xcode 7.3 version) describes the issue and defines similar get/setCameraPosition() and overlapAmount() methods to account for this.

The SpriteKit bug is fixed in Xcode 8 / iOS 10, so the workaround is no longer needed. If you remove the call to overlapAmount() inside get/setCameraPosition() and simply use the cameraNode.position, that should fix the problem.

2 Likes

Thought so, thank you for confirmation