How do SpriteKit positions work? - swift

I'm building a game and I've noticed that when I do something like
node.position = CGPointMake(0, 0) //Bottom Left
node.anchorPoint = CGPointMake(0,0) //Bottom Left
that depending on which phone you have iPhone 4s, 5s, 6s ect. It shows up in different places.
How can I change it so that it uses the bounds of the screen size to work out its calculation like
self.view.frame.width/2
Cheers, I'm guessing its scale issue?

Use bounds
self.view.bounds.size

The answer lies in GameScene.sks. On the right side of the editor, you can see the dimensions of the screen. The point value is the scene's coordinate positions. To make it standard across devices, in App Delegate, under applicationDidFinishLaunchingWithOptions, scene.scalemode = .AspectFill. The scalemode has many different options to stretch the .sks file's dimensions to the device's screen. You can read about them here: understanding scalemodes. The scalemodes are called like so: .ResizeFill . ResizeFit etc..

Related

Where did these borders come from in Monogame Android?

Even when I use GraphicsDevice.ToggleFullScreen() or GraphicsDevice.IsFullScreen = true; followed by GraphicsDevice.ApplyChanges() as described in this post, I still seem to have this border on both edges of the screen, shown in classic CornflowerBlue for contrast in this screenshot. The background image is anchored at 0,0 with width and height set to the dimensions of the screen. The "borders" seem to be about 10 or 20px from what I can guess, and not at the top or bottom, only at the left and right edges. I can't understand where this is coming from.
If you want your game to be at full screen of every device:
#if ANDROID
graphics.IsFullScreen = true;
graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
graphics.SupportedOrientations = DisplayOrientation.Portrait;//if your game does NOT support for anything else but portrait mode
graphics.ApplyChanges();
#endif
However, in this case, you need to be careful because the ratio of devices are different, some are 16:9, some are 4:3, etc. If you need your game to be adapt to all of them, you better adjust the sizes of your game objects to be changeable or set them to be proportional.

SpriteKit - Can't understand what size to make background

I am completely confused on how to correctly size my lans background image which is landscape based. As of right now I'm doing GameScene(size: self.frame.size) and I print out the size of the screen so I know what size to make my background and it turns out my background should be 1024x768 but that doesn't seem like landscape dimensions? So I made my background 1024x768 but the entire image doesn't fit into my iphone when its landscape because the iphone lanscape dimensions arent 1024x768. How do I make a background that will look 1:1 with the dimensions of my iphone? The only way I can think is if I set the GameScene(size: CGPoint(x: 1334, y: 750)) but then wont it be screwed up for any other device? What's the best way to approach this? I have an artist who is going to make a background for me but I have no idea what dimensions to give him.
When dealing with scenes for Sprite Kit, try not to focus on the screen size, because screen size is no longer a factor (now this is not 100% absolute fact, this is a general rule to go by)
Instead, treat your SKScene as if it was a virtual screen. The size of your SKScene is the "resolution" of your SKScene, and the OS will work in the background to figure out how to convert 1 virtual pixel (From here on out we will call point) to screen pixels( referred to here on out as pixels)
Now there is only 1 special case where the OS will change the resolution (scene size) to match the screen, and that is .resizeFill The other 3 will never change resolution on you.
.aspectFill and .aspectFit will ensure that your point to pixel conversion keeps and equal width and height (e.g. 1 point could equal 4x4 pixels) The only difference is .aspectFill will expand to fill the entire screen, meaning that excess points will be rendered outside the native screen bounds [ so (0,0) may lie 20 pixels left of the left most pixel, thus not being visible] and .aspectFit will fill till it hits a screen border, leaving black bars to fill the unused pixels.
Now .fill does not keep and equal width and height point to pixel ratio, and in the case of a 4:3 going to a 16:9 screen, you will notice that your point to pixel will be 5:4 because a 16:9 screen is 25% wider than a 4:3. This gets you the fatty effect.
So when dealing with your game you need to figure out the desired effect. If you set your scene size to 1024x768, then all non retina iPads will have a 1:1 pixel to point ratio, where retina has 2:1 pixels to point ratio. For an iphone 5, you would get roughly 1.14 pixels to every point (iphone is 1168 and your scene is 1024, so you do 1168/1024) then of the 768, you would be loosing 25%, because the ipad is 25% taller than an iphone in landscape. This means only 576 points will be showing, and the rest are in invisible screen space.
Basically, you can never get a 1:1 with both an iPad and an iPhone doing a universal app because you are working with 2 different aspect ratios. You are going to have to make 2 different sets of assets, or take some creative liberties that doesn't alter the gaming experience. This depends entirely on the game and unfortunately nobody will be able to answer it till they have an understanding of your game.

Lower Left Coordinates of SKScene

I'm new to Swift SpriteKit programming and the coordinate system is driving me crazy. I create a sprite and I want to move it to the four corners of the screen. So, I set the position to (0,0). That's off the bottom left corner of the screen. Through some manual testing I've developed the chart below. The lower left and upper right are what the iOS simulator report when I touch the screen.
I have 2 questions:
1: Is there a method of determining the coordinates of the lower left hand corner of the view? Maybe I could build a dictionary with the coordinate values and the determine the machine type and then set the offsets. But, that's a lot of work and might not be accurate for new devices. It just seems that there should be a scene or frame property that I can use to put an object at the bottom left of the window.
2: The math doesn't work. In the iPhone5, 300 (lower left x) + 320 (width) = 620, not the reported 727. Same issue is true with the y coordinates. How does this work?
I set as few parameters as possible. I have not changed the anchorPoint or position of the scene.
Device Size LL UR
iPhone4s (320,480) (260,0) (766,764)
iPhone5 (320,568) (300,0) (727,764)
iPhone5s (320,568) (298,0) (727,764)
iPhone6 (375,667) (297,1) (728,765)
iPhone6plus (414,736) (298,0) (728,766)
iPad2 (768,1024) (226,0) (800,768)
iPad Air (768,1024) (224,0) (800,767)
iPad Retina (768,1024) (225,0) (800,768)
Ok, I think I figured this out. Setting scene!.scaleMode=SKSceneScaleMode.ResizeFill allow me to identify the four corners of the screen. So, now I can determine when a sprite crosses the edge of the screen. This doesn't seem to distort my images. I haven't been able to test it on a read device yet, but it leaves a blank area around the iPad2.
Applause for the hard work! haha
If I was going about getting values for the lower coordinates, I would use CGRectGetMinX to get the x-coordinate and CGRectGetMinY to get the the y-coordinate likewise:
CGPoint minimum = CGPointMake(CGRectGetMinX(self.frame),CGRectGetMinY(self.frame));
Then, if you wanted to get the top coordinates just use the same things but say MaxX or MaxY. Yeah, the coordinates are a bit confusing but if you use those then it will be a breeze.
EDIT: If you need to find if a body has exited outside visible space, so far what has worked for me is making a physics body to detect contact with it on the edge
[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]
possibly another option you could try is to see the bounds of a UIScreen object.

Supporting different orientations using Cocos2d on iPhone

I’m trying to support both landscape and portrait orientations in my iPhone Cocos2D game, but I’m having trouble getting the coordinates to translate properly.
Here’s what I’m doing so far.
I have a GameWorld layer that I always keep in portrait, regardless of the device orientation. The following code is in my DeviceRotated event for UIDeviceOrientationLandscapeLeft. (‘self’ is my GameWorld layer)
[self runAction:[CCMoveTo actionWithDuration: 0.25f position:ccp(80, 0)]];
[self runAction:[CCRotateTo actionWithDuration:0.25f angle:90]];
So that I don’t have to write different code for each orientation I was hoping to use the following in my Sprite class to translate Sprite coordinates.
CGPoint spriteLoc = ccp(0,0);
CGPoint translatedSpriteLoc = [self.parent convertToNodeSpace:spriteLoc];
self.position = translatedSpriteLoc;
However, this doesn’t work.
If the device is in portrait mode with the sprite in the lower left corner and I rotate the device to the left, the sprite appears in the lower right. I want the sprite to be in the lower left in landscape just like it is in portrait.
Am I missing something or is there a better way to translate coordinates?
Well, if you don't mind a "jump cut" when you switch orientations, you can just use the built-in orientation support within Cocos2d. See this post at the Cocos2d forums.
If, however, you need pretty orientation, you may have to do something along the lines of what you were showing above, orienting things manually via rotation using actions.
Without more detail, it's hard to say why your approach doesn't work, but my guess is that you are seeing the sprite positioning you describe as a result of the fact that if you don't change orientation, the lower left in portrait IS the lower right in landscape when rotated left, i.e., it's the same point in GL space: (0,0). You're going to have to move the "origin point" of your GameWorld Layer as well as rotating it.
Try adding a full-screen image to your layer to see what's actually happening when rotating it. That should help you narrow down what you need to do.

How does the Maps app on the iPhone 3Gs rotate as you turn the phone?

On an iPhone 3Gs, if you click the little "show my location" symbol on the lower left of the window twice, it switches to a mode that causes the map to rotate so that north on the map faces towards north according to the compass. I don't have a 3Gs, so I just found out about this from a buddy who does have one.
I tried applying a rotation transformation to a MKMapView's layer, like this:
CATransform3D rotationTransform = CATransform3DIdentity;
rotationTransform = CATransform3DRotate(rotationTransform, degreesToRadians(-20), 0.0, 0.0, 1.0);
theMapView.layer.transform = rotationTransform;
That sort of works, but not really. The contents of the map do rotate, but the frame rotates and stretches. The map view ends up in a strip that stretches diagonally across the screen, and it ends up under the buttons in my view.
I tried enclosing the map in another view to isolate it, but that doesn't work either. Next I'll try rotating the enclosing view, but I'm hoping somebody else has figured this out. Getting it to work by trial and error is likely to be difficult at best.
Regards,
Duncan C
I have the same problem. I was able to solve the stretching by placing the MkMapView in a UIView container.