📄 gamespritesunit.pas
字号:
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 + -