Game1.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.Xna.Framework;
  5. using Microsoft.Xna.Framework.Audio;
  6. using Microsoft.Xna.Framework.Content;
  7. using Microsoft.Xna.Framework.Graphics;
  8. using Microsoft.Xna.Framework.Input;
  9. using Microsoft.Xna.Framework.Media;
  10. namespace Flood_Control
  11. {
  12. /// <summary>
  13. /// This is the main type for your game
  14. /// </summary>
  15. public class Game1 : Microsoft.Xna.Framework.Game
  16. {
  17. GraphicsDeviceManager graphics;
  18. SpriteBatch spriteBatch;
  19. Texture2D playingPieces;
  20. Texture2D backgroundScreen;
  21. Texture2D titleScreen;
  22. GameBoard gameBoard;
  23. SpriteFont pericles36Font;
  24. Vector2 scorePosition = new Vector2(605, 215);
  25. Vector2 gameBoardDisplayOrigin = new Vector2(70, 89);
  26. int playerScore = 0;
  27. enum GameStates { TitleScreen, Playing, GameOver };
  28. GameStates gameState = GameStates.TitleScreen;
  29. Rectangle EmptyPiece = new Rectangle(1, 247, 40, 40);
  30. const float MinTimeSinceLastInput = 0.25f;
  31. float timeSinceLastInput = 0.0f;
  32. Queue<ScoreZoom> ScoreZooms = new Queue<ScoreZoom>();
  33. Vector2 gameOverLocation = new Vector2(200, 260);
  34. float gameOverTimer;
  35. const float MaxFloodCounter = 100.0f;
  36. float floodCount = 0.0f;
  37. float timeSinceLastFloodIncrease = 0.0f;
  38. float timeBetweenFloodIncreases = 1.0f;
  39. float floodIncreaseAmount = 0.5f;
  40. const int MaxWaterHeight = 244;
  41. const int WaterWidth = 297;
  42. Vector2 waterOverlayStart = new Vector2(85, 245);
  43. Vector2 waterPosition = new Vector2(478, 338);
  44. int currentLevel = 0;
  45. int linesCompletedThisLevel = 0;
  46. const float floodAccelerationPerLevel = 0.5f;
  47. Vector2 levelTextPosition = new Vector2(512, 215);
  48. public Game1()
  49. {
  50. graphics = new GraphicsDeviceManager(this);
  51. Content.RootDirectory = "Content";
  52. }
  53. /// <summary>
  54. /// Allows the game to perform any initialization it needs to before starting to run.
  55. /// This is where it can query for any required services and load any non-graphic
  56. /// related content. Calling base.Initialize will enumerate through any components
  57. /// and initialize them as well.
  58. /// </summary>
  59. protected override void Initialize()
  60. {
  61. // TODO: Add your initialization logic here
  62. #if !___MOBILE___
  63. this.IsMouseVisible = true;
  64. #else
  65. this.IsFullScreen = true;
  66. #endif
  67. graphics.PreferredBackBufferWidth = 800;
  68. graphics.PreferredBackBufferHeight = 600;
  69. graphics.ApplyChanges();
  70. gameBoard = new GameBoard();
  71. base.Initialize();
  72. }
  73. /// <summary>
  74. /// LoadContent will be called once per game and is the place to load
  75. /// all of your content.
  76. /// </summary>
  77. protected override void LoadContent()
  78. {
  79. // Create a new SpriteBatch, which can be used to draw textures.
  80. spriteBatch = new SpriteBatch(GraphicsDevice);
  81. playingPieces = Content.Load<Texture2D>(@"Textures\Tile_Sheet");
  82. backgroundScreen = Content.Load<Texture2D>(@"Textures\Background");
  83. titleScreen = Content.Load<Texture2D>(@"Textures\TitleScreen");
  84. pericles36Font = Content.Load<SpriteFont>(@"Fonts\Pericles36");
  85. // TODO: use this.Content to load your game content here
  86. }
  87. /// <summary>
  88. /// UnloadContent will be called once per game and is the place to unload
  89. /// all content.
  90. /// </summary>
  91. protected override void UnloadContent()
  92. {
  93. // TODO: Unload any non ContentManager content here
  94. }
  95. private int DetermineScore(int SquareCount)
  96. {
  97. return (int)((Math.Pow((SquareCount / 5), 2) + SquareCount) * 10);
  98. }
  99. private void CheckScoringChain(List<Vector2> WaterChain)
  100. {
  101. if (WaterChain.Count > 0)
  102. {
  103. Vector2 LastPipe = WaterChain[WaterChain.Count - 1];
  104. if (LastPipe.X == GameBoard.GameBoardWidth - 1)
  105. {
  106. if (gameBoard.HasConnector(
  107. (int)LastPipe.X, (int)LastPipe.Y, "Right"))
  108. {
  109. playerScore += DetermineScore(WaterChain.Count);
  110. linesCompletedThisLevel++;
  111. floodCount = MathHelper.Clamp(floodCount -
  112. (DetermineScore(WaterChain.Count) / 10), 0.0f, 100.0f);
  113. ScoreZooms.Enqueue(new ScoreZoom("+" +
  114. DetermineScore(WaterChain.Count).ToString(),
  115. new Color(1.0f, 0.0f, 0.0f, 0.4f)));
  116. foreach (Vector2 ScoringSquare in WaterChain)
  117. {
  118. gameBoard.AddFadingPiece(
  119. (int)ScoringSquare.X,
  120. (int)ScoringSquare.Y,
  121. gameBoard.GetSquare(
  122. (int)ScoringSquare.X,
  123. (int)ScoringSquare.Y));
  124. gameBoard.SetSquare((int)ScoringSquare.X,
  125. (int)ScoringSquare.Y, "Empty");
  126. }
  127. if (linesCompletedThisLevel >= 10)
  128. {
  129. StartNewLevel();
  130. }
  131. }
  132. }
  133. }
  134. }
  135. private void HandleMouseInput(MouseState mouseState)
  136. {
  137. int x = ((mouseState.X -
  138. (int)gameBoardDisplayOrigin.X) / GamePiece.PieceWidth);
  139. int y = ((mouseState.Y -
  140. (int)gameBoardDisplayOrigin.Y) / GamePiece.PieceHeight);
  141. if ((x >= 0) && (x < GameBoard.GameBoardWidth) &&
  142. (y >= 0) && (y < GameBoard.GameBoardHeight))
  143. {
  144. if (mouseState.LeftButton == ButtonState.Pressed)
  145. {
  146. gameBoard.AddRotatingPiece(x, y,
  147. gameBoard.GetSquare(x, y), false);
  148. gameBoard.RotatePiece(x, y, false);
  149. timeSinceLastInput = 0.0f;
  150. }
  151. if (mouseState.RightButton == ButtonState.Pressed)
  152. {
  153. gameBoard.AddRotatingPiece(x, y,
  154. gameBoard.GetSquare(x, y), true);
  155. gameBoard.RotatePiece(x, y, true);
  156. timeSinceLastInput = 0.0f;
  157. }
  158. }
  159. }
  160. private void UpdateScoreZooms()
  161. {
  162. int dequeueCounter = 0;
  163. foreach (ScoreZoom zoom in ScoreZooms)
  164. {
  165. zoom.Update();
  166. if (zoom.IsCompleted)
  167. dequeueCounter++;
  168. }
  169. for (int d = 0; d < dequeueCounter; d++)
  170. ScoreZooms.Dequeue();
  171. }
  172. private void StartNewLevel()
  173. {
  174. currentLevel++;
  175. floodCount = 0.0f;
  176. linesCompletedThisLevel = 0;
  177. floodIncreaseAmount += floodAccelerationPerLevel;
  178. gameBoard.ClearBoard();
  179. gameBoard.GenerateNewPieces(false);
  180. }
  181. /// <summary>
  182. /// Allows the game to run logic such as updating the world,
  183. /// checking for collisions, gathering input, and playing audio.
  184. /// </summary>
  185. /// <param name="gameTime">Provides a snapshot of timing values.</param>
  186. protected override void Update(GameTime gameTime)
  187. {
  188. KeyboardState keyState = Keyboard.GetState();
  189. // Allows the game to exit
  190. if (keyState.IsKeyDown(Keys.Escape)
  191. || GamePad.GetState(PlayerIndex.One).Buttons.Back ==
  192. ButtonState.Pressed)
  193. this.Exit();
  194. // TODO: Add your update logic here
  195. switch (gameState)
  196. {
  197. case GameStates.TitleScreen:
  198. if (Keyboard.GetState().IsKeyDown(Keys.Space))
  199. {
  200. gameBoard.ClearBoard();
  201. gameBoard.GenerateNewPieces(false);
  202. playerScore = 0;
  203. currentLevel = 0;
  204. floodIncreaseAmount = 0.0f;
  205. StartNewLevel();
  206. gameState = GameStates.Playing;
  207. }
  208. break;
  209. case GameStates.Playing:
  210. timeSinceLastInput +=
  211. (float)gameTime.ElapsedGameTime.TotalSeconds;
  212. timeSinceLastFloodIncrease +=
  213. (float)gameTime.ElapsedGameTime.TotalSeconds;
  214. if (timeSinceLastFloodIncrease >= timeBetweenFloodIncreases)
  215. {
  216. floodCount += floodIncreaseAmount;
  217. timeSinceLastFloodIncrease = 0.0f;
  218. if (floodCount >= MaxFloodCounter)
  219. {
  220. gameOverTimer = 8.0f;
  221. gameState = GameStates.GameOver;
  222. }
  223. }
  224. if (gameBoard.ArePiecesAnimating())
  225. {
  226. gameBoard.UpdateAnimatedPieces();
  227. }
  228. else
  229. {
  230. gameBoard.ResetWater();
  231. for (int y = 0; y < GameBoard.GameBoardHeight; y++)
  232. {
  233. CheckScoringChain(gameBoard.GetWaterChain(y));
  234. }
  235. gameBoard.GenerateNewPieces(true);
  236. if (timeSinceLastInput >= MinTimeSinceLastInput)
  237. {
  238. HandleMouseInput(Mouse.GetState());
  239. }
  240. }
  241. UpdateScoreZooms();
  242. break;
  243. case GameStates.GameOver:
  244. gameOverTimer -= (float)gameTime.ElapsedGameTime.TotalSeconds;
  245. if (gameOverTimer <= 0)
  246. {
  247. gameState = GameStates.TitleScreen;
  248. }
  249. break;
  250. }
  251. base.Update(gameTime);
  252. }
  253. private void DrawEmptyPiece(int pixelX, int pixelY)
  254. {
  255. spriteBatch.Draw(
  256. playingPieces,
  257. new Rectangle(pixelX, pixelY,
  258. GamePiece.PieceWidth, GamePiece.PieceHeight),
  259. EmptyPiece,
  260. Color.White);
  261. }
  262. private void DrawStandardPiece(int x, int y,
  263. int pixelX, int pixelY)
  264. {
  265. spriteBatch.Draw(
  266. playingPieces, new Rectangle(pixelX, pixelY,
  267. GamePiece.PieceWidth, GamePiece.PieceHeight),
  268. gameBoard.GetSourceRect(x, y),
  269. Color.White);
  270. }
  271. private void DrawFallingPiece(int pixelX, int pixelY,
  272. string positionName)
  273. {
  274. spriteBatch.Draw(
  275. playingPieces,
  276. new Rectangle(pixelX, pixelY -
  277. gameBoard.fallingPieces[positionName].VerticalOffset,
  278. GamePiece.PieceWidth, GamePiece.PieceHeight),
  279. gameBoard.fallingPieces[positionName].GetSourceRect(),
  280. Color.White);
  281. }
  282. private void DrawFadingPiece(int pixelX, int pixelY,
  283. string positionName)
  284. {
  285. spriteBatch.Draw(
  286. playingPieces,
  287. new Rectangle(pixelX, pixelY,
  288. GamePiece.PieceWidth, GamePiece.PieceHeight),
  289. gameBoard.fadingPieces[positionName].GetSourceRect(),
  290. Color.White *
  291. gameBoard.fadingPieces[positionName].alphaLevel);
  292. }
  293. private void DrawRotatingPiece(int pixelX, int pixelY,
  294. string positionName)
  295. {
  296. spriteBatch.Draw(
  297. playingPieces,
  298. new Rectangle(pixelX + (GamePiece.PieceWidth / 2),
  299. pixelY + (GamePiece.PieceHeight / 2),
  300. GamePiece.PieceWidth,
  301. GamePiece.PieceHeight),
  302. gameBoard.rotatingPieces[positionName].GetSourceRect(),
  303. Color.White,
  304. gameBoard.rotatingPieces[positionName].RotationAmount,
  305. new Vector2(GamePiece.PieceWidth / 2,
  306. GamePiece.PieceHeight / 2),
  307. SpriteEffects.None, 0.0f);
  308. }
  309. /// <summary>
  310. /// This is called when the game should draw itself.
  311. /// </summary>
  312. /// <param name="gameTime">Provides a snapshot of timing values.</param>
  313. protected override void Draw(GameTime gameTime)
  314. {
  315. GraphicsDevice.Clear(Color.MonoGameOrange);
  316. // TODO: Add your drawing code here
  317. if (gameState == GameStates.TitleScreen)
  318. {
  319. spriteBatch.Begin();
  320. spriteBatch.Draw(titleScreen,
  321. new Rectangle(0, 0,
  322. this.Window.ClientBounds.Width,
  323. this.Window.ClientBounds.Height),
  324. Color.White);
  325. spriteBatch.End();
  326. }
  327. if ((gameState == GameStates.Playing) ||
  328. (gameState == GameStates.GameOver))
  329. {
  330. spriteBatch.Begin();
  331. spriteBatch.Draw(backgroundScreen,
  332. new Rectangle(0, 0,
  333. this.Window.ClientBounds.Width,
  334. this.Window.ClientBounds.Height),
  335. Color.White);
  336. for (int x = 0; x < GameBoard.GameBoardWidth; x++)
  337. for (int y = 0; y < GameBoard.GameBoardHeight; y++)
  338. {
  339. int pixelX = (int)gameBoardDisplayOrigin.X +
  340. (x * GamePiece.PieceWidth);
  341. int pixelY = (int)gameBoardDisplayOrigin.Y +
  342. (y * GamePiece.PieceHeight);
  343. DrawEmptyPiece(pixelX, pixelY);
  344. bool pieceDrawn = false;
  345. string positionName = x.ToString() + "_" + y.ToString();
  346. if (gameBoard.rotatingPieces.ContainsKey(positionName))
  347. {
  348. DrawRotatingPiece(pixelX, pixelY, positionName);
  349. pieceDrawn = true;
  350. }
  351. if (gameBoard.fadingPieces.ContainsKey(positionName))
  352. {
  353. DrawFadingPiece(pixelX, pixelY, positionName);
  354. pieceDrawn = true;
  355. }
  356. if (gameBoard.fallingPieces.ContainsKey(positionName))
  357. {
  358. DrawFallingPiece(pixelX, pixelY, positionName);
  359. pieceDrawn = true;
  360. }
  361. if (!pieceDrawn)
  362. {
  363. DrawStandardPiece(x, y, pixelX, pixelY);
  364. }
  365. }
  366. foreach (ScoreZoom zoom in ScoreZooms)
  367. {
  368. spriteBatch.DrawString(pericles36Font, zoom.Text,
  369. new Vector2(this.Window.ClientBounds.Width / 2,
  370. this.Window.ClientBounds.Height / 2),
  371. zoom.DrawColor, 0.0f,
  372. new Vector2(pericles36Font.MeasureString(zoom.Text).X / 2,
  373. pericles36Font.MeasureString(zoom.Text).Y / 2),
  374. zoom.Scale, SpriteEffects.None, 0.0f);
  375. }
  376. spriteBatch.DrawString(pericles36Font,
  377. playerScore.ToString(),
  378. scorePosition,
  379. Color.Black);
  380. spriteBatch.DrawString(pericles36Font,
  381. currentLevel.ToString(),
  382. levelTextPosition,
  383. Color.Black);
  384. int waterHeight = (int)(MaxWaterHeight * (floodCount / 100));
  385. spriteBatch.Draw(backgroundScreen,
  386. new Rectangle(
  387. (int)waterPosition.X,
  388. (int)waterPosition.Y + (MaxWaterHeight - waterHeight),
  389. WaterWidth,
  390. waterHeight),
  391. new Rectangle(
  392. (int)waterOverlayStart.X,
  393. (int)waterOverlayStart.Y + (MaxWaterHeight - waterHeight),
  394. WaterWidth,
  395. waterHeight),
  396. new Color(255, 255, 255, 180));
  397. spriteBatch.End();
  398. }
  399. if (gameState == GameStates.GameOver)
  400. {
  401. spriteBatch.Begin();
  402. spriteBatch.DrawString(pericles36Font,
  403. "G A M E O V E R!",
  404. gameOverLocation,
  405. Color.Yellow);
  406. spriteBatch.End();
  407. }
  408. base.Draw(gameTime);
  409. }
  410. }
  411. }