⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isoengine.pas

📁 一款RPG游戏的引擎可以自己制作一款RPG游戏的引擎可以自己制作
💻 PAS
📖 第 1 页 / 共 4 页
字号:

procedure TIsoMap.SetImageString(ImageIndex: integer; const Value: string);
begin
  if (ImageIndex>=0) then
  begin
    if (length(fImageStrings)<=ImageIndex) then setlength(FIMageSTrings,ImageIndex+1);
      FImagestrings[ImageIndex] := value;
  end;
end;

function TIsoMap.GetImageString(ImageIndex: integer): string;
begin
  if (ImageIndex<0) then Result := ''
  else
  begin
    if (length(fImageStrings)<=ImageIndex) then setlength(FIMageSTrings,ImageIndex+1);
    result := FImageStrings[ImageIndex];
  end;
end;

function TIsoMap._GetCoordCell(c: TCellsCoord): TIsoCell;
begin
   result := IsoMap[c.x,c.y];
end;

function TIsoMap.AddComment(s: string): Integer;
var i,l : integer;
begin
  l :=length(fcomments);
  for i := 0 to l-1 do
  begin
    if (Fcomments[i]=s) then
    begin
      result := i;
      exit;
    end;
  end;
  setlength(fcomments,l+1);
  FComments[l] := s;
  Result := l;
end;

function TIsoMap.GetComment(i: Integer): string;
begin
  if (i<0) then Result := ''
  else
  Result := fcomments[i];
end;

function TIsoMap.GetCellComment(x, y: TGridInt): string;
begin
  result := GetComment(Cell[x,y].CommentID);
end;

procedure TIsoMap.SetCellComment(x, y: TGridInt; s: string);
begin
  if (s='') then IsoMap[x,y].CommentID := -1
  else
  IsoMap[x,y].CommentID := AddComment(s);
end;

procedure TIsoMap.GetVisibleCorners(var MinX, MinY, MaxX, MaxY: Integer);
begin
  MinX := MaxInt(0, XOffset div CellWidth - 1); // first visible left
  MinY := MaxInt(0, YOffset div (fCellHeightdiv2) - 1); // first visible top
//  MaxX := MinInt(MapWidth, MinX + (GetSurfaceWidth div CellWidth) + CellWidth);

  MaxX := MinInt(MapWidth,MinX + (GetSurfaceWidth div CellWidth) + 2);
//  MaxY := MinInt(MapHeight,MinY + GetSurfaceHeight div (FCellHeightdiv2) + 5);
  MaxY := MinInt(MapHeight,MinY + GetSurfaceHeight div (FCellHeightdiv2) + 1);

end;

procedure TIsoMap.SetAllState(state: TCellState);
var Cellx,Celly : TGridInt;
begin
    for cellx := 0 to MapWidth-1 do
      for celly := 0 to MapHeight-1  do
        IsoMap[Cellx,CellY].State := state;
end;

procedure TIsoMap.UpdateArea(p1, p2: TPoint);
var x,y : integer;
  c1,c2 : TCellsCoord;
begin
  if (p1.x < p2.x) then
  begin  c1 := CellAt(p1);  c2 := Cellat(p2);  end
  else
  begin  c1 := Cellat(p2);  c2 := CellAt(p1);  end;

  for x:= c1.X to c2.X do
  begin
    if (c1.Y < c2.Y) then
    begin
      for y := c1.Y to c2.Y do
        AddState(X,Y,[tsDirty]);
    end
    else
      for y := c2.Y to c1.Y do
        AddState(X,Y,[tsDirty]);
  end;
end;

procedure TIsoMap.UpdateArea(x1, y1, x2, y2: integer);
var p1,p2 : Tpoint;
begin
  p1.x := x1; p1.y := y1;
  p2.x := x2; p2.y := y2;
  UpdateArea(p1,p2);
end;

function TIsoMap.CellAt(x, y: integer): TCellsCoord;
var p : TPoint;
begin
    p.x := x; p.y := y;
    result := CellAt(p);
end;


// this set of procedures are the guts of the engine. It draws the map over and over and over...
procedure TIsoMap.CountDirtyCells;  // this isn't neeed but is nice to have for stats sake
var x,y : integer;
begin
dirtyCount := 0;
    for x:= 0 to MapWidth-1 do
      for y := 0 to MapHeight -1 do
        if (tsDirty in IsoMap[x,y].State) then
          inc(dirtycount);
end;

procedure TIsoMap.MarkDirty(x,y : integer);  // mark any cells that are overlapped from this image
var ic,x1,y1,ImageIndex,ImageHeight,ImageWidth,l,f,t : integer;
begin
  ic := GetImageCount;
  f := IsoMap[x,y].AlwaysDisplayFrom;
  t := IsoMap[x,y].AlwaysDisplayTo;
  ImageHeight := CellHeight;
  ImageWidth := CellWidth;

  for l := f to t+1 do
  begin
  gx := x;
  gy := y;
  gl := l;
    if (l<=t) then
      ImageIndex := IsoMap[x,y].imageindexes[l-1].ImageIndex
    else
      if ((IsoMap[x,y].AnimateNext-1)>=0) and
     (IsoMap[x,y].animateNext< Length(IsoMap[x,y].ImageIndexes)) then
        ImageIndex := IsoMap[x,y].ImageIndexes[IsoMap[x,y].AnimateNext-1].ImageIndex
     else
      ImageIndex := -1;
    if (ImageIndex<0) or (ImageIndex>ic) then Continue;
    x1 := GetImageHeight(ImageIndex);
    y1 := GetImageWidth(ImageIndex);
    if (x1>ImageHeight) then ImageHeight := x1;
    if (y1>ImageWidth) then ImageWidth := y1;
  end;
// we should now have the largest height and width of any image this cell will create

  ImageHeight := ImageHeight div FCellHeight; // number of cells changed
  ImageWidth := ImageWidth div FCellWidth;
  for x1 := MaxInt(0,x - ImageWidth) to x do
    for y1 := MaxInt(0,y - ImageHeight) to y do
    if (not(isstate(x1,y1,[tsDirty]))) then
    begin
      Inc(DirtyCount);
      IsoMap[x1,y1].State := IsoMap[x1,y1].State + [tsDirty];
    end;
end;

function TIsoMap.CheckForDirtyOverlap(x,y,l : integer) : boolean; // check to see if we are overlapping any dirty cells
var x1,y1,ImageIndex,ImageHeight,ImageWidth : Integer;
begin
    ImageIndex := IsoMap[x,y].ImageIndexes[l-1].ImageIndex;
    Result := False;
    if (ImageIndex<0) then Exit;
    ImageHeight := GetImageHeight(ImageIndex);
    ImageWidth := GetImageWidth(ImageIndex);
    ImageHeight := ImageHeight div FCellHeight; // number of cells changed
    ImageWidth := ImageWidth div FCellWidth;
    if (ImageWidth=1) and (ImageHeight=1) then Exit;  // this image doesn't cross cell boundries
    Result := True;
    for x1 := MaxInt(0,x-ImageWidth) to x do
      for y1 := MaxInt(0,y-ImageHeight) to y do
        if (isstate(x1,y1,[tsDirty])) then Exit;
    Result := False;
end;


procedure TIsoMap.CheckForDirtyCells;
var x,y,MaxTo,l : integer;
  Marked : Boolean;



begin
  MaxTo := 0;
  l := 0;
  while(l<=MaxTo) do
  begin
    Inc(l);
  // mark off the animation part first, it may affect other things
    for x:= 0 to MapWidth-1 do
      for y := 0 to MapHeight -1 do
      begin
        Marked := False;
        if (IsoMap[x,y].AnimateFrom < IsoMap[x,y].AnimateTo) then
        begin
            if (IsoMap[x,y].AnimateCount=0) then
            begin
              Inc(IsoMap[x,y].AnimateNext);
              if (IsoMap[x,y].AnimateNext > IsoMap[x,y].AnimateTo) then
                IsoMap[x,y].AnimateNext := Isomap[x,y].AnimateFrom;
              IsoMap[x,y].AnimateCount := Isomap[x,y].AnimateSpeed; // reset the counter
            end
            else Dec(IsoMap[x,y].AnimateCount);
            if ((IsoMap[x,y].AnimateNext-1)>=0) and
                (IsoMap[x,y].animateNext< Length(IsoMap[x,y].IMageIndexes)) then
              Marked := -1 <> IsoMap[x,y].ImageIndexes[IsoMap[x,y].AnimateNext-1].ImageIndex;
        end;
        if (IsoMap[x,y].AlwaysDisplayTo > MaxTo) then
          MaxTo := IsoMap[x,y].AlwaysDisplayTo;
        if (l>=IsoMap[x,y].AlwaysDisplayFrom) and (l<=IsoMap[x,y].AlwaysDisplayTo) then
        begin
          Marked := (tsDirty in IsoMap[x,y].State);  // found dirty cell
          if (not Marked) then
          begin   // this cell's clean. How about cell's it may be overlapping?
            Marked := (IsoMap[x,y].ImageIndexes[l-1].ImageIndex <= GetImageCount)
                and CheckForDirtyOverlap(x,y,l) ;// eg a tree behind a building changed
                                         // must update the building because the
                                         // tree might be showing through a window
          end;
        end;
        if (Marked) then
          MarkDirty(x,y);
      end;
  end;
end;





procedure TIsoMap.DrawIsoMap;
var ix,iy,x,y,l,MinX,MinY,MaxX,MaxY : TGridInt;
  MaxTo,ImageWidth,ImageHeight,ImageIndex : Integer;



procedure DrawBackground;
var x,y : integer;
begin
  l := 0;
  MaxTo := 0; // this is reset because the area displayed may be less then what was checked for dirtyness
        // and may have fewer layers.
  while(l<=MaxTo) do
  begin
    Inc(l);
    if (not LayerVisible[l]) then Continue;
    for y := MinY to MaxY-1  do
      for x := MinX to MaxX-1 do
      begin
          gx := x;
          gy := y;
          gl := l;
        if not(tsDirty in IsoMap[x,y].State) then continue; // skip any cells that havent changed!
        ix := (x * CellWidth) + ((y mod 2) * (fCellWidthDiv2)) - XOffset; //offset x
        iy := (y * (fCellHeightDiv2)+ CellHeight) - YOffset; //  variable height
        if (IsoMap[x,y].AlwaysDisplayTo > MaxTo) then
          MaxTo := IsoMap[x,y].AlwaysDisplayTo;
        if (l>=IsoMap[x,y].AlwaysDisplayFrom) and (l<=IsoMap[x,y].AlwaysDisplayTo) then
        begin
          ImageIndex := IsoMap[x,y].ImageIndexes[l-1].ImageIndex;
//   if (ImageIndex >-1) then
          begin
            if (ImageIndex > GetImageCount) then
              Continue;
              if (ImageIndex>-1) then
                ImageHeight := GetImageHeight(ImageIndex)
              else
                ImageHeight := CellHeight;
              DrawImage(IsoMap[x,y],ImageIndex,x,y,ScrollXOffset+ix,ScrollYOffset + iy - ImageHeight
                - 0, // level offset
                l,  //layer
                0); // animation later
          end;
        end;
      end;
    end;
end;
procedure DrawAnimation;
var x,y : integer;
begin
    for y := MinY to MaxY-1  do
      for x := MinX to MaxX-1 do
      begin
        if not(tsDirty in IsoMap[x,y].State) then continue; // skip any cells that havent changed!
        if (IsoMap[x,y].AnimateFrom < IsoMap[x,y].AnimateTo) then
        begin
{       This has already been done while marking dirty cells
            if (IsoMap[x,y].AnimateCount=0) then
            begin
              Inc(IsoMap[x,y].AnimateNext);
              if (IsoMap[x,y].AnimateNext > IsoMap[x,y].AnimateTo) then
                IsoMap[x,y].AnimateNext := Isomap[x,y].AnimateFrom;
              IsoMap[x,y].AnimateCount := Isomap[x,y].AnimateSpeed; // reset the counter
            end
            else Dec(IsoMap[x,y].AnimateCount);
}
            if ((IsoMap[x,y].AnimateNext-1)>=0) and
               (IsoMap[x,y].animateNext< Length(IsoMap[x,y].ImageIndexes)) then
              ImageIndex := IsoMap[x,y].ImageIndexes[IsoMap[x,y].AnimateNext-1].ImageIndex
            else
              Continue;
            if (ImageIndex = -1) then continue;
            ImageHeight := GetImageHeight(ImageIndex);
            DrawImage(IsoMap[x,y],ImageIndex,x,y,
                ScrollXOffset+(x * CellWidth) + ((y mod 2) * (fCellWidthDiv2)) - XOffset, //offset x
                ScrollYOffset+(y * (fCellHeightDiv2) - ImageHeight + CellHeight) //  variable height
                - YOffset //offset y
                - 0, // level offset
                32767,  // animations are always the highest layer
                0); // animation later
        end;
      end;
end;
procedure DrawGrids;
var x,y : integer;
begin
    for y := MinY to MaxY-1  do
      for x := MinX to MaxX-1 do
        if (ShowGrid or (tsSelected in IsoMap[x,y].State)) then
        begin
          ix := ScrollXOffset+(x * CellWidth) + ((y mod 2) * (fCellWidthDiv2)) - XOffset; //offset x
          iy := ScrollYOffset+(y * (fCellHeightDiv2)+ CellHeight) - YOffset; //  variable height
          if (ShowGrid) then
            DrawGrid(ix,iy,-1)
          else
            DrawGrid(ix,iy,DrawCount);
        end;
end;
begin
  if (not CanDRaw) then Exit;
  if (CellWidth=0) then Exit;
  if (CellHeight < 2) then Exit;
  GetVisibleCorners(MinX,MinY,MaxX,MaxY);

  try
  if (FBruteForce) then
  begin
    AddAllState([tsDirty]);// let's clear the screen 1st time
  end
  else
  begin
    if (DrawCount=0) then
    begin
      AddAllState([tsDirty]);// let's clear the screen 1st time
      cls;
    end
    else
    begin
      CheckForDirtyCells;
    end;
    CountDirtyCells;
  end;
  DrawBackground;
  DrawAnimation;
  DrawGrids;
  Inc(DrawCount);

  finally
    Flip;
    if (DrawCount and 1)=1 then // keep dirty cells, so back buffer is updated with current screens data
    begin
      SubAllState([tsDirty]); // clear all dirty cells
      AddAllStateState([tsSelected],[tsDirty]); // selected cells are dirty
    end;
  end;
end;



procedure TIsoMap.SetXOffset(const Value: Integer);
begin
  if (Value>0) and (Value < MapWidth*FCellWidthDiv2) then
  FXOffset := Value;
end;

procedure TIsoMap.SetYOffset(const Value: Integer);
begin
  if (value>0) and (value< MapHeight * FCellHEightDiv2) then
  FYOffset := Value;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -