Merge remote-tracking branch 'refs/remotes/upstream/master' into hit-samples

This commit is contained in:
Dean Herbert
2016-12-08 21:41:02 +09:00
42 changed files with 7 additions and 7 deletions

View File

@ -0,0 +1,158 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.ComponentModel;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Transformations;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class DrawableHitCircle : DrawableOsuHitObject
{
private OsuHitObject osuObject;
public ApproachCircle ApproachCircle;
private CirclePiece circle;
private RingPiece ring;
private FlashPiece flash;
private ExplodePiece explode;
private NumberPiece number;
private GlowPiece glow;
public DrawableHitCircle(OsuHitObject h) : base(h)
{
osuObject = h;
Origin = Anchor.Centre;
Position = osuObject.Position;
Children = new Drawable[]
{
glow = new GlowPiece
{
Colour = osuObject.Colour
},
circle = new CirclePiece
{
Colour = osuObject.Colour,
Hit = () =>
{
((PositionalJudgementInfo)Judgement).PositionOffset = Vector2.Zero; //todo: set to correct value
UpdateJudgement(true);
return true;
},
},
number = new NumberPiece(),
ring = new RingPiece(),
flash = new FlashPiece(),
explode = new ExplodePiece
{
Colour = osuObject.Colour,
},
ApproachCircle = new ApproachCircle()
{
Colour = osuObject.Colour,
}
};
//may not be so correct
Size = circle.DrawSize;
}
double hit50 = 150;
double hit100 = 80;
double hit300 = 30;
protected override void CheckJudgement(bool userTriggered)
{
if (!userTriggered)
{
if (Judgement.TimeOffset > hit50)
Judgement.Result = HitResult.Miss;
return;
}
double hitOffset = Math.Abs(Judgement.TimeOffset);
if (hitOffset < hit50)
{
Judgement.Result = HitResult.Hit;
OsuJudgementInfo osuInfo = Judgement as OsuJudgementInfo;
if (hitOffset < hit300)
osuInfo.Score = OsuScoreResult.Hit300;
else if (hitOffset < hit100)
osuInfo.Score = OsuScoreResult.Hit100;
else if (hitOffset < hit50)
osuInfo.Score = OsuScoreResult.Hit50;
}
else
Judgement.Result = HitResult.Miss;
}
protected override void UpdateInitialState()
{
base.UpdateInitialState();
//sane defaults
ring.Alpha = circle.Alpha = number.Alpha = glow.Alpha = 1;
ApproachCircle.Alpha = 0;
ApproachCircle.Scale = new Vector2(2);
explode.Alpha = 0;
Scale = new Vector2(0.5f); //this will probably need to be moved to DrawableHitObject at some point.
}
protected override void UpdatePreemptState()
{
base.UpdatePreemptState();
ApproachCircle.FadeIn(Math.Min(TIME_FADEIN * 2, TIME_PREEMPT));
ApproachCircle.ScaleTo(0.6f, TIME_PREEMPT);
}
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
base.UpdateState(state);
ApproachCircle.FadeOut();
glow.FadeOut(400);
switch (state)
{
case ArmedState.Idle:
Delay(osuObject.Duration + TIME_PREEMPT);
FadeOut(TIME_FADEOUT);
break;
case ArmedState.Miss:
FadeOut(TIME_FADEOUT / 5);
break;
case ArmedState.Hit:
const double flash_in = 30;
flash.FadeTo(0.8f, flash_in);
flash.Delay(flash_in);
flash.FadeOut(100);
explode.FadeIn(flash_in);
Delay(flash_in, true);
//after the flash, we can hide some elements that were behind it
ring.FadeOut();
circle.FadeOut();
number.FadeOut();
FadeOut(800);
ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad);
break;
}
}
}
}

View File

@ -0,0 +1,81 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Objects.Drawables;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class DrawableOsuHitObject : DrawableHitObject
{
public const float TIME_PREEMPT = 600;
public const float TIME_FADEIN = 400;
public const float TIME_FADEOUT = 500;
public DrawableOsuHitObject(OsuHitObject hitObject)
: base(hitObject)
{
}
public override JudgementInfo CreateJudgementInfo() => new OsuJudgementInfo();
protected override void UpdateState(ArmedState state)
{
if (!IsLoaded) return;
Flush();
UpdateInitialState();
Delay(HitObject.StartTime - Time.Current - TIME_PREEMPT + Judgement.TimeOffset, true);
UpdatePreemptState();
Delay(TIME_PREEMPT, true);
}
protected virtual void UpdatePreemptState()
{
FadeIn(TIME_FADEIN);
}
protected virtual void UpdateInitialState()
{
Alpha = 0;
}
}
public class OsuJudgementInfo : PositionalJudgementInfo
{
public OsuScoreResult Score;
public ComboResult Combo;
}
public enum ComboResult
{
[Description(@"")]
None,
[Description(@"Good")]
Good,
[Description(@"Amazing")]
Perfect
}
public enum OsuScoreResult
{
[Description(@"Miss")]
Miss,
[Description(@"50")]
Hit50,
[Description(@"100")]
Hit100,
[Description(@"300")]
Hit300,
}
}

View File

@ -0,0 +1,129 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using OpenTK;
using osu.Framework.Input;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
class DrawableSlider : DrawableOsuHitObject
{
private Slider slider;
private DrawableHitCircle initialCircle;
private List<ISliderProgress> components = new List<ISliderProgress>();
SliderBody body;
SliderBall ball;
SliderBouncer bouncer1, bouncer2;
public DrawableSlider(Slider s) : base(s)
{
slider = s;
Origin = Anchor.TopLeft;
Position = Vector2.Zero;
RelativeSizeAxes = Axes.Both;
Children = new Drawable[]
{
body = new SliderBody(s)
{
Position = s.Position,
PathWidth = 36,
},
bouncer1 = new SliderBouncer(slider, false) { Position = slider.Curve.PositionAt(1) },
bouncer2 = new SliderBouncer(slider, true) { Position = slider.Position },
initialCircle = new DrawableHitCircle(new HitCircle
{
StartTime = s.StartTime,
Position = s.Position,
Colour = s.Colour,
Sample = s.Sample,
}),
ball = new SliderBall(slider),
};
components.Add(body);
components.Add(ball);
components.Add(bouncer1);
components.Add(bouncer2);
}
int currentRepeat;
protected override void Update()
{
base.Update();
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
int repeat = (int)(progress * slider.RepeatCount);
progress = (progress * slider.RepeatCount) % 1;
if (repeat > currentRepeat)
{
if (ball.Tracking)
PlaySample();
currentRepeat = repeat;
}
if (repeat % 2 == 1)
progress = 1 - progress;
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
if (initialCircle.Judgement?.Result != HitResult.Hit)
initialCircle.Position = slider.Curve.PositionAt(progress);
components.ForEach(c => c.UpdateProgress(progress, repeat));
}
protected override void CheckJudgement(bool userTriggered)
{
var j = Judgement as OsuJudgementInfo;
var sc = initialCircle.Judgement as OsuJudgementInfo;
if (!userTriggered && Time.Current >= HitObject.EndTime)
{
j.Score = sc.Score;
j.Result = sc.Result;
}
}
protected override void UpdateInitialState()
{
base.UpdateInitialState();
body.Alpha = 1;
//we need to be visible to handle input events. note that we still don't get enough events (we don't get a position if the mouse hasn't moved since the slider appeared).
ball.Alpha = 0.01f;
}
protected override void UpdateState(ArmedState state)
{
base.UpdateState(state);
ball.FadeIn();
Delay(HitObject.Duration, true);
body.FadeOut(160);
ball.FadeOut(160);
FadeOut(800);
}
}
internal interface ISliderProgress
{
void UpdateProgress(double progress, int repeat);
}
}

View File

@ -0,0 +1,84 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Game.Modes.Objects.Drawables;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
public class HitExplosion : FlowContainer
{
private readonly OsuJudgementInfo judgement;
private SpriteText line1;
private SpriteText line2;
public HitExplosion(OsuJudgementInfo judgement, OsuHitObject h = null)
{
this.judgement = judgement;
AutoSizeAxes = Axes.Both;
Origin = Anchor.Centre;
Direction = FlowDirection.VerticalOnly;
Spacing = new Vector2(0, 2);
Position = (h?.EndPosition ?? Vector2.Zero) + judgement.PositionOffset;
Children = new Drawable[]
{
line1 = new SpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Text = judgement.Score.GetDescription(),
Font = @"Venera",
TextSize = 16,
},
line2 = new SpriteText
{
Text = judgement.Combo.GetDescription(),
Font = @"Venera",
TextSize = 11,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
if (judgement.Result == HitResult.Miss)
{
FadeInFromZero(60);
ScaleTo(1.6f);
ScaleTo(1, 100, EasingTypes.In);
MoveToRelative(new Vector2(0, 100), 800, EasingTypes.InQuint);
RotateTo(40, 800, EasingTypes.InQuint);
Delay(600);
FadeOut(200);
}
else
{
line1.TransformSpacingTo(new Vector2(14, 0), 1800, EasingTypes.OutQuint);
line2.TransformSpacingTo(new Vector2(14, 0), 1800, EasingTypes.OutQuint);
FadeOut(500);
}
switch (judgement.Result)
{
case HitResult.Miss:
Colour = Color4.Red;
break;
}
Expire();
}
}
}

View File

@ -0,0 +1,38 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
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;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class ApproachCircle : Container
{
private Sprite approachCircle;
public ApproachCircle()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
AutoSizeAxes = Axes.Both;
Children = new Drawable[]
{
approachCircle = new Sprite()
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
approachCircle.Texture = textures.Get(@"Play/osu/approachcircle@2x");
}
}
}

View File

@ -0,0 +1,58 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
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;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class CirclePiece : Container
{
private Sprite disc;
private Triangles triangles;
public Func<bool> Hit;
public CirclePiece()
{
Size = new Vector2(144);
Masking = true;
CornerRadius = DrawSize.X / 2;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new Drawable[]
{
disc = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
},
triangles = new Triangles
{
BlendingMode = BlendingMode.Additive,
RelativeSizeAxes = Axes.Both
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
disc.Texture = textures.Get(@"Play/osu/disc@2x");
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
return Hit?.Invoke() ?? false;
}
}
}

View File

@ -0,0 +1,32 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class ExplodePiece : Container
{
public ExplodePiece()
{
Size = new Vector2(144);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
BlendingMode = BlendingMode.Additive;
Alpha = 0;
Children = new Drawable[]
{
new Triangles
{
BlendingMode = BlendingMode.Additive,
RelativeSizeAxes = Axes.Both
}
};
}
}
}

View File

@ -0,0 +1,35 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class FlashPiece : Container
{
public FlashPiece()
{
Size = new Vector2(144);
Masking = true;
CornerRadius = Size.X / 2;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
BlendingMode = BlendingMode.Additive;
Alpha = 0;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both
}
};
}
}
}

View File

@ -0,0 +1,39 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class GlowPiece : Container
{
private Sprite layer;
public GlowPiece()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new[]
{
layer = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
BlendingMode = BlendingMode.Additive,
Alpha = 0.5f
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
layer.Texture = textures.Get(@"Play/osu/ring-glow@2x");
}
}
}

View File

@ -0,0 +1,38 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class NumberPiece : Container
{
private Sprite number;
public NumberPiece()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new[]
{
number = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 1
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
number.Texture = textures.Get(@"Play/osu/number@2x");
}
}
}

View File

@ -0,0 +1,37 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class RingPiece : Container
{
private Sprite ring;
public RingPiece()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Children = new Drawable[]
{
ring = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre
}
};
}
[BackgroundDependencyLoader]
private void load(TextureStore textures)
{
ring.Texture = textures.Get(@"Play/osu/ring@2x");
}
}
}

View File

@ -0,0 +1,116 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Transformations;
using osu.Framework.Input;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderBall : Container, ISliderProgress
{
private readonly Slider slider;
private Box follow;
const float width = 70;
public SliderBall(Slider slider)
{
this.slider = slider;
Masking = true;
AutoSizeAxes = Axes.Both;
BlendingMode = BlendingMode.Additive;
Origin = Anchor.Centre;
BorderThickness = 5;
BorderColour = Color4.Orange;
Children = new Drawable[]
{
follow = new Box
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Colour = Color4.Orange,
Width = width,
Height = width,
Alpha = 0,
},
new Container
{
Masking = true,
AutoSizeAxes = Axes.Both,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
BorderThickness = 7,
BorderColour = Color4.White,
Alpha = 1,
CornerRadius = width / 2,
Children = new[]
{
new Box
{
Colour = slider.Colour,
Alpha = 0.4f,
Width = width,
Height = width,
},
}
}
};
}
private InputState lastState;
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
lastState = state;
return base.OnMouseDown(state, args);
}
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
{
lastState = state;
return base.OnMouseUp(state, args);
}
protected override bool OnMouseMove(InputState state)
{
lastState = state;
return base.OnMouseMove(state);
}
bool tracking;
public bool Tracking
{
get { return tracking; }
set
{
if (value == tracking) return;
tracking = value;
follow.ScaleTo(tracking ? 2.8f : 1, 300, EasingTypes.OutQuint);
follow.FadeTo(tracking ? 0.2f : 0, 300, EasingTypes.OutQuint);
}
}
private bool validTrackingTime => Time.Current >= slider.StartTime && Time.Current <= slider.EndTime;
protected override void Update()
{
base.Update();
CornerRadius = DrawWidth / 2;
Tracking = validTrackingTime && lastState != null && Contains(lastState.Mouse.NativeState.Position) && lastState.Mouse.HasMainButtonPressed;
}
public void UpdateProgress(double progress, int repeat)
{
Position = slider.Curve.PositionAt(progress);
}
}
}

View File

@ -0,0 +1,163 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Configuration;
using OpenTK;
using OpenTK.Graphics.ES30;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderBody : Container, ISliderProgress
{
private Path path;
private BufferedContainer container;
public float PathWidth
{
get { return path.PathWidth; }
set
{
path.PathWidth = value;
}
}
public double? SnakedStart { get; private set; }
public double? SnakedEnd { get; private set; }
private Slider slider;
public SliderBody(Slider s)
{
slider = s;
Children = new Drawable[]
{
container = new BufferedContainer
{
CacheDrawnFrameBuffer = true,
Children = new Drawable[]
{
path = new Path
{
BlendingMode = BlendingMode.None,
},
}
},
};
container.Attach(RenderbufferInternalFormat.DepthComponent16);
}
public void SetRange(double p0, double p1)
{
if (p0 > p1)
MathHelper.Swap(ref p0, ref p1);
if (updateSnaking(p0, p1))
{
// Autosizing does not give us the desired behaviour here.
// We want the container to have the same size as the slider,
// and to be positioned such that the slider head is at (0,0).
container.Size = path.Size;
container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - currentCurve[0]);
container.ForceRedraw();
}
}
private Bindable<bool> snakingIn;
private Bindable<bool> snakingOut;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
snakingIn = config.GetBindable<bool>(OsuConfig.SnakingInSliders);
snakingOut = config.GetBindable<bool>(OsuConfig.SnakingOutSliders);
int textureWidth = (int)PathWidth * 2;
//initialise background
var upload = new TextureUpload(textureWidth * 4);
var bytes = upload.Data;
const float aa_portion = 0.02f;
const float border_portion = 0.18f;
const float gradient_portion = 1 - border_portion;
const float opacity_at_centre = 0.3f;
const float opacity_at_edge = 0.8f;
for (int i = 0; i < textureWidth; i++)
{
float progress = (float)i / (textureWidth - 1);
if (progress <= border_portion)
{
bytes[i * 4] = 255;
bytes[i * 4 + 1] = 255;
bytes[i * 4 + 2] = 255;
bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * 255);
}
else
{
progress -= border_portion;
bytes[i * 4] = (byte)(slider.Colour.R * 255);
bytes[i * 4 + 1] = (byte)(slider.Colour.G * 255);
bytes[i * 4 + 2] = (byte)(slider.Colour.B * 255);
bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (slider.Colour.A * 255));
}
}
var texture = new Texture(textureWidth, 1);
texture.SetData(upload);
path.Texture = texture;
}
private List<Vector2> currentCurve = new List<Vector2>();
private bool updateSnaking(double p0, double p1)
{
if (SnakedStart == p0 && SnakedEnd == p1) return false;
SnakedStart = p0;
SnakedEnd = p1;
slider.Curve.GetPathToProgress(currentCurve, p0, p1);
path.ClearVertices();
foreach (Vector2 p in currentCurve)
path.AddVertex(p - currentCurve[0]);
return true;
}
public void UpdateProgress(double progress, int repeat)
{
double start = 0;
double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - DrawableOsuHitObject.TIME_PREEMPT)) / DrawableOsuHitObject.TIME_FADEIN, 0, 1) : 1;
if (repeat >= slider.RepeatCount - 1)
{
if (Math.Min(repeat, slider.RepeatCount - 1) % 2 == 1)
{
start = 0;
end = snakingOut ? progress : 1;
}
else
{
start = snakingOut ? progress : 0;
}
}
SetRange(start, end);
}
}
}

View File

@ -0,0 +1,58 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderBouncer : Container, ISliderProgress
{
private readonly Slider slider;
private readonly bool isEnd;
private TextAwesome icon;
public SliderBouncer(Slider slider, bool isEnd)
{
this.slider = slider;
this.isEnd = isEnd;
AutoSizeAxes = Axes.Both;
BlendingMode = BlendingMode.Additive;
Origin = Anchor.Centre;
Children = new Drawable[]
{
icon = new TextAwesome
{
Icon = FontAwesome.fa_eercast,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
TextSize = 24,
}
};
}
protected override void LoadComplete()
{
base.LoadComplete();
icon.RotateTo(360, 1000);
icon.Loop();
}
public void UpdateProgress(double progress, int repeat)
{
if (Time.Current < slider.StartTime)
Alpha = 0;
Alpha = repeat + 1 < slider.RepeatCount && repeat % 2 == (isEnd ? 0 : 1) ? 1 : 0;
}
}
}

View File

@ -0,0 +1,44 @@
//Copyright (c) 2007-2016 ppy Pty Ltd <contact@ppy.sh>.
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
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.MathUtils;
using OpenTK;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class Triangles : Container<Triangle>
{
protected override void LoadComplete()
{
base.LoadComplete();
const float size = 100;
for (int i = 0; i < 10; i++)
{
Add(new Triangle
{
Origin = Anchor.Centre,
RelativePositionAxes = Axes.Both,
Position = new Vector2(RNG.NextSingle(), RNG.NextSingle()),
Scale = new Vector2(RNG.NextSingle() * 0.4f + 0.2f),
// Scaling height by 0.866 results in equiangular triangles (== 60° and equal side length)
Size = new Vector2(size, 0.866f * size),
Alpha = RNG.NextSingle() * 0.3f,
});
}
}
protected override void Update()
{
base.Update();
foreach (Drawable d in Children)
d.Position -= new Vector2(0, (float)(d.Scale.X * (Time.Elapsed / 2880)));
}
}
}