编程语言
首页 > 编程语言> > Delphi 经典游戏程序设计40例 的学习 例18 线条光线的威力

Delphi 经典游戏程序设计40例 的学习 例18 线条光线的威力

作者:互联网

 

 

unit R18;

interface

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

type
  TpatDt = record   //角色,记录类型
    Used : Byte;
    Sban : Byte;
    Xpos : Integer;
    Ypos : Integer;
    Scon : Byte;       //计数器,1星星出现前的时机调整,2受到光线照射的次数
  end;

  TRei18 = class(TForm)
    Button1: TButton;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    procedure LineRay;
    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;

var
  Rei18: TRei18;
  LoadBmap,XpatBmap,MakeBmap : TBitmap;
  RectL,RectM,RectD : TRect;
  PX,PY : Byte;
  Bn    :Byte;  //星星的编号 0:未定
  Ray   : Byte;  //光线的 on off
  TM    : Byte;  //决定线条颜色的计数器 0-3
  BX,BY : Word;  //射击目标的左端坐标
  RX,RY : Word;  //实际画线终点目标

  ChPon : array[1..5] of TpatDt;

  //复合图案0-2 数组
  SpDat : array[0..5] of Byte = (0, 76,77,92,93, 19);
  


implementation

{$R *.dfm}

procedure TRei18.FormCreate(Sender: TObject);
var
  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);

  MakeBmap := TBitmap.Create;
  MakeBmap.Width := DYoko + 32;
  MakeBmap.Height := DTate + 32;

  // 星星角色数组初始设置
  Randomize;
  for Cn := 1 to 5 do
  begin
    ChPon[Cn].Used := 0;
    ChPon[Cn].Scon := Random(100) + 60;   //计数器,1星星出现前的时机调整
  end;


end;

procedure TRei18.Timer1Timer(Sender: TObject);
begin
  if Ray = 1 then
    LineRay
  else
    MStars;

end;

procedure TRei18.LineRay;
var
  n : Byte;
begin
  TM := (TM + 1) and 3;        // TM决定线条颜色的计数器 0-3

  if Bn <> 0 then               //星星的编号  0:未定
  begin
    ChPon[Bn].Scon := ChPon[Bn].Scon + 1;
    if ChPon[Bn].Scon > 20 then
    begin
      for n := 0 to 8 do         // 8 根光线?
      begin
        Rei18.Canvas.Pen.Width := 3;
        Rei18.Canvas.Pen.Color := clBlack;    // 黑色线条 去除用?
        Rei18.Canvas.MoveTo(DYoko div 2,DTate - 34);  //发射位置
        Rei18.Canvas.LineTo(RX + n * 3,BY );          //
      end;
      //去除掉星星角色,重新计数?
      ChPon[Bn].Used := 0 ;
      ChPon[Bn].Scon := Random(80) + 60;
      Bn := 0;     // 射击目标清零,
      BY := 0;     // 没有了星星阻隔,光线射到0?
    end;
  end;

  RX := BX + Random(9);
  for n := 0 to 8 do
  begin
    RY := BY;
    if (n < 2) or (n > 6) then
    begin
     Rei18.Canvas.Pen.Width := 2;
     Rei18.Canvas.Pen.Color := clBlack;
    end
    else begin
      Rei18.Canvas.Pen.Width :=1;
      if (n = 2) or (n = 6) then      //2,6线要短些
        RY := BY + 2;
      case TM of        //决定线条颜色的计数器 0-3
        0: Rei18.Canvas.Pen.Color := clYellow;
        1: Rei18.Canvas.Pen.Color := clAqua;
        2: Rei18.Canvas.pen.Color := clWhite;
        3: Rei18.Canvas.Pen.Color := clMaroon;
      end;
    end;
    Rei18.Canvas.MoveTo(DYoko div 2,DTate -34);
    Rei18.Canvas.LineTo(RX + n * 3,RY );
  end;
end;

procedure TRei18.MStars;
var
  Cn : Byte;        //c 表示 chpon?  n 表示 数?number?
begin
  for Cn := 1 to 5 do
  if ChPon[Cn].Used = 0 then
  begin
    ChPon[Cn].Scon := ChPon[Cn].Scon + 1;
    if ChPon[Cn].Scon > 150 then       //  计数到150星星出现?
    begin
      ChPon[Cn].Used := 1;
      ChPon[Cn].Sban := 2;
      ChPon[Cn].Xpos := (Cn -1) * 120 + Random(60) + 20; //间隔排列,出现晚的星
      ChPon[Cn].Ypos := Random(20) + 10;  //Y方向 10上下
      ChPon[Cn].Scon := 0;                 //计数器清零
    end;
  end
  else if Bn = 0 then        //星星的编号 0:未定
  begin
    BX := chpon[Cn].Xpos;
    if BX < DYoko div 2 then      //这个是因星星在画面的 位置微调BX 位置?
      BX := BX - 12               //左侧的光线倾斜度更大?
    else
      BX := BX - 4;
    BY := ChPon[Cn].Ypos - 4;     //确定射击光线终点Y 坐标
    Bn := Cn ;                      //确定射击的目标
  end;

  RectM := Rect(16,16,DYoko + 16,DTate + 16);
  MakeBmap.Canvas.Brush.Color := clBlack;
  MakeBmap.Canvas.FillRect(RectM);

  ChrDi(2,2,1,DYoko div 2, DTate - 16,MakeBmap); // 画出炮台
  for Cn := 1  to 5 do                           //画出星星
    if ChPon[Cn].Used = 1 then
      ChrDi(1,1,5,ChPon[Cn].Xpos + 16,ChPon[Cn].Ypos + 16,MakeBmap);
  Rei18.Canvas.CopyMode := cmSrcCopy;
  RectD := Rect(0,0,DYoko,DTate);
  Rei18.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM);


end;

procedure TRei18.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 TRei18.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 TRei18.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Ray := 1;
end;

procedure TRei18.Button1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Ray := 0;
end;



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

end.

1,程序结构同前例一样,在TIMER中绘画

2,有个星星角色

3,光线用画线来实现,大概因为是模拟,所以出现一些加减微调?这些微调似乎没有算法,只是例子中调试出的?

 

标签:Canvas,end,Cn,18,Delphi,begin,40,ChPon,procedure
来源: https://www.cnblogs.com/D7mir/p/16514619.html