Files
Mindustry/core/src/mindustry/entities/Predict.java
2021-07-20 17:55:00 -04:00

97 lines
3.1 KiB
Java

package mindustry.entities;
import arc.math.*;
import arc.math.geom.*;
import arc.util.*;
import mindustry.gen.*;
/**
* Class for predicting shoot angles based on velocities of targets.
*/
public class Predict{
private static final Vec2 vec = new Vec2();
private static final Vec2 vresult = new Vec2();
/**
* Calculates of intercept of a stationary and moving target. Do not call from multiple threads!
* @param srcx X of shooter
* @param srcy Y of shooter
* @param dstx X of target
* @param dsty Y of target
* @param dstvx X velocity of target (subtract shooter X velocity if needed)
* @param dstvy Y velocity of target (subtract shooter Y velocity if needed)
* @param v speed of bullet
* @return the intercept location
*/
public static Vec2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v){
dstvx /= Time.delta;
dstvy /= Time.delta;
float tx = dstx - srcx,
ty = dsty - srcy;
// Get quadratic equation components
float a = dstvx * dstvx + dstvy * dstvy - v * v;
float b = 2 * (dstvx * tx + dstvy * ty);
float c = tx * tx + ty * ty;
// Solve quadratic
Vec2 ts = quad(a, b, c);
// Find smallest positive solution
Vec2 sol = vresult.set(dstx, dsty);
if(ts != null){
float t0 = ts.x, t1 = ts.y;
float t = Math.min(t0, t1);
if(t < 0) t = Math.max(t0, t1);
if(t > 0){
sol.set(dstx + dstvx * t, dsty + dstvy * t);
}
}
return sol;
}
public static Vec2 intercept(Position src, Position dst, float v){
return intercept(src, dst, 0, 0, v);
}
public static Vec2 intercept(Position src, Position dst, float offsetx, float offsety, float v){
float ddx = 0, ddy = 0;
if(dst instanceof Hitboxc h){
ddx += h.deltaX();
ddy += h.deltaY();
}
if(src instanceof Hitboxc h){
ddx -= h.deltaX();
ddy -= h.deltaY();
}
return intercept(src.getX(), src.getY(), dst.getX() + offsetx, dst.getY() + offsety, ddx, ddy, v);
}
/**
* See {@link #intercept(float, float, float, float, float, float, float)}.
*/
public static Vec2 intercept(Hitboxc src, Hitboxc dst, float v){
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), dst.deltaX() - src.deltaX()/(2f* Time.delta), dst.deltaY() - src.deltaX()/(2f* Time.delta), v);
}
private static Vec2 quad(float a, float b, float c){
Vec2 sol = null;
if(Math.abs(a) < 1e-6){
if(Math.abs(b) < 1e-6){
sol = Math.abs(c) < 1e-6 ? vec.set(0, 0) : null;
}else{
vec.set(-c / b, -c / b);
}
}else{
float disc = b * b - 4 * a * c;
if(disc >= 0){
disc = Mathf.sqrt(disc);
a = 2 * a;
sol = vec.set((-b - disc) / a, (-b + disc) / a);
}
}
return sol;
}
}