Horizontal infinite scrolling with SKSpriteNode in Swift - ios

I am trying to make my game character loop around the screen infinitely like this: http://i.imgur.com/F2yuqen.gifv
Basically, there are three characters. One spawns in the middle of the screen, and the other two spawn exactly the screen width away on opposite sides and move with the main player. Once the main player's x position is less than 0, or greater than the screen width, it is placed back into the middle of the screen. This makes it infinite in essence.
It works great in processing, but in swift my variables for screen width self.size.width seem much larger than the actual screen width when I run the game in the iOS simulator. This makes the character movement not seem smooth and if it is cut off on one side, it does not show up on the other side like it does in the first example.
Example: http://i.imgur.com/gLS4ijK.gifv
Again, I think it has something to do with self.size.width not actually being the width of the display in the simulator.
Code:

Figured it out, I had to add
scene.size = skView.bounds.size
to GameViewController.swift

Related

iOS landscape positioning problems Swift SpriteKit

For some reason, I am unable to position a node at the top or bottom of my screen. I used to be able to do this just fine using self.frame.height / 2 but now that I am working in landscape, this line of code is not working.
Notes: my anchor point is 0.5, 0.5 and my scale mode is .aspectFill
Thanks for all your help.
This probably has something to do with the aspect ratio of your scene and using .aspectFill.
When you use .aspectFill, SpriteKit will resize the scene to fill the viewport from edge to edge, both horizontally and vertically, but it won't stretch it. That means that for a landscape orientation, you will probably end up "cropping" off the top and the bottom of the scene unless you have a particularly shallow scene designed.
In other words, you're encountering the opposite of letterboxing. The width and height of the scene are fixed, and when the device size differs from that in aspect ratio, it "overflows" one axis offscreen. In your case, it's probably overflowing the scene off the top and the bottom in order to fill your scene left and right.
There are a few strategies to fix this.
First, you could choose a different scaleMode. .aspectFit, for instance, would probably return your height calculations to what you expected, but it will come at the cost of also including letterboxing on the left and right, which is probably not what you want, but maybe.
Second, you could compute a new scene size to match the aspect ratio of your viewport. This will give you the behavior you expect in both directions, but it will also mean that your scene varies in aspect ratio based on the device it is played back on, which will require you to adjust your gameplay and scene layout to accommodate this variable shape. This is a lot of work, but it is typically the best solution. (One solution is to resize the scene, but then leave your "real scene" centered in the middle of it, but that can be unsatisfying and problematic for some game types.)
Third, you could use the scaleMode that simply scales the scene to the viewport. This will cause some squishing/stretching depending on the device, so it is generally not a great option, but depending on the game type you are making, this might be an option.

Objects positioning in SpriteKitScene

I am making this basic space shooting game but I can't get the x-coordinates of enemies right. Sometimes, they go out of the screen - or remain half inside at the edges. How can I fix this permanently regardless of which iPhone the app runs on?
here is the code for my positioning: (note that egg is name of my enemy. it is function I made for calling it every single time)
func egg() {
var egg = SKSpriteNode(imageNamed: list[Int(arc4random_uniform(6))])
var min = self.size.width / 8
var max = self.size.width
var point = UInt32(max - min)
egg.position = CGPoint(x: CGFloat(arc4random_uniform(point)), y: self.size.height)
let action = SKAction.moveToY(-100, duration: 2)
let actionDone = SKAction.removeFromParent()
egg.runAction(SKAction.sequence([action, actionDone]))
}
There are several places where things can be going sideways.
• First, it looks like you're assuming the location of your scene's anchorPoint is at (0,0). If it's not (the default .sks file now has an anchorPoint at (0.5,0.5), for instance), that could explain why your enemies never show up. The first thing I would do is double-check the anchorPoint of my scene.
• If you're adding these eggs to some other node besides the scene itself, then those eggs will "inherit" whatever translation, rotation, and scale that their parent node has. In other words, if you add an egg at (20,20) to a node at (30,30), it will appear at (50,50). Make sure the "context" of the eggs is what you expect.
• Your "min" and "max" values seem a little odd. The "min" looks like it is intended to be "indented" by 1/8th of the screen size on the left, but you aren't indenting it on the right. Maybe that's what you intend, but if you intend them to have symmetrical behavior, then you'll want to back "max" off by an eighth, too. Also, you're not adding that eighth back into the x value when you're determining the position, so this could stick an egg at x=0. This would explain why your sprites are sometimes "half inside at the edge".
• The size of your scene is not necessarily the screen dimensions. This depends heavily on the "scaleMode" of your SKScene. Check the documentation for more information on this, but briefly, the scaleMode tells SpriteKit how to render a scene that doesn't match its view in size or aspect ratio. Does it stretch? Does it crop? Does it letterbox? If you run a square 400x400 scene on a 1024x768 screen device, it has to have some way of knowing what you mean. Does it draw that 400x400 in the middle of the screen and let stuff be seen "outside" that rect? Or does it scale it up to fill the screen, cropping off the top and bottom? Or does it scale it up to FIT the screen, allowing space above and below that is technically outside the scene's size? Or does it scale it up and squash the scene to fit exactly? If your scene isn't matching up exactly with your device's screen, this could explain why things are not playing nice and staying within visible bounds.

Math formula for perfectly fitting buttons in current devices screen width

Could someone point me in the right direction for figuring out how to properly write out my code so that all buttons on any particular y-axis would try to fit the width of the current device screen as best as possible?
To be more exact, currently, I have 4 buttons (made from a SKSpriteNode) that need to be positioned within the screen in such a way that they look perfectly fitted. Device screen is portrait, although from a math point of view, that wouldn't matter, only the actual width of the screen. Each button width uses the same texture, thus resulting in identical widths, but the texture it self might change from time to time resulting in each buttons width either to shrink a little or expand.
Right now, my positioning code looks as follows:
btnLvl1.position = CGPointMake(_scrollingNode.size.width/20*3, scrollStart.position.y - 60);
btnLvl2.position = CGPointMake(_scrollingNode.size.width/20*8, scrollStart.position.y - 60);
btnLvl3.position = CGPointMake(_scrollingNode.size.width/20*13, scrollStart.position.y - 60);
btnLvl4.position = CGPointMake(_scrollingNode.size.width/20*18, scrollStart.position.y - 60);
I was hoping someone could recommend a math formula for making sure, regardless of each button width & how many buttons there are, that they would be placed within the screen width as best as possible. A super bonus would be if something could be done for the height of a device screen (but not necessary).
P.S. I did try figuring this one out my self, but I'm not very strong math-wise.
You can use your scene size to "auto-fit" any node. For example, if you want to center a button on the screen:
button.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
Although you can use this:
button.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

Dealing with different iOS device resolutions in SpriteKit

I'm playing around with SpriteKit in Xcode 6, iOS 8 beta 5. Everything is all laid out and working perfectly on the iPhone 4S simulator, however when switching to the 5S, the elements at the bottom of the screen are cut off.
It was to my understanding that the bottom left corner of the iPhone screen should be CGPoint(0, 0) but after checking the location by printing the coordinates to the console that the lowest point of the left corner I could click was around (5, 44). Is there something wrong in my scene setup thats causing this?
No changes have been made to the GameViewController file and even after I strip the GameScene file the problem persists.
Can anyone at least point me in the right direction with this?
Adding the following code will fix your problem (code is in Swift):
scene.scaleMode = SKSceneScaleMode.ResizeFill
Now if you want to know why this fixes your problem, what your problem actually is, and how to handle multiple resolutions – I suggest you continue reading.
There are three things that can impact the position of nodes in your scene.
1) Anchor Point
Make sure your scene's anchor point is set to (0,0) bottom left. By default the scene's anchor point starts at (0,0) so i'm assuming that is not causing the issue.
2) Size Check the size of your scene. I typically make my scene size match the size of the device (i.e. iPad, iPhone 4-inch, iPhone 3.5 inch), then I place another layer in the scene for storing my nodes. This makes me able to do a scrolling effect for devices with smaller resolutions, but it depends on your game of-course. My guess is that your scene size might be set to 320, 480 which could be causing the positioning problems on your iPhone 5s.
3) Scale Mode The scale mode has a huge effect on the positioning of nodes in your scene. Make sure you set the scale mode to something that makes sense for your game. The scale mode kicks in when your scene size does not match the size of the view. So the purpose of the scale mode is to let Sprite Kit know how to deal with this situation. My guess is that you have the scene size set to 320,480 and the scene is being scaled to match the iPhone 5 view which will cause positioning problems identical to what you described. Below are the various scale modes you can set for your scene.
SKSceneScaleMode.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.
SKSceneScaleMode.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.
SKSceneScaleMode.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.
SKSceneScaleMode.ResizeFill
The scene is not scaled to match the view. Instead, the scene is
automatically resized so that its dimensions always matches those of
the view.
Conclusion
It looks like you want to remove the scaling of your scene, that way your positions in the scene will match the actual positions in the view. You can either set your scene's size to match the view size, in which case no scaling will take place. Or you can set your scene's scale mode to ResizeFill which will always make the scene's size match your view's size and it won't scale anything. In general I would stay away from any scaling and instead adjust the interface and the scene size to best suit each device. You may also want to add zoom and/or scrolling to allow devices with smaller resolutions to achieve the same view field.
But what if I want to scale my scene?
If however you need to scale your scene, but you still want positions to be relative to the view (i.e. You want (0,0) to be the bottom left of screen even when scene is cutoff) then see my answer here
Additional Info
See answer here for sample code showing how I layout nodes dynamically.
See answer here for more details about scaling to support multiple devices.
If you want to preserve the size of your scene (usually desired when you work with a fixed size and coordinates system), you might want to add padding to either side of your scene. This would remove the letter boxing and preserve all the physics and dynamics of your app on any platform.
I created a small Framework to help with this:
https://github.com/Tokuriku/tokuriku-framework-stash
Just:
Download the ZIP file for the Repository
Open the "SceneSizer" sub-folder
Drag the SceneSizer.framework "lego block" in your project
Make sure that the Framework in Embedded and not just Linked
Import the Framework somewhere in your code import SceneSizer
And you're done, you can now call the sizer Class with:
SceneSizer.calculateSceneSize(#initialSize: CGSize, desiredWidth: CGFloat, desiredHeight: CGFloat) -> CGSize
Just in case, try doing CMD+1, worked for me. Some of the elements were cut off because they were simply not displayed in Simulator - I stress this, this is just a simulator feature (and a bug if you ask me, wasted hours of time to solve this). CMD+2, CMD+3 views can sometimes hide parts of the scene.

iOs simulator frame rate drop

I'm doing my first steps in spriteKit, i only have two scenes, in the second one i have a method which spawns little pixels (rocks) and they fall down with the physic. The other thing I have is a parallax effect with a image.png which size is 323x90. The image move in the background from left to right and when it disappear in the right it spawns again (i don't destroy the node, only change it's position) in the left and begin again the animation.
When the rocks are falling, the node max count is 20 - 21 but my FPS drop to 20-21. This is beginning to slow down and i don't understand why, i wonder what will happen when my scene grows up. I've tried with iphone 5 simulator and is the same. Does any one know why?

Resources