|
if u and l and not d and not r then MoveTo(MoveCount,DrUpLeft); if u and r and not l and not d then MoveTo(MoveCount,DrUpRight); if d and l and not r and not u then MoveTo(MoveCount,DrDownLeft); if d and r and not u and not l then MoveTo(MoveCount,DrDownRight); if d and not l and not r and not u then MoveTo(MoveCount,DrDown); if u and not l and not r and not d then MoveTo(MoveCount,DrUp); if l and not u and not r and not d then MoveTo(MoveCount,DrLeft); if r and not l and not u and not d then MoveTo(MoveCount,DrRight); {根据目的地来判断运动的方向,从而播放相应方向运动的动画}
Collision; {检测碰撞} Engine.X := -X+Engine.Width div 2 - Width div 2; Engine.Y := -Y+Engine.Height div 2 - Height div 2; {移动引擎,从而是游戏人物处于舞台的正中央} end;
procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer); begin if not DXDraw.CanDraw then exit; {检测DXDraw是否可以画,否则退出} DXInput.Update; {捕捉各类设备输入,这里我们用来检测鼠标的输入}
LagCount := 1000 div 60; {用来控制整个游戏运行速度的参数} DXSpriteEngine.Move(LagCount); DXSpriteEngine.Dead;
DXDraw.Surface.Fill(0); {将整个屏幕填充为黑色} DXSpriteEngine.Draw;
with DXDraw.Surface.Canvas do begin brush.style:=bsclear; pen.style:=psclear; pen.color:=clwhite; Font.Color:=clWhite; Font.Size:=10;
textout(10,10,'Press ESC to Quit'); textout(100,100,'X: '+IntToStr(AnchorX)+'Y: '+IntToStr(AnchorY)); {鼠标点击的位置经转换后在游戏世界中的坐标} textout(100,200,'Sprit x:'+IntToStr(Trunc(PlayerSprite.x))+'Y: ' +IntToStr(Trunc(PlayerSprite.y))); {精灵在游戏世界中的坐标} textout(100,300,'Relative x:'+IntToStr(AnchorX-Trunc(PlayerSprite.x))+'Y: ' +IntToStr(AnchorY-Trunc (PlayerSprite.y))); {精灵当前位置与目的地之间的绝对距离} textout(200,100,'Mouse x:'+IntToStr(MainForm.MouseX)+'Y: ' +IntToStr(MainForm.MouseY)); {鼠标当前位置,相对于窗口左上角,未转换为游戏世界坐标} Release; end; {在字母上输出相应参数,用于程序调试} DXDraw.Flip; {将内存中的后台表面翻转到当前并且显示} end;
procedure TMainForm.DXDrawFinalize(Sender: TObject); begin DXTimer.Enabled := False; {关闭定时器} end;
procedure TMainForm.DXDrawInitialize(Sender: TObject); begin DXTimer.Enabled := True; {启动定时器} end;
procedure TMainForm.FormCreate(Sender: TObject); begin Steps:=0; AnchorX:=0; AnchorY:=0;
MouseX:=320; MouseY:=240; {默认使鼠标处于屏幕的中央}
ImageList.Items.MakeColorTable;
DXDraw.ColorTable := ImageList.Items.ColorTable; DXDraw.DefColorTable := ImageList.Items.ColorTable; DXDraw.UpdatePalette; {更新系统调色板}
BackSprite:=TBackgroundSprite.Create(DXSpriteEngine.Engine); with TBackgroundSprite(BackSprite) do begin SetMapSize(1, 1);{设定背景显示样式为1×1} Image := ImageList.Items.Find('background'); {载入背景图片} Z := -2; {设定背景层次} Tile := True; {设定背景填充样式为平铺} end;
PlayerSprite := TPlayerSprite.Create(DXSpriteEngine.Engine); with TPlayerSprite(PlayerSprite) do begin Image := ImageList.Items.Find('player'); Z := 2; Width := Image.Width; Height := Image.Height; end; {载入游戏人物} end;
procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin {如果按了Esc,则退出} if Key=VK_ESCAPE then Close;
{全屏模式和窗口模式的切换} if (ssAlt in Shift) and (Key=VK_RETURN) then begin DXDraw.Finalize;
if doFullScreen in DXDraw.Options then begin RestoreWindow;
DXDraw.Cursor := crNone; BorderStyle := bsSizeable; DXDraw.Options := DXDraw.Options - [doFullScreen]; end else begin StoreWindow;
DXDraw.Cursor := crNone; BorderStyle := bsNone; DXDraw.Options := DXDraw.Options + [doFullScreen]; end; DXDraw.Initialize; end; end;
procedure TMainForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin AnchorX := x + Trunc(PlayerSprite.x)-320; AnchorY := y + Trunc(PlayerSprite.y)-240; {将鼠标在屏幕上点击的位置转换到游戏世界中} PlayerSprite.CanMove:=True; {此参数允许鼠标拖动} end;
procedure TMainForm.DXDrawMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if PlayerSprite.CanMove then begin AnchorX := x + Trunc(PlayerSprite.x)-320; AnchorY := y + Trunc(PlayerSprite.y)-240; {在鼠标拖动过程中将鼠标在屏幕上点击的位置转换到游戏世界中} end;
MouseX:=X; MouseY:=Y; {鼠标当前位置} end;
procedure TMainForm.DXDrawMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin PlayerSprite.CanMove:=False; end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin DXSpriteEngine.Free; end;
procedure TPlayerSprite.MoveTo(MoveCount: Integer; Direction: TDirection); begin {控制精灵往各个方向移动} case Direction of DrUp: begin Y := Y-(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+20+1; {当前动画中播放的图片序号}
if steps>4*speed-2 then steps:=0; end; DrDown: begin Y := Y+(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+1; if steps> 4*speed-2 then steps:=0; end; DrLeft: begin X := X-(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+10+1; if steps>4*speed-2 then steps:=0; end; DrRight: begin X := X+(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+30+1; if steps>4*speed-2 then steps:=0; end; DrUpLeft: begin X := X-(150/1000)*MoveCount; Y := Y-(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+15+1; if steps>4*speed-2 then steps:=0; end; DrUpRight: begin X := X+(150/1000)*MoveCount; Y := Y-(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+25+1; if steps>4*speed-2 then steps:=0; end; DrDownLeft: begin X := X-(150/1000)*MoveCount; Y := Y+(150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+5+1; if steps>4*speed-2 then steps:=0; end; DrDownRight: begin X := X + (150/1000)*MoveCount; Y := Y + (150/1000)*MoveCount; Inc(steps); AnimPos:=steps div speed+35+1; if steps>4*speed-2 then steps:=0; end; end; end;
end.
后记
通过以上的讲解和例子,相信大家已经对 Delphi 下的 DirectX 游戏开发有了初步的概念。国内讲解开发 DirectX 游戏的权威资料很少,如果这篇讲解可以起到抛砖引玉的效果的话,我将再高兴不过了。本文部分内容借鉴了国外一些游戏开发网站的技术文档,在此一并致谢。如果各位有什么问题需要和我交流,请发信至eagle_california@yahoo.com。 源程序下载地址:http://www.cfan.com.cn/11PROGRAM/200312/0312yde.zip 作者:郭磊
|