Exemple #1
0
    public void RemoveTimer(GameObject go)
    {
        Timer timer = getChildGameObject(go, "Timer").GetComponent <Timer>();

        if (timer != null && raceStatusPanel != null)
        {
            int count = raceStatusPanel.transform.childCount;
            for (int i = 0; i < count; i++)
            {
                Transform  child = raceStatusPanel.transform.GetChild(i);
                RaceStatus rs    = child.GetComponent <RaceStatus>();
                if (rs.timer == timer)
                {
                    child.transform.parent = null; // detach from parent
                    Destroy(child.gameObject);     // destroy child
                    UpdateRaceStatusPannel();      // update the UI with the new child count
                    Debug.Log("removed timer");
                    return;
                }
            }
            Debug.LogError("failed to find timer while removing it");
            return;
        }
        Debug.LogError("failed to remove timer");
    }
    public void RemoveLapTimer(LapTimer t)
    {
        if (raceStatusPanel == null)
        {
            return;
        }

        int count = raceStatusPanel.transform.childCount;

        for (int i = 0; i < count; i++)
        {
            Transform  child = raceStatusPanel.transform.GetChild(i);
            RaceStatus rs    = child.GetComponent <RaceStatus>();
            if (rs.timer == t)
            {
                Destroy(child.gameObject);
                float height = (count - 1) * raceStatusHeight;
                raceStatusPanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
                raceStatusPanel.anchoredPosition = new Vector3(8.0f, -1 * height, 0.0f);
                Debug.Log("removed lap timer");
                return;
            }
        }

        Debug.LogError("failed to remove lap timer");
    }
        protected override void Init()
        {
            if (jQuery.Browser.Mozilla || jQuery.Browser.Opera)
            {
                _music = LoadAudio("Audio/race.ogg");
            }
            else
            {
                _music = LoadAudio("Audio/race.mp3");
            }

            TimeLeft = RoadLength / 35;

            Position = 0;
            Shift    = 0;

            pendingTimers = new List <int>();

            AddSystem(new RoadSystem());
            AddSystem(new CloudSystem());
            AddSystem(new ObstacleSystem());
            AddSystem(_npcSystem         = new NpcSystem());
            AddSystem(CarSystem          = new CarSystem());
            AddSystem(_engineSoundSystem = new EngineSoundSystem());

            // Get reference to game images
            _backgroundImage = LoadImage("Images/Race/bg.png", false);
            _timeLeftFrame   = LoadImage("Images/Race/TimeLeft.png", false);
            _meterImage      = LoadImage("Images/Race/rpm10.png", false);
            _markerImage     = LoadImage("Images/Race/marker.png", false);

            // Setup the track
            Curve = 0;

            _rpm   = 200;
            Status = RaceStatus.Starting;

            // Calculate the distance table for track rendering
            DistanceTable = new float[Lines];
            for (int i = 0; i < Lines + 1; i++)
            {
                DistanceTable[i] = 1000000 / (300 - i);
            }

            ShowMessage(_startMessage);
            Window.SetTimeout(delegate()
            {
                HideMessage();
                Status = RaceStatus.Running;
                _music.Play();

                _music.AddEventListener("ended", delegate(ElementEvent e) { _music.Play(); }, false);
            }, 3000);
        }
Exemple #4
0
 private void Awake()
 {
     if (Instance == null)
     {
         Instance = this;
     }
     else
     {
         Destroy(gameObject);
     }
 }
        public void Crash()
        {
            if (Status == RaceStatus.Crashing)
            {
                return;
            }

            Speed  = 9;
            Status = RaceStatus.Crashing;
            CarSystem.CarObject.StartAnimation("Crash");
        }
Exemple #6
0
        public bool SetRaceStatus(int race, RaceStatus raceStatus, string login, string gamerefID, string characterID)
        {
            switch (raceStatus)
            {
            case RaceStatus.Commander:
                return(SetCommander(race, login, gamerefID, characterID));

            case RaceStatus.Admiral: {
                var command = GetCommand(race);
                if (!command.firstAdmiral.has)
                {
                    return(SetFirstAdmiral(race, login, gamerefID, characterID));
                }
                else
                {
                    return(SetSecondAdmiral(race, login, gamerefID, characterID));
                }
            }

            case RaceStatus.None:
            {
                var command = GetCommand(race);
                if (command.commander.IsCommander(login, gamerefID, characterID))
                {
                    command.Clear();
                    cache.SetChanged(true);
                    Save();
                    return(true);
                }
                else if (command.firstAdmiral.IsAdmiral(login, gamerefID, characterID))
                {
                    command.firstAdmiral.Clear();
                    cache.SetChanged(true);
                    Save();
                    return(true);
                }
                else if (command.secondAdmiral.IsAdmiral(login, gamerefID, characterID))
                {
                    command.secondAdmiral.Clear();
                    cache.SetChanged(true);
                    Save();
                    return(true);
                }
            }
                return(false);

            default:
                return(false);
            }
        }
Exemple #7
0
    public void AddTimer(Timer t, tk.JsonTcpClient client)
    {
        if (racerStatusPrefab == null)
        {
            return;
        }

        GameObject go = Instantiate(racerStatusPrefab) as GameObject;
        RaceStatus rs = go.GetComponent <RaceStatus>();

        rs.Init(t, client);
        go.transform.SetParent(raceStatusPanel.transform);

        UpdateRaceStatusPannel(); // update the UI with the new child count
        Debug.Log("Added timer");
    }
Exemple #8
0
        public static RaceState FromRace(Race race, RaceStatus status, TimeInvalidReason?timeInvalidReason, string instanceName)
        {
            var transponders = race.Transponders.ToList().AsReadOnly();
            var start        = race.Starts.OrderBy(s => s.When).LastOrDefault(s => s.InstanceName == instanceName);
            var result       = race.Results.SingleOrDefault(r => r.InstanceName == instanceName) ?? new RaceResult
            {
                RaceId            = race.Id,
                InstanceName      = instanceName,
                Status            = status,
                TimeInvalidReason = timeInvalidReason
            };
            var passings      = race.Passings?.Where(p => p.InstanceName == instanceName).Select(RacePassingState.FromPassing).ToList().AsReadOnly();
            var time          = race.Times.SingleOrDefault(r => r.InstanceName == instanceName);
            var laps          = race.Laps?.Where(l => l.InstanceName == instanceName).Select(l => RaceLapState.FromLap(l)).ToList().AsReadOnly();
            var estimatedLaps = race.EstimatedLaps?.ToList().AsReadOnly();

            return(new RaceState(race, transponders, start, result, passings, time, laps, estimatedLaps));
        }
    public void AddLapTimer(LapTimer t, tk.JsonTcpClient client)
    {
        if (raceStatusPrefab == null)
        {
            return;
        }

        Debug.Log("Adding lap timer.");
        GameObject go = Instantiate(raceStatusPrefab) as GameObject;
        RaceStatus rs = go.GetComponent <RaceStatus>();

        rs.Init(t, client);
        go.transform.SetParent(raceStatusPanel.transform);

        float height = raceStatusPanel.transform.childCount * raceStatusHeight;

        raceStatusPanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
        raceStatusPanel.anchoredPosition = new Vector3(8.0f, -1 * height, 0.0f);
    }
Exemple #10
0
        public static void ProcessErgastRaceStatus()
        {
            string fileLocation = Seed.baseLocation + "status.csv";
            var    data         = new List <RaceStatus>();

            // Checks file is currently open.
            using (var sr = new StreamReader(fileLocation))
            {
                data = File.ReadAllLines(fileLocation)
                       .Skip(1)
                       .Select(x => RaceStatus.FromCsv(x))
                       .ToList();
            }

            using (var db = new F1EncyclopediaContext())
            {
                foreach (var rs in data)
                {
                    db.RaceStatuses.AddIfNotExists(rs, x => x.Status == rs.Status);
                }
                db.SaveChanges();
            }
        }
 private void EndRace()
 {
     ResultText.enabled = true;
     status             = RaceStatus.Ended;
 }
 // Start is called before the first frame update
 void Start()
 {
     ResultText.enabled = false;
     status             = RaceStatus.Running;
 }
Exemple #13
0
        public void Crash()
        {
            if (Status == RaceStatus.Crashing) return;

            Speed = 9;
            Status = RaceStatus.Crashing;
            CarSystem.CarObject.StartAnimation("Crash");
        }
Exemple #14
0
        protected override void Update(CanvasContext2D context)
        {
            if (Status != RaceStatus.Fail && Status != RaceStatus.Win)
            {
                context.DrawImage(_timeLeftFrame, 308, 10);

                Type.SetField(context, "textAlign", "right");
                context.FillStyle = "#00AD11";

                if (TimeLeft > 10000 || Math.Floor((TimeLeft / 300) % 2) != 0)
                {
                    if (TimeLeft < 0) TimeLeft = 0;
                    context.Font = "110px Digital";
                    context.FillText(Math.Floor(TimeLeft / 1000).ToString(), 475, 105);
                }

                if (Speed > 0)
                {
                    context.Save();
                    context.Scale(-1, 1);
                    long width = Math.Floor((10 * Speed) / MaxSpeed) * 22;
                    if (width > 0) context.DrawImage(_meterImage, 220 - width, 0, width, 102, -561 - width, 20, width, 102);
                    context.Restore();
                }

                context.Font = "30px Digital";
                context.FillText(Math.Floor(Speed * 5) + " Km/h", 780, 120);

                int rpmWidth = Math.Floor(_rpm / 500) * 22 + 22;

                context.DrawImage(_meterImage, 220 - rpmWidth, 0, rpmWidth, 102, 240 - rpmWidth, 20, rpmWidth, 102);
                context.FillText(Math.Floor(_rpm) + " RPM", 130, 120);

                context.BeginPath();
                context.LineWidth = 3;
                context.StrokeStyle = "#00AD11";
                context.MoveTo(5, 150);
                float x = 5 + Math.Min(Position * 735 / RoadLength, 735);
                context.LineTo(x, 150);
                context.Stroke();
                context.ClosePath();

                context.BeginPath();
                context.StrokeStyle = "#006808";
                context.MoveTo(x, 150);
                context.LineTo(790, 150);
                context.Stroke();
                context.ClosePath();
                context.DrawImage(_markerImage, x, 142);
            }

            if (Status == RaceStatus.Running)
            {
                TimeLeft -= DeltaTime;

                if (TimeLeft < 0)
                {
                    _music.Pause();
                    CarSystem.CarObject.CurrentAnimation = "Forward";
                    Status = RaceStatus.Fail;
                    ShowMessage(_failMessage);
                    RemoveSystem(_engineSoundSystem);
                    RemoveSystem(_npcSystem);
                    pendingTimers.Add(Window.SetTimeout(delegate()
                    {
                        UpdateMessage("<p>Press a key to continue.</p>");
                    }, 3000));
                }
            }
        }
Exemple #15
0
        protected override void PreUpdate(CanvasContext2D context)
        {
            // Draw background
            context.DrawImage(_backgroundImage, 0, 0);

            switch (Status)
            {
                case RaceStatus.Running:
                    // Handle left and right turns
                    if (Speed > 0)
                    {
                        float increment = (60 - Math.Max(Speed, 20)) / 80;

                        if (Left)
                        {
                            Shift += increment * DeltaTime;
                            CarSystem.CarObject.CurrentAnimation = Down ? "b-Left" : "Left";
                        }
                        if (Right)
                        {
                            Shift -= increment * DeltaTime;
                            CarSystem.CarObject.CurrentAnimation = Down ? "b-Right" : "Right";
                        }
                    }

                    if (!(Left ^ Right)) CarSystem.CarObject.CurrentAnimation = Down ? "b-Forward" : "Forward";

                    // Handle acceleration, braking and inertia
                    if (Down) Speed -= 0.4f;
                    else if (Up) Speed += 0.3f;
                    else Speed -= 0.1f;

                    if (Up) _rpm += 40;
                    else _rpm -= 40;
                    if (_rpm > 4500) _rpm = 4500;
                    else if (_rpm < 200) _rpm = 200;

                    // When driving off the road
                    if (Math.Abs(Shift) > 350)
                    {
                        Speed *= 0.95f;

                        if (Math.Abs(Shift) > 450)
                            Shift = (Shift / Math.Abs(Shift)) * 450;
                    }
                    break;

                case RaceStatus.Win:
                case RaceStatus.Fail:
                    Speed -= 1;
                    _rpm -= 40;
                    break;

                case RaceStatus.Crashing:
                    Speed -= 0.3f;
                    Shift -= Shift * DeltaTime / 1000;
                    break;
            }

            // Speed capping
            if (Speed > MaxSpeed) Speed = MaxSpeed;
            if (Speed < 0) Speed = 0;

            // Calculating new position
            Position += Speed * DeltaTime;

            // Drift in turns
            Shift += Curve * Speed * 150;

            if (Position >= RoadLength && Status == RaceStatus.Running)
            {
                _music.Pause();
                Status = RaceStatus.Win;
                CarSystem.CarObject.StartAnimation("Skid");
                ShowMessage(_winMessage);
                RemoveSystem(_engineSoundSystem);
                RemoveSystem(_npcSystem);

                int timeLeft = Math.Floor(TimeLeft / 1000);
                CurrentGame.Score += 1000 + timeLeft * 500;

                //if (!_practice)
                //{
                //    pendingTimers.Add(
                //    Window.SetTimeout(delegate()
                //    {
                //        UpdateMessage("<p>Time Left: " + timeLeft + "</p>");
                //    }, 1500));

                //    pendingTimers.Add(
                //    Window.SetTimeout(delegate()
                //    {
                //        UpdateMessage("<p>Score: " + CurrentGame.Score + "</p>");
                //    }, 2500));
                //}

                pendingTimers.Add(
                Window.SetTimeout(delegate()
                {
                    UpdateMessage("<p>Press a key to continue.</p>");
                }, 3000));
            }
        }
Exemple #16
0
        protected override void Init()
        {
            if (jQuery.Browser.Mozilla)
                _music = LoadAudio("Audio/race.ogg");
            else
                _music = LoadAudio("Audio/race.mp3");

            TimeLeft = RoadLength / 35;

            Position = 0;
            Shift = 0;

            pendingTimers = new List<int>();

            AddSystem(new RoadSystem());
            AddSystem(new CloudSystem());
            AddSystem(new ObstacleSystem());
            AddSystem(_npcSystem = new NpcSystem());
            AddSystem(CarSystem = new CarSystem());
            AddSystem(_engineSoundSystem = new EngineSoundSystem());

            // Get reference to game images
            _backgroundImage = LoadImage("Images/Race/bg.png", false);
            _timeLeftFrame = LoadImage("Images/Race/TimeLeft.png", false);
            _meterImage = LoadImage("Images/Race/rpm10.png", false);
            _markerImage = LoadImage("Images/Race/marker.png", false);

            // Setup the track
            Curve = 0;

            _rpm = 200;
            Status = RaceStatus.Starting;

            // Calculate the distance table for track rendering
            DistanceTable = new float[Lines];
            for (int i = 0; i < Lines + 1; i++)
            {
                DistanceTable[i] = 1000000 / (300 - i);
            }

            ShowMessage(_startMessage);
            Window.SetTimeout(delegate()
            {
                HideMessage();
                Status = RaceStatus.Running;
                _music.Play();

                _music.AddEventListener("ended", delegate(ElementEvent e) { _music.Play(); }, false);
            }, 3000);
        }
Exemple #17
0
        public async Task PresentUserResultAsync(Race race, RaceStatus status, TimeInvalidReason?timeInvalidReason, TimeSpan?time, TimeInfo timeInfo,
                                                 IList <TimeSpan> lapTimes)
        {
            Debug.Assert(race.Distance != null, "race.Distance != null");

            if (status == RaceStatus.Done && !timeInvalidReason.HasValue && !time.HasValue)
            {
                throw new InvalidRaceResultException();
            }

            using (var transaction = context.BeginTransaction(IsolationLevel.RepeatableRead))
                try
                {
                    foreach (var raceResult in race.Results.Where(r => r.InstanceName == UserInstanceName).ToList())
                    {
                        context.RaceResults.Remove(raceResult);
                    }
                    foreach (var raceTime in race.Times.Where(r => r.InstanceName == UserInstanceName).ToList())
                    {
                        context.RaceTimes.Remove(raceTime);
                    }
                    foreach (var raceLap in race.Laps.Where(l => l.InstanceName == UserInstanceName).ToList())
                    {
                        context.RaceLaps.Remove(raceLap);
                    }

                    race.PresentedInstanceName = UserInstanceName;

                    var result = new RaceResult
                    {
                        Race              = race,
                        InstanceName      = UserInstanceName,
                        Status            = status,
                        TimeInvalidReason = timeInvalidReason
                    };

                    if (time.HasValue)
                    {
                        var raceTime = new RaceTime
                        {
                            Race = race,
                            PresentationSource = PresentationSource.User,
                            InstanceName       = UserInstanceName,
                            Time     = time.Value,
                            TimeInfo = timeInfo
                        };
                        race.Times.Add(raceTime);

                        await UpdatePointsAsync(result, raceTime);

                        if (lapTimes != null)
                        {
                            var now = DateTime.UtcNow;
                            foreach (var lapTime in lapTimes)
                            {
                                race.Laps.Add(new RaceLap
                                {
                                    Race = race,
                                    PresentationSource = PresentationSource.User,
                                    InstanceName       = UserInstanceName,
                                    Time  = lapTime,
                                    When  = now - time.Value + lapTime,
                                    Flags = RaceEventFlags.Inserted | RaceEventFlags.Present
                                });
                            }
                        }
                    }
                    race.Results.Add(result);
                    race.Distance.LastRaceCommitted = DateTime.UtcNow;

                    await context.SaveChangesAsync();

                    foreach (var combination in await DistanceCombinations(race.Distance.CompetitionId, race.DistanceId).ToListAsync())
                    {
                        recorder.RecordEvent(new DistanceCombinationClassificationChangedEvent(combination));
                    }

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
        }
Exemple #18
0
        private void Start()
        {
            var optionsBuilder = new DbContextOptionsBuilder <DakarDbContext>();

            optionsBuilder.UseSqlite("Data Source=DakarDatabase.db");

            using (var dataContext = new DakarDbContext(optionsBuilder.Options))
            {
                var _dakarRepo = new DakarRepo(dataContext);

                List <VehicleModel> vehicleModels = _dakarRepo.GetVehiclesFromRace(raceId);
                List <Vehicle>      vehicles      = new List <Vehicle>();
                Thread[]            threads       = new Thread[vehicleModels.Count];

                for (int i = 0; i < vehicleModels.Count; i++)
                {
                    vehicles.Add(new Vehicle(vehicleModels[i]));
                    vehicles[i].VehicleModel.VehicleStatus = VehicleStatus.Running;
                }

                RaceStatus raceStatus = RaceStatus.Running;

                while (raceStatus == RaceStatus.Running)
                {
                    for (int i = 0; i < vehicles.Count; i++)
                    {
                        if (vehicles[i].VehicleModel.VehicleStatus != VehicleStatus.Wracked &&
                            vehicles[i].VehicleModel.VehicleStatus != VehicleStatus.Finished)
                        {
                            threads[i] = new Thread(vehicles[i].Step);
                            threads[i].Start();
                        }
                    }

                    raceStatus = RaceStatus.Finished;

                    for (int i = 0; i < vehicles.Count; i++)
                    {
                        threads[i].Join();

                        if (vehicles[i].VehicleModel.VehicleStatus != VehicleStatus.Finished &&
                            vehicles[i].VehicleModel.VehicleStatus != VehicleStatus.Wracked)
                        {
                            raceStatus = RaceStatus.Running;
                        }

                        if (vehicles[i].MalfunctionStatistic != null)
                        {
                            _dakarRepo.AddMalfunctionStatistic(vehicles[i].MalfunctionStatistic);
                            vehicles[i].MalfunctionStatistic = null;
                        }
                    }

                    Thread.Sleep((int)(dt * 2000));

                    t += dt;
                    _dakarRepo.GetRace(raceId).TimeElapsed = t;

                    _dakarRepo.SaveChanges();
                }

                _dakarRepo.FinishRace();
                _dakarRepo.SaveChanges();
            }
        }
Exemple #19
0
 void UpdateRaceStatus(RaceStatus raceStatus)
 {
     droneRacer.RaceStatus = raceStatus;
 }
Exemple #20
0
        protected override void PreUpdate(CanvasContext2D context)
        {
            // Draw background
            context.DrawImage(_backgroundImage, 0, 0);

            switch (Status)
            {
            case RaceStatus.Running:
                // Handle left and right turns
                if (Speed > 0)
                {
                    float increment = (60 - Math.Max(Speed, 20)) / 80;

                    if (Left)
                    {
                        Shift += increment * DeltaTime;
                        CarSystem.CarObject.CurrentAnimation = Down ? "b-Left" : "Left";
                    }
                    if (Right)
                    {
                        Shift -= increment * DeltaTime;
                        CarSystem.CarObject.CurrentAnimation = Down ? "b-Right" : "Right";
                    }
                }

                if (!(Left ^ Right))
                {
                    CarSystem.CarObject.CurrentAnimation = Down ? "b-Forward" : "Forward";
                }

                // Handle acceleration, braking and inertia
                if (Down)
                {
                    Speed -= 0.4f;
                }
                else if (Up)
                {
                    Speed += 0.3f;
                }
                else
                {
                    Speed -= 0.1f;
                }

                if (Up)
                {
                    _rpm += 40;
                }
                else
                {
                    _rpm -= 40;
                }
                if (_rpm > 4500)
                {
                    _rpm = 4500;
                }
                else if (_rpm < 200)
                {
                    _rpm = 200;
                }

                // When driving off the road
                if (Math.Abs(Shift) > 350)
                {
                    Speed *= 0.95f;

                    if (Math.Abs(Shift) > 450)
                    {
                        Shift = (Shift / Math.Abs(Shift)) * 450;
                    }
                }
                break;

            case RaceStatus.Win:
            case RaceStatus.Fail:
                Speed -= 1;
                _rpm  -= 40;
                break;

            case RaceStatus.Crashing:
                Speed -= 0.3f;
                Shift -= Shift * DeltaTime / 1000;
                break;
            }

            // Speed capping
            if (Speed > MaxSpeed)
            {
                Speed = MaxSpeed;
            }
            if (Speed < 0)
            {
                Speed = 0;
            }

            // Calculating new position
            Position += Speed * DeltaTime;

            // Drift in turns
            Shift += Curve * Speed * 150;

            if (Position >= RoadLength && Status == RaceStatus.Running)
            {
                _music.Pause();
                Status = RaceStatus.Win;
                CarSystem.CarObject.StartAnimation("Skid");
                ShowMessage(_winMessage);
                RemoveSystem(_engineSoundSystem);
                RemoveSystem(_npcSystem);

                int timeLeft = Math.Floor(TimeLeft / 1000);
                CurrentGame.Score += 1000 + timeLeft * 500;

                //if (!_practice)
                //{
                //    pendingTimers.Add(
                //    Window.SetTimeout(delegate()
                //    {
                //        UpdateMessage("<p>Time Left: " + timeLeft + "</p>");
                //    }, 1500));

                //    pendingTimers.Add(
                //    Window.SetTimeout(delegate()
                //    {
                //        UpdateMessage("<p>Score: " + CurrentGame.Score + "</p>");
                //    }, 2500));
                //}

                pendingTimers.Add(
                    Window.SetTimeout(delegate()
                {
                    UpdateMessage("<p>Press a key to continue.</p>");
                }, 3000));
            }
        }
Exemple #21
0
        protected override void Update(CanvasContext2D context)
        {
            if (Status != RaceStatus.Fail && Status != RaceStatus.Win)
            {
                context.DrawImage(_timeLeftFrame, 308, 10);

                Type.SetField(context, "textAlign", "right");
                context.FillStyle = "#00AD11";

                if (TimeLeft > 10000 || Math.Floor((TimeLeft / 300) % 2) != 0)
                {
                    if (TimeLeft < 0)
                    {
                        TimeLeft = 0;
                    }
                    context.Font = "110px Digital";
                    context.FillText(Math.Floor(TimeLeft / 1000).ToString(), 475, 105);
                }

                if (Speed > 0)
                {
                    context.Save();
                    context.Scale(-1, 1);
                    long width = Math.Floor((10 * Speed) / MaxSpeed) * 22;
                    if (width > 0)
                    {
                        context.DrawImage(_meterImage, 220 - width, 0, width, 102, -561 - width, 20, width, 102);
                    }
                    context.Restore();
                }

                context.Font = "30px Digital";
                context.FillText(Math.Floor(Speed * 5) + " Km/h", 780, 120);

                int rpmWidth = Math.Floor(_rpm / 500) * 22 + 22;

                context.DrawImage(_meterImage, 220 - rpmWidth, 0, rpmWidth, 102, 240 - rpmWidth, 20, rpmWidth, 102);
                context.FillText(Math.Floor(_rpm) + " RPM", 130, 120);

                context.BeginPath();
                context.LineWidth   = 3;
                context.StrokeStyle = "#00AD11";
                context.MoveTo(5, 150);
                float x = 5 + Math.Min(Position * 735 / RoadLength, 735);
                context.LineTo(x, 150);
                context.Stroke();
                context.ClosePath();

                context.BeginPath();
                context.StrokeStyle = "#006808";
                context.MoveTo(x, 150);
                context.LineTo(790, 150);
                context.Stroke();
                context.ClosePath();
                context.DrawImage(_markerImage, x, 142);
            }

            if (Status == RaceStatus.Running)
            {
                TimeLeft -= DeltaTime;

                if (TimeLeft < 0)
                {
                    _music.Pause();
                    CarSystem.CarObject.CurrentAnimation = "Forward";
                    Status = RaceStatus.Fail;
                    ShowMessage(_failMessage);
                    RemoveSystem(_engineSoundSystem);
                    RemoveSystem(_npcSystem);
                    pendingTimers.Add(Window.SetTimeout(delegate()
                    {
                        UpdateMessage("<p>Press a key to continue.</p>");
                    }, 3000));
                }
            }
        }