mirror of
https://github.com/Phantop/LADXHD.git
synced 2024-11-01 04:14:22 +00:00
868 lines
36 KiB
C#
868 lines
36 KiB
C#
|
using System;
|
|||
|
using Microsoft.Xna.Framework;
|
|||
|
using Microsoft.Xna.Framework.Content;
|
|||
|
using Microsoft.Xna.Framework.Graphics;
|
|||
|
using ProjectZ.InGame.Controls;
|
|||
|
using ProjectZ.InGame.GameObjects.Base;
|
|||
|
using ProjectZ.InGame.SaveLoad;
|
|||
|
using ProjectZ.InGame.Things;
|
|||
|
|
|||
|
namespace ProjectZ.InGame.Screens
|
|||
|
{
|
|||
|
public class IntroScreen : Screen
|
|||
|
{
|
|||
|
private Texture2D _sprOcean;
|
|||
|
private Texture2D _sprRain;
|
|||
|
private Texture2D _sprIntro;
|
|||
|
private Texture2D _sprWaves;
|
|||
|
private Texture2D _sprCloud;
|
|||
|
|
|||
|
private Animator _loadingAnimator;
|
|||
|
private Animator _marinAnimator;
|
|||
|
private Animator _linkAnimator;
|
|||
|
private Animator _lightAnimation;
|
|||
|
private Animator _linkBoatAnimator;
|
|||
|
|
|||
|
private Animator[] _thunder = new Animator[2];
|
|||
|
private Vector2[] _thunderPositions = new Vector2[2];
|
|||
|
private float[] _thunderCounts = { 1000, 2000 };
|
|||
|
|
|||
|
private enum States
|
|||
|
{
|
|||
|
OceanCamera,
|
|||
|
OceanPicture,
|
|||
|
OceanThunder,
|
|||
|
StrandFading,
|
|||
|
StrandCamera,
|
|||
|
StrandMarin,
|
|||
|
StrandLogo
|
|||
|
};
|
|||
|
|
|||
|
private States _currentState;
|
|||
|
|
|||
|
private int _scale = 1;
|
|||
|
private Vector2 _cameraCenter;
|
|||
|
private Matrix TransformMatrix =>
|
|||
|
Matrix.CreateTranslation(new Vector3(
|
|||
|
-(float)(Math.Round(_cameraCenter.X * _scale) / _scale),
|
|||
|
-(float)(Math.Round(_cameraCenter.Y * _scale) / _scale), 0)) *
|
|||
|
Matrix.CreateScale(_scale) *
|
|||
|
Matrix.CreateTranslation(new Vector3((int)(Game1.WindowWidth * 0.5f), (int)(Game1.WindowHeight * 0.5f), 0)) * Game1.GetMatrix;
|
|||
|
|
|||
|
private float _cameraState;
|
|||
|
private Vector2 _cameraStart;
|
|||
|
private Vector2 _cameraTarget;
|
|||
|
|
|||
|
private enum MarinState
|
|||
|
{
|
|||
|
WalkSlow,
|
|||
|
Walk,
|
|||
|
Run,
|
|||
|
Stand,
|
|||
|
Hold,
|
|||
|
Push,
|
|||
|
End
|
|||
|
};
|
|||
|
|
|||
|
private MarinState marinState;
|
|||
|
|
|||
|
private MarinState[] _marinStates =
|
|||
|
{
|
|||
|
MarinState.WalkSlow, MarinState.Stand, MarinState.Run, MarinState.Stand, MarinState.Walk, MarinState.Stand, MarinState.Walk, MarinState.Stand, MarinState.Walk, MarinState.Stand,
|
|||
|
MarinState.Hold, MarinState.Push, MarinState.Hold, MarinState.Push, MarinState.Hold, MarinState.Push, MarinState.Hold, MarinState.Push, MarinState.End,
|
|||
|
};
|
|||
|
private int[] _marinTimes = {
|
|||
|
1000, 1100, 900, 1300, 200, // stand times
|
|||
|
2000, 500, 2100, 200, 400, 200, 250, 750 // push hold times
|
|||
|
};
|
|||
|
|
|||
|
private Vector2[] _marinGoalPositions =
|
|||
|
{
|
|||
|
new Vector2(-150, 219), new Vector2(-94, 219), new Vector2(-72, 219), new Vector2(-64, 219),
|
|||
|
new Vector2(-18, 219)
|
|||
|
};
|
|||
|
|
|||
|
private float _marinStateCounter;
|
|||
|
private int _marinIndex;
|
|||
|
private int _marinWalkIndex;
|
|||
|
private int _marinTimeIndex;
|
|||
|
|
|||
|
private readonly Rectangle _oceanCloudRectangle = new Rectangle(0, 0, 32, 32);
|
|||
|
private int _thunderIndex;
|
|||
|
private float _thunderCount = 250;
|
|||
|
private float _thunderTransition;
|
|||
|
|
|||
|
private readonly Rectangle _ocean0Rectangle = new Rectangle(0, 288, 32, 16);
|
|||
|
private readonly Rectangle _ocean1Rectangle = new Rectangle(0, 304, 32, 16);
|
|||
|
private readonly Rectangle _ocean2Rectangle = new Rectangle(0, 320, 32, 16);
|
|||
|
private readonly Rectangle _oceanRectangle = new Rectangle(0, 144, 32, 32);
|
|||
|
|
|||
|
private DictAtlasEntry _spriteOceanBoat;
|
|||
|
|
|||
|
private Vector2 _oceanBoatPosition;
|
|||
|
private Vector2 _oceanPosition0;
|
|||
|
private Vector2 _oceanPosition1;
|
|||
|
private Vector2 _oceanPosition2;
|
|||
|
private Vector2 _oceanPosition3;
|
|||
|
|
|||
|
private readonly int[] _thunderFrame = { 1, 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1, 0 };
|
|||
|
private Color[] _oceanColor = { new Color(0, 32, 168), new Color(32, 32, 168), new Color(96, 96, 232) };
|
|||
|
|
|||
|
private DictAtlasEntry _spriteBackground;
|
|||
|
private DictAtlasEntry _spriteMountain;
|
|||
|
private DictAtlasEntry _spriteLogo0;
|
|||
|
private DictAtlasEntry _spriteLogo1;
|
|||
|
|
|||
|
private readonly Rectangle _treesRectangle = new Rectangle(0, 320, 32, 46);
|
|||
|
private readonly Rectangle _sandRectangle = new Rectangle(0, 364, 32, 16);
|
|||
|
private readonly Rectangle _waveRectangle = new Rectangle(0, 0, 32, 24);
|
|||
|
|
|||
|
private Vector2 _logoPosition;
|
|||
|
private float _logoState;
|
|||
|
private float _logoCounter;
|
|||
|
|
|||
|
private Vector2 _ligthPosition;
|
|||
|
private Vector2[] _lightPositions =
|
|||
|
{
|
|||
|
new Vector2(7, 0),
|
|||
|
new Vector2(41, 0),
|
|||
|
new Vector2(2, 19),
|
|||
|
new Vector2(0, 56),
|
|||
|
new Vector2(34, 9),
|
|||
|
new Vector2(55, 9),
|
|||
|
new Vector2(72, 9),
|
|||
|
new Vector2(96, 9),
|
|||
|
new Vector2(34, 47),
|
|||
|
new Vector2(55, 47),
|
|||
|
new Vector2(72, 47),
|
|||
|
new Vector2(90, 47),
|
|||
|
new Vector2(119, 47),
|
|||
|
};
|
|||
|
private int _lightIndex;
|
|||
|
|
|||
|
private Vector2 _treePosition;
|
|||
|
private Vector2 _mountainRightPosition;
|
|||
|
private Vector2 _mountainLeftPosition;
|
|||
|
private Vector2 _cloundLeftPosition;
|
|||
|
private Vector2 _wavePosition;
|
|||
|
private Vector2 _marinPosition;
|
|||
|
private Vector2 _marinGoal;
|
|||
|
|
|||
|
private int _currentFrame;
|
|||
|
private float _waveCounter;
|
|||
|
|
|||
|
private int _oceanFrameIndex;
|
|||
|
|
|||
|
private float _oceanShoreCounter = 2000;
|
|||
|
|
|||
|
private int _screenWidth = 160;
|
|||
|
private int _screenHeight = 144;
|
|||
|
|
|||
|
private float StrandFadeTime = 600;
|
|||
|
private float _strandFadeCount;
|
|||
|
private float _loadingTransparency = 0.75f;
|
|||
|
|
|||
|
private const int Slow = 500;
|
|||
|
private const int Fast = 200;
|
|||
|
private readonly int[] _waveTimes = { Slow, Fast, Fast, Fast, Slow, Fast, Fast, Fast, Fast, Fast };
|
|||
|
|
|||
|
private bool _loaded;
|
|||
|
|
|||
|
public IntroScreen(string screenId) : base(screenId) { }
|
|||
|
|
|||
|
public override void Load(ContentManager content)
|
|||
|
{
|
|||
|
if (_loaded)
|
|||
|
return;
|
|||
|
_loaded = true;
|
|||
|
|
|||
|
_spriteOceanBoat = Resources.GetSprite("intro_boat");
|
|||
|
|
|||
|
_spriteBackground = Resources.GetSprite("intro_background");
|
|||
|
_spriteMountain = Resources.GetSprite("intro_mountain");
|
|||
|
_spriteLogo0 = Resources.GetSprite("intro_logo_0");
|
|||
|
_spriteLogo1 = Resources.GetSprite("intro_logo_1");
|
|||
|
|
|||
|
_mountainLeftPosition.X = -_spriteBackground.SourceRectangle.Width / 2 - _spriteMountain.SourceRectangle.Width;
|
|||
|
_mountainLeftPosition.Y = 0;
|
|||
|
|
|||
|
_mountainRightPosition.X = _spriteBackground.SourceRectangle.Width / 2;
|
|||
|
_mountainRightPosition.Y = 0;
|
|||
|
|
|||
|
_treePosition.X = 0;
|
|||
|
_treePosition.Y = _spriteBackground.SourceRectangle.Height - 16;
|
|||
|
|
|||
|
_wavePosition.X = _treePosition.X;
|
|||
|
_wavePosition.Y = _treePosition.Y + _treesRectangle.Height + 16;
|
|||
|
|
|||
|
_logoPosition.X = -_spriteBackground.SourceRectangle.Width / 2 + 16;
|
|||
|
_logoPosition.Y = 3;
|
|||
|
|
|||
|
_sprOcean = Resources.GetTexture("ocean.png");
|
|||
|
_sprRain = Resources.GetTexture("rain.png");
|
|||
|
_sprIntro = Resources.GetTexture("intro.png");
|
|||
|
_sprCloud = Resources.GetTexture("cloud.png");
|
|||
|
_sprWaves = Resources.GetTexture("waves.png");
|
|||
|
|
|||
|
_loadingAnimator = AnimatorSaveLoad.LoadAnimator("Intro/loading");
|
|||
|
_loadingAnimator.Play("idle");
|
|||
|
|
|||
|
_thunder[0] = AnimatorSaveLoad.LoadAnimator("Intro/thunder");
|
|||
|
_thunder[1] = AnimatorSaveLoad.LoadAnimator("Intro/thunder");
|
|||
|
|
|||
|
_linkBoatAnimator = AnimatorSaveLoad.LoadAnimator("Intro/link_boat");
|
|||
|
_marinAnimator = AnimatorSaveLoad.LoadAnimator("Intro/maria");
|
|||
|
_linkAnimator = AnimatorSaveLoad.LoadAnimator("Intro/link");
|
|||
|
_lightAnimation = AnimatorSaveLoad.LoadAnimator("Intro/light");
|
|||
|
}
|
|||
|
|
|||
|
public override void OnLoad()
|
|||
|
{
|
|||
|
Init();
|
|||
|
}
|
|||
|
|
|||
|
private void Init()
|
|||
|
{
|
|||
|
_linkAnimator.Play("idle");
|
|||
|
_marinAnimator.Play("walk");
|
|||
|
_lightAnimation.Stop();
|
|||
|
|
|||
|
_currentState = States.OceanCamera;
|
|||
|
_cameraCenter = new Vector2(-220, 55);
|
|||
|
|
|||
|
// start playing the prologue music
|
|||
|
Game1.GameManager.ResetMusic();
|
|||
|
Game1.GameManager.StopMusic();
|
|||
|
Game1.GameManager.SetMusic(25, 0);
|
|||
|
|
|||
|
Game1.GbsPlayer.SetVolumeMultiplier(1.0f);
|
|||
|
Game1.GbsPlayer.Play();
|
|||
|
// play track for 52sec
|
|||
|
#if WINDOWS
|
|||
|
Game1.GbsPlayer.SoundGenerator.SetStopTime(48.75f);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
public override void Update(GameTime gameTime)
|
|||
|
{
|
|||
|
if (Game1.FinishedLoading && Game1.LoadFirstSave)
|
|||
|
{
|
|||
|
Game1.LoadFirstSave = false;
|
|||
|
if (SaveManager.FileExists(Values.PathSaveFolder + "/" + SaveGameSaveLoad.SaveFileName + "0"))
|
|||
|
{
|
|||
|
// change to the game screen
|
|||
|
Game1.ScreenManager.ChangeScreen(Values.ScreenNameGame);
|
|||
|
// load the save
|
|||
|
Game1.GameManager.LoadSaveFile(0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if WINDOWS
|
|||
|
if (Game1.GbsPlayer.SoundGenerator.WasStopped && Game1.GbsPlayer.SoundGenerator.FinishedPlaying())
|
|||
|
{
|
|||
|
Game1.GameManager.SetMusic(0, 0);
|
|||
|
Game1.GbsPlayer.Play();
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (Game1.FinishedLoading &&
|
|||
|
(ControlHandler.ButtonPressed(CButtons.A) || ControlHandler.ButtonPressed(CButtons.Start)))
|
|||
|
Game1.ScreenManager.ChangeScreen(Values.ScreenNameMenu);
|
|||
|
|
|||
|
if (!Game1.FinishedLoading)
|
|||
|
_loadingAnimator.Update();
|
|||
|
if (Game1.FinishedLoading)
|
|||
|
_loadingTransparency = AnimationHelper.MoveToTarget(_loadingTransparency, 0, 0.125f * Game1.TimeMultiplier);
|
|||
|
|
|||
|
UpdateOcean();
|
|||
|
|
|||
|
UpdateBeach();
|
|||
|
|
|||
|
_scale = MathHelper.Clamp(Math.Min(Game1.WindowWidth / _screenWidth, Game1.WindowHeight / _screenHeight), 1, 10);
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateOcean()
|
|||
|
{
|
|||
|
if (_currentState == States.OceanCamera)
|
|||
|
{
|
|||
|
// move the camera to the center
|
|||
|
var goalPosition = new Vector2(0, 55);
|
|||
|
var direction = goalPosition - _cameraCenter;
|
|||
|
if (direction.Length() < Game1.TimeMultiplier * 0.25f)
|
|||
|
{
|
|||
|
_currentState = States.OceanPicture;
|
|||
|
|
|||
|
_linkBoatAnimator.Stop();
|
|||
|
_linkBoatAnimator.Play("run");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
direction.Normalize();
|
|||
|
_cameraCenter += direction * Game1.TimeMultiplier * 0.25f;
|
|||
|
}
|
|||
|
|
|||
|
_thunderIndex = 0;
|
|||
|
for (var i = 0; i < _thunder.Length; i++)
|
|||
|
{
|
|||
|
_thunder[i].Update();
|
|||
|
if (_thunder[i].IsPlaying)
|
|||
|
UpdateThunderIndex(_thunder[i].FrameCounter);
|
|||
|
|
|||
|
_thunderCounts[i] -= Game1.DeltaTime;
|
|||
|
if (_thunderCounts[i] <= 0)
|
|||
|
{
|
|||
|
var animation = Game1.RandomNumber.Next(0, 4);
|
|||
|
_thunder[i].Play("thunder" + animation);
|
|||
|
_thunderCounts[i] = Game1.RandomNumber.Next(2000, 4000);
|
|||
|
|
|||
|
// play sound effect
|
|||
|
Game1.GameManager.PlaySoundEffect("D378-12-0C", true);
|
|||
|
|
|||
|
var randomX = (int)_cameraCenter.X - 150 + Game1.RandomNumber.Next(0, 300);
|
|||
|
if (animation < 2)
|
|||
|
_thunderPositions[i] = new Vector2(randomX, 28);
|
|||
|
else
|
|||
|
_thunderPositions[i] = new Vector2(randomX, 14);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_oceanPosition0 = new Vector2(_cameraCenter.X * 0.1f, 60 + (int)Math.Round(Math.Sin(Game1.TotalTime / 500) * 1));
|
|||
|
_oceanPosition1 = new Vector2(_cameraCenter.X * 0.05f, 60 + (int)Math.Round(Math.Sin(Game1.TotalTime / 500 + 0.1) * 2));
|
|||
|
_oceanPosition2 = new Vector2(-_cameraCenter.X * 0.05f, 60 + (int)Math.Round(Math.Sin(Game1.TotalTime / 500 + 0.2) * 3));
|
|||
|
_oceanPosition3 = new Vector2(-_cameraCenter.X * 0.25f, 60 + (int)Math.Round(Math.Sin(Game1.TotalTime / 500 + 0.2) * 3));
|
|||
|
_oceanBoatPosition = new Vector2(-16 + _cameraCenter.X * 0.05f, 47 + (int)Math.Round(Math.Sin(Game1.TotalTime / 500) * 2.5));
|
|||
|
}
|
|||
|
else if (_currentState == States.OceanPicture)
|
|||
|
{
|
|||
|
_cameraCenter = new Vector2(0, 0);
|
|||
|
|
|||
|
_linkBoatAnimator.Update();
|
|||
|
|
|||
|
if (_oceanFrameIndex != _linkBoatAnimator.CurrentFrameIndex &&
|
|||
|
(_linkBoatAnimator.CurrentFrameIndex == 1 || _linkBoatAnimator.CurrentFrameIndex == 10))
|
|||
|
{
|
|||
|
Game1.GameManager.PlaySoundEffect("D378-12-0C", true);
|
|||
|
}
|
|||
|
|
|||
|
_oceanFrameIndex = _linkBoatAnimator.CurrentFrameIndex;
|
|||
|
|
|||
|
// transition to next state
|
|||
|
if (!_linkBoatAnimator.IsPlaying)
|
|||
|
{
|
|||
|
_currentState = States.OceanThunder;
|
|||
|
_thunderTransition = 0;
|
|||
|
_thunderCount = 250;
|
|||
|
_thunder[0].Play("null");
|
|||
|
}
|
|||
|
}
|
|||
|
else if (_currentState == States.OceanThunder)
|
|||
|
{
|
|||
|
if (_thunderCount < 0)
|
|||
|
{
|
|||
|
_thunder[0].Play("thunderboat");
|
|||
|
|
|||
|
var counter = _thunder[0].FrameCounter;
|
|||
|
UpdateThunderIndex(counter);
|
|||
|
|
|||
|
if (counter > 500)
|
|||
|
{
|
|||
|
_thunderTransition = ((float)counter - 500) / 700f;
|
|||
|
if (_thunderTransition >= 1)
|
|||
|
{
|
|||
|
InitBeach();
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
_thunderCount -= Game1.DeltaTime;
|
|||
|
|
|||
|
_thunder[0].Update();
|
|||
|
|
|||
|
// center the camera
|
|||
|
_cameraCenter = new Vector2(0, 55);
|
|||
|
|
|||
|
_oceanPosition0 = new Vector2(_cameraCenter.X * 0.1f, 60);
|
|||
|
_oceanPosition1 = new Vector2(_cameraCenter.X * 0.05f, 60);
|
|||
|
_oceanPosition2 = new Vector2(-_cameraCenter.X * 0.05f, 60);
|
|||
|
_oceanPosition3 = new Vector2(-_cameraCenter.X * 0.25f, 60);
|
|||
|
_oceanBoatPosition = new Vector2(-16 + _cameraCenter.X * 0.05f, 47);
|
|||
|
|
|||
|
_thunderPositions[0] = new Vector2(-2, -17);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateThunderIndex(double time)
|
|||
|
{
|
|||
|
var index = (int)(time / (2000 / 60.0));
|
|||
|
if (index < _thunderFrame.Length)
|
|||
|
_thunderIndex = _thunderFrame[index];
|
|||
|
}
|
|||
|
|
|||
|
private void InitBeach()
|
|||
|
{
|
|||
|
_currentState = States.StrandFading;
|
|||
|
|
|||
|
_cameraCenter = new Vector2(-400, 210);
|
|||
|
_marinPosition = new Vector2(-250, 219);
|
|||
|
|
|||
|
_marinAnimator.Play("stand");
|
|||
|
_marinAnimator.SpeedMultiplier = 1.0f;
|
|||
|
|
|||
|
_logoState = 0;
|
|||
|
_strandFadeCount = 3700 + StrandFadeTime;
|
|||
|
_marinIndex = 0;
|
|||
|
_marinWalkIndex = 0;
|
|||
|
_marinTimeIndex = 0;
|
|||
|
|
|||
|
NextState();
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateBeach()
|
|||
|
{
|
|||
|
if (_currentState != States.StrandFading && _currentState != States.StrandCamera &&
|
|||
|
_currentState != States.StrandMarin && _currentState != States.StrandLogo)
|
|||
|
return;
|
|||
|
|
|||
|
if (_currentState == States.StrandFading)
|
|||
|
{
|
|||
|
_strandFadeCount -= Game1.DeltaTime;
|
|||
|
|
|||
|
if (_strandFadeCount < StrandFadeTime)
|
|||
|
{
|
|||
|
UpdateMarin();
|
|||
|
}
|
|||
|
|
|||
|
if (_strandFadeCount <= 0)
|
|||
|
{
|
|||
|
_strandFadeCount = 0;
|
|||
|
_currentState = States.StrandCamera;
|
|||
|
}
|
|||
|
}
|
|||
|
// move camera to marin
|
|||
|
else if (_currentState == States.StrandCamera)
|
|||
|
{
|
|||
|
UpdateMarin();
|
|||
|
|
|||
|
// reached marin?
|
|||
|
if (_cameraCenter.X >= _marinPosition.X + 18)
|
|||
|
{
|
|||
|
_currentState = States.StrandMarin;
|
|||
|
}
|
|||
|
}
|
|||
|
// camera follows marin directly
|
|||
|
else if (_currentState == States.StrandMarin)
|
|||
|
{
|
|||
|
UpdateMarin();
|
|||
|
|
|||
|
if (_marinIndex == _marinStates.Length - 1)
|
|||
|
{
|
|||
|
_cameraState = 0;
|
|||
|
_cameraStart = _cameraCenter;
|
|||
|
_cameraTarget = new Vector2(_cameraCenter.X, _logoPosition.Y + _spriteLogo0.ScaledRectangle.Height + 5);
|
|||
|
|
|||
|
_logoCounter = 0;
|
|||
|
_currentState = States.StrandLogo;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (_currentState == States.StrandLogo)
|
|||
|
{
|
|||
|
if (!MoveCamera(0.65f))
|
|||
|
{
|
|||
|
_logoCounter += Game1.DeltaTime;
|
|||
|
|
|||
|
if (_logoCounter > 750 && _logoState != 1)
|
|||
|
{
|
|||
|
_logoState = AnimationHelper.MoveToTarget(_logoState, 1, 0.05f * Game1.TimeMultiplier);
|
|||
|
|
|||
|
if (_logoState == 1)
|
|||
|
Game1.GameManager.PlaySoundEffect("D378-25-19");
|
|||
|
}
|
|||
|
|
|||
|
if (_logoCounter > 1500)
|
|||
|
{
|
|||
|
if (!_lightAnimation.IsPlaying)
|
|||
|
{
|
|||
|
_lightAnimation.Play("idle");
|
|||
|
|
|||
|
_lightIndex = (_lightIndex + Game1.RandomNumber.Next(1, _lightPositions.Length)) % _lightPositions.Length;
|
|||
|
_ligthPosition = _lightPositions[_lightIndex];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_oceanShoreCounter -= Game1.DeltaTime;
|
|||
|
if (_oceanShoreCounter <= 0)
|
|||
|
{
|
|||
|
_oceanShoreCounter += 3500;
|
|||
|
Game1.GameManager.PlaySoundEffect("D378-15-0F");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (_currentState != States.StrandLogo && _strandFadeCount < StrandFadeTime)
|
|||
|
{
|
|||
|
UpdateCamera(new Vector2(_marinPosition.X + 18, 210), _currentState == States.StrandMarin ? 1.0f : 0.75f);
|
|||
|
}
|
|||
|
|
|||
|
_marinAnimator.Update();
|
|||
|
_linkAnimator.Update();
|
|||
|
_lightAnimation.Update();
|
|||
|
|
|||
|
_cloundLeftPosition = new Vector2(-_sprCloud.Width, 47);
|
|||
|
|
|||
|
// update wave animation
|
|||
|
_waveCounter += Game1.DeltaTime;
|
|||
|
if (_waveCounter > _waveTimes[_currentFrame])
|
|||
|
{
|
|||
|
_waveCounter -= _waveTimes[_currentFrame];
|
|||
|
_currentFrame = (_currentFrame + 1) % 10;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateCamera(Vector2 tragetPosition, float maxSpeed)
|
|||
|
{
|
|||
|
var direction = tragetPosition - _cameraCenter;
|
|||
|
if (direction != Vector2.Zero)
|
|||
|
{
|
|||
|
var distance = direction.Length();
|
|||
|
|
|||
|
if (distance <= 0.1f * Game1.TimeMultiplier)
|
|||
|
_cameraCenter = tragetPosition;
|
|||
|
else
|
|||
|
{
|
|||
|
var speedMult = Math.Clamp(CameraFunction(distance / 12.5f), 0, maxSpeed);
|
|||
|
|
|||
|
direction.Normalize();
|
|||
|
var cameraSpeed = direction * speedMult * Game1.TimeMultiplier;
|
|||
|
|
|||
|
_cameraCenter += cameraSpeed;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private float CameraFunction(float x)
|
|||
|
{
|
|||
|
var y = MathF.Atan(x);
|
|||
|
|
|||
|
if (x > 2)
|
|||
|
y += (x - 2) / 2;
|
|||
|
|
|||
|
return y + 0.1f;
|
|||
|
}
|
|||
|
|
|||
|
private bool MoveCamera(float speed)
|
|||
|
{
|
|||
|
if (_cameraCenter == _cameraTarget)
|
|||
|
return false;
|
|||
|
|
|||
|
_cameraState += 0.005f * Game1.TimeMultiplier;
|
|||
|
_cameraState = Math.Clamp(_cameraState, 0, 1);
|
|||
|
|
|||
|
_cameraCenter = Vector2.Lerp(_cameraStart, _cameraTarget, 0.5f + MathF.Sin(-MathF.PI * 0.5f + _cameraState * MathF.PI) * 0.5f);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateMarin()
|
|||
|
{
|
|||
|
if (marinState == MarinState.Stand)
|
|||
|
{
|
|||
|
_marinAnimator.Play("stand");
|
|||
|
|
|||
|
_marinStateCounter -= Game1.DeltaTime;
|
|||
|
if (_marinStateCounter <= 0)
|
|||
|
NextState();
|
|||
|
}
|
|||
|
else if (marinState == MarinState.Walk || marinState == MarinState.WalkSlow)
|
|||
|
{
|
|||
|
_marinAnimator.Play("move");
|
|||
|
|
|||
|
if (_marinPosition.X < _marinGoal.X)
|
|||
|
{
|
|||
|
_marinPosition.X += Game1.TimeMultiplier * (marinState == MarinState.Walk ? 0.5f : 0.25f);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_marinPosition = _marinGoal;
|
|||
|
NextState();
|
|||
|
}
|
|||
|
}
|
|||
|
else if (marinState == MarinState.Run)
|
|||
|
{
|
|||
|
_marinAnimator.SpeedMultiplier = 2.0f;
|
|||
|
_marinAnimator.Play("move");
|
|||
|
|
|||
|
if (_marinPosition.X < _marinGoal.X)
|
|||
|
{
|
|||
|
_marinPosition.X += Game1.TimeMultiplier * 1.0f;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_marinPosition = _marinGoal;
|
|||
|
_marinAnimator.SpeedMultiplier = 1.0f;
|
|||
|
NextState();
|
|||
|
}
|
|||
|
}
|
|||
|
else if (marinState == MarinState.Hold)
|
|||
|
{
|
|||
|
_marinAnimator.Play("hold");
|
|||
|
_linkAnimator.Play("idle");
|
|||
|
|
|||
|
_marinStateCounter -= Game1.DeltaTime;
|
|||
|
if (_marinStateCounter <= 0)
|
|||
|
NextState();
|
|||
|
}
|
|||
|
else if (marinState == MarinState.Push)
|
|||
|
{
|
|||
|
_marinAnimator.Play("push");
|
|||
|
_linkAnimator.Play("pushed");
|
|||
|
|
|||
|
_marinStateCounter -= Game1.DeltaTime;
|
|||
|
if (_marinStateCounter <= 0)
|
|||
|
NextState();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void NextState()
|
|||
|
{
|
|||
|
marinState = _marinStates[_marinIndex];
|
|||
|
_marinIndex++;
|
|||
|
|
|||
|
if (marinState == MarinState.Stand || marinState == MarinState.Hold || marinState == MarinState.Push)
|
|||
|
{
|
|||
|
_marinStateCounter = _marinTimes[_marinTimeIndex];
|
|||
|
_marinTimeIndex++;
|
|||
|
}
|
|||
|
else if (marinState == MarinState.Walk || marinState == MarinState.WalkSlow || marinState == MarinState.Run)
|
|||
|
{
|
|||
|
_marinGoal = _marinGoalPositions[_marinWalkIndex];
|
|||
|
_marinWalkIndex++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public override void Draw(SpriteBatch spriteBatch)
|
|||
|
{
|
|||
|
Game1.Graphics.GraphicsDevice.Clear(_currentState == States.OceanPicture ? Color.Black : new Color(104, 96, 248));
|
|||
|
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointWrap, null, null, null, TransformMatrix);
|
|||
|
|
|||
|
DrawOcean(spriteBatch);
|
|||
|
|
|||
|
DrawBeach(spriteBatch);
|
|||
|
|
|||
|
spriteBatch.End();
|
|||
|
|
|||
|
// draw the loading animation
|
|||
|
if (_loadingTransparency > 0)
|
|||
|
{
|
|||
|
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointWrap, null, null, null, Game1.GetMatrix);
|
|||
|
_loadingAnimator.DrawBasic(spriteBatch, new Vector2(
|
|||
|
Game1.WindowWidth - 2 * _scale, Game1.WindowHeight - 2 * _scale), Color.White * _loadingTransparency, _scale);
|
|||
|
spriteBatch.End();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void DrawOcean(SpriteBatch spriteBatch)
|
|||
|
{
|
|||
|
if (_currentState != States.OceanCamera && _currentState != States.OceanPicture && _currentState != States.OceanThunder)
|
|||
|
return;
|
|||
|
|
|||
|
var screenLeft = (int)Math.Floor(_cameraCenter.X) - (int)Math.Ceiling(Game1.WindowWidth / (double)_scale / 2.0);
|
|||
|
var screenRight = (int)Math.Ceiling(_cameraCenter.X) + (int)Math.Ceiling(Game1.WindowWidth / (double)_scale / 2.0);
|
|||
|
var screenTop = (int)Math.Floor(_cameraCenter.Y) - (int)Math.Ceiling(Game1.WindowHeight / (double)_scale / 2.0);
|
|||
|
var screenBottom = (int)Math.Ceiling(_cameraCenter.Y) + (int)Math.Ceiling(Game1.WindowHeight / (double)_scale / 2.0);
|
|||
|
var width = screenRight - screenLeft + 2;
|
|||
|
var height = screenBottom - screenTop + 2;
|
|||
|
var cloudOffset = _cameraCenter.X * 0.05f;
|
|||
|
|
|||
|
if (_currentState == States.OceanCamera || _currentState == States.OceanThunder)
|
|||
|
{
|
|||
|
// draw the dark cloud
|
|||
|
spriteBatch.Draw(Resources.SprWhite, new Rectangle(screenLeft, screenTop, width, -screenTop), new Color(24, 56, 40));
|
|||
|
|
|||
|
// draw the clouds
|
|||
|
spriteBatch.Draw(_sprOcean,
|
|||
|
new Rectangle(screenLeft, 0, width, _oceanCloudRectangle.Height),
|
|||
|
new Rectangle(_oceanCloudRectangle.X + screenLeft - (int)cloudOffset,
|
|||
|
_oceanCloudRectangle.Y + _thunderIndex * (_oceanCloudRectangle.Height + 16), width,
|
|||
|
_oceanCloudRectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - cloudOffset % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the dark sky
|
|||
|
spriteBatch.Draw(Resources.SprWhite, new Rectangle(screenLeft, _oceanCloudRectangle.Height, width, 64), _oceanColor[_thunderIndex]);
|
|||
|
|
|||
|
// draw the ocean top
|
|||
|
var oceanAnimationOffset = _thunderIndex * 64;
|
|||
|
spriteBatch.Draw(_sprOcean,
|
|||
|
new Rectangle(screenLeft, (int)_oceanPosition0.Y, width, _ocean0Rectangle.Height),
|
|||
|
new Rectangle(_ocean0Rectangle.X + screenLeft - (int)_oceanPosition0.X,
|
|||
|
_ocean0Rectangle.Y + oceanAnimationOffset, width, _ocean0Rectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - _oceanPosition0.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the ocean middle
|
|||
|
spriteBatch.Draw(_sprOcean,
|
|||
|
new Rectangle(screenLeft, (int)_oceanPosition1.Y, width, _ocean1Rectangle.Height),
|
|||
|
new Rectangle(_ocean1Rectangle.X + screenLeft - (int)_oceanPosition1.X,
|
|||
|
_ocean1Rectangle.Y + oceanAnimationOffset, width, _ocean1Rectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - _oceanPosition1.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the boat
|
|||
|
DrawHelper.DrawNormalized(spriteBatch, _spriteOceanBoat, _oceanBoatPosition, Color.White);
|
|||
|
|
|||
|
// draw the ocean middle
|
|||
|
spriteBatch.Draw(_sprOcean,
|
|||
|
new Rectangle(screenLeft, (int)_oceanPosition2.Y, width, _ocean2Rectangle.Height),
|
|||
|
new Rectangle(_ocean2Rectangle.X + screenLeft - (int)_oceanPosition2.X,
|
|||
|
_ocean2Rectangle.Y + oceanAnimationOffset, width, _ocean2Rectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - _oceanPosition2.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the ocean
|
|||
|
spriteBatch.Draw(_sprOcean,
|
|||
|
new Rectangle(screenLeft, (int)_oceanPosition3.Y + 16, width, _oceanRectangle.Height),
|
|||
|
new Rectangle(_oceanRectangle.X + screenLeft - (int)_oceanPosition3.X,
|
|||
|
_oceanRectangle.Y + _thunderIndex * (_oceanRectangle.Height + 16), width, _oceanRectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - _oceanPosition3.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the dark ocean
|
|||
|
spriteBatch.Draw(Resources.SprWhite,
|
|||
|
new Rectangle(screenLeft, (int)_oceanPosition3.Y + 48, width,
|
|||
|
screenBottom - ((int)_oceanPosition3.Y + 48)), new Color(16, 0, 104));
|
|||
|
}
|
|||
|
|
|||
|
if (_currentState == States.OceanPicture)
|
|||
|
{
|
|||
|
_linkBoatAnimator.Draw(spriteBatch, Vector2.Zero, Color.White);
|
|||
|
}
|
|||
|
|
|||
|
// draw the rain
|
|||
|
var rainOffset = new Vector2((float)(Game1.TotalTime / 2.5f + Math.Sin(Game1.TotalTime / 500) * 5), (float)Game1.TotalTime / 2.3f);
|
|||
|
spriteBatch.Draw(_sprRain,
|
|||
|
new Rectangle(screenLeft, screenTop, width, height),
|
|||
|
new Rectangle(screenLeft - (int)rainOffset.X, screenTop - (int)rainOffset.Y, width, height),
|
|||
|
Color.White, 0, new Vector2(1 - rainOffset.X % 1, 1 - rainOffset.Y % 1), SpriteEffects.None, 0);
|
|||
|
|
|||
|
if (_currentState == States.OceanCamera)
|
|||
|
{
|
|||
|
// draw the thunder
|
|||
|
for (var i = 0; i < _thunder.Length; i++)
|
|||
|
_thunder[i].DrawBasic(spriteBatch, _thunderPositions[i] + new Vector2(cloudOffset, 0), Color.White);
|
|||
|
}
|
|||
|
else if (_currentState == States.OceanThunder)
|
|||
|
{
|
|||
|
// draw the thunder on top of the boat
|
|||
|
_thunder[0].DrawBasic(spriteBatch, _thunderPositions[0] + new Vector2(cloudOffset, 0), Color.White);
|
|||
|
|
|||
|
if (_thunderTransition > 0)
|
|||
|
{
|
|||
|
var white = MathHelper.Clamp(_thunderTransition * 1.5f, 0, 1);
|
|||
|
spriteBatch.Draw(Resources.SprWhite, new Rectangle(screenLeft, screenTop, width, height), Color.White * white);
|
|||
|
|
|||
|
// draw the boat
|
|||
|
var boatWhite = MathHelper.Clamp(1.5f - _thunderTransition * 1.5f, 0, 1);
|
|||
|
DrawHelper.DrawNormalized(spriteBatch, _spriteOceanBoat, _oceanBoatPosition, Color.White * boatWhite);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//spriteBatch.Draw(Resources.SprWhite, new Rectangle(-2, 72, 4, 4), Color.Red);
|
|||
|
}
|
|||
|
|
|||
|
private void DrawBeach(SpriteBatch spriteBatch)
|
|||
|
{
|
|||
|
if (_currentState != States.StrandFading && _currentState != States.StrandCamera &&
|
|||
|
_currentState != States.StrandMarin && _currentState != States.StrandLogo)
|
|||
|
return;
|
|||
|
|
|||
|
var screenLeft = (int)Math.Floor(_cameraCenter.X) - (int)Math.Ceiling(Game1.WindowWidth / (double)_scale / 2.0);
|
|||
|
var screenRight = (int)Math.Ceiling(_cameraCenter.X) + (int)Math.Ceiling(Game1.WindowWidth / (double)_scale / 2.0);
|
|||
|
var screenTop = (int)Math.Floor(_cameraCenter.Y) - (int)Math.Ceiling(Game1.WindowHeight / (double)_scale / 2.0);
|
|||
|
var screenBottom = (int)Math.Ceiling(_cameraCenter.Y) + (int)Math.Ceiling(Game1.WindowHeight / (double)_scale / 2.0);
|
|||
|
var width = screenRight - screenLeft + 2;
|
|||
|
var height = screenBottom - screenTop + 1;
|
|||
|
|
|||
|
// draw the sky white
|
|||
|
spriteBatch.Draw(Resources.SprWhite, new Rectangle(
|
|||
|
screenLeft, screenTop, width, -screenTop + 47), new Color(248, 248, 248));
|
|||
|
|
|||
|
var mountainOffset = new Vector2((float)(Math.Round(_cameraCenter.X * 0.5f * _scale) / _scale), 0);
|
|||
|
|
|||
|
// draw the clouds on the left
|
|||
|
var cloudLeft = -_spriteBackground.ScaledRectangle.Width / 2;
|
|||
|
if (screenLeft < cloudLeft + (int)mountainOffset.X)
|
|||
|
spriteBatch.Draw(_sprCloud,
|
|||
|
new Rectangle(screenLeft, (int)_cloundLeftPosition.Y, (cloudLeft + (int)mountainOffset.X) - screenLeft, _sprCloud.Height),
|
|||
|
new Rectangle(screenLeft - (int)mountainOffset.X, 0, (cloudLeft + (int)mountainOffset.X) - screenLeft, _sprCloud.Height),
|
|||
|
Color.White, 0, new Vector2(-mountainOffset.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the clouds on the right
|
|||
|
var cloudRight = _spriteBackground.ScaledRectangle.Width / 2;
|
|||
|
if (cloudRight + (int)mountainOffset.X < screenRight)
|
|||
|
spriteBatch.Draw(_sprCloud,
|
|||
|
new Rectangle(cloudRight + (int)mountainOffset.X, (int)_cloundLeftPosition.Y, screenRight - (cloudRight + (int)mountainOffset.X), _sprCloud.Height),
|
|||
|
new Rectangle(0, 0, screenRight - (cloudRight + (int)mountainOffset.X), _sprCloud.Height),
|
|||
|
Color.White, 0, new Vector2(-mountainOffset.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the top of the mountain
|
|||
|
spriteBatch.Draw(_sprIntro, new Vector2(-_spriteBackground.ScaledRectangle.Width / 2, 0) + mountainOffset, _spriteBackground.ScaledRectangle, Color.White);
|
|||
|
|
|||
|
// draw the left side of the mountain
|
|||
|
spriteBatch.Draw(_sprIntro, _mountainLeftPosition + mountainOffset, _spriteMountain.SourceRectangle,
|
|||
|
Color.White, 0, Vector2.Zero, 1, SpriteEffects.FlipHorizontally, 0);
|
|||
|
|
|||
|
// draw the right side of the mountain
|
|||
|
spriteBatch.Draw(_sprIntro, _mountainRightPosition + mountainOffset, _spriteMountain.SourceRectangle, Color.White);
|
|||
|
|
|||
|
// draw the trees
|
|||
|
var treeOffset = new Vector2(_cameraCenter.X * 0.075f, 0);
|
|||
|
spriteBatch.Draw(_sprWaves,
|
|||
|
new Rectangle(screenLeft, (int)_treePosition.Y, width, _treesRectangle.Height),
|
|||
|
new Rectangle(_treesRectangle.X + screenLeft - (int)treeOffset.X, _treesRectangle.Y, width, _treesRectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - treeOffset.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the strand
|
|||
|
var strandOffset = new Vector2(-_cameraCenter.X * 0.025f, 0);
|
|||
|
spriteBatch.Draw(_sprWaves,
|
|||
|
new Rectangle(screenLeft, (int)_treePosition.Y + _treesRectangle.Height, width, _sandRectangle.Height),
|
|||
|
new Rectangle(_sandRectangle.X + screenLeft - (int)strandOffset.X, _sandRectangle.Y, width, _sandRectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - strandOffset.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw the waves
|
|||
|
spriteBatch.Draw(_sprWaves,
|
|||
|
new Rectangle(screenLeft, (int)_wavePosition.Y, width, _waveRectangle.Height),
|
|||
|
new Rectangle(_waveRectangle.X + screenLeft - (int)strandOffset.X, _waveRectangle.Y + _currentFrame * 32, width, _waveRectangle.Height),
|
|||
|
Color.White, 0, new Vector2(1 - strandOffset.X % 1, 0), SpriteEffects.None, 0);
|
|||
|
|
|||
|
// draw marin
|
|||
|
_marinAnimator.DrawBasic(spriteBatch, _marinPosition, Color.White);
|
|||
|
|
|||
|
// draw link
|
|||
|
_linkAnimator.DrawBasic(spriteBatch, new Vector2(-8, 225), Color.White);
|
|||
|
|
|||
|
// draw the logo
|
|||
|
{
|
|||
|
var logoHeight = (int)(_spriteLogo0.SourceRectangle.Height * (MathF.Sin(_logoState * MathF.PI - MathF.PI / 2) * 0.5f + 0.5f));
|
|||
|
logoHeight += logoHeight % 2;
|
|||
|
|
|||
|
spriteBatch.Draw(_spriteLogo0.Texture,
|
|||
|
new Rectangle((int)_logoPosition.X, (int)_logoPosition.Y + _spriteLogo0.SourceRectangle.Height / 2 - logoHeight / 2,
|
|||
|
_spriteLogo0.SourceRectangle.Width, logoHeight), _spriteLogo0.ScaledRectangle, Color.White);
|
|||
|
|
|||
|
var textTransparency = Math.Clamp((_logoState - 0.5f) * 2, 0, 1);
|
|||
|
DrawHelper.DrawNormalized(spriteBatch, _spriteLogo1, _logoPosition, Color.White * textTransparency);
|
|||
|
}
|
|||
|
|
|||
|
var lightPosition = _logoPosition + _ligthPosition;
|
|||
|
|
|||
|
// draw the light around the logo
|
|||
|
if (_lightAnimation.IsPlaying)
|
|||
|
_lightAnimation.DrawBasic(spriteBatch, lightPosition, Color.White);
|
|||
|
|
|||
|
// draw the white forground for the fadein
|
|||
|
if (_strandFadeCount > 0)
|
|||
|
{
|
|||
|
var white = MathHelper.Clamp(_strandFadeCount / StrandFadeTime, 0, 1);
|
|||
|
spriteBatch.Draw(Resources.SprWhite, new Rectangle(screenLeft, screenTop, width, height), Color.White * white);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|