I have an object with a Vector2 Position, and a cursor with Vector2 Position.
When I hold a certain key, I want the object to circle around the object, but I'm having trouble calculating the correct coordinates.
I've managed to make the object circle around the cursor (but it's not going in a perfect circle, but more of a spiral) with this code:
Vector2 diff= Vector2.Normalize(cursor.Location - this.Location);
float angle = (float)Math.Atan2(diff.Y, diff.X) + (float)(90 * (Math.PI / 180));
this.Position += new Vector2((float)(speed * Math.Cos(angle)), (float)(speed* Math.Sin(angle)));
I calculate the angle between cursor's and object's locations, and add 90° (in radians) to that value, which, by my logic, should make the object travel in a perfect circle. However, the distance between the cursor and the object quickly spreads.
What am I calculating wrong here?
Usually when you want something to circle around a point, you define the distance to an amount and you incrementally change the angle in your Update method. THEN in your draw method you can draw it where you should by calculating the position from the cursor.Location, the distance from the cursor and the desired distance.
In most situations like these you want your orbiter to have the same loation like your cursor, so calculating the new position in the Draw method works best, given that these calculations are cheap and super fast (you generally do not want to hog down your Draw method).
I am not able to check it right now, but what you should be doing is something in these lines:
Given that your object should rotate D distance away from your cursor with an angular velocity of AngularVelocity (per second), then when this initially happens, set a variable angle to zero. Then in your update do:
angle += (gameTime.ElapsedGameTime.TotalSeconds * AngularVelocity)
and in your Draw method do:
var displacedPosition = new Vector2(D * Math.Sin(angle), D * Math.Cos(angle));
and render your orbiter using the displacedPosition instead of the normal position if it is currently orbiting.
Related
I am trying to build a simple game, where the user can place some elements and move them around.
What I want is to give the user an option to move the objects on specific axis according to his/her decision.
Pretty much like the movement gizmo in unity.
I know how I can drag an object in the world with the mouse but how can I move on specific axis (e.g. Z axis).
I tried to read the "Mouse X" value, but it only work on a specific viewing angle, if I look at the object from different angle the object won't move correctly.
What I did is this:
private void OnMouseDrag()
{
transform.Translate(moveAxis * Input.GetAxis("Mouse X");
}
where moveAxis is a Vector3 that represents the axis, and the script is attached to the arrow gizmo.
Here's one approach:
Convert the moveAxis direction from local space to screen space. Make sure you have a cached Camera field/variable, because calling Camera.main and/or GetComponent<Camera> is a slow operation:
// Get world direction from moveAxis
Vector3 worldDirection = transform.TransformDirection(moveAxis);
Vector2 screenDirection = camera.WorldToScreenPoint(worldDirection + transform.position)
- camera.WorldToScreenPoint(transform.position);
// optionally, normalize the vector in screen space.
// screenDirection.Normalize();
You can normalize the screen direction if you don't want the angle of the axis on the screen to matter to how fast dragging occurs. You probably don't want to normalize it but give it a try if you want a different feel.
Then, calculate the dot product between the axis direction & the movement of the mouse to calculate a magnitude:
Vector2 mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
float translateMagnitude = Vector2.Dot(mouseMovement, screenDirection);
mouseMovement.x must be negative for left and positive is right and mouseMovement.y must be negative for down and positive for up. If either axis is inverted, multiply that axis's value by -1f.
This way, translateMagnitude will be positive if the mouse is moved in the direction of the axis in screen space, and negative if it is moved against it.
Then, multiply the magnitude by some configurable sensitivity factor and multiply that by the axis vector for the Translate call:
public float translateSensitivity;
...
transform.Translate(moveAxis * translateSensitivity * translateMagnitude);
I have a relatively complicated math problem I need to solve for a game I'm working on in Unity. I've tried a couple things but nothing has worked.
Basically, I need to apply an offset rotation (Quaternion) to a parent, where the result of this rotation is to move its child in a given direction.
To explain it better, the problem would be simple if it could be guaranteed that the parent's forward vector was pointed at the child. Then I would simply create a ghost position by adding the desired direction to the child, and then use a LookAt rotation to rotate the parent to look at that ghost position. (The child doesn't need to be put in a specific position, it just needs to move generally in that direction)
What makes this complicated is that A. the parent could be at any rotation, and B. the child could be at any position relative the parent.
For context, I'm working on a procedural animation system and I'd like to have the bones bend in the direction of the Agent's velocity. With the IK'd bones this is easy, just move the IK. But for the actual bones, I need a way to move a bone in a direction by rotating its parent's bone.
Thanks for any help!
First, we need to have the child's current position and the target position in the coordinate system of the parent. It sounds as if the child's position already is expressed in this coordinate system. Then, if the target position is in world coordinates, you simply do this with the inverse parent world transform:
pTargetLocal = parent.worldMatrix^-1 * pTarget
Once we have this, we want to find a rotation R, such that pCurrentLocal is rotated towards pTargetLocal. Assuming unit vectors (as rotations preserve lengths), this equals:
parent.worldMatrix * pTargetLocal = parent.worldMatrix * R * pCurrentLocal
pTargetLocal = R * pCurrentLocal
Once we have R, we just need to update parent.worldMatrix = parent.worldMatrix * R.
This can be solved by representing R in axis-angle format. The axis would be axis = Vector3.Cross(pCurrentLocal, pTargetLocal) and the angle is angle = Vector3.Angle(pCurrentLocal, pTargetLocal). You can either calculate a quaternion or a matrix from these parameters and multiply it with the current parent transform.
I assumed that the rotation center is the origin of the parent's local coordinate system. You could also rotate about another center to incorporate a translation component.
I have been working on and off of a certain game I'm making (trying to get it finished!) and a problem that has been unsolved for a while in it is the collision detection between a ball and a square.
Basically what I want to happen eventually is depending on the angle/way the rectangle is facing, I want the ball to bounce of it accordingly (I know I could just inverse the ball direction before/as it hit the square).
At the moment though, my current problem is trying to inverse the correct X and Y components depending on the side/face that the ball collides with the square, e.g. if the ball hits the right side of the square, then I need to inverse the ball's X component.
This doesn't seem to work and I was wondering if I could somehow label each side of the rectangle, in terms of for the top of it label that 'face 1' or something, then for the right side of it 'face 2' or 'side 2', etc...
I have provided some code below (this is the code I'm using now):
//(collision with right side of square)
if (theBall.GetRectangle.Left <= thePaddle.GetRectangle.Right)
{
theBall.pVelocity.X = -theBall.pVelocity.X;
}
//(collision with bottom of square)
if (theBall.GetRectangle.Top <= thePaddle.GetRectangle.Bottom)
{
theBall.pVelocity.Y = -theBall.pVelocity.Y;
}
I have written the code for the other 2 sides of the rectangle but they are just the opposite of the two above, i.e. for collision with top of rectangle = opposite of bottom, etc.
EDIT: the object I am checking against if the ball has collided with DOES NOT move, I mean it only rotates... so I don't know if this is important (it probably is, therefore I apologise for missing this info out at the start).
EDIT # 23:36: ok, I have tried something.... and it hasn't worked... :(
public Vector2 DistBetweenBallAndBlock(Paddle thePaddle, Ball theBall)
{
Vector2 centreOfBall = new Vector2(theBall.Texture.Width / 2, theBall.Texture.Height / 2);
float distX = thePaddle.Position.X - centreOfBall.X;
float distY = thePaddle.Position.Y - centreOfBall.Y;
if (distX < 0)
{
distX = -distX;
}
if (distY < 0)
{
distY = -distY;
}
return new Vector2(distX, distY);
}
I have then tried to just print the result just to get an idea of what's going on and what sort of values are being output:
Vector2 a = ball.DistBetweenBallAndBlock(paddle1, ball);
angleOfPaddle = Math.Atan2(a.Y, a.X);
I then just print this value to screen, however I am getting the same result of 0.63...
To detect a collision between Rectangles you could use Rectangle.Intersect method, instead of checking the objects' sides.
And to detect which side of the rectangle is hit, you can compute the Vector2 between the ball center and the rectangle center. Getting its angle with Math.Atan2 you can easily know which face of the rectangle has been hit.
Looked up some Vector stuff, based on my comment.
Collision Style
The optimal way of colliding with a circular object is to collide using a vector between it and the nearest point of the object you're checking against. If the distance is less than or equal to the radius of the circle, there is a collision. The advantages of this method are that you don't have to keep track of a rectangle, you get circular collision, and you get the angle of the collision from the vector.
How You Do It
I'll assume you have some strategy to keep from considering every object every frame, and keep to the basic problem. Your paddle has 4 vertices, one for each corner. Because your ball is essentially a vertex with a picture drawn over it, you can easily check the distance between the ball and each corner of your paddle. Two will be nearest. From there, it's just a matter of finding out if that edge collides. I found a solution to that here, which includes a nice formula.
Does that help?
Is there a code formula for this? I am using C# and XNA, and in my class I have an array of three vectors (representing the vertices of the triangle), as well as a separate vector coordinate.
I plan to update these positions in the loop as it escalates further towards the top of the screen.
I'd ask maths.stackexchange.com, but seeing as how this applies to programming (and I personally am better at reading code as opposed to math itself - I'm still taking Algebra in school), I think it would make more sense for me to ask it here.
Edit
Yes, I am looking for an equilateral triangle. Or any triangle, for that matter. It doesn't matter what it is. All I am looking for is a formula; is that so hard to ask for?
Teh Problem
Basically, the problem I am trying to solve is to shoot a triangle out of my player (think Space Invaders; i.e., the triangle acts as a ray from the ray gun). What I need is a formula of code which will allow the triangle to be rendered based on its center position and radius, as the triangle will move upwards on its Y coordinate. I have the draw calls, and they work, but the problem is that the triangle when put in a for loop draw iteration (where the center vector position - on the Y coordinate - is incremented by N) simply sits next to the player's position when being drawn.
I think this is what you are looking for...
the angle is the orientation of the triangle...
this build a triangle....
void BuildTriangle(Vector2 Center, float Radius, float Angle, Vector2[] tri)
{
for (int i=0; i<3; i++)
{
t[i].X = Center.X + Radius * (float) Math.Cos(Angle + i * 2 * MathHelper.PI/3);
t[i].Y = Center.Y + Radius * (float) Math.Sin(Angle + i * 2 * MathHelper.PI/3);
}
}
if you want to move it, add to the center a velocity vector and rebuild it...
Can anyone help me with this please
I want to be able to rotate a 3D object around a stationary 3D object. Well there will be no movement involved as I just want to draw the objects at their locations once the game starts and then they will remain there for the remainder of the game.
Say for instance I have a object X that is stationary in 3D space. I then have 2 other objects, Y1 and Y2. Both of these objects are stationary as well and cant be moved. All 3 objects are on the same x and y axis. Lets say X is at (0,0,0) and Y1 is at (0,0,-50). I want to draw Y2 at a 45 degree angle from Y1 around the Y-axis but keep it the same distance from X.
Can anyone please suggest the best way of doing this please?
I have tried the following but that just rotates the object around its origin. So I guess I have to rotate it around the world origin? How is this done?
Matrix.CreateRotationY(Rotation)
I'm not sure what you want, but this is one method for rotate one object around another:
Vector3 Origin; // Stationary Object
float Yaw, Pitch; // Angles
float Distance;
Vector3 OrbitOffset = Vector3.UnitX * Distance;
// Other approach that consider the initial pos of the object to rotate
// Vector3 OrbitOffset = OrbitPos - Origin;
Matrix Rotation = Matrix.CreateFromYawPitchRoll(Yaw, Pitch, 0);
Vector3.Transform(ref OrbitOffset, ref Rotation, out OrbitOffset);
Vector3 OrbitPos = Origin + OrbitOffset; // Final position of the rotated object
if you dont need rotation about more than 2 angles at once, you can use basic Euler method.
see :
http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
thats a mathematical approach tough... but it works..
Just if you want a rotation around multiple axes, you will have serious problems with gimbal lock