diff --git a/art b/art index faeba700c..e2663c1cb 160000 --- a/art +++ b/art @@ -1 +1 @@ -Subproject commit faeba700c5526bd4fd57ccc927d875c82b9d3553 +Subproject commit e2663c1cbe029f04a98500735943f0b9465548bf diff --git a/assets b/assets index d2ea072f3..c6a2a13d7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d2ea072f32d0ba74cf8c62576f28e7b03d591ddb +Subproject commit c6a2a13d754e3566d25e762acec3a74e7116f23e diff --git a/source/funkin/graphics/FlxFilteredSprite.hx b/source/funkin/graphics/FlxFilteredSprite.hx index 3563ea976..af4418d60 100644 --- a/source/funkin/graphics/FlxFilteredSprite.hx +++ b/source/funkin/graphics/FlxFilteredSprite.hx @@ -37,7 +37,6 @@ import openfl.display._internal.CairoGraphics as GfxRenderer; /** * A modified `FlxSprite` that supports filters. * The name's pretty much self-explanatory. - * @author CheemsAndFriends */ @:access(openfl.geom.Rectangle) @:access(openfl.filters.BitmapFilter) @@ -146,7 +145,7 @@ class FlxFilteredSprite extends FlxSprite _matrix.ty = Math.floor(_matrix.ty); } - camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); + camera.drawPixels((filtered) ? _blankFrame : _frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader); } @:noCompletion @@ -154,7 +153,6 @@ class FlxFilteredSprite extends FlxSprite { filterDirty = false; _filterMatrix.identity(); - var filteredFrame = (filtered) ? _frame : null; if (filters != null && filters.length > 0) { @@ -195,6 +193,7 @@ class FlxFilteredSprite extends FlxSprite } else { + trace("GAGAGA"); resetFrame(); filtered = false; } @@ -215,6 +214,11 @@ class FlxFilteredSprite extends FlxSprite return super.set_frame(value); } + + override public function destroy() + { + super.destroy(); + } } @:noCompletion @@ -339,6 +343,15 @@ class FlxAnimateFilterRenderer if (target1 == null) bitmap2.dispose(); if (target2 == null) bitmap3.dispose(); + // var gl = renderer.__gl; + + // var renderBuffer = bitmap.getTexture(renderer.__context3D); + // @:privateAccess + // gl.readPixels(0, 0, bitmap.width, bitmap.height, renderBuffer.__format, gl.UNSIGNED_BYTE, bitmap.image.data); + // bitmap.image.version = 0; + // @:privateAccess + // bitmap.__textureVersion = -1; + return bitmap; } diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx index e187c7808..d4df2a4f7 100644 --- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx +++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx @@ -217,6 +217,9 @@ class FlxAtlasSprite extends FlxAnimate { if (this.anim == null) return false; if (!this.anim.isPlaying) return false; + + if (fr != null) return (anim.reversed && anim.curFrame < fr.index || !anim.reversed && anim.curFrame >= (fr.index + fr.duration)); + return (anim.reversed && anim.curFrame == 0 || !(anim.reversed) && (anim.curFrame) >= (anim.length - 1)); } @@ -283,7 +286,7 @@ class FlxAtlasSprite extends FlxAnimate { onAnimationFrame.dispatch(currentAnimation, frame); - if (fr != null && frame > (fr.index + fr.duration - 1) || isLoopComplete()) + if (isLoopComplete()) { anim.pause(); _onAnimationComplete(); diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index a3d945594..80b05e5ac 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -412,7 +412,7 @@ class Save */ public function addCharacterSeen(character:String):Void { - data.unlocks.charactersSeen.push(character); + if (!data.unlocks.charactersSeen.contains(character)) data.unlocks.charactersSeen.push(character); } /** diff --git a/source/funkin/ui/charSelect/CharSelectGF.hx b/source/funkin/ui/charSelect/CharSelectGF.hx index a990db817..e8eeded40 100644 --- a/source/funkin/ui/charSelect/CharSelectGF.hx +++ b/source/funkin/ui/charSelect/CharSelectGF.hx @@ -133,7 +133,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass fadeTimer += FlxG.elapsed; if (fadeTimer >= 1 / 24) { - fadeTimer = 0; + fadeTimer -= FlxG.elapsed; // only inc the index for the first frame, used for reference of where to "start" if (fadeAnimIndex == 0) { diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx index 8809ad29b..9767c2d3b 100644 --- a/source/funkin/ui/charSelect/CharSelectPlayer.hx +++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx @@ -26,19 +26,17 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass } else { - playAnimation("idle", true, false, true); + playAnimation("idle", true, false, false); } + case "deselect": + playAnimation("deselect loop start", true, false, true); case "slidein idle point", "cannot select", "unlock": - playAnimation("idle", true, false, true); + playAnimation("idle", true, false, false); case "idle": trace('Waiting for onBeatHit'); } }); - - onAnimationFrame.add(function(animLabel:String, frame:Int) { - if (animLabel == "deselect" && desLp != null && frame >= desLp.index) playAnimation("deselect loop start", true, false, true); - }); } public function onStepHit(event:SongTimeScriptEvent):Void {} @@ -50,6 +48,7 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass // I tried make this not interrupt an existing idle, // but isAnimationFinished() and isLoopComplete() both don't work! What the hell? // danceEvery isn't necessary if that gets fixed. + // if (getCurrentAnimation() == "idle") { trace('Player beat hit'); diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 80ad59439..818b68c1c 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -1,5 +1,6 @@ package funkin.ui.charSelect; +import openfl.filters.BitmapFilter; import flixel.FlxObject; import flixel.FlxSprite; import flixel.group.FlxGroup; @@ -31,6 +32,9 @@ import funkin.vis.dsp.SpectralAnalyzer; import openfl.display.BlendMode; import funkin.save.Save; import openfl.filters.ShaderFilter; +import funkin.util.FramesJSFLParser; +import funkin.util.FramesJSFLParser.FramesJSFLInfo; +import funkin.util.FramesJSFLParser.FramesJSFLFrame; class CharSelectSubState extends MusicBeatSubState { @@ -82,10 +86,16 @@ class CharSelectSubState extends MusicBeatSubState var charSelectCam:FunkinCamera; + var selectedBizz:Array = [ + new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 21, 1, false, false, false), + new DropShadowFilter(5, 45, 0x000000, 1, 2, 2, 1, 1, false, false, false) + ]; + + var bopInfo:FramesJSFLInfo; + public function new() { super(); - loadAvailableCharacters(); } @@ -119,6 +129,8 @@ class CharSelectSubState extends MusicBeatSubState { super.create(); + bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt")); + var bg:FlxSprite = new FlxSprite(-153, -140); bg.loadGraphic(Paths.image('charSelect/charSelectBG')); bg.scrollFactor.set(0.1, 0.1); @@ -281,10 +293,21 @@ class CharSelectSubState extends MusicBeatSubState unlockSound = new FunkinSound(); unlockSound.loadEmbedded(Paths.sound('CS_unlock')); unlockSound.pitch = 1; - unlockSound.volume = 0.7; + + unlockSound.volume = 0; + unlockSound.play(true); FlxG.sound.defaultSoundGroup.add(unlockSound); + // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro + // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? + FunkinSound.playMusic('stayFunky', + { + startingVolume: 0, + overrideExisting: true, + restartTrack: true, + }); + initLocks(); for (index => member in grpIcons.members) @@ -384,16 +407,24 @@ class CharSelectSubState extends MusicBeatSubState grpIcons.scrollFactor.set(); - // playing it here to preload it. not doing this makes a super awkward pause at the end of the intro - // TODO: probably make an intro thing for funkinSound itself that preloads the next audio? - FunkinSound.playMusic('stayFunky', - { - startingVolume: 0, - overrideExisting: true, - restartTrack: true, - }); - - unLock(); + if (nonLocks.length > 0) unLock(); + else + FunkinSound.playMusic('stayFunky', + { + startingVolume: 1, + overrideExisting: true, + restartTrack: true, + onLoad: function() { + @:privateAccess + gfChill.analyzer = new SpectralAnalyzer(FlxG.sound.music._channel.__audioSource, 7, 0.1); + #if desktop + // On desktop it uses FFT stuff that isn't as optimized as the direct browser stuff we use on HTML5 + // So we want to manually change it! + @:privateAccess + gfChill.analyzer.fftN = 512; + #end + } + }); } function unLock() @@ -428,15 +459,37 @@ class CharSelectSubState extends MusicBeatSubState lock.playAnimation("unlock"); + unlockSound.volume = 0.7; unlockSound.play(true); lock.onAnimationComplete.addOnce(function(_) { + var char = availableChars.get(index); camera.flash(0xFFFFFFFF, 0.1); playerChill.playAnimation("unlock"); playerChill.visible = true; + var id = grpIcons.members.indexOf(lock); + + nametag.switchChar(char); + gfChill.switchGF(char); + + var icon = new PixelatedIcon(0, 0); + icon.setCharacter(char); + icon.setGraphicSize(128, 128); + icon.updateHitbox(); + grpIcons.insert(id, icon); + grpIcons.remove(lock, true); + icon.ID = 0; + + bopPlay = true; + + updateIconPositions(); + if (nonLocks.length == 0) { + playerChillOut.onAnimationComplete.addOnce((_) -> playerChillOut.switchChar(char)); + @:bypassAccessor curChar = char; + Save.instance.addCharacterSeen(char); FunkinSound.playMusic('stayFunky', { startingVolume: 1, @@ -713,6 +766,48 @@ class CharSelectSubState extends MusicBeatSubState cursorDarkBlue.y = MathUtil.coolLerp(cursorDarkBlue.y, cursorLocIntended.y, lerpAmnt * 0.2); } + var bopTimer:Float = 0; + + var delay = 1 / 24; + + var bopFr = 0; + + var bopPlay:Bool = false; + + var bopRefX:Float = 0; + var bopRefY:Float = 0; + + function doBop(icon:PixelatedIcon, elapsed:Float):Void + { + if (bopFr >= bopInfo.frames.length) + { + bopRefX = 0; + bopRefY = 0; + bopPlay = false; + bopFr = 0; + return; + } + bopTimer += elapsed; + + if (bopTimer >= delay) + { + bopTimer -= bopTimer; + + var refFrame = bopInfo.frames[bopInfo.frames.length - 1]; + var curFrame = bopInfo.frames[bopFr]; + + var xDiff:Float = curFrame.x - refFrame.x; + var yDiff:Float = curFrame.y - refFrame.y; + var scaleXDiff:Float = curFrame.scaleX - refFrame.scaleX; + var scaleYDiff:Float = curFrame.scaleY - refFrame.scaleY; + + icon.scale.set(2.6, 2.6); + icon.scale.add(scaleXDiff, scaleYDiff); + + bopFr++; + } + } + public override function dispatchEvent(event:ScriptEvent):Void { // super.dispatchEvent(event) dispatches event to module scripts. @@ -725,11 +820,6 @@ class CharSelectSubState extends MusicBeatSubState function spamOnStep():Void { - if (FlxG.keys.justPressed.B) - { - cursorY = 3; - cursorX = 3; - } if (spamUp || spamDown || spamLeft || spamRight) { // selectSound.changePitchBySemitone(1); @@ -776,7 +866,7 @@ class CharSelectSubState extends MusicBeatSubState case "idle": lock.playAnimation("selected"); case "selected" | "clicked": - if (controls.ACCEPT) lock.playAnimation((FlxG.keys.pressed.CONTROL) ? "unlock" : "clicked", true); + if (controls.ACCEPT) lock.playAnimation("clicked", true); } } else @@ -789,8 +879,19 @@ class CharSelectSubState extends MusicBeatSubState if (index == getCurrentSelected()) { // memb.pixels = memb.withDropShadow.clone(); - if (memb.scale.x != 2.6) memb.filters = [new DropShadowFilter()]; - memb.scale.set(2.6, 2.6); + memb.filters = selectedBizz; + + if (bopPlay) + { + if (bopRefX == 0) + { + bopRefX = memb.x; + bopRefY = memb.y; + } + doBop(memb, FlxG.elapsed); + } + else + memb.scale.set(2.6, 2.6); if (controls.ACCEPT) memb.animation.play("confirm"); if (memb.animation.curAnim.name == "confirm" && controls.BACK) @@ -805,7 +906,7 @@ class CharSelectSubState extends MusicBeatSubState else { // memb.pixels = memb.noDropShadow.clone(); - if (memb.scale.x == 2) memb.filters = []; + memb.filters = null; memb.scale.set(2, 2); } } diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 8087916cb..79b30ff4d 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -32,6 +32,7 @@ import openfl.media.Video; import openfl.net.NetStream; import funkin.api.newgrounds.NGio; import openfl.display.BlendMode; +import funkin.save.Save; #if desktop #end @@ -272,6 +273,8 @@ class TitleState extends MusicBeatState } #end + if (Save.instance.charactersSeen.contains("pico")) Save.instance.charactersSeen.remove("pico"); + Conductor.instance.update(); /* if (FlxG.onMobile) diff --git a/source/funkin/util/FramesJSFLParser.hx b/source/funkin/util/FramesJSFLParser.hx index 33bcf9d9d..fa01a2c87 100644 --- a/source/funkin/util/FramesJSFLParser.hx +++ b/source/funkin/util/FramesJSFLParser.hx @@ -25,9 +25,22 @@ class FramesJSFLParser var x:Float = Std.parseFloat(frameInfo[0]); var y:Float = Std.parseFloat(frameInfo[1]); - var alpha:Float = Std.parseFloat(frameInfo[2]); + var alpha:Float = (frameInfo[2] != "undefined") ? Std.parseFloat(frameInfo[2]) : 100; - var shit:FramesJSFLFrame = {x: x, y: y, alpha: alpha}; + var scaleX:Float = 1; + var scaleY:Float = 1; + + if (frameInfo[3] != null) scaleX = Std.parseFloat(frameInfo[4]); + if (frameInfo[4] != null) scaleX = Std.parseFloat(frameInfo[4]); + + var shit:FramesJSFLFrame = + { + x: x, + y: y, + alpha: alpha, + scaleX: scaleX, + scaleY: scaleY + }; output.frames.push(shit); } @@ -45,4 +58,6 @@ typedef FramesJSFLFrame = var x:Float; var y:Float; var alpha:Float; + var scaleX:Float; + var scaleY:Float; } diff --git a/source/funkin/util/logging/AnsiTrace.hx b/source/funkin/util/logging/AnsiTrace.hx index 2c18d494d..322a66820 100644 --- a/source/funkin/util/logging/AnsiTrace.hx +++ b/source/funkin/util/logging/AnsiTrace.hx @@ -6,6 +6,9 @@ class AnsiTrace // but adds nice cute ANSI things public static function trace(v:Dynamic, ?info:haxe.PosInfos) { + #if TREMOVE + return; + #end var str = formatOutput(v, info); #if js if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null) (untyped console).log(str);