From d686890f763bd7a4db1841464dd7e3559fac1d0f Mon Sep 17 00:00:00 2001 From: FabsTheFabs <flamingkitty24@gmail.com> Date: Sat, 15 Jun 2024 05:59:58 +0100 Subject: [PATCH] most of the old code --- source/funkin/ui/charSelect/CharIcon.hx | 17 + .../funkin/ui/charSelect/CharIconCharacter.hx | 49 ++ source/funkin/ui/charSelect/CharIconLocked.hx | 3 + source/funkin/ui/charSelect/CharSelectGF.hx | 137 ++++ .../funkin/ui/charSelect/CharSelectPlayer.hx | 58 ++ .../ui/charSelect/CharSelectSubState.hx | 618 ++++++++++++++++++ source/funkin/ui/charSelect/Nametag.hx | 101 +++ source/funkin/ui/debug/DebugMenuSubState.hx | 6 + 8 files changed, 989 insertions(+) create mode 100644 source/funkin/ui/charSelect/CharIcon.hx create mode 100644 source/funkin/ui/charSelect/CharIconCharacter.hx create mode 100644 source/funkin/ui/charSelect/CharIconLocked.hx create mode 100644 source/funkin/ui/charSelect/CharSelectGF.hx create mode 100644 source/funkin/ui/charSelect/CharSelectPlayer.hx create mode 100644 source/funkin/ui/charSelect/CharSelectSubState.hx create mode 100644 source/funkin/ui/charSelect/Nametag.hx diff --git a/source/funkin/ui/charSelect/CharIcon.hx b/source/funkin/ui/charSelect/CharIcon.hx new file mode 100644 index 000000000..6d6274286 --- /dev/null +++ b/source/funkin/ui/charSelect/CharIcon.hx @@ -0,0 +1,17 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; + +class CharIcon extends FlxSprite +{ + public var locked:Bool = false; + + public function new(x:Float, y:Float, locked:Bool = false) + { + super(x, y); + + this.locked = locked; + + makeGraphic(128, 128); + } +} diff --git a/source/funkin/ui/charSelect/CharIconCharacter.hx b/source/funkin/ui/charSelect/CharIconCharacter.hx new file mode 100644 index 000000000..7f7b5c212 --- /dev/null +++ b/source/funkin/ui/charSelect/CharIconCharacter.hx @@ -0,0 +1,49 @@ +package funkin.ui.charSelect; + +import openfl.display.BitmapData; +import openfl.filters.DropShadowFilter; +import openfl.filters.ConvolutionFilter; +import funkin.graphics.shaders.StrokeShader; + +class CharIconCharacter extends CharIcon +{ + public var dropShadowFilter:DropShadowFilter; + + var matrixFilter:Array<Float> = [ + 1, 1, 1, + 1, 1, 1, + 1, 1, 1 + ]; + + var divisor:Int = 1; + var bias:Int = 0; + var convolutionFilter:ConvolutionFilter; + + public var noDropShadow:BitmapData; + public var withDropShadow:BitmapData; + + var strokeShader:StrokeShader; + + public function new(path:String) + { + super(0, 0, false); + + loadGraphic(Paths.image('freeplay/icons/' + path + 'pixel')); + setGraphicSize(128, 128); + updateHitbox(); + antialiasing = false; + + strokeShader = new StrokeShader(); + // shader = strokeShader; + + // noDropShadow = pixels.clone(); + + // dropShadowFilter = new DropShadowFilter(5, 45, 0, 1, 0, 0); + // convolutionFilter = new ConvolutionFilter(3, 3, matrixFilter, divisor, bias); + // pixels.applyFilter(pixels, pixels.rect, new openfl.geom.Point(0, 0), dropShadowFilter); + // pixels.applyFilter(pixels, pixels.rect, new openfl.geom.Point(0, 0), convolutionFilter); + // withDropShadow = pixels.clone(); + + // pixels = noDropShadow.clone(); + } +} diff --git a/source/funkin/ui/charSelect/CharIconLocked.hx b/source/funkin/ui/charSelect/CharIconLocked.hx new file mode 100644 index 000000000..dbe84a6ce --- /dev/null +++ b/source/funkin/ui/charSelect/CharIconLocked.hx @@ -0,0 +1,3 @@ +package funkin.ui.charSelect; + +class CharIconLocked extends CharIcon {} diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx new file mode 100644 index 000000000..6d8e3e657 --- /dev/null +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -0,0 +1,137 @@ +package funkin.ui.charSelect; + +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import flixel.tweens.FlxTween; +import flixel.tweens.FlxEase; +import flixel.math.FlxMath; +import funkin.util.FramesJSFLParser; +import funkin.util.FramesJSFLParser.FramesJSFLInfo; +import funkin.util.FramesJSFLParser.FramesJSFLFrame; +import flixel.math.FlxMath; + +class CharSelectGF extends FlxAtlasSprite +{ + var fadeTimer:Float = 0; + var fadingStatus:FadeStatus = OFF; + var fadeAnimIndex:Int = 0; + + var animInInfo:FramesJSFLInfo; + var animOutInfo:FramesJSFLInfo; + + var intendedYPos:Float = 0; + var intendedAlpha:Float = 0; + + public function new() + { + super(0, 0, Paths.animateAtlas("charSelect/gfChill")); + anim.play(""); + switchGF("bf"); + } + + override public function update(elapsed:Float) + { + super.update(elapsed); + + switch (fadingStatus) + { + case OFF: + // do nothing if it's off! + // or maybe force position to be 0,0? + // maybe reset timers? + resetFadeAnimParams(); + case FADE_OUT: + doFade(animOutInfo); + case FADE_IN: + doFade(animInInfo); + default: + } + + if (FlxG.keys.justPressed.J) + { + alpha = 1; + x = y = 0; + fadingStatus = FADE_OUT; + } + if (FlxG.keys.justPressed.K) + { + alpha = 0; + fadingStatus = FADE_IN; + } + } + + /** + * @param animInfo Should not be confused with animInInfo! + * This is merely a local var for the function! + */ + function doFade(animInfo:FramesJSFLInfo) + { + fadeTimer += FlxG.elapsed; + if (fadeTimer >= 1 / 24) + { + fadeTimer = 0; + // only inc the index for the first frame, used for reference of where to "start" + if (fadeAnimIndex == 0) + { + fadeAnimIndex++; + return; + } + + var curFrame:FramesJSFLFrame = animInfo.frames[fadeAnimIndex]; + var prevFrame:FramesJSFLFrame = animInfo.frames[fadeAnimIndex - 1]; + + var xDiff:Float = curFrame.x - prevFrame.x; + var yDiff:Float = curFrame.y - prevFrame.y; + var alphaDiff:Float = curFrame.alpha - prevFrame.alpha; + alphaDiff /= 100; // flash exports alpha as a whole number + + alpha += alphaDiff; + alpha = FlxMath.bound(alpha, 0, 1); + x += xDiff; + y += yDiff; + + fadeAnimIndex++; + } + + if (fadeAnimIndex >= animInfo.frames.length) fadingStatus = OFF; + } + + function resetFadeAnimParams() + { + fadeTimer = 0; + fadeAnimIndex = 0; + } + + public function switchGF(str:String) + { + str = switch (str) + { + case "pico": + "nene"; + case "bf": + "gf"; + default: + "gf"; + } + + switch str + { + default: + loadAtlas(Paths.animateAtlas("charSelect/" + str + "Chill")); + } + + animInInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "In.txt")); + animOutInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/" + str + "AnimInfo/" + str + "Out.txt")); + + anim.play(""); + playAnimation("idle", true, false, true); + + updateHitbox(); + } +} + +enum FadeStatus +{ + OFF; + FADE_OUT; + FADE_IN; +} diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx new file mode 100644 index 000000000..9322369ba --- /dev/null +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -0,0 +1,58 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; +import funkin.graphics.adobeanimate.FlxAtlasSprite; + +class CharSelectPlayer extends FlxAtlasSprite +{ + public function new(x:Float, y:Float) + { + super(x, y, Paths.animateAtlas("charSelect/bfChill")); + + onAnimationFinish.add(function(animLabel:String) { + switch (animLabel) + { + case "slidein": + if (hasAnimation("slidein idle point")) playAnimation("slidein idle point", true, false, false); + else + playAnimation("idle", true, false, true); + case "slidein idle point": + playAnimation("idle", true, false, true); + case "select": + anim.pause(); + case "deselect": + playAnimation("deselect loop start", true, false, true); + } + }); + } + + public function updatePosition(str:String) + { + switch (str) + { + case "bf": + x = 0; + y = 0; + case "pico": + x = 0; + y = 0; + case "random": + } + } + + public function switchChar(str:String) + { + switch str + { + default: + loadAtlas(Paths.animateAtlas("charSelect/" + str + "Chill")); + } + + anim.play(""); + playAnimation("slidein", true, false, false); + + updateHitbox(); + + updatePosition(str); + } +} diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx new file mode 100644 index 000000000..a360328a2 --- /dev/null +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -0,0 +1,618 @@ +package funkin.ui.charSelect; + +import flixel.text.FlxText; +import flixel.FlxSprite; +import flixel.system.debug.watch.Tracker.TrackerProfile; +import flixel.math.FlxPoint; +import flixel.tweens.FlxTween; +import openfl.display.BlendMode; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.group.FlxSpriteGroup; +import funkin.play.stage.Stage; +import funkin.play.stage.StageData.StageDataParser; +import funkin.modding.events.ScriptEvent; +import funkin.modding.events.ScriptEventDispatcher; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import flixel.FlxObject; +import openfl.display.BlendMode; +import flixel.group.FlxGroup; +import funkin.util.MathUtil; +import flixel.util.FlxTimer; +import flixel.tweens.FlxEase; +import flixel.sound.FlxSound; +import funkin.audio.FunkinSound; + +class CharSelectSubState extends MusicBeatSubState +{ + var cursor:FlxSprite; + var cursorBlue:FlxSprite; + var cursorDarkBlue:FlxSprite; + + var grpCursors:FlxTypedGroup<FlxSprite>; + + var cursorConfirmed:FlxSprite; + var cursorDenied:FlxSprite; + + var cursorX:Int = 0; + var cursorY:Int = 0; + + var cursorFactor:Float = 110; + var cursorOffsetX:Float = -16; + var cursorOffsetY:Float = -48; + + var cursorLocIntended:FlxPoint = new FlxPoint(0, 0); + var lerpAmnt:Float = 0.95; + + var tmrFrames:Int = 60; + + var currentStage:Stage; + + var playerChill:CharSelectPlayer; + var playerChillOut:CharSelectPlayer; + var gfChill:CharSelectGF; + var gfChillOut:CharSelectGF; + + var curChar(default, set):String = "pico"; + var nametag:Nametag; + var camFollow:FlxObject; + + var availableChars:Map<Int, String> = new Map<Int, String>(); + var pressedSelect:Bool = false; + + var selectTimer:FlxTimer = new FlxTimer(); + var selectSound:FunkinSound; + + public function new() + { + super(); + + availableChars.set(4, "bf"); + availableChars.set(3, "pico"); + } + + override public function create() + { + super.create(); + + selectSound = new FunkinSound(); + selectSound.loadEmbedded(Paths.sound('CS_select')); + selectSound.pitch = 1; + selectSound.volume = 0.7; + FlxG.sound.defaultSoundGroup.add(selectSound); + + Conductor.forceBPM(90); + + var bg:FlxSprite = new FlxSprite(-153, -140); + bg.loadGraphic(Paths.image('charSelect/charSelectBG')); + bg.scrollFactor.set(0.1, 0.1); + add(bg); + + var crowd:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/crowd")); + crowd.anim.play(""); + crowd.scrollFactor.set(0.3, 0.3); + add(crowd); + + var stageSpr:FlxSprite = new FlxSprite(-40, 391); + stageSpr.frames = Paths.getSparrowAtlas("charSelect/charSelectStage"); + stageSpr.animation.addByPrefix("idle", "stage", 24, true); + stageSpr.animation.play("idle"); + add(stageSpr); + + var curtains:FlxSprite = new FlxSprite(-47, -49); + curtains.loadGraphic(Paths.image('charSelect/curtains')); + curtains.scrollFactor.set(1.4, 1.4); + add(curtains); + + var barthing:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing")); + barthing.anim.play(""); + barthing.blend = BlendMode.MULTIPLY; + barthing.scrollFactor.set(0, 0); + add(barthing); + + var charLight:FlxSprite = new FlxSprite(800, 250); + charLight.loadGraphic(Paths.image('charSelect/charLight')); + add(charLight); + + var charLightGF:FlxSprite = new FlxSprite(180, 240); + charLightGF.loadGraphic(Paths.image('charSelect/charLight')); + add(charLightGF); + + gfChill = new CharSelectGF(); + gfChill.switchGF("bf"); + add(gfChill); + + playerChill = new CharSelectPlayer(0, 0); + playerChill.switchChar("bf"); + add(playerChill); + + playerChillOut = new CharSelectPlayer(0, 0); + playerChillOut.switchChar("bf"); + add(playerChillOut); + + var speakers:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/charSelectSpeakers")); + speakers.anim.play(""); + speakers.scrollFactor.set(1.8, 1.8); + add(speakers); + + var fgBlur:FlxSprite = new FlxSprite(-125, 170); + fgBlur.loadGraphic(Paths.image('charSelect/foregroundBlur')); + fgBlur.blend = openfl.display.BlendMode.MULTIPLY; + add(fgBlur); + + var dipshitBlur:FlxSprite = new FlxSprite(419, -65); + dipshitBlur.frames = Paths.getSparrowAtlas("charSelect/dipshitBlur"); + dipshitBlur.animation.addByPrefix('idle', "CHOOSE vertical", 24, true); + dipshitBlur.blend = BlendMode.ADD; + dipshitBlur.animation.play("idle"); + add(dipshitBlur); + + var dipshitBacking:FlxSprite = new FlxSprite(423, -17); + dipshitBacking.frames = Paths.getSparrowAtlas("charSelect/dipshitBacking"); + dipshitBacking.animation.addByPrefix('idle', "CHOOSE horizontal", 24, true); + dipshitBacking.blend = BlendMode.ADD; + dipshitBacking.animation.play("idle"); + add(dipshitBacking); + + var chooseDipshit:FlxSprite = new FlxSprite(426, -13); + chooseDipshit.loadGraphic(Paths.image('charSelect/chooseDipshit')); + add(chooseDipshit); + + chooseDipshit.scrollFactor.set(); + dipshitBacking.scrollFactor.set(); + dipshitBlur.scrollFactor.set(); + + nametag = new Nametag(); + add(nametag); + + nametag.scrollFactor.set(); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSprite, ["x", "y", "alpha", "scale", "blend"])); + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxAtlasSprite, ["x", "y"])); + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSound, ["pitch", "volume"])); + + // FlxG.debugger.track(crowd); + // FlxG.debugger.track(stageSpr, "stageSpr"); + // FlxG.debugger.track(bfChill, "bf chill"); + // FlxG.debugger.track(playerChill, "player"); + // FlxG.debugger.track(nametag, "nametag"); + FlxG.debugger.track(selectSound, "selectSound"); + // FlxG.debugger.track(chooseDipshit, "choose dipshit"); + // FlxG.debugger.track(barthing, "barthing"); + // FlxG.debugger.track(fgBlur, "fgBlur"); + // FlxG.debugger.track(dipshitBlur, "dipshitBlur"); + // FlxG.debugger.track(dipshitBacking, "dipshitBacking"); + // FlxG.debugger.track(charLightGF, "charLight"); + // FlxG.debugger.track(gfChill, "gfChill"); + + grpCursors = new FlxTypedGroup<FlxSprite>(); + add(grpCursors); + + cursor = new FlxSprite(0, 0); + cursor.loadGraphic(Paths.image('charSelect/charSelector')); + cursor.color = 0xFFFFFF00; + + // FFCC00 + + cursorBlue = new FlxSprite(0, 0); + cursorBlue.loadGraphic(Paths.image('charSelect/charSelector')); + cursorBlue.color = 0xFF3EBBFF; + + cursorDarkBlue = new FlxSprite(0, 0); + cursorDarkBlue.loadGraphic(Paths.image('charSelect/charSelector')); + cursorDarkBlue.color = 0xFF3C74F7; + + cursorBlue.blend = BlendMode.SCREEN; + cursorDarkBlue.blend = BlendMode.SCREEN; + + cursorConfirmed = new FlxSprite(0, 0); + cursorConfirmed.scrollFactor.set(); + cursorConfirmed.frames = Paths.getSparrowAtlas("charSelect/charSelectorConfirm"); + cursorConfirmed.animation.addByPrefix("idle", "cursor ACCEPTED", 24, true); + cursorConfirmed.visible = false; + add(cursorConfirmed); + + cursorDenied = new FlxSprite(0, 0); + cursorDenied.scrollFactor.set(); + cursorDenied.frames = Paths.getSparrowAtlas("charSelect/charSelectorDenied"); + cursorDenied.animation.addByPrefix("idle", "cursor DENIED", 24, false); + cursorDenied.visible = false; + add(cursorDenied); + + grpCursors.add(cursorDarkBlue); + grpCursors.add(cursorBlue); + grpCursors.add(cursor); + + initLocks(); + + cursor.scrollFactor.set(); + cursorBlue.scrollFactor.set(); + cursorDarkBlue.scrollFactor.set(); + + FlxTween.color(cursor, 0.2, 0xFFFFFF00, 0xFFFFCC00, {type: FlxTween.PINGPONG}); + + // FlxG.debugger.track(cursor); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(CharSelectSubState, ["curChar", "grpXSpread", "grpYSpread"])); + FlxG.debugger.track(this); + + FlxG.sound.playMusic(Paths.music('charSelect/charSelectMusic')); + + camFollow = new FlxObject(0, 0, 1, 1); + add(camFollow); + camFollow.screenCenter(); + + FlxG.camera.follow(camFollow, LOCKON, 0.01); + + var temp:FlxSprite = new FlxSprite(); + temp.loadGraphic(Paths.image('charSelect/placement')); + add(temp); + temp.alpha = 0.0; + Conductor.stepHit.add(spamOnStep); + // FlxG.debugger.track(temp, "tempBG"); + } + + var grpIcons:FlxSpriteGroup; + + var grpXSpread(default, set):Float = 107; + var grpYSpread(default, set):Float = 127; + + function initLocks() + { + grpIcons = new FlxSpriteGroup(); + add(grpIcons); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSpriteGroup, ["x", "y"])); + // FlxG.debugger.track(grpIcons, "iconGrp"); + + for (i in 0...9) + { + if (availableChars.exists(i)) + { + var path:String = availableChars.get(i); + var temp:CharIconCharacter = new CharIconCharacter(path); + temp.ID = 0; + + var idleAnimPrefix:String = switch (path) + { + case "pico": + "Pico Icon"; + case "bf": + "boyfriend icon instance 1"; + case _: + "Pico Icon"; + }; + + // temp.animation.addByPrefix("idle", idleAnimPrefix, 0, false); + // temp.animation.play("idle"); + grpIcons.add(temp); + } + else + { + var temp:FlxSprite = new FlxSprite(); + temp.ID = 1; + temp.frames = Paths.getSparrowAtlas("charSelect/locks"); + + var lockIndex:Int = i + 1; + + if (i == 3) lockIndex = 3; + + if (i >= 4) lockIndex = i - 2; + + temp.animation.addByIndices("idle", "LOCK FULL " + lockIndex + " instance 1", [0], "", 24); + temp.animation.addByIndices("selected", "LOCK FULL " + lockIndex + " instance 1", [3, 4, 5], "", 24, false); + temp.animation.addByIndices("clicked", "LOCK FULL " + lockIndex + " instance 1", [9, 10, 11, 12, 13, 14, 15], "", 24, false); + + temp.animation.play("idle"); + + grpIcons.add(temp); + } + } + + updateIconPositions(); + + grpIcons.scrollFactor.set(); + } + + function updateIconPositions() + { + grpIcons.x = 450; + grpIcons.y = 120; + for (index => member in grpIcons.members) + { + var posX:Float = (index % 3); + var posY:Float = Math.floor(index / 3); + + member.x = posX * grpXSpread; + member.y = posY * grpYSpread; + + member.x += grpIcons.x; + member.y += grpIcons.y; + } + } + + var holdTmrUp:Float = 0; + var holdTmrDown:Float = 0; + var holdTmrLeft:Float = 0; + var holdTmrRight:Float = 0; + var spamUp:Bool = false; + var spamDown:Bool = false; + var spamLeft:Bool = false; + var spamRight:Bool = false; + + override public function update(elapsed:Float) + { + super.update(elapsed); + + Conductor.update(); + + if (controls.UI_UP_R || controls.UI_DOWN_R || controls.UI_LEFT_R || controls.UI_RIGHT_R) selectSound.pitch = 1; + + if (controls.UI_UP) holdTmrUp += elapsed; + if (controls.UI_UP_R) + { + holdTmrUp = 0; + spamUp = false; + } + + if (controls.UI_DOWN) holdTmrDown += elapsed; + if (controls.UI_DOWN_R) + { + holdTmrDown = 0; + spamDown = false; + } + + if (controls.UI_LEFT) holdTmrLeft += elapsed; + if (controls.UI_LEFT_R) + { + holdTmrLeft = 0; + spamLeft = false; + } + + if (controls.UI_RIGHT) holdTmrRight += elapsed; + if (controls.UI_RIGHT_R) + { + holdTmrRight = 0; + spamRight = false; + } + + var initSpam = 0.5; + + if (holdTmrUp >= initSpam) spamUp = true; + if (holdTmrDown >= initSpam) spamDown = true; + if (holdTmrLeft >= initSpam) spamLeft = true; + if (holdTmrRight >= initSpam) spamRight = true; + + if (controls.UI_UP_P) + { + cursorY -= 1; + holdTmrUp = 0; + + selectSound.play(true); + } + if (controls.UI_DOWN_P) + { + cursorY += 1; + holdTmrDown = 0; + selectSound.play(true); + } + if (controls.UI_LEFT_P) + { + cursorX -= 1; + holdTmrLeft = 0; + selectSound.play(true); + } + if (controls.UI_RIGHT_P) + { + cursorX += 1; + holdTmrRight = 0; + selectSound.play(true); + } + + if (cursorX < -1) + { + cursorX = 1; + } + if (cursorX > 1) + { + cursorX = -1; + } + if (cursorY < -1) + { + cursorY = 1; + } + if (cursorY > 1) + { + cursorY = -1; + } + + if (availableChars.exists(getCurrentSelected())) + { + curChar = availableChars.get(getCurrentSelected()); + + if (controls.ACCEPT) + { + cursorConfirmed.visible = true; + cursorConfirmed.x = cursor.x - 2; + cursorConfirmed.y = cursor.y - 4; + cursorConfirmed.animation.play("idle", true); + + grpCursors.visible = false; + + FlxG.sound.play(Paths.sound('CS_confirm')); + + FlxTween.tween(FlxG.sound.music, {pitch: 0.1}, 1.5, {ease: FlxEase.quadInOut}); + playerChill.playAnimation("select"); + pressedSelect = true; + selectTimer.start(1.5, (_) -> { + pressedSelect = false; + close(); + }); + } + + if (pressedSelect && controls.BACK) + { + cursorConfirmed.visible = false; + grpCursors.visible = true; + + FlxTween.globalManager.cancelTweensOf(FlxG.sound.music); + FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1, {ease: FlxEase.quartInOut}); + playerChill.playAnimation("deselect"); + pressedSelect = false; + selectTimer.cancel(); + } + } + else + { + curChar = "locked"; + + if (controls.ACCEPT) + { + cursorDenied.visible = true; + cursorDenied.x = cursor.x - 2; + cursorDenied.y = cursor.y - 4; + cursorDenied.animation.play("idle", true); + cursorDenied.animation.finishCallback = (_) -> { + cursorDenied.visible = false; + }; + } + } + + updateLockAnims(); + + camFollow.screenCenter(); + camFollow.x += cursorX * 10; + camFollow.y += cursorY * 10; + + cursorLocIntended.x = (cursorFactor * cursorX) + (FlxG.width / 2) - cursor.width / 2; + cursorLocIntended.y = (cursorFactor * cursorY) + (FlxG.height / 2) - cursor.height / 2; + + cursorLocIntended.x += cursorOffsetX; + cursorLocIntended.y += cursorOffsetY; + + cursor.x = MathUtil.coolLerp(cursor.x, cursorLocIntended.x, lerpAmnt); + cursor.y = MathUtil.coolLerp(cursor.y, cursorLocIntended.y, lerpAmnt); + + cursorBlue.x = MathUtil.coolLerp(cursorBlue.x, cursor.x, lerpAmnt * 0.4); + cursorBlue.y = MathUtil.coolLerp(cursorBlue.y, cursor.y, lerpAmnt * 0.4); + + cursorDarkBlue.x = MathUtil.coolLerp(cursorDarkBlue.x, cursorLocIntended.x, lerpAmnt * 0.2); + cursorDarkBlue.y = MathUtil.coolLerp(cursorDarkBlue.y, cursorLocIntended.y, lerpAmnt * 0.2); + } + + function spamOnStep() + { + if (spamUp || spamDown || spamLeft || spamRight) + { + selectSound.changePitchBySemitone(1); + if (selectSound.pitch > 5) selectSound.pitch = 5; + selectSound.play(true); + + if (spamUp) + { + cursorY -= 1; + holdTmrUp = 0; + } + if (spamDown) + { + cursorY += 1; + holdTmrDown = 0; + } + if (spamLeft) + { + cursorX -= 1; + holdTmrLeft = 0; + } + if (spamRight) + { + cursorX += 1; + holdTmrRight = 0; + } + } + } + + private function updateLockAnims() + { + for (index => member in grpIcons.group.members) + { + switch (member.ID) + { + case 1: + if (index == getCurrentSelected()) + { + switch (member.animation.curAnim.name) + { + case "idle": + member.animation.play("selected"); + case "selected" | "clicked": + if (controls.ACCEPT) member.animation.play("clicked", true); + } + } + else + { + member.animation.play("idle"); + } + case 0: + var memb:CharIconCharacter = cast member; + + if (index == getCurrentSelected()) + { + // memb.pixels = memb.withDropShadow.clone(); + memb.setGraphicSize(128 * 1.3); + } + else + { + // memb.pixels = memb.noDropShadow.clone(); + memb.setGraphicSize(128); + } + } + } + } + + function getCurrentSelected() + { + var tempX:Int = cursorX + 1; + var tempY:Int = cursorY + 1; + var gridPosition:Int = tempX + tempY * 3; + return gridPosition; + } + + function set_curChar(value:String):String + { + if (curChar == value) return value; + + curChar = value; + + nametag.switchChar(value); + playerChill.visible = false; + playerChillOut.visible = true; + playerChillOut.anim.goToFrameLabel("slideout"); + playerChillOut.anim.callback = (_, frame:Int) -> { + if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 1) + { + playerChill.visible = true; + playerChill.switchChar(value); + gfChill.switchGF(value); + } + if (frame == playerChillOut.anim.getFrameLabel("slideout").index + 2) + { + playerChillOut.switchChar(value); + playerChillOut.visible = false; + } + }; + return value; + } + + function set_grpXSpread(value:Float):Float + { + grpXSpread = value; + updateIconPositions(); + return value; + } + + function set_grpYSpread(value:Float):Float + { + grpYSpread = value; + updateIconPositions(); + return value; + } +} diff --git a/source/funkin/ui/charSelect/Nametag.hx b/source/funkin/ui/charSelect/Nametag.hx new file mode 100644 index 000000000..b6cedb0c7 --- /dev/null +++ b/source/funkin/ui/charSelect/Nametag.hx @@ -0,0 +1,101 @@ +package funkin.ui.charSelect; + +import flixel.FlxSprite; +import funkin.graphics.shaders.MosaicEffect; +import flixel.util.FlxTimer; + +class Nametag extends FlxSprite +{ + var midpointX(default, set):Float = 1008; + var midpointY(default, set):Float = 100; + var mosaicShader:MosaicEffect; + + public function new(?x:Float = 0, ?y:Float = 0) + { + super(x, y); + + mosaicShader = new MosaicEffect(); + shader = mosaicShader; + + switchChar("bf"); + + FlxG.debugger.addTrackerProfile(new TrackerProfile(Nametag, ["midpointX", "midpointY"])); + FlxG.debugger.track(this, "Nametag"); + } + + public function updatePosition():Void + { + var offsetX:Float = getMidpoint().x - midpointX; + var offsetY:Float = getMidpoint().y - midpointY; + + x -= offsetX; + y -= offsetY; + } + + public function switchChar(str:String):Void + { + shaderEffect(); + + new FlxTimer().start(4 / 30, _ -> { + var path:String = str; + switch str + { + case "bf": + path = "boyfriend"; + } + + loadGraphic(Paths.image('charSelect/' + path + "Nametag")); + updateHitbox(); + scale.x = scale.y = 0.77; + + updatePosition(); + shaderEffect(true); + }); + } + + function shaderEffect(fadeOut:Bool = false):Void + { + if (fadeOut) + { + setBlockTimer(0, 1, 1); + setBlockTimer(1, width / 27, height / 26); + setBlockTimer(2, width / 10, height / 10); + + setBlockTimer(3, 1, 1); + } + else + { + setBlockTimer(0, (width / 10), (height / 10)); + setBlockTimer(1, width / 73, height / 6); + setBlockTimer(2, width / 10, height / 10); + } + } + + function setBlockTimer(frame:Int, ?forceX:Float, ?forceY:Float) + { + var daX:Float = 10 * FlxG.random.int(1, 4); + var daY:Float = 10 * FlxG.random.int(1, 4); + + if (forceX != null) daX = forceX; + + if (forceY != null) daY = forceY; + + new FlxTimer().start(frame / 30, _ -> { + mosaicShader.setBlockSize(daX, daY); + }); + } + + function set_midpointX(val:Float):Float + { + this.midpointX = val; + updatePosition(); + return val; + } + + function set_midpointY(val:Float):Float + { + this.midpointY = val; + updatePosition(); + return val; + } +} diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index f8b1be9d2..22dc5dba6 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -56,6 +56,7 @@ class DebugMenuSubState extends MusicBeatSubState // Call onMenuChange when the first item is created to move the camera . onMenuChange(createItem("CHART EDITOR", openChartEditor)); // createItem("Input Offset Testing", openInputOffsetTesting); + createItem("CHARACTER SELECT", openCharSelect, true); createItem("ANIMATION EDITOR", openAnimationEditor); // createItem("STAGE EDITOR", openStageEditor); // createItem("TEST STICKERS", testStickers); @@ -102,6 +103,11 @@ class DebugMenuSubState extends MusicBeatSubState trace('Input Offset Testing'); } + function openCharSelect() + { + FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); + } + function openAnimationEditor() { FlxG.switchState(() -> new funkin.ui.debug.anim.DebugBoundingState());