Changeset 9


Ignore:
Timestamp:
Mar 26, 2015, 9:06:17 PM (10 years ago)
Author:
chronos
Message:
  • Fixed: Allow train to go in round if track is circular.
  • Added: Add new train each week.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UEngine.pas

    r8 r9  
    4040  end;
    4141
     42  TTrackPoint = record
     43    StationIndex: Integer;
     44    Point: TPoint;
     45  end;
     46
    4247  { TMetroLine }
    4348
     
    4752    Stations: TMetroStations;
    4853    Trains: TMetroTrains;
    49     TrackPoints: array of TPoint;
     54    TrackPoints: array of TTrackPoint;
    5055    procedure ConnectStation(Station: TMetroStation);
    5156    procedure DisconnectStation(Station: TMetroStation);
    52     procedure AddTrack(P1, P2: TPoint);
     57    procedure AddTrack(P1, P2: TPoint; StationIndex: Integer);
    5358    function GetTrackLength: Integer;
    54     function GetStationTrackPos(Station: TMetroStation): Integer;
     59    function GetStationTrackPos(StationIndex: Integer): Integer;
    5560    constructor Create;
    5661    destructor Destroy; override;
     
    7075  private
    7176    LastPosDelta: Integer;
     77    function GetTargetStation: TMetroStation;
    7278  public
    7379    Passengers: TMetroPassengers;
     
    7783    InStation: Boolean;
    7884    StationStopTime: TDateTime;
    79     TargetStation: TMetroStation;
    80     function GetPos: TPoint;
     85    TargetStationIndex: Integer;
     86    function GetPosition: TPoint;
    8187    constructor Create;
    8288    destructor Destroy; override;
     89    property TargetStation: TMetroStation read GetTargetStation;
    8390  end;
    8491
     
    8895    function GetUnusedTrain: TMetroTrain;
    8996    function GetUnusedCount: Integer;
     97    function AddNew: TMetroTrain;
    9098  end;
    9199
     
    123131    LastNewStationTime: TDateTime;
    124132    LastNewPassengerTime: TDateTime;
     133    LastNewWeekTime: TDateTime;
    125134    ImagePassenger: TImage;
    126135    ImageLocomotive: TImage;
     
    211220end;
    212221
     222function TMetroTrains.AddNew: TMetroTrain;
     223begin
     224  Result := TMetroTrain.Create;
     225  Add(Result);
     226end;
     227
    213228{ TMetroStations }
    214229
     
    264279var
    265280  Train: TMetroTrain;
     281  StationIndex: Integer;
    266282begin
    267283  Stations.Add(Station);
    268284  Station.Lines.Add(Self);
     285  StationIndex := Stations.Count - 1;
    269286  if Stations.Count = 1 then begin
    270287    SetLength(TrackPoints, Length(TrackPoints) + 1);
    271     TrackPoints[High(TrackPoints)] := Station.Position;
     288    TrackPoints[High(TrackPoints)].StationIndex := StationIndex;
     289    TrackPoints[High(TrackPoints)].Point := Station.Position;
    272290  end else begin
    273291     if Stations.Count > 1 then
    274        AddTrack(TMetroStation(Stations[Stations.Count - 2]).Position, Station.Position);
     292       AddTrack(TMetroStation(Stations[Stations.Count - 2]).Position, Station.Position, StationIndex);
    275293       // Place one train if at least two stations present
    276294       if (Stations.Count = 2) then begin
     
    278296         if Assigned(Train) then begin
    279297           Train.Line := Self;
    280            Train.TargetStation := TMetroStation(Stations.First);
     298           Train.TargetStationIndex := 0;
    281299           Trains.Add(Train);
    282300         end;
     
    289307var
    290308  I: Integer;
     309  StationIndex: Integer;
    291310begin
    292311  if (Stations.Count > 0) and (Stations.Last = Station) then begin
    293     Stations.Delete(Stations.Count - 1);
     312    StationIndex := Stations.Count - 1;
     313    Stations.Delete(StationIndex);
    294314    Station.Lines.Remove(Self);
    295315    if Stations.Count > 0 then begin
    296       while (Length(TrackPoints) > 0) and (not ComparePoint(TrackPoints[High(TrackPoints)], TMetroStation(Stations.Last).Position)) do
     316      while (Length(TrackPoints) > 0) and (not ComparePoint(TrackPoints[High(TrackPoints)].Point,
     317        TMetroStation(Stations.Last).Position)) do
    297318        SetLength(TrackPoints, Length(TrackPoints) - 1);
    298319    end else SetLength(TrackPoints, 0);
     
    307328end;
    308329
    309 procedure TMetroLine.AddTrack(P1, P2: TPoint);
     330procedure TMetroLine.AddTrack(P1, P2: TPoint; StationIndex: Integer);
    310331var
    311332  Delta: TPoint;
     
    314335  if Abs(Delta.X) > Abs(Delta.Y) then begin
    315336    SetLength(TrackPoints, Length(TrackPoints) + 1);
    316     TrackPoints[High(TrackPoints)] := Point(P2.X - Sign(Delta.X) * Abs(Delta.Y), P1.Y);
     337    TrackPoints[High(TrackPoints)].Point := Point(P2.X - Sign(Delta.X) * Abs(Delta.Y), P1.Y);
     338    TrackPoints[High(TrackPoints)].StationIndex := StationIndex - 1;
    317339  end else begin
    318340    SetLength(TrackPoints, Length(TrackPoints) + 1);
    319     TrackPoints[High(TrackPoints)] := Point(P1.X, P2.Y - Sign(Delta.Y) * Abs(Delta.X));
     341    TrackPoints[High(TrackPoints)].Point := Point(P1.X, P2.Y - Sign(Delta.Y) * Abs(Delta.X));
     342    TrackPoints[High(TrackPoints)].StationIndex := StationIndex - 1;
    320343  end;
    321344  SetLength(TrackPoints, Length(TrackPoints) + 1);
    322   TrackPoints[High(TrackPoints)] := P2;
     345  TrackPoints[High(TrackPoints)].Point := P2;
     346  TrackPoints[High(TrackPoints)].StationIndex := StationIndex;
    323347end;
    324348
     
    330354  for I := 0 to High(TrackPoints) do
    331355  if I > 0 then
    332     Result := Result + Distance(TrackPoints[I], TrackPoints[I - 1]);
    333 end;
    334 
    335 function TMetroLine.GetStationTrackPos(Station: TMetroStation): Integer;
     356    Result := Result + Distance(TrackPoints[I].Point, TrackPoints[I - 1].Point);
     357end;
     358
     359function TMetroLine.GetStationTrackPos(StationIndex: Integer): Integer;
    336360var
    337361  I: Integer;
     
    340364  for I := 0 to High(TrackPoints) do begin
    341365    if I > 0 then
    342       Result := Result + Distance(TrackPoints[I], TrackPoints[I - 1]);
    343     if (TrackPoints[I].X = Station.Position.X) and (TrackPoints[I].Y = Station.Position.Y) then Break;
     366      Result := Result + Distance(TrackPoints[I].Point, TrackPoints[I - 1].Point);
     367    if TrackPoints[I].StationIndex = StationIndex then Break;
    344368  end;
    345369end;
     
    362386{ TMetroTrain }
    363387
    364 function TMetroTrain.GetPos: TPoint;
     388function TMetroTrain.GetTargetStation: TMetroStation;
     389begin
     390  Result := nil;
     391  if Assigned(Line) then
     392  if (TargetStationIndex >= 0) and (TargetStationIndex < Line.Stations.Count) then
     393    Result := TMetroStation(Line.Stations[TargetStationIndex]);
     394end;
     395
     396function TMetroTrain.GetPosition: TPoint;
    365397var
    366398  I: Integer;
     
    374406    if Length(TrackPoints) > 1 then
    375407    for I := 1 to High(TrackPoints) do begin
    376       D := Distance(TrackPoints[I], TrackPoints[I - 1]);
     408      D := Distance(TrackPoints[I].Point, TrackPoints[I - 1].Point);
    377409      if (Sum + D) > Self.TrackPos then begin
    378         R := Point(TrackPoints[I].X - TrackPoints[I - 1].X, TrackPoints[I].Y - TrackPoints[I - 1].Y);
    379         Result := Point(Trunc(TrackPoints[I - 1].X + R.X * (TrackPos - Sum) / D),
    380           Trunc(TrackPoints[I - 1].Y + R.Y * (TrackPos - Sum) / D));
     410        R := Point(TrackPoints[I].Point.X - TrackPoints[I - 1].Point.X,
     411          TrackPoints[I].Point.Y - TrackPoints[I - 1].Point.Y);
     412        Result := Point(Trunc(TrackPoints[I - 1].Point.X + R.X * (TrackPos - Sum) / D),
     413          Trunc(TrackPoints[I - 1].Point.Y + R.Y * (TrackPos - Sum) / D));
    381414        Exit;
    382415      end else Sum := Sum + D;
    383416    end;
    384     Result := TrackPoints[High(TrackPoints)];
     417    Result := TrackPoints[High(TrackPoints)].Point;
    385418  end else Result := Point(0, 0);
    386419end;
     
    482515  with TMetroLine(Lines[I]) do begin
    483516    for T := 1 to High(TrackPoints) do begin
    484       D := PointToLineDistance(Pos, TrackPoints[T - 1], TrackPoints[T]);
     517      D := PointToLineDistance(Pos, TrackPoints[T - 1].Point, TrackPoints[T].Point);
    485518      if D < Distance then begin
    486519        Result := TMetroLine(Lines[I]);
     
    616649  P: Integer;
    617650  PosDelta: Integer;
    618   TargetStationIndex: Integer;
    619651  CurrentStation: TMetroStation;
    620   BestStation: TMetroStation;
    621652begin
    622653  if State = gsRunning then begin
     654
     655  // Add new stations
     656  if (Now - LastNewWeekTime) > 7 then begin
     657    LastNewWeekTime := Now;
     658    Trains.AddNew;
     659    // TODO: Show notification screen with confirmation
     660  end;
    623661
    624662  // Add new stations
     
    653691
    654692          // Choose next target station
    655           TargetStationIndex := Line.Stations.IndexOf(TargetStation) + Direction;
     693          TargetStationIndex := TargetStationIndex + Direction;
    656694          if TargetStationIndex < 0 then begin
    657             TargetStationIndex := 1;
    658             Direction := -Direction;
     695            if Line.Stations.Last = Line.Stations.First then begin
     696              TargetStationIndex := Line.Stations.Count - 2;
     697              TrackPos := Line.GetStationTrackPos(Line.Stations.Count - 1);
     698            end else begin
     699              TargetStationIndex := 1;
     700              Direction := -Direction;
     701            end;
    659702          end else if TargetStationIndex >= Line.Stations.Count then begin
    660             TargetStationIndex := Line.Stations.Count - 2;
    661             Direction := -Direction;
     703            if Line.Stations.Last = Line.Stations.First then begin
     704              TargetStationIndex := 1;
     705              TrackPos := 0;
     706            end else begin
     707              TargetStationIndex := Line.Stations.Count - 2;
     708              Direction := -Direction;
     709            end;
    662710          end;
    663           TargetStation := TMetroStation(Line.Stations[TargetStationIndex]);
    664711
    665712          // Unload passengers in target station
     
    695742          end;
    696743
    697           LastPosDelta := Abs(TrackPos - Line.GetStationTrackPos(TargetStation));
     744          LastPosDelta := Abs(TrackPos - Line.GetStationTrackPos(TargetStationIndex));
    698745          InStation := False;
    699746        end;
     
    701748      TrackPos := TrackPos + Direction * TrainSpeed;
    702749      if TrackPos < 0 then begin
    703         TrackPos := 0;
     750        if Line.Stations.First = Line.Stations.Last then TrackPos := Line.GetTrackLength
     751          else TrackPos := 0;
    704752      end else
    705753      if TrackPos > Line.GetTrackLength then begin
    706         TrackPos := Line.GetTrackLength;
    707       end;
    708       PosDelta := Abs(TrackPos - Line.GetStationTrackPos(TargetStation));
     754        if Line.Stations.First = Line.Stations.Last then TrackPos := 0
     755          else TrackPos := Line.GetTrackLength;
     756      end;
     757      PosDelta := Abs(TrackPos - Line.GetStationTrackPos(TargetStationIndex));
    709758      if PosDelta >= LastPosDelta then begin
    710759        // We are getting far from station, stop at station
    711         TrackPos := Line.GetStationTrackPos(TargetStation);
     760        TrackPos := Line.GetStationTrackPos(TargetStationIndex);
    712761        InStation := True;
    713762        StationStopTime := Now;
     
    721770  for I := 0 to Stations.Count - 1 do
    722771  with TMetroStation(Stations[I]) do begin
    723     //if Passengers.Count > MaxWaitingPassengers then State := gsGameOver;
     772    if Passengers.Count > MaxWaitingPassengers then State := gsGameOver;
    724773  end;
    725774
     
    837886  LastNewStationTime := Now;
    838887  LastNewPassengerTime := Now;
     888  LastNewWeekTime := Now;
    839889  State := gsRunning;
    840890  StartTime := Now;
     
    899949    Canvas.Pen.Style := psSolid;
    900950    Canvas.Pen.Width := 15;
    901     if Length(TrackPoints) > 0 then Canvas.MoveTo(TrackPoints[0]);
     951    if Length(TrackPoints) > 0 then Canvas.MoveTo(TrackPoints[0].Point);
    902952    for S := 1 to High(TrackPoints) do begin
    903       Canvas.LineTo(TrackPoints[S]);
     953      Canvas.LineTo(TrackPoints[S].Point);
    904954      if (S = High(TrackPoints)) then begin
    905         Angle := arctan2((TrackPoints[S].Y - TrackPoints[S - 1].Y), (TrackPoints[S].X - TrackPoints[S - 1].X));
    906         EndPoint := Point(Round(TrackPoints[S].X + EndStationLength * Cos(Angle)),
    907           Round(TrackPoints[S].Y + EndStationLength * Sin(Angle)));
     955        Angle := arctan2((TrackPoints[S].Point.Y - TrackPoints[S - 1].Point.Y), (TrackPoints[S].Point.X - TrackPoints[S - 1].Point.X));
     956        EndPoint := Point(Round(TrackPoints[S].Point.X + EndStationLength * Cos(Angle)),
     957          Round(TrackPoints[S].Point.Y + EndStationLength * Sin(Angle)));
    908958        Canvas.LineTo(EndPoint);
    909959        Canvas.MoveTo(Point(Round(EndPoint.X + Cos(Angle + Pi / 2) * EndStationLength / 3),
     
    914964    end;
    915965    if (Length(TrackPoints) > 1) then begin
    916       Angle := arctan2((TrackPoints[1].Y - TrackPoints[0].Y), (TrackPoints[1].X - TrackPoints[0].X));
    917       Canvas.MoveTo(TrackPoints[0]);
    918       EndPoint := Point(Round(TrackPoints[0].X - EndStationLength * Cos(Angle)),
    919         Round(TrackPoints[0].Y - EndStationLength * Sin(Angle)));
     966      Angle := arctan2((TrackPoints[1].Point.Y - TrackPoints[0].Point.Y), (TrackPoints[1].Point.X - TrackPoints[0].Point.X));
     967      Canvas.MoveTo(TrackPoints[0].Point);
     968      EndPoint := Point(Round(TrackPoints[0].Point.X - EndStationLength * Cos(Angle)),
     969        Round(TrackPoints[0].Point.Y - EndStationLength * Sin(Angle)));
    920970      Canvas.LineTo(EndPoint);
    921971      Canvas.MoveTo(Point(Round(EndPoint.X - Cos(Angle + Pi / 2) * EndStationLength / 3),
     
    939989      Canvas.Brush.Style := bsSolid;
    940990      Canvas.Pen.Style := psClear;
    941       Pos := GetPos;
     991      Pos := GetPosition;
    942992      Canvas.Rectangle(Pos.X - TrainSize div 2, Pos.Y - TrainSize div 2,
    943993        Pos.X + TrainSize div 2, Pos.Y + TrainSize div 2);
Note: See TracChangeset for help on using the changeset viewer.