FireMonkey3D之中国象棋程序(一)界面设计

FireMonkey3D之中国象棋程序(一)界面设计

声明:本程序设计参考象棋巫师源码(开发工具dephi 11,建议用delphi 10.3以上版本)。

第一步我们设计图形界面,显示初始化棋局。效果如下图:

 我们先做个3D象棋子控件(请看我的博客关于FireMonkey3D的文章:万能控件Mesh详解),源码如下:

unit ChessPiece;

interface

uses
  System.SysUtils,System.Types,System.UITypes,System.Classes, FMX.Types, FMX.Controls3D, FMX.Objects3D,FMX.Types3D,
  FMX.Materials,System.Math.Vectors,FMX.Graphics,System.Math,System.RTLConsts;
type
  TChessPiece = class(TControl3D)
  private
    FMat:TLightMaterial;
    FBitmap:TTextureBitmap;
	  FChessName:string;
    FSide,FID:Byte;//ID为棋子序号
    FColor:TAlphaColor;
    procedure SetChessName(const Value:string);
    procedure SetSide(const Value:Byte);
	  procedure SetID(const Value:Byte);
    procedure DrawPiece;
  protected
    procedure Render; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property ChessName:string  read FChessName write SetChessName;
	  property Side:Byte  read FSide write SetSide default 0;
	  property id:Byte read FID write SetID;
    property Cursor default crDefault;
    property DragMode default TDragMode.dmManual;
    property Position;
    property Scale;
    property RotationAngle;
    property Locked default False;
    property Width;
    property Height;
    property Depth nodefault;
    property Opacity nodefault;
    property Projection;
    property HitTest default True;
    property VisibleContextMenu default True;
    property Visible default True;
    property ZWrite default True;
    property OnDragEnter;
    property OnDragLeave;
    property OnDragOver;
    property OnDragDrop;
    property OnDragEnd;
    property OnClick;
    property OnDblClick;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnMouseWheel;
    property OnMouseEnter;
    property OnMouseLeave;
    property OnKeyDown;
    property OnKeyUp;
    property OnRender;
  end;
procedure Register;

implementation
procedure TChessPiece.DrawPiece;
var
  Rect:TRectF;
begin
  with FBitmap do
  begin
	Canvas.BeginScene;
  Clear($FFFFFFFF);
  Rect:=TRectF.Create(2,2,98,98);
  Canvas.Stroke.Thickness:=2;
  Canvas.Stroke.Color:=FColor;
	Canvas.DrawEllipse(Rect,1);
  Canvas.Fill.Color:=FColor;
	Canvas.FillText(Rect,FChessName,false,1,[TFillTextFlag.RightToLeft],TTextAlign.Center,TTextAlign.Center);
	Canvas.EndScene;
  end;
  Repaint;
end;

constructor TChessPiece.Create(AOwner: TComponent);
begin
  inherited;
  FColor:=$FFFF0000;
  FChessName:="车";
  FMat:=TLightMaterial.Create;
  FMat.Emissive:=TAlphaColorRec.Burlywood;
  FBitmap:=TTextureBitmap.Create;
  with FBitmap do
  begin
    SetSize(100,200);
    Canvas.Font.Family:="方正隶书繁体";
	  Canvas.Font.Size:=85;
  end;
  DrawPiece;
end;

destructor TChessPiece.Destroy;
begin
  FMat.Free;
  FBitmap.Free;
  inherited;
  
end;
procedure TChessPiece.SetChessName(const Value:string);
begin
  if FChessName <> Value then
  begin
    FChessName := Value;
    DrawPiece;
  end;
end;
procedure TChessPiece.SetSide(const Value:Byte);
begin
  if FSide <> Value then
  begin
    FSide := Value;
    case FSide of
         0:  FColor:=$FFFF0000;
         1:  FColor:=$FF24747D;
    end;
    DrawPiece;
  end;
end;
procedure TChessPiece.SetID(const Value:Byte);
begin
  if FID<>value then
     FID:=Value;
end;
procedure TChessPiece.Render;
var
  i,j,k,VH,VW,AA,BB,M:Integer;
  indice:array of  Integer;
  P,P1:TPoint3D;
  Ver:TVertexBuffer;
  Idx:TIndexBuffer;
  Pt:TPointF;
  Angle,H,D,R:Single;//H:前后圆的半径Height/2,R:棋子周边圆弧的半径,D棋子的厚度Height/5
begin
  VH:=32;VW:=12;
  indice:=[0,1,3,0,3,2];
  H:=0.5*Height;
  D:=0.2*Height;
  R:=D/sin(DegToRad(48));
  FMat.Texture:=nil;
  FMat.Texture:=FBitmap.Texture;
  Ver:=TVertexBuffer.Create([TVertexFormat.Vertex,TVertexFormat.Normal,TVertexFormat.TexCoord0],VH*VW*4+VH*2);
  Idx:=TIndexBuffer.Create(VH*6*VW+VH*6-12,TIndexFormat.UInt32);
  AA:=0;BB:=0;
  //Around棋子周边
  for I := 0 to VH-1 do
  for J := 0 to VW-1 do
  begin
    for k := 0 to 1 do
    begin
      Angle:=DegToRad((318-(j+k)*8));
      P:=Point3D(0,R*sin(Angle),R*Cos(Angle));
      P1:=P/R;
      P.Offset(0,-R*Sin(DegToRad(318))-H,0);
      Ver.Vertices[AA+k*2]:=P*TMatrix3D.CreateRotationZ(2*Pi/VH*i);
      Ver.Normals[AA+k*2]:=P1*TMatrix3D.CreateRotationZ(2*Pi/VH*i);
	    Ver.Vertices[AA+k*2+1]:=P*TMatrix3D.CreateRotationZ(2*Pi/VH*(i+1));
      Ver.Normals[AA+k*2+1]:=P1*TMatrix3D.CreateRotationZ(2*Pi/VH*(i+1));
	    //按横向、纵向细分一个贴图
      Ver.TexCoord0[AA+k*2]:=PointF(1/12*(J+k),I/128+0.5);
      Ver.TexCoord0[AA+k*2+1]:=PointF(1/12*(J+k),(I+1)/128+0.5);
    end;
    inc(AA,4);
    for k :=0 to 5 do
    begin
      Idx.Indices[BB]:=indice[k]+4*(BB div 6);
      inc(BB);
    end;
  end;
  //Front Back 前后圆
  M:=AA;
  for I := 0 to VH-1 do
  begin
    P:=Point3D(0,-H,-D);
    Ver.Vertices[AA]:=P*TMatrix3D.CreateRotationZ(2*Pi/VH*i);
    Ver.Normals[AA]:=Point3D(0,0,-1);
    Pt:=PointF(0,-0.5).Rotate(2*Pi/VH*i);
    Pt.Offset(0.5,0.5);
    Ver.TexCoord0[AA]:=PointF(Pt.x,Pt.y/2);;
    P:=Point3D(0,-H,D);
    Ver.Vertices[AA+1]:=P*TMatrix3D.CreateRotationZ(2*Pi/VH*i);
    Ver.Normals[AA+1]:=Point3D(0,0,1);
    Ver.TexCoord0[AA+1]:=PointF(Pt.x,Pt.y/2+0.5);
    Inc(AA,2);
  end;
  for I := 0 to VH-3 do
  begin
    Idx.Indices[BB]:=M+2+I*2;
    Idx.Indices[BB+1]:=M+4+I*2;
    Idx.Indices[BB+2]:=M;
    Idx.Indices[BB+3]:=M+5+I*2;
    Idx.Indices[BB+4]:=M+3+i*2;
    Idx.Indices[BB+5]:=M+1;
    Inc(BB,6);
  end;
  Context.DrawTriangles(ver,idx,FMat,Opacity);
  Ver.Free;
  Idx.Free;
end;
procedure Register;
begin
  RegisterComponents("3D Others", [TChessPiece]);
end;

end.
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » FireMonkey3D之中国象棋程序(一)界面设计