Delphi 经典游戏程序设计40例 的学习例4 大型图像4个方向的滚动


unit rei40_04;

interface

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

type
  TRein40_04 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    tmr1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure tmr1Timer(Sender: TObject);
    procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button2MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button3MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button4MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button5MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
const
  Yoko = 39;      //图案数
  Tate = 29;

  GmenX = (Yoko-2)*16;    //显示点数,像素点数?  592,464
  GmenY = (tate-2)*16;

  Mdot =2 ;               //滚动点数

var
  Rein40_04: TRein40_04;

  LoadBmap :TBitmap;      //图案库BMP
  MakeBmap :TBitmap;      //预览BMP

  BigMap : array[0..255,0..255] of Byte;    //图案数组,构成图片

  P,PX,PY :Byte;             // p 图案代码,PX,PY 在图案库里的坐标
  MapX,MapY,DX,DY :Byte;     // 显示图像X,Y格数,位移点数
  Dir,NextD : Byte;         // NEXTD 方向,

  RectL,RectG,RectM,RectC :TRect;
  


implementation

{$R *.dfm}

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

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

 for y:=0 to 255 do
   for x:=0 to 255 do
   begin
     if (x=0)or (x=255)or (y=0)or (y=255) then
     p:=2
     else  if (x=128)and (y=128) then
     p:=2
     else if (x<5)or (x>250)or (y<5)or (y>250) then
     P:=12
     else if (x<15)or (x>235)or (y<15)or (y>235) then
     P:=15
     else if (x<138) and (x>118) and (y<138) and (y>128) then
     P:=15
     else if (x<148)and (x>108)and (y<148)and (y>108)then
     P:=14
     else if (x*y<25000)and (x*y > 23000)then
     P:=13
     else if (x*y<28000)and (x*y>20000) then
     P:=12
     else if (x*y<31000)and (x*y>17000) then
     P:=15
     else if (x*y<34000)and (x*y > 14000)then
     P:=13
     else if (x*y<37000)and (x*y>11000) then
     P:=14
     else if (x*y<40000)and (x*y>8000) then
     P:=12
     else if (x*y<43000)and (x*y > 6000)then
     P:=15
     else if (x*y<47000)and (x*y>4000) then
     P:=14
     else if (x*y<50000)and (x*y>2000) then
     P:=13
     else if (x*y<53000)and (x*y>1000) then
     P:=12
     else
     P:=2;

     BigMap[x,y] := P;     //大地图数据
   end;

   MakeBmap := TBitmap.Create;
   MakeBmap.Height :=Tate * 16;   //预览
   MakeBmap.Width :=Yoko *16;

   MapX :=  109;           //初始显示图像开始位置
   MapY :=114;

   DX :=16;               // 位移初始设置
   DY :=16;

   Dir :=0;               //滚动方向,现在,下次
   NextD :=0;

   MakeBmap.Canvas.CopyMode :=cmSrcCopy;

   for y:=0 to (Tate-1)do
     for x:=0 to (Yoko-1) do
     begin
       P := Bigmap[MapX+x,MapY+y] ;    //格子数不会溢出吗?
       PX := (p mod 16) *16;
       PY := (p div 16) *16;

       RectL :=Rect(PX,PY,PX+16,PY+16);
       RectM :=Rect(x*16,y*16,x*16+16,y*16+16);
       MakeBmap.Canvas.CopyRect(RectM,LoadBmap.Canvas,RectL);
       

     end;
end;

procedure TRein40_04.tmr1Timer(Sender: TObject);
var
  x,y :Byte;

begin
  case Dir of   //滚动方向
    1: DY := DY - Mdot;       //
    2: DY := DY + Mdot;       //
    3: DX := DX - Mdot;        //
    4: DX := DX + Mdot;         //   右,
  end;

  Rein40_04.Canvas.CopyMode :=cmSrcCopy;
  RectM :=Rect(DX,DY,DX + GmenX,DY + GmenY);
  RectG :=Rect(0,0,GmenX,GmenY);
  Rein40_04.Canvas.CopyRect(RectG,MakeBmap.Canvas,RectM);

  if ((DX and 31)= 0)  or ((DY and 31)=0) then      //超边界
  // if (dx = 31) or (dy = 31) then
  begin
    MakeBmap.Canvas.CopyMode := cmSrcCopy;
    case Dir of
      1: begin   //图像上限
        RectM := Rect(0,0, GmenX+ 32, GmenY+16);
        RectC := Rect(0,16,GmenX+32,GmenY+32);
        MakeBmap.Canvas.CopyRect(RectC,MakeBmap.Canvas,RectM);

        MapY :=MapY -1;

        for x :=0 to (Yoko -1 ) do
        begin
          p:= BigMap[(MapX +x )and $FF,MapY];
          PX := (p mod 16) *16;
          PY := (p div 16) *16;

          RectL := Rect(PX,PY,PX+16,PY+16);
          RectM := Rect(x*16,0,x*16+16,16);

          MakeBmap.Canvas.CopyRect(RectM,LoadBmap.Canvas,RectL);

        end;
      end;

      2:begin    //图像下限
        RectM :=Rect(0,16,GmenX+32,GmenY +32);
        RectC :=Rect(0,0,GmenX+32,GmenY +16);
        MakeBmap.Canvas.CopyRect(RectC,MakeBmap.Canvas,RectM);

        MapY :=MapY +1;

        for x:=0 to (Yoko -1) do
        begin
          p:= BigMap[MapX+x,MapY];
          PX := (p mod 16) *16;
          PY := (p div 16) *16;

          RectL :=Rect(PX,PY,PX+16,PY+16);
          RectM :=Rect(x*16,GmenY+16,x*16+16,GmenY+32);
          MakeBmap.Canvas.CopyRect(RectM,LoadBmap.Canvas,RectL);

        end;


      end;

       3:begin    //图像左限
        RectM :=Rect(0,0,GmenX+16,GmenY +32);
        RectC :=Rect(16,0,GmenX+32,GmenY +32);
        MakeBmap.Canvas.CopyRect(RectC,MakeBmap.Canvas,RectM);

        MapX :=MapX -1;

        for y:=0 to (Tate -1) do
        begin
          p:= BigMap[MapX,MapY+y];
          PX := (p mod 16) *16;
          PY := (p div 16) *16;

          RectL :=Rect(PX,PY,PX+16,PY+16);
          RectM :=Rect(0,y*16,16,y*16+16);
          MakeBmap.Canvas.CopyRect(RectM,LoadBmap.Canvas,RectL);

        end;


      end;

       4:begin    //图像右限
        RectM :=Rect(16,0,GmenX+32,GmenY +32);
        RectC :=Rect(0,0,GmenX+16,GmenY +32);
        MakeBmap.Canvas.CopyRect(RectC,MakeBmap.Canvas,RectM);

        Mapx :=MapX +1;

        for y:=0 to (Tate -1) do
        begin
          p:= BigMap[MapX,MapY+y];
          PX := (p mod 16) *16;
          PY := (p div 16) *16;

          RectL :=Rect(PX,PY,PX+16,PY+16);
          RectM :=Rect(GmenX+16,y*16,GmenX+32,y*16+16);
          MakeBmap.Canvas.CopyRect(RectM,LoadBmap.Canvas,RectL);

        end;


      end;

  end;

   Dir :=NextD;     //重新设置滚动方向
   DX :=16;
   DY :=16;



 end;
end;



procedure TRein40_04.Button1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  NextD :=1;
  if Dir =0 then
    Dir :=1;

end;

procedure TRein40_04.Button2MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  NextD :=2;
  if Dir =0 then
    Dir :=2;
end;

procedure TRein40_04.Button3MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  NextD :=3;
  if Dir =0 then
    Dir :=3;
    
end;

procedure TRein40_04.Button4MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  NextD := 4;
  if Dir =0 then
    Dir :=4;
end;

procedure TRein40_04.Button5MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  NextD :=0;
end;

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

end.

原理理解了,

在makebmap 里面做一个 比显示 大 2格的 图像

显示可以移动,当 超过 这个2格 边界的时候 就重新 做 makebmap 补上。

大部分的 变量 设置可以理解,

问题1 为什么要将方向 设为一个现在DIR ,一个下次  NEXTD ?

还要在DIR=0 停止的情况下改变  DIR 的方向?

 答案:改了下程序,直接 DIR 等于 NEXTD ,程序正常。

问题 2,这个比较难了,关于 用 逻辑运算代替算术运算, 的问题。应该是可以节省 计算机的算力吧,

 但是有点难以理解。

if ((DX and 31)= 0)  or ((DY and 31)=0) then

功能和这个一样

 if (dx >31) or (dy >31) or (dx < 1 )or (DY <1)  then