//-----------------------------------------------------------------------------
// RacingGameManager.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Threading;
using RacingGame.GameLogic;
using RacingGame.GameScreens;
using RacingGame.Graphics;
using RacingGame.Helpers;
using RacingGame.Landscapes;
using RacingGame.Sounds;
using Model = RacingGame.Graphics.Model;
using Texture = RacingGame.Graphics.Texture;
using RacingGame.Properties;
using RacingGame.Shaders;
using System.Threading.Tasks;
namespace RacingGame
{
///
/// This is the main entry class our game. Handles all game screens,
/// which themself handle all the game logic.
/// As you can see this class is very simple, which is really cool.
///
public class RacingGameManager : BaseGame
{
///
/// Game screens stack. We can easily add and remove game screens
/// and they follow the game logic automatically. Very cool.
///
private static Stack gameScreens = new Stack();
///
/// Player for the game, also allows us to control the car and contains
/// all the required code for the car physics, chase camera and basic
/// player values and the game time because this is the top class
/// of many derived classes. Player, car and camera position is set
/// when the game starts depending on the selected level.
///
private static Player player = new Player(new Vector3(0, 0, 0));
///
/// Car model and selection plate for the car selection screen.
///
private static Model carModel = null,
carSelectionPlate = null;
///
/// Car textures we exchange for our car model.
///
private static Texture[] carTextures = null;
///
/// The player can select between the 3 cars: 0 (white), 1 (red) and
/// 2 (yellow).
///
public static int currentCarNumber = 0;
///
/// The player can also select a car color, which will be used to
/// recolor the car. Looks best for the first car (white).
///
public static int currentCarColor;// Color carColor = Color.White;
///
/// Helper texture for color selection
///
public static Texture colorSelectionTexture = null;
///
/// Material for brake tracks on the road.
///
private static Material brakeTrackMaterial = null;
///
/// Car colors for the car selection screen.
///
public static List CarColors = new List(
new Color[]
{
Color.White,
Color.Yellow,
Color.Blue,
Color.Purple,
Color.Red,
Color.Green,
Color.Teal,
Color.Gray,
Color.Chocolate,
Color.MonoGameOrange,
Color.SeaGreen,
});
///
/// Landscape we are currently using.
///
private static Landscape landscape = null;
///
/// Level we use for our track and landscape
///
public enum Level
{
Beginner,
Advanced,
Expert,
}
///
/// Load level
///
/// Set new level
public static void LoadLevel(Level setNewLevel)
{
landscape.ReloadLevel(setNewLevel);
}
public static event EventHandler LoadEvent;
///
/// In menu
///
/// Bool
public static bool InMenu
{
get
{
return gameScreens.Count > 0 &&
gameScreens.Peek().GetType() != typeof(GameScreen);
}
}
///
/// In game?
///
public static bool InGame
{
get
{
return gameScreens.Count > 0 &&
gameScreens.Peek().GetType() == typeof(GameScreen);
}
}
///
/// ShowMouseCursor
///
/// Bool
public static bool ShowMouseCursor
{
get
{
// Only if not in Game, not in splash screen!
return gameScreens.Count > 0 &&
gameScreens.Peek().GetType() != typeof(GameScreen) &&
gameScreens.Peek().GetType() != typeof(SplashScreen) &&
gameScreens.Peek().GetType() != typeof(LoadingScreen);
}
}
///
/// In car selection screen
///
/// Bool
public static bool InCarSelectionScreen
{
get
{
return gameScreens.Count > 0 &&
gameScreens.Peek().GetType() == typeof(CarSelection);
}
}
///
/// Player for the game, also allows us to control the car and contains
/// all the required code for the car physics, chase camera and basic
/// player values and the game time because this is the top class
/// of many derived classes.
/// Easy access here with a static property in case we need the player
/// somewhere in the game.
///
/// Player
public static Player Player
{
get
{
return player;
}
}
///
/// Car model
///
/// Model
public static Model CarModel
{
get
{
return carModel;
}
}
///
/// Car color
///
/// Color
public static Color CarColor
{
get
{
return CarColors[currentCarColor % CarColors.Count];
}
}
///
/// Number of car colors
///
/// Int
public static int NumberOfCarColors
{
get
{
return CarColors.Count;
}
}
///
/// Number of car texture types
///
/// Int
public static int NumberOfCarTextureTypes
{
get
{
return carTextures.Length;
}
}
///
/// Car texture
///
/// Car number
/// Texture
public static Texture CarTexture(int carNumber)
{
return carTextures[carNumber % carTextures.Length];
}
///
/// Brake track material
///
/// Material
public static Material BrakeTrackMaterial
{
get
{
return brakeTrackMaterial;
}
}
///
/// Car selection plate
///
/// Model
public static Model CarSelectionPlate
{
get
{
return carSelectionPlate;
}
}
///
/// Landscape we are currently using, used for several things (menu
/// background, the game, some other classes outside the landscape class).
///
/// Landscape
public static Landscape Landscape
{
get
{
return landscape;
}
}
///
/// The Task that will load most of the content for this game
/// in the background, while the loading screen is shown.
///
private static Task loadingTask;
public static Task LoadingTask
{
get
{
return loadingTask;
}
set
{
loadingTask = value;
}
}
public static bool ContentLoaded
{
get
{
return loadingTask?.IsCompleted == true;
}
}
///
/// Create Racing game
///
public RacingGameManager()
: base("RacingGame")
{
Sound.Initialize();
// Start playing the menu music
//Sound.Play(Sound.Sounds.MenuMusic);
// Create main menu at our main entry point
gameScreens.Push(new MainMenu());
// But start with splash screen, if user clicks or presses Start,
// we are back in the main menu.
gameScreens.Push(new SplashScreen());
//We want to initially show the loading screen while things start.
gameScreens.Push(new LoadingScreen());
}
///
/// Create Racing game for unit tests, not used for anything else.
///
public RacingGameManager(string unitTestName)
: base(unitTestName)
{
// Don't add game screens here
}
///
/// Load car stuff
///
protected override void Initialize()
{
base.Initialize();
}
///
/// Initializes and loads some content, previously referred to as the
/// "car stuff".
///
public static void LoadResources()
{
LoadEvent("Models...", null);
// Load models
carModel = new Model("Car");
carSelectionPlate = new Model("CarSelectionPlate");
LoadEvent("Landscape...", null);
// Load landscape
landscape = new Landscape(Level.Beginner);
LoadEvent("Textures...", null);
// Load textures, first one is grabbed from the imported one through
// the car.x model, the other two are loaded seperately.
carTextures = new Texture[3];
carTextures[0] = new Texture("RacerCar");
carTextures[1] = new Texture("RacerCar2");
carTextures[2] = new Texture("RacerCar3");
colorSelectionTexture = new Texture("ColorSelection");
brakeTrackMaterial = new Material("Track");
LoadEvent("All systems go!", null);
Task.Delay(1000).Wait();
}
///
/// Add game screen
///
/// Game screen
public static void AddGameScreen(IGameScreen gameScreen)
{
// Play sound for screen click
Sound.Play(Sound.Sounds.ScreenClick);
// Add the game screen
gameScreens.Push(gameScreen);
}
///
/// Update
///
protected override void Update(GameTime gameTime)
{
// Update game engine
base.Update(gameTime);
if (gameScreens.Count > 0)
{
if (gameScreens.Peek().GetType() != typeof(LoadingScreen))
{
// Update player and game logic
player.Update();
}
//Update the game screen
gameScreens.Peek().Update(gameTime);
}
}
///
/// Render
///
protected override void Render()
{
// No more game screens?
if (gameScreens.Count == 0)
{
// Before quiting, stop music and play crash sound :)
Sound.PlayCrashSound(true);
Sound.StopMusic();
// Then quit
Exit();
return;
}
// Handle current screen
if (gameScreens.Peek().Render())
{
// If this was the options screen and the resolution has changed,
// apply the changes
if (gameScreens.Peek().GetType() == typeof(Options) &&
(BaseGame.Width != GameSettings.Default.ResolutionWidth ||
BaseGame.Height != GameSettings.Default.ResolutionHeight ||
BaseGame.Fullscreen != GameSettings.Default.Fullscreen))
{
BaseGame.ApplyResolutionChange();
}
// Play sound for screen back
Sound.Play(Sound.Sounds.ScreenBack);
gameScreens.Pop();
}
}
///
/// Post user interface rendering, in case we need it.
/// Used for rendering the car selection 3d stuff after the UI.
///
protected override void PostUIRender()
{
// Enable depth buffer again
BaseGame.Device.DepthStencilState = DepthStencilState.Default;
// Currently in car selection screen?
if (gameScreens.Count > 0 &&
gameScreens.Peek().GetType() == typeof(CarSelection))
((CarSelection)gameScreens.Peek()).PostUIRender();
// Do menu shader after everything
if (BaseGame.UsePostScreenShaders && PostScreenMenu.Started)
UI.PostScreenMenuShader.Show();
}
}
}