TextureFont.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. //-----------------------------------------------------------------------------
  2. // TextureFont.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 System;
  10. using System.Collections.Generic;
  11. using System.Text;
  12. using RacingGame.Helpers;
  13. namespace RacingGame.Graphics
  14. {
  15. /// <summary>
  16. /// Texture font for our game, uses GameFont.png.
  17. /// If you want to know more details about creating bitmap fonts in XNA,
  18. /// how to generate the bitmaps and more details about using it, please
  19. /// check out the following links:
  20. /// http://blogs.msdn.com/garykac/archive/2006/08/30/728521.aspx
  21. /// http://blogs.msdn.com/garykac/articles/732007.aspx
  22. /// http://www.angelcode.com/products/bmfont/
  23. /// </summary>
  24. class TextureFont : IDisposable
  25. {
  26. /// <summary>
  27. /// Game font filename for our bitmap.
  28. /// </summary>
  29. const string GameFontFilename = "GameFont";
  30. /// <summary>
  31. /// Font height
  32. /// </summary>
  33. const int FontHeight = 36;
  34. /// <summary>
  35. /// Substract this value from the y postion when rendering.
  36. /// Most letters start below the CharRects, this fixes that issue.
  37. /// </summary>
  38. const int SubRenderHeight = 5;
  39. /// <summary>
  40. /// Char rectangles, goes from space (32) to ~ (126).
  41. /// Height is not used (always the same), instead we save the actual
  42. /// used width for rendering in the height value!
  43. /// This are the characters:
  44. /// !"#$%&'()*+,-./0123456789:;<=>?@
  45. /// ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`
  46. /// abcdefghijklmnopqrstuvwxyz{|}~
  47. /// Then we also got 4 extra rects for the XBox Buttons: A, B, X, Y
  48. /// </summary>
  49. static Rectangle[] CharRects = new Rectangle[126 - 32 + 1]
  50. {
  51. new Rectangle(0, 0, 1, 8), // space
  52. new Rectangle(1, 0, 11, 10),
  53. new Rectangle(12, 0, 14, 13),
  54. new Rectangle(26, 0, 20, 18),
  55. new Rectangle(46, 0, 20, 18),
  56. new Rectangle(66, 0, 24, 22),
  57. new Rectangle(90, 0, 25, 23),
  58. new Rectangle(115, 0, 8, 7),
  59. new Rectangle(124, 0, 10, 9),
  60. new Rectangle(136, 0, 10, 9),
  61. new Rectangle(146, 0, 20, 18),
  62. new Rectangle(166, 0, 20, 18),
  63. new Rectangle(186, 0, 10, 8),
  64. new Rectangle(196, 0, 10, 9),
  65. new Rectangle(207, 0, 10, 8),
  66. new Rectangle(217, 0, 18, 16),
  67. new Rectangle(235, 0, 20, 19),
  68. new Rectangle(0, 36, 20, 18), // 1
  69. new Rectangle(20, 36, 20, 18),
  70. new Rectangle(40, 36, 20, 18),
  71. new Rectangle(60, 36, 21, 19),
  72. new Rectangle(81, 36, 20, 18),
  73. new Rectangle(101, 36, 20, 18),
  74. new Rectangle(121, 36, 20, 18),
  75. new Rectangle(141, 36, 20, 18),
  76. new Rectangle(161, 36, 20, 18), // 9
  77. new Rectangle(181, 36, 10, 8),
  78. new Rectangle(191, 36, 10, 8),
  79. new Rectangle(201, 36, 20, 18),
  80. new Rectangle(221, 36, 20, 18),
  81. new Rectangle(0, 72, 20, 18), // >
  82. new Rectangle(20, 72, 19, 17),
  83. new Rectangle(39, 72, 26, 24),
  84. new Rectangle(65, 72, 22, 20),
  85. new Rectangle(87, 72, 22, 20),
  86. new Rectangle(109, 72, 22, 20),
  87. new Rectangle(131, 72, 23, 21),
  88. new Rectangle(154, 72, 20, 18),
  89. new Rectangle(174, 72, 19, 17),
  90. new Rectangle(193, 72, 23, 21),
  91. new Rectangle(216, 72, 23, 21),
  92. new Rectangle(239, 72, 11, 10),
  93. new Rectangle(0, 108, 15, 13), // J
  94. new Rectangle(15, 108, 22, 20),
  95. new Rectangle(37, 108, 19, 17),
  96. new Rectangle(56, 108, 29, 26),
  97. new Rectangle(85, 108, 23, 21),
  98. new Rectangle(108, 108, 24, 22), // O
  99. new Rectangle(132, 108, 22, 20),
  100. new Rectangle(154, 108, 24, 22),
  101. new Rectangle(178, 108, 24, 22),
  102. new Rectangle(202, 108, 21, 19),
  103. new Rectangle(223, 108, 17, 15), // T
  104. new Rectangle(0, 144, 22, 20), // U
  105. new Rectangle(22, 144, 22, 20),
  106. new Rectangle(44, 144, 30, 28),
  107. new Rectangle(74, 144, 22, 20),
  108. new Rectangle(96, 144, 20, 18),
  109. new Rectangle(116, 144, 20, 18),
  110. new Rectangle(136, 144, 10, 9),
  111. new Rectangle(146, 144, 18, 16),
  112. new Rectangle(167, 144, 10, 9),
  113. new Rectangle(177, 144, 17, 16),
  114. new Rectangle(194, 144, 17, 16),
  115. new Rectangle(211, 144, 17, 16),
  116. new Rectangle(228, 144, 20, 18),
  117. new Rectangle(0, 180, 20, 18), // b
  118. new Rectangle(20, 180, 18, 16),
  119. new Rectangle(38, 180, 20, 18),
  120. new Rectangle(58, 180, 20, 18), // e
  121. new Rectangle(79, 180, 14, 12), // f
  122. new Rectangle(93, 180, 20, 18), // g
  123. new Rectangle(114, 180, 19, 18), // h
  124. new Rectangle(133, 180, 11, 10),
  125. new Rectangle(145, 180, 11, 10), // j
  126. new Rectangle(156, 180, 20, 18),
  127. new Rectangle(176, 180, 11, 9),
  128. new Rectangle(187, 180, 29, 27),
  129. new Rectangle(216, 180, 20, 18),
  130. new Rectangle(236, 180, 20, 19),
  131. new Rectangle(0, 216, 20, 18), // p
  132. new Rectangle(20, 216, 20, 18),
  133. new Rectangle(40, 216, 13, 12), // r
  134. new Rectangle(53, 216, 17, 16),
  135. new Rectangle(70, 216, 14, 11), // t
  136. new Rectangle(84, 216, 19, 18),
  137. new Rectangle(104, 216, 17, 16),
  138. new Rectangle(122, 216, 25, 23),
  139. new Rectangle(148, 216, 19, 17),
  140. new Rectangle(168, 216, 18, 16),
  141. new Rectangle(186, 216, 16, 15),
  142. new Rectangle(203, 216, 10, 9),
  143. new Rectangle(214, 216, 12, 11), // |
  144. new Rectangle(227, 216, 10, 9),
  145. new Rectangle(237, 216, 18, 17),
  146. };
  147. /// <summary>
  148. /// Font texture
  149. /// </summary>
  150. Texture fontTexture;
  151. /// <summary>
  152. /// Font sprite
  153. /// </summary>
  154. SpriteBatch fontSprite;
  155. /// <summary>
  156. /// Height
  157. /// </summary>
  158. /// <returns>Int</returns>
  159. public static int Height
  160. {
  161. get
  162. {
  163. return BaseGame.YToRes1050(FontHeight - SubRenderHeight);
  164. }
  165. }
  166. /// <summary>
  167. /// Create texture font
  168. /// </summary>
  169. public TextureFont()
  170. {
  171. fontTexture = new Texture(GameFontFilename);
  172. fontSprite = new SpriteBatch(BaseGame.Device);
  173. }
  174. /// <summary>
  175. /// Dispose
  176. /// </summary>
  177. public void Dispose()
  178. {
  179. Dispose(true);
  180. GC.SuppressFinalize(this);
  181. }
  182. /// <summary>
  183. /// Dispose
  184. /// </summary>
  185. /// <param name="disposing">Disposing</param>
  186. protected virtual void Dispose(bool disposing)
  187. {
  188. if (disposing)
  189. {
  190. if (fontTexture != null)
  191. fontTexture.Dispose();
  192. if (fontSprite != null)
  193. fontSprite.Dispose();
  194. }
  195. }
  196. /// <summary>
  197. /// Get the text width of a given text.
  198. /// </summary>
  199. /// <param name="text">Text</param>
  200. /// <returns>Width (in pixels) of the text</returns>
  201. public static int GetTextWidth(string text)
  202. {
  203. int width = 0;
  204. //foreach (char c in text)
  205. char[] chars = text.ToCharArray();
  206. for (int num = 0; num < chars.Length; num++)
  207. {
  208. int charNum = (int)chars[num];
  209. if (charNum >= 32 &&
  210. charNum - 32 < CharRects.Length)
  211. width += BaseGame.XToRes1400(CharRects[charNum - 32].Height);
  212. }
  213. return width;
  214. }
  215. /// <summary>
  216. /// TextureFont to render
  217. /// </summary>
  218. internal class FontToRender
  219. {
  220. /// <summary>
  221. /// X and y position
  222. /// </summary>
  223. public int x, y;
  224. /// <summary>
  225. /// Text
  226. /// </summary>
  227. public string text;
  228. /// <summary>
  229. /// Color
  230. /// </summary>
  231. public Color color;
  232. /// <summary>
  233. /// Scale, usually just 1
  234. /// </summary>
  235. public float scale;
  236. /// <summary>
  237. /// Create font to render
  238. /// </summary>
  239. /// <param name="setX">Set x</param>
  240. /// <param name="setY">Set y</param>
  241. /// <param name="setText">Set text</param>
  242. /// <param name="setColor">Set color</param>
  243. public FontToRender(int setX, int setY, string setText, Color setColor)
  244. {
  245. x = setX;
  246. y = setY;
  247. text = setText;
  248. color = setColor;
  249. scale = 1.0f;
  250. }
  251. /// <summary>
  252. /// Create font to render
  253. /// </summary>
  254. /// <param name="setX">Set x</param>
  255. /// <param name="setY">Set y</param>
  256. /// <param name="setText">Set text</param>
  257. /// <param name="setColor">Set color</param>
  258. public FontToRender(int setX, int setY, string setText, Color setColor,
  259. float setScale)
  260. {
  261. x = setX;
  262. y = setY;
  263. text = setText;
  264. color = setColor;
  265. scale = setScale;
  266. }
  267. }
  268. /// <summary>
  269. /// Remember font texts to render to render them all at once
  270. /// in our Render method (beween rest of the ui and the mouse cursor).
  271. /// </summary>
  272. static List<FontToRender> remTexts = new List<FontToRender>();
  273. /// <summary>
  274. /// Write the given text at the specified position.
  275. /// </summary>
  276. /// <param name="x">X</param>
  277. /// <param name="y">Y</param>
  278. /// <param name="text">Text</param>
  279. /// <param name="color">Color</param>
  280. public static void WriteText(int x, int y, string text, Color color)
  281. {
  282. remTexts.Add(new FontToRender(x, y, text, color));
  283. }
  284. /// <summary>
  285. /// Write
  286. /// </summary>
  287. /// <param name="x">X</param>
  288. /// <param name="y">Y</param>
  289. /// <param name="text">Text</param>
  290. public static void WriteText(int x, int y, string text)
  291. {
  292. remTexts.Add(new FontToRender(x, y, text, Color.White));
  293. }
  294. /// <summary>
  295. /// Write text centered
  296. /// </summary>
  297. /// <param name="x">X</param>
  298. /// <param name="y">Y</param>
  299. /// <param name="text">Text</param>
  300. public static void WriteTextCentered(int x, int y, string text)
  301. {
  302. WriteText(x - GetTextWidth(text) / 2, y - Height / 2, text);
  303. }
  304. /// <summary>
  305. /// Write text centered with scale factor
  306. /// </summary>
  307. /// <param name="x">X</param>
  308. /// <param name="y">Y</param>
  309. /// <param name="text">Text</param>
  310. /// <param name="color">Color</param>
  311. public static void WriteTextCentered(int x, int y, string text,
  312. Color color, float scale)
  313. {
  314. int width = TextureFont.GetTextWidth(text);
  315. remTexts.Add(new FontToRender(
  316. x - (int)Math.Round(width * scale / 2),
  317. y - (int)Math.Round(TextureFont.Height * scale / 2),
  318. text, color, scale));
  319. }
  320. /// <summary>
  321. /// Write game time
  322. /// </summary>
  323. /// <param name="x">X</param>
  324. /// <param name="y">Y</param>
  325. /// <param name="timeMilliseconds">Time Milliseconds</param>
  326. /// <param name="col">Color</param>
  327. public static void WriteGameTime(int x, int y, int timeMilliseconds,
  328. Color col)
  329. {
  330. WriteText(x, y,
  331. // negative?
  332. (timeMilliseconds < 0 ? "-" : "") +
  333. // Minutes
  334. ((Math.Abs(timeMilliseconds) / 1000) / 60) + ":" +
  335. // Seconds
  336. ((Math.Abs(timeMilliseconds) / 1000) % 60).ToString("00") + "." +
  337. // Milliseconds
  338. ((Math.Abs(timeMilliseconds) / 10) % 100).ToString("00"),
  339. col);
  340. }
  341. /// <summary>
  342. /// Write all
  343. /// Draws the added texts to the screen.
  344. /// </summary>
  345. public void WriteAll()
  346. {
  347. if (remTexts.Count == 0)
  348. return;
  349. // Start rendering
  350. fontSprite.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
  351. // Draw each character in the text
  352. //foreach (UIRenderer.FontToRender fontText in texts)
  353. for (int textNum = 0; textNum < remTexts.Count; textNum++)
  354. {
  355. FontToRender fontText = remTexts[textNum];
  356. int x = fontText.x;
  357. int y = fontText.y;
  358. Color color = fontText.color;
  359. //foreach (char c in fontText.text)
  360. char[] chars = fontText.text.ToCharArray();
  361. for (int num = 0; num < chars.Length; num++)
  362. {
  363. int charNum = (int)chars[num];
  364. if (charNum >= 32 &&
  365. charNum - 32 < CharRects.Length)
  366. {
  367. // Draw this char
  368. Rectangle rect = CharRects[charNum - 32];
  369. // Reduce height to prevent overlapping pixels
  370. rect.Y += 1;
  371. rect.Height = FontHeight;
  372. Rectangle destRect = new Rectangle(x,
  373. y - BaseGame.YToRes1050(SubRenderHeight),
  374. rect.Width, rect.Height);
  375. // Scale destRect (1600x1200 is the base size)
  376. destRect.Width = BaseGame.XToRes1400(
  377. (int)Math.Round(destRect.Width * fontText.scale));
  378. destRect.Height = BaseGame.YToRes1050(
  379. (int)Math.Round(destRect.Height * fontText.scale));
  380. // Since we want upscaling, we use the modified destRect
  381. fontSprite.Draw(fontTexture.XnaTexture, destRect, rect, color);
  382. // Increase x pos by width we use for this character
  383. int charWidth = CharRects[charNum - 32].Height;
  384. x += BaseGame.XToRes1400(
  385. (int)Math.Round(charWidth * fontText.scale));
  386. }
  387. }
  388. }
  389. // End rendering
  390. fontSprite.End();
  391. remTexts.Clear();
  392. }
  393. }
  394. }