IsoLandscape.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:8k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit IsoLandscape;
  2. //---------------------------------------------------------------------------
  3. // Isometric Landscape with "Wave" effect
  4. // Written by Yuriy Kotsarenko (lifepower@mail333.com)
  5. //
  6. // This unit was taken from very old sources and I never got my hands on
  7. // rewriting this. The current implementation is... let's say not very good.
  8. //---------------------------------------------------------------------------
  9. interface
  10. //---------------------------------------------------------------------------
  11. const
  12.  Undefined= -1;
  13.  TileWidth = 64;
  14.  TileHeight = 32;
  15. //---------------------------------------------------------------------------
  16. type
  17.  MapRec = record
  18.   Heights: array[0..3] of Byte;
  19.   Light  : array[0..3] of Byte;
  20.  end;
  21. //---------------------------------------------------------------------------
  22.  TLand = class
  23.  private
  24.   Wave: array[0..63, 0..63] of Real;
  25.   function Sine(Value: Real): Real;
  26.   procedure CalculateWave();
  27.   procedure CalculateHeights();
  28.  public
  29.   XView,
  30.   YView,
  31.   Width,
  32.   Height: Integer;
  33.   XViewFloat,
  34.   YViewFloat,
  35.   XViewVel,
  36.   YViewVel: Real;
  37.   Alpha,
  38.   Beta,
  39.   Gamma: Real;
  40.   Grid: Boolean;
  41.   Map: array[0..127, 0..63] of MapRec;
  42.   constructor Create();
  43.   function SquareHeight(Xp, Yp, Corner: Integer): Integer;
  44.   function SquareLight(Xp, Yp, Corner: Integer): Integer;
  45.   procedure Render();
  46.   procedure Process();
  47.  end;
  48. //---------------------------------------------------------------------------
  49. implementation
  50. uses
  51.  IsoUtil, AsphyreTypes, AsphyreDevices, AsphyreEffects;
  52. //---------------------------------------------------------------------------
  53. constructor TLand.Create();
  54. begin
  55.  inherited;
  56.  FillChar(Map, SizeOf(Map), 0);
  57.  Width:= 64;
  58.  Height:= 128;
  59.  XView:= 1280;
  60.  YView:= 768;
  61.  XViewFloat:= 1280;
  62.  YViewFloat:= 768;
  63.  XViewVel:= 0;
  64.  YViewVel:= 0;
  65.  Alpha:= 0;
  66.  Beta:= 0;
  67.  Gamma:= 0;
  68.  CalculateWave();
  69.  CalculateHeights();
  70. end;
  71. //---------------------------------------------------------------------------
  72. function TLand.Sine(Value: Real): Real;
  73. begin
  74.  Result:= (Sin(Value * pi) + 1) / 2;
  75. end;
  76. //---------------------------------------------------------------------------
  77. procedure TLand.CalculateWave();
  78. var
  79.  i, j: Integer;
  80. begin
  81.  for j:= 0 to 63 do
  82.   for i:= 0 to 63 do
  83.    Wave[j, i]:= Sine((i / 8) + Alpha) + (Sine((i / 4) + Beta) / 2) + (Sine((j / 16) + Gamma) / 2);
  84. end;
  85. //---------------------------------------------------------------------------
  86. procedure TLand.CalculateHeights();
  87. var
  88.  i, j, DeltaX, Value, Light, x, y: Integer;
  89. begin
  90.  for j:= 1 to Height - 2 do
  91.   for i:= 1 to Width - 2 do
  92.    begin
  93.     DeltaX:= 1 - (j and $01);
  94.     Iso2Line(I, j + 64, x, y);
  95.     x:= x - 64;
  96.     if (x >= 0)and(y >= 0)and(x < 64)and(y < 64) then
  97.      begin
  98.       Value:= Round(Wave[y, x] * 96) + 32;
  99.      end else Value:= 0;
  100.     Light:= Value;
  101.     if (Light > 255) then Light:= 255;
  102.     Map[j, i].Heights[0]:= Value;
  103.     Map[j, i].Light[0]:= Light;
  104.     Map[j + 1, i - DeltaX].Heights[1]:= Value;
  105.     Map[j + 1, i - DeltaX].Light[1]:= Light;
  106.     Map[j - 1, i - DeltaX].Heights[2]:= Value;
  107.     Map[j - 1, i - DeltaX].Light[2]:= Light;
  108.     Map[j, i - 1].Heights[3]:= Value;
  109.     Map[j, i - 1].Light[3]:= Light;
  110.    end;
  111. end;
  112. //---------------------------------------------------------------------------
  113. function TLand.SquareHeight(Xp, Yp, Corner: Integer): Integer;
  114. begin
  115.  if (Xp < 0) then Xp:= 0;
  116.  if (Yp < 0) then Yp:= 0;
  117.  if (Xp > Width - 1) then Xp:= Width - 1;
  118.  if (Yp > Height - 1) then Yp:= Height - 1;
  119.  Result:= Map[Yp,Xp].Heights[Corner];
  120. end;
  121. //---------------------------------------------------------------------------
  122. function TLand.SquareLight(Xp, Yp, Corner: Integer): Integer;
  123. begin
  124.  if (Xp < 0) then Xp:=0;
  125.  if (Yp < 0) then Yp:=0;
  126.  if (Xp > Width - 1) then Xp:= Width - 1;
  127.  if (Yp > Height - 1) then Yp:= Height - 1;
  128.  Result:= Map[Yp, Xp].Light[Corner];
  129. end;
  130. //---------------------------------------------------------------------------
  131. procedure TLand.Render();
  132. var
  133.  ImageIndex: Integer;
  134.  x, y, Xpos, Ypos, XposAdd, XMap, YMap, TileHWidth, TileHHeight: Integer;
  135. begin
  136.  TileHWidth:= TileWidth div 2;
  137.  TileHHeight:= TileHeight div 2;
  138.  ImageIndex:= Devices[0].Images.Image['water'].ImageIndex;
  139.  // render tiles
  140.  for Y:= -1 to (Integer(Devices[0].Params.BackBufferHeight) div TileHHeight) + 14 do
  141.   begin
  142.    Ymap:= (YView div TileHHeight) + Y;
  143.    Ypos:= (Ymap * TileHHeight) - YView - TileHHeight;
  144.    XposAdd:= ((Ymap and $01) * TileHWidth) - XView - TileHWidth;
  145.    for X:= -1 to (Devices[0].Params.BackBufferWidth div TileWidth) + 2 do
  146.     begin
  147.      Xmap:= (XView div TileWidth) + X;
  148.      Xpos:= (Xmap * TileWidth) + XposAdd;
  149.      if (Xmap >= 0)and(Ymap >= 0)and(Xmap < Width)and(Ymap < Height)and(Map[Ymap, Xmap].Light[0] > 0)
  150.         and(Map[Ymap, Xmap].Light[1] > 0)and(Map[Ymap, Xmap].Light[2] > 0)and(Map[Ymap, Xmap].Light[3] > 0) then
  151.       begin
  152.        Devices[0].Canvas.UseImage(Devices[0].Images[ImageIndex], TexFull4);
  153.        Devices[0].Canvas.TexMap(Point4(Xpos, (Ypos + TileHHeight) -
  154.         SquareHeight(Xmap, Ymap,0), Xpos + TileHWidth, Ypos -
  155.         SquareHeight(Xmap, Ymap, 1), Xpos + TileWidth, (Ypos + TileHHeight) -
  156.         SquareHeight(Xmap,Ymap,3), Xpos + TileHWidth, (Ypos + TileHeight) -
  157.         SquareHeight(Xmap,Ymap,2)), cGray4(SquareLight(Xmap,Ymap,0),
  158.         SquareLight(Xmap,Ymap,1), SquareLight(Xmap,Ymap,3), SquareLight(Xmap,
  159.         Ymap, 2)), fxuAdd or fxfDiffuse);
  160.        // NOTE: if you render GRID *HERE*, it'll stall Asphyre buffering and
  161.        // will reduce performance dramatically!
  162.      end;
  163.     end;{ for X:=-1 to ... }
  164.   end;{ for Y:=-1 to ... }
  165.  if (not Grid) then Exit;
  166.  
  167.  // render grid
  168.  for Y:= -1 to (Integer(Devices[0].Params.BackBufferHeight) div TileHHeight) + 14 do
  169.   begin
  170.    Ymap:= (YView div TileHHeight) + Y;
  171.    Ypos:= (Ymap * TileHHeight) - YView - TileHHeight;
  172.    XposAdd:= ((Ymap and $01) * TileHWidth) - XView - TileHWidth;
  173.    for X:= -1 to (Devices[0].Params.BackBufferWidth div TileWidth) + 2 do
  174.     begin
  175.      Xmap:= (XView div TileWidth) + X;
  176.      Xpos:= (Xmap * TileWidth) + XposAdd;
  177.      if (Xmap >= 0)and(Ymap >= 0)and(Xmap < Width)and(Ymap < Height)and(Map[Ymap, Xmap].Light[0] > 0)
  178.         and(Map[Ymap, Xmap].Light[1] > 0)and(Map[Ymap, Xmap].Light[2] > 0)and(Map[Ymap, Xmap].Light[3] > 0) then
  179.       begin
  180.        Devices[0].Canvas.WireQuadHw(Point4(Xpos, (Ypos + TileHHeight) -
  181.         SquareHeight(Xmap, Ymap,0) - 4, Xpos + TileHWidth, Ypos -
  182.         SquareHeight(Xmap, Ymap, 1) - 4, Xpos + TileWidth, (Ypos +
  183.          TileHHeight) - SquareHeight(Xmap,Ymap,3) - 4, Xpos + TileHWidth,
  184.          (Ypos + TileHeight) - SquareHeight(Xmap,Ymap,2) - 4),
  185.          cColor4($40FFFFFF), fxuBlend);
  186.      end;
  187.     end;{ for X:=-1 to ... }
  188.   end;{ for Y:=-1 to ... }
  189. end;
  190. //---------------------------------------------------------------------------
  191. procedure TLand.Process();
  192. begin
  193.  if (XViewVel > 8) then XViewVel:= 8;
  194.  if (YViewVel > 8) then YViewVel:= 8;
  195.  if (XViewVel < -8) then XViewVel:= -8;
  196.  if (YViewVel < -8) then YViewVel:= -8;
  197.  XViewFloat:= XViewFloat + XViewVel;
  198.  YViewFloat:= YViewFloat + YViewVel;
  199.  if (Abs(XViewVel) < 0.3) then XViewVel:= 0;
  200.  if (Abs(YViewVel) < 0.3) then YViewVel:= 0;
  201.  if (XViewVel > 0) then XViewVel:= XViewVel - 0.5;
  202.  if (YViewVel > 0) then YViewVel:= YViewVel - 0.5;
  203.  if (XViewVel < 0) then XViewVel:= XViewVel + 0.5;
  204.  if (YViewVel < 0) then YViewVel:= YViewVel + 0.5;
  205.  XView:= Round(XViewFloat);
  206.  YView:= Round(YViewFloat);
  207.  Alpha:= Alpha - 0.02;
  208.  Beta:= Beta - 0.0257;
  209.  Gamma:= Gamma - 0.033;
  210.  CalculateWave();
  211.  CalculateHeights();
  212. end;
  213. //---------------------------------------------------------------------------
  214. end.