Swift-Making an SKNode simply "move forward" on an angle - swift

I've already asked this question in a different way here; Swift-Setting a physics body velocity by angle but the three attempts to answer it were unfortunately not exactly what I'm looking for, although I'm grateful for what they taught me anyway. I decided that I should simply rephrase my question with an example and further explanation instead of perpetuating a discussion via comments. So here it is.
Imagine I have an SKNode positioned in the centre of the screen. Let's say this is a ball, so any rotation action on it is not visible. I would need a way to have a random angle selected, and have said SKNode rotate to it, and then continuously move in the direction determined by the aforementioned angle from its original position in the centre of the screen, until, say, the edge of the screen.
I know how to determine the random angle, have the SKNode rotate to it, and have it stop at the edge of the screen. Hopefully with this example what I need is clearer, a way to simply have an SKNode move forward, but on an angle determined by a single variable, and not a velocity determined by two, dx and dy.
Thanks in advance.

To do this, you just need to use some trigonometry!
When zRotation is between 0 and 90, you don't need to do anything to the angle except converting it to radians. Just call tan(radianAngle). Now tan will return how much should the node move in the y axis when it moves by 1 in the x axis. If you learned trigonometry before, you should understand what I'm saying. If you have not learned trigonometry, learn it. :)
Let's say the node's zRotation is 60 degrees, which is π/3 radians. Pass that into tan and you get √3. This means your dx and dy parameters in SKAction must be in the ratio of 1 : √3 in order to make the node move in the direction of 60 degrees.
When zRotation is between 90 and 180, you need to first subtract the angle from 180, then convert it to radians. Again, pass that to tan and the return value is how much your node should move in the y direction when it moves by -1 in the x axis. The dx : dy ratio is now -1 : tan(angleInRadians).
When zRotation is between 180 and 270, subtract 180 from that angle and convert it to radians. The dx : dy ratio is -1 : -tan(angleInRadians).
Lastly, a zRotation bewteen 270 and 360, subtract the angle from 360 and convert it to radians. The dx : dy ratio is 1 : -tan(angleInRadians).
Just before you convert the angle to radians, check if the angle is 90 degrees. If it is, please hard code the dx and dy because tan(M_PI / 2) is undefined.

Related

Onscreen angle of 3D vector

My math is too rusty to figure this out. I want to derive the onscreen angle (the angle as seen on the 2d screen) of a 3d vector.
Given the x and y rotation of a vector (z rotation is zero and doesn't mstter), what does the angle on screen look like?
We know when y is zero and x is positive, the angle is 90. When y is zero and x is negative the angle is -90. When y is 90, for any value of x, the angle is 180. When y is -90, for any value of x, the angle is 0.
So what the formula here so I can derive the angle for the other values of x and y rotation?
The problem, as stated, doesn't make sense. If you're holding z to zero rotation, you've converted a 3D problem to 2D already. Also, it seems the angle you're measuring is from the y-axis which is fine but will change the ultimate formula. Normally, the angle is measured from the x-axis and trigometric functions will assume that. Finally, if using Cartesian coordinates, holding y constant will not keep the angle constant (and from the system you described for x, the angle would be in the range from -90 to 90 - but exclusive of the end points).
The arctangent function mentioned above assumes an angle measured from the x-axis.
Angle can be calculated using the inverse tangent of the y/x ratio. On unity3d coordinated system (left-handed) you can get the angle by,
angle = Mathf.Rad2Deg * Mathf.Atan(y/x);
Your question is what will a 3-d vector look like.
(edit after posted added perspective info)
If you are looking at it isometrically from the z-axis, it would not matter what the z value of the vector is.
(Assuming a starting point of 0,0,0)
1,1,2 looks the same as 1,1,3.
all x,y,z1 looks the same as any x,y,z2 for any values of z1 and z2
You could create the illusion that something is coming "out of the page" by drawing higher values of z bigger. It would not change the angle, but it would be a visual hint of the z value.
Lastly, you can use Dinal24's method. You would apply the same technique twice, once for x/y, and then again with the z.
This page may be helpful: http://www.mathopenref.com/trigprobslantangle.html
Rather than code this up yourself, try to find a library that already does it, like https://processing.org/reference/PVector.html

How to calculate image rotation from touches?

I'm an iphone developer, but this question is about geometry.
I have a simple rectangle (maybe a photo). The user touches this photo at a point and drags their finger to a new point:
http://dl.dropbox.com/u/792862/Untitleddrawing.png
How many radians I must rotate this rectangle to simulate a rotation given by the touches?
I'm assuming that you have a fixed origin for your rotation (the crosshair in your picture would suggest so) and the touch sets the other point.
First you need a method to figure out the angle of a line. The atan2 function (available in any well-equipped math library) figures out the angle between any line and the X axis. First figure out the starting angle:
startAngle = atan2(startY - originY, startX - originX)
And then the ending angle:
endAngle = atan2(endY - originY, endX - originX)
And then just subtract the two angles from each other to figure out your rotation:
angleToRotate = endAngle - startAngle
You might need to swap things around depending on which way your rotations work.
Use atan2 to convert the starting point and the ending point to angles, after translating each to correct for a non-(0,0) origin if necessary.

Matlab matrix translation and rotation multiple times

I have a map of individual trees from a forest stored as x,y points in a matrix. I call it fixedPositions. It's cartesian and (0,0) is the origin.
Given a velocity and a heading, i.e. .5 m/s and 60 degrees (2 o'clock equivalent on a watch), how do I rotate the x,y points, so that the new origin is centered at (.5cos(60),.5sin(60)) and 60 degrees is now at the top of the screen?
Then if I were to give you another heading and speed, i.e. 0 degrees and 2m/s, it should calculate it from the last point, not the original fixedPositions origin.
I've wasted my day trying to figure this out. I wish I took matrix algebra but I'm at a loss.
I tried doing cos(30) and even those wouldn't compute correctly, which after an hour I realize were in radians.
I'd try the following: In your object, you already have a property heading. Now you add another property, currentPosition (an maybe rename them to heading_robot and currentPos_robot). heading as well as currentPosition should always be relative to the original coordinate system
Then you add a new method, updatePosition that takes (newHeading, distance) as input. This method will update both heading and currentPosition, by first adding the angle in newHeading to the angle in heading, after which you update currentPosition by adding [distance*cos(heading),distance*sin(heading)] (check for signs of sin/cos here!) to the old value of currentPosition.
Finally, to get the view of the landscape (i.e. apparentPositions), you run bsxfun(#minus,fixedPositions,currentPosition) to move the origin to where the robot is at this moment, and then you multiply with the 2D rotation matrix using the angle stored in heading.
You just first translate the coordinates (-0.5cos(60),-0.5sin(60)) to take the origin to your target point.
Then rotate by multiplying the coordinates by a rotation matrix.
Of course, most programming languages use radians as angle units, so that instead of 60 you must enter 60 * PI / 180

iPhone Pong Advanced Deflection Angle

I am currently developing a simple Pong game for the iPhone. Currently using CGRectIntersectsRect for the collision detection and as for the deflection of the ball when it hits the paddle, I just multiply the ball velocity with -1 (therefore reversing the direction of the ball).
What I am trying to do is to make it so that when the ball hits the paddle, it checks whether how far is the ball from the center of the paddle, and increases the deflection angle the further the ball is away from the center of the paddle. (E.g. In this case, the ball will be deflected back at 90 degrees no matter where it came from, as long as it hits the center of the paddle)
How am I suppose to do that?
Any help would be greatly appreciated.
Thank you.
What you have given us are reference points (centre and edge). What we need are a reference line from which to measure the new angle. Additionally, what you are saying is not consistent and thus does not make sense.
I am guessing that what you are asking is a way to calculate the outgoing angle such that it is only a function of where it hit on the paddle. If it hit the paddle centre, then irrespective of the incoming angle, it will bounce off at an angle of 90 degrees to the paddle. If it hit the paddle edge, then irrespective of the incoming angle it will bounce off at an angle of 45 degrees to the paddle.
If so, then the following should do it (it is not the only way).
Assumption: The paddle shape is a rectangle.
Let L be the length of the paddle.
Let K be a constant such that L / (2 * K) = 1 / sqrt(2).
Let D be the distance from the centre of the paddle (may be + or -).
theta = pi/2 - asin (D / K);
This should give you an angle relative to the paddle.
Hope this helps.

cocos2d help find points on a circle

I am trying to solve a tricky math problem, in a cocos2d for iphone context.
Basically I have a roullette wheel which is rotating over time.
I want to have a Sprite latch onto the wheel at certain points (like compass ordinal points N, S, E, W) and bounce off at all other points.
I have the image of the wheel rotating, and just need to solve the part where I can test for whether a sprite has intersected with the circle at the right point on the circle as it is rotating.
I think this question is going in the right direction, but I can't get my head around it. Can anyone help explain?
Best way to find a point on a circle closest to a given point
If I understand correctly:
First check the distance between the sprite and the centre of the roulette wheel. This will tell you if the sprite is at the edge of the wheel. (If not, nothing happens, right?)
Then, find the angle that the sprite makes from the "x-axis" of the roulette wheel.
spriteAngle = atan2(sprite.x - rouletteCentre.x, sprite.y - rouletteCentre.y)
You'll need to find the equivalent of the atan2() function. It usually returns an answer in radians; you may want to convert it to degrees or quarter-turns or something if you prefer.
Then, subtract the angle that the roulette wheel itself is rotated by (if the wheel itself is rotating, if not then you're already done). Make sure your angle measurement is consistent.
actualAngle = spriteAngle - rouletteRotationAngle
Note that actualAngle may be outside the range 0-360 degrees, and you will need to make it "wrap around".
Lastly, you will want to allow a small range of values as acceptable (e.g. 98 degrees to 102 might count as "North").
So you have a circle of radius r, with center (x0,y0).
A point lies outside of the circle, at coordinates (x,y). Your question is to find the closest point on the circle itself to the point (x,y).
The solution is simple. The closest projection of a point onto a circle is accomplished by a simple scaling. Thus,
d = sqrt((x-x0)^2 + (y-y0)^2)
xp = x0 + (x - x0)*r/d
yp = y0 + (y - y0)*r/d
The new point (xp,yp) will lie on the circle itself. To be honest, you would be better off to work in polar coordinates, with the origin at the center of the circle. Then everything gets much easier.
Your next question will be where did it hit on the circle? Don't forget the points of the compass on the circle are rotating with time. An atan2 function will give you the angle that the point (xp-x0,yp-y0) lies at. Most toolsets will have that functionality. See that I've subtracted off the origin here.