Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Monofoxe/Monofoxe.Engine/GameMgr.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using Monofoxe.Engine.Drawing;
using Monofoxe.Engine.SceneSystem;
using Monofoxe.Engine.Utils;
using System;
using System.Collections.Generic;
using System.Reflection;
Expand Down Expand Up @@ -99,6 +100,7 @@ public static void Init(Game game)
var keyboardBind = StuffResolver.GetStuff<ITextInputBinder>();
keyboardBind?.Init();

/*PerlinNoise.Seed = RandomExt.Global.Next*/

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove


Input.MaxGamepadCount = 2;

Expand Down
136 changes: 136 additions & 0 deletions Monofoxe/Monofoxe.Engine/Shake/BounceShake.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/////////////////////////////////////////////////////////////////////////////////////////////
/// Original Unity version made by Ivan Pensionerov https://github.com/gasgiant/Camera-Shake
/// Ported and improved by Minkberry.
/////////////////////////////////////////////////////////////////////////////////////////////
using Monofoxe.Engine.Shake.Utils;
using Microsoft.Xna.Framework;
using Monofoxe.Engine.Utils;

namespace Monofoxe.Engine.Shake
{
public class BounceShake : IShake
{
private readonly Params _pars;
private readonly Easing _moveCurve = Easing.EaseInOutCubic;
private readonly Vector2? _sourcePosition = null;

private float _attenuation = 1;
private Displacement _direction;
private Displacement _previousWaypoint;
private Displacement _currentWaypoint;
private int _bounceIndex;
private float _t;


/// <summary>
/// Creates an instance of BounceShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
public BounceShake(Params parameters, Vector2? sourcePosition = null)
{
_sourcePosition = sourcePosition;
_pars = parameters;
Displacement rnd = Displacement.InsideUnitSpheres();
_direction = Displacement.Scale(rnd, _pars.AxesMultiplier).Normalized;
}


/// <summary>
/// Creates an instance of BounceShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="initialDirection">Initial direction of the shake motion.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
public BounceShake(Params parameters, Displacement initialDirection, Vector2? sourcePosition = null)
{
_sourcePosition = sourcePosition;
_pars = parameters;
_direction = Displacement.Scale(initialDirection, _pars.AxesMultiplier).Normalized;
}


public Displacement CurrentDisplacement { get; private set; }
public bool IsFinished { get; private set; }


public void Initialize(Vector2 cameraPosition, float cameraRotation)
{
_attenuation = _sourcePosition == null ?
1 : _pars.Attenuation.Attenuate(_sourcePosition.Value, cameraPosition);
_currentWaypoint = _attenuation * _direction.ScaledBy(_pars.PositionStrength, _pars.RotationStrength);
}


public void Update(TimeKeeper time, Vector2 cameraPosition, float cameraRotation)
{
if (_t < 1)
{
_t += (float)time.Time() * _pars.Frequence;
if (_pars.Frequence == 0) _t = 1;

CurrentDisplacement = Displacement.Lerp(_previousWaypoint, _currentWaypoint,
_moveCurve.GetEasing(_t));
}
else
{
_t = 0;
CurrentDisplacement = _currentWaypoint;
_previousWaypoint = _currentWaypoint;
_bounceIndex++;
if (_bounceIndex > _pars.NumBounces)
{
IsFinished = true;
return;
}

Displacement rnd = Displacement.InsideUnitSpheres();
_direction = -_direction
+ _pars.Randomness * Displacement.Scale(rnd, _pars.AxesMultiplier).Normalized;
_direction = _direction.Normalized;
float decayValue = 1 - (float)_bounceIndex / _pars.NumBounces;
_currentWaypoint = decayValue * decayValue * _attenuation
* _direction.ScaledBy(_pars.PositionStrength, _pars.RotationStrength);
}
}


public class Params
{
/// <summary>
/// Strength of the shake for positional axes.
/// </summary>
public float PositionStrength = 0.05f;

/// <summary>
/// Strength of the shake for rotational axes.
/// </summary>
public float RotationStrength = 0.1f;

/// <summary>
/// Preferred direction of shaking.
/// </summary>
public Displacement AxesMultiplier = new Displacement(Vector2.One, 0);

/// <summary>
/// Frequency of shaking.
/// </summary>
public float Frequence = 25;

/// <summary>
/// Number of vibrations before stop.
/// </summary>
public int NumBounces = 5;

/// <summary>
/// Randomness of motion.
/// </summary>
public float Randomness = 0.5f;

/// <summary>
/// How strength falls with distance from the shake source.
/// </summary>
public Attenuation Attenuation = new Attenuation();
}
}
}
33 changes: 33 additions & 0 deletions Monofoxe/Monofoxe.Engine/Shake/IShake.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/////////////////////////////////////////////////////////////////////////////////////////////
/// Original Unity version made by Ivan Pensionerov https://github.com/gasgiant/Camera-Shake
/// Ported and improved by Minkberry.
/////////////////////////////////////////////////////////////////////////////////////////////
using Monofoxe.Engine.Shake.Utils;
using Microsoft.Xna.Framework;
using Monofoxe.Engine.Utils;

namespace Monofoxe.Engine.Shake
{
public interface IShake
{
/// <summary>
/// Represents current position and rotation of the camera according to the shake.
/// </summary>
Displacement CurrentDisplacement { get; }

/// <summary>
/// Shake system will dispose the shake on the first frame when this is true.
/// </summary>
bool IsFinished { get; }

/// <summary>
/// Shaker calls this when the shake is added to the list of active shakes.
/// </summary>
void Initialize(Vector2 cameraPosition, float cameraRotation);

/// <summary>
/// Shaker calls this every frame on active shakes.
/// </summary>
void Update(TimeKeeper time, Vector2 cameraPosition, float cameraRotation);
}
}
145 changes: 145 additions & 0 deletions Monofoxe/Monofoxe.Engine/Shake/PerlinShake.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/////////////////////////////////////////////////////////////////////////////////////////////
/// Original Unity version made by Ivan Pensionerov https://github.com/gasgiant/Camera-Shake
/// Ported and improved by Minkberry.
/////////////////////////////////////////////////////////////////////////////////////////////
using Microsoft.Xna.Framework;
using Monofoxe.Engine.Utils;
using Monofoxe.Engine.Shake.Utils;

namespace Monofoxe.Engine.Shake
{
public class PerlinShake : IShake
{
private readonly Params _pars;
private readonly Envelope _envelope;

public IAmplitudeController AmplitudeController;

private Vector2[] _seeds;
private float _t;
private Vector2? _sourcePosition;
private float _norm;

/// <summary>
/// Creates an instance of PerlinShake.
/// </summary>
/// <param name="parameters">Parameters of the shake.</param>
/// <param name="maxAmplitude">Maximum amplitude of the shake.</param>
/// <param name="sourcePosition">World position of the source of the shake.</param>
/// <param name="manualStrengthControl">Pass true if you want to control amplitude manually.</param>
public PerlinShake(
Params parameters,
float maxAmplitude = 1,
Vector2? sourcePosition = null,
bool manualStrengthControl = false
)
{
_pars = parameters;
_envelope = new Envelope(_pars.Envelope, maxAmplitude,
manualStrengthControl ?
Envelope.EnvelopeControlMode.Manual : Envelope.EnvelopeControlMode.Auto);
AmplitudeController = _envelope;
_sourcePosition = sourcePosition;
}


public Displacement CurrentDisplacement { get; private set; }
public bool IsFinished { get; private set; }


public void Initialize(Vector2 cameraPosition, float cameraRotation)
{
_seeds = new Vector2[_pars.NoiseModes.Length];
_norm = 0;
for (int i = 0; i < _seeds.Length; i++)
{
_seeds[i] = RandomExt.Global.NextInsideUnitCircle() * 20;
_norm += _pars.NoiseModes[i].Amplitude;
}
}


public void Update(TimeKeeper time, Vector2 cameraPosition, float cameraRotation)
{
if (_envelope.IsFinished)
{
IsFinished = true;
return;
}
_t += (float)time.Time();
_envelope.Update((float)time.Time());

Displacement disp = Displacement.Zero;
for (int i = 0; i < _pars.NoiseModes.Length; i++)
{
disp += _pars.NoiseModes[i].Amplitude / _norm
* SampleNoise(_seeds[i], _pars.NoiseModes[i].Frequence);
}

CurrentDisplacement = _envelope.Intensity * Displacement.Scale(disp, _pars.Strength);
if (_sourcePosition != null)
{
CurrentDisplacement *= _pars.Attenuation.Attenuate(_sourcePosition.Value, cameraPosition);
}
}


private Displacement SampleNoise(Vector2 seed, float freq)
{
var position = new Vector2(
PerlinNoise.CarmodyNoise(seed.X + _t * freq, seed.Y),
PerlinNoise.CarmodyNoise(seed.X, seed.Y + _t * freq)
);
position -= Vector2.One * 0.5f;

var rotation = PerlinNoise.CarmodyNoise(-seed.X - _t * freq, -seed.Y - _t * freq);
rotation -= 0.5f;

return new Displacement(position, rotation);
}


public class Params
{
/// <summary>
/// Strength of the shake for each axis.
/// </summary>
public Displacement Strength = new Displacement(Vector2.Zero, 0.8f);

/// <summary>
/// Layers of perlin noise with different frequencies.
/// </summary>
public NoiseMode[] NoiseModes = { new NoiseMode(12, 1) };

/// <summary>
/// Strength over time.
/// </summary>
public Envelope.EnvelopeParams Envelope;

/// <summary>
/// How strength falls with distance from the shake source.
/// </summary>
public Attenuation Attenuation = new Attenuation();
}


public struct NoiseMode
{
public NoiseMode(float freq, float amplitude)
{
Frequence = freq;
Amplitude = amplitude;
}

/// <summary>
/// Frequency multiplier for the noise.
/// </summary>
public float Frequence;

/// <summary>
/// Amplitude of the mode. Ranges from 0 to 1.
/// </summary>
public float Amplitude;
}
}
}
43 changes: 43 additions & 0 deletions Monofoxe/Monofoxe.Engine/Shake/Presets/DirectionalShakePreset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/////////////////////////////////////////////////////////////////////////////////////////////
/// Original Unity version made by Ivan Pensionerov https://github.com/gasgiant/Camera-Shake
/// Ported and improved by Minkberry.
/////////////////////////////////////////////////////////////////////////////////////////////
using Monofoxe.Engine.Shake.Utils;
using Microsoft.Xna.Framework;

namespace Monofoxe.Engine.Shake.Presets
{
/// <summary>
/// Preset for bounce shake.
/// Suitable for short and snappy shakes. Moves camera in X and Y axes and rotates it in Z axis.
/// </summary>
public class DirectionalShakePreset : ShakePreset
{
public float PositionStrength = 10f;
public float RotationStrength = 0.02f;

public float Frequency = 25;

/// <summary>
/// Number of vibrations before stop.
/// </summary>
public int BounceCount = 5;

public Vector2 Direction = Vector2.UnitX;


public override IShake CreateShake()
{
var pars = new BounceShake.Params
{
PositionStrength = PositionStrength,
RotationStrength = RotationStrength,
Frequence = Frequency,
NumBounces = BounceCount,
Attenuation = Attenuation
};

return new BounceShake(pars, new Displacement(Direction), UsesAttenuation ? (Vector2?)SourcePosition : null);
}
}
}
Loading