mirror of
https://github.com/ppy/osu.git
synced 2026-05-15 12:42:48 +08:00
Compare commits
182 Commits
@@ -1,4 +1,6 @@
|
||||
using osu.Framework.Graphics.Containers;
|
||||
#define SoloTesting
|
||||
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -96,7 +98,7 @@ namespace Symcol.Core.Networking
|
||||
public Action OnAbort;
|
||||
|
||||
/// <summary>
|
||||
/// Called to load the game
|
||||
/// Called to load the game (Includes Host)
|
||||
/// </summary>
|
||||
public Action<List<ClientInfo>> OnLoadGame;
|
||||
|
||||
@@ -286,8 +288,10 @@ namespace Symcol.Core.Networking
|
||||
}
|
||||
}
|
||||
|
||||
#if !SoloTesting
|
||||
if (InMatchClients.Count == 0 && LoadedClients.Count > 0 && Loaded && !InGame)
|
||||
SendStartGame();
|
||||
#endif
|
||||
|
||||
//Peers
|
||||
else if (SendClient != null)
|
||||
@@ -333,6 +337,11 @@ namespace Symcol.Core.Networking
|
||||
}
|
||||
}
|
||||
|
||||
#if SoloTesting
|
||||
if (Loaded && !InGame)
|
||||
SendStartGame();
|
||||
#endif
|
||||
|
||||
if (p != null)
|
||||
OnPacketReceive?.Invoke(p);
|
||||
|
||||
@@ -552,7 +561,7 @@ namespace Symcol.Core.Networking
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send tto all but the one that sent it
|
||||
/// Send to all but the one that sent it
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
/// <param name="playerID"></param>
|
||||
|
||||
@@ -14,6 +14,10 @@ namespace Symcol.Rulesets.Core.HitObjects
|
||||
public abstract class DrawableSymcolHitObject<TObject> : DrawableHitObject<TObject>
|
||||
where TObject : HitObject
|
||||
{
|
||||
//Future prep?
|
||||
//public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { }
|
||||
//public override void ApplyTransformsAt(double time, bool propagateChildren = false) { }
|
||||
|
||||
protected virtual Container<Drawable> Content => new Container();
|
||||
|
||||
public IReadOnlyList<Drawable> Children
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using Symcol.Core.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Symcol.Rulesets.Core.Multiplayer.Networking
|
||||
{
|
||||
[Serializable]
|
||||
public class ScorePacket : Packet
|
||||
{
|
||||
public override int PacketSize => 2048;
|
||||
|
||||
public int Score;
|
||||
|
||||
public ScorePacket(ClientInfo clientInfo, int score) : base(clientInfo)
|
||||
{
|
||||
Score = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,12 +62,12 @@ namespace Symcol.Rulesets.Core.Multiplayer.Pieces
|
||||
},
|
||||
TabControl = new OsuTabControl<MatchScreenMode>
|
||||
{
|
||||
Position = new Vector2(36, 0),
|
||||
Position = new Vector2(72, 0),
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.08f,
|
||||
Width = 0.6f
|
||||
Width = 0.8f
|
||||
},
|
||||
SelectedContent = new Container
|
||||
{
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using Symcol.Core.Networking;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Networking;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Symcol.Rulesets.Core.Multiplayer.Pieces
|
||||
{
|
||||
public class MultiplayerScoreboard : Container
|
||||
{
|
||||
public readonly Container<MultiplayerScoreboardItem> ScoreboardItems;
|
||||
|
||||
private readonly RulesetNetworkingClientHandler rulesetNetworkingClientHandler;
|
||||
|
||||
private readonly ScoreProcessor scoreProcessor;
|
||||
|
||||
private double updateScoreTime = 0;
|
||||
|
||||
public MultiplayerScoreboard(RulesetNetworkingClientHandler rulesetNetworkingClientHandler, List<ClientInfo> playerList, ScoreProcessor scoreProcessor)
|
||||
{
|
||||
this.rulesetNetworkingClientHandler = rulesetNetworkingClientHandler;
|
||||
this.scoreProcessor = scoreProcessor;
|
||||
|
||||
AlwaysPresent = true;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
Width = 120;
|
||||
|
||||
Position = new Vector2(0, -200);
|
||||
Anchor = Anchor.CentreLeft;
|
||||
Origin = Anchor.TopLeft;
|
||||
|
||||
Child = ScoreboardItems = new Container<MultiplayerScoreboardItem>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
};
|
||||
|
||||
int i = 1;
|
||||
foreach (ClientInfo clientInfo in playerList)
|
||||
{
|
||||
if (clientInfo is RulesetClientInfo rulesetClientInfo)
|
||||
{
|
||||
ScoreboardItems.Add(new MultiplayerScoreboardItem(rulesetClientInfo, i) { });
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
rulesetNetworkingClientHandler.OnPacketReceive += (Packet packet) =>
|
||||
{
|
||||
if (packet is ScorePacket scorePacket)
|
||||
{
|
||||
rulesetNetworkingClientHandler.ShareWithOtherPeers(scorePacket);
|
||||
foreach (MultiplayerScoreboardItem item in ScoreboardItems)
|
||||
if (scorePacket.ClientInfo == item.ClientInfo)
|
||||
item.Score = scorePacket.Score;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (Time.Current >= updateScoreTime)
|
||||
{
|
||||
updateScoreTime = Time.Current + 500;
|
||||
foreach (MultiplayerScoreboardItem item in ScoreboardItems)
|
||||
if (rulesetNetworkingClientHandler.ClientInfo == item.ClientInfo)
|
||||
item.Score = (int)scoreProcessor.TotalScore.Value;
|
||||
|
||||
rulesetNetworkingClientHandler.SendToHost(new ScorePacket(rulesetNetworkingClientHandler.ClientInfo, (int)scoreProcessor.TotalScore.Value));
|
||||
rulesetNetworkingClientHandler.SendToInGameClients(new ScorePacket(rulesetNetworkingClientHandler.ClientInfo, (int)scoreProcessor.TotalScore.Value));
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Tab)
|
||||
{
|
||||
if (Alpha > 0)
|
||||
this.FadeOut(100);
|
||||
else
|
||||
this.FadeIn(100);
|
||||
}
|
||||
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Networking;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Symcol.Rulesets.Core.Multiplayer.Pieces
|
||||
{
|
||||
public class MultiplayerScoreboardItem : Container
|
||||
{
|
||||
public int Score
|
||||
{
|
||||
get { return score; }
|
||||
set
|
||||
{
|
||||
if (value != score)
|
||||
{
|
||||
score = value;
|
||||
scoreText.Text = value.ToString();
|
||||
|
||||
foreach(MultiplayerScoreboardItem item in itemList)
|
||||
if (value > item.Score && Place > item.Place)
|
||||
{
|
||||
Place = item.Place;
|
||||
foreach (MultiplayerScoreboardItem i in itemList)
|
||||
if (i.Place < Place)
|
||||
i.Place -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int Place
|
||||
{
|
||||
get { return place; }
|
||||
set
|
||||
{
|
||||
if (Place != place)
|
||||
{
|
||||
place = value;
|
||||
this.MoveTo(new Vector2(0, (-height - 8) * (value - 1)), 200, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int place = 0;
|
||||
|
||||
private int score = 0;
|
||||
|
||||
private const int height = 60;
|
||||
|
||||
public readonly RulesetClientInfo ClientInfo;
|
||||
|
||||
private readonly SpriteText scoreText;
|
||||
|
||||
private static List<MultiplayerScoreboardItem> itemList = new List<MultiplayerScoreboardItem>();
|
||||
|
||||
public MultiplayerScoreboardItem(RulesetClientInfo clientInfo, int place)
|
||||
{
|
||||
ClientInfo = clientInfo;
|
||||
this.place = place;
|
||||
|
||||
itemList.Add(this);
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = height;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 8;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
Alpha = 0.8f,
|
||||
},
|
||||
new SpriteText
|
||||
{
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
Position = new Vector2(4),
|
||||
Text = clientInfo.Username
|
||||
},
|
||||
scoreText = new SpriteText
|
||||
{
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Position = new Vector2(-4),
|
||||
Text = Score.ToString()
|
||||
}
|
||||
};
|
||||
|
||||
this.MoveTo(new Vector2(0, (-height - 8) * (Place - 1)), 200, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
itemList.Remove(this);
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,9 @@ using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK.Input;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Networking;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Pieces;
|
||||
using System.Collections.Generic;
|
||||
using Symcol.Core.Networking;
|
||||
|
||||
namespace Symcol.Rulesets.Core.Multiplayer.Screens
|
||||
{
|
||||
@@ -85,13 +88,18 @@ namespace Symcol.Rulesets.Core.Multiplayer.Screens
|
||||
|
||||
private HUDOverlay hudOverlay;
|
||||
|
||||
private MultiplayerScoreboard scoreboard;
|
||||
|
||||
private bool loadedSuccessfully => RulesetContainer?.Objects.Any() == true;
|
||||
|
||||
public MultiPlayer(RulesetNetworkingClientHandler rulesetNetworkingClientHandler)//, WorkingBeatmap beatmap = null)
|
||||
private readonly List<ClientInfo> playerList;
|
||||
|
||||
public MultiPlayer(RulesetNetworkingClientHandler rulesetNetworkingClientHandler, List<ClientInfo> playerList)//, WorkingBeatmap beatmap = null)
|
||||
{
|
||||
RulesetNetworkingClientHandler = rulesetNetworkingClientHandler;
|
||||
RulesetNetworkingClientHandler.OnAbort = () => Exit();
|
||||
RulesetNetworkingClientHandler.StartGame = () => start();
|
||||
this.playerList = playerList;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@@ -191,7 +199,8 @@ namespace Symcol.Rulesets.Core.Multiplayer.Screens
|
||||
Origin = Anchor.Centre,
|
||||
ProcessCustomClock = false,
|
||||
Breaks = beatmap.Breaks
|
||||
}
|
||||
},
|
||||
scoreboard = new MultiplayerScoreboard(RulesetNetworkingClientHandler, playerList, scoreProcessor)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -137,6 +137,7 @@ namespace Symcol.Rulesets.Core.Multiplayer.Screens
|
||||
protected virtual void Load(List<ClientInfo> playerList)
|
||||
{
|
||||
MakeCurrent();
|
||||
Push(new MultiPlayer(RulesetNetworkingClientHandler, playerList));
|
||||
}
|
||||
|
||||
private void openSongSelect()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//osu.Game.Screens.Symcol.SymcolMenu
|
||||
//Symcol.Rulesets.Core.SymcolSettingsSubsection
|
||||
//#define SymcolMods
|
||||
#define SymcolMods
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<Compile Include="Containers\LinkText.cs" />
|
||||
<Compile Include="Containers\ProfileLink.cs" />
|
||||
<Compile Include="HitObjects\DrawableSymcolHitObject.cs" />
|
||||
<Compile Include="Multiplayer\Networking\ScorePacket.cs" />
|
||||
<Compile Include="Multiplayer\Pieces\Chat.cs" />
|
||||
<Compile Include="Multiplayer\Pieces\ChatMessage.cs" />
|
||||
<Compile Include="Multiplayer\Networking\ChatPacket.cs" />
|
||||
@@ -54,6 +55,8 @@
|
||||
<Compile Include="Multiplayer\Options\MultiplayerDropdownEnumOption.cs" />
|
||||
<Compile Include="Multiplayer\Options\MultiplayerOption.cs" />
|
||||
<Compile Include="Multiplayer\Options\MultiplayerToggleOption.cs" />
|
||||
<Compile Include="Multiplayer\Pieces\MultiplayerScoreboard.cs" />
|
||||
<Compile Include="Multiplayer\Pieces\MultiplayerScoreboardItem.cs" />
|
||||
<Compile Include="Multiplayer\Screens\MatchSongSelect.cs" />
|
||||
<Compile Include="Multiplayer\Screens\MultiPlayer.cs" />
|
||||
<Compile Include="Multiplayer\Screens\RulesetLobbyScreen.cs" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//osu.Game.Screens.Symcol.SymcolMenu
|
||||
//Symcol.Rulesets.Core.Multiplayer.Screens.RulesetMultiplayerSelection
|
||||
//#define SymcolMods
|
||||
#define SymcolMods
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game;
|
||||
|
||||
+1
-1
Submodule osu-framework updated: 41e2a0a430...d8d4f55e10
+1
-1
Submodule osu-resources updated: 7bb0782200...6e145ed502
@@ -237,6 +237,10 @@
|
||||
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
|
||||
<Name>osu.Game.Rulesets.Osu</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Shape\osu.Game.Rulesets.Shape.csproj">
|
||||
<Project>{baf6d7b6-5e48-4278-ab81-f079af640e31}</Project>
|
||||
<Name>osu.Game.Rulesets.Shape</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
|
||||
<Project>{f167e17a-7de6-4af5-b920-a5112296c695}</Project>
|
||||
<Name>osu.Game.Rulesets.Taiko</Name>
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
<language>en-AU</language>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
|
||||
<file src="*.dll" target="lib\net45\"/>
|
||||
<file src="*.config" target="lib\net45\"/>
|
||||
<file src="x86\*.dll" target="lib\net45\x86\"/>
|
||||
<file src="x64\*.dll" target="lib\net45\x64\"/>
|
||||
<file src="**.exe" target="lib\net45\" exclude="**vshost**"/>
|
||||
<file src="**.dll" target="lib\net45\"/>
|
||||
<file src="**.config" target="lib\net45\"/>
|
||||
</files>
|
||||
</package>
|
||||
|
||||
|
||||
@@ -16,29 +16,13 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
public override void PostProcess(Beatmap<CatchHitObject> beatmap)
|
||||
{
|
||||
if (beatmap.ComboColours.Count == 0)
|
||||
return;
|
||||
|
||||
int index = 0;
|
||||
int colourIndex = 0;
|
||||
|
||||
CatchHitObject lastObj = null;
|
||||
|
||||
initialiseHyperDash(beatmap.HitObjects);
|
||||
|
||||
base.PostProcess(beatmap);
|
||||
|
||||
int index = 0;
|
||||
foreach (var obj in beatmap.HitObjects)
|
||||
{
|
||||
if (obj.NewCombo)
|
||||
{
|
||||
if (lastObj != null) lastObj.LastInCombo = true;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
|
||||
}
|
||||
|
||||
obj.IndexInBeatmap = index++;
|
||||
obj.ComboColour = beatmap.ComboColours[colourIndex];
|
||||
|
||||
lastObj = obj;
|
||||
}
|
||||
}
|
||||
|
||||
private void initialiseHyperDash(List<CatchHitObject> objects)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
@@ -32,25 +31,11 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
AddNested(new Banana
|
||||
{
|
||||
Samples = Samples,
|
||||
ComboColour = getNextComboColour(),
|
||||
StartTime = i,
|
||||
X = RNG.NextSingle()
|
||||
});
|
||||
}
|
||||
|
||||
private Color4 getNextComboColour()
|
||||
{
|
||||
switch (RNG.Next(0, 3))
|
||||
{
|
||||
default:
|
||||
return new Color4(255, 240, 0, 255);
|
||||
case 1:
|
||||
return new Color4(255, 192, 0, 255);
|
||||
case 2:
|
||||
return new Color4(214, 221, 28, 255);
|
||||
}
|
||||
}
|
||||
|
||||
public double EndTime => StartTime + Duration;
|
||||
|
||||
public double Duration { get; set; }
|
||||
|
||||
@@ -5,24 +5,25 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
public abstract class CatchHitObject : HitObject, IHasXPosition, IHasCombo
|
||||
public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInformation
|
||||
{
|
||||
public const double OBJECT_RADIUS = 44;
|
||||
|
||||
public float X { get; set; }
|
||||
|
||||
public Color4 ComboColour { get; set; }
|
||||
|
||||
public int IndexInBeatmap { get; set; }
|
||||
|
||||
public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(IndexInBeatmap % 4);
|
||||
|
||||
public virtual bool NewCombo { get; set; }
|
||||
|
||||
public int IndexInCurrentCombo { get; set; }
|
||||
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The next fruit starts a new combo. Used for explodey.
|
||||
/// </summary>
|
||||
|
||||
@@ -8,6 +8,8 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
{
|
||||
@@ -57,6 +59,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
AddJudgement(new Judgement { Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss });
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
|
||||
if (HitObject is IHasComboInformation combo)
|
||||
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
|
||||
}
|
||||
|
||||
private const float preempt = 1000;
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
|
||||
@@ -5,28 +5,39 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
{
|
||||
public class DrawableDroplet : PalpableCatchHitObject<Droplet>
|
||||
{
|
||||
private Pulp pulp;
|
||||
|
||||
public DrawableDroplet(Droplet h)
|
||||
: base(h)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 4;
|
||||
AccentColour = h.ComboColour;
|
||||
Masking = false;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new Pulp
|
||||
InternalChild = pulp = new Pulp
|
||||
{
|
||||
AccentColour = AccentColour,
|
||||
Size = Size
|
||||
};
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
pulp.AccentColour = AccentColour;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS);
|
||||
AccentColour = HitObject.ComboColour;
|
||||
Masking = false;
|
||||
|
||||
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
||||
@@ -33,6 +32,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
// todo: this should come from the skin.
|
||||
AccentColour = colourForRrepesentation(HitObject.VisualRepresentation);
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
createPulp(HitObject.VisualRepresentation),
|
||||
@@ -273,5 +275,31 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
|
||||
border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1);
|
||||
}
|
||||
|
||||
private Color4 colourForRrepesentation(FruitVisualRepresentation representation)
|
||||
{
|
||||
switch (representation)
|
||||
{
|
||||
default:
|
||||
case FruitVisualRepresentation.Pear:
|
||||
return new Color4(17, 136, 170, 255);
|
||||
case FruitVisualRepresentation.Grape:
|
||||
return new Color4(204, 102, 0, 255);
|
||||
case FruitVisualRepresentation.Raspberry:
|
||||
return new Color4(121, 9, 13, 255);
|
||||
case FruitVisualRepresentation.Pineapple:
|
||||
return new Color4(102, 136, 0, 255);
|
||||
case FruitVisualRepresentation.Banana:
|
||||
switch (RNG.Next(0, 3))
|
||||
{
|
||||
default:
|
||||
return new Color4(255, 240, 0, 255);
|
||||
case 1:
|
||||
return new Color4(255, 192, 0, 255);
|
||||
case 2:
|
||||
return new Color4(214, 221, 28, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
var catchObject = (DrawableCatchHitObject)h;
|
||||
|
||||
catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
|
||||
catchObject.AccentColour = HitObject.ComboColour;
|
||||
|
||||
dropletContainer.Add(h);
|
||||
base.AddNested(h);
|
||||
|
||||
@@ -60,65 +60,66 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
AddNested(new Fruit
|
||||
{
|
||||
Samples = Samples,
|
||||
ComboColour = ComboColour,
|
||||
StartTime = StartTime,
|
||||
X = X
|
||||
});
|
||||
|
||||
for (var span = 0; span < this.SpanCount(); span++)
|
||||
double lastDropletTime = StartTime;
|
||||
|
||||
for (int span = 0; span < this.SpanCount(); span++)
|
||||
{
|
||||
var spanStartTime = StartTime + span * spanDuration;
|
||||
var reversed = span % 2 == 1;
|
||||
|
||||
for (var d = tickDistance; d <= length; d += tickDistance)
|
||||
for (double d = 0; d <= length; d += tickDistance)
|
||||
{
|
||||
if (d > length - minDistanceFromEnd)
|
||||
break;
|
||||
|
||||
var timeProgress = d / length;
|
||||
var distanceProgress = reversed ? 1 - timeProgress : timeProgress;
|
||||
|
||||
var lastTickTime = spanStartTime + timeProgress * spanDuration;
|
||||
AddNested(new Droplet
|
||||
double time = spanStartTime + timeProgress * spanDuration;
|
||||
|
||||
double tinyTickInterval = time - lastDropletTime;
|
||||
while (tinyTickInterval > 100)
|
||||
tinyTickInterval /= 2;
|
||||
|
||||
for (double t = lastDropletTime + tinyTickInterval; t < time; t += tinyTickInterval)
|
||||
{
|
||||
StartTime = lastTickTime,
|
||||
ComboColour = ComboColour,
|
||||
X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
|
||||
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
|
||||
double progress = reversed ? 1 - (t - spanStartTime) / spanDuration : (t - spanStartTime) / spanDuration;
|
||||
|
||||
AddNested(new TinyDroplet
|
||||
{
|
||||
Bank = s.Bank,
|
||||
Name = @"slidertick",
|
||||
Volume = s.Volume
|
||||
}))
|
||||
});
|
||||
}
|
||||
StartTime = t,
|
||||
X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
|
||||
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
|
||||
{
|
||||
Bank = s.Bank,
|
||||
Name = @"slidertick",
|
||||
Volume = s.Volume
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
double tinyTickInterval = tickDistance / length * spanDuration;
|
||||
while (tinyTickInterval > 100)
|
||||
tinyTickInterval /= 2;
|
||||
|
||||
for (double t = 0; t < spanDuration; t += tinyTickInterval)
|
||||
{
|
||||
double progress = reversed ? 1 - t / spanDuration : t / spanDuration;
|
||||
|
||||
AddNested(new TinyDroplet
|
||||
if (d > minDistanceFromEnd && Math.Abs(d - length) > minDistanceFromEnd)
|
||||
{
|
||||
StartTime = spanStartTime + t,
|
||||
ComboColour = ComboColour,
|
||||
X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
|
||||
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
|
||||
AddNested(new Droplet
|
||||
{
|
||||
Bank = s.Bank,
|
||||
Name = @"slidertick",
|
||||
Volume = s.Volume
|
||||
}))
|
||||
});
|
||||
StartTime = time,
|
||||
X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
|
||||
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
|
||||
{
|
||||
Bank = s.Bank,
|
||||
Name = @"slidertick",
|
||||
Volume = s.Volume
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
lastDropletTime = time;
|
||||
}
|
||||
|
||||
AddNested(new Fruit
|
||||
{
|
||||
Samples = Samples,
|
||||
ComboColour = ComboColour,
|
||||
StartTime = spanStartTime + spanDuration,
|
||||
X = X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
|
||||
|
||||
[TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2149")]
|
||||
[TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2232")]
|
||||
public new void Test(string name)
|
||||
{
|
||||
base.Test(name);
|
||||
|
||||
@@ -6,13 +6,11 @@ using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||
using osu.Game.Tests.Visual;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
@@ -62,8 +60,6 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
Scale = 1.5f,
|
||||
};
|
||||
|
||||
fruit.ComboColour = colourForRrepesentation(fruit.VisualRepresentation);
|
||||
|
||||
return new DrawableFruit(fruit)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
@@ -74,31 +70,5 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
LifetimeEnd = double.PositiveInfinity,
|
||||
};
|
||||
}
|
||||
|
||||
private Color4 colourForRrepesentation(FruitVisualRepresentation representation)
|
||||
{
|
||||
switch (representation)
|
||||
{
|
||||
default:
|
||||
case FruitVisualRepresentation.Pear:
|
||||
return new Color4(17, 136, 170, 255);
|
||||
case FruitVisualRepresentation.Grape:
|
||||
return new Color4(204, 102, 0, 255);
|
||||
case FruitVisualRepresentation.Raspberry:
|
||||
return new Color4(121, 9, 13, 255);
|
||||
case FruitVisualRepresentation.Pineapple:
|
||||
return new Color4(102, 136, 0, 255);
|
||||
case FruitVisualRepresentation.Banana:
|
||||
switch (RNG.Next(0, 3))
|
||||
{
|
||||
default:
|
||||
return new Color4(255, 240, 0, 255);
|
||||
case 1:
|
||||
return new Color4(255, 192, 0, 255);
|
||||
case 2:
|
||||
return new Color4(214, 221, 28, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
if (caughtFruit == null) return;
|
||||
|
||||
caughtFruit.AccentColour = fruit.AccentColour;
|
||||
caughtFruit.RelativePositionAxes = Axes.None;
|
||||
caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
@@ -24,7 +23,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
private readonly GlowPiece glowPiece;
|
||||
private readonly BodyPiece bodyPiece;
|
||||
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
||||
private readonly Container fullHeightContainer;
|
||||
|
||||
/// <summary>
|
||||
@@ -40,6 +38,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
public DrawableHoldNote(HoldNote hitObject, ManiaAction action)
|
||||
: base(hitObject, action)
|
||||
{
|
||||
Container<DrawableHoldNoteTick> tickContainer;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
@@ -57,7 +56,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
||||
tickContainer = new Container<DrawableHoldNoteTick>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ChildrenEnumerable = HitObject.NestedHitObjects.OfType<HoldNoteTick>().Select(tick => new DrawableHoldNoteTick(tick)
|
||||
{
|
||||
HoldStartTime = () => holdStartTime
|
||||
})
|
||||
},
|
||||
head = new DrawableHeadNote(this, action)
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
@@ -70,16 +76,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var tick in HitObject.NestedHitObjects.OfType<HoldNoteTick>())
|
||||
{
|
||||
var drawableTick = new DrawableHoldNoteTick(tick)
|
||||
{
|
||||
HoldStartTime = () => holdStartTime
|
||||
};
|
||||
|
||||
tickContainer.Add(drawableTick);
|
||||
AddNested(drawableTick);
|
||||
}
|
||||
foreach (var tick in tickContainer)
|
||||
AddNested(tick);
|
||||
|
||||
AddNested(head);
|
||||
AddNested(tail);
|
||||
@@ -90,12 +88,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
if (base.AccentColour == value)
|
||||
return;
|
||||
base.AccentColour = value;
|
||||
|
||||
tickContainer.Children.ForEach(t => t.AccentColour = value);
|
||||
|
||||
glowPiece.AccentColour = value;
|
||||
bodyPiece.AccentColour = value;
|
||||
head.AccentColour = value;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
@@ -28,16 +27,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
if (action != null)
|
||||
Action = action.Value;
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
if (base.AccentColour == value)
|
||||
return;
|
||||
base.AccentColour = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,13 +48,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
if (base.AccentColour == value)
|
||||
return;
|
||||
base.AccentColour = value;
|
||||
|
||||
laneGlowPiece.AccentColour = value;
|
||||
GlowPiece.AccentColour = value;
|
||||
headPiece.AccentColour = value;
|
||||
laneGlowPiece.AccentColour = AccentColour;
|
||||
GlowPiece.AccentColour = AccentColour;
|
||||
headPiece.AccentColour = AccentColour;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,24 +13,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
public override void PostProcess(Beatmap<OsuHitObject> beatmap)
|
||||
{
|
||||
applyStacking(beatmap);
|
||||
|
||||
if (beatmap.ComboColours.Count == 0)
|
||||
return;
|
||||
|
||||
int comboIndex = 0;
|
||||
int colourIndex = 0;
|
||||
|
||||
foreach (var obj in beatmap.HitObjects)
|
||||
{
|
||||
if (obj.NewCombo)
|
||||
{
|
||||
comboIndex = 0;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
|
||||
}
|
||||
|
||||
obj.IndexInCurrentCombo = comboIndex++;
|
||||
obj.ComboColour = beatmap.ComboColours[colourIndex];
|
||||
}
|
||||
base.PostProcess(beatmap);
|
||||
}
|
||||
|
||||
private void applyStacking(Beatmap<OsuHitObject> beatmap)
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@@ -21,7 +22,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
private readonly NumberPiece number;
|
||||
private readonly GlowPiece glow;
|
||||
|
||||
public DrawableHitCircle(HitCircle h) : base(h)
|
||||
public DrawableHitCircle(HitCircle h)
|
||||
: base(h)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
@@ -30,13 +32,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
glow = new GlowPiece
|
||||
{
|
||||
Colour = AccentColour
|
||||
},
|
||||
glow = new GlowPiece(),
|
||||
circle = new CirclePiece
|
||||
{
|
||||
Colour = AccentColour,
|
||||
Hit = () =>
|
||||
{
|
||||
if (AllJudged)
|
||||
@@ -52,15 +50,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
},
|
||||
ring = new RingPiece(),
|
||||
flash = new FlashPiece(),
|
||||
explode = new ExplodePiece
|
||||
{
|
||||
Colour = AccentColour,
|
||||
},
|
||||
explode = new ExplodePiece(),
|
||||
ApproachCircle = new ApproachCircle
|
||||
{
|
||||
Alpha = 0,
|
||||
Scale = new Vector2(4),
|
||||
Colour = AccentColour,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,6 +64,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
explode.Colour = AccentColour;
|
||||
glow.Colour = AccentColour;
|
||||
circle.Colour = AccentColour;
|
||||
ApproachCircle.Colour = AccentColour;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
if (!userTriggered)
|
||||
|
||||
@@ -5,6 +5,9 @@ using System.ComponentModel;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Framework.Graphics;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@@ -15,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
protected DrawableOsuHitObject(OsuHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
AccentColour = HitObject.ComboColour;
|
||||
Alpha = 0;
|
||||
}
|
||||
|
||||
@@ -35,6 +37,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
|
||||
if (HitObject is IHasComboInformation combo)
|
||||
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
|
||||
}
|
||||
|
||||
protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein);
|
||||
|
||||
protected virtual void UpdateCurrentState(ArmedState state)
|
||||
|
||||
@@ -13,6 +13,7 @@ using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@@ -41,7 +42,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
Body = new SliderBody(s)
|
||||
{
|
||||
AccentColour = AccentColour,
|
||||
PathWidth = s.Scale * 64,
|
||||
},
|
||||
ticks = new Container<DrawableSliderTick> { RelativeSizeAxes = Axes.Both },
|
||||
@@ -50,7 +50,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
BypassAutoSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(s.Scale),
|
||||
AccentColour = AccentColour,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0
|
||||
},
|
||||
@@ -87,6 +86,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
|
||||
}
|
||||
|
||||
public override Color4 AccentColour
|
||||
{
|
||||
get { return base.AccentColour; }
|
||||
set
|
||||
{
|
||||
base.AccentColour = value;
|
||||
Body.AccentColour = AccentColour;
|
||||
Ball.AccentColour = AccentColour;
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Blending = BlendingMode.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.2f,
|
||||
}, false);
|
||||
}, s => s.GetTexture("Play/osu/hitcircle") == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
}, false);
|
||||
}, s => s.GetTexture("Play/osu/hitcircle") == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Texture = textures.Get(name),
|
||||
Blending = BlendingMode.Additive,
|
||||
Alpha = 0.5f
|
||||
}, false);
|
||||
}, s => s.GetTexture("Play/osu/hitcircle") == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
Colour = Color4.White.Opacity(0.5f),
|
||||
},
|
||||
Child = new Box()
|
||||
}, false),
|
||||
}, s => s.GetTexture("Play/osu/hitcircle") == null),
|
||||
number = new OsuSpriteText
|
||||
{
|
||||
Text = @"1",
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
public double? SnakedStart { get; private set; }
|
||||
public double? SnakedEnd { get; private set; }
|
||||
|
||||
private Color4 accentColour;
|
||||
private Color4 accentColour = Color4.White;
|
||||
/// <summary>
|
||||
/// Used to colour the path.
|
||||
/// </summary>
|
||||
@@ -173,6 +173,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
|
||||
texture.SetData(upload);
|
||||
path.Texture = texture;
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
|
||||
private void computeSize()
|
||||
|
||||
@@ -6,13 +6,11 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public abstract class OsuHitObject : HitObject, IHasCombo, IHasEditablePosition
|
||||
public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
|
||||
{
|
||||
public const double OBJECT_RADIUS = 64;
|
||||
|
||||
@@ -53,10 +51,14 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
|
||||
public float Scale { get; set; } = 1;
|
||||
|
||||
public Color4 ComboColour { get; set; } = Color4.Gray;
|
||||
public virtual bool NewCombo { get; set; }
|
||||
|
||||
public int IndexInCurrentCombo { get; set; }
|
||||
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
public bool LastInCombo { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
@@ -99,10 +99,10 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
StartTime = StartTime,
|
||||
Position = Position,
|
||||
IndexInCurrentCombo = IndexInCurrentCombo,
|
||||
ComboColour = ComboColour,
|
||||
Samples = Samples,
|
||||
SampleControlPoint = SampleControlPoint
|
||||
SampleControlPoint = SampleControlPoint,
|
||||
IndexInCurrentCombo = IndexInCurrentCombo,
|
||||
ComboIndex = ComboIndex,
|
||||
};
|
||||
|
||||
TailCircle = new SliderCircle(this)
|
||||
@@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
StartTime = EndTime,
|
||||
Position = EndPosition,
|
||||
IndexInCurrentCombo = IndexInCurrentCombo,
|
||||
ComboColour = ComboColour
|
||||
ComboIndex = ComboIndex,
|
||||
};
|
||||
|
||||
AddNested(HeadCircle);
|
||||
@@ -160,7 +160,6 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
Position = Position + Curve.PositionAt(distanceProgress),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
ComboColour = ComboColour,
|
||||
Samples = sampleList
|
||||
});
|
||||
}
|
||||
@@ -179,7 +178,6 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
Position = Position + Curve.PositionAt(repeat % 2),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
ComboColour = ComboColour,
|
||||
Samples = new List<SampleInfo>(RepeatSamples[repeatIndex])
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Visual;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
@@ -61,7 +60,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
StartTime = Time.Current + 1000 + timeOffset,
|
||||
Position = positionOffset.Value,
|
||||
ComboColour = Color4.LightSeaGreen
|
||||
};
|
||||
|
||||
circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
||||
|
||||
@@ -117,7 +117,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-(distance / 2), 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
Vector2.Zero,
|
||||
@@ -138,7 +137,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-200, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
Vector2.Zero,
|
||||
@@ -162,7 +160,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
CurveType = CurveType.Linear,
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-200, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
Vector2.Zero,
|
||||
@@ -189,7 +186,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
CurveType = CurveType.Bezier,
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-200, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
Vector2.Zero,
|
||||
@@ -215,7 +211,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
CurveType = CurveType.Linear,
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(0, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
Vector2.Zero,
|
||||
@@ -245,7 +240,6 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
StartTime = Time.Current + 1000,
|
||||
Position = new Vector2(-100, 0),
|
||||
ComboColour = Color4.LightSeaGreen,
|
||||
CurveType = CurveType.Catmull,
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
info face="vitaru!font" size=100 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=4 padding=0,0,0,0 spacing=4,4 outline=0
|
||||
common lineHeight=100 base=83 scaleW=1024 scaleH=1024 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||
page id=0 file="symcolFont_0.png"
|
||||
chars count=1
|
||||
char id=57419 x=495 y=537 width=88 height=89 xoffset=0 yoffset=8 xadvance=89 page=0 chnl=15
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,76 @@
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System;
|
||||
using osu.Game.Audio;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Beatmaps
|
||||
{
|
||||
internal class ShapeBeatmapConverter : BeatmapConverter<ShapeHitObject>
|
||||
{
|
||||
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasPosition) };
|
||||
|
||||
protected override IEnumerable<ShapeHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
|
||||
{
|
||||
var curveData = original as IHasCurve;
|
||||
var endTimeData = original as IHasEndTime;
|
||||
var positionData = original as IHasPosition;
|
||||
var comboData = original as IHasCombo;
|
||||
|
||||
List<SampleInfo> samples = original.Samples;
|
||||
|
||||
bool isSquare = samples.Any(s => s.Name == SampleInfo.HIT_WHISTLE);
|
||||
bool isTriangle = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
||||
bool isX = samples.Any(s => s.Name == SampleInfo.HIT_CLAP);
|
||||
|
||||
if (isSquare)
|
||||
{
|
||||
yield return new BaseShape
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
StartPosition = positionData?.Position ?? Vector2.Zero,
|
||||
Samples = original.Samples,
|
||||
NewCombo = comboData?.NewCombo ?? false,
|
||||
ShapeID = 2,
|
||||
};
|
||||
}
|
||||
else if (isTriangle)
|
||||
{
|
||||
yield return new BaseShape
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
StartPosition = positionData?.Position ?? Vector2.Zero,
|
||||
Samples = original.Samples,
|
||||
NewCombo = comboData?.NewCombo ?? false,
|
||||
ShapeID = 3,
|
||||
};
|
||||
}
|
||||
else if (isX)
|
||||
{
|
||||
yield return new BaseShape
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
StartPosition = positionData?.Position ?? Vector2.Zero,
|
||||
Samples = original.Samples,
|
||||
NewCombo = comboData?.NewCombo ?? false,
|
||||
ShapeID = 4,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new BaseShape
|
||||
{
|
||||
StartTime = original.StartTime,
|
||||
StartPosition = positionData?.Position ?? Vector2.Zero,
|
||||
Samples = original.Samples,
|
||||
NewCombo = comboData?.NewCombo ?? false,
|
||||
ShapeID = 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Beatmaps
|
||||
{
|
||||
internal class ShapeBeatmapProcessor : BeatmapProcessor<ShapeHitObject>
|
||||
{
|
||||
public override void PostProcess(Beatmap<ShapeHitObject> beatmap)
|
||||
{
|
||||
base.PostProcess(beatmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Shape.Objects.Drawables;
|
||||
using osu.Framework.Extensions;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Judgements
|
||||
{
|
||||
public class ShapeJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// The positional hit offset.
|
||||
/// </summary>
|
||||
public Vector2 PositionOffset;
|
||||
|
||||
public ComboResult Combo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Mods
|
||||
{
|
||||
public class ShapeModNoFail : ModNoFail
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ShapeModEasy : ModEasy
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ShapeModHidden : ModHidden
|
||||
{
|
||||
public override string Description => @"Notes fade out";
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
}
|
||||
|
||||
public class ShapeModHardRock : ModHardRock
|
||||
{
|
||||
public override double ScoreMultiplier => 1.08;
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
|
||||
public class ShapeModSuddenDeath : ModSuddenDeath
|
||||
{
|
||||
public override string Description => "Don't Miss";
|
||||
public override bool Ranked => true;
|
||||
}
|
||||
|
||||
public class ShapeModDaycore : ModDaycore
|
||||
{
|
||||
public override double ScoreMultiplier => 0.3;
|
||||
}
|
||||
|
||||
public class ShapeModDoubleTime : ModDoubleTime
|
||||
{
|
||||
public override double ScoreMultiplier => 1.16;
|
||||
}
|
||||
|
||||
public class ShapeModHalfTime : ModHalfTime
|
||||
{
|
||||
public override double ScoreMultiplier => 0.3;
|
||||
}
|
||||
|
||||
public class ShapeModNightcore : ModNightcore
|
||||
{
|
||||
public override double ScoreMultiplier => 1.16;
|
||||
}
|
||||
|
||||
public class ShapeModFlashlight : ModFlashlight
|
||||
{
|
||||
public override string Description => @"I don't even know how to play with this";
|
||||
public override double ScoreMultiplier => 1.18;
|
||||
}
|
||||
|
||||
public class ShapeRelax : ModRelax
|
||||
{
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
|
||||
public class ShapeModAutoplay : ModAutoplay<ShapeHitObject>
|
||||
{
|
||||
protected override Score CreateReplayScore(Beatmap<ShapeHitObject> beatmap) => new Score
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Rulesets.Shape;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Screens;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Multi
|
||||
{
|
||||
public class ShapeLobbyItem : RulesetLobbyItem
|
||||
{
|
||||
public override Texture Icon => ShapeRuleset.ShapeTextures.Get("icon");
|
||||
|
||||
public override string RulesetName => "Shape!";
|
||||
|
||||
//public override Texture Background => ShapeRuleset.ShapeTextures.Get("VitaruTouhosuModeTrue2560x1440");
|
||||
|
||||
public override RulesetLobbyScreen RulesetLobbyScreen => new ShapeLobbyScreen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Symcol.Rulesets.Core.Multiplayer.Networking;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Screens;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Multi
|
||||
{
|
||||
public class ShapeLobbyScreen : RulesetLobbyScreen
|
||||
{
|
||||
public override string RulesetName => "shape";
|
||||
|
||||
public override RulesetMatchScreen MatchScreen => new ShapeMatchScreen(RulesetNetworkingClientHandler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Symcol.Rulesets.Core.Multiplayer.Networking;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Screens;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Multi
|
||||
{
|
||||
public class ShapeMatchScreen : RulesetMatchScreen
|
||||
{
|
||||
public readonly RulesetNetworkingClientHandler ShapeNetworkingClientHandler;
|
||||
|
||||
public ShapeMatchScreen(RulesetNetworkingClientHandler shapeNetworkingClientHandler) : base(shapeNetworkingClientHandler)
|
||||
{
|
||||
ShapeNetworkingClientHandler = shapeNetworkingClientHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects
|
||||
{
|
||||
public class BaseShape : ShapeHitObject
|
||||
{
|
||||
public override HitObjectType Type => HitObjectType.Shape;
|
||||
public Vector2 StartPosition { get; set; }
|
||||
public float ShapeSize { get; set; } = 40;
|
||||
public int ShapeID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The hit window that results in a "GREAT" hit.
|
||||
/// </summary>
|
||||
public double HitWindowGreat = 35;
|
||||
|
||||
/// <summary>
|
||||
/// The hit window that results in a "GOOD" hit.
|
||||
/// </summary>
|
||||
public double HitWindowGood = 80;
|
||||
|
||||
/// <summary>
|
||||
/// The hit window that results in a "MISS".
|
||||
/// </summary>
|
||||
public double HitWindowMiss = 95;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
HitWindowGreat = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 50, 35, 20);
|
||||
HitWindowGood = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 120, 80, 50);
|
||||
HitWindowMiss = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 135, 95, 70);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Rulesets.Shape.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Shape.Judgements;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables
|
||||
{
|
||||
public class DrawableBaseShape : DrawableShapeHitObject<ShapeHitObject>
|
||||
{
|
||||
private BaseDial baseDial;
|
||||
private ShapeCircle circle;
|
||||
private ShapeSquare square;
|
||||
private ShapeTriangle triangle;
|
||||
private ShapeX x;
|
||||
|
||||
private bool validKeyPressed;
|
||||
|
||||
private readonly BaseShape shape;
|
||||
|
||||
public DrawableBaseShape(BaseShape Shape) : base(Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
Position = shape.StartPosition;
|
||||
Alpha = 0;
|
||||
AlwaysPresent = true;
|
||||
Anchor = Anchor.TopLeft;
|
||||
Origin = Anchor.Centre;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
LifetimeStart = shape.StartTime - (TIME_PREEMPT + 1000f);
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
{
|
||||
base.CheckForJudgements(userTriggered, timeOffset);
|
||||
|
||||
if (LifetimeStart <= Time.Current)
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (timeOffset > shape.HitWindowGood)
|
||||
{
|
||||
AddJudgement(new ShapeJudgement { Result = HitResult.Miss });
|
||||
Delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
double hitOffset = Math.Abs(timeOffset);
|
||||
|
||||
if (hitOffset > shape.HitWindowMiss)
|
||||
return;
|
||||
|
||||
if (!validKeyPressed)
|
||||
{
|
||||
AddJudgement(new ShapeJudgement { Result = HitResult.Miss });
|
||||
Delete();
|
||||
}
|
||||
else if (hitOffset < shape.HitWindowGood)
|
||||
{
|
||||
AddJudgement(new ShapeJudgement { Result = hitOffset < shape.HitWindowGreat ? HitResult.Great : HitResult.Good });
|
||||
Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
AddJudgement(new ShapeJudgement { Result = HitResult.Miss });
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnPressed(ShapeAction action)
|
||||
{
|
||||
if (LifetimeStart <= Time.Current)
|
||||
{
|
||||
switch (shape.ShapeID)
|
||||
{
|
||||
case 1:
|
||||
ShapeAction[] hitActionsNorth = { ShapeAction.SouthLeftButton, ShapeAction.SouthRightButton };
|
||||
validKeyPressed = hitActionsNorth.Contains(action);
|
||||
return UpdateJudgement(true);
|
||||
case 2:
|
||||
ShapeAction[] hitActionsSouth = { ShapeAction.WestLeftButton, ShapeAction.WestRightButton };
|
||||
validKeyPressed = hitActionsSouth.Contains(action);
|
||||
return UpdateJudgement(true);
|
||||
case 3:
|
||||
ShapeAction[] hitActionsWest = { ShapeAction.EastLeftButton, ShapeAction.EastRightButton };
|
||||
validKeyPressed = hitActionsWest.Contains(action);
|
||||
return UpdateJudgement(true);
|
||||
case 4:
|
||||
ShapeAction[] hitActionsEast = { ShapeAction.NorthLeftButton, ShapeAction.NorthRightButton };
|
||||
validKeyPressed = hitActionsEast.Contains(action);
|
||||
return UpdateJudgement(true);
|
||||
}
|
||||
}
|
||||
return UpdateJudgement(false);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (LifetimeStart <= Time.Current)
|
||||
{
|
||||
if (Time.Current >= (shape.StartTime - TIME_PREEMPT) - 500 && !loaded)
|
||||
{
|
||||
preLoad();
|
||||
}
|
||||
|
||||
if (Time.Current >= shape.StartTime - TIME_PREEMPT && !started)
|
||||
{
|
||||
start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool loaded = false;
|
||||
private bool started = false;
|
||||
|
||||
private void preLoad()
|
||||
{
|
||||
loaded = true;
|
||||
switch (shape.ShapeID)
|
||||
{
|
||||
case 1:
|
||||
Children = new Drawable[]
|
||||
{
|
||||
baseDial = new BaseDial(shape)
|
||||
{
|
||||
Depth = -1,
|
||||
ShapeID = shape.ShapeID,
|
||||
},
|
||||
circle = new ShapeCircle(shape) { Depth = -2, Colour = Color4.Red, },
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
Children = new Drawable[]
|
||||
{
|
||||
baseDial = new BaseDial(shape)
|
||||
{
|
||||
Depth = -1,
|
||||
ShapeID = shape.ShapeID,
|
||||
},
|
||||
square = new ShapeSquare(shape) { Depth = -2, Colour = Color4.Violet, },
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
Children = new Drawable[]
|
||||
{
|
||||
baseDial = new BaseDial(shape)
|
||||
{
|
||||
Depth = -1,
|
||||
ShapeID = shape.ShapeID,
|
||||
},
|
||||
triangle = new ShapeTriangle(shape) { Depth = -2, Colour = Color4.Green, },
|
||||
};
|
||||
break;
|
||||
case 4:
|
||||
Children = new Drawable[]
|
||||
{
|
||||
baseDial = new BaseDial(shape)
|
||||
{
|
||||
Depth = -1,
|
||||
ShapeID = shape.ShapeID,
|
||||
},
|
||||
x = new ShapeX(shape) { Depth = -2, Colour = Color4.Blue, },
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void start()
|
||||
{
|
||||
started = true;
|
||||
this.FadeIn(TIME_FADEIN);
|
||||
baseDial.StartSpinning(TIME_PREEMPT);
|
||||
switch (shape.ShapeID)
|
||||
{
|
||||
case 1:
|
||||
circle.Position = new Vector2(RNG.Next(-200, 200), -400);
|
||||
circle.MoveTo(baseDial.Position, TIME_PREEMPT);
|
||||
break;
|
||||
case 2:
|
||||
square.Position = new Vector2(RNG.Next(-200, 200), -400);
|
||||
square.MoveTo(baseDial.Position, TIME_PREEMPT);
|
||||
break;
|
||||
case 3:
|
||||
triangle.Position = new Vector2(RNG.Next(-200, 200), -400);
|
||||
triangle.MoveTo(baseDial.Position, TIME_PREEMPT);
|
||||
break;
|
||||
case 4:
|
||||
x.Position = new Vector2(RNG.Next(-200, 200), -400);
|
||||
x.MoveTo(baseDial.Position, TIME_PREEMPT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Marks this for death
|
||||
internal void Delete()
|
||||
{
|
||||
AlwaysPresent = true;
|
||||
Alpha = 0;
|
||||
LifetimeEnd = Time.Current;
|
||||
Expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using osu.Game.Rulesets.Shape.Judgements;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using Symcol.Rulesets.Core.HitObjects;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables
|
||||
{
|
||||
public abstract class DrawableShapeHitObject<ShapeObject> : DrawableSymcolHitObject<ShapeHitObject>, IKeyBindingHandler<ShapeAction>
|
||||
where ShapeObject : ShapeHitObject
|
||||
{
|
||||
public float TIME_PREEMPT = 800;
|
||||
public float TIME_FADEIN = 400;
|
||||
public float TIME_FADEOUT = 400;
|
||||
|
||||
public DrawableShapeHitObject(ShapeHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void UpdatePreemptState()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void UpdateInitialState()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public abstract bool OnPressed(ShapeAction action);
|
||||
|
||||
public virtual bool OnReleased(ShapeAction action) => false;
|
||||
}
|
||||
|
||||
public enum ComboResult
|
||||
{
|
||||
[Description(@"")]
|
||||
None,
|
||||
[Description(@"Good")]
|
||||
Good,
|
||||
[Description(@"Amazing!")]
|
||||
Perfect
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Shape.Judgements;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables
|
||||
{
|
||||
public class DrawableShapeJudgement : DrawableJudgement
|
||||
{
|
||||
public DrawableShapeJudgement(Judgement judgement, DrawableHitObject judgedObject)
|
||||
: base(judgement, judgedObject)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
if (Judgement.Result != HitResult.Miss)
|
||||
JudgementText.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint);
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
|
||||
{
|
||||
//The cat in the hat is the creepiest fucker you will ever meet
|
||||
public class Arrow : Container
|
||||
{
|
||||
private readonly BaseShape shape;
|
||||
private Container line1;
|
||||
private Container line1Glow;
|
||||
private Container line2;
|
||||
|
||||
public Arrow(BaseShape Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
line1 = new Container
|
||||
{
|
||||
Rotation = 360 - 45,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = -2,
|
||||
Colour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
},
|
||||
line2 = new Container
|
||||
{
|
||||
Rotation = 45,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = -1,
|
||||
Colour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Hollow = true,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.White.Opacity(0.25f),
|
||||
Radius = shape.ShapeSize / 4,
|
||||
}
|
||||
},
|
||||
line1Glow = new Container
|
||||
{
|
||||
Rotation = 360 - 45,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = 0,
|
||||
Colour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Hollow = true,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.White.Opacity(0.25f),
|
||||
Radius = shape.ShapeSize / 4,
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
|
||||
{
|
||||
public class BaseDial : BeatSyncedContainer
|
||||
{
|
||||
private BaseShape shape;
|
||||
private ShapeCircle baseCircle;
|
||||
private ShapeSquare baseSquare;
|
||||
private ShapeTriangle baseTriangle;
|
||||
private ShapeX baseX;
|
||||
private Container arrow;
|
||||
private Container box;
|
||||
public int ShapeID { get; set; }
|
||||
|
||||
public BaseDial(BaseShape Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
arrow = new Container
|
||||
{
|
||||
Depth = 0,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize * 0.6f),
|
||||
Colour = Color4.DarkGray,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
new Triangle
|
||||
{
|
||||
Colour = Color4.White,
|
||||
Size = new Vector2(shape.ShapeSize / 4),
|
||||
Origin = Anchor.BottomCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
},
|
||||
}
|
||||
},
|
||||
box = new Container
|
||||
{
|
||||
Depth = -1,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(shape.ShapeSize / 4),
|
||||
Colour = Color4.DarkGray,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
switch (ShapeID)
|
||||
{
|
||||
case 1:
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
baseCircle = new ShapeCircle(shape) { Colour = Color4.Gray, Depth = 1 },
|
||||
});
|
||||
break;
|
||||
case 2:
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
baseSquare = new ShapeSquare(shape) { Colour = Color4.Gray, Depth = 1 },
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
baseTriangle = new ShapeTriangle(shape) { Colour = Color4.Gray, Depth = 1 },
|
||||
});
|
||||
break;
|
||||
case 4:
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
baseX = new ShapeX(shape) { Colour = Color4.Gray, Depth = 1 },
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void StartSpinning(float time)
|
||||
{
|
||||
box.RotateTo(360, time);
|
||||
arrow.RotateTo(360, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ShapeCircle : Container
|
||||
{
|
||||
private BaseShape shape;
|
||||
private Container ring;
|
||||
|
||||
public ShapeCircle(BaseShape Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
ring = new Container
|
||||
{
|
||||
Size = new Vector2(shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
BorderThickness = shape.ShapeSize / 6,
|
||||
Depth = -2,
|
||||
BorderColour = Color4.White,
|
||||
CornerRadius = shape.ShapeSize / 2,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Hollow = true,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.White.Opacity(0.25f),
|
||||
Radius = shape.ShapeSize / 4,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ShapeSquare : Container
|
||||
{
|
||||
private BaseShape shape;
|
||||
private Container box;
|
||||
|
||||
public ShapeSquare(BaseShape Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
box = new Container
|
||||
{
|
||||
Size = new Vector2(shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
BorderThickness = shape.ShapeSize / 6,
|
||||
Depth = -2,
|
||||
BorderColour = Color4.White,
|
||||
CornerRadius = shape.ShapeSize / 8,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Hollow = true,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.White.Opacity(0.25f),
|
||||
Radius = shape.ShapeSize / 4,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ShapeTriangle : Container
|
||||
{
|
||||
private BaseShape shape;
|
||||
private Triangle triangle;
|
||||
|
||||
public ShapeTriangle(BaseShape Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
triangle = new Triangle
|
||||
{
|
||||
Size = new Vector2(shape.ShapeSize),
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = -2,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
|
||||
{
|
||||
public class ShapeX : Container
|
||||
{
|
||||
private BaseShape shape;
|
||||
private Container line1;
|
||||
private Container line1Glow;
|
||||
private Container line2;
|
||||
|
||||
public ShapeX(BaseShape Shape)
|
||||
{
|
||||
shape = Shape;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
Children = new Drawable[]
|
||||
{
|
||||
line1 = new Container
|
||||
{
|
||||
Rotation = 360 - 45,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = -2,
|
||||
Colour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
},
|
||||
line2 = new Container
|
||||
{
|
||||
Rotation = 45,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = -1,
|
||||
Colour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Hollow = true,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.White.Opacity(0.25f),
|
||||
Radius = shape.ShapeSize / 4,
|
||||
}
|
||||
},
|
||||
line1Glow = new Container
|
||||
{
|
||||
Rotation = 360 - 45,
|
||||
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
|
||||
Masking = true,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Depth = 0,
|
||||
Colour = Color4.White,
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Hollow = true,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.White.Opacity(0.25f),
|
||||
Radius = shape.ShapeSize / 4,
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace osu.Game.Rulesets.Shape.Objects
|
||||
{
|
||||
public enum HitObjectType
|
||||
{
|
||||
Shape,
|
||||
Arrow,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Shape.Objects.Drawables;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects
|
||||
{
|
||||
public abstract class ShapeHitObject : HitObject
|
||||
{
|
||||
public const double HitboxSize = 8;
|
||||
|
||||
public float BPM;
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public Vector2 StackedPosition => Position + StackOffset;
|
||||
|
||||
public virtual Vector2 EndPosition => Position;
|
||||
|
||||
public Vector2 StackedEndPosition => EndPosition + StackOffset;
|
||||
|
||||
public virtual int StackHeight { get; set; }
|
||||
|
||||
public Vector2 StackOffset => new Vector2(0,0);
|
||||
|
||||
public double Radius => HitboxSize * Scale;
|
||||
|
||||
public float Scale { get; set; } = 1;
|
||||
|
||||
public abstract HitObjectType Type { get; }
|
||||
|
||||
public Color4 ComboColour { get; set; }
|
||||
public virtual bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime);
|
||||
|
||||
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using OpenTK;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Objects
|
||||
{
|
||||
internal class ShapeHitObjectDifficulty
|
||||
{
|
||||
/// <summary>
|
||||
/// Factor by how much speed / aim strain decays per second.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// These values are results of tweaking a lot and taking into account general feedback.
|
||||
/// Opinionated observation: Speed is easier to maintain than accurate jumps.
|
||||
/// </remarks>
|
||||
internal static readonly double[] DECAY_BASE = { 0.3, 0.15 };
|
||||
|
||||
/// <summary>
|
||||
/// Pseudo threshold values to distinguish between "singles" and "streams"
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Of course the border can not be defined clearly, therefore the algorithm has a smooth transition between those values.
|
||||
/// They also are based on tweaking and general feedback.
|
||||
/// </remarks>
|
||||
private const double stream_spacing_threshold = 110,
|
||||
single_spacing_threshold = 125;
|
||||
|
||||
/// <summary>
|
||||
/// Scaling values for weightings to keep aim and speed difficulty in balance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Found from testing a very large map pool (containing all ranked maps) and keeping the average values the same.
|
||||
/// </remarks>
|
||||
private static readonly double[] spacing_weight_scaling = { 1400, 26.25 };
|
||||
|
||||
/// <summary>
|
||||
/// Almost the normed diameter of a hitbox (104 osu pixel). That is -after- position transforming.
|
||||
/// </summary>
|
||||
private const double almost_diameter = 90;
|
||||
|
||||
internal ShapeHitObject BaseHitObject;
|
||||
internal double[] Strains = { 1, 1 };
|
||||
|
||||
internal int MaxCombo = 1;
|
||||
|
||||
private float scalingFactor;
|
||||
|
||||
private Vector2 startPosition = new Vector2(0);
|
||||
private Vector2 endPosition;
|
||||
|
||||
internal ShapeHitObjectDifficulty(ShapeHitObject baseHitObject)
|
||||
{
|
||||
BaseHitObject = baseHitObject;
|
||||
float hitboxRadius = baseHitObject.Scale * 64;
|
||||
|
||||
// We will scale everything by this factor, so we can assume a uniform HitboxSize among beatmaps.
|
||||
scalingFactor = 52.0f / hitboxRadius;
|
||||
if (hitboxRadius < 4)
|
||||
{
|
||||
float smallHitboxBonus = Math.Min(30.0f - hitboxRadius, 5.0f) / 50.0f;
|
||||
scalingFactor *= 1.0f + smallHitboxBonus;
|
||||
}
|
||||
|
||||
else
|
||||
endPosition = startPosition;
|
||||
}
|
||||
|
||||
internal void CalculateStrains(ShapeHitObjectDifficulty previousHitObject, double timeRate)
|
||||
{
|
||||
calculateSpecificStrain(previousHitObject, ShapeDifficultyCalculator.DifficultyType.Speed, timeRate);
|
||||
calculateSpecificStrain(previousHitObject, ShapeDifficultyCalculator.DifficultyType.Aim, timeRate);
|
||||
}
|
||||
|
||||
// Caution: The subjective values are strong with this one
|
||||
private static double spacingWeight(double distance, ShapeDifficultyCalculator.DifficultyType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ShapeDifficultyCalculator.DifficultyType.Speed:
|
||||
if (distance > single_spacing_threshold)
|
||||
return 2.5;
|
||||
else if (distance > stream_spacing_threshold)
|
||||
return 1.6 + 0.9 * (distance - stream_spacing_threshold) / (single_spacing_threshold - stream_spacing_threshold);
|
||||
else if (distance > almost_diameter)
|
||||
return 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter);
|
||||
else if (distance > almost_diameter / 2)
|
||||
return 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2);
|
||||
else
|
||||
return 0.95;
|
||||
|
||||
case ShapeDifficultyCalculator.DifficultyType.Aim:
|
||||
return Math.Pow(distance, 0.99);
|
||||
}
|
||||
|
||||
Debug.Assert(false, "Invalid Shape difficulty hit object type.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void calculateSpecificStrain(ShapeHitObjectDifficulty previousHitObject, ShapeDifficultyCalculator.DifficultyType type, double timeRate)
|
||||
{
|
||||
double addition = 0;
|
||||
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
|
||||
double decay = Math.Pow(DECAY_BASE[(int)type], timeElapsed / 1000);
|
||||
|
||||
addition = spacingWeight(DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type];
|
||||
|
||||
// You will never find maps that require this amongst ranked maps.
|
||||
addition /= Math.Max(timeElapsed, 50);
|
||||
|
||||
Strains[(int)type] = previousHitObject.Strains[(int)type] * decay + addition;
|
||||
}
|
||||
|
||||
internal double DistanceTo(ShapeHitObjectDifficulty other)
|
||||
{
|
||||
// Scale the distance by hitbox size.
|
||||
return (startPosition - other.endPosition).Length * scalingFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Modes.Objects;
|
||||
using osu.Game.Modes.Osu.Objects;
|
||||
using osu.Game.Modes.Vitaru.Objects.Characters;
|
||||
|
||||
namespace osu.Game.Modes.Vitaru.Objects
|
||||
{
|
||||
internal class VitaruConverter : HitObjectConverter<VitaruHitObject>
|
||||
{
|
||||
public override List<VitaruHitObject> Convert(Beatmap beatmap)
|
||||
{
|
||||
List<VitaruHitObject> output = new List<VitaruHitObject>();
|
||||
|
||||
foreach (HitObject i in beatmap.HitObjects)
|
||||
{
|
||||
VitaruHitObject h = i as VitaruHitObject;
|
||||
|
||||
if (h == null)
|
||||
{
|
||||
OsuHitObject o = i as OsuHitObject;
|
||||
|
||||
if (o == null) throw new HitObjectConvertException(@"Vitaru", i);
|
||||
|
||||
h = new Enemy();
|
||||
}
|
||||
output.Add(h);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<configuration>
|
||||
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
|
||||
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
|
||||
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
|
||||
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
|
||||
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
|
||||
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
|
||||
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
|
||||
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
|
||||
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
|
||||
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
|
||||
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
|
||||
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
|
||||
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
|
||||
<!-- XQuartz compatibility (X11 on Mac) -->
|
||||
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
|
||||
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
|
||||
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
|
||||
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
|
||||
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
|
||||
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
|
||||
</configuration>
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("osu.Game.Modes.Vitaru")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("osu.Game.Modes.Vitaru")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016 - 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("58f6c80c-1253-4a0e-a465-b8c85ebeadf3")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Shape.Judgements;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
using osu.Game.Rulesets.Shape.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Scoring
|
||||
{
|
||||
internal class ShapeScoreProcessor : ScoreProcessor<ShapeHitObject>
|
||||
{
|
||||
public ShapeScoreProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
public ShapeScoreProcessor(RulesetContainer<ShapeHitObject> rulesetContainer)
|
||||
: base(rulesetContainer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Reset(bool storeResults)
|
||||
{
|
||||
base.Reset(storeResults);
|
||||
|
||||
Health.Value = 1;
|
||||
|
||||
TotalScore.Value = 0;
|
||||
|
||||
scoreResultCounts.Clear();
|
||||
comboResultCounts.Clear();
|
||||
}
|
||||
|
||||
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
|
||||
private readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
|
||||
|
||||
private float hpDrainRate;
|
||||
|
||||
private int totalAccurateJudgements;
|
||||
|
||||
public override void PopulateScore(Score score)
|
||||
{
|
||||
base.PopulateScore(score);
|
||||
|
||||
score.Statistics[HitResult.Perfect] = scoreResultCounts.GetOrDefault(HitResult.Perfect);
|
||||
score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great);
|
||||
score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good);
|
||||
score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh);
|
||||
score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss);
|
||||
}
|
||||
|
||||
protected override void SimulateAutoplay(Beatmap<ShapeHitObject> beatmap)
|
||||
{
|
||||
hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate;
|
||||
totalAccurateJudgements = beatmap.HitObjects.Count;
|
||||
|
||||
foreach (var unused in beatmap.HitObjects)
|
||||
{
|
||||
AddJudgement(new ShapeJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnNewJudgement(Judgement judgement)
|
||||
{
|
||||
base.OnNewJudgement(judgement);
|
||||
|
||||
var shapeJudgement = (ShapeJudgement)judgement;
|
||||
|
||||
if (judgement != null)
|
||||
{
|
||||
if (judgement.Result != HitResult.None)
|
||||
{
|
||||
scoreResultCounts[judgement.Result] = scoreResultCounts.GetOrDefault(judgement.Result) + 1;
|
||||
comboResultCounts[shapeJudgement.Combo] = comboResultCounts.GetOrDefault(shapeJudgement.Combo) + 1;
|
||||
}
|
||||
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case HitResult.Great:
|
||||
Health.Value = Health.Value + 0.05f;
|
||||
break;
|
||||
case HitResult.Miss:
|
||||
Health.Value = Health.Value - 0.1f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Platform;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Settings
|
||||
{
|
||||
public class ShapeConfigManager : IniConfigManager<ShapeSetting>
|
||||
{
|
||||
protected override string Filename => @"shape.ini";
|
||||
|
||||
public ShapeConfigManager(Storage storage) : base(storage) { }
|
||||
|
||||
protected override void InitialiseDefaults()
|
||||
{
|
||||
Set(ShapeSetting.Skin, "default");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum ShapeSetting
|
||||
{
|
||||
Skin
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using Symcol.Rulesets.Core;
|
||||
using Symcol.Rulesets.Core.Wiki;
|
||||
using osu.Game.Rulesets.Shape.Wiki;
|
||||
using Symcol.Rulesets.Core.Multiplayer.Screens;
|
||||
using osu.Game.Rulesets.Shape.Multi;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Settings
|
||||
{
|
||||
public class ShapeSettings : SymcolSettingsSubsection
|
||||
{
|
||||
protected override string Header => "shape!";
|
||||
|
||||
public override WikiOverlay Wiki => shapeWiki;
|
||||
|
||||
private readonly ShapeWikiOverlay shapeWiki = new ShapeWikiOverlay();
|
||||
|
||||
public override RulesetLobbyItem RulesetLobbyItem => shapeLobby;
|
||||
|
||||
private readonly ShapeLobbyItem shapeLobby = new ShapeLobbyItem();
|
||||
|
||||
public static ShapeConfigManager ShapeConfigManager;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host, Storage storage)
|
||||
{
|
||||
ShapeConfigManager = new ShapeConfigManager(host.Storage);
|
||||
|
||||
Storage skinsStorage = storage.GetStorageForDirectory("Skins");
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsButton
|
||||
{
|
||||
Text = "Open In-game Wiki",
|
||||
Action = shapeWiki.Show
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
using osu.Game.Rulesets.Shape.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape
|
||||
{
|
||||
public class ShapeDifficultyCalculator : DifficultyCalculator<ShapeHitObject>
|
||||
{
|
||||
private const double star_scaling_factor = 0.0675;
|
||||
private const double extreme_scaling_factor = 0.5;
|
||||
|
||||
internal List<ShapeHitObjectDifficulty> DifficultyHitObjects = new List<ShapeHitObjectDifficulty>();
|
||||
|
||||
public ShapeDifficultyCalculator(Beatmap beatmap, Mod[] mods) : base(beatmap, mods) { }
|
||||
|
||||
public ShapeDifficultyCalculator(Beatmap beatmap) : base(beatmap) { }
|
||||
|
||||
protected override void PreprocessHitObjects()
|
||||
{
|
||||
foreach (var h in Beatmap.HitObjects) { }
|
||||
}
|
||||
|
||||
protected override BeatmapConverter<ShapeHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ShapeBeatmapConverter();
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
|
||||
{
|
||||
// Fill our custom DifficultyHitObject class, that carries additional information
|
||||
DifficultyHitObjects.Clear();
|
||||
|
||||
foreach (var hitObject in Beatmap.HitObjects)
|
||||
DifficultyHitObjects.Add(new ShapeHitObjectDifficulty(hitObject));
|
||||
|
||||
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
|
||||
DifficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
||||
|
||||
if (!CalculateStrainValues()) return 0;
|
||||
|
||||
double speedDifficulty = (CalculateDifficulty(DifficultyType.Speed) * 0.75f);
|
||||
double aimDifficulty = (CalculateDifficulty(DifficultyType.Aim) * 1.5f);
|
||||
|
||||
double speedStars = Math.Sqrt(speedDifficulty) * star_scaling_factor;
|
||||
double aimStars = Math.Sqrt(aimDifficulty) * star_scaling_factor;
|
||||
|
||||
double starRating = speedStars + aimStars + Math.Abs(speedStars - aimStars) * extreme_scaling_factor;
|
||||
|
||||
return starRating;
|
||||
}
|
||||
|
||||
protected bool CalculateStrainValues()
|
||||
{
|
||||
// Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment.
|
||||
using (List<ShapeHitObjectDifficulty>.Enumerator hitObjectsEnumerator = DifficultyHitObjects.GetEnumerator())
|
||||
{
|
||||
|
||||
if (!hitObjectsEnumerator.MoveNext()) return false;
|
||||
|
||||
ShapeHitObjectDifficulty current = hitObjectsEnumerator.Current;
|
||||
|
||||
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
|
||||
while (hitObjectsEnumerator.MoveNext())
|
||||
{
|
||||
var next = hitObjectsEnumerator.Current;
|
||||
next?.CalculateStrains(current, TimeRate);
|
||||
current = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected const double STRAIN_STEP = 200;
|
||||
protected const double DECAY_WEIGHT = 0.75;
|
||||
|
||||
protected double CalculateDifficulty(DifficultyType type)
|
||||
{
|
||||
double actualStrainStep = STRAIN_STEP * TimeRate;
|
||||
|
||||
List<double> highestStrains = new List<double>();
|
||||
double intervalEndTime = actualStrainStep;
|
||||
double maximumStrain = 0;
|
||||
|
||||
ShapeHitObjectDifficulty previousHitObject = null;
|
||||
foreach (ShapeHitObjectDifficulty hitObject in DifficultyHitObjects)
|
||||
{
|
||||
while (hitObject.BaseHitObject.StartTime > intervalEndTime)
|
||||
{
|
||||
highestStrains.Add(maximumStrain);
|
||||
|
||||
// The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay
|
||||
// until the beginning of the next interval.
|
||||
if (previousHitObject == null)
|
||||
{
|
||||
maximumStrain = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double decay = Math.Pow(ShapeHitObjectDifficulty.DECAY_BASE[(int)type], (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000);
|
||||
maximumStrain = previousHitObject.Strains[(int)type] * decay;
|
||||
}
|
||||
|
||||
// Go to the next time interval
|
||||
intervalEndTime += actualStrainStep;
|
||||
}
|
||||
|
||||
// Obtain maximum strain
|
||||
maximumStrain = Math.Max(hitObject.Strains[(int)type], maximumStrain);
|
||||
|
||||
previousHitObject = hitObject;
|
||||
}
|
||||
|
||||
// Build the weighted sum over the highest strains for each interval
|
||||
double difficulty = 0;
|
||||
double weight = 1;
|
||||
highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
|
||||
|
||||
foreach (double strain in highestStrains)
|
||||
{
|
||||
difficulty += weight * strain;
|
||||
weight *= DECAY_WEIGHT;
|
||||
}
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
public enum DifficultyType
|
||||
{
|
||||
Speed = 0,
|
||||
Aim,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape
|
||||
{
|
||||
class ShapeInputManager : RulesetInputManager<ShapeAction>
|
||||
{
|
||||
public ShapeInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public enum ShapeAction
|
||||
{
|
||||
//Movement
|
||||
[Description("West Left")]
|
||||
WestLeftButton,
|
||||
[Description("West Right")]
|
||||
WestRightButton,
|
||||
[Description("East Left")]
|
||||
EastLeftButton,
|
||||
[Description("East Right")]
|
||||
EastRightButton,
|
||||
[Description("North Left")]
|
||||
NorthLeftButton,
|
||||
[Description("North Right")]
|
||||
NorthRightButton,
|
||||
[Description("South Left")]
|
||||
SouthLeftButton,
|
||||
[Description("South Right")]
|
||||
SouthRightButton,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Shape.Mods;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Shape.Settings;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape
|
||||
{
|
||||
public class ShapeRuleset : Ruleset
|
||||
{
|
||||
public override Drawable CreateIcon() => new Sprite { Texture = ShapeTextures.Get("icon") };
|
||||
|
||||
public static ResourceStore<byte[]> ShapeResources;
|
||||
public static TextureStore ShapeTextures;
|
||||
public static AudioManager ShapeClassicAudio;
|
||||
|
||||
public ShapeRuleset(RulesetInfo rulesetInfo)
|
||||
: base(rulesetInfo)
|
||||
{
|
||||
ShapeResources = new ResourceStore<byte[]>();
|
||||
ShapeResources.AddStore(new NamespacedResourceStore<byte[]>(new DllResourceStore("osu.Game.Rulesets.Shape.dll"), ("Assets")));
|
||||
ShapeResources.AddStore(new DllResourceStore("osu.Game.Rulesets.Shape.dll"));
|
||||
ShapeTextures = new TextureStore(new RawTextureLoaderStore(new NamespacedResourceStore<byte[]>(ShapeResources, @"Textures")));
|
||||
ShapeTextures.AddStore(new RawTextureLoaderStore(new OnlineStore()));
|
||||
}
|
||||
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ShapeRulesetContainer(this, beatmap, isForCurrentRuleset);
|
||||
|
||||
public override int? LegacyID => 5;
|
||||
|
||||
public override string Description => "shape!";
|
||||
|
||||
public override string ShortName => "shape";
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ShapeDifficultyCalculator(beatmap, mods);
|
||||
|
||||
public override SettingsSubsection CreateSettings() => new ShapeSettings();
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
new KeyBinding(InputKey.A, ShapeAction.EastLeftButton),
|
||||
new KeyBinding(InputKey.S, ShapeAction.WestLeftButton),
|
||||
new KeyBinding(InputKey.D, ShapeAction.NorthLeftButton),
|
||||
new KeyBinding(InputKey.F, ShapeAction.SouthLeftButton),
|
||||
new KeyBinding(InputKey.J, ShapeAction.SouthRightButton),
|
||||
new KeyBinding(InputKey.K, ShapeAction.NorthRightButton),
|
||||
new KeyBinding(InputKey.L, ShapeAction.WestRightButton),
|
||||
new KeyBinding(InputKey.Semicolon, ShapeAction.EastRightButton),
|
||||
};
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ModType.DifficultyReduction:
|
||||
return new Mod[]
|
||||
{
|
||||
new ShapeModEasy(),
|
||||
new ShapeModNoFail(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ShapeModHalfTime(),
|
||||
new ShapeModDaycore(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
case ModType.DifficultyIncrease:
|
||||
return new Mod[]
|
||||
{
|
||||
new ShapeModHardRock(),
|
||||
new ShapeModSuddenDeath(),
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ShapeModDoubleTime(),
|
||||
new ShapeModNightcore(),
|
||||
},
|
||||
},
|
||||
new MultiMod
|
||||
{
|
||||
Mods = new Mod[]
|
||||
{
|
||||
new ShapeModHidden(),
|
||||
new ShapeModFlashlight(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
case ModType.Special:
|
||||
return new Mod[]
|
||||
{
|
||||
new ShapeRelax()
|
||||
};
|
||||
default : return new Mod[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
using osu.Game.Rulesets.Shape.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Shape.Judgements;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.UI
|
||||
{
|
||||
public class ShapePlayfield : Playfield
|
||||
{
|
||||
private Container shapePlayfield;
|
||||
private readonly Container judgementLayer;
|
||||
|
||||
//public override bool ProvidingUserCursor => false;
|
||||
|
||||
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
|
||||
|
||||
public override Vector2 Size
|
||||
{
|
||||
get
|
||||
{
|
||||
var parentSize = Parent.DrawSize;
|
||||
var aspectSize = parentSize.X * 0.75f < parentSize.Y ? new Vector2(parentSize.X, parentSize.X * 0.75f) : new Vector2(parentSize.Y * 4f / 3f, parentSize.Y);
|
||||
|
||||
return new Vector2(aspectSize.X / parentSize.X, aspectSize.Y / parentSize.Y) * base.Size;
|
||||
}
|
||||
}
|
||||
|
||||
public ShapePlayfield() : base(BASE_SIZE.X)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
shapePlayfield = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -3,
|
||||
},
|
||||
judgementLayer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -2,
|
||||
},
|
||||
//Will need custom UI like vitaru does it
|
||||
});
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject h)
|
||||
{
|
||||
h.Depth = (float)h.HitObject.StartTime;
|
||||
|
||||
h.OnJudgement += onJudgement;
|
||||
|
||||
IDrawableHitObjectWithProxiedApproach c = h as IDrawableHitObjectWithProxiedApproach;
|
||||
if (c != null)
|
||||
shapePlayfield.Add(c.ProxiedLayer.CreateProxy());
|
||||
|
||||
base.Add(h);
|
||||
}
|
||||
|
||||
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||
{
|
||||
var shapeJudgement = (ShapeJudgement)judgement;
|
||||
var shapeObject = (ShapeHitObject)judgedObject.HitObject;
|
||||
|
||||
DrawableShapeJudgement explosion = new DrawableShapeJudgement(shapeJudgement, judgedObject)
|
||||
{
|
||||
Scale = new Vector2(0.5f),
|
||||
Alpha = 0.5f,
|
||||
Origin = Anchor.Centre,
|
||||
Position = judgedObject.Position,
|
||||
};
|
||||
|
||||
judgementLayer.Add(explosion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.Shape.Judgements;
|
||||
using osu.Game.Rulesets.Shape.Objects;
|
||||
using osu.Game.Rulesets.Shape.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Shape.Beatmaps;
|
||||
using osu.Game.Rulesets.Shape.UI;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Shape.Scoring;
|
||||
using osu.Framework.Input;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape
|
||||
{
|
||||
internal class ShapeRulesetContainer : RulesetContainer<ShapeHitObject>
|
||||
{
|
||||
public ShapeRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
{
|
||||
}
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new ShapeScoreProcessor(this);
|
||||
|
||||
protected override BeatmapConverter<ShapeHitObject> CreateBeatmapConverter() => new ShapeBeatmapConverter();
|
||||
|
||||
protected override BeatmapProcessor<ShapeHitObject> CreateBeatmapProcessor() => new ShapeBeatmapProcessor();
|
||||
|
||||
protected override Playfield CreatePlayfield() => new ShapePlayfield();
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new ShapeInputManager(Ruleset.RulesetInfo);
|
||||
|
||||
protected override DrawableHitObject<ShapeHitObject> GetVisualRepresentation(ShapeHitObject h)
|
||||
{
|
||||
var shape = h as BaseShape;
|
||||
if (shape != null)
|
||||
return new DrawableBaseShape(shape);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override Vector2 GetAspectAdjustedSize() => new Vector2(0.75f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Symcol.Rulesets.Core.Wiki;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Wiki.Sections
|
||||
{
|
||||
public class Gameplay : WikiSection
|
||||
{
|
||||
public override string Title => "Gameplay";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Users;
|
||||
using Symcol.Rulesets.Core.Wiki;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Wiki
|
||||
{
|
||||
public class ShapeWikiHeader : WikiHeader
|
||||
{
|
||||
protected override Texture RulesetIcon => ShapeRuleset.ShapeTextures.Get("icon");
|
||||
|
||||
protected override string RulesetName => "shape";
|
||||
|
||||
protected override string RulesetDescription => "shape! is a 3rd party ruleset developed for osu!lazer.";
|
||||
|
||||
protected override string RulesetUrl => $@"https://github.com/Symcol/osu/tree/symcol/osu.Game.Rulesets.Shape";
|
||||
|
||||
protected override User Creator => new User
|
||||
{
|
||||
Username = "Shawdooow",
|
||||
Id = 7726082
|
||||
};
|
||||
|
||||
protected override string DiscordInvite => $@"https://discord.gg/JvS5cxA";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using osu.Game.Rulesets.Shape.Wiki.Sections;
|
||||
using Symcol.Rulesets.Core.Wiki;
|
||||
|
||||
namespace osu.Game.Rulesets.Shape.Wiki
|
||||
{
|
||||
public class ShapeWikiOverlay : WikiOverlay
|
||||
{
|
||||
protected override WikiHeader Header => new ShapeWikiHeader();
|
||||
|
||||
protected override WikiSection[] Sections => new WikiSection[]
|
||||
{
|
||||
new Gameplay()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-0.18.1.0" newVersion="0.18.1.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{BAF6D7B6-5E48-4278-AB81-F079AF640E31}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>osu.Game.Rulesets.Shape</RootNamespace>
|
||||
<AssemblyName>osu.Game.Rulesets.Shape</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\osu.Game\bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\osu.Game\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Beatmaps\ShapeBeatmapConverter.cs" />
|
||||
<Compile Include="Beatmaps\ShapeBeatmapProcessor.cs" />
|
||||
<Compile Include="Judgements\ShapeJudgement.cs" />
|
||||
<Compile Include="Multi\ShapeLobbyItem.cs" />
|
||||
<Compile Include="Multi\ShapeLobbyScreen.cs" />
|
||||
<Compile Include="Multi\ShapeMatchScreen.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\Arrow.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\Circle.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\Square.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\Triangle.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\X.cs" />
|
||||
<Compile Include="Objects\BaseShape.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableBaseShape.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableShapeJudgement.cs" />
|
||||
<Compile Include="Mods\ShapeMod.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableShapeHitObject.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\BaseDial.cs" />
|
||||
<Compile Include="Objects\HitObjectType.cs" />
|
||||
<Compile Include="Objects\ShapeHitObjectDifficulty.cs" />
|
||||
<Compile Include="Objects\ShapeHitObject.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Settings\ShapeConfigManager.cs" />
|
||||
<Compile Include="Settings\ShapeSettings.cs" />
|
||||
<Compile Include="ShapeDifficultyCalculator.cs" />
|
||||
<Compile Include="UI\ShapeRulsesetContainer.cs" />
|
||||
<Compile Include="Scoring\ShapeScoreProcessor.cs" />
|
||||
<Compile Include="UI\ShapePlayfield.cs" />
|
||||
<Compile Include="ShapeRuleset.cs" />
|
||||
<Compile Include="ShapeInputManager.cs" />
|
||||
<Compile Include="Wiki\Sections\Gamemodes.cs" />
|
||||
<Compile Include="Wiki\ShapeWikiHeader.cs" />
|
||||
<Compile Include="Wiki\ShapeWikiOverlay.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="OpenTK.dll.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
<Project>{C76BF5B3-985E-4D39-95FE-97C9C879B83A}</Project>
|
||||
<Name>osu.Framework</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu-resources\osu.Game.Resources\osu.Game.Resources.csproj">
|
||||
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
|
||||
<Name>osu.Game.Resources</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||
<Project>{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Symcol.Rulesets.Core\Symcol.Rulesets.Core.csproj">
|
||||
<Project>{552b5940-c647-4060-aa4d-61baac415c72}</Project>
|
||||
<Name>Symcol.Rulesets.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Assets\Audio\" />
|
||||
<Folder Include="Assets\Font\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Assets\Textures\icon.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NUnit" version="3.8.1" targetFramework="net461" />
|
||||
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -20,11 +20,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
public class DrawableDrumRoll : DrawableTaikoHitObject<DrumRoll>
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of rolling hits required to reach the dark/final accent colour.
|
||||
/// Number of rolling hits required to reach the dark/final colour.
|
||||
/// </summary>
|
||||
private const int rolling_hits_for_dark_accent = 5;
|
||||
|
||||
private Color4 accentDarkColour;
|
||||
private const int rolling_hits_for_engaged_colour = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Rolling number of tick hits. This increases for hits and decreases for misses.
|
||||
@@ -53,11 +51,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
|
||||
public override bool OnPressed(TaikoAction action) => false;
|
||||
|
||||
private Color4 colourIdle;
|
||||
private Color4 colourEngaged;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
MainPiece.AccentColour = AccentColour = colours.YellowDark;
|
||||
accentDarkColour = colours.YellowDarker;
|
||||
MainPiece.AccentColour = colourIdle = colours.YellowDark;
|
||||
colourEngaged = colours.YellowDarker;
|
||||
}
|
||||
|
||||
private void onTickJudgement(DrawableHitObject obj, Judgement judgement)
|
||||
@@ -67,10 +68,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
else
|
||||
rollingHits--;
|
||||
|
||||
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_dark_accent);
|
||||
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour);
|
||||
|
||||
Color4 newAccent = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_dark_accent, AccentColour, accentDarkColour, 0, 1);
|
||||
MainPiece.FadeAccent(newAccent, 100);
|
||||
Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1);
|
||||
MainPiece.FadeAccent(newColour, 100);
|
||||
}
|
||||
|
||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
|
||||
|
||||
protected override IEnumerable<VitaruHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
|
||||
{
|
||||
var curveData = original as IHasCurve;
|
||||
var endTimeData = original as IHasEndTime;
|
||||
var positionData = original as IHasPosition;
|
||||
var comboData = original as IHasCombo;
|
||||
@@ -43,9 +42,8 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
|
||||
bool isCoolWave = samples.Any(s => s.Name == SampleInfo.HIT_CLAP);
|
||||
|
||||
Pattern p;
|
||||
Pattern a;
|
||||
|
||||
if (curveData != null)
|
||||
if (original is IHasCurve curveData)
|
||||
{
|
||||
if (isLine)
|
||||
{
|
||||
@@ -245,8 +243,7 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
a = p;
|
||||
HitObjectList.Add(a);
|
||||
HitObjectList.Add(p);
|
||||
yield return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,23 +7,7 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
|
||||
{
|
||||
public override void PostProcess(Beatmap<VitaruHitObject> beatmap)
|
||||
{
|
||||
if (beatmap.ComboColours.Count == 0)
|
||||
return;
|
||||
|
||||
int comboIndex = 0;
|
||||
int colourIndex = 0;
|
||||
|
||||
foreach (var obj in beatmap.HitObjects)
|
||||
{
|
||||
if (obj.NewCombo)
|
||||
{
|
||||
comboIndex = 0;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
|
||||
}
|
||||
|
||||
obj.ComboIndex = comboIndex++;
|
||||
obj.ComboColour = beatmap.ComboColours[colourIndex];
|
||||
}
|
||||
base.PostProcess(beatmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,13 +70,12 @@ namespace osu.Game.Rulesets.Vitaru.Multi
|
||||
|
||||
protected override void Load(List<ClientInfo> playerList)
|
||||
{
|
||||
base.Load(playerList);
|
||||
|
||||
MakeCurrent();
|
||||
foreach (ClientInfo client in playerList)
|
||||
if (client is VitaruClientInfo vitaruClientInfo)
|
||||
VitaruPlayfield.LoadPlayerList.Add(vitaruClientInfo);
|
||||
|
||||
Push(new MultiPlayer(VitaruNetworkingClientHandler));
|
||||
Push(new MultiPlayer(VitaruNetworkingClientHandler, playerList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,5 +24,7 @@ namespace osu.Game.Rulesets.Vitaru.Multi
|
||||
public Dictionary<VitaruAction, bool> Actions;
|
||||
|
||||
public VitaruAction PressedAction;
|
||||
|
||||
public VitaruAction ReleasedAction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Characters
|
||||
AlwaysPresent = true;
|
||||
CharacterName = "enemy";
|
||||
Team = 1;
|
||||
CharacterColor = pattern.ComboColour;
|
||||
CharacterColor = drawablePattern.AccentColour;
|
||||
HitboxWidth = 27;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Vitaru.Objects.Characters.Pieces
|
||||
{
|
||||
public class Seal : Container
|
||||
{
|
||||
private readonly Container characterSigil;
|
||||
|
||||
private readonly VitaruPlayer vitaruPlayer;
|
||||
|
||||
private readonly Sprite gear1;
|
||||
private readonly Sprite gear2;
|
||||
private readonly Sprite gear3;
|
||||
private readonly Sprite gear4;
|
||||
private readonly Sprite gear5;
|
||||
|
||||
public Seal(VitaruPlayer character)
|
||||
{
|
||||
vitaruPlayer = character;
|
||||
|
||||
Color4 lightColor = vitaruPlayer.CharacterColor.Lighten(0.5f);
|
||||
Color4 darkColor = vitaruPlayer.CharacterColor.Darken(0.5f);
|
||||
|
||||
Scale = new Vector2(0.6f);
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
AlwaysPresent = true;
|
||||
Alpha = 0.5f;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
characterSigil = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Masking = true,
|
||||
Size = new Vector2(90),
|
||||
CornerRadius = 45
|
||||
},
|
||||
new Sprite
|
||||
{
|
||||
Colour = vitaruPlayer.CharacterColor,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("seal"),
|
||||
},
|
||||
};
|
||||
|
||||
switch (vitaruPlayer.CurrentCharacter)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case Characters.SakuyaIzayoi:
|
||||
characterSigil.Children = new Drawable[]
|
||||
{
|
||||
gear1 = new Sprite
|
||||
{
|
||||
Colour = lightColor,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("gearSmall"),
|
||||
Position = new Vector2(-41, 10),
|
||||
},
|
||||
gear2 = new Sprite
|
||||
{
|
||||
Colour = vitaruPlayer.CharacterColor,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("gearMedium"),
|
||||
Position = new Vector2(-4, 16),
|
||||
},
|
||||
gear3 = new Sprite
|
||||
{
|
||||
Colour = darkColor,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("gearLarge"),
|
||||
Position = new Vector2(-16, -34),
|
||||
},
|
||||
gear4 = new Sprite
|
||||
{
|
||||
Colour = vitaruPlayer.CharacterColor,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("gearMedium"),
|
||||
Position = new Vector2(35, -40),
|
||||
},
|
||||
gear5 = new Sprite
|
||||
{
|
||||
Colour = lightColor,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("gearSmall"),
|
||||
Position = new Vector2(33, 8),
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
this.RotateTo((float)(-Clock.CurrentTime / 1000 * 90) * 0.1f);
|
||||
|
||||
switch (vitaruPlayer.CurrentCharacter)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case Characters.SakuyaIzayoi:
|
||||
float speed = 0.25f;
|
||||
gear1.RotateTo((float)(Clock.CurrentTime / 1000 * 90) * 1.25f * speed);
|
||||
gear2.RotateTo((float)(-Clock.CurrentTime / 1000 * 90) * 1.1f * speed);
|
||||
gear3.RotateTo((float)(Clock.CurrentTime / 1000 * 90) * speed);
|
||||
gear4.RotateTo((float)(-Clock.CurrentTime / 1000 * 90) * 1.1f * speed);
|
||||
gear5.RotateTo((float)(Clock.CurrentTime / 1000 * 90) * 1.25f * speed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Characters.Pieces
|
||||
Team = ParentCharacter.Team,
|
||||
BulletSpeed = 0.8f,
|
||||
BulletDamage = 5,
|
||||
ComboColour = ParentCharacter.CharacterColor,
|
||||
ColorOverride = ParentCharacter.CharacterColor,
|
||||
StartAngle = StartAngle,
|
||||
}));
|
||||
s.MoveTo(ToSpaceOfOtherDrawable(new Vector2(0, 0), s));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
private bool loaded;
|
||||
private bool started;
|
||||
private bool done;
|
||||
|
||||
private readonly double endTime;
|
||||
|
||||
private int currentRepeat;
|
||||
|
||||
@@ -37,9 +39,12 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
this.pattern = pattern;
|
||||
|
||||
if (!pattern.IsSlider && !pattern.IsSpinner)
|
||||
this.pattern.EndTime = this.pattern.StartTime + TIME_FADEOUT;
|
||||
{
|
||||
endTime = this.pattern.StartTime + TIME_FADEOUT;
|
||||
this.pattern.EndTime = endTime;
|
||||
}
|
||||
else if (pattern.IsSlider)
|
||||
this.pattern.EndTime += TIME_FADEOUT;
|
||||
endTime = this.pattern.EndTime += TIME_FADEOUT;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -48,9 +53,6 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
|
||||
PatternCount++;
|
||||
|
||||
if (pattern.IsSlider)
|
||||
pattern.EndTime = pattern.StartTime + pattern.RepeatCount * pattern.Curve.Distance / pattern.Velocity;
|
||||
|
||||
LifetimeStart = pattern.StartTime - (TIME_PREEMPT + 1000f);
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
Size = new Vector2(30),
|
||||
CornerRadius = 30f / 2,
|
||||
BorderThickness = 10,
|
||||
BorderColour = pattern.ComboColour,
|
||||
BorderColour = AccentColour,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
@@ -92,7 +94,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = pattern.ComboColour.Opacity(0.5f),
|
||||
Colour = AccentColour.Opacity(0.5f),
|
||||
Radius = Width / 2,
|
||||
}
|
||||
};
|
||||
@@ -109,7 +111,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(20),
|
||||
BorderThickness = 6,
|
||||
BorderColour = pattern.ComboColour,
|
||||
BorderColour = AccentColour,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
@@ -120,7 +122,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = pattern.ComboColour.Opacity(0.5f),
|
||||
Colour = AccentColour.Opacity(0.5f),
|
||||
Radius = Width / 2,
|
||||
}
|
||||
};
|
||||
@@ -141,7 +143,6 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
foreach (var o in pattern.NestedHitObjects)
|
||||
{
|
||||
var b = (Bullet)o;
|
||||
b.ComboColour = pattern.ComboColour;
|
||||
DrawableBullet drawableBullet = new DrawableBullet(ParentContainer, b, this);
|
||||
ParentContainer.Add(drawableBullet);
|
||||
AddNested(drawableBullet);
|
||||
@@ -304,9 +305,8 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
#region Slider Stuff
|
||||
private void sliderUpdate()
|
||||
{
|
||||
double progress = MathHelper.Clamp((Time.Current - pattern.StartTime) / pattern.Duration, 0, 1);
|
||||
int repeat = pattern.RepeatAt(progress);
|
||||
progress = pattern.ProgressAt(progress);
|
||||
double completionProgress = MathHelper.Clamp((Time.Current - pattern.StartTime) / pattern.Duration, 0, 1);
|
||||
int repeat = pattern.RepeatAt(completionProgress);
|
||||
|
||||
if (HitObject.StartTime <= Time.Current && !started)
|
||||
{
|
||||
@@ -316,9 +316,9 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
|
||||
if (!done && started)
|
||||
{
|
||||
Position = pattern.Curve.PositionAt(progress);
|
||||
Position = pattern.PositionAt(completionProgress);
|
||||
if (currentGameMode != VitaruGamemode.Dodge)
|
||||
enemy.Position = pattern.Curve.PositionAt(progress);
|
||||
enemy.Position = pattern.PositionAt(completionProgress);
|
||||
}
|
||||
|
||||
if (repeat > currentRepeat)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using Symcol.Rulesets.Core.HitObjects;
|
||||
using System.ComponentModel;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
{
|
||||
@@ -12,6 +15,16 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
|
||||
|
||||
public readonly Framework.Graphics.Containers.Container ParentContainer;
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
|
||||
if (HitObject is IHasComboInformation combo && HitObject.ColorOverride == Color4.White)
|
||||
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
|
||||
else
|
||||
AccentColour = HitObject.ColorOverride;
|
||||
}
|
||||
|
||||
public DrawableVitaruHitObject(VitaruHitObject hitObject, Framework.Graphics.Containers.Container parent) : base(hitObject)
|
||||
{
|
||||
ParentContainer = parent;
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
|
||||
Alpha = 0,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Colour = drawableBullet.Bullet.ComboColour,
|
||||
Colour = drawableBullet.AccentColour,
|
||||
Texture = VitaruRuleset.VitaruTextures.Get("bulletKiai"),
|
||||
};
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 1,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderColour = drawableBullet.Bullet.ComboColour,
|
||||
BorderColour = drawableBullet.AccentColour,
|
||||
BorderThickness = 6,
|
||||
Masking = true,
|
||||
|
||||
@@ -103,10 +103,10 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
|
||||
{
|
||||
Radius = drawableBullet.Bullet.BulletDiameter,
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = drawableBullet.Bullet.ComboColour.Opacity(0.2f)
|
||||
Colour = drawableBullet.AccentColour.Opacity(0.2f)
|
||||
};
|
||||
|
||||
if (drawableBullet.Bullet.Ghost && currentCharacter == Characters.Characters.Kaguya | currentCharacter == Characters.Characters.AliceMuyart)
|
||||
if (drawableBullet.Bullet.Ghost && currentCharacter == Characters.Characters.YuyukoSaigyouji | currentCharacter == Characters.Characters.AliceMuyart)
|
||||
box.Colour = Color4.Cyan;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
|
||||
CornerRadius = 16;
|
||||
|
||||
BorderThickness = 8;
|
||||
BorderColour = drawableLaser.Laser.ComboColour;
|
||||
BorderColour = drawableLaser.AccentColour;
|
||||
|
||||
Child = new Box
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
|
||||
Anchor = Anchor.Centre;
|
||||
BorderThickness = 4;
|
||||
AlwaysPresent = true;
|
||||
BorderColour = seekingBullet.SeekingBullet.ComboColour;
|
||||
BorderColour = seekingBullet.AccentColour;
|
||||
CornerRadius = 4;
|
||||
|
||||
Child = new Box
|
||||
@@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Radius = 8,
|
||||
Colour = seekingBullet.SeekingBullet.ComboColour.Opacity(0.25f),
|
||||
Colour = seekingBullet.AccentColour.Opacity(0.25f),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user