Delphi 经典游戏程序设计40例 的学习 例23 行动的记录与重现

unit R23; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type TPatDt = record Used : Byte; Sban : Byte; Xpos : Integer; Ypos : Integer; Smov : Byte; Scon : Byte; Dtim : Byte; DlyS : array[1..40] of Byte; DlyX : array[1..40] of Integer; DlyY : array[1..40] of Integer; end; TRei23 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Button2MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Button3MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Button3MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure Button4Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } procedure MkDpat(Bmap : TBitmap;Zx:Byte); procedure InitChr; procedure Mstar; procedure ChrDz(Znum,Xsiz,Ysiz : Byte;Dpon : Word;X1,Y1 : Integer;Bmap : TBitmap); procedure PatDz(Pnum : Byte;X1,Y1 : Integer;Bmap,Zmap : TBitmap); public { Public declarations } end; const Yoko = 37; Tate = 27; DYoko = Yoko * 16; DTate = Tate * 16; PtFull = 16; MaxSp = 6; Mdot = 3; MaxMd = 1000; //最大行动记录数 var Rei23: TRei23; LoadBmap,XpatBmap,MakeBmap,BpatBmap : TBitmap; Z1Bmap,Z2Bmap,Z3Bmap,Z4Bmap,Z5Bmap : TBitmap; RectL,RectM,RectD : TRect; PX,PY,Mode : Byte; //模式, Sc,Memo : Word; //行动记录索引 Mdate : array[0..MaxMd] of Byte; //0,随机数种子值,其后,星舰模式 ChPon : array[0..6] of TPatDt; SpSiz : array[0..(MaxSp * 2 -1)] of Byte = ( 1,1, 2,2, 1,1, 1,1, 1,1, 1,1) ; SpPon : array[0..(MaxSp -1)] of Word; SpDat : array[0..8] of Byte = ( 0, 78,79,94,95, //星舰复合图案 19, 20, 21, 22); implementation {$R *.dfm} procedure TRei23.FormCreate(Sender: TObject); var n : Byte; begin LoadBmap := TBitmap.Create; LoadBmap.LoadFromFile(GetCurrentDir + '\Pat_Sample.bmp'); Sc := 0 ; for n := 0 to (MaxSp -1) do begin SpPon[n] := Sc; Sc := Sc + SpSiz[n * 2] * SpSiz[n * 2 + 1]; //0,1,5,6,7,8 end; XpatBmap := TBitmap.Create; XpatBmap.Width := 256; XpatBmap.Height := 256; RectL := Rect(0,0,256,256); XpatBmap.Canvas.CopyMode := cmSrcCopy ; XpatBmap.Canvas.CopyRect(RectL,LoadBmap.Canvas,RectL); XpatBmap.Canvas.Brush.Color := clBlack; XpatBmap.Canvas.BrushCopy(RectL,LoadBmap,RectL,clWhite); XpatBmap.Canvas.CopyMode := cmMergePaint; XpatBmap.Canvas.CopyRect(RectL,LoadBmap.Canvas,RectL); BpatBmap := TBitmap.Create; BpatBmap.Width := 8; BpatBmap.Height := 8; Z1Bmap := TBitmap.Create; Z2Bmap := TBitmap.Create; Z3Bmap := TBitmap.Create; Z4Bmap := TBitmap.Create; Z5Bmap := TBitmap.Create; MkDpat(Z1Bmap,3); MkDpat(Z2Bmap,6); MkDpat(Z3Bmap,8); MkDpat(Z4Bmap,10); MkDpat(Z5Bmap,12); MakeBmap := TBitmap.Create; MakeBmap.Width := DYoko + 32; MakeBmap.Height := DTate + 32; Randomize; Mdate[0] := Random(256); //随机数种子? Mode := 1; //0,星星自由移动,1,P模式,2,re重现记录模式 InitChr; end; procedure TRei23.MkDpat(Bmap : TBitmap;Zx:Byte); begin Bmap.Width := 256; Bmap.Height := 256; BpatBmap.Canvas.CopyMode := cmSrcCopy; RectL := Rect(Zx * 8 + 32,64,Zx * 8 + 40,72); RectD := Rect(0,0,8,8); BpatBmap.Canvas.CopyRect(RectD,LoadBmap.Canvas,rectl); Bmap.Canvas.Brush.Bitmap := BpatBmap; Bmap.Canvas.CopyMode := cmMergeCopy; RectL := Rect(0,0,256,256); Bmap.Canvas.CopyRect(RectL,LoadBmap.Canvas,RectL); Bmap.Canvas.CopyMode := cmMergePaint; Bmap.Canvas.CopyRect(RectL,XpatBmap.Canvas,RectL); Bmap.Canvas.Brush.Bitmap := nil; end; procedure TRei23.InitChr; var n,Cn : Byte; begin //随机数和动作记忆指针的初始设置 RandSeed := Mdate[0]; Memo := 1; //角色用数组的初始化 ChPon[0].Used := 1; ChPon[0].Sban := 1; ChPon[0].Xpos := 280; ChPon[0].Ypos := 300; ChPon[0].Smov := 0; ChPon[0].Scon := 0; ChPon[0].Dtim := 0; for Cn := 1 to 6 do begin ChPon[Cn].Used := 1; ChPon[Cn].Sban := Random(4) + 2; ChPon[Cn].Xpos := Random(100) + Cn * 80; ChPon[Cn].Ypos := Random(200) + 10; ChPon[Cn].Smov := Cn; ChPon[Cn].Scon := Random(10); ChPon[Cn].Dtim := Random(2) + 2; end; //拖影数组初始化 for Cn := 0 to 6 do for n := 1 to 40 do With ChPon[Cn] do begin DlyS[n] := Sban; DlyX[n] := Xpos; DlyY[n] := Ypos; end; end; procedure TRei23.Mstar; //Timer interval 将被执行一次 var n,Cn : Byte; begin for Cn := 0 to 6 do if ChPon[Cn].Used = 1 then begin with ChPon[Cn] do //拖影数据存储 begin for n := 39 downto 1 do begin DlyS[n + 1] := DlyS[n]; DlyX[n + 1] := DlyX[n]; DlyY[n + 1] := DlyY[n]; end; DlyS[1] := Sban; DlyX[1] := Xpos; DlyY[1] := Ypos; end; case Cn of //星舰的动作管理 0 : if Memo = MaxMd + 1 then //动作存储满了 begin Mode := 0; //模式0,停止星舰移动 ChPon[0].Used := 0; // 星舰不显示 end else begin case Mode of 1: begin //P 模式,记录移动 Mdate[Memo] := ChPon[0].Smov; Memo := Memo + 1; end; 2: if Mdate[Memo] <> 255 then begin ChPon[0].Smov := Mdate[Memo]; Memo := Memo + 1; end else begin //255中断 Mode := 0; ChPon[0].Used := 0; end; end; case ChPon[0].Smov of 1: if ChPon[0].Xpos < DYoko - 32 - Mdot then //星舰R ChPon[0].Xpos := ChPon[0].Xpos + Mdot; 5: if ChPon[0].Xpos > Mdot then //星舰L ChPon[0].Xpos := ChPon[0].Xpos - Mdot; end; end; //星星的动作管理 1..6 : begin ChPon[Cn].Sban := ((ChPon[Cn].Sban + 1) and 3) + 2; //实现图案旋转变化 if ChPon[Cn].Scon <> 0 then ChPon[Cn].Scon := ChPon[Cn].Scon - 1 else begin ChPon[Cn].Smov := (ChPon[Cn].Smov and 7) + 1; //方向变化 ChPon[Cn].Scon := Random(30) + Cn * 5; //方向上的时间计数初始 end; case ChPon[Cn].Smov of 1: if ChPon[Cn].Xpos < DYoko - 16 - Mdot then ChPon[Cn].Xpos := ChPon[Cn].Xpos + Mdot; //右 2: if (ChPon[Cn].Xpos < DYoko - 16 - Mdot) and (ChPon[Cn].Ypos > Mdot) then begin ChPon[cn].Xpos := ChPon[Cn].Xpos + Mdot; //右上 ChPon[Cn].Ypos := ChPon[Cn].Ypos - Mdot; end; 3: if ChPon[Cn].Ypos > Mdot then //上 ChPon[Cn].Ypos := ChPon[Cn].Ypos - Mdot; 4: if (ChPon[Cn].Xpos > Mdot) and (ChPon[Cn].Ypos > Mdot) then begin ChPon[Cn].Xpos := ChPon[Cn].Xpos - Mdot; //左上 ChPon[Cn].Ypos := ChPon[Cn].Ypos - Mdot; end; 5: if ChPon[Cn].Xpos > Mdot then ChPon[Cn].Xpos := ChPon[Cn].Xpos - Mdot; //左 6: if (ChPon[Cn].Xpos > Mdot) and (ChPon[Cn].Ypos < DTate - 16 - Mdot) then begin ChPon[Cn].Xpos := ChPon[Cn].Xpos - Mdot; //左下 ChPon[Cn].Ypos := ChPon[Cn].Ypos + Mdot; end; 7: if ChPon[Cn].Ypos < DTate - 16 - Mdot then ChPon[Cn].Ypos := ChPon[Cn].Ypos + Mdot; //下 8: if (ChPon[Cn].Xpos < DYoko - 16 - Mdot) and (ChPon[Cn].Ypos < DTate - 16 - Mdot) then begin ChPon[Cn].Xpos := ChPon[Cn].Xpos + Mdot; //右下 ChPon[Cn].Ypos := ChPon[Cn].Ypos + Mdot; end; end; end; end; end; end; procedure TRei23.ChrDz(Znum,Xsiz,Ysiz : Byte;Dpon : Word;X1,Y1 : Integer;Bmap : TBitmap); var CDX,CDY :Byte; ZBmap : TBitmap; begin case Znum of 0 : ZBmap := LoadBmap; 1 : ZBmap := Z1Bmap; 2 : ZBmap := Z2Bmap; 3 : ZBmap := Z3Bmap; 4 : ZBmap := Z4Bmap; 5 : ZBmap := Z5Bmap; end; for CDY := 0 to (Ysiz - 1)do for CDX := 0 to (Xsiz - 1) do begin if (X1 + CDX * 16 >= 0) and (X1 + CDX * 16 <= DYoko + 16) and (Y1 + CDY * 16 >= 0) and (Y1 + CDY * 16 <= DTate + 16) then PatDz(SpDat[Dpon],X1 + CDX * 16,Y1 + CDY * 16,Bmap,ZBmap); Dpon := Dpon + 1; end; end; procedure TRei23.PatDz(Pnum : Byte;X1,Y1 : Integer;Bmap,Zmap : TBitmap); begin PX := (Pnum and $f) * 16; PY := Pnum and $f0; RectL := Rect(PX,PY,PX + 16,PY + 16); RectD := Rect(X1,Y1,X1 + 16,Y1 + 16); if Pnum <> 0 then if Pnum >= PtFull then begin Bmap.Canvas.CopyMode := cmSrcPaint; Bmap.Canvas.CopyRect(RectD,XpatBmap.Canvas,RectL); Bmap.Canvas.CopyMode := cmSrcAnd; Bmap.Canvas.CopyRect(RectD,Zmap.Canvas,RectL); end else begin Bmap.Canvas.CopyMode := cmSrcCopy; Bmap.Canvas.CopyRect(RectD,Zmap.Canvas,RectL); end; end; procedure TRei23.Timer1Timer(Sender: TObject); var n,Cn : Byte; begin Mstar; //计算星舰的坐标 MakeBmap.Canvas.Brush.Color := clBlack; RectM := Rect(16,16,DYoko + 16,DTate + 16); MakeBmap.Canvas.FillRect(RectM); //FORM全刷黑 MakeBmap.Canvas.CopyMode := cmSrcCopy; for Cn := 0 to 6 do //绘制星舰,星星 with ChPon[Cn] do if (Used <> 0) and (Sban <> 0) then begin if Dtim <> 0 then for n := 5 downto 1 do if (DlyX[n * Dtim] <> Xpos) or (DlyY[n * Dtim] <> Ypos) then ChrDz(n,SpSiz[Sban * 2],SpSiz[Sban * 2 + 1],SpPon[DlyS[n * Dtim]], DlyX[n * Dtim] + 16,DlyY[n * Dtim] + 16,MakeBmap); ChrDz(0,SpSiz[Sban * 2],SpSiz[Sban * 2 + 1],SpPon[Sban], Xpos + 16,Ypos + 16,MakeBmap); end; Rei23.Canvas.CopyMode := cmSrcCopy; RectD := Rect(0,0,DYoko,DTate); rei23.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM); end; procedure TRei23.Button1Click(Sender: TObject); begin //指定P 模式 Mdate[0] := Random(256); Mode := 1; InitChr; end; procedure TRei23.Button2MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin //星舰L 移动 if mode = 1 then ChPon[0].Smov := 5; end; procedure TRei23.Button2MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin //星舰L 停止移动 if Mode = 1 then ChPon[0].Smov := 0; end; procedure TRei23.Button3MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin //星舰R 移动 if Mode = 1 then ChPon[0].Smov := 1; end; procedure TRei23.Button3MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin //星舰R停止 移动 if Mode = 1 then ChPon[0].Smov := 0; end; procedure TRei23.Button4Click(Sender: TObject); begin //指定Re ,重现模式 if Mode = 1 then //模式1,p 下被中断,相当于这个星舰行为记录的结束标示符 Mdate[Memo] := 255; Mode := 2; InitChr; end; procedure TRei23.FormClose(Sender: TObject; var Action: TCloseAction); begin LoadBmap.Free; XpatBmap.Free; MakeBmap.Free; BpatBmap.Free; Z1Bmap.Free; Z2Bmap.Free; Z3Bmap.Free; Z4Bmap.free; Z5Bmap.Free; end; end.
1,程序结构,按钮提供控制,一个 MSTAR提供 坐标计算,有绘图的函数,
在TIMER 中整合起来 INTERVAL 被执行一次,计算 各角色坐标,然后绘制出来。
这个关键的就是坐标的计算吧
2,有个BUG 找了好久,有4个星星没有拖影,程序和原版核对了几次,以为是坐标的计算问题
后来发现不是的,原来是对拖影坐标的变量 数据格式 定义错了。
定义成了 BYTE,应该是 INTEGER。所以只在 256,256的坐标范围类有拖影。
也说明了DELPHI 编译下不会对可以兼容的?2端数据格式不一致进行提示,会进行强制转换
3,100元买了一个15寸屏幕的华硕09年的笔记本,15寸的比 原来13寸的屏幕字体看起来大多了,