mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 08:32:57 +08:00
parent
58b5e2c01b
commit
32b540268e
@ -23,6 +23,5 @@ namespace osu.Game.Rulesets.Catch
|
||||
MoveRight,
|
||||
[Description("Engage dash")]
|
||||
Dash,
|
||||
PositionUpdate
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
// Copyright (c) 2007-2018 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.MathUtils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Users;
|
||||
|
||||
@ -23,15 +26,78 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
|
||||
public override Replay Generate()
|
||||
{
|
||||
// todo: add support for HT DT
|
||||
const double dash_speed = CatcherArea.Catcher.BASE_SPEED;
|
||||
const double movement_speed = dash_speed / 2;
|
||||
float lastPosition = 0.5f;
|
||||
double lastTime = 0;
|
||||
|
||||
// Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled
|
||||
Replay.Frames.Add(new CatchReplayFrame(-100000, 0));
|
||||
Replay.Frames.Add(new CatchReplayFrame(-100000, lastPosition));
|
||||
|
||||
void moveToNext(CatchHitObject h)
|
||||
{
|
||||
float positionChange = Math.Abs(lastPosition - h.X);
|
||||
double timeAvailable = h.StartTime - lastTime;
|
||||
|
||||
//So we can either make it there without a dash or not.
|
||||
double speedRequired = positionChange / timeAvailable;
|
||||
|
||||
bool dashRequired = speedRequired > movement_speed && h.StartTime != 0;
|
||||
|
||||
// todo: get correct catcher size, based on difficulty CS.
|
||||
const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f;
|
||||
|
||||
if (lastPosition - catcher_width_half < h.X && lastPosition + catcher_width_half > h.X)
|
||||
{
|
||||
//we are already in the correct range.
|
||||
lastTime = h.StartTime;
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, lastPosition));
|
||||
return;
|
||||
}
|
||||
|
||||
if (h is BananaShower.Banana)
|
||||
{
|
||||
// auto bananas unrealistically warp to catch 100% combo.
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
|
||||
}
|
||||
else if (h.HyperDash)
|
||||
{
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable, lastPosition, ReplayButtonState.Right1));
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
|
||||
}
|
||||
else if (dashRequired)
|
||||
{
|
||||
//we do a movement in two parts - the dash part then the normal part...
|
||||
double timeAtNormalSpeed = positionChange / movement_speed;
|
||||
double timeWeNeedToSave = timeAtNormalSpeed - timeAvailable;
|
||||
double timeAtDashSpeed = timeWeNeedToSave / 2;
|
||||
|
||||
float midPosition = (float)Interpolation.Lerp(lastPosition, h.X, (float)timeAtDashSpeed / timeAvailable);
|
||||
|
||||
//dash movement
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + 1, lastPosition, ReplayButtonState.Left1));
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition));
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
|
||||
}
|
||||
else
|
||||
{
|
||||
double timeBefore = positionChange / movement_speed;
|
||||
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeBefore, lastPosition, ReplayButtonState.Right1));
|
||||
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
|
||||
}
|
||||
|
||||
lastTime = h.StartTime;
|
||||
lastPosition = h.X;
|
||||
}
|
||||
|
||||
foreach (var obj in Beatmap.HitObjects)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case Fruit _:
|
||||
Replay.Frames.Add(new CatchReplayFrame(obj.StartTime, obj.X));
|
||||
moveToNext(obj);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -42,7 +108,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
case BananaShower.Banana _:
|
||||
case TinyDroplet _:
|
||||
case Droplet _:
|
||||
Replay.Frames.Add(new CatchReplayFrame(nestedObj.StartTime, nestedObj.X));
|
||||
moveToNext(nestedObj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -14,15 +14,29 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
{
|
||||
}
|
||||
|
||||
public override List<InputState> GetPendingStates() => new List<InputState>
|
||||
public override List<InputState> GetPendingStates()
|
||||
{
|
||||
new CatchReplayState
|
||||
if (!Position.HasValue) return new List<InputState>();
|
||||
|
||||
var action = new List<CatchAction>();
|
||||
|
||||
if (CurrentFrame.ButtonState == ReplayButtonState.Left1)
|
||||
action.Add(CatchAction.Dash);
|
||||
|
||||
if (Position.Value.X > CurrentFrame.Position.X)
|
||||
action.Add(CatchAction.MoveRight);
|
||||
else if (Position.Value.X < CurrentFrame.Position.X)
|
||||
action.Add(CatchAction.MoveLeft);
|
||||
|
||||
return new List<InputState>
|
||||
{
|
||||
PressedActions = new List<CatchAction> { CatchAction.PositionUpdate },
|
||||
CatcherX = ((CatchReplayFrame)CurrentFrame).MouseX
|
||||
},
|
||||
new CatchReplayState { PressedActions = new List<CatchAction>() },
|
||||
};
|
||||
new CatchReplayState
|
||||
{
|
||||
PressedActions = action,
|
||||
CatcherX = Position.Value.X
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public class CatchReplayState : ReplayState<CatchAction>
|
||||
{
|
||||
|
@ -9,8 +9,8 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
{
|
||||
public override bool IsImportant => MouseX > 0;
|
||||
|
||||
public CatchReplayFrame(double time, float? x = null)
|
||||
: base(time, x ?? -1, null, ReplayButtonState.None)
|
||||
public CatchReplayFrame(double time, float? x = null, ReplayButtonState button = ReplayButtonState.None)
|
||||
: base(time, x ?? -1, null, button)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatcherArea : Container, IKeyBindingHandler<CatchAction>
|
||||
public class CatcherArea : Container
|
||||
{
|
||||
public const float CATCHER_SIZE = 172;
|
||||
|
||||
@ -84,16 +84,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(CatchAction action)
|
||||
protected override void Update()
|
||||
{
|
||||
if (action != CatchAction.PositionUpdate) return false;
|
||||
base.Update();
|
||||
|
||||
CatchFramedReplayInputHandler.CatchReplayState state = (CatchFramedReplayInputHandler.CatchReplayState)GetContainingInputManager().CurrentState;
|
||||
var state = GetContainingInputManager().CurrentState as CatchFramedReplayInputHandler.CatchReplayState;
|
||||
|
||||
if (state.CatcherX.HasValue)
|
||||
if (state?.CatcherX != null)
|
||||
MovableCatcher.X = state.CatcherX.Value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnReleased(CatchAction action) => false;
|
||||
|
Loading…
Reference in New Issue
Block a user