Changeset 30 for trunk/UEngine.pas


Ignore:
Timestamp:
Apr 18, 2015, 6:17:34 PM (9 years ago)
Author:
chronos
Message:
  • Added: Automatic zooming to all existed map stations. This solve problem if too many stations were existed and some of them appeared behind window border.
  • Added: Much of used TCanvas functions are now available through TMetaCanvas.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UEngine.pas

    r29 r30  
    66
    77uses
    8   Classes, SysUtils, Contnrs, Graphics, Controls, ExtCtrls, Math, DateUtils;
     8  Classes, SysUtils, Contnrs, Graphics, Controls, ExtCtrls, Math, DateUtils,
     9  UMetaCanvas;
    910
    1011type
     
    209210  private
    210211    FDestRect: TRect;
     212    FSourceRect: TRect;
    211213    FZoom: Double;
    212214    procedure SetDestRect(AValue: TRect);
     215    procedure SetSourceRect(AValue: TRect);
    213216    procedure SetZoom(AValue: Double);
    214217  public
    215     SourceRect: TRect;
     218    function PointDestToSrc(Pos: TPoint): TPoint;
     219    function PointSrcToDest(Pos: TPoint): TPoint;
    216220    constructor Create;
     221    property SourceRect: TRect read FSourceRect write SetSourceRect;
    217222    property DestRect: TRect read FDestRect write SetDestRect;
    218223    property Zoom: Double read FZoom write SetZoom;
     
    237242    FTime: TDateTime;
    238243    FLastTime: TDateTime;
     244    MetaCanvas: TMetaCanvas;
     245    procedure ResizeView;
    239246    function GetExistStationShapes: TStationShapeSet;
    240247    function GetStationOnPos(Pos: TPoint): TMapStation;
     
    273280    constructor Create;
    274281    destructor Destroy; override;
    275     procedure Paint(Canvas: TCanvas);
     282    procedure Paint(TargetCanvas: TCanvas);
    276283    property Time: TDateTime read FTime;
    277284  end;
     
    307314  NewTrainPeriod = 7; // Each week
    308315  NewPassengerPeriod = 0.3 * OneSecond;
    309   NewPassengerProbability = 0.002;
     316  NewPassengerProbability = 0.003;
    310317  VisiblePassengersPerLine = 6;
    311318
     
    350357    Trunc((DestRect.Bottom - DestRect.Top) / Zoom - (AValue.Bottom - AValue.Top) / Zoom) div 2);
    351358  FDestRect := AValue;
    352   SourceRect := Bounds(SourceRect.Left + Diff.X, SourceRect.Top + Diff.Y,
     359  FSourceRect := Bounds(FSourceRect.Left + Diff.X, FSourceRect.Top + Diff.Y,
    353360    Trunc((DestRect.Right - DestRect.Left) / Zoom),
    354361    Trunc((DestRect.Bottom - DestRect.Top) / Zoom));
     362end;
     363
     364procedure TView.SetSourceRect(AValue: TRect);
     365var
     366  ZX: Double;
     367  ZY: Double;
     368begin
     369  if RectEquals(FSourceRect, AValue) then Exit;
     370  FSourceRect := AValue;
     371  ZX := (FDestRect.Right - FDestRect.Left) / (FSourceRect.Right - FSourceRect.Left);
     372  ZY := (FDestRect.Bottom - FDestRect.Top) / (FSourceRect.Bottom - FSourceRect.Top);
     373  if  ZX > ZY then
     374    Zoom := ZY
     375    else Zoom := ZX;
    355376end;
    356377
     
    361382    raise Exception.Create(SZeroZoomNotAlowed);
    362383  FZoom := AValue;
    363   SourceRect := Bounds(Trunc(SourceRect.Left + (SourceRect.Right - SourceRect.Left) div 2 - (DestRect.Right - DestRect.Left) / Zoom / 2),
    364     Trunc(SourceRect.Top +  (SourceRect.Bottom - SourceRect.Top) div 2 - (DestRect.Bottom - DestRect.Top) / Zoom / 2),
     384  FSourceRect := Bounds(Trunc(FSourceRect.Left + (FSourceRect.Right - FSourceRect.Left) div 2 - (DestRect.Right - DestRect.Left) / Zoom / 2),
     385    Trunc(FSourceRect.Top +  (FSourceRect.Bottom - FSourceRect.Top) div 2 - (FDestRect.Bottom - DestRect.Top) / Zoom / 2),
    365386    Trunc((DestRect.Right - DestRect.Left) / Zoom),
    366387    Trunc((DestRect.Bottom - DestRect.Top) / Zoom));
    367388end;
    368389
     390function TView.PointDestToSrc(Pos: TPoint): TPoint;
     391begin
     392  Result := Point(Trunc(Pos.X / FZoom + FSourceRect.Left),
     393    Trunc(Pos.Y / FZoom + FSourceRect.Top));
     394end;
     395
     396function TView.PointSrcToDest(Pos: TPoint): TPoint;
     397begin
     398  Result := Point(Trunc((Pos.X - FSourceRect.Left) * FZoom),
     399    Trunc((Pos.Y - FSourceRect.Top) * FZoom));
     400end;
     401
    369402constructor TView.Create;
    370403begin
    371   Zoom := 1.5;
     404  Zoom := 1;
    372405end;
    373406
     
    10831116
    10841117{ TEngine }
     1118
     1119procedure TEngine.ResizeView;
     1120var
     1121  StationRect: TRect;
     1122  NewPoint: TPoint;
     1123begin
     1124  // Need to see all stations on screen
     1125  View.SourceRect := RectEnlarge(Stations.GetRect, 100);
     1126
     1127  NewPoint := Point(
     1128    Trunc((View.SourceRect.Left + (View.SourceRect.Right - View.SourceRect.Left) / 2) -
     1129    (View.DestRect.Left + (View.DestRect.Right - View.DestRect.Left) / 2 / View.Zoom)),
     1130    Trunc((View.SourceRect.Top + (View.SourceRect.Bottom - View.SourceRect.Top) / 2) -
     1131    (View.DestRect.Top + (View.DestRect.Bottom - View.DestRect.Top) / 2 / View.Zoom)));
     1132  View.SourceRect := Bounds(NewPoint.X, NewPoint.Y, Trunc((View.DestRect.Right - View.DestRect.Left) / View.Zoom),
     1133    Trunc((View.DestRect.Bottom - View.DestRect.Top) / View.Zoom));
     1134end;
    10851135
    10861136function TEngine.GetExistStationShapes: TStationShapeSet;
     
    16181668    LastNewStationTime := Time;
    16191669    Stations.AddNew;
    1620     // Need to see all stations on screen
    1621     View.SourceRect := RectEnlarge(Stations.GetRect, 70);
     1670    ResizeView;
    16221671  end;
    16231672
     
    16761725  LastMousePos := Position;
    16771726  if MouseHold then begin
    1678       FocusedStation := GetStationOnPos(Position);
     1727      FocusedStation := GetStationOnPos(View.PointDestToSrc(Position));
    16791728      Line := nil;
    16801729      if Assigned(TrackStationDown) then Line := TrackStationDown.Line;
     
    17281777        SelectedTrain.Line := nil;
    17291778      end;
    1730       FocusedTrack := GetTrackOnPos(Position);
     1779      FocusedTrack := GetTrackOnPos(View.PointDestToSrc(Position));
    17311780      if Assigned(FocusedTrack.PointDown) then begin
    17321781        SelectedTrain.Line := FocusedTrack.PointDown.Line;
     
    17811830
    17821831    // Train selection
    1783     SelectedTrain := GetTrainOnPos(Position);
     1832    SelectedTrain := GetTrainOnPos(View.PointDestToSrc(Position));
    17841833    if Assigned(SelectedTrain) then begin
    17851834      Exit;
     
    17951844
    17961845    // Line selection
    1797     Track := GetTrackOnPos(Position);
     1846    Track := GetTrackOnPos(View.PointDestToSrc(Position));
    17981847    if Assigned(Track) and Assigned(Track.PointDown) and Assigned(Track.PointUp) then begin
    17991848      SelectedLine := Track.PointDown.Line;
     
    18201869
    18211870    // New track creation from selected station as start
    1822     Station := GetStationOnPos(Position);
     1871    Station := GetStationOnPos(View.PointDestToSrc(Position));
    18231872    if Assigned(Station) then begin
    18241873      if Assigned(SelectedLine) and (SelectedLine.LineStations.Count = 0) then NewLine := SelectedLine
     
    18621911    Trains.Add(NewTrain);
    18631912  end;
     1913
     1914  ResizeView;
    18641915
    18651916  SelectedLine := nil;
     
    18911942  if FileExists(ImageLocomotiveName) then
    18921943    ImageLocomotive.Picture.LoadFromFile(ImageLocomotiveName);
     1944  MetaCanvas := TMetaCanvas.Create;
    18931945end;
    18941946
    18951947destructor TEngine.Destroy;
    18961948begin
     1949  MetaCanvas.Free;
    18971950  Trains.Free;
    18981951  ImageLocomotive.Free;
     
    19061959end;
    19071960
    1908 procedure TEngine.Paint(Canvas: TCanvas);
     1961procedure TEngine.Paint(TargetCanvas: TCanvas);
    19091962var
    19101963  I: Integer;
     
    19151968  Text: string;
    19161969  Angle: Double;
    1917   EndPoint: TPoint;
    19181970  PassengerPos: TPoint;
    19191971  Direction: Integer;
    19201972  Points: array of TPoint;
     1973  Canvas: TMetaCanvas;
    19211974const
    19221975  GameOverText = 'Game Over';
     
    19241977  GameOverStatistic = '%d passengers travelled on your metro over %d days.';
    19251978begin
    1926   Canvas.Brush.Color := $eff0e0;
    1927   Canvas.Brush.Style := bsSolid;
    1928   Canvas.Clear;
     1979  Canvas := MetaCanvas;
     1980  Canvas.SetSize(Point(TargetCanvas.Width, TargetCanvas.Height));
     1981  Canvas.Reset;
    19291982
    19301983  // Draw station passenger overload
     
    19882041    Canvas.Pen.Color := TrackStationDown.Line.Color;
    19892042    Canvas.MoveTo(TrackStationDown.LineStation.TrackPoint.Position);
    1990     DrawLine(Canvas, LastMousePos);
     2043    DrawLine(Canvas, View.PointDestToSrc(LastMousePos));
    19912044  end;
    19922045  if Assigned(TrackStationUp) and Assigned(TrackStationUp.LineStation) then begin
    19932046    Canvas.Pen.Color := TrackStationUp.Line.Color;
    19942047    Canvas.MoveTo(TrackStationUp.LineStation.TrackPoint.Position);
    1995     DrawLine(Canvas, LastMousePos);
     2048    DrawLine(Canvas, View.PointDestToSrc(LastMousePos));
    19962049  end;
    19972050
     
    20062059      Canvas.Brush.Style := bsClear;
    20072060      Canvas.Pen.Color := SelectedLine.Color;
    2008       DrawShape(Canvas, Position, Shape, StationSize + Canvas.Pen.Width + 6, 0);
     2061      DrawShape(Canvas, Position, Shape, StationSize + Canvas.Pen.Width + 4, 0);
    20092062    end;
    20102063
     
    20462099  end;
    20472100
     2101  // Clear background
     2102  TargetCanvas.Brush.Color := $eff0e0;
     2103  TargetCanvas.Brush.Style := bsSolid;
     2104  TargetCanvas.Clear;
     2105
     2106  MetaCanvas.Move(Point(-View.SourceRect.Left, -View.SourceRect.Top));
     2107  MetaCanvas.Zoom(View.Zoom);
     2108
     2109  // Draw meta canvas to real target canvas
     2110  MetaCanvas.DrawTo(TargetCanvas);
     2111
    20482112  // Line selection
    20492113  for I := 0 to High(LineColors) do begin
    20502114    if Assigned(Lines.SearchByColor(LineColors[I])) then begin
    2051       Canvas.Brush.Color := LineColors[I];
     2115      TargetCanvas.Brush.Color := LineColors[I];
    20522116      Size := 15;
    20532117    end else begin
    2054       Canvas.Brush.Color := clSilver;
     2118      TargetCanvas.Brush.Color := clSilver;
    20552119      Size := 5;
    20562120    end;
    2057     Canvas.Pen.Color := clBlack;
     2121    TargetCanvas.Pen.Color := clBlack;
    20582122    if Assigned(SelectedLine) and (SelectedLine.Color = LineColors[I]) then begin
    2059       Canvas.Pen.Style := psSolid;
     2123      TargetCanvas.Pen.Style := psSolid;
    20602124    end else begin
    2061       Canvas.Pen.Style := psClear;
    2062     end;
    2063 
    2064     Canvas.EllipseC(Canvas.Width div 2 - Length(LineColors) div 2 * LineColorsDist + I * LineColorsDist,
    2065       Canvas.Height - LineColorsDist, Size, Size);
     2125      TargetCanvas.Pen.Style := psClear;
     2126    end;
     2127
     2128    TargetCanvas.EllipseC(TargetCanvas.Width div 2 - Length(LineColors) div 2 * LineColorsDist + I * LineColorsDist,
     2129      TargetCanvas.Height - LineColorsDist, Size, Size);
    20662130  end;
    20672131
    20682132  // Draw unused trains
    20692133  Text := IntToStr(Trains.GetUnusedCount);
    2070   Canvas.Draw(Canvas.Width div 2 - Length(LineColors) div 2 * LineColorsDist - 100,
    2071     Canvas.Height - LineColorsDist - ImageLocomotive.Picture.Bitmap.Height div 2, ImageLocomotive.Picture.Bitmap);
    2072   Canvas.Brush.Style := bsClear;
    2073   Canvas.TextOut(Canvas.Width div 2 - Length(LineColors) div 2 * LineColorsDist - 50 - Canvas.TextWidth(Text),
    2074     Canvas.Height - LineColorsDist - Canvas.TextHeight(Text) div 2, Text);
    2075 
     2134  TargetCanvas.Draw(Canvas.Width div 2 - Length(LineColors) div 2 * LineColorsDist - 100,
     2135    TargetCanvas.Height - LineColorsDist - ImageLocomotive.Picture.Bitmap.Height div 2, ImageLocomotive.Picture.Bitmap);
     2136  TargetCanvas.Brush.Style := bsClear;
     2137  TargetCanvas.TextOut(TargetCanvas.Width div 2 - Length(LineColors) div 2 * LineColorsDist - 50 - TargetCanvas.TextWidth(Text),
     2138    TargetCanvas.Height - LineColorsDist - TargetCanvas.TextHeight(Text) div 2, Text);
    20762139
    20772140  // Status interface
    20782141  Text := IntToStr(ServedPassengerCount);
    2079   Canvas.Draw(Canvas.Width - 140, 20, ImagePassenger.Picture.Bitmap);
    2080   Canvas.Brush.Style := bsClear;
    2081   Canvas.TextOut(Canvas.Width - 146 - Canvas.TextWidth(Text), 25, Text);
    2082 
    2083   DrawClock(Canvas);
    2084 
     2142  TargetCanvas.Draw(TargetCanvas.Width - 140, 20, ImagePassenger.Picture.Bitmap);
     2143  TargetCanvas.Brush.Style := bsClear;
     2144  TargetCanvas.TextOut(TargetCanvas.Width - 146 - TargetCanvas.TextWidth(Text), 25, Text);
     2145
     2146  DrawClock(TargetCanvas);
     2147
     2148  // Show grabbed train by mouse
    20852149  if Assigned(SelectedTrain) then begin
    2086     Canvas.Brush.Color := clBlack; //SelectedTrain.Line.Color;
    2087     Canvas.Brush.Style := bsSolid;
    2088     Canvas.Pen.Style := psClear;
     2150    TargetCanvas.Brush.Color := clBlack; //SelectedTrain.Line.Color;
     2151    TargetCanvas.Brush.Style := bsSolid;
     2152    TargetCanvas.Pen.Style := psClear;
    20892153    Pos := LastMousePos;
    20902154    Angle := 0;
     
    20952159    Points[2] := RotatePoint(Pos, Point(Pos.X + TrainSize div 2, Pos.Y + TrainSize div 3), Angle);
    20962160    Points[3] := RotatePoint(Pos, Point(Pos.X - TrainSize div 2, Pos.Y + TrainSize div 3), Angle);
    2097     Canvas.Polygon(Points);
     2161    TargetCanvas.Polygon(Points);
    20982162  end;
    20992163
     
    21012165  if State = gsGameOver then
    21022166  begin
    2103     Canvas.Font.Size := 40;
    2104     Canvas.Font.Color := clBlack;
    2105     Canvas.TextOut((Canvas.Width - Canvas.TextWidth(GameOverText)) div 2, 100, GameOverText);
    2106     Canvas.Font.Size := 14;
    2107     Canvas.TextOut((Canvas.Width - Canvas.TextWidth(GameOverReason)) div 2, 160, GameOverReason);
     2167    TargetCanvas.Font.Size := 40;
     2168    TargetCanvas.Font.Color := clBlack;
     2169    TargetCanvas.TextOut((TargetCanvas.Width - TargetCanvas.TextWidth(GameOverText)) div 2, 100, GameOverText);
     2170    TargetCanvas.Font.Size := 14;
     2171    TargetCanvas.TextOut((TargetCanvas.Width - TargetCanvas.TextWidth(GameOverReason)) div 2, 160, GameOverReason);
    21082172    Text := Format(GameOverStatistic, [ServedPassengerCount, Trunc(Time)]);
    2109     Canvas.TextOut((Canvas.Width - Canvas.TextWidth(Text)) div 2, 180, Text);
     2173    TargetCanvas.TextOut((TargetCanvas.Width - TargetCanvas.TextWidth(Text)) div 2, 180, Text);
    21102174  end;
    21112175end;
Note: See TracChangeset for help on using the changeset viewer.