Delphi 经典游戏程序设计40例 的学习 例8 多重滚动


unit rei08;

interface

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

type
  TR08 = class(TForm)
    tmr1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure tmr1Timer(Sender: TObject);
  private
    { Private declarations }
    procedure ScrolX(var SX :Word;Y1,Y2:Word;Bmap:TBitmap);
    procedure SbanDi(Sary:array of Byte;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;
  SY1 = 160;    // 滚动块的Y 坐标
  SY2 = 260;
  SY3 = 340;


var
  R08: TR08;
  BackBmap,LoadBmap,XpatBmap,MakeBmap : TBitmap;
  PX,PY :Byte;
  n,SX1,SX2,SX3,SX4 :Word;
  RectL,RectB,RectM,RectD :TRect;
   //复合图案数组
  Spr00 : array[0..(31*11+1)] of Byte = (
  31, 11,
    12,12,12,12,12,12,12, 0,12,12,12, 0,12,12,12,12,12,12,12,
      0,12, 0, 0, 0, 0, 0,12,12,12,12,12,
    12, 0, 0,12, 0, 0,12, 0, 0,12, 0, 0,12, 0, 0,12, 0, 0,12,
      0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,12,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12, 0, 0,12, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12,12,12,12, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12, 0, 0,12, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0,
    0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0, 0, 0,12, 0, 0, 0,
      0,12, 0, 0, 0,12, 0,12, 0, 0, 0,12,
    0, 0,12,12,12, 0, 0, 0,12,12,12, 0, 0, 0,12,12,12, 0, 0,
      0,12,12,12,12,12, 0,12,12,12,12,12);
  

implementation

{$R *.dfm}

procedure TR08.FormCreate(Sender: TObject);
begin
  R08.Height := 480;
  R08.Width := 640;
   // 载入 背景 图案
  BackBmap := TBitmap.Create;
  BackBmap.LoadFromFile(GetCurrentDir + '\Back_Sample.bmp');
  // 载入图库图案
  LoadBmap := TBitmap.Create;
  LoadBmap.LoadFromFile(GetCurrentDir + '\Pat_Sample.bmp');
  LoadBmap.Palette := BackBmap.Palette;
  // 去除用模板点阵图
  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;
  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 );

  SX1 := 0; // 初始滚动点
  SX2 := 0;
  SX3 := 0;
  

end;

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

procedure TR08.tmr1Timer(Sender: TObject);
begin
   SX1 := SX1 + 4;
   SX2 := SX2 + 2;
   SX3 := SX3 + 1;
   ScrolX(SX1,0,SY1,MakeBmap);
   ScrolX(SX2,SY1,SY2,MakeBmap);
   ScrolX(SX3,SY2,SY3,MakeBmap);
   SbanDi(Spr00,66,66,MakeBmap);

   R08.Canvas.CopyMode :=cmSrcCopy;
   RectM := Rect(16,16,DYoko + 16,DTate + 16);
   RectD := Rect(0,0,DYoko ,DTate );
   R08.Canvas.CopyRect(RectD,MakeBmap.Canvas ,RectM );
end;


//滚动核心,方块挪动  ,
procedure TR08.ScrolX(var SX :Word;Y1,Y2:Word;Bmap:TBitmap);
begin
  RectB := Rect(0,Y1,SX,Y2 ) ;
  RectD := Rect(DYoko - SX + 16,Y1 + 16,DYoko + 16,Y2 +16);
  Bmap.Canvas.CopyMode := cmSrcCopy;
  Bmap.Canvas.CopyRect(RectD,BackBmap.Canvas,RectB );

 if SX = DYoko then
    SX :=0
 else begin
    RectB := Rect(SX ,Y1,DYoko,Y2 );
    RectD := Rect(16,Y1 + 16,DYoko- SX + 16,Y2 + 16);
    Bmap.Canvas.CopyRect(RectD,BackBmap.Canvas,RectB );
  end;
end;

 // 指定复合图案贴图,数组图案,自定义格式,数组0,1元素为 X,Y 图案个数
procedure TR08.SbanDi(Sary:array of Byte;X1,Y1:Integer;Bmap:TBitmap);
var
  X,Y : Byte;
begin
  n := 2;
  for Y :=0 to (Sary[1]-1) do
    for X :=0 to (Sary[0] -1) do
    begin
      if (X1 + X*16 >=0 ) and (X1 + X*16 <=  DYoko + 16)
      and (Y1 + Y*16 >=0 ) and (Y1 + Y*16 <=Dtate + 16) then
      PatDi(Sary[n],X1 + X*16,Y1 + Y*16,Bmap);
      n := n +1;
    end;

end;

 // 图案贴图,可重叠
procedure TR08.PatDi(Pnum : Byte;X1,Y1 : Integer;Bmap:TBitmap);
begin
  PX := (Pnum mod 16 ) * 16;
  PY := (Pnum div  16 ) * 16;

  RectL := Rect(PX,PY,PX+ 16,PY + 16);
  RectD := Rect(X1,Y1,X1 + 16,Y1 + 16);
  if Pnum <> 0  then
  if Pnum >= 16 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.

背景图片的处理,分割的很巧妙,需要预先设计好图片

云层的近大远小,近快远慢,让视觉上出现了立体效果?

图案的特定 数组格式 出现大数组了。前2元素为XY 大小,所以出现了一个 算术表达式来 直观的 表达?

用了4个内存点阵图来处理

还有单个的图案贴图方法,复合图案的贴图方法,