| 1 |
#region File Description |
| 2 |
//----------------------------------------------------------------------------- |
| 3 |
// GameplayScreen.cs |
| 4 |
// |
| 5 |
// Microsoft XNA Community Game Platform |
| 6 |
// Copyright (C) Microsoft Corporation. All rights reserved. |
| 7 |
//----------------------------------------------------------------------------- |
| 8 |
#endregion |
| 9 |
|
| 10 |
#region Using Statements |
| 11 |
using System; |
| 12 |
using System.Threading; |
| 13 |
using System.Linq; |
| 14 |
using System.Collections.Generic; |
| 15 |
using Microsoft.Xna.Framework; |
| 16 |
using Microsoft.Xna.Framework.Content; |
| 17 |
using Microsoft.Xna.Framework.Graphics; |
| 18 |
using Microsoft.Xna.Framework.Input; |
| 19 |
using Microsoft.Xna.Framework.Media; |
| 20 |
using Drawing; |
| 21 |
#endregion |
| 22 |
|
| 23 |
namespace MyXnaGame |
| 24 |
{ |
| 25 |
/// <summary> |
| 26 |
/// This screen implements the actual game logic. It is just a |
| 27 |
/// placeholder to get the idea across: you'll probably want to |
| 28 |
/// put some more interesting gameplay in here! |
| 29 |
/// </summary> |
| 30 |
class GameplayScreen : GameScreen |
| 31 |
{ |
| 32 |
public static GameStates gamestate; |
| 33 |
public Ball ball; |
| 34 |
public Bat rightBat; |
| 35 |
public Bat leftBat; |
| 36 |
private int resetTimer; |
| 37 |
private bool resetTimerInUse; |
| 38 |
private bool lastScored; |
| 39 |
private Input myInputClass; |
| 40 |
public HudContainer hudContainer = new HudContainer(); |
| 41 |
public SafeArea safeArea; |
| 42 |
public Vector2 safeTopLeft = Vector2.Zero; // (2.0f * (safeArea.dx), 1.5f * (safeArea.dy)); |
| 43 |
public ContentManager content; |
| 44 |
private SpriteFont gameFont; |
| 45 |
private SpriteFont hudFont; |
| 46 |
public SpriteFont arial; |
| 47 |
public int screenWidth = 1280; |
| 48 |
public int screenHeight = 720; |
| 49 |
private Texture2D backgroundTexture; |
| 50 |
public Song PlayingSong { get; private set; } |
| 51 |
Vector2 enemyPosition = new Vector2(100, 100); |
| 52 |
Random random = new Random(); |
| 53 |
float pauseAlpha; |
| 54 |
|
| 55 |
public enum GameStates |
| 56 |
{ |
| 57 |
Menu, |
| 58 |
Running, |
| 59 |
End |
| 60 |
} |
| 61 |
|
| 62 |
|
| 63 |
public GameplayScreen() |
| 64 |
{ |
| 65 |
safeArea = new SafeArea(); |
| 66 |
TransitionOnTime = TimeSpan.FromSeconds(1.5); |
| 67 |
TransitionOffTime = TimeSpan.FromSeconds(0.5); |
| 68 |
|
| 69 |
} |
| 70 |
|
| 71 |
|
| 72 |
// LOADCONTENT |
| 73 |
// |
| 74 |
// |
| 75 |
public override void LoadContent() |
| 76 |
{ |
| 77 |
if (content == null) |
| 78 |
content = new ContentManager(ScreenManager.Game.Services, "Content"); |
| 79 |
DrawingHelper.Initialize(ScreenManager.GraphicsDevice); |
| 80 |
safeArea.LoadGraphicsContent(ScreenManager.GraphicsDevice); |
| 81 |
gameFont = content.Load<SpriteFont>("gamefont"); |
| 82 |
arial = content.Load<SpriteFont>("Arial"); |
| 83 |
hudFont = content.Load<SpriteFont>("menufont"); |
| 84 |
hudContainer.LoadGraphicsContent(ScreenManager.GraphicsDevice, hudFont, safeArea); |
| 85 |
var hudInfo = new HudTextComponent("...Ninja Cats!", HudComponent.PresetPosition.BottomRight); |
| 86 |
hudContainer.Add(hudInfo); |
| 87 |
|
| 88 |
myInputClass = new Input(); |
| 89 |
PlayingSong = content.Load<Song>(@"sfx/boomer"); |
| 90 |
MediaPlayer.Play(PlayingSong); |
| 91 |
backgroundTexture = content.Load<Texture2D>(@"gfx/mm7Background"); |
| 92 |
|
| 93 |
ball = new Ball(content, new Vector2 (ScreenManager.GraphicsDevice.Viewport.Width, |
| 94 |
ScreenManager.GraphicsDevice.Viewport.Height)); |
| 95 |
rightBat = new Bat(content, new Vector2 (ScreenManager.GraphicsDevice.Viewport.Width, |
| 96 |
ScreenManager.GraphicsDevice.Viewport.Height), true); |
| 97 |
leftBat = new Bat(content, new Vector2(ScreenManager.GraphicsDevice.Viewport.Width, |
| 98 |
ScreenManager.GraphicsDevice.Viewport.Height), false); |
| 99 |
|
| 100 |
// A real game would probably have more content than this sample, so |
| 101 |
// it would take longer to load. We simulate that by delaying for a |
| 102 |
// while, giving you a chance to admire the beautiful loading screen. |
| 103 |
Thread.Sleep(1000); |
| 104 |
|
| 105 |
// once the load has finished, we use ResetElapsedTime to tell the game's |
| 106 |
// timing mechanism that we have just finished a very long frame, and that |
| 107 |
// it should not try to catch up. |
| 108 |
ScreenManager.Game.ResetElapsedTime(); |
| 109 |
} |
| 110 |
|
| 111 |
|
| 112 |
|
| 113 |
public override void UnloadContent() |
| 114 |
{ |
| 115 |
content.Unload(); |
| 116 |
} |
| 117 |
|
| 118 |
|
| 119 |
|
| 120 |
// UPDATE |
| 121 |
// |
| 122 |
// |
| 123 |
public override void Update(GameTime gameTime, bool otherScreenHasFocus, |
| 124 |
bool coveredByOtherScreen) |
| 125 |
{ |
| 126 |
base.Update(gameTime, otherScreenHasFocus, false); |
| 127 |
|
| 128 |
ball.UpdatePosition(); |
| 129 |
leftBat.UpdatePosition(ball); |
| 130 |
rightBat.UpdatePosition(ball); |
| 131 |
myInputClass.Update(); |
| 132 |
|
| 133 |
|
| 134 |
|
| 135 |
if (gamestate == GameStates.Running) |
| 136 |
{ |
| 137 |
if (leftBat.GetPoints() > 9) |
| 138 |
{ |
| 139 |
// menu.InfoText = "Left Player Wins"; |
| 140 |
gamestate = GameStates.End; |
| 141 |
} |
| 142 |
else if (rightBat.GetPoints() > 9) |
| 143 |
{ |
| 144 |
// menu.InfoText = "Right Player Wins"; |
| 145 |
gamestate = GameStates.End; |
| 146 |
if (resetTimerInUse) |
| 147 |
{ |
| 148 |
resetTimer++; |
| 149 |
ball.Stop(); |
| 150 |
} |
| 151 |
if (resetTimer == 120) |
| 152 |
{ |
| 153 |
resetTimerInUse = false; |
| 154 |
ball.Reset(lastScored); |
| 155 |
resetTimer = 0; |
| 156 |
} |
| 157 |
|
| 158 |
if (!resetTimerInUse) |
| 159 |
{ |
| 160 |
if (ball.GetPosition().X > screenWidth) |
| 161 |
{ |
| 162 |
resetTimerInUse = true; |
| 163 |
lastScored = true; |
| 164 |
leftBat.IncrementPoints(); |
| 165 |
} |
| 166 |
else if (ball.GetPosition().X < 0) |
| 167 |
{ |
| 168 |
resetTimerInUse = true; |
| 169 |
lastScored = false; |
| 170 |
rightBat.IncrementPoints(); |
| 171 |
} |
| 172 |
} |
| 173 |
|
| 174 |
|
| 175 |
// Gradually fade in or out depending on whether we are covered by the pause screen. |
| 176 |
if (coveredByOtherScreen) |
| 177 |
pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1); |
| 178 |
else |
| 179 |
pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0); |
| 180 |
} |
| 181 |
} |
| 182 |
} |
| 183 |
|
| 184 |
|
| 185 |
private int CheckHitLocation(Bat bat) |
| 186 |
{ |
| 187 |
int block = 0; |
| 188 |
if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 20) block = 1; |
| 189 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 2) block = 2; |
| 190 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 3) block = 3; |
| 191 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 4) block = 4; |
| 192 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 5) block = 5; |
| 193 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 6) block = 6; |
| 194 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 7) block = 7; |
| 195 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 8) block = 8; |
| 196 |
else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 20 * 19) block = 9; |
| 197 |
else block = 10; |
| 198 |
return block; |
| 199 |
} |
| 200 |
|
| 201 |
|
| 202 |
|
| 203 |
/// <summary> |
| 204 |
/// Lets the game respond to player input. Unlike the Update method, |
| 205 |
/// this will only be called when the gameplay screen is active. |
| 206 |
/// </summary> |
| 207 |
public override void HandleInput(InputState input) //, GameTime gameTime) |
| 208 |
{ |
| 209 |
if (input == null) |
| 210 |
throw new ArgumentNullException("input"); |
| 211 |
myInputClass.Update(); // Updates myInputClass, instead of the default one. |
| 212 |
|
| 213 |
// Look up inputs for the active player profile. |
| 214 |
int playerIndex = (int)ControllingPlayer.Value; |
| 215 |
|
| 216 |
KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex]; |
| 217 |
GamePadState gamePadState = input.CurrentGamePadStates[playerIndex]; |
| 218 |
|
| 219 |
// The game pauses either if the user presses the pause button, or if |
| 220 |
// they unplug the active gamepad. This requires us to keep track of |
| 221 |
// whether a gamepad was ever plugged in, because we don't want to pause |
| 222 |
// on PC if they are playing with a keyboard and have no gamepad at all! |
| 223 |
bool gamePadDisconnected = !gamePadState.IsConnected && |
| 224 |
input.GamePadWasConnected[playerIndex]; |
| 225 |
|
| 226 |
if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected) |
| 227 |
{ |
| 228 |
ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer); |
| 229 |
} |
| 230 |
|
| 231 |
else |
| 232 |
{ // If/ElseIf is used so we don't move up AND down (by holding both buttons). It's either up OR down, not both |
| 233 |
if (myInputClass.LeftDown) leftBat.MoveDown(); |
| 234 |
else if ((myInputClass.LeftUp)) leftBat.MoveUp(); |
| 235 |
if (myInputClass.RightDown) rightBat.MoveDown(); |
| 236 |
else if (myInputClass.RightUp) rightBat.MoveUp(); |
| 237 |
} |
| 238 |
|
| 239 |
//checking if the rectangles collide. |
| 240 |
if (ball.GetDirection() > 1.5f * Math.PI || ball.GetDirection() < 0.5f * Math.PI) |
| 241 |
{ |
| 242 |
if (rightBat.GetSize().Intersects(ball.GetSize())) |
| 243 |
{ |
| 244 |
ball.BatHit(CheckHitLocation(rightBat)); |
| 245 |
} |
| 246 |
} |
| 247 |
else |
| 248 |
{ |
| 249 |
if (leftBat.GetSize().Intersects(ball.GetSize())) |
| 250 |
{ |
| 251 |
ball.BatHit(CheckHitLocation(leftBat)); |
| 252 |
} |
| 253 |
} |
| 254 |
|
| 255 |
|
| 256 |
|
| 257 |
// Handles whether or not the ball went off the left or right side of the screen |
| 258 |
if (ball.GetPosition().X > screenWidth) |
| 259 |
{ |
| 260 |
ball.Reset(true); |
| 261 |
} |
| 262 |
else if (ball.GetPosition().X < 0) |
| 263 |
{ |
| 264 |
ball.Reset(false); |
| 265 |
} |
| 266 |
} |
| 267 |
|
| 268 |
|
| 269 |
|
| 270 |
private void SetUpSingle() |
| 271 |
{ |
| 272 |
rightBat = new AIBat(content, new Vector2(screenWidth, screenHeight), false); |
| 273 |
leftBat = new Bat(content, new Vector2(screenWidth, screenHeight), true); |
| 274 |
} |
| 275 |
|
| 276 |
|
| 277 |
public void SetUpMulti() |
| 278 |
{ |
| 279 |
rightBat = new Bat(content, new Vector2(screenWidth, screenHeight), false); |
| 280 |
leftBat = new Bat(content, new Vector2(screenWidth, screenHeight), true); |
| 281 |
} |
| 282 |
|
| 283 |
|
| 284 |
|
| 285 |
// DRAW CALLS |
| 286 |
// |
| 287 |
// |
| 288 |
public override void Draw(GameTime gameTime) |
| 289 |
{ |
| 290 |
// Our player and enemy are both actually just text strings. |
| 291 |
SpriteBatch spriteBatch = ScreenManager.SpriteBatch; |
| 292 |
|
| 293 |
spriteBatch.Begin(); |
| 294 |
|
| 295 |
// Draws the backgrund |
| 296 |
spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, 800, 600), Color.White); |
| 297 |
|
| 298 |
// Draws the score |
| 299 |
spriteBatch.DrawString(arial, leftBat.GetPoints().ToString(), new Vector2 |
| 300 |
(screenWidth / 4 - arial.MeasureString(rightBat.GetPoints().ToString()).X, 20), Color.White); |
| 301 |
spriteBatch.DrawString(arial, rightBat.GetPoints().ToString(), new Vector2 |
| 302 |
(screenWidth / 4 * 3 - arial.MeasureString(rightBat.GetPoints().ToString()).X, 20), Color.White); |
| 303 |
|
| 304 |
// draw hud |
| 305 |
hudContainer.Draw(spriteBatch); |
| 306 |
spriteBatch.DrawString(gameFont, "Mega Man Pong", |
| 307 |
enemyPosition, Color.Black); |
| 308 |
|
| 309 |
#if DEBUG // I've temporarily commented out the safeArea debug -DV |
| 310 |
// safeArea.Draw(spriteBatch); |
| 311 |
#endif |
| 312 |
|
| 313 |
// debug info |
| 314 |
var safeAreaInfo = "dx=" + safeArea.dx + ",dy=" + safeArea.dy |
| 315 |
+ ",w=" + safeArea.width + ",h=" + safeArea.height; |
| 316 |
//+ ", H = " + playerHorizDirection |
| 317 |
//+ ", V = " + playerVertDirection; |
| 318 |
spriteBatch.DrawString(gameFont, safeAreaInfo, safeTopLeft, Color.Green); |
| 319 |
|
| 320 |
// Draws ball and bats |
| 321 |
ball.Draw(spriteBatch); |
| 322 |
rightBat.Draw(spriteBatch); |
| 323 |
leftBat.Draw(spriteBatch); |
| 324 |
|
| 325 |
spriteBatch.End(); |
| 326 |
|
| 327 |
// If the game is transitioning on or off, fade it out to black. |
| 328 |
if (TransitionPosition > 0 || pauseAlpha > 0) |
| 329 |
{ |
| 330 |
float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2); |
| 331 |
ScreenManager.FadeBackBufferToBlack(alpha); |
| 332 |
} |
| 333 |
} |
| 334 |
} |
| 335 |
} |
| 336 |
|