UIRenderer.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. //-----------------------------------------------------------------------------
  2. // UIRenderer.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using Microsoft.Xna.Framework;
  8. using Microsoft.Xna.Framework.Graphics;
  9. using Microsoft.Xna.Framework.Input;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Diagnostics;
  13. using System.Text;
  14. using RacingGame.GameLogic;
  15. using RacingGame.Helpers;
  16. using RacingGame.Shaders;
  17. using RacingGame.Tracks;
  18. using RacingGame.GameScreens;
  19. namespace RacingGame.Graphics
  20. {
  21. /// <summary>
  22. /// Helper class to render all UI 2D stuff. Rendering textures is very easy
  23. /// with XNA using the Sprite class, but we still have to create
  24. /// SpriteBatches. This class helps and handles everything for us.
  25. /// </summary>
  26. public class UIRenderer : IDisposable
  27. {
  28. /// <summary>
  29. /// Graphic rectangles for displaying UI stuff.
  30. /// </summary>
  31. public readonly static Rectangle
  32. BackgroundGfxRect = new Rectangle(0, 0, 1024, 640),
  33. RacingGameLogoGfxRect = new Rectangle(0, 1024 - 375, 1024, 374),
  34. BottomLeftBorderGfxRect = new Rectangle(2, 984, 38, 37),
  35. BottomRightBorderGfxRect = new Rectangle(42, 984, 38, 37),
  36. PressStartGfxRect = new Rectangle(2, 1, 631, 45),
  37. HeaderChooseCarGfxRect = new Rectangle(0, 212, 512, 100),
  38. HeaderOptionsGfxRect = new Rectangle(512, 212, 512, 100),
  39. HeaderSelectTrackGfxRect = new Rectangle(0, 312, 512, 100),
  40. HeaderHelpGfxRect = new Rectangle(512, 312, 512, 100),
  41. HeaderHighscoresGfxRect = new Rectangle(0, 412, 512, 100),
  42. BlackBarGfxRect = new Rectangle(99, 999, 1, 1),
  43. OptionsRadioButtonGfxRect = new Rectangle(128, 980, 25, 25),
  44. MenuButtonPlayGfxRect = new Rectangle(0, 0, 212, 212),
  45. MenuButtonHighscoresGfxRect = new Rectangle(212, 0, 212, 212),
  46. MenuButtonOptionsGfxRect = new Rectangle(2 * 212, 0, 212, 212),
  47. MenuButtonHelpGfxRect = new Rectangle(3 * 212, 0, 212, 212),
  48. MenuButtonQuitGfxRect = new Rectangle(212, 240, 212, 212),
  49. MenuButtonSelectionGfxRect = new Rectangle(3 * 212, 240, 212, 212),
  50. MenuTextPlayGfxRect = new Rectangle(0, 214, 212, 24),
  51. MenuTextHighscoresGfxRect = new Rectangle(212, 214, 212, 24),
  52. MenuTextOptionsGfxRect = new Rectangle(2 * 212, 214, 212, 24),
  53. MenuTextHelpGfxRect = new Rectangle(3 * 212, 214, 212, 24),
  54. MenuTextQuitGfxRect = new Rectangle(212, 240 + 214, 212, 24),
  55. BigArrowGfxRect = new Rectangle(867, 242, 127, 178),
  56. TrackButtonBeginnerGfxRect = new Rectangle(0, 480, 212, 352),
  57. TrackButtonAdvancedGfxRect = new Rectangle(212, 480, 212, 352),
  58. TrackButtonExpertGfxRect = new Rectangle(2 * 212, 480, 212, 352),
  59. TrackButtonSelectionGfxRect = new Rectangle(3 * 212, 480, 212, 352),
  60. TrackTextBeginnerGfxRect = new Rectangle(0, 834, 212, 24),
  61. TrackTextAdvancedGfxRect = new Rectangle(212, 834, 212, 24),
  62. TrackTextExpertGfxRect = new Rectangle(2 * 212, 834, 212, 24),
  63. BottomButtonSelectionGfxRect = new Rectangle(212 * 2, 240, 212, 92),
  64. BottomButtonAButtonGfxRect = new Rectangle(0, 872, 212, 92),
  65. BottomButtonBButtonGfxRect = new Rectangle(212, 872, 212, 92),
  66. BottomButtonBackButtonGfxRect = new Rectangle(2 * 212, 872, 212, 92),
  67. BottomButtonStartButtonGfxRect = new Rectangle(3 * 212, 872, 212, 92),
  68. SelectionArrowGfxRect = new Rectangle(874, 426, 53, 39),
  69. SelectionRadioButtonGfxRect = new Rectangle(935, 427, 39, 39);
  70. /// <summary>
  71. /// In game gfx rects. Tacho is our speedometer we see on the screen.
  72. /// </summary>
  73. public static readonly Rectangle
  74. LapsGfxRect = new Rectangle(381, 132, 222, 160),
  75. TachoGfxRect = new Rectangle(0, 0, 343, 341),
  76. TachoArrowGfxRect = new Rectangle(347, 0, 28, 186),
  77. TachoMphGfxRect = new Rectangle(184, 256, 148, 72),
  78. TachoGearGfxRect = new Rectangle(286, 149, 52, 72),
  79. CurrentAndBestGfxRect = new Rectangle(381, 2, 342, 128),
  80. CurrentTimePosGfxRect = new Rectangle(540, 8, 170, 52),
  81. BestTimePosGfxRect = new Rectangle(540, 72, 170, 52),
  82. TrackNameGfxRect = new Rectangle(726, 2, 282, 62),
  83. Best5GfxRect = new Rectangle(726, 66, 282, 62);
  84. /// <summary>
  85. /// Background
  86. /// </summary>
  87. Texture background;
  88. /// <summary>
  89. /// Buttons
  90. /// </summary>
  91. Texture buttons;
  92. /// <summary>
  93. /// Headers
  94. /// </summary>
  95. Texture headers;
  96. /// <summary>
  97. /// Help screen texture
  98. /// </summary>
  99. Texture helpScreen;
  100. /// <summary>
  101. /// Options screen texture
  102. /// </summary>
  103. Texture optionsScreen;
  104. /// <summary>
  105. /// Mouse cursor
  106. /// </summary>
  107. Texture mouseCursor;
  108. /// <summary>
  109. /// Font
  110. /// </summary>
  111. TextureFont font;
  112. /// <summary>
  113. /// Post screen menu shader for cool screen effects like the TV effect,
  114. /// stripes, a flash effect and some color correction.
  115. /// </summary>
  116. PostScreenMenu postScreenMenuShader;
  117. /// <summary>
  118. /// Post screen game shader for glow, color correction and motion blur
  119. /// effects in the game.
  120. /// </summary>
  121. PostScreenGlow postScreenGameShader;
  122. /// <summary>
  123. /// Sky cube background rendering
  124. /// </summary>
  125. PreScreenSkyCubeMapping skyCube = null;
  126. /// <summary>
  127. /// And finally the lens flare we render at the end.
  128. /// </summary>
  129. LensFlare lensFlare = null;
  130. /// <summary>
  131. /// Ingame texture for the speed, gear, time, rank, laps, etc.
  132. /// </summary>
  133. Texture ingame = null;
  134. /// <summary>
  135. /// Trophies
  136. /// </summary>
  137. Texture[] trophies = new Texture[3];
  138. /// <summary>
  139. /// Buttons
  140. /// </summary>
  141. /// <returns>Texture</returns>
  142. public Texture Buttons
  143. {
  144. get
  145. {
  146. return buttons;
  147. }
  148. }
  149. /// <summary>
  150. /// Headers
  151. /// </summary>
  152. /// <returns>Texture</returns>
  153. public Texture Headers
  154. {
  155. get
  156. {
  157. return headers;
  158. }
  159. }
  160. /// <summary>
  161. /// Help screen
  162. /// </summary>
  163. /// <returns>Texture</returns>
  164. public Texture HelpScreen
  165. {
  166. get
  167. {
  168. return helpScreen;
  169. }
  170. }
  171. /// <summary>
  172. /// Options screen
  173. /// </summary>
  174. /// <returns>Texture</returns>
  175. public Texture OptionsScreen
  176. {
  177. get
  178. {
  179. return optionsScreen;
  180. }
  181. }
  182. /// <summary>
  183. /// Ingame
  184. /// </summary>
  185. /// <returns>Texture</returns>
  186. public Texture Ingame
  187. {
  188. get
  189. {
  190. return ingame;
  191. }
  192. }
  193. /// <summary>
  194. /// Trophy types we can get at the end of each game.
  195. /// Gold means new record. Silver means place 2
  196. /// and Bronse is used for everything below (since we won ^^).
  197. /// </summary>
  198. public enum TrophyType
  199. {
  200. Gold,
  201. Silver,
  202. Bronze,
  203. }
  204. /// <summary>
  205. /// Get trophy texture
  206. /// </summary>
  207. /// <param name="trophyType">Trophy type</param>
  208. /// <returns>Texture</returns>
  209. public Texture GetTrophyTexture(TrophyType trophyType)
  210. {
  211. return trophies[(int)trophyType];
  212. }
  213. /// <summary>
  214. /// Post screen menu shader
  215. /// </summary>
  216. /// <returns>Post screen menu</returns>
  217. public PostScreenMenu PostScreenMenuShader
  218. {
  219. get
  220. {
  221. return postScreenMenuShader;
  222. }
  223. }
  224. public PostScreenGlow PostScreenGlowShader
  225. {
  226. get
  227. {
  228. return postScreenGameShader;
  229. }
  230. }
  231. /// <summary>
  232. /// Sky cube map texture
  233. /// </summary>
  234. /// <returns>Texture cube</returns>
  235. public TextureCube SkyCubeMapTexture
  236. {
  237. get
  238. {
  239. return skyCube.SkyCubeMapTexture;
  240. }
  241. }
  242. /// <summary>
  243. /// Create user interface renderer
  244. /// </summary>
  245. public UIRenderer()
  246. {
  247. background = new Texture("Background");
  248. buttons = new Texture("Buttons");
  249. headers = new Texture("Headers");
  250. #if XBOX360
  251. helpScreen = new Texture("HelpScreenXbox360");
  252. optionsScreen = new Texture("OptionsScreenXbox360");
  253. #else
  254. helpScreen = new Texture("HelpScreenWindows");
  255. optionsScreen = new Texture("OptionsScreenWindows");
  256. #endif
  257. mouseCursor = new Texture("MouseCursor");
  258. ingame = new Texture("Ingame");
  259. trophies[0] = new Texture("Pokal1");
  260. trophies[1] = new Texture("Pokal2");
  261. trophies[2] = new Texture("Pokal3");
  262. font = new TextureFont();
  263. postScreenMenuShader = new PostScreenMenu();
  264. postScreenGameShader = new PostScreenGlow();
  265. skyCube = new PreScreenSkyCubeMapping();
  266. lensFlare = new LensFlare(LensFlare.DefaultSunPos);
  267. BaseGame.LightDirection = LensFlare.DefaultLightPos;
  268. }
  269. /// <summary>
  270. /// Dispose
  271. /// </summary>
  272. public void Dispose()
  273. {
  274. Dispose(true);
  275. GC.SuppressFinalize(this);
  276. }
  277. /// <summary>
  278. /// Dispose
  279. /// </summary>
  280. /// <param name="disposing">Disposing</param>
  281. protected virtual void Dispose(bool disposing)
  282. {
  283. if (disposing)
  284. {
  285. if (background != null)
  286. background.Dispose();
  287. if (buttons != null)
  288. buttons.Dispose();
  289. if (headers != null)
  290. headers.Dispose();
  291. if (helpScreen != null)
  292. helpScreen.Dispose();
  293. if (optionsScreen != null)
  294. optionsScreen.Dispose();
  295. if (mouseCursor != null)
  296. mouseCursor.Dispose();
  297. if (font != null)
  298. font.Dispose();
  299. if (postScreenMenuShader != null)
  300. postScreenMenuShader.Dispose();
  301. if (postScreenGameShader != null)
  302. postScreenGameShader.Dispose();
  303. if (skyCube != null)
  304. skyCube.Dispose();
  305. if (lensFlare != null)
  306. lensFlare.Dispose();
  307. if (ingame != null)
  308. ingame.Dispose();
  309. }
  310. }
  311. /// <summary>
  312. /// Time fadeup modes
  313. /// </summary>
  314. public enum TimeFadeupMode
  315. {
  316. Plus,
  317. Minus,
  318. Normal,
  319. }
  320. class TimeFadeupText
  321. {
  322. public string text;
  323. public Color color;
  324. public float showTimeMs;
  325. public const float MaxShowTimeMs = 2250;
  326. public TimeFadeupText(string setText, Color setColor)
  327. {
  328. text = setText;
  329. color = setColor;
  330. showTimeMs = MaxShowTimeMs;
  331. }
  332. }
  333. List<TimeFadeupText> fadeupTexts = new List<TimeFadeupText>();
  334. /// <summary>
  335. /// Add time fadeup effect. Used in the game to show times, plus (green)
  336. /// means we took longer for this checkpoint, minus (green) means we did
  337. /// good.
  338. /// </summary>
  339. /// <param name="timeMilisec">Time</param>
  340. /// <param name="mode">Mode</param>
  341. public void AddTimeFadeupEffect(int timeMilliseconds, TimeFadeupMode mode)
  342. {
  343. string text =
  344. //min
  345. ((timeMilliseconds / 1000) / 60) + ":" +
  346. //sec
  347. ((timeMilliseconds / 1000) % 60).ToString("00") + "." +
  348. //ms
  349. ((timeMilliseconds / 10) % 100).ToString("00");
  350. Color col = Color.White;
  351. if (mode == TimeFadeupMode.Plus)
  352. {
  353. text = "+ " + text;
  354. col = Color.Red;
  355. }
  356. else if (mode == TimeFadeupMode.Minus)
  357. {
  358. text = "- " + text;
  359. col = Color.Green;
  360. }
  361. fadeupTexts.Add(new TimeFadeupText(text, col));
  362. }
  363. /// <summary>
  364. /// Render all time fadeup effects, move them up and fade them out.
  365. /// </summary>
  366. public void RenderTimeFadeupEffects()
  367. {
  368. for (int num = 0; num < fadeupTexts.Count; num++)
  369. {
  370. TimeFadeupText fadeupText = fadeupTexts[num];
  371. fadeupText.showTimeMs -= BaseGame.ElapsedTimeThisFrameInMilliseconds;
  372. if (fadeupText.showTimeMs < 0)
  373. {
  374. fadeupTexts.Remove(fadeupText);
  375. num--;
  376. }
  377. else
  378. {
  379. // Fade out
  380. float alpha = 1.0f;
  381. if (fadeupText.showTimeMs < 1500)
  382. alpha = fadeupText.showTimeMs / 1500.0f;
  383. // Move up
  384. float moveUpAmount =
  385. (TimeFadeupText.MaxShowTimeMs - fadeupText.showTimeMs) /
  386. TimeFadeupText.MaxShowTimeMs;
  387. // Calculate screen position
  388. TextureFont.WriteTextCentered(BaseGame.Width / 2,
  389. BaseGame.Height / 3 - (int)(moveUpAmount * BaseGame.Height / 3),
  390. fadeupText.text,
  391. ColorHelper.ApplyAlphaToColor(fadeupText.color, alpha),
  392. 2.25f);
  393. }
  394. }
  395. }
  396. /// <summary>
  397. /// Render game background
  398. /// </summary>
  399. public void RenderGameBackground()
  400. {
  401. // Show game background (sky and lensflare)
  402. skyCube.RenderSky();
  403. // Render lens flare on top of 3d stuff
  404. if (Track.disableLensFlareInTunnel == false)
  405. lensFlare.Render(Color.White);
  406. }
  407. private Vector3 oldCarForward = Vector3.Zero;
  408. private Vector3 oldCarUp = Vector3.Zero;
  409. private float carMenuTime = 0.0f;
  410. private Vector3 carPos = RacingGameManager.Player.CarPosition;
  411. private int randomCarNumber = RandomHelper.GetRandomInt(3);
  412. private Color randomCarColor = RandomHelper.RandomColor;
  413. /// <summary>
  414. /// Render menu track background
  415. /// </summary>
  416. public void RenderMenuTrackBackground()
  417. {
  418. // Only render track if we are not doing any 3d data on the screen
  419. if (RacingGameManager.InCarSelectionScreen == false)
  420. {
  421. RacingGameManager.Landscape.Render();
  422. RacingGameManager.CarModel.RenderCar(
  423. randomCarNumber,
  424. randomCarColor,
  425. false,
  426. RacingGameManager.Player.CarRenderMatrix);
  427. }
  428. }
  429. /// <summary>
  430. ///
  431. /// </summary>
  432. public void UpdateCarInMenu()
  433. {
  434. // Advance menu car preview time
  435. carMenuTime += BaseGame.ElapsedTimeThisFrameInMilliseconds / 1000.0f;
  436. if (carMenuTime > RacingGameManager.Landscape.BestReplay.LapTime)
  437. carMenuTime -= RacingGameManager.Landscape.BestReplay.LapTime;
  438. // Use data from replay
  439. Matrix carMatrix =
  440. RacingGameManager.Landscape.BestReplay.GetCarMatrixAtTime(
  441. carMenuTime);
  442. // Interpolate carPos a little
  443. carPos = carMatrix.Translation;
  444. // Set carPos for camera (else the car will drive away from us ^^)
  445. RacingGameManager.Player.SetCarPosition(
  446. carPos, carMatrix.Forward, carMatrix.Up);
  447. // Put camera behind car, but make it move smoothly
  448. Vector3 newCarForward = carMatrix.Forward;
  449. Vector3 newCarUp = carMatrix.Up;
  450. if (oldCarForward == Vector3.Zero)
  451. oldCarForward = newCarForward;
  452. if (oldCarUp == Vector3.Zero)
  453. oldCarUp = newCarUp;
  454. oldCarForward = oldCarForward * 0.95f + newCarForward * 0.05f;
  455. oldCarUp = oldCarUp * 0.95f + newCarUp * 0.05f;
  456. RacingGameManager.Player.SetCameraPosition(
  457. // Mix camera positions, interpolate slowly, much smoother camera!
  458. carPos + oldCarForward * 13 - oldCarUp * 1.3f);
  459. RacingGameManager.Player.Update();
  460. }
  461. /// <summary>
  462. /// Render menu background
  463. /// </summary>
  464. public void RenderMenuBackground()
  465. {
  466. BaseGame.UI.UpdateCarInMenu();
  467. // Render game background
  468. RenderGameBackground();
  469. // And show track
  470. RenderMenuTrackBackground();
  471. // Render background with transparency
  472. // The background itself should be rendered before this ^^
  473. background.RenderOnScreen(
  474. BaseGame.ResolutionRect, BackgroundGfxRect,
  475. ColorHelper.ApplyAlphaToColor(Color.White, 0.85f));
  476. // Show RacingGame logo bouncing with the music
  477. float bounceSize = 1.005f +
  478. (float)Math.Sin(BaseGame.TotalTime / 0.46f) * 0.045f *
  479. (float)Math.Cos(BaseGame.TotalTime / 0.285f);
  480. background.RenderOnScreen(
  481. BaseGame.CalcRectangleWithBounce(362, 36, 601, 218, bounceSize),
  482. RacingGameLogoGfxRect);
  483. }
  484. /// <summary>
  485. /// Render black bar
  486. /// </summary>
  487. /// <param name="yPos">Y position</param>
  488. /// <param name="height">Height</param>
  489. public void RenderBlackBar(int yPos, int height)
  490. {
  491. buttons.RenderOnScreen(
  492. BaseGame.CalcRectangle(0, yPos, 1024, height),
  493. BlackBarGfxRect,
  494. ColorHelper.ApplyAlphaToColor(Color.White, 0.85f));
  495. }
  496. public bool backButtonPressed = false;
  497. /// <summary>
  498. /// Render bottom buttons (select, back, etc.)
  499. /// </summary>
  500. /// <param name="onlyBack">Only back</param>
  501. public bool RenderBottomButtons(bool onlyBack)
  502. {
  503. Rectangle bButtonRect = BaseGame.CalcRectangleCenteredWithGivenHeight(
  504. 0, 587, 48, BottomButtonBButtonGfxRect);
  505. bButtonRect.X = BaseGame.Width - bButtonRect.Width - BaseGame.XToRes(25 + 25);
  506. bool overBButton = Input.MouseInBox(bButtonRect);
  507. int xAdd = BaseGame.XToRes(16);
  508. int yAdd = BaseGame.YToRes(9);
  509. if (overBButton)
  510. bButtonRect = new Rectangle(
  511. bButtonRect.X - xAdd / 2, bButtonRect.Y - yAdd / 2,
  512. bButtonRect.Width + xAdd, bButtonRect.Height + yAdd);
  513. buttons.RenderOnScreen(bButtonRect, BottomButtonBButtonGfxRect);
  514. // Is mouse over button?
  515. if (overBButton)
  516. buttons.RenderOnScreen(bButtonRect, BottomButtonSelectionGfxRect);
  517. // Store value if back button was pressed;
  518. backButtonPressed = overBButton && Input.MouseLeftButtonJustPressed;
  519. // Don't show button a if there is nothing to select here
  520. if (onlyBack)
  521. return false;
  522. Rectangle aButtonRect = BaseGame.CalcRectangleCenteredWithGivenHeight(
  523. 0, 587, 48, BottomButtonAButtonGfxRect);
  524. aButtonRect.X = BaseGame.Width -
  525. aButtonRect.Width * 2 - BaseGame.XToRes(55 + 25);
  526. bool overAButton = Input.MouseInBox(aButtonRect);
  527. if (overAButton)
  528. aButtonRect = new Rectangle(
  529. aButtonRect.X - xAdd / 2, aButtonRect.Y - yAdd / 2,
  530. aButtonRect.Width + xAdd, aButtonRect.Height + yAdd);
  531. buttons.RenderOnScreen(aButtonRect, BottomButtonAButtonGfxRect);
  532. // Is mouse over button?
  533. if (overAButton)
  534. {
  535. buttons.RenderOnScreen(aButtonRect, BottomButtonSelectionGfxRect);
  536. if (Input.MouseLeftButtonJustPressed)
  537. return true;
  538. }
  539. return false;
  540. }
  541. /// <summary>
  542. /// Render game user interface
  543. /// </summary>
  544. /// <param name="currentGameTime">Current game time</param>
  545. /// <param name="bestLapTime">Best lap time</param>
  546. /// <param name="lapNumber">Lap number</param>
  547. /// <param name="speed">Speed</param>
  548. /// <param name="gear">Gear</param>
  549. /// <param name="trackName">Track name</param>
  550. /// <param name="top5LapTimes">Top 5 lap times</param>
  551. public void RenderGameUI(int currentGameTime, int bestLapTime,
  552. int lapNumber, float speed, int gear, float acceleration,
  553. string trackName, int[] top5LapTimes)
  554. {
  555. if (top5LapTimes == null)
  556. throw new ArgumentNullException("top5LapTimes");
  557. Color baseUIColor = Color.White;//ColorHelper.HalfAlpha;
  558. // If game is over, set speed, gear and acceleration to 0
  559. if (RacingGameManager.Player.GameOver)
  560. {
  561. speed = 0;
  562. gear = 1;
  563. acceleration = 0;
  564. }
  565. // More distance to the screen borders on the Xbox 360 to fit better into
  566. // the save region. Calculate all rectangles for each platform,
  567. // then they will be used the same way on both platforms.
  568. #if XBOX360
  569. // Draw all boxes and background stuff
  570. Rectangle lapsRect = BaseGame.CalcRectangle1600(
  571. 60, 46, LapsGfxRect.Width, LapsGfxRect.Height);
  572. ingame.RenderOnScreen(lapsRect, LapsGfxRect, baseUIColor);
  573. Rectangle timesRect = BaseGame.CalcRectangle1600(
  574. 60, 46, CurrentAndBestGfxRect.Width, CurrentAndBestGfxRect.Height);
  575. timesRect.Y = BaseGame.Height-timesRect.Bottom;
  576. ingame.RenderOnScreen(timesRect, CurrentAndBestGfxRect, baseUIColor);
  577. Rectangle trackNameRect = BaseGame.CalcRectangle1600(
  578. 60, 46, TrackNameGfxRect.Width, TrackNameGfxRect.Height);
  579. trackNameRect.X = BaseGame.Width-trackNameRect.Right;
  580. ingame.RenderOnScreen(trackNameRect, TrackNameGfxRect, baseUIColor);
  581. Rectangle top5Rect1 = BaseGame.CalcRectangle1600(
  582. 60, 4, Best5GfxRect.Width, Best5GfxRect.Height);
  583. top5Rect1.X = trackNameRect.X;
  584. int top5Distance = top5Rect1.Y;
  585. top5Rect1.Y += trackNameRect.Bottom;
  586. ingame.RenderOnScreen(top5Rect1, Best5GfxRect, baseUIColor);
  587. Rectangle top5Rect2 = new Rectangle(top5Rect1.X,
  588. top5Rect1.Bottom+top5Distance, top5Rect1.Width, top5Rect1.Height);
  589. ingame.RenderOnScreen(top5Rect2, Best5GfxRect, baseUIColor);
  590. Rectangle top5Rect3 = new Rectangle(top5Rect1.X,
  591. top5Rect2.Bottom+top5Distance, top5Rect1.Width, top5Rect1.Height);
  592. ingame.RenderOnScreen(top5Rect3, Best5GfxRect, baseUIColor);
  593. Rectangle top5Rect4 = new Rectangle(top5Rect1.X,
  594. top5Rect3.Bottom+top5Distance, top5Rect1.Width, top5Rect1.Height);
  595. ingame.RenderOnScreen(top5Rect4, Best5GfxRect, baseUIColor);
  596. Rectangle top5Rect5 = new Rectangle(top5Rect1.X,
  597. top5Rect4.Bottom+top5Distance, top5Rect1.Width, top5Rect1.Height);
  598. ingame.RenderOnScreen(top5Rect5, Best5GfxRect, baseUIColor);
  599. Rectangle tachoRect = BaseGame.CalcRectangle1600(
  600. 60, 46, TachoGfxRect.Width, TachoGfxRect.Height);
  601. tachoRect.X = BaseGame.Width-tachoRect.Right;
  602. tachoRect.Y = BaseGame.Height-tachoRect.Bottom;
  603. #else
  604. // Draw all boxes and background stuff
  605. Rectangle lapsRect = BaseGame.CalcRectangle1600(
  606. 10, 10, LapsGfxRect.Width, LapsGfxRect.Height);
  607. ingame.RenderOnScreen(lapsRect, LapsGfxRect, baseUIColor);
  608. Rectangle timesRect = BaseGame.CalcRectangle1600(
  609. 10, 10, CurrentAndBestGfxRect.Width, CurrentAndBestGfxRect.Height);
  610. timesRect.Y = BaseGame.Height - timesRect.Bottom;
  611. ingame.RenderOnScreen(timesRect, CurrentAndBestGfxRect, baseUIColor);
  612. Rectangle trackNameRect = BaseGame.CalcRectangle1600(
  613. 10, 10, TrackNameGfxRect.Width, TrackNameGfxRect.Height);
  614. trackNameRect.X = BaseGame.Width - trackNameRect.Right;
  615. ingame.RenderOnScreen(trackNameRect, TrackNameGfxRect, baseUIColor);
  616. Rectangle top5Rect1 = BaseGame.CalcRectangle1600(
  617. 10, 4, Best5GfxRect.Width, Best5GfxRect.Height);
  618. top5Rect1.X = trackNameRect.X;
  619. int top5Distance = top5Rect1.Y;
  620. top5Rect1.Y += trackNameRect.Bottom;
  621. ingame.RenderOnScreen(top5Rect1, Best5GfxRect, baseUIColor);
  622. Rectangle top5Rect2 = new Rectangle(top5Rect1.X,
  623. top5Rect1.Bottom + top5Distance, top5Rect1.Width, top5Rect1.Height);
  624. ingame.RenderOnScreen(top5Rect2, Best5GfxRect, baseUIColor);
  625. Rectangle top5Rect3 = new Rectangle(top5Rect1.X,
  626. top5Rect2.Bottom + top5Distance, top5Rect1.Width, top5Rect1.Height);
  627. ingame.RenderOnScreen(top5Rect3, Best5GfxRect, baseUIColor);
  628. Rectangle top5Rect4 = new Rectangle(top5Rect1.X,
  629. top5Rect3.Bottom + top5Distance, top5Rect1.Width, top5Rect1.Height);
  630. ingame.RenderOnScreen(top5Rect4, Best5GfxRect, baseUIColor);
  631. Rectangle top5Rect5 = new Rectangle(top5Rect1.X,
  632. top5Rect4.Bottom + top5Distance, top5Rect1.Width, top5Rect1.Height);
  633. ingame.RenderOnScreen(top5Rect5, Best5GfxRect, baseUIColor);
  634. Rectangle tachoRect = BaseGame.CalcRectangle1600(
  635. 10, 10, TachoGfxRect.Width, TachoGfxRect.Height);
  636. tachoRect.X = BaseGame.Width - tachoRect.Right;
  637. tachoRect.Y = BaseGame.Height - tachoRect.Bottom;
  638. #endif
  639. // Rest can stay the same because we use the rectangles from now on
  640. ingame.RenderOnScreen(tachoRect, TachoGfxRect, baseUIColor);
  641. // Ok, now add the numbers, text and speed values
  642. TextureFontBigNumbers.WriteNumber(
  643. lapsRect.X + BaseGame.XToRes1600(15),
  644. lapsRect.Y + BaseGame.YToRes1200(12),
  645. lapNumber);
  646. // Current and best game times
  647. Color highlightColor = new Color(255, 185, 80);
  648. int blockHeight = BaseGame.YToRes1200(74);
  649. TextureFont.WriteGameTime(
  650. timesRect.X + BaseGame.XToRes1600(154),
  651. timesRect.Y + blockHeight / 2 - TextureFont.Height / 2,
  652. currentGameTime,
  653. highlightColor);
  654. TextureFont.WriteGameTime(
  655. timesRect.X + BaseGame.XToRes1600(154),
  656. timesRect.Y + timesRect.Height / 2 + blockHeight / 2 -
  657. TextureFont.Height / 2,
  658. bestLapTime,
  659. Color.White);
  660. // Track name
  661. TextureFont.WriteTextCentered(
  662. trackNameRect.X + trackNameRect.Width / 2,
  663. trackNameRect.Y + blockHeight / 2,
  664. trackName);
  665. // Top 5
  666. // Possible improvement: Show currentRank here (insert us)
  667. Color rankColor =
  668. bestLapTime == top5LapTimes[0] ?
  669. highlightColor : Color.White;
  670. TextureFont.WriteTextCentered(
  671. top5Rect1.X + BaseGame.XToRes(32) / 2,
  672. top5Rect1.Y + blockHeight / 2,
  673. "1.", rankColor, 1.0f);
  674. TextureFont.WriteGameTime(
  675. top5Rect1.X + BaseGame.XToRes(35 + 15),
  676. top5Rect1.Y + blockHeight / 2 - TextureFont.Height / 2,
  677. top5LapTimes[0], rankColor);
  678. rankColor =
  679. bestLapTime == top5LapTimes[1] ?
  680. highlightColor : Color.White;
  681. TextureFont.WriteTextCentered(
  682. top5Rect2.X + BaseGame.XToRes(32) / 2,
  683. top5Rect2.Y + blockHeight / 2,
  684. "2.", rankColor, 1.0f);
  685. TextureFont.WriteGameTime(
  686. top5Rect2.X + BaseGame.XToRes(35 + 15),
  687. top5Rect2.Y + blockHeight / 2 - TextureFont.Height / 2,
  688. top5LapTimes[1], rankColor);
  689. rankColor =
  690. bestLapTime == top5LapTimes[2] ?
  691. highlightColor : Color.White;
  692. TextureFont.WriteTextCentered(
  693. top5Rect3.X + BaseGame.XToRes(32) / 2,
  694. top5Rect3.Y + blockHeight / 2,
  695. "3.", rankColor, 1.0f);
  696. TextureFont.WriteGameTime(
  697. top5Rect3.X + BaseGame.XToRes(35 + 15),
  698. top5Rect3.Y + blockHeight / 2 - TextureFont.Height / 2,
  699. top5LapTimes[2], rankColor);
  700. rankColor =
  701. bestLapTime == top5LapTimes[3] ?
  702. highlightColor : Color.White;
  703. TextureFont.WriteTextCentered(
  704. top5Rect4.X + BaseGame.XToRes(32) / 2,
  705. top5Rect4.Y + blockHeight / 2,
  706. "4.", rankColor, 1.0f);
  707. TextureFont.WriteGameTime(
  708. top5Rect4.X + BaseGame.XToRes(35 + 15),
  709. top5Rect4.Y + blockHeight / 2 - TextureFont.Height / 2,
  710. top5LapTimes[3], rankColor);
  711. rankColor =
  712. bestLapTime == top5LapTimes[4] ?
  713. highlightColor : Color.White;
  714. TextureFont.WriteTextCentered(
  715. top5Rect5.X + BaseGame.XToRes(32) / 2,
  716. top5Rect5.Y + blockHeight / 2,
  717. "5.", rankColor, 1.0f);
  718. TextureFont.WriteGameTime(
  719. top5Rect5.X + BaseGame.XToRes(35 + 15),
  720. top5Rect5.Y + blockHeight / 2 - TextureFont.Height / 2,
  721. top5LapTimes[4], rankColor);
  722. // Acceleration
  723. Point tachoPoint = new Point(
  724. tachoRect.X +
  725. BaseGame.XToRes1600(194),
  726. tachoRect.Y +
  727. BaseGame.YToRes1200(194));
  728. //ingame.RenderOnScreenWithRotation(
  729. // tachoPoint, TachoArrowGfxRect, -acceleration*2);
  730. if (acceleration < 0)
  731. acceleration = 0;
  732. if (acceleration > 1)
  733. acceleration = 1;
  734. float rotation = -2.33f + acceleration * 2.5f;
  735. int tachoArrowWidth = BaseGame.XToRes1600(TachoArrowGfxRect.Width);
  736. int tachoArrowHeight = BaseGame.YToRes1200(TachoArrowGfxRect.Height);
  737. Vector2 rotationPoint = new Vector2(
  738. TachoArrowGfxRect.Width / 2,
  739. TachoArrowGfxRect.Height - 13);
  740. ingame.RenderOnScreenWithRotation(
  741. new Rectangle(tachoPoint.X, tachoPoint.Y,
  742. tachoArrowWidth, tachoArrowHeight),
  743. TachoArrowGfxRect,
  744. rotation, rotationPoint);
  745. // Speed in mph
  746. TextureFontBigNumbers.WriteNumber(
  747. tachoRect.X + BaseGame.XToRes1600(TachoMphGfxRect.X),
  748. tachoRect.Y + BaseGame.YToRes1200(TachoMphGfxRect.Y),
  749. TachoMphGfxRect.Height,
  750. (int)Math.Round(speed));
  751. // Gear
  752. TextureFontBigNumbers.WriteNumber(
  753. tachoRect.X + BaseGame.XToRes1600(TachoGearGfxRect.X),
  754. tachoRect.Y + BaseGame.YToRes1200(TachoGearGfxRect.Y),
  755. TachoGearGfxRect.Height,
  756. Math.Min(5, gear));
  757. }
  758. bool showFps =
  759. #if DEBUG
  760. true;
  761. #else
  762. false;
  763. #endif
  764. /// <summary>
  765. /// Render all UI elements at the end of the frame, will also
  766. /// render the mouse cursor if we got a mouse attached.
  767. ///
  768. /// Render all ui elements that we collected this frame.
  769. /// Flush user interface graphics, this are mainly all
  770. /// Texture.RenderOnScreen calls we made this frame so far.
  771. /// Used in UIRenderer.RenderTextsAndMouseCursor, but can also be
  772. /// called to force rendering UI at a specific point in the code.
  773. /// </summary>
  774. public static void Render(LineManager2D lineManager2D)
  775. {
  776. if (lineManager2D == null)
  777. throw new ArgumentNullException("lineManager2D");
  778. // Disable depth buffer for UI
  779. BaseGame.Device.DepthStencilState = DepthStencilState.None;
  780. // Draw all sprites
  781. Texture.additiveSprite.End();
  782. Texture.alphaSprite.End();
  783. //SpriteHelper.DrawAllSprites();
  784. // Render all 2d lines
  785. lineManager2D.Render();
  786. // Restore depth buffer?
  787. BaseGame.Device.DepthStencilState = DepthStencilState.Default;
  788. }
  789. /// <summary>
  790. /// Render texts and mouse cursor, which is done at the very end
  791. /// of our render loop.
  792. /// </summary>
  793. public void RenderTextsAndMouseCursor()
  794. {
  795. #if DEBUG
  796. // Show fps
  797. if (Input.KeyboardF1JustPressed ||
  798. // Also allow toggeling with gamepad
  799. (Input.GamePad.Buttons.LeftShoulder == ButtonState.Pressed &&
  800. Input.GamePadYJustPressed))
  801. showFps = !showFps;
  802. #endif
  803. if (showFps)
  804. TextureFont.WriteText(
  805. BaseGame.XToRes(200), BaseGame.YToRes(26),
  806. "Fps: " + BaseGame.Fps + " " +
  807. BaseGame.Width + "x" + BaseGame.Height);
  808. // Render font texts
  809. RenderTimeFadeupEffects();
  810. font.WriteAll();
  811. // Render mouse
  812. // For the xbox, there is no mouse support, don't show cursor!
  813. if (Input.MouseDetected &&
  814. // Also don't show cursor in game!
  815. RacingGameManager.ShowMouseCursor)
  816. {
  817. Texture.alphaSprite.Begin(SpriteSortMode.Deferred, BlendState.Additive);
  818. Texture.additiveSprite.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
  819. // Use our SpriteHelper logic to render the mouse cursor now!
  820. mouseCursor.RenderOnScreen(Input.MousePos);
  821. Texture.additiveSprite.End();
  822. Texture.alphaSprite.End();
  823. //SpriteHelper.DrawAllSprites();
  824. }
  825. }
  826. }
  827. }