unit gameobject; {$mode objfpc}{$H+} interface uses Classes, SysUtils, renderobject, math, movingparticle; //abstract class type TCollisionType=(ctCircles, ctUnrotatedRectangles); TGameObject=class(TRenderobject) { Render object with game mechanics like hitboxes and } private explodetime: qword; fIsExploding: boolean; fRange: single; fRenderCollision: boolean; explosion: array of TMovingParticle; function getRange: single; protected CollisionType: TCollisionType; public procedure explode; virtual; //splits up the objects into a million objects function exploding: boolean; function blownup: boolean; //returns true if it has gone far enough function checkCollision(other: TGameObject):boolean; virtual; property range: single read getRange; property renderCollision: boolean read fRenderCollision write fRenderCollision; destructor destroy; override; end; implementation { procedure TGameObject.renderRelative; begin inherited renderRelative; if fRenderCollision then begin //todo: render collision box/sphere end; end; } function TGameObject.blownup: boolean; //returns true if it has gone far enough begin if fIsExploding then result:=gettickcount64>=explodetime+2000 else result:=false; end; function TGameobject.exploding: boolean; begin result:=fIsExploding; end; procedure TGameObject.explode; var t: integer; i: integer; f: single; begin //boom //create 64 children if fIsExploding then exit; fIsExploding:=true; explodetime:=gettickcount64; setlength(explosion,64); fChildrenOnly:=true; width:=0; height:=0; t:=getTexture; for i:=0 to 63 do begin explosion[i]:=TMovingParticle.create(t); explosion[i].starttime:=explodetime; explosion[i].speed:=0.001+0.0001*(5+random(10)); explosion[i].direction:=random(360);//i*8;//random(360); explosion[i].x:=0; explosion[i].initialx:=0; explosion[i].y:=0; explosion[i].initialy:=0; explosion[i].width:=0.02; explosion[i].height:=0.02; explosion[i].setTextureCoords((i mod 8)/8,i/8/8,(i mod 8)/8+0.125,i/8/8+0.125); addChild(explosion[i]); end; end; function TGameObject.getRange: single; begin if fRange=0 then frange:=(width+height)/4; //just an average result:=frange; end; function TGameObject.checkCollision(other: TGameObject):boolean; //only circle ranges are handled atm. So don't use very rectangular objects //todo: Add rectangular support, including rotated rectangles //todo2: polygon collision //honestly though, everyone is free to add this, I only need this basic stuff for the tutorial var range_other: single; range_self: single; distance: single; begin result:=false; if CollisionType=ctCircles then begin range_other:=other.range; range_self:=range; distance:=sqrt(sqr(abs(other.x-x))+sqr(abs(other.y-y))); result:=distance<(range_other+range_self); end else if CollisionType=ctUnrotatedRectangles then begin //rectangles Result := (Left < other.Right) and (other.Left < Right) and (Top < other.Bottom) and (other.Top < Bottom); end; end; destructor TGameObject.destroy; var i: integer; begin for i:=0 to length(explosion)-1 do begin removeChild(explosion[i]); explosion[i].Free; end; setlength(explosion,0); inherited destroy; end; end.