1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-09-01 03:15:53 +00:00
Funkin/source/funkin/ui/freeplay/DifficultyDot.hx
2025-08-20 05:30:24 +08:00

234 lines
5.7 KiB
Haxe

package funkin.ui.freeplay;
import flixel.FlxSprite;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import flixel.math.FlxMath;
import flixel.group.FlxSpriteGroup;
import flixel.util.FlxColor;
enum DotType
{
NORMAL;
ERECT;
INACTIVE;
}
enum DotState
{
DESELECTING;
DESELECTED;
SELECTED;
}
class DifficultyDot extends FlxSpriteGroup
{
/**
* The difficulty id which this dot represents.
*/
public var difficultyId:String;
public var type:DotType = NORMAL;
public var state:DotState = DESELECTED;
// 0 - deselected, 1 - selected, 2 - pulse color
var normalColors:Array<FlxColor> = [0xFF484848, 0xFFFAFAFA, 0xFF919191, 0xFFC9C9C9];
var nightColors:Array<FlxColor> = [0xFF34296A, 0xFFC28AFF, 0xFF8A58D0, 0xFFFFB1DC];
public var important:Bool = false;
var pulseColor = false;
public var dot:FlxSprite;
public var pulse:FlxSprite;
// var newColors:Array<FlxColor> = [0xFFE86D09, 0xFFE54400, 0xFFE83509, 0xFFF3D48A, 0xFFFAF269, 0xFFF9F0C2];
public function new(id:String, num:Int)
{
super(0, 0);
difficultyId = id;
dot = new FlxSprite().loadGraphic(Paths.image('freeplay/seperator'));
add(dot);
dot.alpha = 0;
pulse = new FlxSprite(0, 0);
pulse.frames = Paths.getSparrowAtlas('freeplay/dotPulse');
pulse.animation.addByPrefix('pulse', 'pulse', 12, true);
pulse.animation.play('pulse', true, false, FlxMath.wrap(num * -2, 0, 11));
pulse.visible = false;
add(pulse);
pulse.animation.onFrameChange.add(function(animName:String, frameNumber:Int, frameIndex:Int) {
interpolateColor();
});
}
var colorTween:FlxTween;
var fadeTween:FlxTween;
/**
* Interpolates between 2 colors to make the dot pulse in time with the pulse's animation.
* The colors are based on the current state of the dot.
*/
public function interpolateColor():Void
{
// pulses should only start AFTER any tweens have finished, so the color doesnt jump
if (state == DESELECTING)
{
if (colorTween?.finished && pulse.animation.curAnim.curFrame == 0) pulseColor = true;
}
else
{
if (pulse.animation.curAnim.curFrame == 0) pulseColor = true;
}
if (!important || !pulseColor) return;
switch (type)
{
case NORMAL:
switch (state)
{
case SELECTED:
// slightly different logic here, a pulse cant go lighter than fully white, so we gotta make its default color darker
color = FlxColor.interpolate(normalColors[1], normalColors[3], pulse.animation.curAnim.curFrame / pulse.animation.curAnim.numFrames);
default:
color = FlxColor.interpolate(normalColors[2], normalColors[0], pulse.animation.curAnim.curFrame / pulse.animation.curAnim.numFrames);
}
case ERECT:
switch (state)
{
case SELECTED:
color = FlxColor.interpolate(nightColors[3], nightColors[1], pulse.animation.curAnim.curFrame / pulse.animation.curAnim.numFrames);
default:
color = FlxColor.interpolate(nightColors[2], nightColors[0], pulse.animation.curAnim.curFrame / pulse.animation.curAnim.numFrames);
}
default:
trace('trying to interpolate color on inavlid dot state!');
}
}
/**
* Updates the current visuals of the dot.
* @param _type Changes the overall appearance of the dot.
* @param _state Changes how the dot will react over time.
*/
public function updateState(_type:DotType, _state:DotState):Void
{
type = _type;
state = _state;
if (colorTween != null)
{
colorTween.cancel();
}
if (fadeTween != null)
{
fadeTween.cancel();
}
dot.x = x;
dot.y = y;
pulse.x = (dot.x + (dot.width / 2)) - (pulse.width / 2);
pulse.y = (dot.y + (dot.height / 2)) - (pulse.height / 2);
pulseColor = false;
pulse.visible = important;
switch (type)
{
case NORMAL:
if (fadeTween?.finished) dot.alpha = 1;
switch (state)
{
case SELECTED:
color = normalColors[1];
case DESELECTING:
colorTween = FlxTween.color(this, 0.5, normalColors[1], normalColors[0], {ease: FlxEase.quartOut});
case DESELECTED:
color = normalColors[0];
default:
trace('freeplay dot state is invalid!');
}
case ERECT:
if (fadeTween?.finished) dot.alpha = 1;
switch (state)
{
case SELECTED:
color = nightColors[1];
case DESELECTING:
colorTween = FlxTween.color(this, 0.5, nightColors[1], nightColors[0], {ease: FlxEase.quartOut});
case DESELECTED:
color = nightColors[0];
default:
trace('freeplay dot state is invalid!');
}
case INACTIVE:
color = 0xFF121212;
if (fadeTween?.finished) dot.alpha = 0.33;
default:
trace('freeplay dot type is invalid!');
}
}
/**
* Fade in the dot. Used when entering Freeplay.
*/
public function fadeIn():Void
{
dot.alpha = 0;
dot.visible = true;
if (fadeTween != null)
{
fadeTween.cancel();
}
if (type == INACTIVE)
{
fadeTween = FlxTween.tween(dot, {alpha: 0.33}, 0.5, {ease: FlxEase.quartOut});
}
else
{
fadeTween = FlxTween.tween(dot, {alpha: 1}, 0.5, {ease: FlxEase.quartOut});
}
}
/**
* Fade out the dot. Used when leaving Freeplay.
*/
public function fadeOut():Void
{
if (fadeTween != null)
{
fadeTween.cancel();
}
fadeTween = FlxTween.tween(dot, {alpha: 0}, 0.25, {ease: FlxEase.quartOut});
pulse.alpha = 0;
}
override function update(elapsed:Float):Void
{
super.update(elapsed);
}
}