⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamespritesunit.pas

📁 Delphi Engine for games.
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit GameSpritesUnit;

Interface


Uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls,  DXClass, DXSprite, DXInput, DXDraws,
  DXSounds, DIB , DXWStatObj, DXWPath, DXWImageSprite;

type

  TObjectState= Set of (
                        osStay,
                        osMove,
                        osCollided,
                        osAttacked,
                        osAttackObject,
                        osAttackGround
                        );

  TTileInf = record
              SetN     : byte;
              TileN    : byte;
              TileBits : byte;
             end;


  TGameObject=class(TWImageSprite)
  private
    // need to load from ini in future
    FUnitName            : string;
    FLife                : Integer;
    FMode                : Integer;

    procedure SetUnitName(const Value: String);
    procedure SetLife(const Value: Integer);
  public
        // need to load from ini in future
        FLifeMax         : Integer;
        FArmorMax        : Integer;
        FArmor           : Integer;
        FDamage          : Integer;
        FAttackRange     : Double;
        FSight           : Integer;
        FSpeed           : Double;

    FObjectToAttack  : TGameObject;
    //FAttacked
    FAttackAngle     : Double;
    FCanAttack       : Boolean;
    FGroundToAttackX : Double;
    FGroundToAttackY : Double;


    procedure Initialize;// do after create
    procedure LoadProperties;// get specials

    property UnitName : String read FUnitName write SetUnitName;
    property Life     : Integer read FLife write SetLife;

    function AttackAngleToDir : byte;
   end;



  TGameUnit = class(TGameObject)
  private
    FAttackCounter       : LongInt;
    //FAttackEffectCount   : Integer;
    FOldAttackEffectTime : Integer;
  protected
    procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
    procedure DoMove(MoveCount: Integer); override;
    procedure DoDraw; override;
  public
    FObjectState     : TObjectState;
    FAllyID          : Byte;
    FUnitColor       : Integer;

    constructor Create(AParent: TSprite); override;
    destructor Destroy; override;

    procedure DoWatchForEnemy;//select FObjectToAttak
    procedure DoAttack;
    //procedure OrientToUnit( DestUnit : TWImageSprite );

   end;




  TAttackEffect = class(TGameObject)
  private
    FStartX       : Double;
    FStartY       : Double;
    FDestX        : Double;
    FDestY        : Double;

    //FMode         : Integer;

   protected
    procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
    procedure DoMove(MoveCount: Integer); override;
  public
    constructor Create(AParent: TSprite); override;
    destructor Destroy; override;
  end;


  TScrollBackground = class(TBackgroundSprite)
  private
    FSpeed      : Double;
    FObstacle   : Array of Array of Boolean;
    FTileMap    : Array of Array of TTileInf;

    FSet1Image  : TPictureCollectionItem;
    FSet2Image  : TPictureCollectionItem;
    FSet3Image  : TPictureCollectionItem;

    function GetObstacle (j, i: Integer): boolean;
    procedure SetObstacle(j, i: Integer; const Value: boolean);

  protected
    procedure DoDraw; override;
    function GetBoundsRect: TRect; override;

  public
    //procedure LoadObstacle;
    procedure MakeMiniMap;

    procedure LoadMap(FileName: string);

    Property Obstacle[j,i : Integer]: boolean Read GetObstacle write SetObstacle;
  end;

Var
 ScrollBackground         : TScrollBackground;

implementation

Uses
Main, Pathes, Math;


{ ------------------------ TGameUnit --------------------------- }

constructor TGameUnit.Create(AParent: TSprite);
begin
 inherited Create(AParent);
end;

destructor TGameUnit.Destroy;
Var
i : integer;
begin
 inherited Destroy;
end;


procedure TGameUnit.DoCollision(Sprite: TSprite; var Done: Boolean);
begin
 //if (Sprite is TAttackEffect)
 FObjectState:=FObjectState+[osCollided];
 Done := true;//interrupt the other detection of the colliding sprite
end;

procedure TGameUnit.DoMove(MoveCount: Integer);
Const
LastTickCount : longint = 0;
LastAnimPos   : Double = 0;
Var
LastX,LastY     : Double;
dx,dy,dl,dr     : Double;
Dir           : Byte;
dl_,X_,Y_     : Double;
i             : integer;
begin

 if FMode=1 then
  begin
    FMode:=2;

    For i:=0 to Engine.Count-1 do
    begin
     if Engine.Items[i] is TGameObject
      then with TGameObject(Engine.Items[i])do
      begin
       if  FObjectToAttack=Self
        then FObjectToAttack:=nil;
      end;
    end;

    FObjectToAttack:=nil;


    MainForm.PlaySound('RobotDth', False);
    Image := MainForm.ImageList.Items.Find('BigExplosion');

    X:=X-(Image.Width-Width)div 2;
    Y:=Y-(Image.Height-Height)div 2;

    Width := Image.Width;
    Height := Image.Height;

    AnimCount := Image.PatternCount;
    AnimLooped := False;
    AnimSpeed := 10/1000;
    AnimStart :=0;
    AnimPos := 0;

    //MainForm.PrintScreen; 

  end
 else
 if FMode=2 then
  begin
    if AnimSpeed=0 then  Dead;
    //if AnimPos=4 then  Dead;
  end;

inherited DoMove(MoveCount);


if Not CanMove then Exit;

if FMode=0 then  //  Existing now
 begin
   //FObjectState:=FObjectState-[osCollided];

   LastX:=X;
   LastY:=Y;

   Dir:=DirChangedXYArr[CurrentDirChangedXYId].Dir;
   dr:=FSpeed*MoveCount*DirV[Dir];
   Case Dir of
   0,2: begin
         dy:=ABS(DirChangedXYArr[CurrentDirChangedXYId+1].Y-cY);
         if dy>dr
          then Y:=Y+DirY[Dir]*dr
           else
             inc(CurrentDirChangedXYId);
             if CurrentDirChangedXYId=DirChangedXYCount-1
              then CanMove:=false;

        end;
   1,3: begin
         dx:=ABS(DirChangedXYArr[CurrentDirChangedXYId+1].X-cX);
         if dx>dr
          then X:=X+DirX[Dir]*dr
           else
             inc(CurrentDirChangedXYId);
             if CurrentDirChangedXYId=DirChangedXYCount-1
              then CanMove:=false;
        end;

   4,5,6,7: begin
            X_:=X;
            Y_:=Y;
            dx:=(DirChangedXYArr[CurrentDirChangedXYId+1].X-cX);
            dy:=(DirChangedXYArr[CurrentDirChangedXYId+1].Y-cY);
            dl_:=Sqrt(dx*dx+dy*dy);

            X:=X+DirX[Dir]*dr;
            Y:=Y+DirY[Dir]*dr;
            dx:=(DirChangedXYArr[CurrentDirChangedXYId+1].X-cX);
            dy:=(DirChangedXYArr[CurrentDirChangedXYId+1].Y-cY);
            dl:=Sqrt(dx*dx+dy*dy);

            if dl>dl_ then
             begin
              X:=X_;
              Y:=Y_;
              inc(CurrentDirChangedXYId);
              if CurrentDirChangedXYId=DirChangedXYCount-1
               then CanMove:=false;
             end;

            end;

   end;//Case

   Z:=Trunc(Y);

   Direction:=Dir;// alsou defind AnimStart


   if CanMove and ( Not (osMove in FObjectState))
    then // Start Mooving
      begin
       FObjectState:=FObjectState+[osMove];
       AnimLooped :=True;
       AnimSpeed := 5/1000;
       AnimCount := XCount;
       AnimPos:=0;
      end;


   if Not CanMove then
    begin //stop Mooving
     DirChangedXYCount:=0;
     FObjectState:=FObjectState-[osMove];
     AnimCount := 0;
    end;


    //if osCollided in  FObjectState then
    if Collision>0 then
     begin
      X:=LastX;
      Y:=LastY;
      Z:=Trunc(Y);
     end;
 end;//FMode=0
end;

procedure TGameUnit.DoDraw;
var
 r     : TRect;
 LifeR : TRect;
 W     : Integer;
 Progress  :integer;
 k         : double;
 DXColor   : Integer;
begin
//DXRed,DXBlue,DXYellow,DXGreen,DXLime

if FMode=0 then
begin

  r:=BoundsRect;
  W:=r.Right-r.Left;
  k:=FLife/FLifeMax;
  if k>0.66 then DXColor:=DXGreen
  else
  if k>0.33 then DXColor:=DXYellow
  else
  DXColor:=DXRed;


  Progress:=Trunc(W*k);
  LifeR:=Bounds(r.Left,r.Top,Progress,3);
  With Engine.Surface do
   begin
    FillRect(LifeR,DXColor);
    //FillRect(r,$0000FF00);
    //Pixels[L,T]:=$0000FF00;//yellow
    //FillRectAlpha(r,$0000FF00,10);
   end;

if Selected then
 begin
  With Engine.Surface.Canvas do
   begin
    Pen.Color:=clLime;
    //Rectangle(r.Left,r.Top,r.Right,r.Bottom);
    Ellipse(r.Left+4,r.Top+28,r.Right-4,r.Bottom-8);

    TextOut(r.Left,r.Bottom,format('%d %.2f',[Direction,FAttackAngle]));

    Release;
   end;
 end;//if selected

end;

inherited DoDraw;

end;

procedure TGameObject.Initialize;
begin

end;

procedure TGameObject.LoadProperties;
begin

end;


procedure TGameUnit.DoWatchForEnemy;
Var
i : integer;
dr,dx,dy: double;
//Sprite : TGameUnit;
begin
//if FObjectToAttack<>nil then Exit;

FCanAttack:=false;
FObjectToAttack:=nil;
if FMode>0 then Exit; 

For i:=0 to Engine.AllCount-1 do
 if Engine.Items[i] is TGameUnit then
  With TGameUnit(Engine.Items[i]) do
   begin
    if FMode>0 then continue;

    if Self.FAllyID=FAllyID
     then continue
      else
      begin
       dx:=Self.x-x;
       dy:=Self.y-y;
       dr:=sqrt(dx*dx+dy*dy);
       if dr<Self.FSight then
         begin
          Self.FObjectToAttack:=TGameUnit(Engine.Items[i]);
          Self.FCanAttack:=true;
          break;
         end;
      end;
   end;
end;

{
procedure TGameUnit.OrientToUnit(DestUnit: TWImageSprite);
begin
end;
}

procedure TGameUnit.DoAttack;
Const
 LastTickCount  : longint = 0;
 LastAnimPos    : Double = 0;
Var
 LastX,LastY    : Double;
 dx,dy,dl,dr    : Double;
 Dir            : Byte;
begin
inc(FAttackCounter);
if (FObjectToAttack = nil)or(Not FCanAttack)then Exit;

if
//(FAttackEffectCount<=4)and
(FAttackCounter-FOldAttackEffectTime>MainForm.DXTimer.FrameRate*0.7)
then
 begin
  MainForm.PlaySound('Gun', False);
  //Inc(FAttackEffectCount);
  FAttackAngle:=GetAngleToUnit(FObjectToAttack);
  Direction:=AttackAngleToDir;

        with TAttackEffect.Create(Engine) do
        begin
         //FGameUnit := Self;
         FObjectToAttack:=Self.FObjectToAttack;
         Direction:=Self.Direction;
         FAttackRange:=Self.FAttackRange;
         FDamage:=Self.FDamage;

         X := Self.X+(Self.Width div 2)+(Self.Width div 2)*Sin(DirRad[Direction])-Width div 2;
         Y := Self.Y+(Self.Height div 2)+(Self.Height div 2)*Cos(DirRad[Direction])-Height div 2;

         FAttackAngle:=GetAngleToUnit(FObjectToAttack);

         FStartX :=X;
         FStartY :=Y;
         FDestX:=FObjectToAttack.X;
         FDestY:=FObjectToAttack.Y;

        end;
        FOldAttackEffectTime := FAttackCounter;
      end;

end;


procedure TGameObject.SetUnitName(const Value: String);
begin

  if Value=FUnitName then Exit;
  FUnitName := Value;

  Image := MainForm.ImageList.Items.Find(Value);
  Width := Image.Width;
  Height := Image.Height;
  CalculatePatternXYCount;
  FObjectToAttack:=nil;
  AnimPos:=0;
  AnimStart:=0;

end;

procedure TGameObject.SetLife(const Value: Integer);
begin
  if Value < 0
   then FLife:=0
  else
  {
  if Value > FLifeMax
   then FLife:=FLifeMax
  else
  }
   FLife := Value;

   if(FLife=0)and(FMode=0)
    then FMode:=1;
    
end;

////////////////////////////////////////////////////////////////////

constructor TAttackEffect.Create(AParent: TSprite);
begin
  inherited Create(AParent);
  Collisioned := False;

  Image := MainForm.ImageList.Items.Find('FBall');
  //Image := MainForm.ImageList.Items.Find('Explosion32x42');

  Z := MapH;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -