| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- //-----------------------------------------------------------------------------
- // Replay.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Microsoft.Xna.Framework;
- using RacingGame.Helpers;
- using System.IO;
- using RacingGame.GameScreens;
- using RacingGame.Tracks;
- namespace RacingGame.GameLogic
- {
- /// <summary>
- /// This class stores a replay for a track, which means we can
- /// see how the player drove one lap of the track. It will be
- /// replace once we drive faster than the current record.
- /// By default we start with the default replay, which just shows
- /// the computer driving at a low speed.
- /// </summary>
- public class Replay : ICloneable
- {
- /// <summary>
- /// Track matrix intervals between the trackMatrixValues.
- /// </summary>
- public const float TrackMatrixIntervals = 0.2f;
- /// <summary>
- /// Replay filenames for each of the tracks
- /// </summary>
- static readonly string[] ReplayFilenames = new string[]
- {
- "TrackBeginner.Replay",
- "TrackAdvanced.Replay",
- "TrackExpert.Replay",
- };
- /// <summary>
- /// Track number for this replay: 0 (beginner), 1 (advanced) or 2 (expert)
- /// </summary>
- int trackNum = 0;
- /// <summary>
- /// Lap time for this replay in seconds.
- /// </summary>
- float lapTime = 0.0f;
- /// <summary>
- /// Track matrix values, each value contains the position and
- /// rotatation of the car at that specific time.
- /// Between this values the car matrix will get interpolated.
- /// </summary>
- List<Matrix> trackMatrixValues = new List<Matrix>();
- /// <summary>
- /// Times for each checkpoint for comparing if we have done
- /// better or worse than the best time.
- /// </summary>
- List<float> checkpointTimes = new List<float>();
- /// <summary>
- /// Track number
- /// </summary>
- public int TrackNumber
- {
- get
- {
- return trackNum;
- }
- }
- /// <summary>
- /// Lap time
- /// </summary>
- public float LapTime
- {
- get
- {
- return lapTime;
- }
- set
- {
- lapTime = value;
- }
- }
- /// <summary>
- /// Number of track matrices currently in trackMatrixValues list.
- /// </summary>
- public int NumberOfTrackMatrices
- {
- get
- {
- return trackMatrixValues.Count;
- }
- }
- /// <summary>
- /// Track number
- /// </summary>
- public List<float> CheckpointTimes
- {
- get
- {
- return checkpointTimes;
- }
- }
- /// <summary>
- /// Get car matrix at time (interpolated)
- /// </summary>
- /// <param name="trackTime">Track time</param>
- /// <returns>Matrix</returns>
- public Matrix GetCarMatrixAtTime(float trackTime)
- {
- // No values available? We need at least 2 matrices!
- if (trackMatrixValues.Count < 2)
- return Matrix.Identity;
- // Not started yet? Then just return start matrix
- if (trackTime <= 0.0f)
- return trackMatrixValues[0];
- // Get track num and percent of the current interval.
- int trackNum = (int)(trackTime / TrackMatrixIntervals);
- float trackIntervalPercent =
- (trackTime - trackNum * TrackMatrixIntervals) /
- TrackMatrixIntervals;
- if (trackNum < 0)
- trackNum = 0;
- // At end? Then wait at start, do not interpolate anymore!
- if (trackNum > trackMatrixValues.Count - 2)
- return trackMatrixValues[0];
- // Interpolate and return
- return Matrix.Lerp(
- trackMatrixValues[trackNum],
- trackMatrixValues[trackNum + 1],
- trackIntervalPercent);
- }
- /// <summary>
- /// Create new replay for a specific track number.
- /// </summary>
- /// <param name="setTrackNum">Set track number</param>
- public Replay(int setTrackNum, bool createNew, Track track)
- {
- trackNum = setTrackNum;
- // if creating new, we're done
- if (createNew == true)
- {
- return;
- }
- bool replayFileFound = false;
- FileHelper.StorageContainerMRE.WaitOne();
- FileHelper.StorageContainerMRE.Reset();
- try
- {
- /*
- StorageDevice storageDevice = FileHelper.XnaUserDevice;
- if ((storageDevice != null) && storageDevice.IsConnected)
- {
- IAsyncResult async = storageDevice.BeginOpenContainer("RacingGame", null, null);
- async.AsyncWaitHandle.WaitOne();
- using (StorageContainer container =
- storageDevice.EndOpenContainer(async))
- {
- async.AsyncWaitHandle.Close();
- if (container.FileExists(ReplayFilenames[trackNum]))
- {
- using (Stream stream = container.OpenFile(ReplayFilenames[trackNum],
- FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
- {
- using (BinaryReader reader = new BinaryReader(stream))
- {
- // Load total lap time
- lapTime = reader.ReadSingle();
- // Load matrix values
- int numOfMatrixValues = reader.ReadInt32();
- for (int num = 0; num < numOfMatrixValues; num++)
- trackMatrixValues.Add(
- FileHelper.ReadMatrix(reader));
- // Load checkpoint times
- int numOfCheckpointTimes = reader.ReadInt32();
- for (int num = 0; num < numOfCheckpointTimes; num++)
- checkpointTimes.Add(reader.ReadSingle());
- }
- }
- }
- }
- }*/
- }
- catch (Exception exc)
- {
- System.Diagnostics.Debug.WriteLine("Settings Load Failure: " + exc.ToString());
- }
- FileHelper.StorageContainerMRE.Set();
- // Load if possible
- if (!replayFileFound && File.Exists(Path.Combine(
- Directories.ContentDirectory, ReplayFilenames[trackNum])))
- {
- using (Stream stream = TitleContainer.OpenStream(
- Path.Combine("Content", ReplayFilenames[trackNum])))
- {
- using (BinaryReader reader = new BinaryReader(stream))
- {
- // Load total lap time
- lapTime = reader.ReadSingle();
- // Load matrix values
- int numOfMatrixValues = reader.ReadInt32();
- for (int num = 0; num < numOfMatrixValues; num++)
- trackMatrixValues.Add(
- FileHelper.ReadMatrix(reader));
- // Load checkpoint times
- int numOfCheckpointTimes = reader.ReadInt32();
- for (int num = 0; num < numOfCheckpointTimes; num++)
- checkpointTimes.Add(reader.ReadSingle());
- }
- }
- }
- if (!replayFileFound)
- {
- // Create new default replay for this track!
- // Get all track positions based on the current top highscore time!
- lapTime = Highscores.GetTopLapTime(trackNum);
- int numOfMatrixValues = 1 + (int)(lapTime / TrackMatrixIntervals);
- float lastTrackPos = 0.0f;
- int oldTrackSegmentNumber = 0;
- // Go twice as long and abort when we reach the finish line!
- for (int num = 0; num < numOfMatrixValues * 2; num++)
- {
- // See Landscape.TestRenderLandscape for more details.
- float carTrackPos = 0.00001f +
- ((float)num / (float)(numOfMatrixValues - 1));// *
- //not needed, scaled in GetTrackPositionMatrix: track.Length;
- float difference = carTrackPos - lastTrackPos;
- carTrackPos = lastTrackPos + difference * 0.1f;
- lastTrackPos = carTrackPos;
- float roadWidth, nextRoadWidth;
- Matrix carMatrix =
- track.GetTrackPositionMatrix(carTrackPos,
- out roadWidth, out nextRoadWidth);
- // Store
- trackMatrixValues.Add(carMatrix);
- // Also check if we passed a checkpoint
- int trackSegmentNumber =
- (int)(carTrackPos * track.NumberOfSegments);
- // Segment changed
- if (trackSegmentNumber != oldTrackSegmentNumber)
- {
- // Check if we passed a checkpoint.
- for (int checkpointNum = 0; checkpointNum < track.
- CheckpointSegmentPositions.Count; checkpointNum++)
- {
- // We have to check if we are between the old
- // and the current track segement numbers, we
- // might skip one or two in 200ms.
- if (track.CheckpointSegmentPositions[checkpointNum] >
- oldTrackSegmentNumber &&
- track.CheckpointSegmentPositions[checkpointNum] <=
- trackSegmentNumber)
- {
- // We passed that checkpoint, add the simulated time
- checkpointTimes.Add(
- lapTime * (float)num / (float)(numOfMatrixValues - 1));
- break;
- }
- }
- }
- oldTrackSegmentNumber = trackSegmentNumber;
- // Reached finish?
- if (carTrackPos >= 1.0f)
- // Then abort, do not add more.
- break;
- }
- // Add the final checkpoint for the laptime
- checkpointTimes.Add(lapTime);
- }
- }
- /// <summary>
- /// Save this replay, will be saved to
- /// TrackBeginner.replay, TrackAdvanced.replay or TrackExpert.replay.
- /// </summary>
- public void Save()
- {
- FileHelper.StorageContainerMRE.WaitOne();
- FileHelper.StorageContainerMRE.Reset();
- try
- {
- /*
- StorageDevice storageDevice = FileHelper.XnaUserDevice;
- if ((storageDevice != null) && storageDevice.IsConnected)
- {
- IAsyncResult async = storageDevice.BeginOpenContainer("RacingGame", null, null);
- async.AsyncWaitHandle.WaitOne();
- using (StorageContainer container =
- storageDevice.EndOpenContainer(async))
- {
- async.AsyncWaitHandle.Close();
- using (Stream stream = container.CreateFile(ReplayFilenames[trackNum]))
- {
- using (BinaryWriter writer = new BinaryWriter(stream))
- {
- // Save lap time
- writer.Write(lapTime);
- // Save track matrix values
- writer.Write(trackMatrixValues.Count);
- for (int num = 0; num < trackMatrixValues.Count; num++)
- FileHelper.WriteMatrix(writer, trackMatrixValues[num]);
- // Save checkpoint times
- writer.Write(checkpointTimes.Count);
- for (int num = 0; num < checkpointTimes.Count; num++)
- writer.Write(checkpointTimes[num]);
- }
- }
- }
- }*/
- }
- catch (Exception exc)
- {
- System.Diagnostics.Debug.WriteLine("Settings Load Failure: " + exc.ToString());
- }
- FileHelper.StorageContainerMRE.Set();
- }
- /// <summary>
- /// Creates a deep copy of a replay object
- /// </summary>
- /// <returns>Deep copy</returns>
- public object Clone()
- {
- Replay clone = (Replay)this.MemberwiseClone();
- clone.checkpointTimes = new List<float>(this.checkpointTimes);
- clone.trackMatrixValues = new List<Matrix>(this.trackMatrixValues);
- return clone;
- }
- /// <summary>
- /// Add car matrix to trackMatrixValues.
- /// </summary>
- /// <param name="addMatrix">Add matrix</param>
- public void AddCarMatrix(Matrix addMatrix)
- {
- trackMatrixValues.Add(addMatrix);
- }
- }
- }
|