1 #region File Description
2 //-----------------------------------------------------------------------------
5 // Microsoft XNA Community Game Platform
6 // Copyright (C) Microsoft Corporation. All rights reserved.
7 //-----------------------------------------------------------------------------
12 using Microsoft
.Xna
.Framework
;
13 using Microsoft
.Xna
.Framework
.Graphics
;
14 using Microsoft
.Xna
.Framework
.Input
;
15 using Microsoft
.Xna
.Framework
.Media
;
16 using Microsoft
.Xna
.Framework
.Input
.Touch
;
17 using Microsoft
.Xna
.Framework
.Content
;
19 namespace Platformer2D
22 /// This is the main type for your game
24 public class PlatformerGame
: Microsoft
.Xna
.Framework
.Game
26 // Resources for drawing.
27 private GraphicsDeviceManager graphics
;
28 private SpriteBatch spriteBatch
;
29 Vector2 baseScreenSize
= new Vector2(800, 480);
30 private Matrix globalTransformation
;
31 int backbufferWidth
, backbufferHeight
;
34 private SpriteFont hudFont
;
36 private Texture2D winOverlay
;
37 private Texture2D loseOverlay
;
38 private Texture2D diedOverlay
;
40 // Meta-level game state.
41 private int levelIndex
= -1;
43 private bool wasContinuePressed
;
45 // When the time remaining is less than the warning time, it blinks on the hud
46 private static readonly TimeSpan WarningTime
= TimeSpan
.FromSeconds(30);
48 // We store our input states so that we only poll once per frame,
49 // then we use the same input state wherever needed
50 private GamePadState gamePadState
;
51 private KeyboardState keyboardState
;
52 private TouchCollection touchState
;
53 private AccelerometerState accelerometerState
;
55 private VirtualGamePad virtualGamePad
;
57 // The number of levels in the Levels directory of our content. We assume that
58 // levels in our content are 0-based and that all numbers under this constant
59 // have a level file present. This allows us to not need to check for the file
60 // or handle exceptions, both of which can add unnecessary time to level loading.
61 private const int numberOfLevels
= 3;
63 public PlatformerGame()
65 graphics
= new GraphicsDeviceManager(this);
68 TargetElapsedTime
= TimeSpan
.FromTicks(333333);
70 graphics
.IsFullScreen
= false;
72 //graphics.PreferredBackBufferWidth = 800;
73 //graphics.PreferredBackBufferHeight = 480;
74 graphics
.SupportedOrientations
= DisplayOrientation
.LandscapeLeft
| DisplayOrientation
.LandscapeRight
;
76 Accelerometer
.Initialize();
80 /// LoadContent will be called once per game and is the place to load
81 /// all of your content.
83 protected override void LoadContent()
85 this.Content
.RootDirectory
= "Content";
87 // Create a new SpriteBatch, which can be used to draw textures.
88 spriteBatch
= new SpriteBatch(GraphicsDevice
);
91 hudFont
= Content
.Load
<SpriteFont
>("Fonts/Hud");
93 // Load overlay textures
94 winOverlay
= Content
.Load
<Texture2D
>("Overlays/you_win");
95 loseOverlay
= Content
.Load
<Texture2D
>("Overlays/you_lose");
96 diedOverlay
= Content
.Load
<Texture2D
>("Overlays/you_died");
98 ScalePresentationArea();
100 virtualGamePad
= new VirtualGamePad(baseScreenSize
, globalTransformation
, Content
.Load
<Texture2D
>("Sprites/VirtualControlArrow"));
102 //Known issue that you get exceptions if you use Media PLayer while connected to your PC
103 //See http://social.msdn.microsoft.com/Forums/en/windowsphone7series/thread/c8a243d2-d360-46b1-96bd-62b1ef268c66
104 //Which means its impossible to test this from VS.
105 //So we have to catch the exception and throw it away
108 MediaPlayer
.IsRepeating
= true;
109 MediaPlayer
.Play(Content
.Load
<Song
>("Sounds/Music"));
116 public void ScalePresentationArea()
118 //Work out how much we need to scale our graphics to fill the screen
119 backbufferWidth
= GraphicsDevice
.PresentationParameters
.BackBufferWidth
;
120 backbufferHeight
= GraphicsDevice
.PresentationParameters
.BackBufferHeight
;
121 float horScaling
= backbufferWidth
/ baseScreenSize
.X
;
122 float verScaling
= backbufferHeight
/ baseScreenSize
.Y
;
123 Vector3 screenScalingFactor
= new Vector3(horScaling
, verScaling
, 1);
124 globalTransformation
= Matrix
.CreateScale(screenScalingFactor
);
125 System
.Diagnostics
.Debug
.WriteLine("Screen Size - Width[" + GraphicsDevice
.PresentationParameters
.BackBufferWidth
+ "] Height [" + GraphicsDevice
.PresentationParameters
.BackBufferHeight
+ "]");
130 /// Allows the game to run logic such as updating the world,
131 /// checking for collisions, gathering input, and playing audio.
133 /// <param name="gameTime">Provides a snapshot of timing values.</param>
134 protected override void Update(GameTime gameTime
)
136 //Confirm the screen has not been resized by the user
137 if (backbufferHeight
!= GraphicsDevice
.PresentationParameters
.BackBufferHeight
||
138 backbufferWidth
!= GraphicsDevice
.PresentationParameters
.BackBufferWidth
)
140 ScalePresentationArea();
142 // Handle polling for our input and handling high-level input
143 HandleInput(gameTime
);
145 // update our level, passing down the GameTime along with all of our input states
146 level
.Update(gameTime
, keyboardState
, gamePadState
,
147 accelerometerState
, Window
.CurrentOrientation
);
149 if (level
.Player
.Velocity
!= Vector2
.Zero
)
150 virtualGamePad
.NotifyPlayerIsMoving();
152 base.Update(gameTime
);
155 private void HandleInput(GameTime gameTime
)
157 // get all of our input states
158 keyboardState
= Keyboard
.GetState();
159 touchState
= TouchPanel
.GetState();
160 gamePadState
= virtualGamePad
.GetState(touchState
, GamePad
.GetState(PlayerIndex
.One
));
161 accelerometerState
= Accelerometer
.GetState();
164 // Exit the game when back is pressed.
165 if (gamePadState
.Buttons
.Back
== ButtonState
.Pressed
)
168 bool continuePressed
=
169 keyboardState
.IsKeyDown(Keys
.Space
) ||
170 gamePadState
.IsButtonDown(Buttons
.A
) ||
171 touchState
.AnyTouch();
173 // Perform the appropriate action to advance the game and
174 // to get the player back to playing.
175 if (!wasContinuePressed
&& continuePressed
)
177 if (!level
.Player
.IsAlive
)
179 level
.StartNewLife();
181 else if (level
.TimeRemaining
== TimeSpan
.Zero
)
183 if (level
.ReachedExit
)
186 ReloadCurrentLevel();
190 wasContinuePressed
= continuePressed
;
192 virtualGamePad
.Update(gameTime
);
195 private void LoadNextLevel()
197 // move to the next level
198 levelIndex
= (levelIndex
+ 1) % numberOfLevels
;
200 // Unloads the content for the current level before loading the next one.
205 string levelPath
= string.Format("Content/Levels/{0}.txt", levelIndex
);
206 using (Stream fileStream
= TitleContainer
.OpenStream(levelPath
))
207 level
= new Level(Services
, fileStream
, levelIndex
);
210 private void ReloadCurrentLevel()
217 /// Draws the game from background to foreground.
219 /// <param name="gameTime">Provides a snapshot of timing values.</param>
220 protected override void Draw(GameTime gameTime
)
222 graphics
.GraphicsDevice
.Clear(Color
.CornflowerBlue
);
224 spriteBatch
.Begin(SpriteSortMode
.Immediate
, null, null, null, null,null, globalTransformation
);
226 level
.Draw(gameTime
, spriteBatch
);
235 private void DrawHud()
237 Rectangle titleSafeArea
= GraphicsDevice
.Viewport
.TitleSafeArea
;
238 Vector2 hudLocation
= new Vector2(titleSafeArea
.X
, titleSafeArea
.Y
);
239 //Vector2 center = new Vector2(titleSafeArea.X + titleSafeArea.Width / 2.0f,
240 // titleSafeArea.Y + titleSafeArea.Height / 2.0f);
242 Vector2 center
= new Vector2(baseScreenSize
.X
/ 2, baseScreenSize
.Y
/ 2);
244 // Draw time remaining. Uses modulo division to cause blinking when the
245 // player is running out of time.
246 string timeString
= "TIME: " + level
.TimeRemaining
.Minutes
.ToString("00") + ":" + level
.TimeRemaining
.Seconds
.ToString("00");
248 if (level
.TimeRemaining
> WarningTime
||
250 (int)level
.TimeRemaining
.TotalSeconds
% 2 == 0)
252 timeColor
= Color
.Yellow
;
256 timeColor
= Color
.Red
;
258 DrawShadowedString(hudFont
, timeString
, hudLocation
, timeColor
);
261 float timeHeight
= hudFont
.MeasureString(timeString
).Y
;
262 DrawShadowedString(hudFont
, "SCORE: " + level
.Score
.ToString(), hudLocation
+ new Vector2(0.0f
, timeHeight
* 1.2f
), Color
.Yellow
);
264 // Determine the status overlay message to show.
265 Texture2D status
= null;
266 if (level
.TimeRemaining
== TimeSpan
.Zero
)
268 if (level
.ReachedExit
)
274 status
= loseOverlay
;
277 else if (!level
.Player
.IsAlive
)
279 status
= diedOverlay
;
284 // Draw status message.
285 Vector2 statusSize
= new Vector2(status
.Width
, status
.Height
);
286 spriteBatch
.Draw(status
, center
- statusSize
/ 2, Color
.White
);
289 if (touchState
.IsConnected
)
290 virtualGamePad
.Draw(spriteBatch
);
293 private void DrawShadowedString(SpriteFont font
, string value, Vector2 position
, Color color
)
295 spriteBatch
.DrawString(font
, value, position
+ new Vector2(1.0f
, 1.0f
), Color
.Black
);
296 spriteBatch
.DrawString(font
, value, position
, color
);