Vector math, finding the angle - vector

I am trying to learn XNA by writing a small 2D game, it's a Top-Down perspective and Im trying to have double movement, moving along the axis using Left-Right and Up-Down keys, as well as looking right at the mouse cursor, so that the player can run and aim at the same time.
I have one vector for the player position (m_PlayerPos), and one vector for the mouse position (m_MousePos), and im trying to get the correct angle towards the mouse position.
Im using the formula method:
public static float Angle(Vector2 from, Vector2 to)
{
return (float)Math.Atan2(from.X - to.X, from.Y - to.Y);
}
This works, but for some reason the method only works half-way, along the x-axis. When the mouse is to the exact left of right of the player, the player looks right at the mouse.
But if I move to the top of the player, it looks down, and if the mouse is below the player, the player looks up. So I need to inverse the Y axis, but Im not sure how.
Thanks in advance for any feedback.

Use to.Y - from.Y.

Multiply it with (0.0, -1.0) (or just multiply the Y component by -1.0). This will mirror the vector along the horizontal axis and should achieve the result you want.

In screen space the origin is in the top-left corner with the Y axis pointing downward whereas in eucledean space the Y axis points upwards. That's why you observe the Y axis being "flipped".

Related

Centering Perspective Camera on two objects by panning

In Unity, I have a perspective camera, and I've got two transforms in my scene that I want the camera to perfectly center on screen. The camera will pan left/right/up/down to the appropriate location.
So far my approach has been to convert the transform positions to screen positions using Camera.WorldToScreenPoint, and taking their average to find the screen midpoint. From there, I know I want to pan the camera a certain number of units toward that midpoint. What I'm having trouble with is figuring out the formula for deciding how much to pan (or, maybe this isn't even the preferred way to determine this).
I think your approach is great. Let me expand the idea.
So this is your screen :D. Blue circle is where you want your objects to be. There are two scenarios. We will use green dots as an example of zooming scenario. Then red dots for panning scenario.
The trick is, you want to keep the dots as close as possible to circumference of blue circle.
Let's say you get red dots as your objects' screen position. You have to shift them towards the center. Let's calculate CenterOfDots. Then calculate it's difference to CenterOfBlueCircle. That's how much pan you need in screen coordinates.
So you have calculated the pan. Now you want to know how much you need to zoom. Let's say you get green dots this time. Calculate DistanceBetweenDots and compare it to DiameterOfBlueCircle. You want them to be the same. So their difference is how much zoom you need in screen coordinates.
There comes the tricky part. Now you know how much to pan and zoom in screen space. But you need to move the camera in world space. Trying to solve it using geometry magic is fine. But I hate headache :D
So instead, I would iteratively shift my camera using the data I calculated above. Just shift the camera in it's local x-y axes towards HowMuchPan, multiplied by a manually given coefficient PanSpeed. This will give a smooth transition to the camera. Same is for the zoom. This time you shift the camera in it's local z axis using HowMuchZoom multiplied by your manually given coefficient ZoomSpeed.
Hope it helps. Have fun :)
i figured out the mathy approach!
for panning, you want to figure out the average screen position of your objects (i.e. the middle). then you want to generate a couple world points against an arbitrary plane some distance away from the camera. the difference between these points is how much to pan the camera
center=Camera.ScreenToWorldPoint(Screen.width*0.5f, Screen.height*0.5f, 10f)
mid=Camera.ScreenToWorldPoint(averageScreenPoint.x, averageScreenPoint.y, 10f)
Camera.transform.Translate(mid-center)
zooming is a bit more complicated, but very similar to the panning approach. you want to use Camera.ScreenToWorldPoint against an arbitrary plane, but you want to do this for 4 points, which will help you figure out a scale to apply to your camera's z position. psuedocode -
screenMin = Camera.ScreenToWorldPoint(0f,0f,10f);
screenMax = Camera.ScreenToWorldPoint(Screen.width,Screen.height,10f);
objMin = Camera.ScreenToWorldPoint(screenPosMin.x, screenPosMin.y, 10f);
objMax = Camera.ScreenToWorldPoint(screenPosMax.x, screenPosMax.y, 10f);
screenDiff = screenMax-screenMin;
objDiff = objMax-objMin;
Vector3 scale = new Vector3(objDiff.x/screenDiff.x, objDiff.y/screenDiff.y, 0f);
ratio = scale.x < scale.y ? scale.y : scale.x;// pick the one that best puts fits on screen.
Camera.localPosition.z = Mathf.Min(ZoomMin, Camera.localPosition.z*ratio);

Rotating a vector in libgdx box2d, firing a cannon ball from a cannon

I have a cannon that fires a cannonball and smoke particle effect, i want the cannon ball to start at the end of the cannon, this i can do by adding the width of the cannon to its x position and adding the half the height to the cannon. This works fine when the cannon is unrotated but when i rotate the cannon its not in the correct position. This is what i use to try and rotate the vector.
Vector2 rotPos = cannon.position.tmp().add(cannon.bounds.width, cannon.bounds.height/2).rotate(cannon.angle);
How can i get a rotated vector that fires the cannon ball in the correct place. See image below.
UPDATE
I tried the below also, same result the ball is off to the left
Vector2 rotPos = world.CannonBody.getWorldVector( world.CannonBody.getPosition() );
The way that you've described the problem, you've solved it for only a single case. This really is just a math problem. Think about the direction you want to shoot, the barrel of the cannon, as the coordinates on a circle.
Since you know the angle, this is easy. Draw a circle with a dot in the center. Then draw a line from the center to the right edge. Then draw another line at a 45 degree angle up from the first line. Connect the two points on the edges with a straight line. You have a triangle now.
Lets call the 45 degree angle line 'r'. And we'll call the first line x, and the last line y.
You should have something that looks like this:
http://i.stack.imgur.com/MJNWZ.jpg
We know that sin(angleInRadians) = y/r. Doing a little algebra we can change this into r*sin(angleInRadians) = y
Boom, you have your y coordinate.
Almost the same thing: cos(angleInRadians) = x/r
So r*cos(angleInRadians) = x
There's your x coordinate.
The you can get the angle of a body directly from box2d, so that's easy. You just need to pick a value for 'r' that represents a correct radius for the circle that you're using to conceptualize the barrel of the cannon at a given angle. If the cannon rotates around the center of the circle, then r is the length of your cannon.
I had an issue which is similar to yours. Here's the question with an answer:
Android. How to move object in the direction it is facing (using Vector3 and Quaternion)
You need something like
translation.set(baseDirection).rot(modelInstance.transform).nor()

Math/Calculations for infinite/repeating world with rotation

How do I make a infinite/repeating world that handles rotation, just like in this game:
http://bloodfromastone.co.uk/retaliation.html
I have coded my rotating moving world by having a hierarchy like this:
Scene
- mainLayer (CCLayer)
- rotationLayer(CCNode)
- positionLayer(CCNode)
The rotationLayer and positionLayer have the same size (4000x4000 px right now).
I rotate the whole world by rotating the rotationLayer, and I move the whole world by moving the positionLayer, so that the player always stays centered on the device screen and it is the world that moves and rotates.
Now I would like to make it so that if the player reaches the bounds of the world (the world is moved so that the worlds bounds gets in to contact with the device screen bounds), then the world is "wrapped" to the opposite bounds so that the world is infinite. If the world did not rotate that would be easy, but now that it does I have no idea how to do this. I am a fool at math and in thinking mathematically, so I need some help here.
Now I do not think I need any cocos2d-iphone related help here. What I need is some way to calculate if my player is outside the bounds of the world, and then some way to calculate what new position I must give the world to wrap the world.
I think I have to calculate a radius for a circle that will be my foundry inside the square world, that no matter what angle the square world is in, will ensure that the visible rectangle (the screen) will always be inside the bounds of the world square. And then I need a way to calculate if the visible rectangle bounds are outside the bounds circle, and if so I need a way to calculate the new opposite position in the bounds circle to move the world to. So to illustrate I have added 5 images.
Visible rectangle well inside bounds circle inside a rotated square world:
Top of visible rectangle hitting bounds circle inside a rotated square world:
Rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world:
Another example of top of visible rectangle hitting bounds circle inside a rotated square world to illustrate a different scenario:
And again rotated square world moved to opposite vertical position so that bottom of visible rectangle now hitting bounds circle inside rotated world:
Moving the positionLayer in a non-rotated situation is the math that I did figure out, as I said I can figure this one out as long as the world does not get rotate, but it does. The world/CCNode (positionLayer) that gets moved/positioned is inside a world/CCNode (rotationLayer) that gets rotated. The anchor point for the rotationLayer that rotates is on the center of screen always, but as the positionLayer that gets moved is inside the rotating rotationLayer it gets rotated around the rotationLayer's anchor point. And then I am lost... When I e.g. move the positionLayer down enough so that its top border hits the top of the screen I need to wrap that positionLayer as JohnPS describes but not so simple, I need it to wrap in a vector based on the rotation of the rotationLayer CCNode. This I do not know how to do.
Thank you
Søren
Like John said, the easiest thing to do is to build a torus world. Imagine that your ship is a point on the surface of the donut and it can only move on the surface. Say you are located at the point where the two circles (red and purple in the picture) intersect:
.
If you follow those circles you'll end up where you started. Also, notice that, no matter how you move on the surface, there is no way you're going to reach an "edge". The surface of the torus has no such thing, which is why it's useful to use as an infinite 2D world. The other reason it's useful is because the equations are quite simple. You specify where on the torus you are by two angles: the angle you travel from the "origin" on the purple circle to find the red circle and the angle you travel on the red circle to find the point you are interested in. Both those angles wrap at 360 degrees. Let's call the two angles theta and phi. They are your ship's coordinates in the world, and what you change when you change velocities, etc. You basically use them as your x and y, except you have to make sure to always use the modulus when you change them (your world will only be 360 degrees in each direction, it will then wrap around).
Suppose now that your ship is at coordinates (theta_ship,phi_ship) and has orientation gamma_ship. You want to draw a square window with the ship at its center and length/width equal to some percentage n of the whole world (say you only want to see a quarter of the world at a time, then you'd set n = sqrt(1/4) = 1/2 and have the length and width of the window set to n*2*pi = pi). To do this you need a function that takes a point represented in the screen coordinates (x and y) and spits out a point in the world coordinates (theta and phi). For example, if you asked it what part of the world corresponds to (0,0) it should return back the coordinates of the ship (theta_ship,phi_ship). If the orientation of the ship is zero (x and y will be aligned with theta and phi) then some coordinate (x_0,y_0) will correspond to (theta_ship+k*x_0, phi_ship+k*y_0), where k is some scaling factor related to how much of the world one can see in a screen and the boundaries on x and y. The rotation by gamma_ship introduces a little bit of trig, detailed in the function below. See the picture for exact definitions of the quantities.
!Blue is the screen coordinate system, red is the world coordinate system and the configuration variables (the things that describe where in the world the ship is). The object
represented in world coordinates is green.
The coordinate transformation function might look something like this:
# takes a screen coordinate and returns a world coordinate
function screen2world(x,y)
# this is the angle between the (x,y) vector and the center of the screen
alpha = atan2(x,y);
radius = sqrt(x^2 + y^2); # and the distance to the center of the screen
# this takes into account the rotation of the ship with respect to the torus coords
beta = alpha - pi/2 + gamma_ship;
# find the coordinates
theta = theta_ship + n*radius*cos(beta)/(2*pi);
phi = phi_ship + n*radius*sin(beta)/(2*pi));
# return the answer, making sure it is between 0 and 2pi
return (theta%(2*pi),phi%(2*pi))
and that's pretty much it, I think. The math is just some relatively easy trig, you should make a little drawing to convince yourself that it's right. Alternatively you can get the same answer in a somewhat more automated fashion by using rotations matrices and their bigger brother, rigid body transformations (the special Euclidian group SE(2)). For the latter, I suggest reading the first few chapters of Murray, Li, Sastry, which is free online.
If you want to do the opposite (go from world coordinates to screen coordinates) you'd have to do more or less the same thing, but in reverse:
beta = atan2(phi-phi_ship, theta-theta_ship);
radius = 2*pi*(theta-theta_ship)/(n*cos(beta));
alpha = beta + pi/2 - gamma_ship;
x = radius*cos(alpha);
y = radius*sin(alpha);
You need to define what you want "opposite bounds" to mean. For 2-dimensional examples see Fundamental polygon. There are 4 ways that you can map the sides of a square to the other sides, and you get a sphere, real projective plane, Klein bottle, or torus. The classic arcade game Asteroids actually has a torus playing surface.
The idea is you need glue each of your boundary points to some other boundary point that will make sense and be consistent.
If your world is truly 3-dimensional (not just 3-D on a 2-D surface map), then I think your task becomes considerably more difficult to determine how you want to glue your edges together--your edges are now surfaces embedded in the 3-D world.
Edit:
Say you have a 2-D map and want to wrap around like in Asteroids.
If the map is 1000x1000 units, x=0 is the left border of the map, x=999 the right border, and you are looking to the right and see 20 units ahead. Then at x=995 you want to see up to 1015, but this is off the right side of the map, so 1015 should become 15.
If you are at x=5 and look to the left 20 units, then you see x=-15 which you really want to be 985.
To get these numbers (always between 0 and 999) when you are looking past the border of your map you need to use the modulo operator.
new_x = x % 1000; // in many programming languages
When x is negative each programming language handles the result of x % 1000 differently. It can even be implementation defined. i.e. it will not always be positive (between 0 and 999), so using this would be safer:
new_x = (x + 1000) % 1000; // result 0 to 999, when x >= -1000
So every time you move or change view you need to recompute the coordinates of your position and coordinates of anything in your view. You apply this operation to get back a coordinate on the map for both x and y coordinates.
I'm new to Cocos2d, but I think I can give it a try on helping you with the geometry calculation issue, since, as you said, it's not a framework question.
I'd start off by setting the anchor point of every layer you're using in the visual center of them all.
Then let's agree on the assumption that the first part to touch the edge will always be a corner.
In case you just want to check IF it's inside the circle, just check if all the four edges are inside the circle.
In case you want to know which edge is touching the circumference of the circle, just check for the one that is the furthest from point x=0 y=0, since the anchor will be at the center.
If you have a reason for not putting the anchor in the middle, you can use the same logic, just as long as you include half of the width of each object on everything.

How to convert mouse movements to rotation of an element

I'm building a wheel menu control. The idea is you spin the wheel until the item you want to act on is in view, then you click on it or whatever. I'm trying to figure out how to translate the user's mouse movements (x & y) into the number of degrees to spin the wheel. I can implement it all, I just am missing the math to do the conversion. Any help or pointers are appreciated!
If the user moves the mouse from [x1,y1] to [x2,y2], what you basically want is to find
θ=θ1-θ2
Where:
θ1 = Math.atan2(y1, x1);
θ2 = Math.atan2(y2, x2);
Now all of this depends on where you define your origin (center of your wheel). If your origin is [x0,y0], then just subtract those values from the actual mouse co-ordinates.
Also on screen, the co-ordinate system is upside down, so 0,0 is in the top-left instead of bottom-left, so you'd need to flip that, but the math is essentially the same.
Also note that the angle is measured in radians and not degrees.
Take the atan2() of two subsequent positions offset from the center of the control and change the value by the delta of the angles multiplied by a constant.

moving items in JPanel

I am working on a pong game and I am working on the mechanism to move the ball. If I add 1 to x the ball moves 1 pixel to the right, if i add 1 to y the ball moves 1 pixel to the bottom. What if I want to move the ball at a certain angle how can 1 calculate the coordinates.
Trying to work with angles will get a bit more complicated than you need to get. For this kind of animation you generally want to use floats to store your objects x and y coordinates and move it by applying x and y deltas (The floats will preserve the detail of the position which is lost to rounding when drawn on the screen). The deltas represent the speed your object is moving in each axis and can be negative or positive.
For each iteration of your animation, add xdelta to your x coordinate and add ydelta to your y coordinate. Round them off to position them on the screen.
When you hit the top or bottom border, you would swap the sign on your ydelta component and likewise for side borders.
You wouldn't want to keep the same x and y delta all the time so when the objects hits a paddle, modify the x or y delta a little bit to change up the angle.
you are looking for line drawing algorithms, something like Bresenham or DDA you can find some reasonable implementations here ofcourse instead of drawing a complete line you would move your ball along that line but the way of finding the set of lines to move on is the same.
You might find these resources helpful.
for something like Pong you should be investigating vector math, but if all you want is to know an angle all you really need is SOHCAHTOA.

Resources