``````{
SEAN PALMER

I've been playing around with it as a way to make 'heat-seeking
missiles' in games. Very interesting...

What I do is have the points set up as follows:

1   : current position
2&3 : current speed + the current position
4   : destination

and update current position by indexing somewhere into the curve (like
at \$100 out of \$FFFF

This works very well. Problem is that I don't know of a good way to
change the speed.

Here is a simple demo that makes a dot chase the mouse cursor (needs
VGA as written) that shows what I mean.

If ANYBODY can make this work smoother or improve on it in any way I
would appreciate being told how... 8)
}

uses
mouse, crt;  { you will need to change accesses to the mouse unit }
{ to use a mouse package that you provide }
type
coord = record
x, y : word;
end;
CurveDataRec = array [0..65521 div sizeof(coord)] of coord;

const
nSteps = 1 shl 8;  {about 8 for smoothness (dots), 4 for speed (lines)}

var
color : byte;
src, spd,
dst, mov1,
mov2 : coord;
i : integer;

procedure plot(x, y : word);
begin
mem[\$A000 : y * 320 + x] := color;
end;

function fracMul(f, f2 : word) : word;
Inline(
\$58/                   {pop ax}
\$5B/                   {pop bx}
\$F7/\$E3/               {mul bx}
\$89/\$D0);              {mov ax,dx}

function mul(f, f2 : word) : longint;
inline(
\$58/                   {pop ax}
\$5B/                   {pop bx}
\$F7/\$E3);              {mul bx}

{this is the original full BSpline routine}

procedure drawBSpline(var d0 : coord; nPoints : word);
const
nsa  = \$10000 div 6;
nsb  = \$20000 div 3;
step = \$10000 div nSteps;
var
i, xx, yy : word;
t1, t2, t3 : word;
c1, c2, c3, c4 : word;
d : curveDataRec absolute d0;
begin
t1 := 0;
color := 32 + 2;
for i := 0 to nPoints - 4 do
begin
{algorithm converted from Steve Enns' original Basic subroutine}
repeat
t2 := fracMul(t1, t1);
t3 := fracMul(t2, t1);
c1 := (integer(t2 - t1) div 2) + nsa - fracmul(nsa, t3);
c2 := (t3 shr 1) + nsb - t2;
c3 := ((t2 + t1 - t3) shr 1) + nsa;
c4 := fracmul(nsa, t3);
xx := (mul(c1, d[i].x) + mul(c2, d[i + 1].x) +
mul(c3, d[i + 2].x) + mul(c4, d[i + 3].x)) shr 16;
yy := (mul(c1, d[i].y) + mul(c2, d[i + 1].y) +
mul(c3, d[i + 2].y) + mul(c4, d[i + 3].y)) shr 16;
plot(xx, yy);
inc(t1, step);
until t1 = 0;  {this is why nSteps must be even power of 2}
inc(color);
end;
end;

{find 1/nth point in BSpline}  {this is what does the B-Spline work}

procedure moveTowards(d1, d2, d3, d4 : coord; t1 : word; var mov : coord);
const
nsa = \$10000 div 6;
nsb = \$20000 div 3;
var
t2, t3 : word;
c1, c2,
c3, c4 : word;
begin
t2 := fracMul(t1, t1);
t3 := fracMul(t2, t1);
c1 := (integer(t2 - t1) div 2) + nsa - fracmul(nsa, t3);
c2 := (t3 shr 1) + nsb - t2;
c3 := ((t2 + t1 - t3) shr 1) + nsa;
c4 := fracmul(nsa, t3);
mov.x := (mul(c1, d1.x) + mul(c2, d2.x) + mul(c3, d3.x) + mul(c4, d4.x)) shr 16;
mov.y := (mul(c1, d1.y) + mul(c2, d2.y) + mul(c3, d3.y) + mul(c4, d4.y)) shr 16;
end;

begin
asm
mov ax, \$13
int \$10
end;  {init vga/mcga graphics}

{mouse.init;}
mshow;

src.x := 5;
src.y := 5;
spd.x := 5;
spd.y := 5;
dst.x := 315;
dst.y := 190;

repeat
{for i:=0 to 23 do begin}
{ color:=i+32;}
{ inc(dst.x,i);}
delay(10);
{mouse.check;}  {this loads Mouse.X, Mouse.Y, Mouse.Button from driver}
mhide;
color := 15;
plot(src.x, src.y);
color := 14;
plot(spd.x, spd.y);
dst.x := mousex shr 1;
dst.y := mousey;
color := 1;
plot(dst.x, dst.y);
mshow;

{the parameters in these next two lines can be changed}
{I have played with almost all possible combinations and}
{most work, but not well, so don't be afraid to play around}
{But I think an entirely different approach is needed for the}
{second moveTowards..}

moveTowards(src, src, spd, dst, \$0010, mov1);
moveTowards(src, spd, dst, dst, \$5000, mov2);
src := mov1;
longint(spd) := (longint(spd) * 7 + longint(mov2)) shr 3 and \$1FFF1FFF;
until 1=0;

mhide;

asm
mov ax, 3
int \$10
end; {text mode again}
end.

``````