Created
January 3, 2019 00:14
-
-
Save makoConstruct/7ed2df66219d5c688ea9c0c3a4df41ff to your computer and use it in GitHub Desktop.
pursuit behaviour
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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