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 |
|