1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 06:03:08 +08:00

Add the concept of nested DrawableHitObjects.

- Applies to Slider Ticks and start circle. repeat/endpoints still need addressing.
- Removed SliderTicksLayer abstraction for now.
This commit is contained in:
Dean Herbert 2017-02-16 17:02:36 +09:00
parent 2640c2ac43
commit 8bf3902cbd
No known key found for this signature in database
GPG Key ID: 46D71BF4958ABB49
9 changed files with 60 additions and 115 deletions

View File

@ -37,7 +37,7 @@ namespace osu.Desktop.VisualTests.Tests
playbackSpeed.ValueChanged += delegate { rateAdjustClock.Rate = playbackSpeed.Value; };
}
HitObjectType mode = HitObjectType.Spinner;
HitObjectType mode = HitObjectType.Slider;
BindableNumber<double> playbackSpeed = new BindableDouble(0.5) { MinValue = 0, MaxValue = 1 };
private Container playfieldContainer;

View File

@ -73,5 +73,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
Hit100,
[Description(@"300")]
Hit300,
[Description(@"10")]
SliderTick
}
}

View File

@ -7,6 +7,7 @@ using osu.Game.Modes.Objects.Drawables;
using osu.Game.Modes.Osu.Objects.Drawables.Pieces;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics.Containers;
namespace osu.Game.Modes.Osu.Objects.Drawables
{
@ -18,11 +19,12 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
private List<ISliderProgress> components = new List<ISliderProgress>();
private Container<DrawableSliderTick> ticks;
SliderBody body;
SliderBall ball;
SliderBouncer bouncer1, bouncer2;
SliderTicksRenderer ticks;
public DrawableSlider(Slider s) : base(s)
{
@ -35,13 +37,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
Position = s.StackedPosition,
PathWidth = s.Scale * 64,
},
ticks = new SliderTicksRenderer
{
Position = s.StackedPosition,
StartTime = s.StartTime,
RepeatDuration = s.Curve.Length / s.Velocity,
Ticks = s.Ticks,
},
ticks = new Container<DrawableSliderTick>(),
bouncer1 = new SliderBouncer(s, false)
{
Position = s.Curve.PositionAt(1),
@ -72,6 +68,26 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
components.Add(ball);
components.Add(bouncer1);
components.Add(bouncer2);
AddNested(initialCircle);
var repeatDuration = s.Curve.Length / s.Velocity;
foreach (var tick in s.Ticks)
{
var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration;
var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? TIME_FADEIN : TIME_FADEIN / 2);
var fadeOutTime = repeatStartTime + repeatDuration;
var drawableTick = new DrawableSliderTick(tick)
{
FadeInTime = fadeInTime,
FadeOutTime = fadeOutTime,
Position = tick.Position,
};
ticks.Add(drawableTick);
AddNested(drawableTick);
}
}
// Since the DrawableSlider itself is just a container without a size we need to
@ -105,8 +121,8 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
if (initialCircle.Judgement?.Result != HitResult.Hit)
initialCircle.Position = slider.Curve.PositionAt(progress);
components.ForEach(c => c.UpdateProgress(progress, repeat));
ticks.ShouldHit = ball.Tracking;
foreach (var c in components) c.UpdateProgress(progress, repeat);
foreach (var t in ticks.Children) t.Tracking = ball.Tracking;
}
protected override void CheckJudgement(bool userTriggered)

View File

@ -22,7 +22,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
public double FadeInTime;
public double FadeOutTime;
public bool ShouldHit;
public bool Tracking;
public override bool RemoveWhenNotAlive => false;
@ -35,7 +35,6 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
Masking = true;
CornerRadius = Size.X / 2;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
BorderThickness = 2;
@ -70,8 +69,13 @@ namespace osu.Game.Modes.Osu.Objects.Drawables
protected override void CheckJudgement(bool userTriggered)
{
var j = Judgement as OsuJudgementInfo;
if (Judgement.TimeOffset >= 0)
Judgement.Result = ShouldHit ? HitResult.Hit : HitResult.Miss;
{
j.Result = Tracking ? HitResult.Hit : HitResult.Miss;
j.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss;
}
}
protected override void UpdatePreemptState()

View File

@ -1,96 +0,0 @@
// Copyright (c) 2007-2017 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.Caching;
using osu.Framework.Graphics.Containers;
using System.Collections.Generic;
namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces
{
public class SliderTicksRenderer : Container<DrawableSliderTick>
{
private Cached drawableTicks = new Cached();
private double startTime;
public double StartTime
{
get { return startTime; }
set
{
startTime = value;
drawableTicks.Invalidate();
}
}
private double repeatDuration;
public double RepeatDuration
{
get { return repeatDuration; }
set
{
repeatDuration = value;
drawableTicks.Invalidate();
}
}
private IEnumerable<SliderTick> ticks;
public IEnumerable<SliderTick> Ticks
{
get { return ticks; }
set
{
ticks = value;
drawableTicks.Invalidate();
}
}
public bool ShouldHit
{
set
{
foreach (var tick in Children)
tick.ShouldHit = value;
}
}
protected override void Update()
{
base.Update();
updateDrawableTicks();
}
[BackgroundDependencyLoader]
private void load()
{
updateDrawableTicks();
}
private void updateDrawableTicks()
{
if (drawableTicks.EnsureValid())
return;
drawableTicks.Refresh(delegate
{
Clear();
if (ticks == null || repeatDuration == 0)
return;
foreach (var tick in ticks)
{
var repeatStartTime = startTime + tick.RepeatIndex * repeatDuration;
var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? DrawableOsuHitObject.TIME_FADEIN : DrawableOsuHitObject.TIME_FADEIN / 2);
var fadeOutTime = repeatStartTime + repeatDuration;
Add(new DrawableSliderTick(tick)
{
FadeInTime = fadeInTime,
FadeOutTime = fadeOutTime,
Position = tick.Position,
});
}
});
}
}
}

View File

@ -96,7 +96,7 @@ namespace osu.Game.Modes.Osu.Objects
{
RepeatIndex = repeat,
StartTime = repeatStartTime + timeProgress * repeatDuration,
Position = Curve.PositionAt(distanceProgress) - StackedPosition,
Position = Curve.PositionAt(distanceProgress),
StackHeight = StackHeight,
Scale = Scale,
Colour = Colour,

View File

@ -53,6 +53,10 @@ namespace osu.Game.Modes.Osu
score += 300;
maxScore += 300;
break;
case OsuScoreResult.SliderTick:
score += 10;
maxScore += 10;
break;
}
}

View File

@ -47,7 +47,6 @@
<Compile Include="Objects\CircularArcApproximator.cs" />
<Compile Include="Objects\Drawables\DrawableOsuHitObject.cs" />
<Compile Include="Objects\Drawables\Connections\ConnectionRenderer.cs" />
<Compile Include="Objects\Drawables\SliderTicksLayer.cs" />
<Compile Include="Objects\Drawables\Connections\FollowPointRenderer.cs" />
<Compile Include="Objects\Drawables\Pieces\ApproachCircle.cs" />
<Compile Include="Objects\Drawables\Pieces\SpinnerBackground.cs" />

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using osu.Framework;
@ -23,8 +24,6 @@ namespace osu.Game.Modes.Objects.Drawables
public bool Interactive = true;
public Container<DrawableHitObject> ChildObjects;
public JudgementInfo Judgement;
public abstract JudgementInfo CreateJudgementInfo();
@ -85,6 +84,19 @@ namespace osu.Game.Modes.Objects.Drawables
Expire(true);
}
private List<DrawableHitObject> nestedHitObjects;
protected IEnumerable<DrawableHitObject> NestedHitObjects => nestedHitObjects;
protected void AddNested(DrawableHitObject h)
{
if (nestedHitObjects == null)
nestedHitObjects = new List<DrawableHitObject>();
h.OnJudgement += (d, j) => { OnJudgement?.Invoke(d, j); } ;
nestedHitObjects.Add(h);
}
/// <summary>
/// Process a hit of this hitobject. Carries out judgement.
/// </summary>
@ -119,7 +131,11 @@ namespace osu.Game.Modes.Objects.Drawables
protected virtual void CheckJudgement(bool userTriggered)
{
//todo: consider making abstract.
if (NestedHitObjects != null)
{
foreach (var d in NestedHitObjects)
d.CheckJudgement(userTriggered);
}
}
protected override void UpdateAfterChildren()