-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParticles.cs
156 lines (123 loc) · 5.44 KB
/
Particles.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using OpenTK;
using OpenTK.Graphics;
using StorybrewCommon.Mapset;
using StorybrewCommon.Scripting;
using StorybrewCommon.Storyboarding;
using StorybrewCommon.Util;
using System;
using System.Drawing;
using System.Linq;
namespace StorybrewScripts
{
public class Particles : StoryboardObjectGenerator
{
[Configurable]
public string Path = "sb/particle.png";
[Configurable]
public int StartTime;
[Configurable]
public int EndTime;
[Configurable]
public int ParticleCount = 32;
[Configurable]
public Vector2 Scale = new Vector2(1, 1);
[Configurable]
public float Rotation = 0;
[Configurable]
public OsbOrigin Origin = OsbOrigin.Centre;
[Configurable]
public Color4 Color = Color4.White;
[Configurable]
public float ColorVariance = 0.6f;
[Configurable]
public bool Additive = false;
[Configurable]
public Vector2 SpawnOrigin = new Vector2(420, 0);
[Configurable]
public float SpawnSpread = 360;
[Configurable]
public float Angle = 110;
[Configurable]
public float AngleSpread = 60;
[Configurable]
public float Speed = 480;
[Configurable]
public float Lifetime = 1000;
[Configurable]
public OsbEasing Easing = OsbEasing.None;
public override void Generate()
{
if (StartTime == EndTime && Beatmap.HitObjects.FirstOrDefault() != null)
{
StartTime = (int)Beatmap.HitObjects.First().StartTime;
EndTime = (int)Beatmap.HitObjects.Last().EndTime;
}
EndTime = Math.Min(EndTime, (int)AudioDuration);
StartTime = Math.Min(StartTime, EndTime);
var bitmap = GetMapsetBitmap(Path);
var duration = (double)(EndTime - StartTime);
var loopCount = Math.Max(1, (int)Math.Floor(duration / Lifetime));
var layer = GetLayer("");
for (var i = 0; i < ParticleCount; i++)
{
var spawnAngle = Random(Math.PI * 2);
var spawnDistance = (float)(SpawnSpread * Math.Sqrt(Random(1f)));
var moveAngle = MathHelper.DegreesToRadians(Angle + Random(-AngleSpread, AngleSpread) * 0.5f);
var moveDistance = Speed * Lifetime * 0.001f;
var spriteRotation = moveAngle + MathHelper.DegreesToRadians(Rotation);
var startPosition = SpawnOrigin + new Vector2((float)Math.Cos(spawnAngle), (float)Math.Sin(spawnAngle)) * spawnDistance;
var endPosition = startPosition + new Vector2((float)Math.Cos(moveAngle), (float)Math.Sin(moveAngle)) * moveDistance;
var loopDuration = duration / loopCount;
var startTime = StartTime + (i * loopDuration) / ParticleCount;
var endTime = startTime + loopDuration * loopCount;
if (!isVisible(bitmap, startPosition, endPosition, (float)spriteRotation, (float)loopDuration))
continue;
var color = Color;
if (ColorVariance > 0)
{
ColorVariance = MathHelper.Clamp(ColorVariance, 0, 1);
var hsba = Color4.ToHsl(color);
var sMin = Math.Max(0, hsba.Y - ColorVariance * 0.5f);
var sMax = Math.Min(sMin + ColorVariance, 1);
var vMin = Math.Max(0, hsba.Z - ColorVariance * 0.5f);
var vMax = Math.Min(vMin + ColorVariance, 1);
color = Color4.FromHsl(new Vector4(
hsba.X,
(float)Random(sMin, sMax),
(float)Random(vMin, vMax),
hsba.W));
}
var particle = layer.CreateSprite(Path, Origin);
if (spriteRotation != 0)
particle.Rotate(startTime, spriteRotation);
if (color.R != 1 || color.G != 1 || color.B != 1)
particle.Color(startTime, color);
if (Scale.X != 1 || Scale.Y != 1)
{
if (Scale.X != Scale.Y)
particle.ScaleVec(startTime, Scale.X, Scale.Y);
else particle.Scale(startTime, Scale.X);
}
if (Additive)
particle.Additive(startTime, endTime);
particle.StartLoopGroup(startTime, loopCount);
particle.Fade(OsbEasing.Out, 0, loopDuration * 0.2, 0, color.A);
particle.Fade(OsbEasing.In, loopDuration * 0.8, loopDuration, color.A, 0);
particle.Move(Easing, 0, loopDuration, startPosition, endPosition);
particle.EndGroup();
}
}
private bool isVisible(Bitmap bitmap, Vector2 startPosition, Vector2 endPosition, float rotation, float duration)
{
var spriteSize = new Vector2(bitmap.Width * Scale.X, bitmap.Height * Scale.Y);
var originVector = OsbSprite.GetOriginVector(Origin, spriteSize.X, spriteSize.Y);
for (var t = 0; t < duration; t += 200)
{
var position = Vector2.Lerp(startPosition, endPosition, t / duration);
if (OsbSprite.InScreenBounds(position, spriteSize, rotation, originVector))
return true;
}
return false;
}
}
}