Why is the coordinate system in sprite kit flipped and can I change that globally? - sprite-kit

I noticed that in Sprite Kit the coordinate system is flipped.
For example, here is a SKSpriteNode:
SKSpriteNode *car = [SKSpriteNode spriteNodeWithImageNamed:#"car"];
car.position = CGPointMake(0, 0);
[road addChild:car];
The car is positioned in the center of it's parent.
When I set position to:
car.position = CGPointMake(-50, 0);
then it is positioned more to the left.
But when I want to move it down, and increase Y, it moves UP!
car.position = CGPointMake(-50, 20);
In UIKit increasing Y always means something moves down. It feels more logical to me. Is there a way to flip the coordinate system in Sprite Kit?

You can set your scene's yScale property to -1. Everything will render upside down, but you can also set the yScale property for each node to -1, which will cause them to render right side up.
You could also make a class category and create a property called invertedPosition with a custom getter/setter that inverts the default position property.

Sprite Kit uses a coordinate orientation that starts from the bottom left corner of the scene (0,0), and the values increase as you move to the right (increasing x) and up (increasing y).

Related

Child gameobject moving faster than parent gameobject

Character is the parent object and has camera object as its child object (FPS type).
Camera object has a script which 'throws' raycast to detect objects in front of it.
Camera object has a child object 'Crosshair', which has a script 'ShowCrosshair' attatched to it.
Character <- Camera <- Crosshair.
Expected behaviour should've been: I move the mouse up and down, camera rotates around y-axis and along with it the crosshair object moves smoothly remaining at the center of the screen.
But, whenever I move the mouse up/down, crosshair moves faster than the camera can rotate and goes out of sight.
Here's my code for Camera Rotate:
//vertical is float and is initially zero and transform is for the current gameObject i.e Camera
vertical -= Input.GetAxis("Mouse Y");
transform.localRotation = Quaternion.Euler(new Vector3(vertical, 0.0f, 0.0f));
This script is attached to Camera object.
It is desired that Crosshair move with camera that is why it's parented by camera object.
I think your unwanted behaviour happends because whenever you move, rotate or scale the parent Transform all the childs are affected, therefore when you rotate the camera, the crosshair moves with it and then you rotate the crosshair causing it to rotate a second time and going out of sight.
It look like you are rotating around the X-axis instead of the Y (vertical) in this line:
transform.localRotation = Quaternion.Euler(new Vector3(vertical, 0.0f, 0.0f));
Also you should probably multiply the affect of the input by the delta time or it will move much too quickly.
vertical -= Input.GetAxis("Mouse Y") * Time.deltaTime;
But I don't think any of that is your problem. You commented that the script is attached to Camera. Is it also attached to Crosshair? Because if so then you will be getting double rotation. If not, take a look at what scripts might be changing the rotation of Crosshair. If you are just moving the camera, you shouldn't need anything rotating Crosshair at all (because it will move with its parent).

What is the significance of anchorPoint property in SpriteKIT

What is the significance of anchorPoint property in SpriteKIT?
I used it to position a specific node above the lower border of the screen. However, is that the only way to make sure that the objects don't cross the lower borders of the screen in a world where gravity is set to true?
What should the anchor point be set to to ensure that a specific node doesn't go out of horizontal/vertical bounds in case an impulse is applied?
Check out Apple's docs on the anchorPoint. Basically, the anchorPoint is used to define the center of an object. By that, I mean when you set the position of the node, it sets the position of the node's anchorPoint in the scene. From there, the anchorPoint with tell the node (I'm going to use Apple's spaceship example) that the image should be shifted so that the anchorPoint is wherever you defined. anchorPoint is a 1.0 by 1.0 size area, with 0.0, 0.0 being the bottom left of the sprite, and 1.0, 1.0 being the top right. It scales for however wide your sprite is. When you adjust the zRotation of your sprite, it will rotate around the anchorPoint.
So if I say, have a sprite with an anchorPoint at 0.5, 1.0, and I set the position to the exact center of the screen, the sprite will actually hang down, as the anchorPoint has been moved up to the top of the node.
Anyway, it should not have an effect on physics. I would recommend using position for setting the position of the node instead. If you are looking to make sure a physics body won't go through a wall/phsyicsBody, then run usesPreciseCollisionDetection = YES (or whatever language you are using's true statement) on your node's physicsBody.

Collision without sprites colliding

I have some simple code that adds a block sprite at the leftmost part of a tile like this :
block.position = CGPointMake((-self.size.width * 0.5), 0);
[self addChild:block];
Since the anchor point is in the middle of the block sprite. self refers to the actual tile.
This works fine and indeed adds the block on the left side of the tile sprite.
Now I also have a player sprite that can collide with that block if it tries to go through it. That also works just fine.
The problem happened when i tried to get the block sprite to show in the exact same spot using another anchor point (i need a new anchor point for a shrink effect i wanted to create - which appears to work fine btw).
The new code becomes :
block.position = CGPointMake(-(self.size.width * 0.5), -(self.size.width * 0.5));
block.anchorPoint = CGPointZero;
[self addChild:block];
The new block appears in a similar to the first case position (though not totally identical).
I am not sure why the position is not identical but i can fix that by adding/subtracting 1 or 2 from the x,y points.
The weird problem is that if my player sprite now tries to go below that block on the tile below (which is an open tile without any blocks), i get a contact between the player and the block.
I have even added debug paths with SKShapeNode to make sure that the player and block sprites do not actually collide. And they don't ! But i still get a collision event.
The player scale is (0.8, 0.9), but i don't think this would play much of a role.
I really don't get why this could be happening. Any ideas guys ?
Changing the sprite's anchor point have no effect on the physics body.
When talking about CGRect, the rect origin is at point {0, 0},
So what is happening is that you now have a sprite that its image is centred around anchor point {0, 0} but with a physics body, that starts at {0, 0} and is the size of the sprite, meaning that it is centred around {0.5, 0.5}.
So even that the player doesn't collide with the image of the sprite, it does collide with its physics body.
What is happening is that you have a physics body, that before had the same centre point as the sprite,
But as oppose to before, where the sprite anchor point were in the middle, which would 'fit' into the physics body,
Now the sprite's anchor point is {0, 0}, which causes the physics body centre point, to actually be the most bottom left point of the sprite.
To resolve this, you need to offset your physics body, so it will be centred around the new anchor point.
For example:
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size center:CGPointZero];
CGPoint newCenter = CGPointMake(block.size.width, block.size.height);
block.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:block.size centre:newCenter];
Good luck mate.
EDIT- On a second thought, I think I got confused with the offset directions.
An edit has been made to correct it.

Cocos2D iPhone - screen coordinates x sprite's internal coordinates

I am new to Cocos2D on iPhone. I see that Cocos2D uses a coordinate axis where 0,0 is at the bottom left corner and X positives are to the right and Y positives up.
Now I have created a sprite and added several sprites as subsprites of this one. For my surprise the subsprites appear mirrored in Y!!! The point 10,10 will be on the upper left corner of the sprite!!!
I can simply flip the sprite in Y to make it follow the same screen coordinate, but then the content will be reversed.
Is this a bug or what?
thanks.
Without seeing any example code is a shot in the dark, but I think you need to use Anchor points.
Each sprite has an anchor point of x, y.
ccp(0.5f, 0.5f) would be the center of the sprite.
(0,0) is the bottom left....(1.0f,1.0f) is top right etc.... Over 1.0 goes outside the sprite.
Child nodes (CCSprite) will use their anchor point on the parent node coordinates.
MySprite.anchorPoint = ccp(0.5f,0.5f);

Rotate UIImageView and still get x/y click position

I have subclassed UIImageView to create a soccer ball.
The ball bounces and moves along an x & y axis, and depending on where you touch the ball, the ball will move as you'd expect a soccer ball would.
My problem is that I would like to rotate the Ball(UIImageView), but still know the x & y positions from it's original position.
I am rotating it with the following code:
ball.superview.transform = CGAffineTransformMakeRotation(M_PI+(ball.center.x*.015));
ball.transform= CGAffineTransformMakeRotation(M_PI+(ball.center.x*.015));
When I rotate it, the x & y position also rotate. Can I somehow get the x/y distance from the centre of the UIImageView? Any other ideas?
Thanks,
James.
I think if you set the anchor of your CALayer of the UIIMageView to be the center of the UIImageView youll be ok, right now its set to the upper left corner and so are expiriencing the x and y moving.
Why are you rotating the superview also? If you don't do that the center x,y will not be affected.
Why not just use ball.center as the position. This way, rotations will have no effect on the position (assuming your image is correctly centered).