|
[传奇技术]mir2res人物或怪物移动
mir2res优秀的地方之一:精灵移动
尽管有很多人说它是拉几,但我从来都相信mir2从coderes到picres都是一个优秀的游戏,超越同类mmrpg很多,下面谈谈它的一个方面
:精灵移动
因为对这个的讨论涉及到地图格及地图单元,先在头脑中想象一下地图格,这里不打算讨论地图单元
这里仅讨论actor.pas中跟动作有关的函数,,验证它的优越之处,,
现在开始,,下面是从mir2res中提取的源程序片断,,正是它们构成了精灵移动的基础
- {------------------------------------------------------------------------------}
- // 常量定义
- {------------------------------------------------------------------------------}
- const
- MAX_HUMANFRAME = 600; // 人类动画总帧数 [0..599]
- MAX_HAIR = 3; // 头发种类数 [0..2]
- MAX_WEAPON = 34; // 武器种类数 [0..34]
-
- {------------------------------------------------------------------------------}
- // 数据结构定义
- {------------------------------------------------------------------------------}
- type
- // 动作定义
- PActionInfo = ^TActionInfo;
- TActionInfo = record
- start : word; // 开始帧
- frame : word; // 帧数
- skip : word; // 跳过的帧数
- ftime : word; // 每帧的延迟时间(毫秒)
- end;
- // 玩家的动作定义
- PHumanAction = ^THumanAction;
- THumanAction = record
- ActStand : TActionInfo; //1
- ActWalk : TActionInfo; //8
- ActRun : TActionInfo; //8
- ActRushLeft : TActionInfo;
- ActRushRight : TActionInfo;
- ActWarMode : TActionInfo; //1
- ActHit : TActionInfo; //6
- ActHeavyHit : TActionInfo; //6
- ActBigHit : TActionInfo; //6
- ActFireHitReady: TActionInfo; //6
- ActSpell : TActionInfo; //6
- ActSitdown : TActionInfo; //1
- ActStruck : TActionInfo; //3
- ActDie : TActionInfo; //4
- end;
- {------------------------------------------------------------------------------}
- // TActor class 精灵类定义
- {------------------------------------------------------------------------------}
- TActor = class(TObject)
- protected
- FrameCount : Word; // 当前动作的总帧数
- FrameStart : Word; // 当前动作的开始帧索引
- FrameEnd : Word; // 当前动作的结束帧索引
- FrameTime : Word; // 当前动作每帧等待的时间
- FrameIndex : Word; // 当前帧索引
- FrameTick : Cardinal; // 当前帧显示时的 GetTickCount
- public
- CurrentMap : TMirMap; // 当前人物所在地图
- CurrentAction : Byte; // 当前动作
- Direction : Byte; // 当前方向
- Appearance : Word; // 外观显示(对 HumanActor 则相当于级别,初级,高级,,中级,,最高级-顶级)
- MapX : Word; // 处于地图上的位置(以 MapPoint 为单位)
- MapY : Word;
- ShiftX : Integer; // 当前位移(以像素为单位, 用于 Walk, Run)
- ShiftY : Integer;
- MovX : Integer; // 上次 Walk, Run 的偏移值,,
- MovY : Integer;
- constructor Create(Map: TMirMap); virtual; abstract; //需要子类的重载
- // 重新计算动画帧
- procedure ReCalcFrames; virtual; abstract;
- // 根据经过的时间处理下一帧
- procedure ProcessFrame; virtual; abstract;
- end;
- {------------------------------------------------------------------------------}
- // THumanActor class 角色精灵类定义
- {------------------------------------------------------------------------------}
- THumanActor = class(TActor)
- private
- protected
- BodyOffset : Word; // 身体图片索引的主偏移
- HairOffset : Word; // 头发图片索引的主偏移
- WeaponOffset : Word; // 武器图片索引的主偏移
- WeaponOrder : Byte; // 武器绘制顺序(是否先于身体绘制)
- public
- Sex : Byte; // 性别
- Job : Byte; // 职业
- Hair : Byte; // 发型
- Weapon : Byte; // 武器
- constructor Create(Map: TMirMap); override; //重载
- procedure ReCalcFrames; override;
- procedure ProcessFrame; override;
- procedure Draw(Surface: IDirectDrawSurface7; X, Y, Width, Height: Integer);
- function CalcNextDirection: Boolean;
- // 移动至 MapPoint, 虽然 MapPoint 坐标定义为 Word, 这里必须用 Integer 代替
- // 因为玩家可以点击至 Map 坐标负方向进行转向
- procedure Walk(X, Y: Integer);
- procedure Run(X, Y: Integer);
- procedure Hit(X, Y: Integer);
- end;
- const
- {------------------------------------------------------------------------------}
- // 人物动作图片索引
- {------------------------------------------------------------------------------}
- // 以下二项数据组成 9 * 2 * 600 = 10800 幅图片
- // Appearance = [0..8] [没穿衣服/初级/中级/高级(武/法/道)/最高级(武/法/道)]
- // Sex = [0..1] [男/女]
- // 每个 Appearance 包含 14 种 Action
- // 不同 Direction 的 Action = Action 的起始帧 * 8 * Direction
- // Action = [0 - 13] (Action 数量与总帧数无关, 并非每个 Action 都 8 帧)
- // Direction = [0 - 7]
- HUMANACTION_STAND = 0;
- HUMANACTION_WALK = 1;
- HUMANACTION_RUN = 2;
- HUMANACTION_RUSHLEFT = 3;
- HUMANACTION_RUSHRIGHT = 4;
- HUMANACTION_WARMODE = 5;
- HUMANACTION_HIT = 6;
- HUMANACTION_HEAVYHIT = 7;
- HUMANACTION_BIGHIT = 8;
- HUMANACTION_FIREHITREADY = 9;
- HUMANACTION_SPELL = 10;
- HUMANACTION_SITDOWN = 11;
- HUMANACTION_STRUCK = 12;
- HUMANACTION_DIE = 13;
- HUMANACTIONS: THumanAction =
- (
- // 开始帧 有效帧 跳过帧 每帧延迟(每帧经过的时间,单位:毫秒)
- ActStand: (start: 0; frame: 4; skip: 4; ftime: 200);
- ActWalk: (start: 64; frame: 6; skip: 2; ftime: 80);
- ActRun: (start: 128; frame: 6; skip: 2; ftime: 90);
- ActRushLeft: (start: 128; frame: 3; skip: 5; ftime: 120);
- ActRushRight: (start: 131; frame: 3; skip: 5; ftime: 120);
- ActWarMode: (start: 192; frame: 1; skip: 0; ftime: 200);
- ActHit: (start: 200; frame: 6; skip: 2; ftime: 85);
- ActHeavyHit: (start: 264; frame: 6; skip: 2; ftime: 90);
- ActBigHit: (start: 328; frame: 8; skip: 0; ftime: 70);
- ActFireHitReady: (start: 192; frame: 6; skip: 4; ftime: 70);
- ActSpell: (start: 392; frame: 6; skip: 2; ftime: 60);
- ActSitdown: (start: 456; frame: 2; skip: 0; ftime: 300);
- ActStruck: (start: 472; frame: 3; skip: 5; ftime: 70);
- ActDie: (start: 536; frame: 4; skip: 4; ftime: 120);
- );
- {------------------------------------------------------------------------------}
- // 武器绘制顺序 (是否先于身体绘制: 0是/1否)
- // WEAPONORDERS: array [Sex, FrameIndex] of Byte
- {------------------------------------------------------------------------------}
- WEAPONORDERS: array[0..1, 0..MAX_HUMANFRAME - 1] of Byte =
- (
- (
- //
- 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,
- //
- 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,
- //
- 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,
- //
- 0,1,1,1,0,0,0,0,
- //
- 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,
- //
- 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,
- //
- 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,
- //
- 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,
- //
- 0,0,1,0,1,1,1,1, 1,1,0,0,0,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,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,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
- ),
- //以上为男600,,下面开始女600
- (
- //
- 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,
- //
- 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,
- //
- 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,
- //
- 1,1,1,1,0,0,0,0,
- //
- 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,
- //
- 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,
- //
- 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,
- //
- 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,
- //
- 0,0,1,0,1,1,1,1, 1,1,0,0,0,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,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,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
- )
- );
- implementation
- { THumanActor }
- procedure THumanActor.Draw(Surface: IDirectDrawSurface7; X, Y, Width, Height: Integer);
- var
- Index: Word;
- begin
- // 绘制武器,允许的范围 [0..33] (WeaponOrder = 0)
- if (WeaponOrder = 0) and (Weapon > 0) and (Weapon < MAX_WEAPON) then
- G_WilWeapon.DrawEx(WeaponOffset + FrameIndex, Surface, X, Y,
- CLIENT_WIDTH, CLIENT_HEIGHT, True);
- // 绘制身体
- G_WilHuman.DrawEx(BodyOffset + FrameIndex, Surface, X, Y,
- CLIENT_WIDTH, CLIENT_HEIGHT, True);
- // 绘制头发,允许的范围 [0..2]
- if (Hair > 0) and (Hair < MAX_HAIR) then
- G_WilHair.DrawEx(HairOffset + FrameIndex, Surface, X, Y,
- CLIENT_WIDTH, CLIENT_HEIGHT, True);
- // 绘制武器,允许的范围 [0..33] (WeaponOrder = 1)
- if (WeaponOrder = 1) and (Weapon > 0) and (Weapon < MAX_WEAPON) then
- G_WilWeapon.DrawEx(WeaponOffset + FrameIndex, Surface, X, Y,
- CLIENT_WIDTH, CLIENT_HEIGHT, True);
- end;
- procedure THumanActor.ProcessFrame;
- var
- CurrTick: Cardinal;
- NewIndex: Integer; //重要的是把握它的实际用意,,下面会谈到
- begin
- inherited;
- CurrTick := GetTickCount;
- case CurrentAction of //这里计算shiftx,,y,,注意,这里只是计算,,而不实际实现人物在地图上的位移效果,
- //shiftx,,y是地图单元用的,,精灵移动好像根本不用到它,,故下面几行不讨论
- HUMANACTION_WALK:
- begin
- ShiftX := MovX * MAPUNIT_WIDTH * Integer((CurrTick - FrameTick)) div (FrameTime * FrameCount);
- ShiftY := MovY * MAPUNIT_HEIGHT * Integer((CurrTick - FrameTick)) div (FrameTime * FrameCount);
- end;
- HUMANACTION_RUN:
- begin
- ShiftX := MovX * 2 * MAPUNIT_WIDTH * Integer((CurrTick - FrameTick)) div (FrameTime * FrameCount);
- ShiftY := MovY * 2 * MAPUNIT_HEIGHT * Integer((CurrTick - FrameTick)) div (FrameTime * FrameCount);
- end;
- end;
- //ProcessFrame对精灵移动的实际作用真正从下面这行开始
- NewIndex := FrameStart + (CurrTick - FrameTick) div (FrameTime); //经过的时间除以每帧经过的时间,,就可以得出理论上应该过多少帧
- if NewIndex = FrameIndex then Exit; // 判断是否需要计算帧,如果理论与实际相符,此函数不发挥作用,如果不符,就要经过这个函数的作用作一点处理
- FrameIndex := NewIndex; //处理的第一步:把frameindex拉回正确位置,,为什么要这么做:mir2是一个网络游戏,由于本地和网络的延迟,,
- // TODO: 可能 GetTickCount 会在 49 天内循环回来,,mir2的B/S模型中,gettickcount是本地的计算(毫秒级的timer)而不是服务端的计算
- if FrameIndex < FrameStart then FrameIndex := FrameStart; //处理的第二步,,注意:在这之前frameindex经过了frameindex=newindex的作用,不是原来的frameindex了,
- if FrameIndex > FrameEnd then
- begin
- case CurrentAction of
- HUMANACTION_WALK:
- begin
- Inc(MapX, MovX);
- Inc(MapY, MovY);
- end;
- HUMANACTION_RUN:
- begin
- Inc(MapX, MovX * 2); //inc,,按movx*2递增mapx
- Inc(MapY, MovY * 2);
- end;
- end;
- CurrentAction := HUMANACTION_STAND; //最终的动作总是停下来
- ReCalcFrames; //停下来就是动作改变,就要重新计算帧,,,等待下一次的processframe过程
- end;
- // 计算武器绘制顺序
- WeaponOrder := WEAPONORDERS[Sex, FrameIndex];
- end;
- constructor THumanActor.Create(Map: TMirMap);
- begin
- inherited; //继承父类TActor的create过程
- Appearance := 7;
- Job := 1;
- Sex := 1;
- Hair := 2;
- Direction := 5;
- Weapon := 31;
- CurrentAction := HUMANACTION_STAND; //一开始被create出来,,动作当然是stand
- MapX := 300;
- MapY := 300;
- end;
- procedure THumanActor.ReCalcFrames;
- var
- InfoPtr: PActionInfo;
- begin
- inherited;
- case CurrentAction of //每一个动作额定对应一个系列的动作图片(开始于多少帧,每帧多少)及图片信息(如每帧持久多少)
- //这个可以说是所有属性的重置,,重置工作的初始过程:为infoprt这个指针变量赋值
- 0: InfoPtr := @HUMANACTIONS.ActStand;
- 1: InfoPtr := @HUMANACTIONS.ActWalk;
- 2: InfoPtr := @HUMANACTIONS.ActRun;
- 3: InfoPtr := @HUMANACTIONS.ActRushLeft;
- 4: InfoPtr := @HUMANACTIONS.ActRushRight;
- 5: InfoPtr := @HUMANACTIONS.ActWarMode;
- 6: InfoPtr := @HUMANACTIONS.ActHit;
- 7: InfoPtr := @HUMANACTIONS.ActHeavyHit;
- 8: InfoPtr := @HUMANACTIONS.ActBigHit;
- 9: InfoPtr := @HUMANACTIONS.ActFireHitReady;
- 10: InfoPtr := @HUMANACTIONS.ActSpell;
- 11: InfoPtr := @HUMANACTIONS.ActSitdown;
- 12: InfoPtr := @HUMANACTIONS.ActStruck;
- 13: InfoPtr := @HUMANACTIONS.ActDie;
- else
- raise Exception.CreateFmt('Unknown Human Action : %d', [CurrentAction]);
- end;
- // 身体图片偏移值
- BodyOffset := MAX_HUMANFRAME * (Appearance * 2 + Sex) + Direction * 8;
- // 头发图片偏移值
- if (Hair > 0) and (Hair < MAX_HAIR) then
- HairOffset := MAX_HUMANFRAME * (Hair * 2 + Sex) + Direction * 8;
- // 武器图片偏移值
- if (Weapon > 0) and (Weapon < MAX_WEAPON) then
- WeaponOffset := MAX_HUMANFRAME * (Weapon * 2 + Sex) + Direction * 8;
- //为infoprt赋值后这里就是具体的重置过程了
- FrameCount := InfoPtr^.frame;
- FrameStart := InfoPtr^.start;
- FrameEnd := FrameStart + FrameCount - 1; //这是什么用意,,最后一帧为什么不显示?
- FrameTime := InfoPtr^.ftime;
- FrameIndex := FrameStart; //从头开始,,注意frameindex,是thumactor的成员
- FrameTick := GetTickCount;
- ShiftX := 0; //x,,y上的位移都置0,,跟movx,,,movy有关,在procseeframe中
- ShiftY := 0; //
- end;
- function THumanActor.CalcNextDirection: Boolean; //计算下一个方向为什么要返回boolean??walk(),run()中会看到作判断用
- var
- NewDir: Byte;
- begin //这里比较容易理解吧:坐标系统跟数学坐标不一样
- if (MovX = -1) and (MovY = -1) then NewDir := DIR_UPLEFT else
- if (MovX = -1) and (MovY = 0) then NewDir := DIR_LEFT else
- if (MovX = -1) and (MovY = 1) then NewDir := DIR_DOWNLEFT else
- if (MovX = 0) and (MovY = -1) then NewDir := DIR_UP else
- if (MovX = 0) and (MovY = 1) then NewDir := DIR_DOWN else
- if (MovX = 1) and (MovY = -1) then NewDir := DIR_UPRIGHT else
- if (MovX = 1) and (MovY = 0) then NewDir := DIR_RIGHT else
- if (MovX = 1) and (MovY = 1) then NewDir := DIR_DOWNRIGHT else
- raise Exception.Create('CalcNextDirection');
- Result := NewDir <> Direction; //比较计算出的新方向与当前方向,,看是不是相等,,到此为止实际上函数的作用已经完成了,但是还要加入一个附加处理
- if Result then Direction := NewDir; //附加处理:如果不等(为真),,那么置当前dir为newdir
- end;
- procedure THumanActor.Walk(X, Y: Integer); //x,,y为目标位置
- begin
- if CurrentAction <> HUMANACTION_STAND then Exit; //走之前一定要是站立状态
- MovX := Min(1, Max(-1, X - MapX)); //movx,,movy是上次 Walk, Run Action 的偏移值,这个语句值得深究,我们来推导一下
- if min(1,max())= 取max then,,max只能取0,,负数,,因此在max内部,,要么为0,不能是-1(为0时,此时x-mapx=-1,x=mapx-1),,要么为负(此时x-mapx<-1,,x<mapx-1)
- 也即x<=mapx-1
- 实际意义就是用户点了(这里只讨论x方向)人物当前x坐标前一个方向
-
- if min(1,max())= 取1 then, , max内部只能取2,,或2以上(max不能是1),,因此x-mapx是,,即x>=mapx+2,,此时x在水平方向总是要比mapx大二个或二个地图格以上
-
- 即(实际意义):用户在水平向上点击了比mapx大二个或二个的地图格以上的地图位置,,此时movx被计算出来,为>=2
-
- 以上讨论水平方向,这里讨论垂直方向,二个方向共同作用,,确定movx,movy,,注意到在上面的过程中,min()只能取1,,或>=2的数值max(),,
- 下面讨论竖直方向的情况,同一个道理
- MovY := Min(1, Max(-1, Y - MapY));
- 三种情况,,,1,,y=mapy 2,,y<mapy 3,,y>=mapy+2
- 设想一下,y仅仅>mapy,,而不规定y>=mapy+2时,比如y=mapy+1时也就是用户点击人物当前位置竖直方向再往下一个伴置,此时
- y>mapy,,但y不>=mapy+2,(至少要3个地图格),此时不满足上面三种情况的任何一种情况
- if (MovX = 0) and (MovY = 0) then Exit; 用户点了站立的位置,,相当于不走,exit,,即walk()函数不发挥作用
- if CalcNextDirection then ReCalcFrames; //如果方向改变了,,那么也要重新计算帧
- if not CurrentMap.CanMove(MapX + MovX, MapY + MovY) then Exit; //如果地图不能走当然也就不能继续walk()了
- CurrentAction := HUMANACTION_WALK;
- ReCalcFrames; //动作由站立改为走也要重新计算帧,,也就是说,,recalcframes,,,的影响因素有二个1,动作,,2方向
- end;
-
- procedure THumanActor.Run(X, Y: Integer); x,,y为目标位置
- begin
- if CurrentAction <> HUMANACTION_STAND then Exit; //跑之前一定要是站立状态
- MovX := Min(1, Max(-1, X - MapX));
- MovY := Min(1, Max(-1, Y - MapY));
- if (MovX = 0) and (MovY = 0) then Exit; //用户点了站立的位置,,相当于不跑
- if CalcNextDirection then ReCalcFrames;
- if not CurrentMap.CanMove(MapX + MovX, MapY + MovY) then Exit;
- if not CurrentMap.CanMove(MapX + MovX * 2, MapY + MovY * 2) then
- begin
- Walk(X, Y);
- Exit; //这里为什么不要recalcframe,,因为包括在walk(x,y)中了
- end;
- CurrentAction := HUMANACTION_RUN; //这句语句的上面计算run产生的地图位移,下面就是产生动画效果
- ReCalcFrames;
- end;
- procedure THumanActor.Hit(X, Y: Integer);
- begin
- if CurrentAction <> HUMANACTION_STAND then Exit;
- MovX := Min(1, Max(-1, X - MapX));
- MovY := Min(1, Max(-1, Y - MapY));
- if (MovX = 0) and (MovY = 0) then Exit;
- CalcNextDirection;
- CurrentAction := HUMANACTION_HIT;
- ReCalcFrames;
- end;
- end.
复制代码
|
|