Replay.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. //-----------------------------------------------------------------------------
  2. // Replay.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Microsoft.Xna.Framework;
  11. using RacingGame.Helpers;
  12. using System.IO;
  13. using RacingGame.GameScreens;
  14. using RacingGame.Tracks;
  15. namespace RacingGame.GameLogic
  16. {
  17. /// <summary>
  18. /// This class stores a replay for a track, which means we can
  19. /// see how the player drove one lap of the track. It will be
  20. /// replace once we drive faster than the current record.
  21. /// By default we start with the default replay, which just shows
  22. /// the computer driving at a low speed.
  23. /// </summary>
  24. public class Replay : ICloneable
  25. {
  26. /// <summary>
  27. /// Track matrix intervals between the trackMatrixValues.
  28. /// </summary>
  29. public const float TrackMatrixIntervals = 0.2f;
  30. /// <summary>
  31. /// Replay filenames for each of the tracks
  32. /// </summary>
  33. static readonly string[] ReplayFilenames = new string[]
  34. {
  35. "TrackBeginner.Replay",
  36. "TrackAdvanced.Replay",
  37. "TrackExpert.Replay",
  38. };
  39. /// <summary>
  40. /// Track number for this replay: 0 (beginner), 1 (advanced) or 2 (expert)
  41. /// </summary>
  42. int trackNum = 0;
  43. /// <summary>
  44. /// Lap time for this replay in seconds.
  45. /// </summary>
  46. float lapTime = 0.0f;
  47. /// <summary>
  48. /// Track matrix values, each value contains the position and
  49. /// rotatation of the car at that specific time.
  50. /// Between this values the car matrix will get interpolated.
  51. /// </summary>
  52. List<Matrix> trackMatrixValues = new List<Matrix>();
  53. /// <summary>
  54. /// Times for each checkpoint for comparing if we have done
  55. /// better or worse than the best time.
  56. /// </summary>
  57. List<float> checkpointTimes = new List<float>();
  58. /// <summary>
  59. /// Track number
  60. /// </summary>
  61. public int TrackNumber
  62. {
  63. get
  64. {
  65. return trackNum;
  66. }
  67. }
  68. /// <summary>
  69. /// Lap time
  70. /// </summary>
  71. public float LapTime
  72. {
  73. get
  74. {
  75. return lapTime;
  76. }
  77. set
  78. {
  79. lapTime = value;
  80. }
  81. }
  82. /// <summary>
  83. /// Number of track matrices currently in trackMatrixValues list.
  84. /// </summary>
  85. public int NumberOfTrackMatrices
  86. {
  87. get
  88. {
  89. return trackMatrixValues.Count;
  90. }
  91. }
  92. /// <summary>
  93. /// Track number
  94. /// </summary>
  95. public List<float> CheckpointTimes
  96. {
  97. get
  98. {
  99. return checkpointTimes;
  100. }
  101. }
  102. /// <summary>
  103. /// Get car matrix at time (interpolated)
  104. /// </summary>
  105. /// <param name="trackTime">Track time</param>
  106. /// <returns>Matrix</returns>
  107. public Matrix GetCarMatrixAtTime(float trackTime)
  108. {
  109. // No values available? We need at least 2 matrices!
  110. if (trackMatrixValues.Count < 2)
  111. return Matrix.Identity;
  112. // Not started yet? Then just return start matrix
  113. if (trackTime <= 0.0f)
  114. return trackMatrixValues[0];
  115. // Get track num and percent of the current interval.
  116. int trackNum = (int)(trackTime / TrackMatrixIntervals);
  117. float trackIntervalPercent =
  118. (trackTime - trackNum * TrackMatrixIntervals) /
  119. TrackMatrixIntervals;
  120. if (trackNum < 0)
  121. trackNum = 0;
  122. // At end? Then wait at start, do not interpolate anymore!
  123. if (trackNum > trackMatrixValues.Count - 2)
  124. return trackMatrixValues[0];
  125. // Interpolate and return
  126. return Matrix.Lerp(
  127. trackMatrixValues[trackNum],
  128. trackMatrixValues[trackNum + 1],
  129. trackIntervalPercent);
  130. }
  131. /// <summary>
  132. /// Create new replay for a specific track number.
  133. /// </summary>
  134. /// <param name="setTrackNum">Set track number</param>
  135. public Replay(int setTrackNum, bool createNew, Track track)
  136. {
  137. trackNum = setTrackNum;
  138. // if creating new, we're done
  139. if (createNew == true)
  140. {
  141. return;
  142. }
  143. bool replayFileFound = false;
  144. FileHelper.StorageContainerMRE.WaitOne();
  145. FileHelper.StorageContainerMRE.Reset();
  146. try
  147. {
  148. /*
  149. StorageDevice storageDevice = FileHelper.XnaUserDevice;
  150. if ((storageDevice != null) && storageDevice.IsConnected)
  151. {
  152. IAsyncResult async = storageDevice.BeginOpenContainer("RacingGame", null, null);
  153. async.AsyncWaitHandle.WaitOne();
  154. using (StorageContainer container =
  155. storageDevice.EndOpenContainer(async))
  156. {
  157. async.AsyncWaitHandle.Close();
  158. if (container.FileExists(ReplayFilenames[trackNum]))
  159. {
  160. using (Stream stream = container.OpenFile(ReplayFilenames[trackNum],
  161. FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
  162. {
  163. using (BinaryReader reader = new BinaryReader(stream))
  164. {
  165. // Load total lap time
  166. lapTime = reader.ReadSingle();
  167. // Load matrix values
  168. int numOfMatrixValues = reader.ReadInt32();
  169. for (int num = 0; num < numOfMatrixValues; num++)
  170. trackMatrixValues.Add(
  171. FileHelper.ReadMatrix(reader));
  172. // Load checkpoint times
  173. int numOfCheckpointTimes = reader.ReadInt32();
  174. for (int num = 0; num < numOfCheckpointTimes; num++)
  175. checkpointTimes.Add(reader.ReadSingle());
  176. }
  177. }
  178. }
  179. }
  180. }*/
  181. }
  182. catch (Exception exc)
  183. {
  184. System.Diagnostics.Debug.WriteLine("Settings Load Failure: " + exc.ToString());
  185. }
  186. FileHelper.StorageContainerMRE.Set();
  187. // Load if possible
  188. if (!replayFileFound && File.Exists(Path.Combine(
  189. Directories.ContentDirectory, ReplayFilenames[trackNum])))
  190. {
  191. using (Stream stream = TitleContainer.OpenStream(
  192. Path.Combine("Content", ReplayFilenames[trackNum])))
  193. {
  194. using (BinaryReader reader = new BinaryReader(stream))
  195. {
  196. // Load total lap time
  197. lapTime = reader.ReadSingle();
  198. // Load matrix values
  199. int numOfMatrixValues = reader.ReadInt32();
  200. for (int num = 0; num < numOfMatrixValues; num++)
  201. trackMatrixValues.Add(
  202. FileHelper.ReadMatrix(reader));
  203. // Load checkpoint times
  204. int numOfCheckpointTimes = reader.ReadInt32();
  205. for (int num = 0; num < numOfCheckpointTimes; num++)
  206. checkpointTimes.Add(reader.ReadSingle());
  207. }
  208. }
  209. }
  210. if (!replayFileFound)
  211. {
  212. // Create new default replay for this track!
  213. // Get all track positions based on the current top highscore time!
  214. lapTime = Highscores.GetTopLapTime(trackNum);
  215. int numOfMatrixValues = 1 + (int)(lapTime / TrackMatrixIntervals);
  216. float lastTrackPos = 0.0f;
  217. int oldTrackSegmentNumber = 0;
  218. // Go twice as long and abort when we reach the finish line!
  219. for (int num = 0; num < numOfMatrixValues * 2; num++)
  220. {
  221. // See Landscape.TestRenderLandscape for more details.
  222. float carTrackPos = 0.00001f +
  223. ((float)num / (float)(numOfMatrixValues - 1));// *
  224. //not needed, scaled in GetTrackPositionMatrix: track.Length;
  225. float difference = carTrackPos - lastTrackPos;
  226. carTrackPos = lastTrackPos + difference * 0.1f;
  227. lastTrackPos = carTrackPos;
  228. float roadWidth, nextRoadWidth;
  229. Matrix carMatrix =
  230. track.GetTrackPositionMatrix(carTrackPos,
  231. out roadWidth, out nextRoadWidth);
  232. // Store
  233. trackMatrixValues.Add(carMatrix);
  234. // Also check if we passed a checkpoint
  235. int trackSegmentNumber =
  236. (int)(carTrackPos * track.NumberOfSegments);
  237. // Segment changed
  238. if (trackSegmentNumber != oldTrackSegmentNumber)
  239. {
  240. // Check if we passed a checkpoint.
  241. for (int checkpointNum = 0; checkpointNum < track.
  242. CheckpointSegmentPositions.Count; checkpointNum++)
  243. {
  244. // We have to check if we are between the old
  245. // and the current track segement numbers, we
  246. // might skip one or two in 200ms.
  247. if (track.CheckpointSegmentPositions[checkpointNum] >
  248. oldTrackSegmentNumber &&
  249. track.CheckpointSegmentPositions[checkpointNum] <=
  250. trackSegmentNumber)
  251. {
  252. // We passed that checkpoint, add the simulated time
  253. checkpointTimes.Add(
  254. lapTime * (float)num / (float)(numOfMatrixValues - 1));
  255. break;
  256. }
  257. }
  258. }
  259. oldTrackSegmentNumber = trackSegmentNumber;
  260. // Reached finish?
  261. if (carTrackPos >= 1.0f)
  262. // Then abort, do not add more.
  263. break;
  264. }
  265. // Add the final checkpoint for the laptime
  266. checkpointTimes.Add(lapTime);
  267. }
  268. }
  269. /// <summary>
  270. /// Save this replay, will be saved to
  271. /// TrackBeginner.replay, TrackAdvanced.replay or TrackExpert.replay.
  272. /// </summary>
  273. public void Save()
  274. {
  275. FileHelper.StorageContainerMRE.WaitOne();
  276. FileHelper.StorageContainerMRE.Reset();
  277. try
  278. {
  279. /*
  280. StorageDevice storageDevice = FileHelper.XnaUserDevice;
  281. if ((storageDevice != null) && storageDevice.IsConnected)
  282. {
  283. IAsyncResult async = storageDevice.BeginOpenContainer("RacingGame", null, null);
  284. async.AsyncWaitHandle.WaitOne();
  285. using (StorageContainer container =
  286. storageDevice.EndOpenContainer(async))
  287. {
  288. async.AsyncWaitHandle.Close();
  289. using (Stream stream = container.CreateFile(ReplayFilenames[trackNum]))
  290. {
  291. using (BinaryWriter writer = new BinaryWriter(stream))
  292. {
  293. // Save lap time
  294. writer.Write(lapTime);
  295. // Save track matrix values
  296. writer.Write(trackMatrixValues.Count);
  297. for (int num = 0; num < trackMatrixValues.Count; num++)
  298. FileHelper.WriteMatrix(writer, trackMatrixValues[num]);
  299. // Save checkpoint times
  300. writer.Write(checkpointTimes.Count);
  301. for (int num = 0; num < checkpointTimes.Count; num++)
  302. writer.Write(checkpointTimes[num]);
  303. }
  304. }
  305. }
  306. }*/
  307. }
  308. catch (Exception exc)
  309. {
  310. System.Diagnostics.Debug.WriteLine("Settings Load Failure: " + exc.ToString());
  311. }
  312. FileHelper.StorageContainerMRE.Set();
  313. }
  314. /// <summary>
  315. /// Creates a deep copy of a replay object
  316. /// </summary>
  317. /// <returns>Deep copy</returns>
  318. public object Clone()
  319. {
  320. Replay clone = (Replay)this.MemberwiseClone();
  321. clone.checkpointTimes = new List<float>(this.checkpointTimes);
  322. clone.trackMatrixValues = new List<Matrix>(this.trackMatrixValues);
  323. return clone;
  324. }
  325. /// <summary>
  326. /// Add car matrix to trackMatrixValues.
  327. /// </summary>
  328. /// <param name="addMatrix">Add matrix</param>
  329. public void AddCarMatrix(Matrix addMatrix)
  330. {
  331. trackMatrixValues.Add(addMatrix);
  332. }
  333. }
  334. }