Delphi 经典游戏程序设计40例 的学习 例22 残留图像效果

unit R22; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TPatDt = record Used : Byte; Sban : Byte; Xpos : Integer; Ypos : Integer; Smov : Byte; Scon : Byte; Dtim : Byte; // 拖影的间隔<8,只存储了40个历史坐标 DlyS : array[1..40] of Byte; //复合图样数组 DlyX : array[1..40] of Integer; //X 坐标用数组 DlyY : array[1..40] of Integer; //y 坐标用数组 end; TRei22 = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Timer1Timer(Sender: TObject); private { Private declarations } procedure MkDpat(Bmap : TBitmap; ZX : Byte); procedure ChMove; 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 = 8; //复合图样总数 Mdot = 3; //移动点数 var Rei22: TRei22; LoadBmap,XpatBmap,BackBmap,MakeBmap : TBitmap; //笔刷,残留图像用点阵图 BpatBmap,Z1Bmap,Z2Bmap,Z3Bmap,Z4Bmap,Z5Bmap :TBitmap; PX,PY : Byte; Sc : Word; RectL,RectB,RectM,RectD : TRect; //角色记录数组 ChPon : array[0..3] of TPatDt; //复合图样的数组 SpSiz :array[0..(MaxSp * 2 - 1)] of Byte = ( 1,1, 2,2, 2,2, 2,3, 1,1, 1,1, 1,1, 1,1 ); SpPon :array[0..(MaxSp -1)] of Word; SpDat :array[0..18] of Byte = ( 0, 28,29,30,31, 32,33,48,49, 65,65,80,81,96,97, 19, 20, 21, 22); implementation {$R *.dfm} procedure TRei22.FormCreate(Sender: TObject); var x,y,n,Cn :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]; 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); //制作背景点阵图 BackBmap := TBitmap.Create; BackBmap.Width := DYoko; BackBmap.Height := Dtate; for x := 0 to Yoko - 1 do for y := 0 to Tate - 1 do begin if ( x <= Yoko div 2 )and (y <= Tate div 2) then n := 1 else if (x >= Yoko div 2) and (y <= Tate div 2) then n :=7 else if (x <= Yoko div 2) and ( Y >= Tate div 2) then n := 13 else n := 15; PatDz(n,x * 16,y * 16,BackBmap,LoadBmap); end; //绘制点阵图, MakeBmap := TBitmap.Create; MakeBmap.Width := DYoko + 32; MakeBmap.Height := Dtate + 32; //角色数组初始 ChPon[0].Used := 1; ChPon[0].Sban := 1; //独眼 ChPon[0].Xpos := 50; ChPon[0].YPos := 50; ChPon[0].Smov := 1; ChPon[0].Scon := 0; ChPon[0].Dtim := 3; ChPon[1].Used := 1; ChPon[1].Sban := 3; //树人 ChPon[1].Xpos := 395; ChPon[1].YPos := 350; ChPon[1].Smov := 5; ChPon[1].Scon := 0; ChPon[1].Dtim := 6; ChPon[2].Used := 1; ChPon[2].Sban := 2; //菠萝人 ChPon[2].Xpos := 510; ChPon[2].YPos := 125; ChPon[2].Smov := 3; ChPon[2].Scon := 0; ChPon[2].Dtim := 4; ChPon[3].Used := 1; ChPon[3].Sban := 4; //星星 ChPon[3].Xpos := 50; ChPon[3].YPos := 275; ChPon[3].Smov := 7; ChPon[3].Scon := 0; ChPon[3].Dtim := 6; for Cn := 0 to 3 do for n := 1 to 40 do with ChPon[Cn] do begin DlyS[n] := Sban; //图案编号0..3 DlyX[n] := Xpos; DlyY[n] := Ypos; end; end; //制作残留图像用的图案 ,ZX 偏移 点数 procedure TRei22.MkDpat(Bmap : TBitmap; ZX : Byte); begin Bmap.Width := 256; Bmap.Height := 256; BpatBmap.Canvas.CopyMode := cmSrcCopy; //调取特定位置图案,8*8 的大小?调取点数是随意额? //调取的就是随意选择的,并不是特定的图案 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 TRei22.ChMove; var n,Cn :Byte; begin for Cn := 0 to 3 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; if Cn = 3 then //3 为旋转的星星图案 Sban := (Sban + 1) and 3 + 4; //图案变化实现星星的旋转 if Scon <> 0 then //scon 表示什么? Scon := Scon - 1 else begin case Smov of //SMOV 表示移动的方向 ? 这个得结合图例看 1: if Xpos < 395 then Xpos := Xpos + Mdot else begin Smov := 2; Xpos := Xpos + Mdot; Ypos := Ypos + Mdot; end; 2: if Ypos < 125 then begin Xpos := Xpos + Mdot; Ypos := Ypos + Mdot; end else begin Smov := 3; Ypos := Ypos + Mdot; end; 3: if Ypos < 275 then Ypos := Ypos + Mdot else begin Smov := 4; Xpos := Xpos - Mdot; Ypos := Ypos + Mdot; end; 4: if Ypos < 350 then begin Xpos := Xpos - Mdot; Ypos := Ypos + Mdot; end else begin Smov := 5; Xpos := Xpos - Mdot; end; 5: if Xpos > 165 then Xpos := Xpos - Mdot else begin Smov := 6; Xpos := Xpos - Mdot; Ypos := Ypos - mdot; end; 6: if Ypos > 275 then begin Xpos := Xpos - Mdot; Ypos := Ypos - Mdot; end else begin Smov := 7; Ypos := Ypos - Mdot; end; 7: if Ypos > 125 then Ypos := Ypos - Mdot else begin Smov := 8; Xpos := Xpos + Mdot; Ypos := Ypos - Mdot; end; 8: if Ypos > 50 then begin Xpos := Xpos + Mdot; Ypos := Ypos - Mdot; end else begin Smov := 1; Scon := 30; end; end; end; end; end; end; //Znum procedure TRei22.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; //Zmap源图,Bmap合成输出图, procedure TRei22.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 TRei22.FormClose(Sender: TObject; var Action: TCloseAction); begin LoadBmap.Free; XpatBmap.Free; BackBmap.Free; MakeBmap.Free; BpatBmap.Free; Z1Bmap.Free; Z2Bmap.Free; Z3Bmap.Free; Z4Bmap.Free; Z5Bmap.Free; end; procedure TRei22.Timer1Timer(Sender: TObject); var n, Cn :Byte; begin ChMove; MakeBmap.Canvas.CopyMode := cmSrcCopy; RectB := Rect(0,0,DYoko,Dtate); RectM := Rect(16,16,DYoko+ 16,Dtate + 16) ; MakeBmap.Canvas.CopyRect(RectM,BackBmap.Canvas,RectB); //复制背景点阵图 for Cn := 0 to 3 do with ChPon[Cn] do if (Used <> 0 ) and (Sban <> 0 ) then begin if Dtim <> 0 then for n := 5 downto 1 do //5拖影 if (DlyX[n * Dtim] <> Xpos) or (DlyY[n * Dtim] <> Ypos) //不重叠 then //dtim 间隔 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; Rei22.Canvas.CopyMode := cmSrcCopy; RectD := Rect(0,0,DYoko,Dtate); Rei22.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM); end; end.
1。角色的记录里面的元素更多了,加入了历史的角色图案和X,Y坐标,用数组来记录
2,MkDpat有点难以理解,
应该还是对笔刷,COPYMODE ,去除用模板,图像重叠的原理,还有相应函数的掌握不够,
需要对以前的例子进行复习。
3.利用WIHT DO 对记录里面的元素进行操作,极大的简化的程序两,
看起来简洁多了,
但是我从网上的一篇DELPHI7规范里面看到,最好不要用WITH进行操作?
4,路径 的逻辑复杂了,掺杂了 CASE ,if,then,else then 的条件判断,但在良好的缩进和 CNPACK 加持下,还是能够直观的看明白的。
5,贴图函数改了一点,其实是取不同的图样?