Delphi 经典游戏程序设计40例 的学习 例17 碰撞检查和事后处理

1,碰撞检查实际还是坐标的检测
2,角色 记录的设置
3,一个动画的实现,没有看的很明白?
4,程序框架类似,也是在TIME 中实现
5,几个函数对角色记录的 计算赋值,最后 画出这些角色,复合图案?复合图样?
6,程序没有对点阵图FREE,
7,碰撞检查放在后面似乎关系不大,显示也好像正常。
unit R17; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TpatDt = record //记录类型的名称 Used : Byte; //角色的状态 Sban : Byte; //复合图案的编号 Xpos : Integer; Ypos : Integer; Smov : ShortInt; //显示行动内容的编号 Scon : Byte; //计数器 end; TRei17 = class(TForm) Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } procedure HitCk; procedure MBalls; procedure MCanon; procedure MStars; procedure ChrDi(Xsiz,Ysiz :Byte;Dpon :Word;X1,Y1 :Integer;Bmap :TBitmap); procedure PatDi(Pnum : Byte;X1,Y1 :Integer;Bmap : TBitmap); public { Public declarations } end; const Yoko = 37; Tate = 27; DYoko = Yoko * 16; DTate = Tate * 16; PtFull = 16; MaxSp = 14; //使用的复合图样总数 var Rei17: TRei17; //载入,去除模板,绘制用点阵图 LoadBmap,XpatBmap,MakeBmap : TBitmap; RectL,RectM,RectD : TRect; PX,PY : Byte; Sc : Word; X,Y : Integer; //角色数组 ChPon : array[0..10] of TpatDt; //复合图样数组 14 SpSiz : array[0..(MaxSp * 2 -1 )] of Byte = ( 1,1, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 2,2, 1,1, 1,1, 1,1, 1,1); SpPon : array[0..(MaxSp -1 )] of Word; SpDat : array[0..40] of Byte = ( 0, 76, 77, 92, 93, 28, 29, 30, 31, 34, 35, 50, 51, 36, 37, 52, 53, 38, 39, 54, 55, 40, 41, 56, 57, 42, 43, 58, 59, 44, 45, 60, 61, 46, 47, 62, 63, 19, 20, 21, 22); implementation {$R *.dfm} procedure TRei17.FormCreate(Sender: TObject); var n,Cn : Byte; begin LoadBmap := TBitmap.Create; LoadBmap.LoadFromFile(GetCurrentDir + '\Pat_Sample.bmp'); 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); //零件贴图指标数组 Sc := 0; for n := 0 to (MaxSp -1) do begin SpPon[n] := Sc; Sc := Sc + SpSiz[n * 2] * SpSiz[n * 2 + 1]; end; //绘制点阵图初始 MakeBmap := TBitmap.Create; MakeBmap.Width := DYoko + 32; MakeBmap.Height := DTate + 32; //角色用数组初始 Randomize; //0,炮台 ChPon[0].Used := 1; //1,使用中 ChPon[0].Sban := 1; //炮台复合图案编号1 ChPon[0].Xpos := DYoko div 2 - 16; //X图像中间 ChPon[0].Ypos := DTate - 32; // Y图像底部 ChPon[0].Smov := 4; //炮台X移动速度 ChPon[0].Scon := 30; //发射间隔计数器 // 1-4 人面球 for Cn := 1 to 4 do begin ChPon[Cn].Used := 0; ChPon[Cn].Scon :=Random(10) + 10; //出现时机计数器 end; //5-10 星星 for Cn := 5 to 10 do ChPon[Cn].Used := 0; end; //碰撞检测 procedure TRei17.HitCk; var Cn,n :Byte; begin for Cn := 1 to 4 do //1-4 人面球 if ChPon[Cn].Used = 2 then //人面球状态非无敌 for n := 5 to 10 do //5-10 星星 if ChPon[n].Used = 1 then // 星星存在 begin X := ChPon[Cn].Xpos - ChPon[n].Xpos; Y := ChPon[Cn].Ypos - ChPon[n].Ypos; //碰撞坐标范围测定 if ( X >= -28 ) and (X <= 12) and (Y >= -28) and (Y <= 12) then begin ChPon[Cn].Used := 255; //改变人面球状态为255 ChPon[n].Used := 0; // 改变星星状态为0 end; end; end; //人面球的移动和出现 procedure TRei17.MBalls; var Cn : Byte; begin for Cn := 1 to 4 do begin ChPon[Cn].Scon := ChPon[Cn].Scon + 1; //人面球出现时机计数 ,存在时间计数 case ChPon[Cn].Used of 0 :begin if (ChPon[Cn].Scon > 30) and (Random(100) < 15) then //出现条件进入状态1 begin ChPon[Cn].Used := 1; ChPon[Cn].Sban := 2; ChPon[Cn].Xpos := (Cn -1) * 160 + 15 + Random(50); //设置出现的初始坐标 ChPon[Cn].Ypos := -31; end; end; 1:begin //状态降落 ChPon[Cn].Ypos := ChPon[Cn].Ypos + 2; ChPon[Cn].Sban := ChPon[Cn].Sban xor 2; //改变图样实现闪烁?XOR 0 OR 2 if ChPon[Cn].Ypos > 100 then //降落到100进入状态2 begin ChPon[Cn].Used := 2; ChPon[Cn].Sban := 2; ChPon[Cn].Scon := 0; //清零,用来计数存在时间 end; end; 2:begin //状态静止 if ChPon[Cn].Scon = 255 then //存在时间条件进入状态3 ChPon[Cn].Used := 3; end; 3:begin // 状态3 ,上升 ChPon[Cn].Ypos := ChPon[Cn].Ypos -4; ChPon[Cn].Sban := ChPon[Cn].Sban xor 2; if ChPon[Cn].Ypos < -31 then //该人面球清零 begin ChPon[Cn].Used := 0; ChPon[Cn].Scon := 0; end; end; 255:begin //碰撞状态 , 爆炸中 if ChPon[Cn].Sban = 2 then begin ChPon[Cn].Sban := 3; //图样3 ChPon[Cn].Scon := 0; ChPon[Cn].Smov := 0; end else begin //如何实现爆炸的动画显示? ChPon[Cn].Sban := ChPon[Cn].Sban + 1; //爆炸图样 +1, if (ChPon[Cn].Sban = 7)and(ChPon[Cn].Smov <= 2) then begin ChPon[Cn].Sban := 3; ChPon[Cn].Smov := ChPon[Cn].Smov + 1; //爆炸显示次数 end else if ChPon[Cn].Sban = 10 then //图样10? begin ChPon[Cn].Used := 0; ChPon[Cn].Scon := 0; end; end; end; end; end; end; //炮台移动和星星发射 procedure TRei17.MCanon; var Cn : Byte; begin ChPon[0].Xpos := ChPon[0].Xpos + ChPon[0].Smov; //炮台来回移动 if (ChPon[0].Xpos < 0) or (ChPon[0].Xpos > DYoko - 32) then begin ChPon[0].Smov := - ChPon[0].Smov; ChPon[0].Xpos := ChPon[0].Xpos + ChPon[0].Smov; end; ChPon[0].Scon := ChPon[0].Scon + 1; //发射星星条件 if (ChPon[0].Scon > 15) and (Random(100) < 35) then begin Cn := 5; while (Cn < 11) and (ChPon[Cn].Used = 1) do //找到可以用的星星? Cn := Cn + 1; if Cn < 11 then //发射星星 begin ChPon[Cn].Used := 1; ChPon[Cn].Xpos := ChPon[0].Xpos + 8; ChPon[Cn].Ypos := DTate -45; ChPon[Cn].Smov := 10 + Random(5); ChPon[0].Scon := 0; // 发射星星后炮台发射计数器清零 end; end; end; procedure TRei17.MStars; var Cn : Byte; begin for Cn := 5 to 10 do if ChPon[Cn].Used = 1then begin ChPon[Cn].Scon := ChPon[Cn].Scon + 1 ; //图案编号计数器? // 它好像没有赋过初值,默认0 ,会不断增大?0-256循环? ChPon[Cn].Sban := 10 + ChPon[Cn].Scon and 3; //星星也有3种图案? 在旋转? ChPon[Cn].Ypos := ChPon[Cn].Ypos - ChPOn[Cn].Smov; if ChPon[Cn].Ypos < -15 then ChPon[Cn].Used := 0; end; end; procedure TRei17.ChrDi(Xsiz,Ysiz:Byte;Dpon:Word;X1,Y1:Integer;Bmap:TBitmap); var CDX,CDY :Byte; begin 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 PatDi(SpDat[Dpon],X1 + CDX * 16,Y1 + CDY * 16,Bmap); Dpon := Dpon + 1; end; end; procedure TRei17.PatDi(Pnum:Byte;X1,Y1:Integer;Bmap: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,LoadBmap.Canvas,RectL); end else begin Bmap.Canvas.CopyMode := cmSrcCopy; Bmap.Canvas.CopyRect(RectD,LoadBmap.Canvas,RectL); end; end; procedure TRei17.Timer1Timer(Sender: TObject); var Cn : Byte; begin HitCk; MBalls; MCanon; MStars; RectM := Rect(16,16,DYoko + 16,DTate + 16); MakeBmap.Canvas.Brush.Color := clBlack; MakeBmap.Canvas.FillRect(RectM); Rei17.Canvas.CopyMode := cmSrcCopy; for Cn := 10 downto 0 do if (ChPon[Cn].Used <> 0) and (ChPon[Cn].Sban <> 0 ) then begin //图案的格式在这里得到了方便的利用 ChrDi(SpSiz[ChPon[Cn].Sban * 2],SpSiz[ChPon[Cn].Sban * 2 + 1], SpPon[ChPon[Cn].Sban],ChPon[Cn].Xpos + 16,ChPon[Cn].Ypos + 16,MakeBmap); end; RectD := Rect(0,0,DYoko,DTate); Rei17.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM); end; end.