Skip to content

Instantly share code, notes, and snippets.

@makoConstruct
Created January 3, 2019 00:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save makoConstruct/7ed2df66219d5c688ea9c0c3a4df41ff to your computer and use it in GitHub Desktop.
Save makoConstruct/7ed2df66219d5c688ea9c0c3a4df41ff to your computer and use it in GitHub Desktop.
pursuit behaviour
float distanceToSlowDown(float initialSpeed, float deceleration){ return sq(initialSpeed)/(2*deceleration); }
float maxDistanceBeforeSlowingWithin(float initialSpeed, float time){ return initialSpeed*time/2; }
bool updateApproacher(float dif, float& currentVelocity, float deceleration, float acceleration, float delta, float error = 1){ //dif is target - position, returns true iff zeroing
float dist = abs(dif);
float sign = dif/dist;
float absvel = currentVelocity*sign;
float acd = acceleration*delta;
float avd = absvel*delta;
float ded = deceleration*delta;
if(deceleration*delta >= absvel && dist >= distanceToSlowDown(absvel, deceleration) && dist <= maxDistanceBeforeSlowingWithin(absvel, delta)){ //that is, if deceleration is strong enough to zero the velocity and if the distance it has yet to travel in the remaining frame is within the exact range afforded by the deceleration, then, zero the velocity, signal to stop
//the final immaculate step
currentVelocity = 0;
return true;
}else{
if(
error*distanceToSlowDown(absvel, deceleration) > dif //||
// currentVelocity/deceleration > endTime - currentTime - averageFrameTime /*ensure you're a frame early by slightly underestimating the amount of time you have*/
){
absvel -= ded;
}else{
absvel += acd;
}
currentVelocity = sign*absvel;
return false;
}
}
float const defaultApproachUpdateError = 1.12; //otherwise, it seems to overshoot
void approachPosition(v2& pos, v2 target, v2& velocity, float acceleration, float delta, float approachUpdateError){
v2 dif = target - pos;
float dm = dif.magnitude();
float vm = velocity.magnitude();
float ad = acceleration*delta;
if(dm != 0 || vm != 0){
v2 forwardAxis = dm == 0 ? velocity/vm : dif/dm;
float fv = forwardAxis.dot(velocity);
float rv = forwardAxis.turnCloc().dot(velocity);
if(fv < 0){ //then slow down
velocity = velocity.shortenBy(ad);
pos += velocity*delta;
}else{
if(abs(rv) > abs(fv)/10000){ //then there's a significant perp component, we will correct perp first
float rvs = fsign(rv);
if(rvs*rv < ad){
rv = 0;
float remainingDelt = delta - (rvs*rv)/ad;
updateApproacher(dm, fv, acceleration, acceleration, remainingDelt, approachUpdateError);
}else{
rv = rvs*(rvs*rv - ad);
}
velocity = forwardAxis*fv + forwardAxis.turnCloc()*rv;
pos += velocity*delta;
}else{ //accelerate straight towards center
if(updateApproacher(dm, fv, acceleration, acceleration, delta, approachUpdateError)){
velocity = (target - pos)/delta;
pos = target;
}else{
pos = target - forwardAxis*(dm - fv*delta);
velocity = forwardAxis*fv;
}
}
}
}else{
pos = target;
velocity = v2(0,0);
}
}
//you might want this too. It's for figuring out how which angle to fire at to hit a moving target. I have in the past combined this with an approacher like the above, it was a very clever boy, you could get past it, but it felt like you had to be wilier.
void targetingFormula(v2 shooter, float bulletSpeed, v2 target, v2 targetVel, double& timeOfCollision, v2& firingAngle){ //if no collision is possible for the given parameters, timeOfCollision will be INFINITY
v2 d = shooter - target;
float dm = d.magnitude();
if(dm == 0){
timeOfCollision = 0;
firingAngle = v2::both(SQRTHALF);
}else{
v2 dn = d/dm;
float nax = dn.dot(targetVel);
float nay = dn.turnCoun().dot(targetVel);
float absnay = abs(nay);
float onay = absnay/bulletSpeed;
if(onay >= 1){
timeOfCollision = INFINITY;
}else{
float bvx = -sqrt(1.0f - sq(onay));
float relxVels = nax - bvx*bulletSpeed;
if(relxVels <= 0){
timeOfCollision = INFINITY;
}else{
timeOfCollision = dm/relxVels;
firingAngle = dn.rotate(v2(bvx, nay/bulletSpeed));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment