mirror of
https://github.com/osukey/osukey.git
synced 2025-07-03 01:09:57 +09:00
Add back CatcherArea to simplify layout
This commit is contained in:
238
osu.Game.Rulesets.Catch/UI/CatcherArea.cs
Normal file
238
osu.Game.Rulesets.Catch/UI/CatcherArea.cs
Normal file
@ -0,0 +1,238 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherArea : Container
|
||||
{
|
||||
public const float CATCHER_SIZE = 172;
|
||||
|
||||
private readonly Catcher catcher;
|
||||
|
||||
public Container ExplodingFruitTarget
|
||||
{
|
||||
set { catcher.ExplodingFruitTarget = value; }
|
||||
}
|
||||
|
||||
public CatcherArea(BeatmapDifficulty difficulty = null)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = CATCHER_SIZE;
|
||||
Child = catcher = new Catcher(difficulty)
|
||||
{
|
||||
AdditiveTarget = this,
|
||||
};
|
||||
}
|
||||
|
||||
public void Add(DrawableHitObject fruit, Vector2 absolutePosition)
|
||||
{
|
||||
fruit.RelativePositionAxes = Axes.None;
|
||||
fruit.Position = new Vector2(catcher.ToLocalSpace(absolutePosition).X - catcher.DrawSize.X / 2, 0);
|
||||
|
||||
fruit.Anchor = Anchor.TopCentre;
|
||||
fruit.Origin = Anchor.BottomCentre;
|
||||
fruit.Scale *= 0.7f;
|
||||
fruit.LifetimeEnd = double.MaxValue;
|
||||
|
||||
catcher.Add(fruit);
|
||||
}
|
||||
|
||||
public bool CanCatch(CatchHitObject obj) => Math.Abs(catcher.Position.X - obj.X) < catcher.DrawSize.X / DrawSize.X / 2;
|
||||
|
||||
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||
{
|
||||
private Texture texture;
|
||||
|
||||
private Container<DrawableHitObject> caughtFruit;
|
||||
|
||||
public Container ExplodingFruitTarget;
|
||||
|
||||
public Container AdditiveTarget;
|
||||
|
||||
public Catcher(BeatmapDifficulty difficulty = null)
|
||||
{
|
||||
RelativePositionAxes = Axes.X;
|
||||
X = 0.5f;
|
||||
|
||||
Origin = Anchor.BottomCentre;
|
||||
Anchor = Anchor.BottomLeft;
|
||||
|
||||
Size = new Vector2(CATCHER_SIZE);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
createCatcherSprite(),
|
||||
caughtFruit = new Container<DrawableHitObject>
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private int currentDirection;
|
||||
|
||||
private bool dashing;
|
||||
|
||||
protected bool Dashing
|
||||
{
|
||||
get { return dashing; }
|
||||
set
|
||||
{
|
||||
if (value == dashing) return;
|
||||
|
||||
dashing = value;
|
||||
|
||||
if (dashing)
|
||||
Schedule(addAdditiveSprite);
|
||||
}
|
||||
}
|
||||
|
||||
private void addAdditiveSprite()
|
||||
{
|
||||
if (!dashing || AdditiveTarget == null) return;
|
||||
|
||||
var additive = createCatcherSprite();
|
||||
|
||||
additive.Anchor = Anchor;
|
||||
additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, DrawHeight); // also temporary to align sprite correctly.
|
||||
additive.Position = Position;
|
||||
additive.Scale = Scale;
|
||||
additive.RelativePositionAxes = RelativePositionAxes;
|
||||
additive.Blending = BlendingMode.Additive;
|
||||
|
||||
AdditiveTarget.Add(additive);
|
||||
|
||||
additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire();
|
||||
|
||||
Scheduler.AddDelayed(addAdditiveSprite, 50);
|
||||
}
|
||||
|
||||
private Sprite createCatcherSprite() => new Sprite
|
||||
{
|
||||
Size = new Vector2(CATCHER_SIZE),
|
||||
FillMode = FillMode.Fill,
|
||||
Texture = texture,
|
||||
OriginPosition = new Vector2(-3, 10) // temporary until the sprite is aligned correctly.
|
||||
};
|
||||
|
||||
public void Add(DrawableHitObject fruit)
|
||||
{
|
||||
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X;
|
||||
|
||||
while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance))
|
||||
{
|
||||
fruit.X += RNG.Next(-5, 5);
|
||||
fruit.Y -= RNG.Next(0, 5);
|
||||
}
|
||||
|
||||
caughtFruit.Add(fruit);
|
||||
|
||||
if (((CatchHitObject)fruit.HitObject).LastInCombo)
|
||||
explode();
|
||||
}
|
||||
|
||||
public bool OnPressed(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection--;
|
||||
return true;
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection++;
|
||||
return true;
|
||||
case CatchAction.Dash:
|
||||
Dashing = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(CatchAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case CatchAction.MoveLeft:
|
||||
currentDirection++;
|
||||
return true;
|
||||
case CatchAction.MoveRight:
|
||||
currentDirection--;
|
||||
return true;
|
||||
case CatchAction.Dash:
|
||||
Dashing = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The relative space to cover in 1 millisecond. based on 1 game pixel per millisecond as in osu-stable.
|
||||
/// </summary>
|
||||
public const double BASE_SPEED = 1.0 / 512;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (currentDirection == 0) return;
|
||||
|
||||
double dashModifier = Dashing ? 1 : 0.5;
|
||||
|
||||
Scale = new Vector2(Math.Sign(currentDirection), 1);
|
||||
X = (float)MathHelper.Clamp(X + Math.Sign(currentDirection) * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1);
|
||||
}
|
||||
|
||||
private void explode()
|
||||
{
|
||||
var fruit = caughtFruit.ToArray();
|
||||
|
||||
foreach (var f in fruit)
|
||||
{
|
||||
var originalX = f.X * Scale.X;
|
||||
|
||||
if (ExplodingFruitTarget != null)
|
||||
{
|
||||
f.Anchor = Anchor.TopLeft;
|
||||
f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget);
|
||||
|
||||
caughtFruit.Remove(f);
|
||||
|
||||
ExplodingFruitTarget.Add(f);
|
||||
}
|
||||
|
||||
f.MoveToY(f.Y - 50, 250, Easing.OutSine)
|
||||
.Then()
|
||||
.MoveToY(f.Y + 50, 500, Easing.InSine);
|
||||
|
||||
f.MoveToX(f.X + originalX * 6, 1000);
|
||||
f.FadeOut(750);
|
||||
|
||||
f.Expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user