Trying to figure out the new rotation angle for rocket - math

i have this code
float angle = rocket.rotation;
float vx = sin(angle * M_PI / 180) * xVelocity;
float vy = cos(angle * M_PI / 180) * yVelocity;
CGPoint direction = ccp(vx, vy);
[rocket setPosition:ccpAdd(rocket.position, direction)];
yVelocity -= 0.2;
basically it fires a rocket in the direction i set it to face. This works fine the rocket goes up then comes down fine. I now need to make the rockets rotation change with the new direction i am setting so that the rocket is rotated correctly for the way it is flying. How can i work out the new angle i need to rotate the rocket properly? I'm assuming i can use the new direction to create this new angle but im not sure how. Thanks

I'm not really sure what you mean, but the first part is not accurate
float angle = rocket.rotation;
float vx = sin(angle * M_PI / 180) * xVelocity;
float vy = cos(angle * M_PI / 180) * yVelocity;
To say how fast the rocket is going and in what direction, you have two options:
Tell direction(angle) and speed(how fast it goes in m/second)
Tell horizontal velocity (how fast it goes horizontally in m/second) and vertical velocity(m/second)
If you have the velocity(horizontal and vertical), you can calculate the speed and direction. And also, if you have the angle and speed, you can calculate the velocity(horizontal and vertical). Your code seems to be calculating the velocity, from direction and velocity instead of direction and speed.
float angle = rocket.rotation;
xVelocity = sin(angle * M_PI / 180) * speed;
yVelocity = cos(angle * M_PI / 180) * speed;
yVelocity -= 0.2f;//apply gravity
//now we need to find the new angle and speed again
//speed is easy, Pythagoras helps
speed = sqrt(xVelocity*xVelocity + yVelocity*yVelocity);
//angle is more difficult, luckily atan2 solves this:
angle = atan2(yVelocity,xVelocity);
//now we can update the rocket
//Sorry, but I don't know COCOS...

Related

Yaw pitch rotation issues

am coding some stuff which should intercept target correctly like turret,cannon.
All calculated correctly but while enemy is moving to left or right side of screen (also up and down) my bot cant shoot them correctly, center is fine. Here little example whats happens with wrong yaw issue, same with pitch https://i.stack.imgur.com/GYGNV.png
Mission is save bot rotation as is, and fix missfire issues.
As main concept i taken camera position and enemy center
Vector2 Rotate(Vector3 Calc)
{
Vector2 coord;
float Yaw = (float)(atan2(Calc.y, Calc.x)) * 180.0f / M_PI;
float Pitch = (float)(atan2(Calc.z, sqrtf(Calc.x * Calc.x + Calc.y * Calc.y))) * 180.0f / M_PI;
coord.x = Pitch;
coord.y = Yaw;
return coord;
}
Vector3 Diff = Target - Bot;
Vector2 Angle = Rotate(Diff);

Calculating gravity velocity over a given distance and time

I'll just start by saying I'm looking at the "projectile" code found in the game "Runescape" originally wrote in Javascript. The original code can be found somewhere half way down the page of this link https://github.com/zg/317-client titled "Projectile". Ultimately what it does is track an object a move towards it at a certain speed relative to the targets distance and the amount of ticks left. The reason I'm racking my brains on this, originally was because of the tan function for the direction of the velocity, but now I'm trying to figure out part of an equation used in calculating the up and downwards force.
I've translated a basic form of this code to Unity in C# to try and reverse engineer it.
void Update()
{
if(x >= distance)
{
x = 0;
z = 0;
duration = 20;
velocityX = 0; velocityZ = 0; acceleration = 0f;
mobile = false;
target();
}
sim();
duration-= interval;
}
void target()
{
velocityX = distance / duration;
if (!mobile) {
velocityZ = -velocityX * Mathf.Tan(elevationPitch * 0.02454369f);
}
}
void sim()
{
acceleration = 2f * (- z - velocityZ * duration) / (duration * duration);
mobile = true;
x += velocityX * interval;
z += velocityZ * interval + 0.5f * acceleration * interval * interval;
velocityZ += acceleration * interval;
cube.transform.position = new Vector3(x,z,0);
}
}
I understand how the velocity addition works in regard to interval, and that velocityX is set to move along x distance linearly over a given duration. If I understand the tan function correctly also, it is used to determine the angle of trajectory and thus the direction of velocity.
In the past couple of days that I have been analyzing this, I was googling a lot about parabolic trajectory and anything related to this topic. I found that the 0.5f * acceleration * interval * interval is the formula for calculating distance and gravity - with the google image here...
enter image description here
Now what I really don't understand is the acceleration formula :
acceleration = 2f * (- z - velocityZ * duration) / (duration * duration);
Does this look familiar to anyone? or can you figure out the maths behind it? I basically was hoping someone could explain this to me. I would also say that I don't fully understand the gravity formula use in this code, it looks like acceleration is being used in place of gravity.
Thanks for your time, guys!

2d physics ball bouncing and rolling on incline response

I asked this question before but it got closed because it said I was asking for recommendations which isn't allowed.
Really I'm just looking for a solution whether it's from a book,website or someone who knows how to do this.
I progressed somewhat since I asked the question the last time, but anyways:
So far I've got a program where you can spawn balls which can collide with other balls and bounce off the window boundaries just fine, you can also draw a linestrip (am using sfml as I'm just a beginner and it requires very little setting up before you can get going with coding), so you hold down the mouse and every however many pixels it'll set the line you're currently drawing and start a new one at the end, so I can either do straight edges or change the setting to make a new line every pixel and make very ugly curves with the mouse (need to figure out how to do splines).
It makes no difference for the collision as it finds the closest point on the line every frame.
So dropping the ball onto the incline is fine, it bounces off like it should, or even several times,
but getting it to roll is a different story, even if you start the ball on the incline with 0 velocity as soon as it starts colliding it gets sent up off the incline instead of moving along it, and starts doing tiny bounces.
The only solution I found, which is terrible, is to time each bounce (or height of bounce I guess) and when its low enough to stop it bouncing and only have gravity act on it.
I'd be happy with it except what happens is it will bounce lower and lower until it reaches the
threshold, at which point it visibly slows down before it starts accelerating again rolling down the incline, which looks really bad, like it comes to a halt and starts getting pulled along.
Ideally I'd like it to actually simulate the physical forces rather than having to resort to tricks like timing the bounces.
While I was writing this I put in some code to work out what the angle is that the ball hits the incline at and I think the problem lies there, it's fine if it hits it from free fall but when rolling the angle shows as about 67-72 degrees when it should be..0 i guess?
Any help appreciated.
Here's the code for the collision.
void Particle::collideRamp(sf::Vector2f cp,sf::Vector2f l1,sf::Vector2f l2) {
//distance between ball and closest point on line
float dx = x - cp.x;
float dy = y - cp.y;
float distance = hypot(dx, dy);
//find line normal
float lx = l2.x - l1.x;
float ly = l2.y - l1.y;
sf::Vector2f LineNormal = normalize(ly, -lx);
//make velocity and projection same length so can mirror velocity against normal
sf::Vector2f normalMag(velocity.x * LineNormal.x,velocity.y * LineNormal.y);
sf::Vector2f Projection = LineNormal * hypotf(normalMag.x, normalMag.y);
sf::Vector2f vel = normalize(velocity.x, velocity.y) * hypotf(normalMag.x, normalMag.y);
//working on making circles rotate but early days
float rsx = prevx - x;
float rsy = prevy - y;
float rSpeed = hypot(rsx, rsy) / circumference;
//work out gravity forces for the incline, sin#mg down incline etc.
sf::Vector2f gravPerpendicular = normalize(-ly, lx);
sf::Vector2f gravParallell = normalize(lx, ly);
float gravPerMag;
float gravParMag;
gravParMag = sin(M_halfPI + atan2f(gravParallell.x,gravParallell.y));
gravPerMag = cos(M_halfPI + atan2f(gravParallell.x,gravParallell.y));
//// Collision detected.
if (distance < (radius)) {
//work out angle the ball struck the incline
float iAngle = atan2f(lx, ly) + atan2f(velocity.x, velocity.y);
//cout << iAngle * 180 / M_PI << " aft " << endl;
//make sure its 0-90
if (iAngle > 1.5708)
iAngle = 1.5708 - (iAngle - 1.5708);
//move the ball back if it went past the line by the amount it passed it by
sf::Vector2f v = normalize(velocity.x + forceAcc.x, velocity.y + forceAcc.y);
float overlap = (radius - distance );
x -= v.x * overlap;
y -= v.y * overlap;
rotationSpeed = rSpeed;
//messing with changing the angle only if bounce is a certain height as this is what's causing the
//problem i think, however the ball slows down before it starts rolling making it look weird
if (collClock.getElapsedTime().asSeconds() > 0.01) {
sf::Vector2f newVel = ((velocity + Projection) + Projection);
forceAcc = newVel;
float e = elasticity * elasticity;
forceAcc *= e;
velocity = sf::Vector2f(0, 0);
}
//add gravity forces, since the force that goes along the line normal is cancelled out
//by an equal force from the line I guess it doesn't need to be added?
//accelerateI(sf::Vector2f(-sin(gravPerpendicular) * gravPerMag * gravity * mass, cos(gravPerpendicular) * gravPerMag * gravity * mass));
//accelerate(sf::Vector2f(sin(gravPerpendicular) * gravPerMag * gravity * mass, -cos(gravPerpendicular) * gravPerMag * gravity * mass));
//this one rolls it down the incline
accelerateI(sf::Vector2f(gravParallell.x * gravParMag * gravity * mass, gravParallell.y * gravParMag * gravity * mass ));
//trying wether subtracting gravity helps
//accelerateI(sf::Vector2f(0, -1 * gravity * mass));
//friction
//accelerateI(sf::Vector2f(gravParallell.x * forceAcc.x * friction * mass, gravParallell.y * forceAcc.y * friction * mass));
collClock.restart();
}
}
Thanks guys

When rotating 2D sprite towards cursor via angularVelocity, it spins at one point

Intro
I've created a spaceship sprite in my Unity project, I wanted it to rotate towards the cursor via angular velocity, because I'd like make my game to be heavily physics based.
Problem
Now my problem with rotating the sprite via by angular velocity is the following:
At -180° / 180° rotation my ship spins around, because while my mouse's angle is already 180°, while my ship's rotation is still -180°, or the other way around.
I tried
I tried to solve it mathematically, wasn't too successful, I could make it spin the right way just much slower/faster, I could fix the 180/-180 point, but made two different ones instead.
Looked for different solutions, but couldn't find a more fitting one.
Code
So I have this code for the rotation:
// Use this for initialization
void Start () {
rb = gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
//getting mouse position in world units
mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
//getting the angle of the ship -> cursor vector
angle = Mathf.Atan2(mousePos.y - transform.position.y, mousePos.x - transform.position.x) * Mathf.Rad2Deg;
//getting the angle between the ship -> cursor and the rigidbody.rotation vector
diffAngle = angle - (rb.rotation + 90);
//Increasing angular velocity scaling with the diffAngle
rb.angularVelocity = diffAngle * Time.deltaTime * PlayerShipStats.Instance.speed * 100f;
Thank you for your contribution in advance
Solution for Problem 1
Inserting this code made it work, not for long :
if(diffAngle > 180) {
diffAngle -= 360;
} else if (diffAngle < -180) {
diffAngle += 360;
}
Problem 2 and Solution for Problem 2
The new problem is:
rigidbody.rotation can exceed it's boundaries, it can be rotated for more than 360 degrees.
this code patched this bug:
if(rb.rotation + 90 >= 180) {
rb.rotation = -270;
} else if (rb.rotation + 90 <= -180) {
rb.rotation = 90;
}
The perfect code
void AimAtTarget(Vector2 target, float aimSpeed) {
//getting the angle of the this -> target vector
float targetAngle = Mathf.Atan2(target.y - transform.position.y, target.x - transform.position.x) * Mathf.Rad2Deg;
if (rb.rotation + 90 >= 180) {
rb.rotation = -270;
} else if (rb.rotation + 90 <= -180) {
rb.rotation = 90;
}
//getting the angle between the this -> target and the rigidbody.rotation vector
float diffAngle = targetAngle - (rb.rotation - 90);
if (diffAngle > 180) {
diffAngle -= 360;
} else if (diffAngle < -180) {
diffAngle += 360;
}
//Increasing angular velocity scaling with the diffAngle
rb.angularVelocity = diffAngle * Time.deltaTime * aimSpeed * 100;
}
There are two problems I see here:
Problem 1
angle is always going to be between -180 and 180, while rb.rotation is between 0 and 360. So you are comparing angles using two different notations. The first step is to get both angles returning -180 to 180 or 0 to 360. I chose to do the following which puts both angles between -180 and 180:
//getting the angle of the ship -> cursor vector
float targetAngle = Mathf.Atan2(
mousePos.y - transform.position.y,
mousePos.x - transform.position.x) * Mathf.Rad2Deg;
//get the current angle of the ship
float sourceAngle = Mathf.Atan2(
this.transform.up.y,
this.transform.up.x) * Mathf.Rad2Deg;
Problem 2
If you fix problem 1 and tried your app you would notice that the ship sometimes rotates the wrong way, although it will eventually get to its target. The problem is that diffAngle can sometimes give a result that is greater than +180 degrees (or less than -180). When this happens we actually want the ship to rotate the other direction. That code looks like this:
//getting the angle between the ship -> cursor and the rigidbody.rotation vector
float diffAngle = targetAngle - sourceAngle;
//use the smaller of the two angles to ensure we always turn the correct way
if (Mathf.Abs(diffAngle) > 180f)
{
diffAngle = sourceAngle - targetAngle;
}
I made a simple Unity to verify this works. I was able to rotate my ship in either direction smoothly.
One thing you may have to handle, if you don't already, is appropriately stopping the rotation of the ship when the it is facing the cursor. In my test I noticed that the ship would jitter slightly when it reached its target because it would (very) slightly overshoot the cursor's angle in one direction and then the other. The larger the value of PlayerShipStats.Instance.speed the more pronounced this effect will likely be.

Find lead to hit a moving target considering gravity in 3D

I'm trying to find a point in 3D space at which I'd have to aim in order to hit a moving target with a projectile which is affected by gravity.
To give you a better picture: imagine an anti-aircraft gun trying to hit an aircraft flying above.
We can assume that the target and the projectile move at a constant rate, other than gravity in the case of the projectile. We can also assume that the shooter is stationary, since if he's not we can just use relative speeds.
After some research I found this article.
I was able to implement his first solution, since he was so kind to give a code example. That looks like this:
public static Vector3 CalculateLead(Vector3 targetVelocity, Vector3 targetPosition, Vector3 gunPosition, float projectileSpeed)
{
Vector3 direction = targetPosition - gunPosition;
float a = targetVelocity.sqrMagnitude - projectileSpeed * projectileSpeed;
float b = 2 * Vector3.Dot(direction, targetVelocity);
float c = direction.sqrMagnitude;
if (a >= 0)
return targetPosition;
else
{
float rt = Mathf.Sqrt(b * b - 4 * a * c);
float dt1 = (-b + rt) / (2 * a);
float dt2 = (-b - rt) / (2 * a);
float dt = (dt1 > 0 ? dt1 : dt2);
return targetPosition + targetVelocity * dt;
}
}
With this code I'm able to perfectly hit the target, as long as the projectile isn't affected by gravity. However, I'd like it to be. Unfortunately I'm not even remotely close to understanding the math posted in the article so I wasn't able to translate it into working code. And after spending several hours trying to find a solution which includes gravity I figured I'd just ask you guys for help.

Resources