Delphi 经典游戏程序设计40例 的学习 例6 简易的零件贴图


 

unit rei06;

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;
  end;

  TRein06 = class(TForm)
    tmr1: TTimer;
    tmr2: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure tmr1Timer(Sender: TObject);
    procedure tmr2Timer(Sender: TObject);
  private
    { Private declarations }
    procedure ChrDi(Used:Byte;Sban:Byte;X1,Y1 :Integer;Bmap:TBitmap);
    procedure SbanDi(Sary:array of Byte;X1,Y1:Integer;Bmap:TBitmap);
    procedure PatDi(Pnum:Byte;X1,Y1:Integer;Bmap:TBitmap);
    procedure ChrCl(Used:Byte;Sban:Byte;X1,Y1:Integer;Bmap:TBitmap);
    procedure SbanCl(Xdot,Ydot:Word;X1,Y1:Integer;Bmap:TBitmap);
    procedure NewXY(var Mnum:Byte;var X1,Y1 :Integer);

  public
    { Public declarations }
  end;

const
  Yoko = 37;
  Tate = 27;
  DYoko =  Yoko*16;
  DTate =  Tate*16;
  PtFull =16;

var
  Rein06: TRein06;

  LoadBmap,XpatBmap,BackBmap,MakeBmap :TBitmap;

  BkImage : array[0..36,0..26] of Byte;
  P,PX,PY,n :Byte;
  RectL,RectB,RectM,RectD :TRect;
  Chr0,Chr1,Chr2 : TPatDt;

  Spr00 : array[0..5] of Byte = (2,2,24,25,26,27);
  Spr01 : array[0..5] of Byte = (2,2,28,29,30,31);
  Spr02 : array[0..5] of Byte = (2,2,32,33,48,49);




implementation

{$R *.dfm}

procedure TRein06.FormCreate(Sender: TObject);
var
  x,y :Byte;

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

  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);

  for y :=0 to (Tate-1) do
    for x:=0 to (Yoko-1) do
    begin
      if (x<14)or (x>22)or (y<9)or (y>17) then
        P:=14
      else if (x<16)or (x>20) or (y<11)or (y>15)then
        P:=12
      else
        P:=7;
      BkImage[x,y] := P;
    end;

   BackBmap := TBitmap.Create;    //背景 37+2 ,27+2
   BackBmap.Width :=DYoko + 32;
   BackBmap.Height := DTate +32;
   for y:=0 to (Tate-1) do
     for x:=0 to (Yoko-1) do
       PatDi(BkImage[x,y],x*16+16,y*16+16,BackBmap);    //+16 实际坐标

   MakeBmap := TBitmap.Create;       //制作画面,初始 复制 背景画面
   MakeBmap.Width := BackBmap.Width;
   MakeBmap.Height := BackBmap.Height;
   MakeBmap.Canvas.Draw(0,0,BackBmap);

   with Chr0 do        //角色赋值
   begin
     Used :=1;           //是否移动?
     Sban :=0;           //角色图形编号
     Xpos :=279;        //初始位置
     Ypos :=199;
     Smov :=4;           //移动方向
   end;

   with Chr1 do
   begin
     Used :=1;
     Sban :=1;
     Xpos := 279;
     Ypos :=199;
     Smov :=1;
     end;

   with Chr2 do
   begin
     Used := 1;
     Sban := 2;
     Xpos :=279;
     Ypos :=199;
     Smov := 2;
   end;


    end;






procedure TRein06.NewXY(var Mnum:Byte;var X1,Y1 :Integer);
begin
  case Mnum of                //Mnum 用的 Smov ,x1,y1 用的 xpos,ypos
    1 : begin                 //xpos ypos -32 到 DYOKO ,DTATE
      X1 := X1 +1;
      if X1 > DYoko then
      begin
         X1 :=279;
         Mnum :=(Mnum and 3) +1;       //方向改变   1234

      end;
    end;

    2 : begin
      Y1 :=Y1-2;
      if Y1 < -31 then
      begin
        Y1 := 199;
        Mnum :=(Mnum and 3) +1;
      end;
    end;

    3 : begin
      X1 := X1-3;
      if X1 < -31 then
      begin
        X1 := 279;
        Mnum := (Mnum and 3) +1;

      end;
    end;

    4 : begin
       Y1 := Y1 + 4;
       if Y1 > DTate then
       begin
         Y1 :=199;
         Mnum :=(Mnum and 3) +1;
       end;

    end;
 end;
end;

procedure TRein06.ChrDi(Used:Byte;Sban:Byte;X1,Y1 :Integer;Bmap:TBitmap);
begin

  if Used =1 then
  begin
     case Sban of
      0 : SbanDi(Spr00,X1 + 16,Y1 +16 ,Bmap);     //MakeMap,显示角色  +16
      1 : SbanDi(Spr01,X1 + 16,Y1 + 16,Bmap);
      2 : SbanDi(Spr02,X1 + 16,Y1 +16,Bmap);
     end;
  end;
end;


procedure TRein06.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                          //判断在角色的某个图案块+16后,0,0,DYOKO+16,DTATE+16 ,
      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 TRein06.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 >= 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 TRein06.ChrCl(Used:Byte;Sban:Byte;X1,Y1:Integer;Bmap:TBitmap);
begin
  if Used = 1 then
    case Sban of
      0 : SbanCl(Spr00[0]*16,Spr00[1]*16,X1 + 16,Y1 + 16,Bmap);
      1 : SbanCl(Spr01[0]*16,Spr01[1]*16,X1 + 16,Y1 + 16 ,Bmap);
      2 : SbanCl(Spr02[0]*16,Spr02[1]*16,X1 + 16,Y1 + 16 ,Bmap);
    end;

end;

procedure TRein06.SbanCl(Xdot,Ydot:Word;X1,Y1:Integer;Bmap:TBitmap);

begin
   if X1 < 0 then      //XDOT ,YDOT 为 角色 的 X ,Y 大小 ,X1,Y1 为角色显示位置,以显示界面为坐标.
   begin
     Xdot := Xdot + X1;     //边界判断,越界的进行裁剪.
     X1 := 0 ;

   end;

   if Y1 < 0 then
   begin
     Ydot := Ydot + Y1;
     Y1 := 0 ;
   end;

   if (X1 + Xdot)>=(DYoko +32 ) then
     Xdot := DYoko +32 - X1;

   if ( Y1 + Ydot )>= ( Dtate + 32 ) then
     Ydot := DTate + 32 - Y1;

   Bmap.Canvas.CopyMode := cmSrcCopy;
   RectB := Rect(X1,Y1,X1 + Xdot ,Y1 + Ydot);
   Bmap.Canvas.CopyRect(RectB,BackBmap.Canvas,RectB);
end;



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

procedure TRein06.tmr1Timer(Sender: TObject);
begin
  ChrDi(Chr0.Used,Chr0.Sban,Chr0.Xpos,Chr0.Ypos,MakeBmap);
  ChrDi(Chr1.Used,Chr1.Sban,Chr1.Xpos,Chr1.Ypos,MakeBmap);
  ChrDi(Chr2.Used,Chr2.Sban,Chr2.Xpos,Chr2.Ypos,MakeBmap);

   Rein06.Canvas.CopyMode := cmSrcCopy;
   RectM := Rect(16,16,DYoko + 16,DTate + 16);   //实际显示画面+16
   RectD := Rect(0,0,DYoko ,DTate);
   Rein06.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM);

   ChrCl(Chr0.Used,Chr0.Sban,Chr0.Xpos,Chr0.Ypos,MakeBmap);
   ChrCl(Chr1.Used,Chr1.Sban,Chr1.Xpos,Chr1.Ypos,MakeBmap);
   ChrCl(Chr2.Used,Chr2.Sban,Chr2.Xpos,Chr2.Ypos,MakeBmap);

end;

procedure TRein06.tmr2Timer(Sender: TObject);
begin
  NewXY( Chr0.Smov,Chr0.Xpos,Chr0.Ypos);
  NewXY( Chr1.Smov,Chr1.Xpos,Chr1.Ypos);
  NewXY( Chr2.Smov,Chr2.Xpos,Chr2.Ypos);
end;

end.

学习点 :

角色的 定义?

函数 功能的一步步划分?

角色图像的边界判断?

角色 移动 贴图 的步骤?

好像是贴上角色, 显示出来,再 擦掉它 这个循环,

好像学到了点东西,但是让我写这个程序,又写不出来

只是将代码敲到了 电脑里面。