Changeset 23 for trunk/UGame.pas


Ignore:
Timestamp:
Mar 2, 2014, 11:27:14 PM (11 years ago)
Author:
chronos
Message:
  • Modified: Calculation of player visible frame is now handled by TView class.
  • Fixed: Set proper max power on existing player move update.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UGame.pas

    r22 r23  
    1010const
    1111  DefaultPlayerStartUnits = 5;
     12  CellMulX = 1.12;
     13  CellMulY = 1.292;
    1214
    1315type
     
    4446  end;
    4547
     48  { TView }
     49
     50  TView = class
     51  private
     52    FDestRect: TRect;
     53    FZoom: Double;
     54    procedure SetDestRect(AValue: TRect);
     55    procedure SetZoom(AValue: Double);
     56  public
     57    SourceRect: TRect;
     58    constructor Create;
     59    destructor Destroy; override;
     60    function CanvasToCellPos(Pos: TPoint): TPoint;
     61    function CellToCanvasPos(Pos: TPoint): TPoint;
     62    function CanvasToCellRect(Pos: TRect): TRect;
     63    function CellToCanvasRect(Pos: TRect): TRect;
     64    property DestRect: TRect read FDestRect write SetDestRect;
     65    property Zoom: Double read FZoom write SetZoom;
     66  end;
     67
    4668  { THexMap }
    4769
     
    5577    DefaultCellSize: TPoint;
    5678    Cells: array of array of TCell;
    57     function PosToCell(Pos: TPoint; Rect: TRect; Zoom: Double): TCell;
    58     function CellToPos(Cell: TCell; Rect: TRect; Zoom: Double): TPoint;
     79    function PosToCell(Pos: TPoint; View: TView): TCell;
     80    function CellToPos(Cell: TCell; View: TView): TPoint;
    5981    function GetHexagonPolygon(Pos: TPoint; HexSize: TPoint): TPointArray;
    60     procedure Paint(Canvas: TCanvas; Rect: TRect; Zoom: Double; SelectedCell: TCell);
     82    procedure Paint(Canvas: TCanvas; View: TView; SelectedCell: TCell; FocusedCell: TCell);
    6183    constructor Create;
    6284    destructor Destroy; override;
     
    6890  end;
    6991
     92
    7093  TPlayerMode = (pmHuman, pmComputer);
    7194
     
    7598    Game: TGame;
    7699    Name: string;
    77     CellPos: TPoint;
    78     ViewSize: TPoint;
    79100    Color: TColor;
    80     ViewZoom: Double;
     101    View: TView;
    81102    SelectedCell: TCell;
     103    FocusedCell: TCell;
    82104    Mode: TPlayerMode;
    83105    TotalUnits: Integer;
    84106    TotalCells: Integer;
    85107    StartUnits: Integer;
    86     function CanvasToCellPos(Pos: TPoint): TPoint;
    87     function CellToCanvasPos(Pos: TPoint): TPoint;
    88     function CanvasToCellRect(Pos: TRect): TRect;
    89     function CellToCanvasRect(Pos: TRect): TRect;
    90108    procedure ComputerTurn;
    91109    procedure SelectCell(Pos: TPoint);
    92110    procedure Paint(PaintBox: TPaintBox);
    93111    constructor Create;
     112    destructor Destroy; override;
    94113    procedure Assign(Source: TPlayer);
    95114  end;
     
    108127  { TGame }
    109128
    110   TMoveEvent = procedure(CellFrom, CellTo: TCell; var CountOnce, CountRepeat: Integer) of object;
     129  TMoveEvent = procedure(CellFrom, CellTo: TCell; var CountOnce, CountRepeat: Integer;
     130    Update: Boolean) of object;
    111131  TWinEvent = procedure(Player: TPlayer) of object;
    112132
     
    153173end;
    154174
     175function RectEquals(A, B: TRect): Boolean;
     176begin
     177  Result := (A.Left = B.Left) and (A.Top = B.Top) and
     178    (A.Right = B.Right) and (A.Bottom = B.Bottom);
     179end;
     180
    155181function PtInPoly(const Points: array of TPoint; Pos: TPoint): Boolean;
    156182var
     
    193219end;
    194220
     221{ TView }
     222
     223procedure TView.SetZoom(AValue: Double);
     224begin
     225  if FZoom = AValue then Exit;
     226  FZoom := AValue;
     227  SourceRect := Bounds(SourceRect.Left, SourceRect.Top,
     228    Trunc((DestRect.Right - DestRect.Left) / Zoom),
     229    Trunc((DestRect.Bottom - DestRect.Top) / Zoom));
     230end;
     231
     232procedure TView.SetDestRect(AValue: TRect);
     233begin
     234  if RectEquals(FDestRect, AValue) then Exit;
     235  FDestRect := AValue;
     236  SourceRect := Bounds(SourceRect.Left, SourceRect.Top,
     237    Trunc((DestRect.Right - DestRect.Left) / Zoom),
     238    Trunc((DestRect.Bottom - DestRect.Top) / Zoom));
     239end;
     240
     241constructor TView.Create;
     242begin
     243  Zoom := 1;
     244end;
     245
     246destructor TView.Destroy;
     247begin
     248  inherited Destroy;
     249end;
     250
    195251{ TCell }
    196252
     
    228284{ TPlayer }
    229285
    230 function TPlayer.CanvasToCellPos(Pos: TPoint): TPoint;
    231 begin
    232   Result := Point(Trunc(Pos.X / ViewZoom + CellPos.X),
    233     Trunc(Pos.Y / ViewZoom + CellPos.Y));
    234 end;
    235 
    236 function TPlayer.CellToCanvasPos(Pos: TPoint): TPoint;
    237 begin
    238   Result := Point(Trunc((Pos.X - CellPos.X) * ViewZoom),
    239     Trunc((Pos.Y - CellPos.Y) * ViewZoom));
    240 end;
    241 
    242 function TPlayer.CanvasToCellRect(Pos: TRect): TRect;
     286function TView.CanvasToCellPos(Pos: TPoint): TPoint;
     287begin
     288  Result := Point(Trunc(Pos.X / Zoom + SourceRect.Left),
     289    Trunc(Pos.Y / Zoom + SourceRect.Top));
     290end;
     291
     292function TView.CellToCanvasPos(Pos: TPoint): TPoint;
     293begin
     294  Result := Point(Trunc((Pos.X - SourceRect.Left) * Zoom),
     295    Trunc((Pos.Y - SourceRect.Top) * Zoom));
     296end;
     297
     298function TView.CanvasToCellRect(Pos: TRect): TRect;
    243299begin
    244300  Result.TopLeft := CanvasToCellPos(Pos.TopLeft);
     
    246302end;
    247303
    248 function TPlayer.CellToCanvasRect(Pos: TRect): TRect;
     304function TView.CellToCanvasRect(Pos: TRect): TRect;
    249305begin
    250306  Result.TopLeft := CellToCanvasPos(Pos.TopLeft);
     
    263319  BottomRight: TPoint;
    264320begin
    265   NewSelectedCell := Game.Map.PosToCell(CanvasToCellPos(Pos), CanvasToCellRect(Bounds(0, 0, ViewSize.X, ViewSize.Y)), ViewZoom);
     321  NewSelectedCell := Game.Map.PosToCell(View.CanvasToCellPos(Pos), View);
    266322  if Assigned(NewSelectedCell) then begin
    267323    if Assigned(SelectedCell) and IsCellsNeighbor(NewSelectedCell, SelectedCell) then begin
     
    279335procedure TPlayer.Paint(PaintBox: TPaintBox);
    280336begin
    281   Game.Map.Paint(PaintBox.Canvas, CanvasToCellRect(Bounds(0, 0, ViewSize.X, ViewSize.Y)), ViewZoom, SelectedCell);
     337  Game.Map.Paint(PaintBox.Canvas, View, SelectedCell, FocusedCell);
    282338end;
    283339
    284340constructor TPlayer.Create;
    285341begin
    286   ViewZoom := 1;
     342  View := TView.Create;
    287343  SelectedCell := nil;
     344  FocusedCell := nil;
    288345  StartUnits := DefaultPlayerStartUnits;
     346end;
     347
     348destructor TPlayer.Destroy;
     349begin
     350  FreeAndNil(View);
     351  inherited Destroy;
    289352end;
    290353
     
    299362  StartUnits := Source.StartUnits;
    300363  SelectedCell := Source.SelectedCell;
    301   ViewZoom := Source.ViewZoom;
     364  View.Zoom := Source.View.Zoom;
    302365end;
    303366
     
    352415    CountOnce := TMove(Moves[I]).CountOnce;
    353416    CountRepeat := TMove(Moves[I]).CountRepeat;
     417    if Assigned(FOnMove) then FOnMove(CellFrom, CellTo, CountOnce, CountRepeat, True);
    354418  end else begin
    355419    CountOnce := CellFrom.Power;
    356420    CountRepeat := 0;
    357   end;
    358   if Assigned(FOnMove) then FOnMove(CellFrom, CellTo, CountOnce, CountRepeat);
     421    if Assigned(FOnMove) then FOnMove(CellFrom, CellTo, CountOnce, CountRepeat, False);
     422  end;
    359423  if I < Moves.Count then begin
    360424    // Already have such move
     
    362426      else begin
    363427        TMove(Moves[I]).CountOnce := CountOnce;
    364         TMove(Moves[I]).CountOnce := CountOnce;
     428        TMove(Moves[I]).CountRepeat := CountRepeat;
    365429      end;
    366430  end else begin
     
    451515  Map := THexMap.Create;
    452516  Map.Game := Self;
    453   Map.Size := Point(2, 2);
     517  Map.Size := Point(20, 20);
    454518  Moves := TObjectList.Create;
    455519end;
     
    490554      StartCell.Power := TPlayer(Players[I]).StartUnits;
    491555    end;
    492     ViewZoom := 1;
     556    View.Zoom := 1;
    493557    // Center board
    494     CellPos := Point(Trunc(Map.GetPixelSize.X div 2 - ViewSize.X div 2 / ViewZoom),
    495       Trunc(Map.GetPixelSize.Y div 2 - ViewSize.Y div 2 / ViewZoom));
     558    View.SourceRect.TopLeft := Point(Trunc(Map.GetPixelSize.X div 2 - (View.SourceRect.Right - View.SourceRect.Left) div 2 / View.Zoom),
     559      Trunc(Map.GetPixelSize.Y div 2 - (View.SourceRect.Bottom - View.SourceRect.Top) div 2 / View.Zoom));
    496560  end;
    497561  CurrentPlayer := TPlayer(Players[0]);
     
    538602end;
    539603
    540 function THexMap.PosToCell(Pos: TPoint; Rect: TRect; Zoom: Double): TCell;
     604function THexMap.PosToCell(Pos: TPoint; View: TView): TCell;
    541605var
    542606  CX, CY: Integer;
     
    546610  Points: array of TPoint;
    547611begin
    548   // TODO: This is implemented as simple sequence lookup. It needs some faster algorithm
     612  // TODO: This is implemented as simple sequence lookup. Needs some faster algorithm
    549613  Result := nil;
    550   CellSize := FloatPoint(DefaultCellSize.X / 1.15 * Zoom, DefaultCellSize.Y / 1.35 * Zoom);
    551   HexSize := FloatPoint(DefaultCellSize.X * Zoom, DefaultCellSize.Y * Zoom);
    552     for CY := Trunc(Rect.Top / CellSize.Y) to Trunc(Rect.Bottom / CellSize.Y) + 1 do
    553     for CX := Trunc(Rect.Left / CellSize.X) to Trunc(Rect.Right / CellSize.X) + 1 do begin
    554       X := CX - Trunc(Rect.Left / CellSize.X);
    555       Y := CY - Trunc(Rect.Top / CellSize.Y);
     614  CellSize := FloatPoint(DefaultCellSize.X / CellMulX, DefaultCellSize.Y / CellMulY);
     615  HexSize := FloatPoint(DefaultCellSize.X, DefaultCellSize.Y);
     616  with View do
     617    for CY := Trunc(SourceRect.Top / CellSize.Y) to Trunc(SourceRect.Bottom / CellSize.Y) + 1 do
     618    for CX := Trunc(SourceRect.Left / CellSize.X) to Trunc(SourceRect.Right / CellSize.X) + 1 do begin
     619      X := CX;
     620      Y := CY;
    556621      if (CY and 1) = 1 then begin
    557622        X := X + 0.5;
     
    560625      if (CX >= 0) and (CY >= 0) and (CY < Size.Y) and (CX < Size.X) then
    561626      if Cells[CY, CX].Terrain = ttNormal then begin
    562         Points := GetHexagonPolygon(Point(Trunc(X * CellSize.X - Frac(Rect.Left / CellSize.X) * CellSize.X),
    563           Trunc(Y * CellSize.Y - Frac(Rect.Top / CellSize.Y) * CellSize.Y)), Point(Trunc(HexSize.X), Trunc(HexSize.Y)));
     627        Points := GetHexagonPolygon(Point(Trunc(X * CellSize.X - Frac(SourceRect.Left / CellSize.X) * CellSize.X),
     628          Trunc(Y * CellSize.Y - Frac(SourceRect.Top / CellSize.Y) * CellSize.Y)),
     629          Point(Trunc(HexSize.X), Trunc(HexSize.Y)));
    564630        if PtInPoly(Points, Pos) then begin
    565631          Result := Cells[CY, CX];
     
    570636end;
    571637
    572 function THexMap.CellToPos(Cell: TCell; Rect: TRect; Zoom: Double): TPoint;
     638function THexMap.CellToPos(Cell: TCell; View: TView): TPoint;
    573639var
    574640  CX, CY: Integer;
     
    578644  Points: array of TPoint;
    579645begin
    580   CellSize := FloatPoint(DefaultCellSize.X / 1.15 * Zoom, DefaultCellSize.Y / 1.35 * Zoom);
    581   HexSize := FloatPoint(DefaultCellSize.X * Zoom, DefaultCellSize.Y * Zoom);
    582   X := Cell.Pos.X - Trunc(Rect.Left / CellSize.X);
    583   Y := Cell.Pos.Y - Trunc(Rect.Top / CellSize.Y);
     646  with View do begin
     647  CellSize := FloatPoint(DefaultCellSize.X / CellMulX * View.Zoom, DefaultCellSize.Y / CellMulY * View.Zoom);
     648  HexSize := FloatPoint(DefaultCellSize.X * View.Zoom, DefaultCellSize.Y * View.Zoom);
     649  X := Cell.Pos.X - Trunc(SourceRect.Left / CellSize.X);
     650  Y := Cell.Pos.Y - Trunc(SourceRect.Top / CellSize.Y);
    584651  if (Cell.Pos.Y and 1) = 1 then begin
    585652    X := X + 0.5;
     
    587654  end;
    588655
    589   Result.X := Trunc(X * CellSize.X - Frac(Rect.Left / CellSize.X) * CellSize.X);
    590   Result.Y := Trunc(Y * CellSize.Y - Frac(Rect.Top / CellSize.Y) * CellSize.Y);
    591 end;
    592 
    593 
    594 procedure THexMap.Paint(Canvas: TCanvas; Rect: TRect; Zoom: Double; SelectedCell: TCell);
     656  Result.X := Trunc(X * CellSize.X - Frac(SourceRect.Left / CellSize.X) * CellSize.X);
     657  Result.Y := Trunc(Y * CellSize.Y - Frac(SourceRect.Top / CellSize.Y) * CellSize.Y);
     658  end;
     659end;
     660
     661
     662procedure THexMap.Paint(Canvas: TCanvas; View: TView; SelectedCell: TCell; FocusedCell: TCell);
    595663var
    596664  CX, CY: Integer;
    597665  X, Y: Double;
     666  CellSizeZoomed: TFloatPoint;
     667  CellSize: TFloatPoint;
    598668  HexSize: TFloatPoint;
    599   CellSize: TFloatPoint;
    600669  I: Integer;
    601670  Points: array of TPoint;
     
    608677begin
    609678  with Canvas do begin
     679    if Assigned(FocusedCell) and (FocusedCell = TCell(Cells[CY, CX])) then begin
     680      Pen.Color := clYellow;
     681      Pen.Style := psSolid;
     682    end else begin
     683      Pen.Color := clBlack;
     684      Pen.Style := psClear;
     685    end;
    610686    Points := GetHexagonPolygon(Point(Trunc(X), Trunc(Y)), Point(Trunc(HexSize.X), Trunc(HexSize.Y)));
    611687    Polygon(Points);
     688    Pen.Style := psSolid;
    612689    Font.Color := clWhite;
    613     Font.Size := Trunc(12 * Zoom);
     690    Font.Size := Trunc(12 * View.Zoom);
    614691    TextOut(Round(X) - TextWidth(Text) div 2, Round(Y) - TextHeight(Text) div 2, Text);
    615692  end;
     
    617694
    618695begin
    619   CellSize := FloatPoint(DefaultCellSize.X / 1.15 * Zoom, DefaultCellSize.Y / 1.35 * Zoom);
    620   HexSize := FloatPoint(DefaultCellSize.X * Zoom, DefaultCellSize.Y * Zoom);
    621   with Canvas do try
     696  CellSize := FloatPoint(DefaultCellSize.X / CellMulX, DefaultCellSize.Y / CellMulY);
     697  HexSize := FloatPoint(DefaultCellSize.X * View.Zoom, DefaultCellSize.Y * View.Zoom);
     698  CellSizeZoomed := FloatPoint(CellSize.X * View.Zoom, CellSize.Y * View.Zoom);
     699  with Canvas, View do try
    622700    Lock;
    623701    ClearCellMoves;
     
    629707    end;
    630708
    631     for CY := Trunc(Rect.Top / CellSize.Y) to Trunc(Rect.Bottom / CellSize.Y) + 1 do
    632     for CX := Trunc(Rect.Left / CellSize.X) to Trunc(Rect.Right / CellSize.X) + 1 do begin
    633       X := CX - Trunc(Rect.Left / CellSize.X);
    634       Y := CY - Trunc(Rect.Top / CellSize.Y);
     709    for CY := Trunc(SourceRect.Top / CellSize.Y) to Trunc(SourceRect.Bottom / CellSize.Y) + 1 do
     710    for CX := Trunc(SourceRect.Left / CellSize.X) to Trunc(SourceRect.Right / CellSize.X) + 1 do begin
     711      X := CX - Trunc(SourceRect.Left / CellSize.X);
     712      Y := CY - Trunc(SourceRect.Top / CellSize.Y);
    635713      if (CY and 1) = 1 then begin
    636714        X := X + 0.5;
     
    644722            else Brush.Color := Cell.GetColor;
    645723          Pen.Color := clBlack;
    646           PaintHexagon(X * CellSize.X - Frac(Rect.Left / CellSize.X) * CellSize.X,
    647             Y * CellSize.Y - Frac(Rect.Top / CellSize.Y) * CellSize.Y, IntToStr(Cell.GetAvialPower));
     724          PaintHexagon(X * CellSizeZoomed.X - Frac(SourceRect.Left / CellSize.X) * CellSizeZoomed.X,
     725            Y * CellSizeZoomed.Y - Frac(SourceRect.Top / CellSize.Y) * CellSizeZoomed.Y, IntToStr(Cell.GetAvialPower));
    648726          // Draw arrows
    649727          Pen.Color := clCream;
    650728          for I := 0 to Cell.MovesFrom.Count - 1 do begin
    651             PosFrom := CellToPos(Cell, Rect, Zoom);
    652             PosTo := CellToPos(TMove(Cell.MovesFrom[I]).CellTo, Rect, Zoom);
     729            PosFrom := CellToPos(Cell, View);
     730            PosTo := CellToPos(TMove(Cell.MovesFrom[I]).CellTo, View);
    653731            Line(Trunc(PosFrom.X + (PosTo.X - PosFrom.X) / 4),
    654732              Trunc(PosFrom.Y + (PosTo.Y - PosFrom.Y) / 4),
Note: See TracChangeset for help on using the changeset viewer.