1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 07:22:55 +08:00

Merge pull request #833 from peppy/logo-beat

Animate osu! logo with playing beatmap
This commit is contained in:
Dean Herbert 2017-05-24 11:56:22 +09:00 committed by GitHub
commit 5efe693e79
3 changed files with 154 additions and 90 deletions

@ -1 +1 @@
Subproject commit 773d60eb6b811f395e32a22dc66bb4d2e63a6dbc
Subproject commit 777996fb9731ba1895a5ab1323cbbc97259ff741

View File

@ -12,20 +12,26 @@ namespace osu.Game.Graphics.Containers
{
public class BeatSyncedContainer : Container
{
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
protected readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
private int lastBeat;
private TimingControlPoint lastTimingPoint;
/// <summary>
/// The amount of time before a beat we should fire <see cref="OnNewBeat(int, TimingControlPoint, EffectControlPoint, TrackAmplitudes)"/>.
/// This allows for adding easing to animations that may be synchronised to the beat.
/// </summary>
protected double EarlyActivationMilliseconds;
protected override void Update()
{
if (beatmap.Value?.Track == null)
if (Beatmap.Value?.Track == null)
return;
double currentTrackTime = beatmap.Value.Track.CurrentTime;
double currentTrackTime = Beatmap.Value.Track.CurrentTime + EarlyActivationMilliseconds;
TimingControlPoint timingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
EffectControlPoint effectPoint = beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
TimingControlPoint timingPoint = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
EffectControlPoint effectPoint = Beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
if (timingPoint.BeatLength == 0)
return;
@ -42,7 +48,7 @@ namespace osu.Game.Graphics.Containers
double offsetFromBeat = (timingPoint.Time - currentTrackTime) % timingPoint.BeatLength;
using (BeginDelayedSequence(offsetFromBeat, true))
OnNewBeat(beatIndex, timingPoint, effectPoint, beatmap.Value.Track.CurrentAmplitudes);
OnNewBeat(beatIndex, timingPoint, effectPoint, Beatmap.Value.Track.CurrentAmplitudes);
lastBeat = beatIndex;
lastTimingPoint = timingPoint;
@ -51,7 +57,7 @@ namespace osu.Game.Graphics.Containers
[BackgroundDependencyLoader]
private void load(OsuGameBase game)
{
beatmap.BindTo(game.Beatmap);
Beatmap.BindTo(game.Beatmap);
}
protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)

View File

@ -5,13 +5,16 @@ using System;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Audio.Track;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;
using OpenTK;
using OpenTK.Graphics;
@ -20,13 +23,15 @@ namespace osu.Game.Screens.Menu
/// <summary>
/// osu! logo and its attachments (pulsing, visualiser etc.)
/// </summary>
public class OsuLogo : Container
public class OsuLogo : BeatSyncedContainer
{
public readonly Color4 OsuPink = OsuColour.FromHex(@"e967a1");
private readonly Sprite logo;
private readonly CircularContainer logoContainer;
private readonly Container logoBounceContainer;
private readonly Container logoBeatContainer;
private readonly Container logoAmplitudeContainer;
private readonly Container logoHoverContainer;
private SampleChannel sampleClick;
@ -67,8 +72,12 @@ namespace osu.Game.Screens.Menu
private const float default_size = 480;
private const double beat_in_time = 60;
public OsuLogo()
{
EarlyActivationMilliseconds = beat_in_time;
Size = new Vector2(default_size);
Anchor = Anchor.Centre;
@ -78,67 +87,16 @@ namespace osu.Game.Screens.Menu
Children = new Drawable[]
{
logoBounceContainer = new Container
logoHoverContainer = new Container
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
logoHoverContainer = new Container
logoBounceContainer = new Container
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new BufferedContainer
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
logoContainer = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.88f),
Masking = true,
Children = new Drawable[]
{
colourAndTriangles = new Container
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuPink,
},
new Triangles
{
TriangleScale = 4,
ColourLight = OsuColour.FromHex(@"ff7db7"),
ColourDark = OsuColour.FromHex(@"de5b95"),
RelativeSizeAxes = Axes.Both,
},
}
},
flashLayer = new Box
{
RelativeSizeAxes = Axes.Both,
BlendingMode = BlendingMode.Additive,
Colour = Color4.White,
Alpha = 0,
},
},
},
logo = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
}
},
rippleContainer = new Container
{
Anchor = Anchor.Centre,
@ -151,36 +109,101 @@ namespace osu.Game.Screens.Menu
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
BlendingMode = BlendingMode.Additive,
Alpha = 0.15f
Alpha = 0
}
}
},
impactContainer = new CircularContainer
logoAmplitudeContainer = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 0,
BorderColour = Color4.White,
RelativeSizeAxes = Axes.Both,
BorderThickness = 10,
Masking = true,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new Box
logoBeatContainer = new Container
{
RelativeSizeAxes = Axes.Both,
AlwaysPresent = true,
Alpha = 0,
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
new BufferedContainer
{
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
logoContainer = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.88f),
Masking = true,
Children = new Drawable[]
{
colourAndTriangles = new Container
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuPink,
},
new Triangles
{
TriangleScale = 4,
ColourLight = OsuColour.FromHex(@"ff7db7"),
ColourDark = OsuColour.FromHex(@"de5b95"),
RelativeSizeAxes = Axes.Both,
},
}
},
flashLayer = new Box
{
RelativeSizeAxes = Axes.Both,
BlendingMode = BlendingMode.Additive,
Colour = Color4.White,
Alpha = 0,
},
},
},
logo = new Sprite
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
},
}
},
impactContainer = new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Alpha = 0,
BorderColour = Color4.White,
RelativeSizeAxes = Axes.Both,
BorderThickness = 10,
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
AlwaysPresent = true,
Alpha = 0,
}
}
},
new MenuVisualisation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
BlendingMode = BlendingMode.Additive,
Alpha = 0.2f,
}
}
}
}
},
new MenuVisualisation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
BlendingMode = BlendingMode.Additive,
Alpha = 0.2f,
}
}
}
@ -197,13 +220,48 @@ namespace osu.Game.Screens.Menu
ripple.Texture = textures.Get(@"Menu/logo");
}
protected override void LoadComplete()
{
base.LoadComplete();
private int lastBeatIndex;
ripple.ScaleTo(ripple.Scale * 1.1f, 500);
ripple.FadeOut(500);
ripple.Loop(300);
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
{
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
lastBeatIndex = beatIndex;
var beatLength = timingPoint.BeatLength;
float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum);
if (beatIndex < 0) return;
logoBeatContainer.ScaleTo(1 - 0.02f * amplitudeAdjust, beat_in_time, EasingTypes.Out);
using (logoBeatContainer.BeginDelayedSequence(beat_in_time))
logoBeatContainer.ScaleTo(1, beatLength * 2, EasingTypes.OutQuint);
ripple.ClearTransforms();
ripple.ScaleTo(logoAmplitudeContainer.Scale);
ripple.Alpha = 0.15f * amplitudeAdjust;
ripple.ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, EasingTypes.OutQuint);
ripple.FadeOut(beatLength, EasingTypes.OutQuint);
if (effectPoint.KiaiMode && flashLayer.Alpha < 0.4f)
{
flashLayer.ClearTransforms();
flashLayer.FadeTo(0.2f * amplitudeAdjust, beat_in_time, EasingTypes.Out);
using (flashLayer.BeginDelayedSequence(beat_in_time))
flashLayer.FadeOut(beatLength);
}
}
protected override void Update()
{
base.Update();
var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value?.Track?.CurrentAmplitudes.Maximum ?? 0 : 0;
logoAmplitudeContainer.ScaleTo(1 - maxAmplitude * 0.04f, 50, EasingTypes.OutQuint);
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
@ -254,4 +312,4 @@ namespace osu.Game.Screens.Menu
impactContainer.ScaleTo(1.12f, 250);
}
}
}
}