mixster
2009-10-07 02:17:32
R0b0t1 prompted me and I delivered:
I have somewhat badly named variables where by I use force when it should be acceleration etc. but it seems to produce reliable and accurate results. The only known problem is that high resistance may lead to unnatural results as it relies on the projectile always moving forwards. Also, a near horizontal arc may cause a maths error if Scar rounds the gradient to 0, but I have been unable to reproduce myself.
Enjoy~
const
init_force = 50; // Initial acceleration - ms^-2 (same as force in newtons assuming 1 kg projectile)
init_angle = 40; // Initial angle in degrees, with horizontal being 0 and vertical being 90
grav = 9.81; // Gravity, x ms^-2
wind = 5; // Wind, x ms^-2 - positive increases distance and vice versa
res = 5; // Resistance, x ms^-2
fps = 64.0;
var
m, r_for, x_for, y_for, cur_ang, x_pos, y_pos: Extended; // resultant force; x and y components of resultant force; current angle of projectile
i: Integer; // Timer
arc: TPointArray;
tb: TBox;
begin
r_for := init_force;
x_pos := 0;
y_pos := 0;
cur_ang := Radians(init_angle);
i := 0;
repeat
SetLength(arc, i + 1);
arc[i] := Point(Round(x_pos), Round(y_pos));
r_for := r_for - (res / fps);
x_for := (r_for * Cos(cur_ang)) - (wind / fps);
y_for := (r_for * Sin(cur_ang)) - (grav / fps);
cur_ang := ArcTan(y_for / x_for);
r_for := x_for / Cos(cur_ang);
x_pos := x_pos + (x_for / fps);
y_pos := y_pos + (y_for / fps);
i := i + 1;
until y_pos <= 0;
Writeln('Flight took ~' + IntToStr(Round(i / fps)) + 's');
SetLength(arc, i + 1);
arc[i] := Point(Round(x_pos), Round(y_pos));
if arc[i].y <> 0 then
begin
if arc[i].x = arc[i - 1].x then
arc[i].y := 0
else
begin
m := (arc[i].y - arc[i - 1].y) / (arc[i].x - arc[i - 1].x);
arc[i].x := arc[i - 1].x + Round(arc[i - 1].y / -m);
arc[i].y := 0;
end;
end;
tb := GetTPABounds(arc);
tb.y2 := tb.y2 + 5;
tb.x2 := tb.x2 + 2;
DisplayDebugImgWindow(tb.x2 + 2, tb.y2 + 5);
Wait(50);
GetDebugCanvas.Brush.Color := clWhite;
GetDebugCanvas.Rectangle(0, 0, tb.x2 + 2, tb.y2 + 5);
GetDebugCanvas.MoveTo(2, tb.y2);
GetDebugCanvas.Pen.Color := clBlack;
for i := 0 to High(arc) do
GetDebugCanvas.LineTo(arc[i].x, tb.y2 - arc[i].y);
end.I have somewhat badly named variables where by I use force when it should be acceleration etc. but it seems to produce reliable and accurate results. The only known problem is that high resistance may lead to unnatural results as it relies on the projectile always moving forwards. Also, a near horizontal arc may cause a maths error if Scar rounds the gradient to 0, but I have been unable to reproduce myself.
Enjoy~