blogger

JackS·Zhao

人生就像开车在路上走,你我只是其中的一个驾驶员。送走老的、迎来小的,匆匆看过路边风景。一直向前行驶,却不知道是谁修的这条路。
学习delphi的第二课HGE 初次完成绘图碰撞等功能

时间:2024-12-15    作者:JackS·Zhao    分类: 编程


代码如下

program RunBall;

uses
  Windows, SysUtils, HGEImages, HGECanvas, HGEDef, HGE, HGESpriteEngine;

type
  //单精灵类
  TMonoSprite = class(TSprite)
  private
    FCounter: Double;//随机数
    FLife: Integer;//生命值
    FHit: Boolean;//是否撞击
  public
    procedure DoMove(const MoveCount: Single); override;//覆盖父类的同名函数,用于小球的移动
  end;

  //玩家精灵
  TPlayerSprite = class(TSprite)
  public
    procedure DoCollision(const Sprite: TSprite); override;//碰撞函数
    procedure DoMove(const MoveCount: Single); override;//移动
  end;

var
  myHGE: IHGE;
  Images: THGEImages;//HGE图片
  Canvas: THGECanvas;//HGE画布
  Font: TSysFont;//系统字体,是D3D的字体
  SpriteEngine: TSpriteEngine;//精灵引擎
  Tile: array[0..80, 0..80] of TSprite;//磁砖,也就是游戏中的地图,是一个二维数组
  PlayerSprite: TPlayerSprite;//玩家精灵的实例

{$R *.res}

//小球的移动函数,小球是按照不规则的环形旋转,并随身向某个方向移动
procedure TMonoSprite.DoMove(const MoveCount: Single);
begin
  inherited;//执行父类的同名函数
  CollidePos := Point2(X + 80, Y + 80);//碰撞点,加上80,是为了移动小球的坐标,使碰撞看上去发生的更加自然
  FCounter := FCounter + 1;
  X := X + Sin256(trunc(FCounter)) * 3;//绕某一点旋转时的X值
  Y := Y + Cos256(trunc(FCounter)) * 3;//绕某一点旋转时的Y值

  //如果发生了撞击
  if FHit then begin
    FLife := FLife - 1;//发生撞击,小球的生命值减一
    if FLife < 0 then Dead;//如果生命值小于0,小球死亡
  end;
end;

//玩家操纵小球的碰撞函数,参数Sprite就是与玩家小球发生的碰撞的那个大些的小球
procedure TPlayerSprite.DoCollision(const Sprite: TSprite);
begin
  //如果参数是系统产生的精灵,就是自由旋转并运动的小球
  if Sprite is TMonoSprite then begin
    with TMonoSprite(Sprite) do begin
      ImageName := 'img1-2';//加载小球碰撞时的图片
      Collisioned := False;//把撞击模式置为否,以等待下一次撞击
      FHit := True;//命中置为真
    end;
  end;

end;

//玩家操作小球的移动函数
procedure TPlayerSprite.DoMove(const MoveCount: Single);
begin
  inherited;//调用父类的同名函数
  CollidePos := Point2(X + 50, Y + 50);//重置碰撞点

  if myHGE.Input_GetKeyState(HGEK_UP) then//如果按下了向上的方向键
    Y := Y - 13;

  if myHGE.Input_GetKeyState(HGEK_DOWN) then//如果按下了向下的方向键
    Y := Y + 13;

  if myHGE.Input_GetKeyState(HGEK_LEFT) then//如果按下了向左的方向键
    X := X - 13;

  if myHGE.Input_GetKeyState(HGEK_RIGHT) then//如果按下了向右的方向键
    X := X + 13;

  Collision;//调用父类的碰撞函数
  Engine.WorldX := X - 340;
  Engine.WorldY := Y - 250;
end;

//创建磁砖们,也就是创建游戏的地图
procedure CreateTiles;
var
  i, j: Integer;
begin
  for i := 0 to 80 do begin
    for j := 0 to 80 do begin
      //调用精灵类的构造器,把精灵类对象创建出来,构造器的参数是精灵类对象的Parent
      //也就是精灵类对象所在的窗口
      Tile[i, j] := TSprite.Create(SpriteEngine);
      Tile[i, j].ImageName := 't' + InttoStr(Random(20));
      Tile[i, j].Width := Tile[i, j].PatternWidth;//磁砖的宽度置为精灵模式的宽度
      Tile[i, j].Height := Tile[i, j].PatternHeight;//磁砖的高度置为精灵模式的高度
      Tile[i, j].Moved := FALSE;
      Tile[i, j].X := i * 64;
      Tile[i, j].Y := j * 64;
    end;
  end;
end;

//创建游戏中旋转的小球,个数是200
procedure CreateSprite;
var
  i: Integer;
begin
  //创建201个旋转的小球
  for i := 0 to 200 do begin
    with TMonoSprite.Create(SpriteEngine) do begin
      ImageName := 'img1';
      Width := PatternWidth;
      Height := PatternHeight;
      Collisioned := True;//撞击模式为真,等待撞击的意思
      CollideRadius := 80;
      X := Random(5000);//从0到5000中取一个随机数
      Y := Random(5000);
      Z := 2;//景深置为第2层
      FCounter := Random(1000);
      FLife := 15;//生命值置为15,也就是可以有16次撞击机会
      FHit := False;//未撞击
    end;
  end;

  //创建玩家精灵类的实例
  PlayerSprite := TPlayerSprite.Create(SpriteEngine);
  with PlayerSprite do begin
    ImageName := 'img2';
    Z := 2;
    X := 2560;
    Y := 2560;
    Collisioned := True;//撞击模式置为真
    CollideRadius := 50;//撞击半径置为50
  end;
end;

//帧函数,游戏中每一帧都要调用的函数,游戏逻辑写在该函数中,也叫逻辑函数
function FrameFunc: Boolean;
begin
  case myHGE.Input_GetKey of
    HGEK_ESCAPE://如果得到的按键消息,是ESC键被按下,则游戏退出
    begin
      FreeAndNil(Canvas);
      FreeAndNil(Images);
      FreeAndNil(SpriteEngine);
      FreeAndNil(Font);
      Result := True;//该函数返回真,游戏就会结束
      Exit;
    end;
  end;

  Result := FALSE;//正常运行时,返回假
end;

//绘制函数,也就是渲染函数,程序开始后,HGE将反复地调用这个函数进行渲染
function RenderFunc: Boolean;
begin
  myHGE.Gfx_BeginScene;//开始渲染
  myHGE.Gfx_Clear(0);//清空游戏画面,并用颜色0填充,0就是黑色
  SpriteEngine.Draw;//绘制输出
  SpriteEngine.Move(1);//从帧列表中向下移动,准备渲染下一帧
  SpriteEngine.Dead;

  myHGE.Gfx_EndScene;//结束渲染

  Result := FALSE;//正常情况下,也要返回假
end;

//这是游戏运行的主函数
procedure Main;
var
  i: Integer;
begin
  myHGE := HGECreate(HGE_VERSION);//创建HGE实例
  myHGE.System_SetState(HGE_SHOWSPLASH, False);//不显示HGE的Logo
  myHGE.System_SetState(HGE_FRAMEFUNC, FrameFunc);//设置帧函数,也就是逻辑函数
  myHGE.System_SetState(HGE_RENDERFUNC, RenderFunc);//设置渲染函数
  myHGE.System_SetState(HGE_USESOUND, False);//设置不使用音效
  myHGE.System_SetState(HGE_WINDOWED, True);//设置使用窗口模式
  myHGE.System_SetState(HGE_SCREENWIDTH, 800);//设置屏幕宽度
  myHGE.System_SetState(HGE_SCREENHEIGHT, 600);//设置屏幕高度
  myHGE.System_SetState(HGE_SCREENBPP, 16);//设置颜色模式
  myHGE.System_SetState(HGE_FPS, HGEFPS_VSYNC);//设置帧播放模式

  Canvas := THGECanvas.Create;//创建画布
  Images := THGEImages.Create;//创建图形
  SpriteEngine := TSpriteEngine.Create(nil);//创建精灵引擎,nil表示没有所有者
  SpriteEngine.Images := Images;
  SpriteEngine.Canvas := Canvas;

  //如果HGE初始化成功
  if myHGE.System_Initiate then begin
    Font := TSysFont.Create;//创建D3D类型的字体
    Font.CreateFont('arial', 15, []);//创建字形,名称为arial,大小为15号,[]表示用字体默认属性

    for i := 0 to 20 do
      Images.LoadFromFile('Gfx\' + 't' + InttoStr(i) + '.png');//把21幅背景图片加载到图形列表

    Images.LoadFromFile('Gfx\img1.png');
    Images.LoadFromFile('Gfx\img1-2.png');
    Images.LoadFromFile('Gfx\img2.png');

    CreateSprite;//创建精灵
    CreateTiles;//创建磁砖,也就是创建地图
    myHGE.System_Start;//开始HGE
  end
  else
    MessageBox(0, pChar(myHGE.System_GetErrorMessage), 'Error Information', MB_OK);

  myHGE.System_Shutdown;
  myHGE := nil;
end;

begin

  ReportMemoryLeaksOnShutdown := True;
  Main;

end.

我所学习的教程来源于 断剑网
运行效果