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.