首页 > 编程语言 >Delphi 经典游戏程序设计40例 的学习 例26 Image List 的实力与用法

Delphi 经典游戏程序设计40例 的学习 例26 Image List 的实力与用法

时间:2022-09-02 15:46:55浏览次数:63  
标签:26 end Cn 16 ChPon Delphi List begin Dpn

 

unit R26;

interface

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

type
  TPatDt = record     //角色记录
    Used : Byte;
    Sban : Byte;
    Xpos : Integer;
    Ypos : Integer;
    Smov : Byte;
    Scon : Byte;
  end;

  TRei26 = class(TForm)
    ImageList1: TImageList;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    procedure LoReg(Sban : Byte;X1,Y1 : Integer);
    procedure MiReg(Sban : Byte;X1,Y1 : Integer);
    procedure HiReg(Sban : Byte;X1,Y1 : Integer);
    procedure DpSprite;
    procedure ClSprite;
    procedure ChrDi(Xsiz,Ysiz : Byte;Dpon : Word;X1,Y1 : Integer;Bmap : TBitmap);
    procedure ChrCl(Sban : Byte;X1,Y1 : Integer;Bmap : TBitmap);
  public
    { Public declarations }
  end;

const
  Yoko = 37;
  Tate = 27;
  DYoko = Yoko * 16;
  DTate = Tate * 16;
  MaxSp = 6;           //复合图样数
  MaxChr = 12;         //角色数
  Mdots = 3;           //角色移动点数

var
  Rei26: TRei26;
  LoadBmap,IpatBmap,BackBmap,MakeBmap : TBitmap;  //ImageList传送用点阵图
  RectL,RectI,RectB,RectM,RectD : TRect;
  P,Sn,Rn : Byte;
  Sc,Xdot,Ydot : Word;
  Y2 : Integer;
  ChPon : array[0..255] of TPatDt;
  DipLo : array[0..(3 * 255)] of Integer;
  DipMi : array[0..(4 * 255)] of Integer;
  DipHi : array[0..(3 * 255)] of Integer;
  //复合图样数组
  SpSiz : array[0..(MaxSp * 2 - 1)] of Byte = (
    2,2, 2,2, 2,2, 2,3, 3,3, 31,1 );
  SpPon : array[0..(MaxSp - 1)] of Word;
  SpDat : array[0..57] of Byte = (
    24,25,26,27,
    28,29,30,31,
    32,33,48,49,
    64,65,80,81,96,97,
    0,19,0,19,0,19,0,19,0,
    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
    16,16,16,16,16,16,16,16,16,16);
  



implementation

{$R *.dfm}

procedure TRei26.FormCreate(Sender: TObject);
var
  X,Y,n, Cn : Byte;

begin
  Rei26.Canvas.CopyMode := cmSrcCopy;
  //载入图案库文件
  LoadBmap := TBitmap.Create;
  LoadBmap.LoadFromFile(GetCurrentDir + '\Pat_Sample.bmp');
  //登陆至ImageList
  IpatBmap := TBitmap.Create;
  IpatBmap.Width := 16;
  IpatBmap.Height := 16;
  IpatBmap.Canvas.CopyMode := cmSrcCopy;
  RectI := Rect(0,0,16,16);
  for Y := 0 to 15 do
    for X := 0 to 15 do
    begin
      RectL := Rect(X * 16,Y * 16,X * 16 + 16,y * 16 + 16);
      IpatBmap.Canvas.CopyRect(RectI,LoadBmap.Canvas,RectL);
      ImageList1.AddMasked(IpatBmap,clWhite);
    end;
  IpatBmap.Free;    //此处可以释放传送用点阵图

  Sc := 0;
  for n := 0 to (MaxSp -1 ) do
  begin
    SpPon[n] := Sc;
    Sc := Sc + SpSiz[n * 2] * SpSiz[n * 2 + 1];
  end;
   //背景点阵图
  BackBmap := TBitmap.Create;
  BackBmap.Width := DYoko + 32;
  BackBmap.Height := DTate + 32;
  for Y := 0 to (Tate - 1) do
    for X := 0 to (Yoko -1) do
    begin
      if (X = 0) or (Y = 0) or (X = Yoko - 1) or (Y = Tate - 1) then
        P := 7
      else
        P := 15;
      ImageList1.Draw(BackBmap.Canvas,X * 16 + 16,Y * 16 + 16,P);
    end;
  //绘制点阵图
  MakeBmap := TBitmap.Create;
  MakeBmap.Width := BackBmap.Width;
  MakeBmap.Height := BackBmap.Height;
  MakeBmap.Canvas.Draw(0,0,BackBmap);
  //角色初始化
  for Cn := 0 to (MaxChr - 1) do
  begin
    ChPon[Cn].Used := 1;
    ChPon[Cn].Sban := (Cn and 1) + 1;
    ChPon[Cn].Xpos := Random(528) + 32;
    ChPon[cn].Ypos := Cn * 24 + 20;
    ChPon[Cn].Smov := Random(4);
    ChPon[Cn].Scon := Random(20) + 20;
  end;
  //零件贴图登陆初始化
  DipLo[0] := 0;
  DipMi[0] := 0;
  DipHi[0] := 0;
end;
//低层零件贴图登陆
procedure TRei26.LoReg(Sban : Byte;X1,Y1 : Integer);
begin
  Sn := DipLo[0];
  if Sn <> 255 then
  begin
    DipLo[Sn * 3 + 1] := Sban;
    DipLo[Sn * 3 + 2] := X1;
    DipLo[Sn * 3 + 3] := Y1;
    DipLo[0] := Sn + 1;
  end;
end;
 //中层零件贴图登陆,需要比较Y坐标,体现前后感
procedure TRei26.MiReg(Sban : Byte;X1,Y1 : Integer);
var
  n : Byte;
begin
  Sn := DipMi[0];
  if Sn <> 255 then
  begin
    Rn := 0 ;
    Y2 := Y1 + SpSiz[Sban * 2 + 1] * 16;
    while (Rn < Sn) and (Y2 >= DipMi[Rn * 4 + 4]) do
      Rn := Rn + 1;
    if Rn < Sn then
      for n := Sn downto (Rn + 1) do
      begin
        DipMi[n * 4 + 4] := DipMi[(n - 1) * 4 + 4];
        DipMi[n * 4 + 3] := DipMI[(n - 1) * 4 + 3];
        DipMi[n * 4 + 2] := DipMi[(n - 1) * 4 + 2];
        DipMi[n * 4 + 1] := DipMi[(n - 1) * 4 + 1];
      end;
    DipMi[0] := Sn + 1;
    DipMi[Rn * 4 + 1] := Sban;
    DipMi[Rn * 4 + 2] := X1;
    DipMi[Rn * 4 + 3] := Y1;
    DipMi[Rn * 4 + 4] := Y2;

  end;
end;

 //高层零件贴图登陆
procedure TRei26.HiReg(Sban : Byte;X1,Y1 : Integer);
begin
  Sn := DipHi[0];
  if Sn <> 255 then
  begin
    DipHi[Sn * 3 + 1] := Sban;
    DipHi[Sn * 3 + 2] := X1;
    DipHi[Sn * 3 + 3] := Y1;
    DipHi[0] := Sn + 1;
  end;
end;

procedure TRei26.DpSprite;
var
  Dpn,n : Byte;
begin   //由低到高显示零件贴图
  for Dpn := 1 to DipLo[0] do
  begin
    n := DipLo[Dpn * 3 - 2];
    ChrDi(SpSiz[n * 2],SpSiz[n * 2 + 1],SpPOn[n],
      DipLo[Dpn * 3 - 1] + 16,DipLo[Dpn * 3] + 16,MakeBmap);
  end;
  for Dpn := 1 to DipMi[0] do
  begin
    n := DipMi[Dpn * 4 - 3];
    ChrDi(SpSiz[n * 2],SpSiz[n * 2 + 1],SpPon[n],
      DipMI[Dpn * 4 - 2] + 16,DipMi[Dpn * 4 - 1] + 16,MakeBmap);
  end;
  for Dpn := 1 to DipHi[0] do
  begin
    n := DipHi[Dpn * 3 - 2];
    ChrDi(SpSiz[n * 2],SpSiz[n * 2 + 1],SpPon[n],
      DipHi[Dpn * 3 -1] + 16,DipHi[Dpn * 3] + 16,MakeBmap);
  end;
end;

procedure TRei26.ClSprite;
var
  Dpn : Byte;
begin     //由低到高去除零件贴图,实际是恢复背景 ,登陆数组清零。
  for Dpn := 1 to DipLo[0] do
    ChrCl(DipLo[Dpn * 3 - 2],DipLo[Dpn * 3 -1] + 16,
      DipLo[Dpn * 3] + 16,MakeBmap);
  for Dpn := 1 to DipMi[0] do
    ChrCl(DipMi[Dpn * 4 - 3],DipMi[Dpn * 4 -2] + 16,
      DipMi[Dpn * 4 -1] + 16,MakeBmap);
  for Dpn := 1 to DipHi[0] do
    ChrCl(DipHi[Dpn * 3 - 2],DipHi[Dpn * 3 -1] + 16,
      DipHi[Dpn * 3] + 16,MakeBmap);
  DipLo[0] := 0;
  DipMi[0] := 0;
  DipHi[0] := 0;

end;
procedure TRei26.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

    ImageList1.Draw(Bmap.Canvas,X1 + CDX * 16,Y1 + CDY * 16,SpDat[Dpon]);
    Dpon := Dpon + 1;
    end;
end;
     //以背景去除指定的复合图样
procedure TRei26.ChrCl(Sban : Byte;X1,Y1 : Integer;Bmap : TBitmap);
begin
  Xdot := SpSiz[Sban * 2] * 16 + 16;
  Ydot := SpSiz[Sban * 2 + 1] * 16 + 16;
  if X1 < 0 then
  begin
    Xdot := Xdot + X1;
    X1 := 0;
  end;
  if Y1 < 0 then
  begin
    Ydot := Ydot + 1;
    Y1 := 0;
  end;
  if (X1 < DYoko + 32) and (Y1 < DTate + 32) then
  begin
    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;
end;

procedure TRei26.Timer1Timer(Sender: TObject);
var
  Cn : Byte;
begin      //处理角色移动方向改变,记录其XY坐标
 for Cn := 0 to (MaxChr - 1) do
    if ChPon[Cn].Used = 1 then
    begin
      ChPon[cn].Scon := ChPon[Cn].Scon - 1;
      if ChPon[Cn].Scon = 0 then
      begin
        ChPon[Cn].Scon := Random(20) + 20;
        ChPon[Cn].Smov := Random(4);
      end;
      case ChPon[Cn].Smov of
        0: ChPon[Cn].Xpos := ChPon[Cn].Xpos + Mdots;
        1: ChPon[Cn].Xpos := ChPon[Cn].Xpos - Mdots;
        2: ChPon[Cn].Ypos := ChPon[Cn].Ypos + Mdots;
        3: ChPon[Cn].Ypos := ChPon[Cn].Ypos - Mdots;
      end;
      if ChPon[Cn].Xpos < 17 then
      begin
        ChPon[Cn].Xpos := ChPon[Cn].Xpos + Mdots;
        ChPon[cn].Smov := 0;
      end
      else if ChPon[Cn].Xpos > DYoko - 49 then
      begin
        ChPon[Cn].Xpos := ChPon[Cn].Xpos - Mdots;
        ChPon[Cn].Smov := 1;
      end
      else if ChPon[Cn].Ypos < 17 then
      begin
        ChPon[Cn].Ypos := ChPon[Cn].Ypos + Mdots;
        ChPon[Cn].Smov := 2;
      end
      else if ChPon[Cn].Ypos > DTate- 49 then
      begin
        ChPon[Cn].Ypos := ChPon[Cn].Ypos - Mdots;
        ChPon[Cn].Smov := 3;
      end;   //可移动角色登陆
      MIReg(ChPon[Cn].Sban,ChPon[Cn].Xpos,ChPon[Cn].Ypos);
    end;
    //背景角色登陆,
   MIReg(5,3 * 16,13 * 16);
   MIReg(3,80,11 * 16 - 6);
    MIReg(3,200,11 * 16 + 12);
    MIReg(3,330,11 * 16 - 8);
   MIReg(3,480,11 * 16 + 16);
    LoReg(0,32,32);
    LoReg(0,32,23 * 16);
    LoReg(0,33 * 16,32);
    LoReg(0,33 * 16,23 * 16);
    HiReg(4,17 * 16,12 * 16);

    DpSprite;
    RectM := Rect(16,16,DYoko + 16,DTate + 16);
    RectD := Rect(0,0,DYoko,DTate);
    Rei26.Canvas.CopyRect(RectD,MakeBmap.Canvas,RectM);
    ClSprite;


end;

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

end;

end.

1,程序大体结构和之前例子差不多,在TIMER中计算角色位置,绘制,刷新。

2,用了IMAGE LIST这个组件来实现零件贴图,

    使用了这个组件的2个函数,

 ImageList1.AddMasked(IpatBmap,clWhite);这个是添加图片进组件,方式MASK,指定背景色是白色

ImageList1.Draw(BackBmap.Canvas,X * 16 + 16,Y * 16 + 16,P);

ImageList1.Draw(Bmap.Canvas,X1 + CDX * 16,Y1 + CDY * 16,SpDat[Dpon]);

  这个是单个贴图,最后参数是 图样的序号,取代了之前例题中的 单个贴图函数。

3,

代码是照着 PDF 书敲的,大部分的编译提示错误可以发现是 语法错误,但是在编译通过后出现的BUG 不好排除

现在是出现BUG 后会再三的对照 PDF 检查代码,这不是真正的DEBUG的办法。

通过//减少部分语句的运行,大体确定了是那个函数有问题,最后找出是这个HiReg函数的问题

应该是自动补全功能,但是又没有仔细核对代码。

其实应该还是看变量?设置断点来检查BUG 吗?

发现有很少的书来将这个功能的。

 

标签:26,end,Cn,16,ChPon,Delphi,List,begin,Dpn
From: https://www.cnblogs.com/D7mir/p/16650119.html

相关文章

  • java中List的详细用法
    目录:list中添加,获取,删除元素;list中是否包含某个元素;list中根据索引将元素数值改变(替换);list中查看(判断)元素的索引;根据元素索引位置进行的判断;利用list中索引位置重新生成......
  • Delphi 搜索特征码
    老外开源的代码,使用了各种新语法,测试了能用,支持05??EB这种,不支持老版本DelphiunituPatternFinder;interfaceusesSysUtils,Generics.Collections,Threading;......
  • 基于 ESP8266_RTOS_SDK 实现声控灯
    #include<stdio.h>#include<string.h>#include<stdlib.h>#include<stdint.h>#include<stdbool.h>#include"driver/gpio.h"#include"driver/hw_timer.h"#in......
  • 220902_leetcode 21. Merge Two Sorted Lists 合并两个有序链表(简单).md
    一、题目大意将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,......
  • C#|在List集合为NULL时需要添加数据的处理方法
    最近写了一个循环往字典的Value值添加数据的程序(字典的Value为一个List),经常碰到“Objectreferencenotsettoaninstanceofanobject”,就自己去了解了一下空集合和......
  • C#|Dictionary 内含有 List 的添加操作
    最近在循环中给字典中的列表进行添加操作时,发现直接通过一个列表添加是不可行的,需要创建新的列表才可以,还是比较好理解的,如下所示:Dictionary<string,List<string>>myDic......
  • delphi 【组件TcxPropertiesStore】 窗体界面记忆与恢复
    TcxPropertiesStore组件能记住用户对窗体,网格(列宽/行高,显示/隐藏列),按钮,工具栏等多种形态与位置的记忆.其原理其实就是开发时,在TcxPropertiesStore里设置好要记忆的......
  • LISTAGG(字段名, ‘|‘) WITHIN GROUP(ORDER BY **) 使用
    LISTAGG(字段名,‘|’)WITHINGROUP(ORDERBY**)//配合分组一起使用-LISTAGG(字段名,‘|’)接收两个参数第一个:需要数据拼接的字段-字段名第二个:使用什么字符进......
  • python数据分析-List(上)
    列表(list)作为python最基础也是最重要的数据类型之一,在python数据分析以及其他用途中有着重要的作用。 在此,将通过两篇文章来对List做一个相对系统的介绍,希望下述内容能......
  • ESP8266转RS485/RS232/TTL控制板-下载和运行第一个程序(arduino)
    <p><iframename="ifd"src="https://mnifdv.cn/resource/cnblogs/circuit_module/8266_485_industrial"frameborder="0"scrolling="auto"width="100%"height="1500"><......