When I run my game it's like the zoom was on 200%. I dont know what to do to make it normal.
class GameViewController: UIViewController {
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
// CONFIGURE THE VIEW
let skView = view as! SKView
skView.multipleTouchEnabled = false
// create and configure the scene
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
// Present the scene
skView.presentScene(scene)
}
p.s: I already checked and it's not in the simulator's settings
The reason your scene looks zoomed is explained by the scaling factor (AspectFill). You'll likely want to use either Fill or ResizeFill.
With SKSceneScaleMode you have four options:
Fill
Each axis of the scene is scaled independently so that each axis in
the scene exactly maps to the length of that axis in the view.
AspectFill
The scaling factor of each dimension is calculated and the larger of
the two is chosen. Each axis of the scene is scaled by the same
scaling factor. This guarantees that the entire area of the view is
filled but may cause parts of the scene to be cropped.
AspectFit
The scaling factor of each dimension is calculated and the smaller of
the two is chosen. Each axis of the scene is scaled by the same
scaling factor. This guarantees that the entire scene is visible but
may require letterboxing in the view.
ResizeFill
The scene is not scaled to match the view. Instead, the scene is
automatically resized so that its dimensions always match those of the
view.
Available in iOS 7.0 and later.
↳ https://developer.apple.com/library/prerelease/ios/documentation/SpriteKit/Reference/SKScene_Ref/#//apple_ref/c/tdef/SKSceneScaleMode
Related
I'm trying to create a boundary of physics for the iPad Pro 12.9
This is how I'm doing it:
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
let sceneBody = SKPhysicsBody(edgeLoopFrom: self.frame)
sceneBody.friction = 0
self.physicsBody = sceneBody
....
}
But the Y is way off in Landscape (much lower and higher than the actual screen), and a little ways off in Portrait. But the X is right in both.
I don't know what I'm doing wrong.
Update
I've added a print to the above, and its showing the maxX and maxY of self.frame to be 375 and 667 respectively. In landscape mode. Neither of those numbers are what they should be, as far as I can tell, yet the X value works correctly whilst Y is way off the top and bottom of the screen.
This iPad model's screen resolution is 2732x2048 (half that in points) so I don't see a correlation between these numbers and the reported frame size.
This has something to do with the way you're scaling the scene. When presenting a scene, you may be setting the scaleMode property of the scene, which is of type SKSceneScaleMode. There are four different modes:
fill: Each axis is scaled independently in order to fit the whole screen
aspectFill: The scene is scaled to fill the screen, but keeping the aspect ratio fixed. This is the one your scene is probably set to.
aspectFit: The scene is scaled to fit inside the screen, but keeps the aspect ratio. If the scene has a different aspect ratio from the device screen, there will be letter boxing.
resizeFill: The scene is resized to fit the view.
I am building a game and I would like to be able to rotate a node. I can rotate is perfectly fine if the parent of that node is self (The GameScene), but if I add the node as a child of another node that doesn't have the same width x height ratio, it looses it's aspect ratio.
I thought I could simply find the scene ratio and multiply the node's width by it after changing parent, and this works fine but... When I rotate the node (zRotation), it stretches again. The maximum stretch is when the node is rotated at 90 degrees, as the new parent node is a rectangle that is higher than larger.
I was wondering if there is a way to always keep the aspect ration intact even when rotating and change node parent (coordinate system)?
I simply add nodes to bigRectangle (a big rectangle on the GameScene). It looks stretched on the rectangle (it does not if I add it to the GameScene) so I change the ratio by doing:
let myRatio = self.frame.height / self.frame.width
myNode.xScale = 1
myNode.yScale = 1 * myRatio
This works but when the node is rotated (zRotation) it becomes stretched again...
I added pictures;
You have to configure this on the scene itself:
scene.scaleMode = .AspectFill
I'm working on a game but can't figure out the right way to scale/ position everything. I have a universal app and when I switch from device to device the nodes aren't in the right place everytime. I'm using AspectFill because it sizes my nodes the the right way for each device. The problem is the positioning. I don't know if I'm right in making the conclusion that I need to figure out how to make the view the same size as the screen so that it changes for each device and then positions and scales everything properly, but this is what I've been trying to figure out. I've been trying many different things online and looking at things like how to make a custom view. I've tried to make a rectangle that ha constraints to fill the screen and then setting that rectangle to equal the UIView or SKView. I've tried many different things and looked at many things online but they are either confusing and I don't know if I'm trying them right or they don't pertain to my situation. This is causing a lot of confusion for me and I was hoping someone could help with this issue. I think the issue is that I need to make a custom view that relates to the size of the screen. I don't know if this is possible or what I should be going after. It would be great if someone could clear this up for me.
To keep my games universal I make all my nodes sizes and positions dependant on SKScene size
Instead of using hardcoded numbers try using proportions from your SKScene size. For example:
Instead of writing this:
node.position = CGPointMake(100, 100)
Write somthing like this:
node.position = CGPointMake(world.frame.size.width / 32 * 16, world.frame.size.height / 18 * 9)
world - SKNode of exactly same size as your SKScene
Same for sizes
let blackSquare = SKSpriteNode(texture: nil, color: UIColor.blackColor(), size: CGSizeMake(world.frame.size.width / 32, world.frame.size.width / 32))
Also GameViewController should look something like this:
override func viewDidLoad() {
super.viewDidLoad()
// Configure the view
let skView = view as! SKView
skView.multipleTouchEnabled = false
// Create and configure the scene
let scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .AspectFill
scene.size = skView.bounds.size
skView.presentScene(scene);
}
Was this helpfull?
If I'm making a game in SpriteKit that has a large "world", and I need the user to have the option of zooming in and out of the SKScene, how would I go about this? Or, to make things simpler, in the didMoveToView function, how can I present more of the world to the user's device's screen (without using world.runAction(SKAction.scaleTo(0.5)) or something)?
There's a SKCameraNode that's built specifically for this. The SKCameraNode defines the viewport into your scene. You create a camera node and assign it to the camera property of your scene.
let cameraNode = SKCameraNode()
cameraNode.position = CGPoint(x: scene.size.width / 2, scene.size.height / 2)
scene.addChild(cameraNode)
scene.camera = cameraNode
You can then create actions and run those actions on the camera. So to zoom in on the scene, you'd do this.
let zoomInAction = SKAction.scale(to: 0.5, duration: 1)
cameraNode.run(zoomInAction)
The cameraNode basically is a square node in the scene, that I think takes the proportions of the view by default? Cuz there's no size initializer. So when you make it smaller, the scene looks like it gets zoomed. To zoom out you'd make an action that increases the scale. Basically imagine a rectangle on your entire scene, and whatever is in the cameraNode's rectangle directly shows on your iPhone screen. You can also add moveTo actions and sequence actions and set timingModes on the actions same as if it were your normal spriteNode.
Here's the WWDC where the apple guy shows what I've just said. CameraNode bit is around 3 mins before the end.
https://developer.apple.com/videos/play/wwdc2015-604/
So, the best solution I could could find goes something like this. In the didMoveToView function, create an SKSpriteNode called World and make it whatever size you want your world to be. Then, write world.setScale(0.5) if you want a 50% zoom-out. However, if you have a player node that needs to always be centered in the screen, you'll need to add the following to your update function.
override func update(currentTime: CFTimeInterval) {
world.position.x = -player.position.x * (0.5)
world.position.y = -player.position.y * (0.5)
}
I have an empty SKScene which needs to be horizontally centered, so I set it's anchorPoint:
self.anchorPoint = CGPoint(0.5f, 0);
I also need to scale it, per SpriteKit - Set Scale and Physics, so I run an action on it like this:
[self runAction:[SKAction scaleTo:0.5f duration:0.0f]];
My problem is that when I detect touches, I get locations that seem strangely off.
I detect touches using the usual (locationInNode:self) method, and I'm currently adding a little blue square where the touches are, but when I touch the 4 corners of my device, I see a frame that is a quarter of my screen (correctly) but is moved to the left by a seemingly arbitrary amount
Here are some things I've already checked:
scene is initialized in viewWillLayoutSubviews, I know it has the correct initial dimensions
scene's scaleMode is set to SKSceneScaleModeAspectFill, but I've tried all of them to no avail
I was struggling with the same issue for awhile, but I think I finally got it figured out. You're not supposed to scale the scene (like it hints if you try setScale). You're supposed to resize it.
Try this:
myScene.scaleMode = SKSceneScaleModeAspectFill;
And then while zooming:
myScene.size = CGSizeMake(newX, newY);
Set Anchor Point as
self.anchorPoint = CGPoint(0.5f, 0);
And set Scene Scale Mode as ASPECT FIT, not aspect fill.
SKSceneScaleModeAspectFit