https://github.com/Robmaister/SharpFont TODO: replace Code Bold.otf with the full version, fix any bugs, build on Linux, possibly move ToolBox string wrapping and limiting logic to ScalableFont class for better results.
429 lines
14 KiB
C#
429 lines
14 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
using FarseerPhysics;
|
|
using FarseerPhysics.Dynamics;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Barotrauma.Networking;
|
|
using Barotrauma.Particles;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using System.Xml;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
class GameMain : Game
|
|
{
|
|
public static GraphicsDeviceManager Graphics;
|
|
static int graphicsWidth, graphicsHeight;
|
|
static SpriteBatch spriteBatch;
|
|
|
|
public static GameMain Instance;
|
|
|
|
public static bool WindowActive
|
|
{
|
|
get { return Instance == null || Instance.IsActive; }
|
|
}
|
|
|
|
public static bool DebugDraw;
|
|
|
|
public static GraphicsDevice CurrGraphicsDevice;
|
|
|
|
public static FrameCounter FrameCounter;
|
|
|
|
public static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
|
|
|
|
public static GameScreen GameScreen;
|
|
public static MainMenuScreen MainMenuScreen;
|
|
public static LobbyScreen LobbyScreen;
|
|
|
|
public static NetLobbyScreen NetLobbyScreen;
|
|
public static ServerListScreen ServerListScreen;
|
|
|
|
public static EditMapScreen EditMapScreen;
|
|
public static EditCharacterScreen EditCharacterScreen;
|
|
|
|
public static Lights.LightManager LightManager;
|
|
|
|
public static ContentPackage SelectedPackage
|
|
{
|
|
get { return Config.SelectedContentPackage; }
|
|
}
|
|
|
|
public static Level Level;
|
|
|
|
public static GameSession GameSession;
|
|
|
|
public static NetworkMember NetworkMember;
|
|
|
|
public static ParticleManager ParticleManager;
|
|
|
|
//public static TextureLoader TextureLoader;
|
|
|
|
public static World World;
|
|
|
|
public static LoadingScreen TitleScreen;
|
|
private static bool loadingScreenOpen;
|
|
|
|
public static GameSettings Config;
|
|
|
|
private bool hasLoaded;
|
|
|
|
private GameTime fixedTime;
|
|
|
|
//public static Random localRandom;
|
|
//public static Random random;
|
|
|
|
//private Stopwatch renderTimer;
|
|
//public static int renderTimeElapsed;
|
|
|
|
public Camera Cam
|
|
{
|
|
get { return GameScreen.Cam; }
|
|
}
|
|
|
|
public static int GraphicsWidth
|
|
{
|
|
get { return graphicsWidth; }
|
|
}
|
|
|
|
public static int GraphicsHeight
|
|
{
|
|
get { return graphicsHeight; }
|
|
}
|
|
|
|
public static GameServer Server
|
|
{
|
|
get { return NetworkMember as GameServer; }
|
|
}
|
|
|
|
public static GameClient Client
|
|
{
|
|
get { return NetworkMember as GameClient; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Total seconds elapsed after startup
|
|
/// </summary>
|
|
public double TotalElapsedTime
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public GameMain()
|
|
{
|
|
Graphics = new GraphicsDeviceManager(this);
|
|
|
|
Window.Title = "Barotrauma";
|
|
|
|
Instance = this;
|
|
|
|
Config = new GameSettings("config.xml");
|
|
if (Config.WasGameUpdated)
|
|
{
|
|
UpdaterUtil.CleanOldFiles();
|
|
Config.WasGameUpdated = false;
|
|
Config.Save("config.xml");
|
|
}
|
|
|
|
ApplyGraphicsSettings();
|
|
|
|
Content.RootDirectory = "Content";
|
|
|
|
FrameCounter = new FrameCounter();
|
|
|
|
//IsMouseVisible = true;
|
|
|
|
IsFixedTimeStep = false;
|
|
//TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 55);
|
|
|
|
Timing.Accumulator = 0.0f;
|
|
fixedTime = new GameTime();
|
|
|
|
World = new World(new Vector2(0, -9.82f));
|
|
FarseerPhysics.Settings.AllowSleep = true;
|
|
FarseerPhysics.Settings.ContinuousPhysics = false;
|
|
FarseerPhysics.Settings.VelocityIterations = 1;
|
|
FarseerPhysics.Settings.PositionIterations = 1;
|
|
|
|
}
|
|
|
|
public void ApplyGraphicsSettings()
|
|
{
|
|
graphicsWidth = Config.GraphicsWidth;
|
|
graphicsHeight = Config.GraphicsHeight;
|
|
Graphics.SynchronizeWithVerticalRetrace = Config.VSyncEnabled;
|
|
|
|
Graphics.HardwareModeSwitch = Config.WindowMode != WindowMode.BorderlessWindowed;
|
|
|
|
Graphics.IsFullScreen = Config.WindowMode == WindowMode.Fullscreen || Config.WindowMode == WindowMode.BorderlessWindowed;
|
|
Graphics.PreferredBackBufferWidth = graphicsWidth;
|
|
Graphics.PreferredBackBufferHeight = graphicsHeight;
|
|
|
|
Graphics.ApplyChanges();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows the game to perform any initialization it needs to before starting to run.
|
|
/// This is where it can query for any required services and load any non-graphic
|
|
/// related content. Calling base.Initialize will enumerate through any components
|
|
/// and initialize them as well.
|
|
/// </summary>
|
|
protected override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
CurrGraphicsDevice = GraphicsDevice;
|
|
|
|
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Character));
|
|
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Item));
|
|
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Items.Components.ItemComponent));
|
|
Hyper.ComponentModel.HyperTypeDescriptionProvider.Add(typeof(Hull));
|
|
}
|
|
|
|
/// <summary>
|
|
/// LoadContent will be called once per game and is the place to load
|
|
/// all of your content.
|
|
/// </summary>
|
|
protected override void LoadContent()
|
|
{
|
|
graphicsWidth = GraphicsDevice.Viewport.Width;
|
|
graphicsHeight = GraphicsDevice.Viewport.Height;
|
|
|
|
Sound.Init();
|
|
|
|
ConvertUnits.SetDisplayUnitToSimUnitRatio(Physics.DisplayToSimRation);
|
|
|
|
spriteBatch = new SpriteBatch(GraphicsDevice);
|
|
TextureLoader.Init(GraphicsDevice);
|
|
|
|
loadingScreenOpen = true;
|
|
TitleScreen = new LoadingScreen(GraphicsDevice);
|
|
|
|
CoroutineManager.StartCoroutine(Load());
|
|
}
|
|
|
|
public IEnumerable<object> Load()
|
|
{
|
|
GUI.GraphicsDevice = GraphicsDevice;
|
|
GUI.Init(Content);
|
|
|
|
GUIComponent.Init(Window);
|
|
DebugConsole.Init(Window);
|
|
DebugConsole.Log(SelectedPackage == null ? "No content package selected" : "Content package \"" + SelectedPackage.Name + "\" selected");
|
|
yield return CoroutineStatus.Running;
|
|
|
|
LightManager = new Lights.LightManager(GraphicsDevice);
|
|
|
|
Hull.renderer = new WaterRenderer(GraphicsDevice, Content);
|
|
TitleScreen.LoadState = 1.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
GUI.LoadContent();
|
|
TitleScreen.LoadState = 2.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
Mission.Init();
|
|
MapEntityPrefab.Init();
|
|
LevelGenerationParams.LoadPresets();
|
|
TitleScreen.LoadState = 10.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
JobPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Jobs));
|
|
StructurePrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Structure));
|
|
TitleScreen.LoadState = 20.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
ItemPrefab.LoadAll(SelectedPackage.GetFilesOfType(ContentType.Item));
|
|
TitleScreen.LoadState = 30.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
Debug.WriteLine("sounds");
|
|
CoroutineManager.StartCoroutine(SoundPlayer.Init());
|
|
|
|
int i = 0;
|
|
while (!SoundPlayer.Initialized)
|
|
{
|
|
i++;
|
|
TitleScreen.LoadState = SoundPlayer.SoundCount == 0 ?
|
|
30.0f :
|
|
Math.Min(30.0f + 40.0f * i / Math.Max(SoundPlayer.SoundCount, 1), 70.0f);
|
|
yield return CoroutineStatus.Running;
|
|
}
|
|
|
|
TitleScreen.LoadState = 70.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
GameModePreset.Init();
|
|
|
|
Submarine.RefreshSavedSubs();
|
|
TitleScreen.LoadState = 80.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
GameScreen = new GameScreen(Graphics.GraphicsDevice, Content);
|
|
TitleScreen.LoadState = 90.0f;
|
|
yield return CoroutineStatus.Running;
|
|
|
|
MainMenuScreen = new MainMenuScreen(this);
|
|
LobbyScreen = new LobbyScreen();
|
|
|
|
ServerListScreen = new ServerListScreen();
|
|
|
|
EditMapScreen = new EditMapScreen();
|
|
EditCharacterScreen = new EditCharacterScreen();
|
|
|
|
yield return CoroutineStatus.Running;
|
|
|
|
ParticleManager = new ParticleManager("Content/Particles/ParticlePrefabs.xml", Cam);
|
|
yield return CoroutineStatus.Running;
|
|
|
|
LocationType.Init();
|
|
MainMenuScreen.Select();
|
|
|
|
TitleScreen.LoadState = 100.0f;
|
|
hasLoaded = true;
|
|
yield return CoroutineStatus.Success;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// UnloadContent will be called once per game and is the place to unload
|
|
/// all content.
|
|
/// </summary>
|
|
protected override void UnloadContent()
|
|
{
|
|
Sound.Dispose();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Allows the game to run logic such as updating the world,
|
|
/// checking for collisions, gathering input, and playing audio.
|
|
/// </summary>
|
|
/// <param name="gameTime">Provides a snapshot of timing values.</param>
|
|
protected override void Update(GameTime gameTime)
|
|
{
|
|
Timing.Accumulator += gameTime.ElapsedGameTime.TotalSeconds;
|
|
bool paused = true;
|
|
|
|
while (Timing.Accumulator >= Timing.Step)
|
|
{
|
|
TotalElapsedTime = gameTime.TotalGameTime.TotalSeconds;
|
|
|
|
fixedTime.IsRunningSlowly = gameTime.IsRunningSlowly;
|
|
TimeSpan addTime = new TimeSpan(0, 0, 0, 0, 16);
|
|
fixedTime.ElapsedGameTime = addTime;
|
|
fixedTime.TotalGameTime.Add(addTime);
|
|
base.Update(fixedTime);
|
|
|
|
PlayerInput.Update(Timing.Step);
|
|
|
|
if (loadingScreenOpen)
|
|
{
|
|
//reset accumulator if loading
|
|
// -> less choppy loading screens because the screen is rendered after each update
|
|
// -> no pause caused by leftover time in the accumulator when starting a new shift
|
|
Timing.Accumulator = 0.0f;
|
|
|
|
if (TitleScreen.LoadState >= 100.0f &&
|
|
(!waitForKeyHit || PlayerInput.GetKeyboardState.GetPressedKeys().Length>0 || PlayerInput.LeftButtonClicked()))
|
|
{
|
|
loadingScreenOpen = false;
|
|
}
|
|
}
|
|
else if (hasLoaded)
|
|
{
|
|
SoundPlayer.Update();
|
|
|
|
if (PlayerInput.KeyHit(Keys.Escape)) GUI.TogglePauseMenu();
|
|
|
|
GUIComponent.ClearUpdateList();
|
|
DebugConsole.AddToGUIUpdateList();
|
|
|
|
paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) &&
|
|
(NetworkMember == null || !NetworkMember.GameStarted);
|
|
|
|
if (!paused)
|
|
{
|
|
Screen.Selected.AddToGUIUpdateList();
|
|
}
|
|
|
|
if (NetworkMember != null)
|
|
{
|
|
NetworkMember.AddToGUIUpdateList();
|
|
}
|
|
|
|
GUI.AddToGUIUpdateList();
|
|
GUIComponent.UpdateMouseOn();
|
|
|
|
DebugConsole.Update(this, (float)Timing.Step);
|
|
|
|
if (!paused)
|
|
{
|
|
Screen.Selected.Update(Timing.Step);
|
|
}
|
|
|
|
if (NetworkMember != null)
|
|
{
|
|
NetworkMember.Update((float)Timing.Step);
|
|
}
|
|
|
|
GUI.Update((float)Timing.Step);
|
|
}
|
|
|
|
CoroutineManager.Update((float)Timing.Step, paused ? 0.0f : (float)Timing.Step);
|
|
|
|
Timing.Accumulator -= Timing.Step;
|
|
}
|
|
|
|
if (!paused) Timing.Alpha = Timing.Accumulator / Timing.Step;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This is called when the game should draw itself.
|
|
/// </summary>
|
|
protected override void Draw(GameTime gameTime)
|
|
{
|
|
double deltaTime = gameTime.ElapsedGameTime.TotalSeconds;
|
|
|
|
FrameCounter.Update(deltaTime);
|
|
|
|
if (loadingScreenOpen)
|
|
{
|
|
TitleScreen.Draw(spriteBatch, GraphicsDevice, (float)deltaTime);
|
|
}
|
|
else if (hasLoaded)
|
|
{
|
|
Screen.Selected.Draw(deltaTime, GraphicsDevice, spriteBatch);
|
|
}
|
|
|
|
if (!DebugDraw) return;
|
|
if (GUIComponent.MouseOn!=null)
|
|
{
|
|
spriteBatch.Begin();
|
|
GUI.DrawRectangle(spriteBatch, GUIComponent.MouseOn.MouseRect, Color.Lime);
|
|
spriteBatch.End();
|
|
}
|
|
}
|
|
|
|
static bool waitForKeyHit = true;
|
|
public static CoroutineHandle ShowLoading(IEnumerable<object> loader, bool waitKeyHit = true)
|
|
{
|
|
waitForKeyHit = waitKeyHit;
|
|
loadingScreenOpen = true;
|
|
TitleScreen.LoadState = null;
|
|
return CoroutineManager.StartCoroutine(TitleScreen.DoLoading(loader));
|
|
}
|
|
|
|
protected override void OnExiting(object sender, EventArgs args)
|
|
{
|
|
if (NetworkMember != null) NetworkMember.Disconnect();
|
|
|
|
base.OnExiting(sender, args);
|
|
}
|
|
|
|
}
|
|
} |