组装21 人物动画的简单实现 角色列表多个角色的显示

Pic027

Pic028

unit Movies;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, DXDraws, WILIB;

type

  TAction = (ActStand, ActWalk, ActRun, ActRushLeft, ActRushRight, ActWarMode,
    ActHit, ActHeavyHit, ActBigHit, ActFireHitReady, ActSpell,
    ActSitdown, ActStruck, ActDie);

  TMagicType = (mtReady, mtFly, mtExplosion,
    mtFlyAxe, mtFireWind, mtFireGun,
    mtLightingThunder, mtThuder, mtExploBujauk,
    mtBujaukGroundEffect, mtKyulkai, mtFlyarrow,
    mt12, mt13, mt14);

  TUseMagicInfo = record
    ServerMagicCode: Integer;
    MagicSerial: Integer;
    Target: Integer;
    EffectType: TMagicType;
    EffectNumber: Integer;
    TargX: Integer;
    TargY: Integer;
    Recusion: Boolean;
    AniTime: Integer;
  end;

  TActionInfo = packed record
    start: Word;
    frame: Word;
    skip: Word;
    ftime: Word;
    usetick: Word;
  end;

  THumanAction = packed record
    ActStand: TActionInfo;
    ActWalk: TActionInfo;
    ActRun: TActionInfo;
    ActRushLeft: TActionInfo;
    ActRushRight: TActionInfo;
    ActWarMode: TActionInfo;
    ActHit: TActionInfo;
    ActHeavyHit: TActionInfo;
    ActBigHit: TActionInfo;
    ActFireHitReady: TActionInfo;
    ActSpell: TActionInfo;
    ActSitdown: TActionInfo;
    ActStruck: TActionInfo;
    ActDie: TActionInfo;
  end;

  TForm1 = class(TForm)

    DXDrawHuman: TDXDraw;
    ButtonPlay: TButton;
    TimerShow: TTimer;
    ListBoxAction: TListBox;
    ListBoxDirect: TListBox;
    ListBoxSex: TListBox;
    ListBoxJob: TListBox;
    ListBoxDress: TListBox;
    MemoResult: TMemo;
    ButtonStop: TButton;
    ListBoxHair: TListBox;
    Edit1: TEdit;
    Label1: TLabel;
    Edit2: TEdit;
    Label2: TLabel;
    Label3: TLabel;
    Edit3: TEdit;
    EditX: TEdit;
    EditY: TEdit;
    Label4: TLabel;
    Label5: TLabel;
    Edit4: TEdit;
    Edit5: TEdit;
    Label6: TLabel;
    Label7: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure DXDrawHumanInitialize(Sender: TObject);
    procedure ButtonPlayClick(Sender: TObject);
    procedure TimerShowTimer(Sender: TObject);

    procedure ButtonStopClick(Sender: TObject);

    procedure GetEffectBase(mag, mtype: integer; var wimg: TWILImages; var idx:
      integer);

    procedure DrawGrid;
    procedure RandomXY(numCount: Integer; var nums: array of Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  HUMANFRAME = 600;

  UNITX = 48;
  UNITY = 32;

  DR_UP = 0;
  DR_UPRIGHT = 1;
  DR_RIGHT = 2;
  DR_DOWNRIGHT = 3;
  DR_DOWN = 4;
  DR_DOWNLEFT = 5;
  DR_LEFT = 6;
  DR_UPLEFT = 7;

  HA: THumanAction = (
    ActStand: (start: 0; frame: 4; skip: 4; ftime: 200; usetick: 0);
    ActWalk: (start: 64; frame: 6; skip: 2; ftime: 90; usetick: 2);
    ActRun: (start: 128; frame: 6; skip: 2; ftime: 120; usetick: 3);
    ActRushLeft: (start: 128; frame: 3; skip: 5; ftime: 120; usetick: 3);
    //先左手
    ActRushRight: (start: 131; frame: 3; skip: 5; ftime: 120; usetick: 3);
    //先右手
    ActWarMode: (start: 192; frame: 1; skip: 0; ftime: 200; usetick: 0);
    //ActHit:    (start: 200;    frame: 5;  skip: 3;  ftime: 140;  usetick: 0);
    ActHit: (start: 200; frame: 6; skip: 2; ftime: 85; usetick: 0);
    ActHeavyHit: (start: 264; frame: 6; skip: 2; ftime: 90; usetick: 0);
    ActBigHit: (start: 328; frame: 8; skip: 0; ftime: 70; usetick: 0);
    //这里指的烈火蓄力的动作?
    ActFireHitReady: (start: 192; frame: 1; skip: 0; ftime: 70; usetick: 0);
    ActSpell: (start: 392; frame: 6; skip: 2; ftime: 60; usetick: 0);
    ActSitdown: (start: 456; frame: 2; skip: 0; ftime: 300; usetick: 0);
    ActStruck: (start: 472; frame: 3; skip: 5; ftime: 70; usetick: 0);
    ActDie: (start: 536; frame: 4; skip: 4; ftime: 120; usetick: 0)
    );

  //一个人物模型就是599张图片
  WORDER: array[0..1, 0..599] of byte = (//男女角色有些不同?
    (
    //站立0-63
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
    0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
    //走64-127
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
    //跑128-191
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
    //战斗准备 8个方向,192-199
    0, 1, 1, 1, 0, 0, 0, 0,
    //攻击动作Hit 200-263
    1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
    //攻击动作HeavyHit  264 - 327
    0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
    1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1,
    //攻击动作BigHit 328- 391
    1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
    1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0,
    //魔法攻击动作Spell 392- 455
    0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
    1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
    //挖,蹲下的动作Sitdown  每个方向2帧  456-471
    0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
    //被攻击后仰的动作Struck 每个方向3帧 472- 535
    0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
    0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
    //死亡的动作 每个方向4帧 536-599
    0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
    0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1
    ),

    (
    //站立0-63
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
    0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
    //走64-127
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
    //跑128-191
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
    //战斗准备 8个方向,192-199
    1, 1, 1, 1, 0, 0, 0, 0,
    //攻击动作Hit 200-263
    1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
    //攻击动作HeavyHit  264 - 327
    0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
    1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1,
    //攻击动作BigHit 328- 391
    1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
    1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0,
    //魔法攻击动作Spell 392- 455
    0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
    1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
    //挖,蹲下的动作Sitdown  每个方向2帧  456-471
    0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
    //被攻击后仰的动作Struck 每个方向3帧 472- 535
    0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
    0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
    //死亡的动作 每个方向4帧 536-599
    0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
    0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1
    )
    );

  EffectBase: array[0..30] of integer = (
    0, //0  火球术
    200, //1  治愈术
    400, //2  大火球
    600, //3  施毒术
    0, //4  攻杀剑术
    900, //5  抗拒火环
    920, //6  地狱火
    940, //7  疾光电影     没有SPELL效果
    20, //8  雷电术,  Magic2
    940, //9  灵魂火符
    940, //10 幽灵盾       没有SPELL效果
    940, //11 神圣战甲术   没有SPELL效果
    0, //12 刺杀剑术
    1380, //13 困魔咒
    1500, //14 召唤骷髅
    1520, //15 隐身术
    940, //16 集体隐身术    没有SPELL效果
    1560, //17 诱惑之光
    1590, //18 瞬息移动
    1620, //19 火墙
    1650, //20 爆裂火焰
    1680, //21 地狱雷光
    0, //22 半月弯刀
    0, //23 烈火剑法
    0, //24 野蛮冲撞
    3960, //25 心灵启示
    1790, //26 群体治疗术
    0, //27 召唤神兽  Magic2
    3880, //28 魔法盾
    3920, //29 圣言术
    3840 //30 冰咆哮

    );

  HitEffectBase: array[0..4] of integer = (
    800,
    1410,
    1700,
    3480,
    3390
    );

  EXPLOSIONBASE = 170;
  FLYBASE = 10;

type
  TActor = class
    RecogId: Integer;
    m_btSex: Byte;
    m_btJob: Byte;
    m_btDress: Byte;
    m_btDir: Byte;
    m_btAtc: TAction;

    m_nCurrX: Integer;
    m_nCurrY: Integer;
    m_nRx: Integer;
    m_nRy: Integer;

    m_nShiftX: Integer;
    m_nShiftY: Integer;

    m_nStartFrame: Integer;
    m_nEndFrame: Integer;
    m_boLockEndFrame: Boolean;
    m_dwFrameTime: LongWord;
    m_dwStartTime: LongWord;
    m_nMaxTick: Integer;
    m_nCurTick: Integer;
    m_nCurrentFrame: Integer;
    m_nCurrentAction: TAction;
    m_nMoveStep: Integer;

    m_BodySurface: TDirectDrawSurface;
    m_nPx: Integer;
    m_nPy: Integer;

    m_btHair: Byte;
    m_nHairOffset: Integer;
    m_HairSurface: TDirectDrawSurface;
    m_nHairPx: Integer;
    m_nHairPy: Integer;

    m_btWeapon: Byte;
    m_nWeaponOffset: Integer;
    m_WeaponSurface: TDirectDrawSurface;
    m_nWeaponPx: Integer;
    m_nWeaponPy: Integer;
    m_nWpord: Integer;

    //刀光效果
    m_boHitEffect: Boolean;
    m_nHitEffectNumber: Integer;

    //施法效果
    m_boUseMagic: Boolean;
    m_CurMagic: TUseMagicInfo;
    m_nCurEffFrame: Integer;
    m_nSpellFrame: Integer;

    constructor Create;
    destructor Destroy;

    procedure CalcActorFrame;
    procedure Run;
    function Move(step: Integer): Boolean;
    procedure Shift(dir, step, cur, max: Integer);
    procedure LoadSurface;
    procedure DrawChr(dsurface: TDirectDrawSurface; dx, dy: integer);

  end;

  TMagicEff = class
    m_boActive: Boolean;

    ServerMagicId: Integer;
    MagOwner: TObject;
    TargerActor: TObject;
    ImgLib: TWILImages;
    EffectBase: Integer;
    MagExplionBase: Integer;
    px, py: Integer;
    rx, ry: Integer;
    Dir16, OldDir16: Byte;
    TargetX, TargetY: Integer;
    TargetRx, TargerRy: Integer;
    FlyX, FlyY, OldFlyX, OldFlyY: Integer;
    FlyXf, FlyYf: Real;
    Repetition: Boolean;

    FixedEffect: Boolean;
    MagicType: Integer;
    NextEffect: TMagicEff;
    ExplosionFrame: Integer;
    NextFrameTime: Integer;
    Light: Integer;

    Start: Integer;
    CurFrame: Integer;
    Frame: Integer;

  private
    m_dwFrameTime: LongWord;
    M_dwStartTime: LongWord;
    repeattime: LongWord;
    steptime: LongWord;
    fireX, fireY: Integer;
    firedisX, firedisY: Integer;
    newfiredisX, newfiredisY: Integer;
    fireMyselfX, fireMyselfY: Integer;
    prevdisX, prevdisY: Integer;
  protected
    procedure GetFlyXY(ms: Integer; var fx, fy: integer);
  public
    constructor Create(id, effnum, sx, sy, tx, ty: Integer; mtype: TMagicType;
      Recusion: Boolean; anitime: Integer);
    destructor Destroy; override;
    function Run: Boolean; dynamic;
    function Shift: Boolean; dynamic;
    procedure DrawEff(surface: TDirectDrawSurface); dynamic;

  end;

  TPlayScene = class

  public
    ActorList: TList;
    EffectList: TList;
    constructor Create;
    destructor Destroy;
    function NewActor(chrid, cx, cy, cdir, dress, hair, weapon: Integer;
      action: TAction): TActor;
    procedure PlayScene(MSurface: TDirectDrawSurface);
  end;

var
  Form1: TForm1;

  MagicEff1: TMagicEff;
  PlayScene: TPlayScene;
  g_mainWil: TWILImages;
  g_WHumImgImages: TWILImages;
  g_WHairImgImages: TWILImages;
  g_WWeaponImages: TWILImages;
  g_WMagicImages: TWILImages;
  g_WMagic2Images: TWILImages;
  g_cacheSurface: TDirectDrawSurface;
  g_MySelf: TAction;
  bmpIndex: Integer;

implementation

{$R *.dfm}

function ToDXD7Color(Color: TColor): TColor;
var
  R, G, B: Integer;
begin
  R := Color and $FF;
  G := (Color and $FF00) shr 8;
  B := (Color and $FF0000) shr 16;
  Result := R shl 16 or G shl 8 or B;
end;

function _MAX(n1, n2: integer): integer;
begin
  if n1 > n2 then
    Result := n1
  else
    Result := n2;
end;

//计算飞的方向16,有16个方向?是将8个方向再次细化?

function GetFlyDirection16(sx, sy, ttx, tty: integer): Integer;
var
  fx, fy: Real;
begin
  fx := ttx - sx;
  fy := tty - sy;
  sx := 0;
  sy := 0;
  Result := 0;
  if fx = 0 then
  begin
    if fy < 0 then
      Result := 0 //
    else
      Result := 8; //
    exit;
  end;

  if fy = 0 then
  begin
    if fx < 0 then
      Result := 12 //
    else
      Result := 4; //
    exit;
  end;

  if (fx > 0) and (fy < 0) then
  begin
    Result := 4;
    if - fy > fx / 4 then
      Result := 3;
    if - fy > fx / 1.9 then
      Result := 2;
    if - fy > fx * 1.4 then
      Result := 1;
    if - fy > fx * 4 then
      Result := 0;
  end;
  if (fx > 0) and (fy > 0) then
  begin
    Result := 4;
    if fy > fx / 4 then
      Result := 5;
    if fy > fx / 1.9 then
      Result := 6;
    if fy > fx * 1.4 then
      Result := 7;
    if fy > fx * 4 then
      Result := 8;
  end;
  if (fx < 0) and (fy > 0) then
  begin
    Result := 12;
    if fy > -fx / 4 then
      Result := 11;
    if fy > -fx / 1.9 then
      Result := 10;
    if fy > -fx * 1.4 then
      Result := 9;
    if fy > -fx * 4 then
      Result := 8;
  end;
  if (fx < 0) and (fy < 0) then
  begin
    Result := 12;
    if - fy > -fx / 4 then
      Result := 13;
    if - fy > -fx / 1.9 then
      Result := 14;
    if - fy > -fx * 1.4 then
      Result := 15;
    if - fy > -fx * 4 then
      Result := 0;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  TimerShow.Enabled := False;
  bmpIndex := -1;
  ListBoxJob.ItemIndex := 0;
  ListBoxSex.ItemIndex := 0;
  ListBoxDress.ItemIndex := 0;
  ListBoxAction.ItemIndex := 0;
  ListBoxDirect.ItemIndex := 0;
  g_WHumImgImages := TWILImages.Create;
  g_WHairImgImages := TWILImages.Create;
  g_WWeaponImages := TWILImages.Create;
  g_WMagicImages := TWILImages.Create;
  g_WMagic2Images := TWILImages.Create;

  PlayScene := TPlayScene.Create;
  MagicEff1 := nil;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  g_WHumImgImages.Destroy;
  g_WHairImgImages.Destroy;
  g_WWeaponImages.Destroy;
  g_WMagicImages.Destroy;
  g_WMagic2Images.Destroy;
  g_cacheSurface.Free;

  PlayScene.Destroy;
  if MagicEff1 <> nil then
    MagicEff1.Free;
end;

procedure TForm1.DXDrawHumanInitialize(Sender: TObject);
begin
  g_WHumImgImages.DDraw := DXDrawHuman.DDraw;
  g_WHumImgImages.FileName := 'E:\mirClient\Mir1.76\Data\Hum.wil';
  g_WHumImgImages.Initialize;
  g_WHairImgImages.DDraw := DXDrawHuman.DDraw;
  g_WHairImgImages.FileName := 'E:\mirClient\Mir1.76\Data\Hair.wil';
  g_WHairImgImages.Initialize;
  g_WWeaponImages.DDraw := DXDrawHuman.DDraw;
  g_WWeaponImages.FileName := 'E:\mirClient\Mir1.76\Data\Weapon.wil';
  g_WWeaponImages.Initialize;

  g_WMagicImages.DDraw := DXDrawHuman.DDraw;
  g_WMagicImages.FileName := 'E:\mirClient\Mir1.76\Data\Magic.wil';
  g_WMagicImages.Initialize;

  g_WMagic2Images.DDraw := DXDrawHuman.DDraw;
  g_WMagic2Images.FileName := 'E:\mirClient\Mir1.76\Data\Magic2.wil';
  g_WMagic2Images.Initialize;

end;

procedure TForm1.ButtonPlayClick(Sender: TObject);

const
  numsMax = 17 * 19;
var

  i: Integer;
  cx, cy, cdir, dress, hair, weapon: Integer;
  action: TAction;
  actor: TActor;

  nums : array of Integer;

begin
  TimerShow.Enabled := True;
  MemoResult.Text := ListBoxJob.Items[ListBoxJob.ItemIndex] + '  ' +
    ListBoxSex.Items[ListBoxSex.ItemIndex] + '  ' +
    ListBoxDress.Items[ListBoxDress.ItemIndex] + '  ' +
    ListBoxAction.Items[ListBoxAction.ItemIndex] + '  ' +
    ListBoxDirect.Items[ListBoxDirect.ItemIndex];

  SetLength(nums,numsMax);
  RandomXY(numsMax,nums);

  for i := 0 to numsMax - 1 do
  begin
    cx := nums[i] mod 17;
    cy := nums[i] div 17;

    cdir := Random(8);
    dress := Random(18);
    hair := Random(2);
    weapon := Random(35);
    //  action := ActStand ;
    action := TAction(Random(14));
    // if action = ActSpell then  action := ActStand;
    action := ActWalk;
    cdir := 4;
    actor := PlayScene.NewActor(i, cx, cy, cdir, dress, hair, weapon, action);
    actor.CalcActorFrame;
  end;

end;

procedure TForm1.TimerShowTimer(Sender: TObject);
begin
  DXDrawHuman.Surface.Fill(clGray);
   DrawGrid;
  PlayScene.PlayScene(DXDrawHuman.Surface);
  DXDrawHuman.Flip;
end;

procedure TForm1.DrawGrid;
var
  i: Integer;
begin

  with DXDrawHuman.Surface.Canvas do
  begin
    Pen.Color := clWhite;
    DXDrawHuman.Surface.Canvas.Pen.Width := 1;
    for i := 0 to 800 div UNITX do
    begin
      MoveTo(i * UNITX, 0);
      LineTo(i * UNITX, 600);
    end;
    for i := 0 to 600 div UNITY do
    begin
      MoveTo(0, i * UNITY);
      LineTo(800, i * UNITY);
    end;
    Release;
  end;
end;

procedure TForm1.RandomXY(numCount: Integer; var nums: array of Integer);
const
  MAX_VALUE = 17 * 19;
var
  i,randIndex: Integer;
  used: array[0..MAX_VALUE - 1] of Boolean;
begin

  Randomize;
  for i := 0 to MAX_VALUE -1  do
    used[i] := False;

  for i := 0 to numCount - 1 do
  begin
    repeat
      randIndex := Random(MAX_VALUE + 1);
    until not used[randIndex];

    nums[i] := randIndex;
    used[randIndex] := True;
  end;
end;

constructor TActor.Create;
begin
  m_BodySurface := nil;

  m_nHairOffset := -1;
  m_btHair := 0;
  m_HairSurface := nil;

  m_nWeaponOffset := -1;
  m_btWeapon := 0;
  m_WeaponSurface := nil;

  m_nCurrentFrame := -1;

  m_nShiftX := 0;
  m_nShiftY := 0;

end;

destructor TActor.Destroy;
begin
  inherited Destroy;
end;

procedure TActor.CalcActorFrame;

begin

  m_nHairOffset := HUMANFRAME * m_btHair;
  m_boUseMagic := FALSE;
  m_boHitEffect := FALSE;
  m_nCurrentFrame := -1;
  case m_nCurrentAction of
    ActStand:
      begin
        m_nStartFrame := HA.ActStand.start + m_btDir * (HA.ActStand.frame +
          HA.ActStand.skip);
        m_nEndFrame := m_nStartFrame + HA.ActStand.frame - 1;
        m_dwFrameTime := HA.ActStand.ftime;
        m_dwStartTime := GetTickCount;

      end;
    ActWalk:
      begin
        m_nStartFrame := HA.ActWalk.start + m_btDir * (HA.ActWalk.frame +
          HA.ActWalk.skip);
        m_nEndFrame := m_nStartFrame + HA.ActWalk.frame - 1;
        m_dwFrameTime := HA.ActWalk.ftime;
        m_dwStartTime := GetTickCount;
        m_nMaxTick := HA.ActWalk.UseTick;
        m_nCurTick := 0;

      end;
    ActRun:
      begin
        m_nStartFrame := HA.ActRun.start + m_btDir * (HA.ActRun.frame +
          HA.ActRun.skip);
        m_nEndFrame := m_nStartFrame + HA.ActRun.frame - 1;
        m_dwFrameTime := HA.ActRun.ftime;
        m_dwStartTime := GetTickCount;
        m_nMaxTick := HA.ActRun.UseTick;
        m_nCurTick := 0;

      end;

    ActRushLeft:
      begin
        m_nStartFrame := HA.ActRushLeft.start + m_btDir * (HA.ActRushLeft.frame
          + HA.ActRushLeft.skip);
        m_nEndFrame := m_nStartFrame + HA.ActRushLeft.frame - 1;
        m_dwFrameTime := HA.ActRushLeft.ftime;
        m_dwStartTime := GetTickCount;
        m_nMaxTick := HA.ActRushLeft.UseTick;
        m_nCurTick := 0;
      end;
    ActRushRight:
      begin
        m_nStartFrame := HA.ActRushRight.start + m_btDir *
          (HA.ActRushRight.frame + HA.ActRushRight.skip);
        m_nEndFrame := m_nStartFrame + HA.ActRushRight.frame - 1;
        m_dwFrameTime := HA.ActRushRight.ftime;
        m_dwStartTime := GetTickCount;
        m_nMaxTick := HA.ActRushRight.UseTick;
        m_nCurTick := 0;

      end;
    ActWarMode:

      begin
        m_nStartFrame := HA.ActWarMode.start + m_btDir * (HA.ActWarMode.frame +
          HA.ActWarMode.skip);
        m_nEndFrame := m_nStartFrame + HA.ActWarMode.frame - 1;
        m_dwFrameTime := HA.ActWarMode.ftime;
        m_dwStartTime := GetTickCount;
        m_nMaxTick := HA.ActWarMode.UseTick;

      end;
    ActHit:
      begin
        m_nStartFrame := HA.ActHit.start + m_btDir * (HA.ActHit.frame +
          HA.ActHit.skip);
        m_nEndFrame := m_nStartFrame + HA.ActHit.frame - 1;
        m_dwFrameTime := HA.ActHit.ftime;
        m_dwStartTime := GetTickCount;
        m_boHitEffect := TRUE;
      end;

    ActHeavyHit:
      begin
        m_nStartFrame := HA.ActHeavyHit.start + m_btDir * (HA.ActHeavyHit.frame
          + HA.ActHeavyHit.skip);
        m_nEndFrame := m_nStartFrame + HA.ActHeavyHit.frame - 1;
        m_dwFrameTime := HA.ActHeavyHit.ftime;
        m_dwStartTime := GetTickCount;
      end;
    ActBigHit:
      begin
        m_nStartFrame := HA.ActBigHit.start + m_btDir * (HA.ActBigHit.frame +
          HA.ActBigHit.skip);
        m_nEndFrame := m_nStartFrame + HA.ActBigHit.frame - 1;
        m_dwFrameTime := HA.ActBigHit.ftime;
        m_dwStartTime := GetTickCount;
      end;
    ActFireHitReady:
      begin
        m_nStartFrame := HA.ActFireHitReady.start + m_btDir *
          (HA.ActFireHitReady.frame +
          HA.ActFireHitReady.skip);
        m_nEndFrame := m_nStartFrame + HA.ActFireHitReady.frame - 1;
        m_dwFrameTime := HA.ActFireHitReady.ftime;
        m_dwStartTime := GetTickCount;
      end;
    ActSpell:
      begin
        m_nStartFrame := HA.ActSpell.start + m_btDir * (HA.ActSpell.frame +
          HA.ActSpell.skip);
        m_nEndFrame := m_nStartFrame + HA.ActSpell.frame - 1;
        m_dwFrameTime := HA.ActSpell.ftime;
        m_dwStartTime := GetTickCount;

        m_nCurEffFrame := 0;
        m_boUseMagic := TRUE;
        m_nSpellFrame := 10; //默认为10帧 而SPELL 动作只有6帧

        if m_CurMagic.EffectNumber = 26 then
        begin
          m_nSpellFrame := 20;
        end;
      end;

    ActSitdown:
      begin
        m_nStartFrame := HA.ActSitdown.start + m_btDir * (HA.ActSitdown.frame +
          HA.ActSitdown.skip);
        m_nEndFrame := m_nStartFrame + HA.ActSitdown.frame - 1;
        m_dwFrameTime := HA.ActSitdown.ftime;
        m_dwStartTime := GetTickCount;
      end;
    ActStruck:
      begin
        m_nStartFrame := HA.ActStruck.start + m_btDir * (HA.ActStruck.frame +
          HA.ActStruck.skip);
        m_nEndFrame := m_nStartFrame + HA.ActStruck.frame - 1;
        m_dwFrameTime := HA.ActStruck.ftime;
        m_dwStartTime := GetTickCount;
      end;
    ActDie:
      begin
        m_nStartFrame := HA.ActDie.start + m_btDir * (HA.ActDie.frame +
          HA.ActDie.skip);
        m_nEndFrame := m_nStartFrame + HA.ActDie.frame - 1;
        m_dwFrameTime := HA.ActDie.ftime;
        m_dwStartTime := GetTickCount;
      end;
  end;
end;

function TActor.Move(step: Integer): Boolean;
var
  prv, curstep, maxstep: Integer;

begin
  Result := False;

  prv := m_nCurrentFrame;

  if (m_nCurrentAction = ActWalk) or
    (m_nCurrentAction = ActRun) or
    (m_nCurrentAction = ActRushLeft) or
    (m_nCurrentAction = ActRushRight) then
  begin
    if (m_nCurrentFrame < m_nStartFrame) or (m_nCurrentFrame > m_nEndFrame) then
      m_nCurrentFrame := m_nStartFrame - 1;
    if GetTickCount - m_dwStartTime > m_dwFrameTime then
    begin

      if m_nCurrentFrame < m_nEndFrame then
      begin
        Inc(m_nCurrentFrame);
        curstep := m_nCurrentFrame - m_nStartFrame + 1;
        maxstep := m_nEndFrame - m_nStartFrame + 1;
        Shift(m_btDir, step, curstep, maxstep);
        m_dwStartTime := GetTickCount;
      end;

      if m_nCurrentFrame >= m_nEndFrame then
      begin
        m_boLockEndFrame := True;
        m_nCurrentAction := ActRun;

      end;

    end;
    Result := True;
  end;

  if prv <> m_nCurrentFrame then
  begin
    LoadSurface;
  end;

end;

procedure TActor.Shift(dir, step, cur, max: Integer);
var
  unx, uny, ss, v: Integer;
begin
  unx := UNITX * step;
  uny := UNITY * step;
  if cur > max then
    cur := max;
  m_nRx := m_nCurrX;
  m_nRy := m_nCurrY;
  ss := Round((max - cur - 1) / max) * step;
  case dir of
    DR_UP:
      begin
        ss := Round((max - cur) / max) * step;
        m_nShiftX := 0;
        m_nRy := m_nCurrY + ss;
        if ss = step then
          m_nShiftY := -Round(uny / max * cur)
        else
          m_nShiftY := Round(uny / max * (max - cur));
      end;

    DR_DOWN:
      begin
        if max >= 6 then
          v := 1
        else
          v := 0;
        ss := Round((max - cur - v) / max) * step;
        m_nShiftX := 0;
        m_nRy := m_nCurrY - ss;
        if ss = step then
          m_nShiftY := Round(uny / max * cur)
        else
          m_nShiftY := -Round(uny / max * (max - cur));
      end;

    DR_RIGHT:
      begin
        ss := Round((max - cur) / max) * step;
        m_nRx := m_nCurrX - ss; //实际地图坐标
        if ss = step then
          m_nShiftX := Round(unx / max * cur)
        else
          m_nShiftX := -Round(unx / max * (max - cur));
        m_nShiftY := 0;
      end;

    DR_LEFT:
      begin
        ss := Round((max - cur) / max) * step;
        m_nRx := m_nCurrX + ss;
        if ss = step then
          m_nShiftX := -Round(unx / max * cur)
        else
          m_nShiftX := Round(unx / max * (max - cur));
        m_nShiftY := 0;
      end;

    DR_UPRIGHT:
      begin
        if max >= 6 then //这里应该是对图像帧数微调
          v := 2
        else
          v := 0;
        ss := Round((max - cur + v) / max) * step;
        m_nRx := m_nCurrX - ss;
        m_nRy := m_nCurrY + ss;
        if ss = step then
        begin
          m_nShiftX := Round(unx / max * cur);
          m_nShiftY := -Round(uny / max * cur);
        end
        else
        begin
          m_nShiftX := -Round(unx / max * (max - cur));
          m_nShiftY := Round(uny / max * (max - cur));
        end;
      end;

    DR_DOWNRIGHT:
      begin
        if max >= 6 then
          v := 2
        else
          v := 0;
        ss := Round((max - cur - v) / max) * step;
        m_nRx := m_nCurrX - ss;
        m_nRy := m_nCurrY - ss;
        if ss = step then
        begin
          m_nShiftX := Round(unx / max * cur);
          m_nShiftY := Round(uny / max * cur);
        end
        else
        begin
          m_nShiftX := -Round(unx / max * (max - cur));
          m_nShiftY := -Round(uny / max * (max - cur));
        end;
      end;

    DR_DOWNLEFT:
      begin
        if max >= 6 then
          v := 2
        else
          v := 0;
        ss := Round((max - cur - v) / max) * step;
        m_nRx := m_nCurrX + ss;
        m_nRy := m_nCurrY - ss;
        if ss = step then
        begin
          m_nShiftX := -Round(unx / max * cur);
          m_nShiftY := Round(uny / max * cur);
        end
        else
        begin
          m_nShiftX := Round(unx / max * (max - cur));
          m_nShiftY := -Round(uny / max * (max - cur));
        end;
      end;

    DR_UPLEFT:
      begin
        if max >= 6 then
          v := 2
        else
          v := 0;
        ss := Round((max - cur + v) / max) * step;
        m_nRx := m_nCurrX + ss;
        m_nRy := m_nCurrY + ss;
        if ss = step then
        begin
          m_nShiftX := -Round(unx / max * cur);
          m_nShiftY := -Round(uny / max * cur);
        end
        else
        begin
          m_nShiftX := Round(unx / max * (max - cur));
          m_nShiftY := Round(uny / max * (max - cur));
        end;
      end;

  end;

end;

procedure TActor.Run;
var
  prv: integer;

begin

  if (m_nCurrentAction = ActWalk) or
    (m_nCurrentAction = ActRun) or
    (m_nCurrentAction = ActRushLeft) or
    (m_nCurrentAction = ActRushRight) then
    Exit;

  prv := m_nCurrentFrame;
  if (m_nCurrentFrame < m_nStartFrame) or (m_nCurrentFrame > m_nEndFrame) then
    m_nCurrentFrame := m_nStartFrame;

  if GetTickCount - m_dwStartTime > m_dwFrameTime then //帧时间到
  begin
    if m_nCurrentFrame < m_nEndFrame then
    begin
      if m_boUseMagic then
      begin
        if (m_nCurEffFrame = m_nSpellFrame - 2) then //定到最后一帧似乎效果好点?
        begin
          Inc(m_nCurrentFrame);
          Inc(m_nCurEffFrame);
          m_dwStartTime := GetTickCount;
        end
        else
        begin
          if m_nCurrentFrame < m_nEndFrame - 1 then
            //定在倒数第二帧,等待效果帧上来
            Inc(m_nCurrentFrame);
          Inc(m_nCurEffFrame);
          m_dwStartTime := GetTickCount;
        end;

      end
      else
      begin

        Inc(m_nCurrentFrame); //增加帧
        m_dwStartTime := GetTickCount;
      end;

    end
    else //到行为动作的尾帧
    begin

      begin

        // m_nCurrentFrame := m_nStartFrame;
        // m_dwStartTime := GetTickCount;
      end;

    end;
  end;

  if m_boUseMagic then
  begin
    if m_nCurEffFrame = m_nSpellFrame - 1 then //魔法起手式到最后一帧了
    begin
      if m_CurMagic.ServerMagicCode > 0 then
      begin
        with m_CurMagic do
          MagicEff1 := TMagicEff.Create(ServerMagicCode,
            EffectNumber,
            m_nCurrX * UNITX, m_nCurrY * UNITY,
            TargX * UNITX, TargY * UNITY,
            EffectType,
            Recusion,
            AniTime);
        form1.MemoResult.Text := ' MagicEff1  ';
      end;

      m_CurMagic.ServerMagicCode := 0;
    end;

  end;

  if prv <> m_nCurrentFrame then
  begin
    // m_dwLoadSurfaceTime := GetTickCount;
    LoadSurface;
  end;
end;

procedure TActor.LoadSurface;

begin
  m_BodySurface := g_WHumImgImages.GetCachedImage(HUMANFRAME * m_btDress
    +
    m_nCurrentFrame, m_nPx, m_nPy);

  if m_nHairOffset >= 0 then
    m_HairSurface := g_WHairImgImages.GetCachedImage(m_nHairOffset +
      m_nCurrentFrame, m_nHairPx, m_nHairPy)
  else
    m_HairSurface := nil;

  m_WeaponSurface := g_WWeaponImages.GetCachedImage(HUMANFRAME * (m_btWeapon * 2
    +
    m_btSex) +
    m_nCurrentFrame, m_nWeaponPx, m_nWeaponPy);
end;

procedure TActor.DrawChr(dsurface: TDirectDrawSurface; dx, dy: integer);
var
  idx, ax, ay: integer;
  d: TDirectDrawSurface;

  wimg: TWILImages;
begin
  if (m_nCurrentFrame >= 0) and (m_nCurrentFrame <= 599) then
    m_nWpord := WORDER[m_btSex, m_nCurrentFrame];

  if (m_nWpord = 0) and (m_WeaponSurface <> nil) then //武器在身体后
    dsurface.Draw(dx + m_nWeaponPx, dy + m_nWeaponPy,
      m_WeaponSurface.ClientRect,
      m_WeaponSurface, True);

  if m_BodySurface <> nil then
    dsurface.Draw(dx + m_nPx, dy + m_nPy, m_BodySurface.ClientRect,
      m_BodySurface, True);

  if m_HairSurface <> nil then
    dsurface.Draw(dx + m_nHairPx, dy + m_nHairPy, m_HairSurface.ClientRect,
      m_HairSurface, True);

  if (m_nWpord = 1) and (m_WeaponSurface <> nil) then //武器在身体前
    dsurface.Draw(dx + m_nWeaponPx, dy + m_nWeaponPy,
      m_WeaponSurface.ClientRect,
      m_WeaponSurface, True);

  //刀光效果
  if m_boHitEffect and (m_nHitEffectNumber > 0) then
  begin
    form1.GetEffectBase(m_nHitEffectNumber - 1, 1, wimg, idx);
    idx := idx + m_btDir * 10 + (m_nCurrentFrame - m_nStartFrame);
    if wimg <> nil then
      d := wimg.GetCachedImage(idx, ax, ay);
    if d <> nil then

      dsurface.Drawadd(Rect(dx + ax, dy + ay, dx + ax + d.Width, dy + ay +
        d.Height),
        d.ClientRect,
        d, True, 255);
  end;

  //施法效果?
  if m_boUseMagic and (m_CurMagic.EffectNumber > 0) then
  begin
    if m_nCurEffFrame in [0..m_nSpellFrame - 1] then
    begin

      form1.GetEffectBase(m_CurMagic.EffectNumber - 1, 0, wimg, idx);
      idx := idx + m_nCurEffFrame;
      if wimg <> nil then
        d := wimg.GetCachedImage(idx, ax, ay);
      if d <> nil then

        dsurface.Drawadd(Rect(dx + ax, dy + ay, dx + ax + d.Width, dy + ay +
          d.Height),
          d.ClientRect,
          d, True, 255);
    end;
  end;

end;

constructor TPlayScene.Create;
begin
  ActorList := TList.Create;
  EffectList := TList.Create;
end;

destructor TPlayScene.Destroy;
begin
  ActorList.Free;
  EffectList.Free;
  inherited Destroy;
end;

function TPlayScene.NewActor(chrid, cx, cy, cdir, dress, hair, weapon: Integer;
  action: TAction): TActor;
var
  i: Integer;
  actor: TActor;
begin
  Result := nil;
  for i := 0 to ActorList.Count - 1 do
    if TActor(ActorList[i]).RecogId = chrid then
    begin
      Result := TActor(ActorList[i]);
      Exit;
    end;
  actor := TActor.Create;

  with actor do
  begin
    RecogId := chrid;
    m_nCurrX := cx;
    m_nCurrY := cy;
    m_nRx := m_nCurrX;
    m_nRy := m_nCurrY;
    m_btDir := Byte(cdir);
    m_btDress := Byte(dress);
    m_btHair := Byte(hair);
    m_btWeapon := Byte(weapon);
    m_nCurrentAction := action;
    m_btSex := m_btDress mod 2;
    m_btHair := (m_btHair + 1) * 2 + m_btSex;
  end;

  ActorList.Add(actor);
  Result := actor;
end;

procedure TPlayScene.PlayScene(MSurface: TDirectDrawSurface);
var
  i, j: Integer;
  actor: TActor;
begin

  i := 0;
  while True do
  begin
    if i >= ActorList.Count then
      Break;
    actor := ActorList[i];

    if actor.Move(1) then
    begin
      Inc(i);
      Continue;
    end;
    actor.Run;
    Inc(i)
  end;

  for j := 0 to 19 do
  begin
    for i := 0 to ActorList.Count - 1 do
    begin
      actor := ActorList[i];
      if j = actor.m_nRy then
        actor.DrawChr(MSurface,
          actor.m_nRx * UNITX + actor.m_nShiftX,
          actor.m_nRy * UNITY + actor.m_nShiftY);
    end;
  end;

  if MagicEff1 <> nil then
  begin
    MagicEff1.Run;
    MagicEff1.DrawEff(MSurface);
  end;
end;

procedure TForm1.ButtonStopClick(Sender: TObject);
var
  i: Integer;
begin
  TimerShow.Enabled := False;

  for i := PlayScene.ActorList.Count - 1 downto 0 do
  begin
    TActor(PlayScene.ActorList[i]).Destroy;
    PlayScene.ActorList.Delete(i);
  end;

end;

procedure TForm1.GetEffectBase(mag, mtype: integer; var wimg: TWILImages; var
  idx:
  integer);
begin
  wimg := nil;
  idx := 0;
  case mtype of
    1:
      begin
        wimg := g_WMagicImages;
        idx := HitEffectBase[mag];
      end;

    0:
      begin
        case mag of
          8, 27:
            begin

              wimg := g_WMagic2Images; //Magic2.wil
              if mag in [0..30] then
                idx := EffectBase[mag];
            end;
        else
          begin
            wimg := g_WMagicImages;
            if mag in [0..30] then
              idx := EffectBase[mag];
          end;

        end;
      end;
  end;
end;

procedure TMagicEff.GetFlyXY(ms: Integer; var fx, fy: integer);
begin

end;

constructor TMagicEff.Create(id, effnum, sx, sy, tx, ty: Integer; mtype:
  TMagicType;
  Recusion: Boolean; anitime: Integer);
var
  tax, tay: Integer;
begin

  case mtype of
    mtReady:
      begin

      end;
    mtFly, mtBujaukGroundEffect, mtExploBujauk:
      begin
        Start := 0;
        Frame := 6;
        CurFrame := Start;
        FixedEffect := False;
        Repetition := Recusion;
        ExplosionFrame := 10;
      end;
    mt12:
      begin
        start := 0;
        Frame := 6;
        CurFrame := Start;
        FixedEffect := False;
        Repetition := Recusion;
        ExplosionFrame := 1;
      end;
    mtExplosion, mtThuder, mtLightingThunder:
      begin
        start := 0;
        Frame := -1;
        CurFrame := Start;
        FixedEffect := True;
        Repetition := False;
        ExplosionFrame := 10;
      end;

    mtFlyAxe:
      begin
        start := 0;
        Frame := 3;
        CurFrame := Start;
        FixedEffect := False;
        Repetition := Recusion;
        ExplosionFrame := 3;
      end;

    mtFlyarrow:
      begin
        start := 0;
        Frame := 1;
        CurFrame := Start;
        FixedEffect := False;
        Repetition := Recusion;
        ExplosionFrame := 1;
      end;

  end;

  ServerMagicId := id;
  TargerActor := nil;
  if effnum > 0 then
    form1.GetEffectBase(effnum - 1, 0, ImgLib, EffectBase);
  // ImgLib := g_WMagicImages;
  // EffectBase := effnum; //传递过来的参数
  TargetX := tx;
  TargetY := ty;

  fireX := sx;
  fireY := sy;

  OldFlyX := sx;
  OldFlyY := sy;
  FlyX := sx;
  FlyY := sy;
  FlyXf := sx;
  FlyYf := sy;

  MagExplionBase := EffectBase + EXPLOSIONBASE;

  Light := 1;

  if fireX <> TargetX then
    tax := Abs(TargetX - fireX)
  else
    tax := 1;

  if fireY <> TargetY then
    tay := Abs(TargetY - fireY)
  else
    tay := 1;

  if Abs(fireX - TargetX) > Abs(fireY - TargetY) then
  begin
    firedisX := Round((TargetX - fireX) * (500 / tax));
    firedisY := Round((TargetY - fireY) * (500 / tax));
  end
  else
  begin
    firedisX := Round((TargetX - fireX) * (500 / tay));
    firedisY := Round((TargetY - fireY) * (500 / tay));
  end;

  NextFrameTime := 80;
  m_dwFrameTime := GetTickCount; //建立的帧时间点,
  M_dwStartTime := GetTickCount;
  steptime := GetTickCount;
  repeattime := anitime;

  Dir16 := GetFlyDirection16(sx, sy, tx, ty);
  OldDir16 := Dir16;
  NextEffect := nil;
  m_boActive := True;
  prevdisX := 99999;
  prevdisY := 99999;

end;

destructor TMagicEff.Destroy;
begin
  inherited Destroy;
end;

function TMagicEff.Run: Boolean;
begin
  Result := Shift;
  if Result then
    if GetTickCount - M_dwStartTime > 10000 then //魔法效果超时
      Result := False //运行失败
    else
      Result := True;
end;

function TMagicEff.Shift: Boolean;
  function OverThrough(olddir, newdir: Integer): Boolean;
  begin
    Result := False;
    if Abs(olddir - newdir) >= 2 then
    begin
      Result := True;
      if ((olddir = 0) and (newdir = 15)) or ((olddir = 15) and (newdir = 0))
        then
        Result := False;
    end;
  end;
var
  i, rrx, rry, ms, stepx, stepy, newstepx, newstepy, nn: Integer;
  tax, tay, shx, shy, passdir16: Integer;
  stepxf, stepyf: Real;
  crash: Boolean;
begin
  Result := True;
  if Repetition then
  begin
    if GetTickCount - steptime > LongWord(NextFrameTime) then
    begin
      steptime := GetTickCount;
      Inc(CurFrame);
      if CurFrame > Start + Frame - 1 then
        CurFrame := Start; //重复模式,回到开始帧图
    end;

  end
  else
  begin
    if (Frame > 0) and (GetTickCount - steptime > LongWord(NextFrameTime)) then
    begin
      steptime := GetTickCount;
      Inc(CurFrame);
      if CurFrame > Start + Frame - 1 then
      begin
        CurFrame := Start + Frame - 1; //不重复模式,定在最后一帧
        Result := False; //修改返回标志。
      end;
    end;
  end;

  if (not FixedEffect) then //不修正效果,其实是飞行中的效果
  begin
    crash := False;

    begin
      ms := GetTickCount - m_dwFrameTime;
      m_dwFrameTime := GetTickCount;

      if FlyX <> TargetX then
        tax := Abs(TargetX - FlyX)
      else
        tax := 1;
      if FlyY <> TargetY then
        tay := Abs(TargetY - FlyY)
      else
        tay := 1;

      if Abs(FlyX - TargetX) > Abs(FlyY - TargetY) then
      begin
        newfiredisX := Round((TargetX - FlyX) * (500 / tax));
        newfiredisY := Round((TargetY - FlyY) * (500 / tax));
      end
      else
      begin
        newfiredisX := Round((TargetX - FlyX) * (500 / tay));
        newfiredisY := Round((TargetY - FlyY) * (500 / tay));
      end;

      if firedisX < newfiredisX then
        firedisX := firedisX + _MAX(1, (newfiredisX - firedisX) div 10);
      if firedisX > newfiredisX then
        firedisX := firedisX - _MAX(1, (firedisX - newfiredisX) div 10);
      if firedisY < newfiredisY then
        firedisY := firedisY + _MAX(1, (newfiredisY - firedisY) div 10);
      if firedisY > newfiredisY then
        firedisY := firedisY - _MAX(1, (firedisY - newfiredisY) div 10);

      stepxf := (firedisX / 700) * ms;
      stepyf := (firedisY / 700) * ms;
      FlyXf := FlyXf + stepxf;
      FlyYf := FlyYf + stepyf;
      FlyX := Round(FlyXf);
      FlyY := Round(FlyYf);

      OldFlyX := FlyX;
      OldFlyY := FlyY;

      passdir16 := GetFlyDirection16(FlyX, FlyY, TargetX, TargetY);

      if ((Abs(TargetX - FlyX) <= 15) and (Abs(TargetY - FlyY) <= 15)) or
        ((Abs(TargetX - FlyX) >= prevdisX) and (Abs(TargetY - FlyY) >=
        prevdisY))
        or OverThrough(OldDir16, passdir16) then
      begin
        crash := True;
        form1.MemoResult.Text := ' crash := True';
      end
      else
      begin
        prevdisX := Abs(TargetX - flyx);
        prevdisY := Abs(TargetY - FlyY);
      end;
      OldDir16 := passdir16;

    end;

    if crash then
    begin
      FixedEffect := True;
      Start := 0;
      Frame := ExplosionFrame;
      CurFrame := Start;
      Repetition := False;
    end;
  end;

  if FixedEffect then
  begin
    if Frame = -1 then
      Frame := ExplosionFrame;

    FlyX := TargetX;
    FlyY := TargetY;

  end;

end;

procedure TMagicEff.DrawEff(surface: TDirectDrawSurface);
var
  img: Integer;
  d: TDirectDrawSurface;
  shx, shy: Integer;
begin
  if m_boActive and ((Abs(FlyX - fireX) > 15) or (Abs(FlyY - fireY) > 15) or
    FixedEffect) then
  begin

    if not FixedEffect then
    begin //飞行动画
      img := EffectBase + FLYBASE + Dir16 * 10;
      d := ImgLib.GetCachedImage(img + CurFrame, px, py);
      if d <> nil then
      begin
        // surface.Draw(FlyX + px, FlyY + py, d.ClientRect, d, True);
        surface.Drawadd(
          Rect(FlyX + px, FlyY + py, FlyX + px + d.Width, FlyY + py + d.Height),
          d.ClientRect,
          d, True, 255);
      end;
    end
    else
    begin //爆炸动画
      img := MagExplionBase + CurFrame;
      d := ImgLib.GetCachedImage(img, px, py);
      if d <> nil then
      begin
        // surface.Draw(FlyX + px, FlyX + py, d.ClientRect, d, True);
        surface.Drawadd(
          Rect(FlyX + px, FlyY + py, FlyX + px + d.Width, FlyY + py + d.Height),
          d.ClientRect,
          d, True, 255);
      end;

    end;
  end;
end;

end.

小结:

1,用Tlist做角色类的列表,进行增加,删除操作。

     列表全部删除需要从尾部开始删除,否则报错。

2,角色的坐标选择用了一个随机不重复的选择,网上查的算法,算法要点是用了一个最大数数组进行标记。

3,X,Y 行列坐标的算法, 列 模 最大列,为余数。行 整除 最大列,为倍数。

4,随机数前要初始化,否则每次随机结果一致。

下一步,

1,调试还是没有学习,需要进行学习。

2,这个用的SURFACE.DRAWADD显示20个角色就已经开始卡顿了,

     问题在那里?

     需要对绘图进行调整,用BLT?

 

posted @ 2025-08-21 11:13  D7mir  阅读(5)  评论(0)    收藏  举报