unit Physics;
interface
uses
Math,
Math3D;
const
MAX_PLAYERS = 4;
AIR_R: single = 0.01;
GND_R: single = 0.1;
GRAV: single = 0.007;
MOVE_STR: single = 0.1;
JUMP_STR: single = 1.4;
type
// type action, pr interfacer les inputs
TAction = (LEFT, RIGHT, UP, DOWN, JUMP);
// objet marble
TMarble = class (TObject)
r,m: single;
P,V,Force: TCoord;
Collision: boolean;
// trucs pasbô :( gestion de la cam?
Anglex,Angley: extended;
A,Cam: TCoord;
// *shrugs*
constructor Create(x,y,z,radius,mass: single);
procedure Effect(Action: TAction); //; Angle: single);
procedure DoCollision(Marble2: TMarble; Dispatch: boolean);
procedure Update(Time: single);
end;
// file de traitement des collisions, hyper important ca ! lol
PCollisionQueue = ^TCollisionQueue;
TCollisionQueue = class (TObject)
i,j: integer;
next,prec: PCollisionQueue;
//constructor Create;
function Add(i,j: integer): PCollisionQueue;
procedure MixUp(n: integer);
end;
// tableau de billes, caicool
TMarbles = class (TObject)
Items: array[1..MAX_PLAYERS] of TMarble;
Count: integer;
CollisionQueue: PCollisionQueue;
constructor Create(n: integer);
procedure Update(Time: single);
procedure RunCollisions;
end;
function Distance(A,B: TMarble): single;
function IsCollision(A,B: TMarble): boolean;
implementation
constructor TMarble.Create(x,y,z,radius,mass: single);
begin
with Self do begin
r := radius;
m := mass;
P.x := x;
P.y := y;
P.z := z;
Collision := false;
// bah! lol
Anglex := 0;
Angley := 5.999;
end;
end;
procedure TMarble.Effect(Action: TAction); //; Angle: single);
var
F: TCoord;
Angle: single; // pasbô :(
begin
Angle := 100*Self.Anglex*180/PI; // lol
with Self do
begin
if P.z=0 then
begin
case Action of
RIGHT:
SetCoord(F,Sin(Angle)*MOVE_STR,-Cos(Angle)*MOVE_STR,0);
LEFT:
SetCoord(F,-Sin(Angle)*MOVE_STR,Cos(Angle)*MOVE_STR,0);
DOWN:
SetCoord(F,Cos(Angle)*MOVE_STR,Sin(Angle)*MOVE_STR,0);
UP:
SetCoord(F,-Cos(Angle)*MOVE_STR,-Sin(Angle)*MOVE_STR,0);
JUMP:
begin
SetCoord(F,0,0,JUMP_STR);
//PlaySample(sonjump);
end;
end;
Force := AddCoord(Force,F);
end;
end;
end;
procedure TMarble.DoCollision(Marble2: TMarble; Dispatch: boolean);
begin
//
// FIX-ME!
//
if Dispatch then Marble2.DoCollision(Self,false);
end;
procedure TMarble.Update(Time: single);
begin
with Self do
begin
Force := AddCoord(Force,ScaleCoord(ScaleCoord(Normalize(V),Sqr(Magnitude(V))),AIR_R)); // F=k.V²
Force := AddCoord(Force,ScaleCoord(V,AIR_R)); // F=k.v
Force.z := Force.z + m*GRAV; // P=m.g
V := AddCoord(V,ScaleCoord(Force,Time/m)); // v1 = v0 + F/m*t
Force := VECT_NULL;
A:=P; // encore un truc moche :(
P := AddCoord(P,ScaleCoord(V,Time)); // x1 = x0 + v*t (idem y,z)
// truc un peu moche de collision avec le sol <:]
if P.z<0 then
begin
P.z := 0;
V.z := -0.4*V.z; // rebond LOL
end;
// alors là, truc ULTRA-moche ! (gestion de la cam, rien a faire là...)
//Anglex := Anglex+degtorad(arctan(-MouseState.lX/300));
//Angley := Angley+degtorad(arctan(-mousestate.lY/300));
Cam.x := (150 * cos(Anglex*100))+P.x;
if (Angley<6) then
begin
Cam.y := (150 * sin(Angley*100))+P.z;
end;
Cam.z := (150 * sin(Anglex*100))+P.y;
// end truc ULTRA-moche
end;
end;
constructor TMarbles.Create(n: integer);
begin
with Self do
begin
Count := n;
end;
end;
procedure TMarbles.Update(Time: single);
var
i,j: integer;
begin
with Self do
begin
for i:=1 to Count do
begin
for j:=1 to Count do
begin
if IsCollision(Items[i],Items[j]) then
begin
CollisionQueue.Add(i,j);
end;
end;
end;
CollisionQueue.MixUp(0);
RunCollisions;
for i:=1 to Count do Items[i].Update(Time);
end;
end;
procedure TMarbles.RunCollisions;
var
p: PCollisionQueue;
begin
p := Self.CollisionQueue;
while p<>nil do
begin
Self.Items[p.i].DoCollision(Self.Items[p.j],true);
//PlaySample(samp);
end;
end;
{constructor TCollisionQueue.Create;
begin
with Self do
begin
i := 0;
j := 0;
next := nil;
prec := nil;
end;
end;}
function TCollisionQueue.Add(i,j: integer): PCollisionQueue;
var
p: PCollisionQueue;
found: boolean;
begin
result := @Self;
found := false;
while (result.next<>nil) and (not found) do
begin
p := result;
if ((p.i=i) and (p.j=j)) or ((p.i=j) and (p.j=i)) then found:=true;
result := p.next;
end;
if not found then
begin
New(result);
p.next := result;
result.i := i;
result.j := j;
result.next := nil;
result.prec := p;
end
else result := nil;
end;
procedure TCollisionQueue.MixUp(n: integer);
var
i: integer;
begin
for i:=1 to n do
begin
//
end;
//
end;
function Distance(A,B: TMarble): single;
begin
result := sqrt(sqr(A.P.x-B.P.x)+sqr(A.P.y-B.P.y)+sqr(A.P.z-B.P.z))-(A.r+B.r);
end;
function IsCollision(A,B: TMarble): boolean;
begin
result := Distance(A,B)<0;
end;
// (\_/)
// (=^.^)
// (")-(")
end.