1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-12 11:47:24 +08:00
osu-lazer/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyCursorStarParticles.cs

232 lines
7.2 KiB
C#
Raw Normal View History

2021-09-05 03:49:05 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Bindings;
using osu.Framework.Utils;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Particles;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Screens.Play;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Rulesets.Osu.Skinning.Legacy
{
public class LegacyCursorStarParticles : BeatSyncedContainer, IKeyBindingHandler<OsuAction>
{
private StarParticleSpewer breakSpewer;
private StarParticleSpewer kiaiSpewer;
[Resolved(canBeNull: true)]
private Player player { get; set; }
[Resolved(canBeNull: true)]
private OsuPlayfield osuPlayfield { get; set; }
[BackgroundDependencyLoader]
private void load(ISkinSource skin, OsuColour colour)
{
var texture = skin.GetTexture("star2");
InternalChildren = new[]
{
breakSpewer = new StarParticleSpewer(texture, 20)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = colour.PinkLighter,
Direction = SpewDirection.None,
Active =
{
Value = false,
2021-09-05 03:49:05 +08:00
}
},
kiaiSpewer = new StarParticleSpewer(texture, 60)
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Colour = colour.PinkLighter,
Direction = SpewDirection.None,
Active =
{
Value = false,
}
},
};
if (player != null)
{
breakSpewer.Active.BindTarget = player.IsBreakTime;
}
if (osuPlayfield != null)
{
breakSpewer.ParticleParent = osuPlayfield;
kiaiSpewer.ParticleParent = osuPlayfield;
}
2021-09-05 03:49:05 +08:00
}
protected override void Update()
{
if (osuPlayfield == null) return;
// find active kiai slider or spinner.
var kiaiHitObject = osuPlayfield.HitObjectContainer.AliveObjects.FirstOrDefault(h =>
h.HitObject.Kiai &&
(
(h is DrawableSlider slider && slider.Tracking.Value) ||
(h is DrawableSpinner spinner && spinner.RotationTracker.Tracking)
)
);
kiaiSpewer.Active.Value = kiaiHitObject != null;
}
public bool OnPressed(OsuAction action)
{
handleInput(action, true);
return false;
}
public void OnReleased(OsuAction action)
{
handleInput(action, false);
}
private bool leftPressed;
private bool rightPressed;
private void handleInput(OsuAction action, bool pressed)
{
switch (action)
{
case OsuAction.LeftButton:
leftPressed = pressed;
break;
case OsuAction.RightButton:
rightPressed = pressed;
break;
}
if (leftPressed && rightPressed)
breakSpewer.Direction = SpewDirection.Both;
else if (leftPressed)
breakSpewer.Direction = SpewDirection.Left;
else if (rightPressed)
breakSpewer.Direction = SpewDirection.Right;
else
breakSpewer.Direction = SpewDirection.None;
}
private class StarParticleSpewer : ParticleSpewer
{
private const int particle_lifetime_min = 300;
private const int particle_lifetime_max = 1000;
public SpewDirection Direction { get; set; }
protected override float ParticleGravity => 240;
2021-09-05 03:49:05 +08:00
public StarParticleSpewer(Texture texture, int perSecond)
: base(texture, perSecond, particle_lifetime_max)
{
2021-09-05 07:01:49 +08:00
Active.BindValueChanged(_ => resetVelocityCalculation());
}
private Vector2 positionInParent => ToSpaceOfOtherDrawable(OriginPosition, ParticleParent);
2021-09-05 07:01:49 +08:00
private Vector2 screenVelocity;
private const double velocity_calculation_delay = 15;
private double lastVelocityCalculation;
private Vector2 positionDifference;
private Vector2? lastPosition;
protected override void Update()
{
base.Update();
if (lastPosition != null)
{
positionDifference += (positionInParent - lastPosition.Value);
2021-09-05 07:01:49 +08:00
lastVelocityCalculation += Clock.ElapsedFrameTime;
}
lastPosition = positionInParent;
2021-09-05 07:01:49 +08:00
if (lastVelocityCalculation > velocity_calculation_delay)
{
screenVelocity = positionDifference / (float)lastVelocityCalculation;
positionDifference = Vector2.Zero;
lastVelocityCalculation = 0;
}
}
private void resetVelocityCalculation()
{
positionDifference = Vector2.Zero;
lastVelocityCalculation = 0;
lastPosition = null;
2021-09-05 03:49:05 +08:00
}
protected override FallingParticle SpawnParticle()
{
var p = base.SpawnParticle();
p.StartPosition = positionInParent;
2021-09-05 03:49:05 +08:00
p.Duration = RNG.NextSingle(particle_lifetime_min, particle_lifetime_max);
p.AngularVelocity = RNG.NextSingle(-3f, 3f);
p.EndScale = RNG.NextSingle(2f);
switch (Direction)
{
case SpewDirection.None:
p.Velocity = Vector2.Zero;
break;
case SpewDirection.Left:
p.Velocity = new Vector2(
RNG.NextSingle(-460f, 0),
RNG.NextSingle(-40f, 40f)
2021-09-05 03:49:05 +08:00
);
break;
case SpewDirection.Right:
p.Velocity = new Vector2(
RNG.NextSingle(0, 460f),
RNG.NextSingle(-40f, 40f)
2021-09-05 03:49:05 +08:00
);
break;
case SpewDirection.Both:
p.Velocity = new Vector2(
RNG.NextSingle(-460f, 460f),
RNG.NextSingle(-160f, 160f)
2021-09-05 03:49:05 +08:00
);
break;
}
p.Velocity += screenVelocity * 40;
2021-09-05 07:01:49 +08:00
2021-09-05 03:49:05 +08:00
return p;
}
}
private enum SpewDirection
{
None,
Left,
Right,
Both,
}
}
}