Delphi 经典游戏程序设计40例 的学习 例20 对应于大画面的大闪电

 

 

unit R20;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TRei20 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
    procedure PatDi(Pnum : Byte;X1,Y1 :Integer;Bmap : TBitmap);
    procedure Thunder(X1,Y1,X2,Y2:Integer; Col,Ran:Byte;Bmap : TBitmap);
  public
    { Public declarations }
  end;
const
  Yoko = 37;
  Tate = 27;
  DYoko = Yoko * 16;
  DTate = Tate * 16;
  PtFull = 16;
var
  Rei20: TRei20;
  LoadBmap,XpatBmap,BackBmap,MakeBmap : TBitmap;
  RectL,RectB,RectM,RectD : TRect;
  PX,PY,TC : Byte;
  RS : LongInt;      //虚拟随机数的SEED 值?

  Tree : array[0..200] of Integer;   //转折点存储数组,格式0索引,X1,Y1;X2,Y2;



implementation

{$R *.dfm}

procedure TRei20.FormCreate(Sender: TObject);
var
  X,Y : Byte;

begin
  Rei20.Height := 480;
  Rei20.Width := 640;

  LoadBmap := TBitmap.Create;
  LoadBmap.LoadFromFile(GetCurrentDir + '\Pat_Sample.bmp');

  XpatBmap := TBitmap.Create;
  XpatBmap.Height := 256;
  XpatBmap.Width := 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);

  BackBmap := TBitmap.Create;
  BackBmap.Height := DTate;
  BackBmap.Width := DYoko;
  for Y := 0 to (Tate -1 ) do
     for X := 0 to (Yoko - 1) do
     begin
       if Y <= 25 then
         PatDi(2,X * 16,Y * 16,BackBmap)
       else
         PatDi(7,X * 16,Y * 16,BackBmap);
       if Y = 25 then
         PatDi(16,X * 16,Y * 16,BackBmap);
     end;

  MakeBmap := TBitmap.Create;
  MakeBmap.Height := DTate + 32;
  MakeBmap.Width := DYoko + 32;
  //随机数初始化
  Randomize;

end;
// x1,y1,x2,y2 闪电区域,col 闪电颜色0黄色1白色 ,ran 是否重现闪电0 新,1重现
procedure TRei20.Thunder(X1,Y1,X2,Y2:Integer; Col,Ran:Byte;Bmap : TBitmap);
const
 Tmax = 12;      //             最大分支数 ?
var
  Xadd,TX,TY :Integer;
  Yadd,Tran,Tn,Mc :Byte;

begin
  //制作闪电
  Tree[0] := 0;
  Bmap.Canvas.Pen.Width := 2;
  case Col of
    0: Bmap.Canvas.Pen.Color := clYellow;
    1: Bmap.Canvas.Pen.Color := clWhite;
  end;

  if Ran = 0 then      //ran 是否重现闪电0 新,1重现
    RS := RandSeed
  else
    RandSeed := RS;

  for Tn := 0 to Tmax do       //最大分支?
  begin
    Yadd := 12 + Random(20);
    if Tree[0] = 0 then
    begin
      TY := Y1;
      TX := X1 + 50 + Random(X2 - X1 - 100);
    end
    else begin
      Tran := Random(Tree[0]) + 1;        //为什么随机找一个存储的坐标?
      TX := Tree[Tran * 2 -1];
      TY := Tree[Tran * 2];
    end;

    if TX < X1 + ( X2- X1 ) div 3 then
      Xadd := 16 + Random(16 - Tn)
    else if TX > x2 - (X2 - X1) div 3 then
      Xadd := -16 - Random(16 - Tn  )
    else
      Xadd := 16 + Tn - Random(33 + Tn * 2);

    Bmap.Canvas.MoveTo(TX,TY);
    //  设置好了线段的起点 TX,TY

    Mc := 0 ;
    //符合条件就不断的画线?
    while(TX + Xadd - 16 > X1 ) and (TX + Xadd + 16 <= X2 ) and
      (TY + Yadd <= Y2) and (Random(Tmax - Tn + 1) + 4 > Mc ) do
    begin
      Mc := Mc + 1;
      TY := TY + Yadd;
      TX := TX + Xadd - 16 + Random(33);
      Bmap.Canvas.LineTo(TX,TY);
      //存储一个合适的   坐标点?  这里为什么还要判断 TX,TY?
      if {(TX > X1 + 50) and (TX < X2 - 50) and (TY < Y2 - 100 ) and   }
        (Tree[0] < 100) then
      begin
        Tree[0] := Tree[0] + 1;
        Tree[Tree[0] * 2 -1] := TX;
        Tree[Tree[0] * 2] := TY;

      end;

    end;

  end;




end;

procedure TRei20.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  LoadBmap.Free;
  XpatBmap.Free;
  MakeBmap.Free;
  BackBmap.Free;
end;

procedure TRei20.Timer1Timer(Sender: TObject);
begin
  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);

  TC := ( TC + 1 ) and 31;
  case TC of
    0 : Thunder(10 + 16,16,582 + 16,400 + 16,1,0,MakeBmap);
    1 : Thunder(10 + 16,16,582 + 16,400 + 16,0,1,MakeBmap);
    2 : Thunder(10 + 16,16,582 + 16,400 + 16,1,1,MakeBmap);

    7 : Thunder(10 + 16,16,582 + 16,400 + 16,1,1,MakeBmap);
    8 : Thunder(10 + 16,16,582 + 16,400 + 16,1,1,MakeBmap);
    9 : Thunder(10 + 16,16,582 + 16,400 + 16,1,0,MakeBmap);
  end;
  //这里自动缩放大小了
  Rei20.Canvas.CopyMode := cmSrcCopy;
  RectD := Rect(0,0,ClientWidth,ClientHeight);
  Rei20.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM);


end;


procedure TRei20.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;





end.

还是没有看明白闪电按照什么算法画出来的,

程序结构是TIME中调用闪电函数,在窗口显示出来

闪电函数负责画线

 

posted @ 2022-07-26 14:19  D7mir  阅读(78)  评论(0)    收藏  举报