How to implement the projectile motion for a box2d body in cocs2dx....
newX = b4->GetPosition().x + cos(60.0);
newY = b4->GetPosition().y + sin(60.0);
is this a right way?
You can do like that initial Velocity of object, angle, gravity= 9.81 and time should be start from zero.
while(count < 10)
{
// this is formula for trajectory
// http://en.wikipedia.org/wiki/Projectile_motion
x = initialVelocity * time * Math.Cos(angle);
y = initialVelocity * time * Math.Sin(angle) - 0.5f * gravity * time * time;
count++;
time += 0.1f;
}
Related
I need to shoot a ball from any height and make it bounce on a target position defined by the user. The angle of launch is also given. I've tried a couple of solutions so far:
Vector3 calcBallisticVelocityVector(Vector3 source, Vector3 target, float angle) {
Vector3 direction = target - source;
float h = direction.y;
direction.y = 0;
float distance = direction.magnitude;
float a = angle * Mathf.Deg2Rad;
direction.y = distance * Mathf.Tan(a);
distance += h/Mathf.Tan(a);
// calculate velocity
float velocity = Mathf.Sqrt(distance * Physics.gravity.magnitude / Mathf.Sin(2*a));
return velocity * direction.normalized;
}
Vector3 calcBallisticVelocityVector2(Vector3 source, Vector3 target, float angle) {
float distance = (target.Planar() - source.Planar()).magnitude;
float a = target.y - source.y - distance;
float halfGravity = -Physics.gravity.magnitude * 0.5f;
float distanceSquared = distance * distance;
float theta = Mathf.Deg2Rad * angle;
float cosSquared = Mathf.Cos(theta) * Mathf.Cos(theta);
float b = distanceSquared / cosSquared;
float speed = Mathf.Sqrt((halfGravity * b) / a);
Vector3 velocity = (target.Planar() - source.Planar()).normalized * Mathf.Cos(theta);
velocity.y = Mathf.Sin(theta);
return velocity * speed;
}
The results I'm getting is that even the ball does go into the direction is expected, it falls earlier than it should be so the speed calculated by these methods seems to be lower than what is actually required to hit the target position.
Rigidbody's mass is set to 1, Gravity is (0, -98, 0), rigid body's drag and angular drag is set to 0. What other variables could be affecting this behavior?
EDIT: One thing I forgot to mention is that I'm setting the resulting vector as rigid body's velocity, so I'm not using via the apply force method.
I adapted code gotten from here: https://answers.unity.com/questions/1131176/projectile-motion.html and now I'm getting the results I was expecting. I can always hit the target position at whatever angle I input.
private Vector3 calcBallisticVelocityVector(Vector3 initialPos, Vector3 finalPos, float angle)
{
var toPos = initialPos - finalPos;
var h = toPos.y;
toPos.y = 0;
var r = toPos.magnitude;
var g = -Physics.gravity.y;
var a = Mathf.Deg2Rad * angle;
var vI = Mathf.Sqrt (((Mathf.Pow (r, 2f) * g)) / (r * Mathf.Sin (2f * a) + 2f * h * Mathf.Pow (Mathf.Cos (a), 2f)));
Vector3 velocity = (finalPos.Planar() - initialPos.Planar()).normalized * Mathf.Cos(a);
velocity.y = Mathf.Sin(a);
return velocity * vI;
}
I am suppose to implement a CatMull Rom Spline, and I have it implemented, but the sphere moves to the points extremely fast. I thought if I used Time.DeltaTime it would slow it down, but it moves too rapidly.
Function to compute point on curve:
Vector3 ComputePointOnCatmullRomCurve(float u, int segmentNumber)
{
// TODO - compute and return a point as a Vector3
// Points on segment number 0 start at controlPoints[0] and end at controlPoints[1]
// Points on segment number 1 start at controlPoints[1] and end at controlPoints[2]
// etc...
Vector3 point = new Vector3();
float c0 = ((-u + 2f) * u - 1f) * u * 0.5f;
float c1 = (((3f * u - 5f) * u) * u + 2f) * 0.5f;
float c2 = ((-3f * u + 4f) * u + 1f) * u * 0.5f;
float c3 = ((u - 1f) * u * u) * 0.5f;
Vector3 p0 = controlPoints[(segmentNumber - 1) % NumberOfPoints];
Vector3 p1 = controlPoints[segmentNumber % NumberOfPoints];
Vector3 p2 = controlPoints[(segmentNumber + 1) % NumberOfPoints];
Vector3 p3 = controlPoints[(segmentNumber + 2) % NumberOfPoints];
point.x = (p0.x * c0) + (p1.x * c1) + (p2.x * c2) + (p3.x * c3);
point.y = (p0.y * c0) + (p1.y * c1) + (p2.y * c2) + (p3.y * c3);
point.x = (p0.z * c0) + (p1.z * c1) + (p2.z * c2) + (p3.z * c3);
return point;
}
**Update Function: **
void Update ()
{
// TODO - use time to determine values for u and segment_number in this function call
// 0.5 Can be used as u
time += DT;
segCounter++;
Vector3 temp = ComputePointOnCatmullRomCurve(time, segCounter);
transform.position = temp;
}
Variables:
const int NumberOfPoints = 8;
Vector3[] controlPoints;
const int MinX = -5;
const int MinY = -5;
const int MinZ = 0;
const int MaxX = 5;
const int MaxY = 5;
const int MaxZ = 5;
float time = 0;
const float DT = 0.01f;
public static int segCounter = 0;
EDIT: Sorry the calculations, and all of that is correct. It's straight from the slides, I just need help with the update function :(
Using Time.deltaTime allows you to be framerate independent. This means that if the framerate drops, or a frame takes longer than the others, your object will adapt the moving distance to keep a constant speed. This is generally a good idea.
Back to your case: Basically you want to pass a position to your function. You currently pass the time. If your catmull rom considers that 0 is the start and 1 is the destination, then after exactly 1 second, you will be at the end of the spline. (Note that this is where being framerate independent is interesting: Whatever the frame rate is. you reach the end in one second). Now, how to convert from time to position. Easy
position = time*speed;
Since time is in second, speed is in units per seconds. Say your catmullrom is one unit long. If speed is two, if will take one second to travel it twice. so half a second to travel it. Since you want to lower the speed, you might want to use values below 1. Try this:
void Update ()
{
time += Time.deltaTime;
var speed = 0.1f;
var splinePos = speed * time;
segCounter++;
Vector3 temp = ComputePointOnCatmullRomCurve(splinePos, segCounter);
transform.position = temp;
}
I'm trying to make a tank game where the player must destroy the enemy tank piloted by AI. As AI has to be able to attack the player's tank. Both shots are parabolic affected by air. So far I have been able to calculate the power and minimum tilt angle to hit the shot without the projectile is affected by the wind.
var Dx = target.position.x - transform.position.x;
var Dy = target.position.y - transform.position.y;
var P1 = Mathf.Sqrt(9.81f * (Dy + Mathf.Sqrt(Dx * Dx + Dy * Dy)));
var InclinationAngle = Mathf.Atan((Dy + Mathf.Sqrt(Dx * Dx + Dy * Dy)) / Dx) * Mathf.Rad2Deg;
transform.localRotation = Quaternion.Euler(new Vector3(-InclinationAngle,0, 0));
var fz = transform.forward.normalized * P1;
rig.AddForce(fz, ForceMode.Impulse);
The problem is when the projectile is affected by wind. The wind can be in one of four directions, forward, back, right or left. I have tried several approaches, but I have not got a good shot. How can the AI aim considering the starting position, target position and the strength and direction of the wind?
I found a solution:
Once calculated the initial rate and the minimum angle of inclination to make the trip
var Dx = target.position.x - transform.position.x;
var Dy = target.position.y - transform.position.y;
var Vmin = Mathf.Sqrt(9.81f * (Dy + Mathf.Sqrt(Dx * Dx + Dy * Dy)));
var InclinationAngle = Mathf.Atan((Dy + Mathf.Sqrt(Dx * Dx + Dy * Dy)) / Dx) * Mathf.Rad2Deg;
must be added opposite to the wind force by the time of flight of the projectile divided by 2 because wee just need the half of the time because there is where the two forces are equals.
var t = Dx/(Vmin * Mathf.Cos(InclinationAngle*Mathf.Deg2Rad));
var fyx = transform.forward.normalized * P1;
var fxz = wind.force*-t/2;
rig.AddForce((fyx+fxz), ForceMode.Impulse);
I'm trying to predict where an object (ball) will move using the following formula
Calculations for t = 1 second
y = VelocityY * t + 0.5*Gravity*t2
x = VelocityX * t
code below:
+(CGVector) getTrajectoryPointWithInitialPosition:(CGVector) initialPosition andInitialVelocity:(CGVector) initialVelocity andSteps: (CGFloat)n andSceneLayer: (SKScene*) sceneLayer
{
// Put data into correct units
CGFloat t = 1.0 / 60.0;
// m/s
CGVector stepVelocity = CGVectorMake(t * initialVelocity.dx, t * initialVelocity.dy);
// m/s^2
CGVector stepGravity = CGVectorMake(t * t * sceneLayer.physicsWorld.gravity.dx, t * t * sceneLayer.physicsWorld.gravity.dy);
initialPosition = CGVectorMake(initialPosition.dx + n * stepVelocity.dx,
initialPosition.dy + n * stepVelocity.dy + 0.5 * (n*n+n) * stepGravity.dy);
return CGVectorMake(initialPosition.dx + n * stepVelocity.dx,
initialPosition.dy + n * stepVelocity.dy + 0.5 * (n*n) * stepGravity.dy);
}
I then launch the ball (stationary/non-dynamic) using the following
CGVector aVelocity = CGVectorMake(initialVelocity.dx*17.5, initialVelocity.dy*17.5);
[ball.physicsBody setVelocity:aVelocity];
What I can't figure out is:
initialVelocity for the ball and the trajectory prediction is the same. If it's the same, why does multiplying initialVelocity for the ball by 17.5 gets the ball movement and the predicted trajectory obtained from above to match up. It looks like it's following the predicted path but I don't understand why multiplying the balls velocity by 17.5 makes the ball
![Before multiplying by 17.5] http://i.imgur.com/bKkPGmh.png - Before multiplying by 17.5
![After multiplying velocity by 17.5] http://i.imgur.com/Ae7sY4i.png - After multiplying by 17.5
I'm trying to make physics bodies generated at a random position with a random velocity hit a target. I gleaned and slightly modified this code from the web that was using chipmunk to run in Box2d
+ (CGPoint) calculateShotForTarget:(CGPoint)target from:(CGPoint) launchPos with:(float) velocity
{
float xp = target.x - launchPos.x;
float y = target.y - launchPos.y;
float g = 20;
float v = velocity;
float angle1, angle2;
float tmp = pow(v, 4) - g * (g * pow(xp, 2) + 2 * y * pow(v, 2));
if(tmp < 0){
NSLog(#"No Firing Solution");
}else{
angle1 = atan2(pow(v, 2) + sqrt(tmp), g * xp);
angle2 = atan2(pow(v, 2) - sqrt(tmp), g * xp);
}
CGPoint direction = CGPointMake(cosf(angle1),sinf(angle1));
CGPoint force = CGPointMake(direction.x * v, direction.y * v);
NSLog(#"force = %#", NSStringFromCGPoint(force));
NSLog(#"direction = %#", NSStringFromCGPoint(direction));
return force;
}
The problem is I don't know how to apply this to my program, I have a gravity of -20 for y but putting 20 for g and a lower velocity like 10 for v gets me nothing but "No Firing Solution".
What am I doing wrong?
A lower velocity of 10 is never going to work the projectile doesn't have enough power to travel the distance.
The error in the calculation is that everything is in meters except for the distance calculations which are in pixels!
Changing the code to this fixed the crazy velocities i was getting:
+ (CGPoint) calculateShotForTarget:(CGPoint)target from:(CGPoint) launchPos with:(float) velocity
{
float xp = (target.x - launchPos.x) / PTM_RATIO;
float y = (target.y - launchPos.y) / PTM_RATIO;
float g = 20;
float v = velocity;
float angle1, angle2;
float tmp = pow(v, 4) - g * (g * pow(xp, 2) + 2 * y * pow(v, 2));
if(tmp < 0){
NSLog(#"No Firing Solution");
}else{
angle1 = atan2(pow(v, 2) + sqrt(tmp), g * xp);
angle2 = atan2(pow(v, 2) - sqrt(tmp), g * xp);
}
CGPoint direction = CGPointMake(cosf(angle1),sinf(angle1));
CGPoint force = CGPointMake(direction.x * v, direction.y * v);
NSLog(#"force = %#", NSStringFromCGPoint(force));
NSLog(#"direction = %#", NSStringFromCGPoint(direction));
return force;
}