mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-01 04:14:22 +00:00
464 lines
17 KiB
C#
464 lines
17 KiB
C#
using System;
|
|
using System.Threading;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using ProjectZ.InGame.GameObjects.Things;
|
|
using ProjectZ.InGame.Map;
|
|
using ProjectZ.InGame.SaveLoad;
|
|
using ProjectZ.InGame.Things;
|
|
#if WINDOWS
|
|
using System.Windows.Forms;
|
|
#endif
|
|
|
|
namespace ProjectZ.InGame.GameSystems
|
|
{
|
|
internal class MapTransitionSystem : GameSystem
|
|
{
|
|
public int AdditionalBlackScreenDelay;
|
|
public bool StartDreamTransition;
|
|
public bool StartTeleportTransition;
|
|
public bool StartKnockoutTransition;
|
|
|
|
public enum TransitionState
|
|
{
|
|
Idle,
|
|
TransitionIn,
|
|
TransitionBlank_0,
|
|
TransitionBlank_1,
|
|
TransitionOut,
|
|
ColorMode
|
|
}
|
|
|
|
public TransitionState CurrentState = TransitionState.Idle;
|
|
public const int ChangeMapTime = 350;
|
|
public const int BlackScreenDelay = 75; // 125
|
|
|
|
private readonly MapManager _gameMapManager;
|
|
private readonly ObjTransition _transitionObject;
|
|
|
|
private Thread _loadingThread;
|
|
|
|
private string _nextMapName;
|
|
private string _nextMapPosition;
|
|
private bool _nextMapCenter;
|
|
private bool _nextMapStartInMiddle;
|
|
private Color _nextMapColor;
|
|
private bool _nextColorMode;
|
|
|
|
private float _changeMapCount;
|
|
|
|
// will be reset after each transition
|
|
private bool _centerCamera;
|
|
private bool _finishedLoading;
|
|
private bool _fullColorMode;
|
|
private bool _knockoutTransition;
|
|
private bool _transitionEnded;
|
|
private bool _introTransition;
|
|
|
|
private const int DreamTransitionTimeAddition = 3000;
|
|
private const int TeleportTransitionTimeAddition = 2000 - ChangeMapTime;
|
|
private int _wobbleTransitionTime;
|
|
private bool _wobbleTransitionOut;
|
|
private bool _wobbleTransitionIn;
|
|
|
|
public MapTransitionSystem(MapManager gameMapManager)
|
|
{
|
|
_gameMapManager = gameMapManager;
|
|
|
|
_transitionObject = new ObjTransition(_gameMapManager.CurrentMap);
|
|
}
|
|
|
|
public override void OnLoad()
|
|
{
|
|
_nextMapName = null;
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
// start map change
|
|
if (_nextMapName != null)
|
|
{
|
|
if (!string.IsNullOrEmpty(_nextMapPosition))
|
|
MapManager.ObjLink.SetNextMapPosition(_nextMapPosition);
|
|
|
|
LoadMapFromFile(_nextMapName, _nextMapCenter, _nextMapStartInMiddle, _nextMapColor, _nextColorMode);
|
|
_nextMapName = null;
|
|
}
|
|
|
|
if (_transitionEnded)
|
|
{
|
|
_transitionEnded = false;
|
|
Game1.GameManager.SaveManager.SetString("transition_ended", "0");
|
|
}
|
|
|
|
if (CurrentState != TransitionState.Idle)
|
|
Game1.GameManager.InGameOverlay.DisableOverlayToggle = true;
|
|
else
|
|
Game1.GbsPlayer.SetVolumeMultiplier(1);
|
|
|
|
if (CurrentState == TransitionState.TransitionOut)
|
|
{
|
|
_changeMapCount += Game1.DeltaTime;
|
|
|
|
var transitionState = _changeMapCount / ChangeMapTime;
|
|
var percentage = MathHelper.Clamp((float)(Math.Sin(transitionState * 1.1) / Math.Sin(1.1)), 0, 1);
|
|
MapManager.ObjLink.UpdateMapTransitionOut(percentage);
|
|
|
|
if (!_wobbleTransitionOut && !_knockoutTransition)
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = percentage;
|
|
|
|
// slowly lower the volume of the music
|
|
var newVolume = 1 - MathHelper.Clamp(transitionState, 0, 1);
|
|
Game1.GbsPlayer.SetVolumeMultiplier(newVolume);
|
|
|
|
if (_wobbleTransitionOut)
|
|
{
|
|
// fade out to a white screen
|
|
var wobblePercentage = MathHelper.Clamp(_changeMapCount / ChangeMapTime, 0, 1);
|
|
_transitionObject.Brightness = wobblePercentage;
|
|
_transitionObject.WobblePercentage = (_wobbleTransitionTime + _changeMapCount) / (_wobbleTransitionTime + ChangeMapTime);
|
|
}
|
|
|
|
if (_changeMapCount >= ChangeMapTime)
|
|
CurrentState = TransitionState.TransitionBlank_0;
|
|
}
|
|
else if (CurrentState == TransitionState.TransitionBlank_0)
|
|
{
|
|
_changeMapCount += Game1.DeltaTime;
|
|
|
|
MapManager.ObjLink.UpdateMapTransitionOut(1);
|
|
|
|
// new map is loaded?
|
|
if (_finishedLoading && _changeMapCount >= ChangeMapTime + BlackScreenDelay + AdditionalBlackScreenDelay)
|
|
{
|
|
FinishLoading();
|
|
CurrentState = TransitionState.TransitionBlank_1;
|
|
}
|
|
}
|
|
else if (CurrentState == TransitionState.TransitionBlank_1)
|
|
{
|
|
_changeMapCount += Game1.DeltaTime;
|
|
|
|
MapManager.ObjLink.UpdateMapTransitionIn(0);
|
|
|
|
if (_changeMapCount >= ChangeMapTime + BlackScreenDelay * 2 + AdditionalBlackScreenDelay)
|
|
{
|
|
CurrentState = TransitionState.TransitionIn;
|
|
|
|
if (_wobbleTransitionIn)
|
|
_changeMapCount = _wobbleTransitionTime;
|
|
else
|
|
{
|
|
_transitionObject.WobbleTransition = false;
|
|
_changeMapCount = ChangeMapTime;
|
|
}
|
|
}
|
|
}
|
|
else if (CurrentState == TransitionState.TransitionIn)
|
|
{
|
|
_changeMapCount -= Game1.DeltaTime;
|
|
|
|
// update the position of the player to walk into the new room
|
|
var percentage = MathHelper.Clamp(_changeMapCount / ChangeMapTime, 0, 1);
|
|
MapManager.ObjLink.UpdateMapTransitionIn(1 - (float)(Math.Sin(percentage * 1.1) / Math.Sin(1.1)));
|
|
|
|
// slowly increase the volume of the music; the music is only playing
|
|
var newVolume = 1 - percentage;
|
|
if (Game1.GbsPlayer.GetVolumeMultiplier() < 1)
|
|
Game1.GbsPlayer.SetVolumeMultiplier(newVolume);
|
|
|
|
if (!_wobbleTransitionOut && !_knockoutTransition && !_introTransition)
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = percentage;
|
|
|
|
if (_wobbleTransitionOut)
|
|
{
|
|
// fade out to a white screen
|
|
var wobblePercentage = 1 - MathHelper.Clamp((_wobbleTransitionTime - _changeMapCount) / ChangeMapTime, 0, 1);
|
|
_transitionObject.Brightness = wobblePercentage;
|
|
_transitionObject.WobblePercentage = _changeMapCount / _wobbleTransitionTime;
|
|
}
|
|
|
|
// light up the scene
|
|
if (_changeMapCount <= 0)
|
|
{
|
|
_transitionEnded = true;
|
|
Game1.GameManager.SaveManager.SetString("transition_ended", "1");
|
|
|
|
CurrentState = TransitionState.Idle;
|
|
EndTransition();
|
|
}
|
|
}
|
|
|
|
if (_knockoutTransition)
|
|
{
|
|
var percentage = MathHelper.Clamp((_changeMapCount - 100) / (ChangeMapTime - 100), 0, 1);
|
|
_transitionObject.TransitionColor = _nextMapColor * percentage;
|
|
_transitionObject.Percentage = 1;
|
|
|
|
Game1.GameManager.MapManager.UpdateCameraX = false;
|
|
Game1.GameManager.MapManager.UpdateCameraY = false;
|
|
}
|
|
|
|
if (_fullColorMode)
|
|
{
|
|
_transitionObject.Percentage = 1;
|
|
_transitionObject.TransitionColor = _nextMapColor * TransitionPercentage();
|
|
}
|
|
else if (!_knockoutTransition)
|
|
{
|
|
_transitionObject.Percentage = (float)Math.Sin(TransitionPercentage() * Math.PI / 2);
|
|
}
|
|
}
|
|
|
|
public override void Draw(SpriteBatch spriteBatch)
|
|
{
|
|
if (CurrentState == TransitionState.Idle)
|
|
return;
|
|
|
|
_transitionObject.Draw(spriteBatch);
|
|
}
|
|
|
|
public void SetColorMode(Color color, float colorTransparency, bool playerOnTop = true)
|
|
{
|
|
if (colorTransparency > 0)
|
|
CurrentState = TransitionState.ColorMode;
|
|
else
|
|
CurrentState = TransitionState.Idle;
|
|
|
|
_changeMapCount = ChangeMapTime;
|
|
|
|
_transitionObject.TransitionColor = color * colorTransparency;
|
|
|
|
if (playerOnTop)
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = colorTransparency;
|
|
}
|
|
|
|
public bool IsTransitioningOut()
|
|
{
|
|
return CurrentState == TransitionState.TransitionOut;
|
|
}
|
|
|
|
public bool IsTransitioningIn()
|
|
{
|
|
return CurrentState == TransitionState.TransitionIn;
|
|
}
|
|
|
|
private void StartTransition()
|
|
{
|
|
// draw the player on top of everything
|
|
MapManager.ObjLink.StartTransitioning();
|
|
|
|
_introTransition = Game1.GameManager.SaveManager.GetString("played_intro", "0") != "1";
|
|
// dont show the player for the intro sequence transition
|
|
if (!_introTransition)
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = 1.0f;
|
|
}
|
|
|
|
private void EndTransition()
|
|
{
|
|
_knockoutTransition = false;
|
|
|
|
MapManager.ObjLink.EndTransitioning();
|
|
|
|
// start the new music
|
|
Game1.GbsPlayer.SetVolumeMultiplier(1);
|
|
Game1.GbsPlayer.Play();
|
|
|
|
MapManager.Camera.SoftUpdate(Game1.GameManager.MapManager.GetCameraTarget());
|
|
}
|
|
|
|
public float TransitionPercentage()
|
|
{
|
|
return MathHelper.Clamp(_changeMapCount / ChangeMapTime, 0, 1);
|
|
}
|
|
|
|
public void AppendMapChange(string mapName, string position)
|
|
{
|
|
AppendMapChange(mapName, position, false, false, Values.MapTransitionColor, false);
|
|
}
|
|
|
|
public void AppendMapChange(string mapName, string position, bool centerCamera, bool startFromMiddle, Color transitionColor, bool colorMode)
|
|
{
|
|
_nextMapName = mapName;
|
|
_nextMapPosition = position;
|
|
_nextMapCenter = centerCamera;
|
|
_nextMapStartInMiddle = startFromMiddle;
|
|
_nextMapColor = transitionColor;
|
|
_nextColorMode = colorMode;
|
|
|
|
MapManager.ObjLink.OnAppendMapChange();
|
|
}
|
|
|
|
public void LoadMapFromFile(string mapFileName, bool centerCamera, bool startFromMiddle, Color transitionColor, bool colorMode)
|
|
{
|
|
// abort the old loading thread if it is still running
|
|
// TODO: thread abort is not supported so it just waits till the loading is finished
|
|
if (_loadingThread != null && _loadingThread.IsAlive)
|
|
_loadingThread.Join();
|
|
|
|
//Debug.Assert(CurrentState == TransitionState.Idle ||
|
|
// CurrentState == TransitionState.ColorMode, "Tried transition while not in idle");
|
|
|
|
_finishedLoading = false;
|
|
|
|
// only show the opening transition
|
|
if (startFromMiddle)
|
|
{
|
|
_changeMapCount = ChangeMapTime;
|
|
CurrentState = TransitionState.TransitionBlank_0;
|
|
}
|
|
else
|
|
{
|
|
_changeMapCount = 0;
|
|
CurrentState = TransitionState.TransitionOut;
|
|
}
|
|
|
|
// center after loading
|
|
_centerCamera = centerCamera;
|
|
|
|
// add the transition object to the map
|
|
_knockoutTransition = false;
|
|
_fullColorMode = colorMode;
|
|
_nextMapColor = transitionColor;
|
|
|
|
_wobbleTransitionOut = false;
|
|
_wobbleTransitionIn = false;
|
|
|
|
_transitionObject.WobbleTransition = false;
|
|
|
|
_transitionObject.TransitionColor = transitionColor;
|
|
_transitionObject.Percentage = startFromMiddle ? 1 : 0;
|
|
|
|
// start transition
|
|
StartTransition();
|
|
|
|
if (StartDreamTransition)
|
|
{
|
|
StartDreamTransition = false;
|
|
DreamTransition();
|
|
}
|
|
if (StartTeleportTransition)
|
|
{
|
|
StartTeleportTransition = false;
|
|
TeleportTransition();
|
|
}
|
|
|
|
if (StartKnockoutTransition)
|
|
{
|
|
StartKnockoutTransition = false;
|
|
KnockoutTransition();
|
|
}
|
|
|
|
// start loading the new map in a thread
|
|
_loadingThread = new Thread(o => ThreadLoading(mapFileName));
|
|
_loadingThread.Start();
|
|
}
|
|
|
|
public void DreamTransition()
|
|
{
|
|
_transitionObject.WobbleTransition = true;
|
|
_fullColorMode = true;
|
|
_wobbleTransitionOut = true;
|
|
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = 0.0f;
|
|
_nextMapColor = Color.White;
|
|
|
|
// take longer
|
|
_changeMapCount = -DreamTransitionTimeAddition;
|
|
_wobbleTransitionTime = DreamTransitionTimeAddition;
|
|
AdditionalBlackScreenDelay = 500;
|
|
}
|
|
|
|
public void TeleportTransition()
|
|
{
|
|
_transitionObject.WobbleTransition = true;
|
|
_fullColorMode = true;
|
|
_wobbleTransitionOut = true;
|
|
_wobbleTransitionIn = true;
|
|
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = 0.0f;
|
|
_nextMapColor = Color.White;
|
|
|
|
// take longer
|
|
_changeMapCount = -TeleportTransitionTimeAddition;
|
|
_wobbleTransitionTime = TeleportTransitionTimeAddition;
|
|
AdditionalBlackScreenDelay = 500;
|
|
}
|
|
|
|
public void KnockoutTransition()
|
|
{
|
|
_knockoutTransition = true;
|
|
|
|
Game1.GameManager.DrawPlayerOnTopPercentage = 0.0f;
|
|
_nextMapColor = Color.White;
|
|
|
|
// take longer
|
|
AdditionalBlackScreenDelay = 1000;
|
|
}
|
|
|
|
public void ThreadLoading(string mapFileName)
|
|
{
|
|
try
|
|
{
|
|
// @HACK: after loading the map the garbage collector will start and increase the frametime
|
|
// this also leads to the door soundeffect cracking sometimes
|
|
// if we wait a little bit the cracking gets reduced by a lot
|
|
//Thread.Sleep(75);
|
|
|
|
// load the map file
|
|
SaveLoadMap.LoadMap(mapFileName, _gameMapManager.NextMap);
|
|
// create the objects
|
|
_gameMapManager.NextMap.Objects.LoadObjects();
|
|
|
|
_finishedLoading = true;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
#if WINDOWS
|
|
// show the error message instead of just crashing the game
|
|
System.Windows.Forms.MessageBox.Show(exception.StackTrace, exception.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
#endif
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public void FinishLoading()
|
|
{
|
|
AdditionalBlackScreenDelay = 0;
|
|
|
|
// switch to the new map
|
|
var oldMap = _gameMapManager.CurrentMap;
|
|
_gameMapManager.CurrentMap = _gameMapManager.NextMap;
|
|
_gameMapManager.NextMap = oldMap;
|
|
|
|
var currentTrack = Game1.GbsPlayer.CurrentTrack;
|
|
var nextTrack = -1;
|
|
for (var i = 0; i < _gameMapManager.CurrentMap.MapMusic.Length; i++)
|
|
if (_gameMapManager.CurrentMap.MapMusic[i] >= 0)
|
|
nextTrack = _gameMapManager.CurrentMap.MapMusic[i];
|
|
|
|
if (currentTrack != nextTrack)
|
|
Game1.GbsPlayer.Pause();
|
|
|
|
Game1.GameManager.ResetMusic();
|
|
|
|
// finish loading map
|
|
_gameMapManager.FinishLoadingMap(_gameMapManager.CurrentMap);
|
|
|
|
MapManager.ObjLink.UpdateMapTransitionIn(0);
|
|
|
|
// set the new music
|
|
for (var i = 0; i < _gameMapManager.CurrentMap.MapMusic.Length; i++)
|
|
if (_gameMapManager.CurrentMap.MapMusic[i] >= 0)
|
|
Game1.GameManager.SetMusic(_gameMapManager.CurrentMap.MapMusic[i], i, false);
|
|
|
|
// center the camera
|
|
var goalPosition = Game1.GameManager.MapManager.GetCameraTarget();
|
|
if (_centerCamera)
|
|
MapManager.Camera.ForceUpdate(goalPosition);
|
|
else
|
|
MapManager.Camera.SoftUpdate(goalPosition);
|
|
}
|
|
}
|
|
}
|