/** * Snowstorm ManiaScript for creating a nice snowstorm effect on the ManiaLink. * * @author Marcel * @license http://opensource.org/licenses/GPL-2.0 GPL v2 * @see https://github.com/BluePsyduck/Misc/wiki/ManiaScript-Snowstorm */ #Include "MathLib" as MathLib /** @var The global speed of all Snowflakes. */ declare Vec2 _Snowstorm_GlobalSpeed; /** @var The Snowflake instances. */ declare CMlControl[] _Snowstorm_Snowflakes; /** @var The last time when the Snowstorm was drawn. */ declare Integer _Snowstorm_LastTime; /** @var Whether the speed should be adjusted to the current mouse position. */ declare Boolean _Snowstorm_FollowMouse; /** * Returns the absolute value. * @param _Number The number. * @return The absolute number. */ Real _Snowstorm_Abs(Real _Number) { if (_Number < 0) { return -_Number; } return _Number; } /** * Returns the sign of the number. * @param _Number The number. * @return 1 when the number is positive, -1 when negative, and 0 otherwise. */ Integer _Snowstorm_Sgn(Real _Number) { if (_Number < 0) { return -1; } else if (_Number > 0) { return 1; } return 0; } /** * Checks whether the Snowflake is already out of the screen. * @param _Snowflake The snowflake to check. * @return The result of the check. */ Boolean _Snowflake_IsOutOfBounds(CMlControl _Snowflake) { return (_Snowstorm_Abs(_Snowflake.PosnX) > 170) || (_Snowstorm_Abs(_Snowflake.PosnY) > 100); } /** * Randomizes the position of the Snowflake, setting it to a border of the screen. * @param _Snowflake The snowflake. */ Void _Snowflake_RandomizePosition(CMlControl _Snowflake) { declare Real Rand = MathLib::Rand(-200., 340.); if (Rand < 0) { // Snowlfake begins at side border _Snowflake.PosnX = _Snowstorm_Sgn(_Snowstorm_GlobalSpeed.X) * -170.; _Snowflake.PosnY = Rand + 100.; } else { // Snowflake begins on top _Snowflake.PosnX = Rand - 160.; _Snowflake.PosnY = 100.; } } /** * Randomizes the position of the Snowflake using the whole screen. * @param _Snowflake The snowflake. */ Void _Snowflake_RandomizePositionFull(CMlControl _Snowflake) { _Snowflake.PosnX = MathLib::Rand(-170., 170.); _Snowflake.PosnY = MathLib::Rand(-100., 100.); } /** * Randomizes the custom speed of the Snowflake. * @param _Snowflake The snowflake. */ Void _Snowflake_RandomizeSpeed(CMlControl _Snowflake) { declare Vec2 Snowstorm_Speed as Speed for _Snowflake; Speed = < MathLib::Rand(-5., 5.), MathLib::Rand(-5., 5.) >; } /** * Draws the current state of the Snowflake. * @param _Snowflake The snowflake. * @param _DeltaTime The time difference to the last call of Draw, in milliseconds. */ Void _Snowflake_Draw(CMlControl _Snowflake, Integer _DeltaTime) { declare Real Delta = _DeltaTime / 1000.; declare Vec2 Snowstorm_Speed as CustomSpeed for _Snowflake; declare Vec2 TotalSpeed = _Snowstorm_GlobalSpeed + CustomSpeed; _Snowflake.RelativePosition += ; if (_Snowflake_IsOutOfBounds(_Snowflake)) { _Snowflake_RandomizePosition(_Snowflake); _Snowflake_RandomizeSpeed(_Snowflake); } } /** * Sets the global falling speed of the Snowflakes. * * @param SpeedX The horizontal speed of the Snowflakes. * @param SpeedY The vertical speed of the Snowflakes. */ Void _Snowstorm_SetGlobalSpeed(Integer _SpeedX, Integer _SpeedY) { _Snowstorm_GlobalSpeed = <_SpeedX * 1., _SpeedY * 1.>; } /** * Creates a new Snowflake instance. * @param Target The target Control, which visualizes the Snowflake. * @return The snowflake. */ CMlControl _Snowflake_Create(CMlControl _Target) { _Snowflake_RandomizePositionFull(_Target); _Snowflake_RandomizeSpeed(_Target); return _Target; } /** * Sets a random speed for the Snowflakes. */ Void Snowstorm_RandomizeGlobalSpeed() { declare Integer SpeedX = MathLib::Rand(25, 75); declare Integer SpeedY = MathLib::Rand(-75, -25); if (MathLib::Rand(0, 1) == 0) { SpeedX = -SpeedX; } _Snowstorm_SetGlobalSpeed(SpeedX, SpeedY); } /** * Specifies whether the Snowflakes should follow the mouse cursor. * * @param FollowMouse The value to be set. */ Void Snowstorm_SetFollowMouse(Boolean _FollowMouse) { _Snowstorm_FollowMouse = _FollowMouse; } /** * Initializes the Snowflakes. * @param Container The Frame holding the Controls, representing the Snowflakes. */ Void Snowstorm_Initialize(CMlFrame _Container) { foreach (Control in _Container.Controls) { _Snowstorm_Snowflakes.add(_Snowflake_Create(Control)); Snowstorm_RandomizeGlobalSpeed(); _Snowstorm_LastTime = Now; } } Void Snowstorm_Initialize() { Snowstorm_Initialize(Page.GetFirstChild("snowstorm") as CMlFrame); } /** * Animates the Snowstorm, letting all Snowflakes redraw. */ Void Snowstorm_Animate() { if (_Snowstorm_FollowMouse && MouseX > -1000. && MouseY > -1000.) { declare Integer SpeedX = MathLib::NearestInteger(MouseX / 160 * 75); declare Integer SpeedY = MathLib::NearestInteger((MouseY - 90) / 180 * 50 - 25); _Snowstorm_SetGlobalSpeed(SpeedX, SpeedY); } declare Integer DeltaTime = Now - _Snowstorm_LastTime; foreach (Snowflake in _Snowstorm_Snowflakes) { _Snowflake_Draw(Snowflake, DeltaTime); } _Snowstorm_LastTime = Now; }