2d parabolic projectile - javascript

I'm looking to create a basic Javascript implementation of a projectile that follows a parabolic arc (or something close to one) to arrive at a specific point. I'm not particularly well versed when it comes to complex mathematics and have spent days reading material on the problem. Unfortunately, seeing mathematical solutions is fairly useless to me. I'm ideally looking for pseudo code (or even existing example code) to try to get my head around it. Everything I find seems to only offer partial solutions to the problem.
In practical terms, I'm looking to simulate the flight of an arrow from one location (the location of the bow) to another. I have already simulated the effects of gravity on my projectile by updating its velocity at each logic interval. What I'm now looking to figure out is exactly how I figure out the correct trajectory/angle to fire my arrow at in order to reach my target in the shortest time possible.
Any help would be greatly appreciated.

Pointy's answer is a good summary of how to simulate the movement of an object given an initial trajectory (where a trajectory is considered to be a direction, and a speed, or in combination a vector).
However you've said in the question (if I've read you correctly) that you want to determine the initial trajectory knowing only the point of origin O and the intended point of target P.
The bad news is that in practise for any particular P there's an infinite number of parabolic trajectories that will get you there from O. The angle and speed are interdependent.
If we translate everything so that O is at the origin (i.e. [0, 0]) then:
T_x = P_x - O_x // the X distance to travel
T_y = P_y - O_y // the Y distance to travel
s_x = speed * cos(angle) // the X speed
s_y = speed * sin(angle) // the Y speed
Then the position (x, y) at any point in time (t) is:
x = s_x * t
y = s_y * t - 0.5 * g * (t ^ 2)
so at impact you've got
T_x = s_x * t
T_y = -0.5 * g * (t ^ 2) + s_y * t
but you have three unknowns (t, s_x and s_y) and two simultaneous equations. If you fix one of those, that should be sufficient to solve the equations.
FWIW, fixing s_x or s_y is equivalent to fixing either speed or angle, that bit is just simple trigonometry.
Some combinations are of course impossible - if the speed is too low or the angle too high the projectile will hit the ground before reaching the target.
NB: this assumes that position is evaluated continuously. It doesn't quite match what happens when time passes in discrete increments, per Pointy's answer and your own description of how you're simulating motion. If you recalculate the position sufficiently frequently (i.e. 10s of times per second) it should be sufficiently accurate, though.

I'm not a physicist so all I can do is tell you an approach based on really simple process.
Your "arrow" has an "x" and "y" coordinate, and "vx" and "vy" velocities. The initial position of the arrow is the initial "x" and "y". The initial "vx" is the horizontal speed of the arrow, and the initial "vy" is the vertical speed (well velocity really but those are just words). The values of those two, conceptually, depend on the angle your bowman will use when shooting the arrow off.
You're going to be simulating the progression of time with discrete computations at discrete time intervals. You don't have to worry about the equations for "smooth" trajectory arcs. Thus, you'll run a timer and compute updated positions every 100 milliseconds (or whatever interval you want).
At each time interval, you're going to add "vx" to "x" and "vy" to "y". (Thus, note that the initial choice of "vx" and "vy" is bound up with your choice of time interval.) You'll also update "vx" and "vy" to reflect the effect of gravity and (if you feel like it) wind. If "vx" doesn't change, you're basically simulating shooting an arrow on the moon :-) But "vy" will change because of gravity. That change should be a constant amount subtracted on each time interval. Call that "delta vy", and you'll have to tinker with things to get the values right based on the effect you want. (Math-wise, "vy" is like the "y" component of the first derivative, and the "delta vy" value is the second derivative.)
Because you're adding a small amount to "vy" every time, the incremental change will add up, correctly simulating "gravity's rainbow" as your arrow moves across the screen.
Now a nuance you'll need to work out is the sign of "vy". The initial sign of "vy" should be the opposite of "delta vy". Which should be positive and which should be negative depends on how the coordinate grid relates to the screen.
edit — See #Alnitak's answer for something actually germane to your question.

Related

Phaser calculate needed y velocity for given y point

In my mobile game, the main character needs to jump to a specific y point before starting to fall down again due to gravity. How could I calculate the y velocity I would need to reach (at peak) a given y position with a given gravity?
I tried to do this with a tween instead of arcade physics because it was exactly what I needed (distance traveled over time with a gravity-like effect), but the performance was not good and was constantly sputtering.
I'm currently using Phaser 2.6.2. Thanks!
There are 2 kinds of time in games, cycle based time and deltaTime.
In a cycle based scenario, the physics don't shift to account for lag so the best solution is this:
You start off with number sequence where you compound gravity with the previous number in the sequence until your sum total equals your desired height.
For an example, I will use height = 75, gravity = 5, and jumpForce=unknown
(5+10+15+20+25)=75
The jump force you need to reach this height will be the last number in the sequence which is "25".
In a deltaTime Scenario (as used in this case), the physics are abstracted to try to adjust to time.
So, if you have 5fps, you'll have 5 cycles/second. if you have 20 fps, you'll have 20 cycles per second; so, this abstraction makes the above irrelevant.
Instead use the standard gravity formula of height = velocity^2 / (2 * gravity)., because this will better model to the formulas used by delta time engines.

Acceleration over time

Scenario
I am working on a top-down view game in which enemies move towards certain positions. The destination being moved towards will often change drastically - sometimes while the enemy is still in motion towards the previous destination...
I want to achieve movement which is more realistic than linear movement, so there should be some acceleration and deceleration as enemies switch between the destinations.
Steering (direction) is not a factor. You may assume the sprites will move much like a hovercraft, drifting between the destinations as quickly as it can manage with respect to acceleration and deceleration.
For simplicity - lets assume there is only 1 dimension (Y) instead of X and Y... the movement should emulate a car which can only move north or south.
Since we are considering realistic movement in this scenario, you might not be surprised that a maximum speed over time is also a consideration. The enemy should never exceed it's own maximum speed; enemies store their own maximum speed in a variable.
One final consideration is that enemies will not only have a 'maximum speed' value, but it will also have a 'maximum acceleration' value - this would be the thing which guides how quickly each enemy can respond to moving in the opposite direction.
For simplicity, assume that the enemy does not have any movement friction... when it stops accelerating, it just keeps cruising at the current velocity forever.
Example
For context, lets elaborate on the car example. A particular car has:
Maximum speed: 10 meters per second
Maximum acceleration: can reach top speed in 2 seconds
(Other factors like destination y-pos, position y-pos, current velocity, etc)
Just like when I'm driving a car, I imagine all of these values are present, but I can't change them. All I can really change is how much I'm putting my foot on the acceleration/brake. Let's call this the 'throttle'. Like the acceleration pedal in a car, I can change this value to any amount at any time, in no time at all.
I can plant my foot down (throttle=1), let go of the pedal immediately (throttle=0), and even change into reverse and plant my foot down again (throttle=-1). Lets assume these changes in throttle are INSTANT (unlike speed or acceleration, which grow/shrink over TIME)
All that said, I imagine the only value that I really need to calculate is what the throttle should be, since thats the only thing I can control in the vehicle.
So, how then do I know how much throttle to use at any given moment, to arrive as quickly as possible to a destination (like some traffic lights) without overshooting my destination? I will need to know how much to push down the accelerator, briefly not accelerate at all, and then how hard decelerate as I'm closing in on the destination.
Preempted movement
This game will likely have an online component. That said, players will be transmitting their positions over a socket connection... however even the best connection could never achieve sending positions frequently enough to achieve smooth movement - you need interpolation. You need to send the 'velocity' (speed) along with the co-ordinates so that I can assume future positions in the time between packets being received.
For that reason, Tweens are a no-go. There would be no way to send a tween, then accurately inform the other parties at what point along each tween each entity currently is (I mean, I guess it is possible, but horrendously overcomplicated and probably involves rather large packet sends, and is probably also very exploitable in terms of the online component), then you need to consider aborting Tweens as the destinations change, etc.
Don't get me wrong, I could probably already model some very realistic movement with the ease-in/ease-out functionality of Tweens, and it would look great, but in an online setting that would be.. very messy.
How's it look so far?
So, essentially I have established that the primary aspect which needs to be calculated at any time is how much throttle to use. Let's work through my logic...
Imagine a very basic, linear movement over time formula... it would look like this:
Example 1 - position over time
currentDY = 5; // Current 'velocity' (also called Delta Y or 'DY')
currentY += currentDY * time // Current Y pos is increased by movement speed over time.
As you can see, at any given moment, the Y position increases over time due to the 'velocity' or DY (over time). Time is only a factor ONCE, so once we reach the destination we just set the DY to zero. Very sharp unrealistic movement. To smoothen the movement, the velocity ALSO needs to change over time...
Example 2 - velocity over time
throttle = -1
currentDY += throttle * time;
currentY += (currentDY * time);
//Throttle being -1 eventually decelerates the DY over time...
Here, the throttle is '-1' (maximum reverse!), so over time this will reduce the velocity. This works great for realistic acceleration, but provides no realistic anticipation or deceleration.
If we reach the destination this time, we can set the throttle to '0'... but it's too late to brake, so the resulting enemy will just keep moving past the target forever. We could throttle = '1' to go back, but we'll end up swinging back and forth forever.
(Also note that the maximum acceleration and speed isn't even a factor yet - it definately needs to be! The enemy cannot keep ramping up their speed forever; velocity delta AND ALSO acceleration delta need to have limits).
All that said, it's not enough to simply change velocity over time, but we also need be able to anticipate how much to decelerate (i.e. 'backwards throttle') BEFORE IT HAPPENS. Here's what I've got so far, and I'm practically certain this is the wrong approach...
Example 3 - throttle over time?? (I'm stuck)
guideY = currentY + (currentDY * (timeScale * 3000));
dist = endY - guideY;
throttle = Math.max(-1, Math.min(1, dist / 200));
currentDY += throttle * time;
currentY += (currentDY * time);
As you can see, this time we attempt to anticipate how much throttle to use by guessing where the enemies position will be in an arbitrary time in the future (i.e. 3 seconds). If the guideY went past the destination, we know that we have to start BRAKING (i.e. reducing speed to stop on top of the destination). By how much - depends on how far away the enemies future position is (i.e. throttle = dist / 200;)
Here's is where I gave up. Testing this code and changing the values to see if they scale properly, the enemy always swings way over the destination, or takes far too long to 'close in' on the destination.
I feel like this is the wrong approach, and I need something more accurate. It feels like I need an intersection to correctly anticipate future positions.
Am I simply using the wrong values for the 3 seconds and dist / 200, or am I not implementing a fully working solution here?
Presently, compared to the linear movement, it always seems to take 8 times longer to arrive at the target position. I haven't even reached the point of implementing maximum values for DeltaVelocity or DeltaAcceleration yet - the accepted solution MUST consider these values despite not being present in my JSFiddle below...
Test my logic
I've put all my examples in a working JSFiddle.
JSFiddle working testbed
(Click the 'ms' buttons below the canvas to simulate the passing of time. Click a button then press+hold Return for very fast repetition)
The sprite is initially moving in the 'wrong' direction - this is intended for testing robustness - It assumes an imaginary scenario where we just finished moving as fast as possible toward an old destination far lower on the screen, and now we need to suddenly start moving up...
As you can see, my third example (see the update function), the time for the sprite to 'settle' at the desired location takes far longer than it should. My math is wrong. I can't get my head around what is needed here.
What should the throttle be at any given time? Is using throttle even a correct approach? Your assistance is very appreciated.
Tiebreaker
Alright, I've been stuck on this for days. This question is going up for some phat bounty.
If a tiebreaker is required, the winner will need to prove the math is legit enough to be tested in reverse. Here's why:
Since the game also comprises of a multiplayer component, enemies will be transmitting their positions and velocities.
As hacking protection, I will eventually need a way to remotely 'check' if the velocity and position at between any two sample times is possible
If the movement was too fast based on maximum velocity and acceleration, the account will be investigated etc. You may assume that the game will know the true maximum acceleration and velocity values of the enemies ahead of time.
So, as well as bounty, you can also take satisfaction in knowing your answer will contribute to ruining the lives of filthy video game cheaters!
Edit 2: Fiddle added by answer author; adding into his answer in case anyone else finds this question: http://jsfiddle.net/Inexorably/cstxLjqf/. Usage/math explained further below.
Edit 1: Rewritten for clarification received in comments.
You should really change your implementation style.
Lets say that we have the following variables: currentX, currentY, currentVX, currentVY, currentAX, currentAY, jerk.
currentVX is what would have been your currentDX. Likewise, currentAX is the x component of your delta velocity value (accel is derivative of velocity).
Now, following your style, we're going to have a guideX and a guideY. However, there is another problem with how you're doing this: You are finding guideY by predicting the target's position in three seconds. While this is a good idea, you're using three seconds no matter how close you are to the target (no matter how small dist is). So when the sprite is 0.5 seconds from the target, it's going to still be moving towards the target's estimated position (three seconds into the future). This means it won't actually be able to hit the target, which seems to be the problem that you implied.
Moving on, recall the previous variables that I mentioned. Those are the current variables -- ie, they will be updated at every call after some seconds have been passed (like you have been doing before). You also mentioned a desire to have maxV, and maxA.
Note that if you have a currentVX of 5 and a currentVY of 7, the velocity is (5^2+7^2)^0.5. So, what you're going to want to do each time you're updating the 'current' archetype of variables is before updating the value, see if the magnitude (so sqrt(x^2+y^2) of those variables like I showed with velocity) will exceed the respective maxV, maxA, or jmax values that you have set as constants.
I'd also like to improve how you generate your guide values. I'm going to assume that the guide can be moving. In this case, the target will have the values listed above: x, y, vx, vy, ax, ay, jx, jy. You can name these however you'd like, I'm going to use targetX, targetY... etc to better illustrate my point.
From here you should be finding your guide values. While the sprite is more than three seconds away from the target, you may use the target's position in three seconds (note: I recommend setting this as a variable so it is simple to modify). For this case:
predictionTime = 3000*timescale; //You can set this to however many seconds you want to be predicting the position from.
If you really wanted to, you could smooth the curve using integration functions or loops for the guide values to get a more accurate guide value from the target values. However, this is not a good idea because if you ever implement multiple targets / etc, it could have a negative impact on performance. Thus, we will use a very simple estimation that is pretty accurate for being such low cost.
if (sprite is more than predictionTime seconds away from the target){
guideX = targetX + predictionTime * targetVX;
guideY = targetY + predictionTime * targetVY;
}
Note that we didn't account for the acceleration and jerk of the target in this, it's not needed for such a simple approximation.
However, what if the sprite is lese than predictionTime seconds away from the target? In this case we want to start increasingly lessening our predictionTime values.
else{
guideX = targetX + remainingTime * targetVX;
guideY = targetY + remainingTime * targetVY;.
}
Here you have three choices on finding the value of remaining time. You can set remainingTime to zero, making the guide coordinates the same as the targets. You can set remainingTime to be sqrt((targetX-currentX)^2+(targetY-currentY))/(sqrt(currentVX)^2+(currentVY)^2), which is basically distance / time in 2d, a cheap and decent approximation. Or you can use for loops as mentioned before to simulate an integral to account for the changing velocity values (if they are deviating from maxV). However, generally you will be remaining at or close to maxV, so this is not really worth the expense. Edit: Also, I'd also recommend setting remainingTime to be 0 if it is less than some value (perhaps about 0.5 or so. This is because you don't want hitbox issues because your sprite is following guide coordinates that have a slight offset (as well as the target moving in circles would give it a larger velocity value while changing direction / essentially a strong evasion tactic. Maybe you should add something in specifically for that.
We now have the guideX and guideY values, and account for getting very close to a moving target having an effect on how far from the target the guide coordinates should be placed. We will now do the 'current' value archetype.
We will update the lowest derivative values first, check to see if they are within bounds of our maximum values, and then update the next lowest and etc. Note that JX and JY are as mentioned before to allow for non constant acceleration.
//You will have to choose the jerk factor -- the rate at which acceleration changes with respect to time.
//We need to figure out what direction we're going in first. Note that the arc tangent function could be atan or whatever your library uses.
dir = arctan((guideY-currentY)/(guideX-currentX));
This will return the direction as an angle, either in radians or degree depending on your trig library. This is the angle that your sprite needs to take to go in the direction of guide.
t = time; //For ease of writing.
newAX = currentAX + jerk*t*cos(dir);
newAY = currentAY + jerk*t*sin(dir);
You may be wondering how the newAx value will ever decrease. If so, note that cos(dir) will return negative if guide is to the left of the target, and likewise sin(dir) will return negative if the sprite needs to go down. Thus, also note that if the guide is directly below the sprite, then newAx will be 0 and newAY will be a negative value because it's going down, but the magnitude of acceleration, in other words what you compare to maxA, will be positive -- as even if the sprite is moving downwards, it's not moving at negative speed.
Note that because cos and sin are of the same library as atan presumably, so the units will be the same (all degrees or all radians). We have a maximum acceleration value. So, we will check to make sure we haven't exceeded that.
magnitudeA = sqrt(newAX^2+newAY^2);
if (magnitudeA > maxA){
currentAX = maxA * cos(dir);
currentAY = maxA * sin(dir);
}
So at this point, we have either capped our acceleration or have satisfactory acceleration components with a magnitude less than maxA. Let us do the same for velocity.
newVX = currentVX + currentAX*t;
newVY = currentVY + magnitudeA*t*sin(dir);
Note that I have included two ways to find the velocity components here. Either one works, I'd recommend choosing one and using it for both x and y velocity values for simplicity. I just wanted to highlight the concept of magnitude of acceleration.
magnitudeV = sqrt(newVX^2+newVY^2);
if (magnitudeV > maxV){
currentVX = maxV * cos(dir);
currentVY = maxV * sin(dir);
}
We'd also like to stop boomeranging around our target. However, we don't want to just say slow down alot like you did in your JSFiddle, because then if the target is moving it will get away (lol). Thus, I suggest checking how close you are, and if you are in a certain proximity, reduce your speed linearly with distance with an offset of the target's speed. So set closeTime to something small like 0.3 or what ever feels good in your game.
if (remainingTime < closeTime){
//We are very close to the target and will stop the boomerang effect. Note we add the target velocity so we don't stall while it's moving.
//Edit: We should have a min speed for the enemy so that it doesn't slow down too much as it gets close. Lets call this min speed, relative to the target.
currentVX = targetVX + currentVX * (closeTime - remainingTime);
currentVY = targetVY + currentVY * (closeTime - remainingTime);
if (minSpeed > sqrt(currentVX^2+currentVY^2) - sqqrt(targetVX^2-targetVY^2)){
currentVX = minSpeed * cos(dir);
currentVY = minSpeed * sin(dir);
}
}
magnitudeV = sqrt(currentVX^2+currentVY^2);
At this point we have good values for velocity too. If you going to put in a speedometer or check the speed, you're interested in magnitudeV.
Now we do the same for position. Note you should include checks that the position is good.
newX = currentX + currentVX*t;
newY = currentY + currentVY*t;
//Check if x, y values are good.
current X = newX; currentY = newY;
Now everything has been updated with the good values, and you may write to the screen.

Circle to circle collision direction. Canvas html5 [duplicate]

I am writing software that extends Circle-Rectangle collision detection (intersection) to include responses to the collision. Circle-edge and circle-rectangle are rather straight-forward. But circle-circle has me stumped.
For example, let two circles collide, one red and one green, in a discrete event simulation. We might have the following situation:
Immediately after they collide we could have:
Here RIP and GIP were the locations of the circles at the previous clock tick. At the current clock tick, the collision is detected at RDP and GDP. However, the collision occurred between clock ticks when the two circles were at RCP and GCP. At the clock tick, the red circle moves RVy downward and RVx rightward; the green circle moves GVy downward and GVx leftward. RVy does not equal GVy; nor does RVx equal GVx.
The collision occurs when the distance between the circle centers is less than or equal to the sum of the circles' radii, that is, in the preceding figure, d <= ( Rr + Gr ). At a collision where d < ( Rr + Gr ), we need to position the DPs back to the CPs before adjusting the circles' velocity components. In the case of d == ( Rr + Gr ), no repositioning is required since the DPs are at the CPs.
This then is the problem: how do I make the move back to the CPs. Some authors have suggested that one-half of the penetration, given by p in the following figure, be applied.
To me that is just plain wrong. It assumes that the velocity vectors of the two circles are equal that, in this example, is not the case. I think penetration has something to do with the computation but how eludes me. I do know that the problem can be recast as a problem of right similar triangles in which we want to solve for Gcdy and GCdx.
The collision itself will be modeled as elastic, and the math for the exchange of inertia is already in place. The only issue is where to position the circles at collision.
"This then is the problem: how do I make the move."
It is likely that you want to know how "to position the DPs back to the CPs before adjusting the circles' velocity components."
So there are two issues, how to determine the CPs (where the collision occurs) and how to adjust the circles' motion going forward from that point. The first part has a rather easy solution (allowing for different radii and velocity components), but the second part depends on whether an elastic or inelastic response is modelled. In a Comment you write:
The collision will be modeled as elastic. The math for the exchange of inertia
is already in place. The problem is where to position the circles.
Given that I'm going to address only the first issue, solving for the exact position where the collision occurs. Assuming uniform motion of both circles, it is sufficient to know the exact time at which collision occurs, i.e. when does the distance between the circles' centers equal the sum of their radii.
With uniform motion one can treat one circle (red) as motionless by subtracting its velocity from that of the other circle (green). In effect we treat the center of the first circle as fixed and consider only the second circle to be in (uniform) motion.
Now the exact time of collision is found by solving a quadratic equation. Let V = (GVx-RVx, GVy-RVy) be the relative motion of the circles, and let P = (GIPx-RIPx,GIPy-RIPy) their relative positions in the "instant" prior to collision. We "animate" a linear path for the relative position P by defining:
P(t) = P + t*V
and ask when this straight line intersects the circle around the origin of radius Rr+Gr, or when does:
(Px + t*Vx)^2 + (Py + t*Vy)^2 = (Rr + Gr)^2
This is a quadratic equation in unknown time t, all other quantities involved being known. The circumstances are such that (with collision occurring at or before position CP) a positive real solution will exist (typically two solutions, one before CP and one after, but possibly a grazing contact giving a "double root"). The solution (root) t you want is the earlier one, the one where t (which is zero at "instant" RIP,GIP positions) is smaller.
If you're looking for a basic reference on inelastic collisions for circular objects, Pool Hall Lessons: Fast, Accurate Collision Detection Between Circles or Spheres by Joe van den Heuvel and Miles Jackson is very easy to follow.
From least formal to most formal, here are some follow up references on the craft of implementing the programming that underpins the solution to your question (collision responses).
Brian Beckman & Charles Torre The Physics in Games - Real-Time Simulation Explained
Chris Hecker, Physics, Part 3: Collision Response, Game Developer 1997
David Baraff, Physically Based Modeling: Principles and Practice, Online Siggraph '97 Course notes, of particular relevance are the Slides for rigid body simulations.
You're going to have to accept some approximations - Beckman demonstrates in the video that even for very simple cases, it isn't possible to analytically predict what would occur, this is even worse because you are simulating a continuous system with discrete steps.
To re-position the two overlapping circles with constant velocities, all you need to do is find the time at which the collision occurred, and add that factor of their velocities to their positions.
First, instead of two circles moving, we will consider one circle with combined radius and relative position and velocity. Let the input circles have positions P1 and P2, velocities V1 and V2, and radii r1 and r2. Let the combined circle have position P = P2 - P1, velocity V = V2 - V1, and radius r = r1 + r2.
We have to find the time at which the circle crosses the origin, in other words find the value of t for which r = |P + tV|. There should be 0, 1, or 2 values depending on whether the circle does not pass through the origin, flies tangent to it, or flies through it.
r^2 = ||P + tV|| by squaring both sides.
r^2 = (P + tV)*(P + tV) = t^2 V*V + 2tP*V + P*P using the fact that the L2-norm is equivalent to the dot product of a vector with itself, and then distributing the dot product.
t^2 V*V + 2tP*V + P*P - r^2 = 0 turning it into a quadratic equation.
If there are no solutions, then the discriminant b^2 - 4ac will be negative. If it is zero or positive, then we are interested in the first solution so we will subtract the discriminant.
a = V*V
b = 2 P*V
c = P*P - r^2
t = (-b - sqrt(b^2 - 4ac)) / (2a)
So t is the time of the collision.
You can actually derive an expression for the time required to reach a collision, given initial positions and velocity vectors.
Call your objects A and B, and say they have position vectors a and b and velocity vectors u and v, respectively. Let's say that A moves at a rate of u units per timestep (so, at time = t, A is at a; at time = t + 1, A is at a + u).
I'm not sure whether you want to see the derivation; it wouldn't look so great... my knowledge of LaTeX is pretty limited. (If you do want me to, I could edit it in later). For now, though, here's what I've got, using generic C#-ish syntax, with a Vector2 type that is declared Vector2(X, Y) and has functions for vector addition, scalar multiplication, dot product, and length.
double timeToCollision(Vector2 a, Vector2 b, Vector2 u, Vector2 v)
{
// w is the vector connecting their centers;
// z is normal to w and equal in length.
Vector2 w = b - a;
Vector2 z = new Vector2(-1 * w.Y, w.X);
Vector2 s = u - v;
// Dot() represents the dot product.
double m = Dot(z, s) / Dot(w, s);
double t = w.Length() / Dot(w, s) *
(w.Length() - sqrt( ((2 * r) ^ 2) * (1 + m ^ 2) - (m * w.Length()) ^ 2) ) /
(1 + m * m)
return t;
}
As for responding to collisions: if you can fast-forward to the point of impact, you don't have to worry about dealing with the intersecting circles.
If you're interested, this expression gives some cool results when there won't be a collision. If the two objects are moving away from each other, but would have collided had their velocities been reversed, you'll get a negative value for t. If the objects are on paths that aren't parallel, but will never meet (passing by each other), you'll get a negative value inside the square root. Discarding the square root term, you'll get the time when they're the closest to each other. And if they're moving in parallel at the same speed, you'll get zero in the denominator and an undefined value for t.
Well, hopefully this was helpful! I happened to have the same problem as you and decided to see whether I could work it out on paper.
Edit: I should have read the previous responses more carefully before posting this... the mess of a formula above is indeed the solution to the quadratic equation that hardmath described. Apologies for the redundant post.

How to do this coordinate system operation more efficiently?

I'm making a 3D game, where the player's back should always be facing the camera and he should move in that direction. I didn't come to the "back facing the camera" part yet, but I believe that it will be simple once I figure out how to move the player in the right direction...
Though it is a 3D coordinate system, height can be ignored (z-axis) because no matter how high the camera is, the player should always be going in the same speed (the camera system is planned to function much like in the game World of Warcraft).
Now, I have summarized my problem to this...
Point (0, 0) is the players position.
Point (x, y) is the camera's position.
The camera is (dx, dy) units away from the player (and because player is at (0, 0), it is also (x, y) units away, although this is a position vector, not a translation one)
Problem: how do I get a point (a, b) in this 2D space that lies on a circle r = 1 but is on the same line as (0, 0) and (x, y)?
Visualization:
By doing this, I should have a 2D vector (a, b), which would, when multiplied by -30, act as the speed for the player.
I know how to do this, but in a very expensive and inefficient way, using the Pythagora's theorem, square roots, and all those out-of-the-question tools (working in Javascript).
Basically, something like this:
c = sqrt(dx*dx + dy*dy); //Get the length of the line
rat = 1/c; //How many times is the desired length (1) bigger than the actual length
a = x*rat;
b = y*rat;
There must be something better!
For reference, I'm making the game in Javascript, using the Three.js engine.
There is nothing to make more efficient here, these calculations are standard stuff for 3D scenes.
Don't optimize prematurely. There is no way this stuff is a bottleneck in your app.
Remember, even if these calculations happen on each render(), they still only happen once every several milliseconds - 17ms assuming 60 FPS, which is a lot. Math.sin() / Math.cos() / Math.sqrt() are plenty efficient, and lots of other calculations happen on each render() that are much more complex.
You'll be just fine with what you have now.

The closer the x/y the more x/y velocity

I am writing a fairly simple script in JavaScript using the canvas. It draws a central node which pulls all of the surrounding nodes towards it. This works great, however I need each node to repel each other.
I am going to do this by increasing each nodes velocity away from each other so eventually they should level out and end up looking something like a flower. It needs to be enough force to stop them from hitting each other or sinking into the center node without flying off into the distance.
I just can not work out how I can have a higher number the closer they get.
So if two nodes where 10px away from each other it would add 5 in force to one of their x velocities. But if they where 1000px away from each other then it would add almost nothing to the force of one of the nodes.
Does anyone know of a mathematical equation I can use to work this kind of thing out, or maybe a nudge in the right direction?
TL;DR: Depending on how close two x values are, I need to increment the x velocity of one node so they move apart but eventually level out. It is just the maths I can not crack, I have pretty much all of the JavaScript done, including the implementation of velocity.
Thanks, and sorry it is a bit wordy.
You just need an inverse (or inverse square) relationship:
var increment = k / distance;
or:
var increment = k / (distance * distance);
You can determine k based on the actual values you want, for example, in the first case, if you wanted an increment of 5 for a distance of 10, you would set k = increment * distance = 50.
Look into the equations governing electrical point charges, have the velocity be based on the "force" each "charge" would feel based on its proximity.

Categories