I'm trying to flip a sprite horizontally i.e.
sprite.scaleX = -1;
What I notice is that the sprite is flipped around its bottom left corner. However since I don't want to mess up my positioning of the sprite (I'd like the sprite to stay in the original place), so I tried to set its anchor point to (1,0)
sprite.anchorPoint = ccp(1,0);
My reasoning is this:
Since the sprite should be flipped around the anchorPoint, if I set the anchorPoint to its bottom right corner then that corner will then become the 'left bottom' corner of the changed sprite; and I should be able to move the sprite using that new anchorPoint just as I do with a normal sprite of anchorPoint (0,0).
However apparently it's not working as I expected. What am I missing?
Edit
What I really want to do is to flip a sprite and then be able to control its position via the left bottom corner - well the left bottom corner of the sprite that I see. I don't think I fully understand how scaleX = -1 is applied relating to the anchorPoint. If somebody can explain to me the concepts behind these parameters then that will greatly help me.
I have to correct myself on making the assertion that setting anchorPoint doesn't help. In fact, setting anchorPoint to (1,0) is exactly the solution to the problem, only that somehow some bug prevented me from recognizing it in my test.
Related
I am having trouble understanding the co-ordinate system in SpriteKit.
The documentation states that a scene size is 1024x768 and the anchor point for the scene is CGPointZero (i.e. the bottom left of the scene). So in Landscape orientation the scene's CGPoint(0,0) is on the bottom left of the view - all good.
However, if the ScaleMode is AspectFill then (as the documentation describes) some of the scene is cropped in portrait orientation - again that makes sense.
Where I am confused is that the cropping appears to be based on an AnchorPoint of CGPoint(0.5,0.5). I.e. a sprite with AnchorPoint CGPoint(0,0) that is drawn at scene position CGPoint(0,0) is cropped in portrait orientation.
My question is: "If the scene's anchor point is CGPoint(0,0) and the ScaleMode is AspectFill, why does this the node at CGPoint(0,0) cropped? Shouldn't it ensure that the bottom left of the scene is always at the bottom left of the view?"
Do not confuse your scene with your view.
Yes, for your scene, the default is bottom left. But scaling applies from the scene to the view. By default, your scene is added to the center of the view.
As far as scaling goes, imagine it being like a balloon that you are going to wrap around a box.
You pull it from all ends evenly till the entire balloon fits around the edges of the box.
Then you take Aspect fill into consideration by taking 2 rectangle boxes, and placing them on the sides so that your box top turns into the desired shape.
This is why (0,0) ends up getting cropped off.
The anchor point applies to what happens inside the scene, not outside.
You would need to change the views anchor point (Not possible that I know of) to achieve what you want, or just shift the scene to the right by the difference of (sceneWidth * scaleFactor) - viewWidth
What is the benefit or purpose to change the CALayer position, which is by default in center, don't it suppose to be a center of CALayer? Whats the point changing a center point to bottom right or any other, because bottom right can't be the center of a square.
It's helpful for things like rotation where you may want to rotate around a particular point instead of the center
This seems to be a major oversight by Apple, but since SKPhysicsJoints have their anchor points set in Scene coordinates, this makes doing any kind of scrolling game impossible.
To simulate a camera in SpriteKit you create a WorldNode which contains all of the gameplay elements, and then pan that around the scene. Unfortunately, doing this causes the Scene coordinates of every object in the game to change on every frame as you pan the world around. In turn, this breaks the joint anchor points, and things go berserk.
There isn't even a way to change the joint's anchor point, so I don't even have a way of just updating the coordinate every frame. It would seem that using SKPhysicsJoint in a scrolling game is not an option.
Does anyone know of a way around this?
Ok, I think I figured out what was going on, and I was totally incorrect in my original assumption. The reason my anchor points looked incorrect is because the [convertPoint toNode] call was returning me Scene coordinates that were incorrect. After several hours I realized it was off by exactly half the screen dimensions. My Scene has an anchorPoint of (0.5, 0.5), but this screws up the conversion values. So, if I simply offset the point by width/2, height/2 it's correct:
GPoint pt = CGPointMake(anchorWorldX, anchorWorldY);
pt = [gGameScene convertPoint:pt fromNode:gGameWorld]; // convert to scene coords, but it's WRONG
pt.x += scene.size.width * scene.anchorPoint.x; // this properly adjusts the value to be correct
pt.y += scene.size.height * scene.anchorPoint.y;
SKPhysicsJointPin* pin =[SKPhysicsJointPin jointWithBodyA:hinge.physicsBody bodyB:door.physicsBody anchor:pt];
I'm creating a car driving game for iOS, but there's a problem:
I added these lines to my ViewController.m:
_carView.transform = CGAffineTransformMakeRotation(steeringTemp-45);
steeringTemp is a float variable wich is changed by the left and right steering buttons.
But when I run the app and press the steering button, the car is rotating in an ugly way. It seems like the center point is changing everytime and the car is rotating like a triangle. I tried to set the origin to the center of the _carView, which is an image view, but it didn't work.
First of all let me tell you that you should be using radians, and not degrees. You can use this macro:
#define DEGREES_TO_RADIANS(angle) (angle * M_PI / 180.0)
And wrap it around your values:
CGAffineTransformMakeRotation(DEGRESS_TO_RADIANS(steeringTemp-45));
Second usually transforms go wrong if you:
Are rotating with the wrong anchorPoint (usually happens with clock pointers)
Don't pay attention to the order of transforms
Anchor Point
You need to make sure that your anchor point to the place you wanted. The anchorPoint defaults to the center, but you can set it to any point you like in the layer that is backed by the view. The anchor point has relative coordinates, so it goes from 0 to 1. (0,0) is your left top corner and (1,1) is your bottom right corner.
You can set it like this:
_carView.layer.anchorPoint = CGPointMake(0, 0);
Transforms order is important
Additionally, be careful if you apply more transforms you should pay attention to the order of those transforms. The previous transforms will always affect the next transforms. A rotation followed by a translation is way different than a translation followed by a rotation.
I am having some issues understanding and using anchorPoint. As I understand it, the default anchor is (.5,.5) which applies transforms about the center of objects. However, when I placed a UIButton into a CCUIViewWrapper, I noticed that scaling it would scale about the right side of the object (i.e. if I scaled from 0 to 1, it would grow from right to left).
I wasn't sure what to make of this, but with tinkering found that I had to adjust the anchor point to (0,0) in order to make scaling occur about the center of the object. Why would this happen?
Further more, while I expect that to make the anchor be the bottom left of the object because Cocos2d is bottom left oriented for (0,0), it did not and in fact aligned the top left with my wrapper's position value.
In the end, what worked to scale about the center was to make the anchor point (0,0) and position the wrapper using the top left of the object, almost as if it were using the UIView coordinates to place the object. I'm not certain if this behavior is something occurring strictly with wrapped UIViews in CCUIViewWrappers nor do I know if this is simply correct behavior and I'm completely misunderstanding it.
Can someone clarify and explain?
I've had a similar problem with the wrapper. One of the issue here is that the wrapper attaches the view to the root window instead of the director's OpenGL view, which means it wont respect whatever autorotation the OpenGL view is using. The code looks like it is trying compensate for the difference between UIView and Cocos2d coordinates but doesn't seem to do it properly when it comes to anchor points. I ended up just using UIView coordinates in the end but I did experiment with an alternate method for setting the anchor point by using:
uiItem.center = ccp((self.anchorPoint.x - 0.5f) * self.contentSize.width, (self.anchorPoint.y - 0.5f) * self.contentSize.height);
At the start of the updateUIViewTransform method in CCUIViewWrappers before setting the view's transform. This makes anchor points behave as expected, at least for views attached directly to a layer.
Instead of using:
uiItem.center = ccp((self.anchorPoint.x - 0.5f) * self.contentSize.width, (self.anchorPoint.y - 0.5f) * self.contentSize.height);
which set the anchor point to the bottom right, I used:
uiItem.center = ccp(-uiItem.bounds.size.height/2, uiItem.bounds.size.width/2);
which set it to the center.
The reason the x and y are flipped, I'm guessing it's because my item is rotated by 90.