组装10 人物动画的简单实现 添加人物发型
实现原理
建立一个ACTOR类
在PLAY按钮中设置好人物的属性,计算出初始帧数据
RUN 中 计算出当前帧,装载帧图片
DrawChr 进行绘画
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); 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; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure DXDrawHumanInitialize(Sender: TObject); procedure ButtonPlayClick(Sender: TObject); procedure TimerShowTimer(Sender: TObject); procedure PlayScence(MSurface: TDirectDrawSurface); procedure ButtonStopClick(Sender: TObject); private { Private declarations } public { Public declarations } end; const HUMANFRAME = 600; 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: 180; usetick: 2); ActRun: (start: 128; frame: 6; skip: 2; ftime: 200; usetick: 3); ActRushLeft: (start: 128; frame: 3; skip: 5; ftime: 200; usetick: 3); //先左手 ActRushRight: (start: 131; frame: 3; skip: 5; ftime: 200; 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: 140; usetick: 0); ActHeavyHit: (start: 264; frame: 6; skip: 2; ftime: 140; usetick: 0); ActBigHit: (start: 328; frame: 8; skip: 0; ftime: 120; usetick: 0); //这里指的烈火蓄力的动作? ActFireHitReady: (start: 192; frame: 1; skip: 0; ftime: 140; usetick: 0); ActSpell: (start: 392; frame: 6; skip: 2; ftime: 200; usetick: 0); ActSitdown: (start: 456; frame: 2; skip: 0; ftime: 240; usetick: 0); ActStruck: (start: 472; frame: 3; skip: 5; ftime: 140; usetick: 0); ActDie: (start: 536; frame: 4; skip: 4; ftime: 200; usetick: 0) ); type TActor = class m_btSex: Byte; m_btJob: Byte; m_btDress: Byte; m_btDir: Byte; m_btAtc: TAction; m_nStartFrame: Integer; m_nEndFrame: Integer; m_dwFrameTime: LongWord; m_dwStartTime: LongWord; m_nMaxTick: Integer; m_nCurTick: Integer; m_nCurrentFrame: 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; constructor Create; destructor Destroy; procedure CalcActorFrame; procedure Run; procedure LoadSurface; procedure DrawChr(dsurface: TDirectDrawSurface; dx, dy: integer); end; var Form1: TForm1; Actor1: TActor; g_mainWil: TWILImages; g_WHumImgImages: TWILImages; g_WHairImgImages: TWILImages; g_cacheSurface: TDirectDrawSurface; bmpIndex: Integer; movetick: Boolean; m_dwMoveTime: LongWord; 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; 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; Actor1 := TActor.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin g_WHumImgImages.Destroy; g_WHairImgImages.Destroy; g_cacheSurface.Free; Actor1.Destroy; 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; end; procedure TForm1.ButtonPlayClick(Sender: TObject); 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]; case ListBoxSex.ItemIndex of 0: Actor1.m_btSex := 0; 1: Actor1.m_btSex := 1; else Actor1.m_btSex := 0; end; case ListBoxJob.ItemIndex of 0: Actor1.m_btJob := 0; 1: Actor1.m_btJob := 1; 2: Actor1.m_btJob := 2; else Actor1.m_btJob := 0; end; case ListBoxDress.ItemIndex of 0: Actor1.m_btDress := 0; 1: Actor1.m_btDress := 1; 2: Actor1.m_btDress := 2; 3: begin case ListBoxJob.ItemIndex of 0: Actor1.m_btDress := 3; 1: Actor1.m_btDress := 4; 2: Actor1.m_btDress := 5; else Actor1.m_btDress := 0; end; end; 4: begin case ListBoxJob.ItemIndex of 0: Actor1.m_btDress := 6; 1: Actor1.m_btDress := 7; 2: Actor1.m_btDress := 8; else Actor1.m_btDress := 0; end; end; else Actor1.m_btDress := 0; end; case ListBoxAction.ItemIndex of 0: Actor1.m_btAtc := ActStand; 1: Actor1.m_btAtc := ActWalk; 2: Actor1.m_btAtc := ActRun; 3: Actor1.m_btAtc := ActRushLeft; 4: Actor1.m_btAtc := ActRushRight; 5: Actor1.m_btAtc := ActWarMode; 6: Actor1.m_btAtc := ActHit; 7: Actor1.m_btAtc := ActHeavyHit; 8: Actor1.m_btAtc := ActBigHit; 9: Actor1.m_btAtc := ActFireHitReady; 10: Actor1.m_btAtc := ActSpell; 11: Actor1.m_btAtc := ActSitdown; 12: Actor1.m_btAtc := ActStruck; 13: Actor1.m_btAtc := ActDie; else Actor1.m_btAtc := ActStand; end; case ListBoxDirect.ItemIndex of 0: Actor1.m_btDir := DR_UP; 1: Actor1.m_btDir := DR_UPRIGHT; 2: Actor1.m_btDir := DR_RIGHT; 3: Actor1.m_btDir := DR_DOWNRIGHT; 4: Actor1.m_btDir := DR_DOWN; 5: Actor1.m_btDir := DR_DOWNLEFT; 6: Actor1.m_btDir := DR_LEFT; 7: Actor1.m_btDir := DR_UPLEFT; else Actor1.m_btDir := DR_UP; end; case ListBoxHair.ItemIndex of 0: Actor1.m_btHair := 0; 1: Actor1.m_btHair := 1; 2: Actor1.m_btHair := 2; 3: Actor1.m_btHair := 3; 4: Actor1.m_btHair := 4; 5: Actor1.m_btHair := 5; 6: Actor1.m_btHair := 6; else Actor1.m_btSex := 0; end; Actor1.CalcActorFrame; end; procedure TForm1.TimerShowTimer(Sender: TObject); begin DXDrawHuman.Surface.Fill(ToDXD7Color(clBlue)); PlayScence(DXDrawHuman.Surface); DXDrawHuman.Flip; end; constructor TActor.Create; begin m_BodySurface := nil; m_HairSurface := nil; m_nHairOffset := -1; m_btHair := 0; m_nCurrentFrame := -1; m_nPx := 0; m_nPy := 0; end; destructor TActor.Destroy; begin end; procedure TActor.CalcActorFrame; begin if m_btHair > -1 then m_nHairOffset := HUMANFRAME * m_btHair else m_nHairOffset := -1; m_nCurrentFrame := -1; case m_btAtc 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; 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; 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; procedure TActor.Run; var prv: integer; begin 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 begin Inc(m_nCurrentFrame); //增加帧 m_dwStartTime := GetTickCount; end; end else //到行为动作的尾帧 begin begin m_nCurrentFrame := m_nStartFrame; m_dwStartTime := GetTickCount; end; 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 * 2 + m_btSex) + 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; end; procedure TActor.DrawChr(dsurface: TDirectDrawSurface; dx, dy: integer); begin 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); end; procedure TForm1.PlayScence(MSurface: TDirectDrawSurface); var m_dwFrameTime: LongWord; begin { movetick := False; if GetTickCount - m_dwMoveTime > 60 then begin m_dwMoveTime := GetTickCount; movetick := True; end; if movetick then begin Actor1.Run; end; } Actor1.Run; Actor1.DrawChr(MSurface, 80, 120); end; procedure TForm1.ButtonStopClick(Sender: TObject); begin TimerShow.Enabled := False; end; end.


有趣点:
男女发型是有区别的,只能是2,4为男性发型,3,5为女性发型
在原始翎风的程序中,对发型进行了男女判断,

浙公网安备 33010602011771号