Trajectory Prediction in Sprite Kit - sprite-kit

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

Related

How to aim a projectile affected by wind for an Artificial Intelligence in 3D world?

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);

Projectile motion for box 2d body

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;
}

I have a line from the center point of a circle to another point. I want to find the point where the line intersects the circumference of the circle

I have tried several different solutions but no luck so far.
- (CGPoint)contractLineTemp:(CGPoint)point :(CGPoint)circle :(float)circleRadius {
CGFloat x,y;
x = point.x - circle.x;
y = point.y - circle.y;
CGFloat theta = atan2(x, y);
CGPoint newPoint;
newPoint.x = circle.x + circleRadius * sin(theta);
newPoint.y = circle.y + circleRadius * cos(theta);
return newPoint;
}
- (CGPoint)contractLineTemp:(CGPoint)startPoint :(CGPoint)endPoint :(float)scaleBy {
float dx = endPoint.x - startPoint.x;
float dy = endPoint.y - startPoint.y;
float scale = scaleBy * Q_rsqrt(dx * dx + dy * dy);
return CGPointMake (endPoint.x - dx * scale, endPoint.y - dy * scale);
}
Both of these solutions kind of work. If I draw the line to the center of the circle you can see that it intersects the circle exactly where it should.
http://www.freeimagehosting.net/le5pi
If I use either of the solutions above and draw to the circumference of the circle depending on the angle it is no longer going towards the center of the circle. In the second image the line should be in the middle of the right edge of the circle and going straight right.
http://www.freeimagehosting.net/53ovs
http://www.freeimagehosting.net/sb3b2
Sorry for the links. I am to new to currently post images.
Thanks for you help.
It's easier to treat this as a vector problem. Your second approach is close, but you don't correctly scale the vector between the two points. It's easier to work with a normalized vector in this case, although you have to assume that the distance between the two points on the line is non-zero.
Given:
double x0 = CIRC_X0; /* x-coord of center of circle */
double y0 = CIRC_Y0; /* y-coord of center of circle */
double x1 = LINE_X1; /* x-coord of other point on the line */
double y1 = LINE_Y1; /* y-coord of other point on the line */
Then the vector between the two points is (vx,vy):
double vx = x1 - x0;
double vy = y1 - y0;
It's easier to work with a unit vector, which we can get by normalizing (vx,vy):
double vmag = sqrt(vx*vx + vy*vy);
vx /= vmag; /* Assumption is vmag > 0 */
vy /= vmag;
Now, any point along the line can be described as:
x0 + dist * vx
y0 + dist * vy
where dist is the distance from the center. The intersection of the circle and the line must be a distance of CIRC_RADIUS from the center, so:
double x_intersect = x0 + CIRC_RADIUS * vx;
double y_intersect = y0 + CIRC_RADIUS * vy;
I think that there may be a convention conflict on what theta, x and y are. The atan2 function yields values in the range -pi..pi, by taking the convention of theta as the angle growing from the X axis towards Y. However you are considering theta as the angle from Y to X.
Try changing the code:
CGFloat theta = atan2(y, x);
CGPoint newPoint;
newPoint.x = circle.x + circleRadius * cos(theta);
newPoint.y = circle.y + circleRadius * sin(theta);
Although your formulae are consistent within a coordinate system, it may have conflict with the screen/display device coordinate system.

reaching particular co-ordinate in projectile motion?

As I wanted to animate an image in projectile motion,
My code is as follows, but it did not reach the target and give projectile animation, any help please?
-(void)timeLine
{
dTime += 0.1;
.................
double s_x = inVel * cos(angle1) ; // the X speed
double s_y = inVel * sin(angle1) ; // the Y speed
NSLog(#"sx = %i",s_x);
NSLog(#"sy = %i",s_y);
x = oX + (s_x * dTime);
y = oY + ( ( s_y * dTime) - (0.5 * 9.8 * dTime * dTime));
NSLog(#"x = %i",x);
NSLog(#"y = %i",y);
imageViewForAnimation.x += x;
imageViewForAnimation.y -= y;
}
imageViewForAnimation.x += x;
imageViewForAnimation.y -= y;
These lines don't seem right to me. You are calculating the actual x and y each time, not the difference moved since the last time. I'm also uncertain why one was being added and one was being subtracted, but that's beside the point. Basically, try changing the lines to
imageViewForAnimation.x = x;
imageViewForAnimation.y = y;
Also, you're doing some calculations over and over which only need to be done once. v_x == s_x (or it should within floating point error) as well as v_y == s_y. You only need to calculate v_x and V_y once beforehand rather than calculating them every time you update the coordinates.

Box2d Calculating Trajectory

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;
}