diff --git a/Project.xml b/Project.xml index de9ba048..53928e72 100644 --- a/Project.xml +++ b/Project.xml @@ -76,7 +76,7 @@ - + diff --git a/art/teaser discord.png b/art/teaser discord.png new file mode 100644 index 00000000..cf57c69c Binary files /dev/null and b/art/teaser discord.png differ diff --git a/art/teaser.png b/art/teaser.png new file mode 100644 index 00000000..0b3be839 Binary files /dev/null and b/art/teaser.png differ diff --git a/assets/data/characters/tankman.xml b/assets/data/characters/tankman.xml index e31636b4..3dd2f589 100644 --- a/assets/data/characters/tankman.xml +++ b/assets/data/characters/tankman.xml @@ -1,11 +1,13 @@ - + + + - + - + diff --git a/assets/data/freeplaySonglist.json b/assets/data/freeplaySonglist.json new file mode 100644 index 00000000..cf387481 --- /dev/null +++ b/assets/data/freeplaySonglist.json @@ -0,0 +1,129 @@ +{ + "addOGSongs": false, + "songs": [ + { + "name": "Tutorial", + "icon": "gf", + "color": "#9271FD" + }, + + + { + "name": "Bopeebo", + "icon": "dad", + "color": "#9271FD" + }, + { + "name": "Fresh", + "icon": "dad", + "color": "#9271FD" + }, + { + "name": "Dadbattle", + "icon": "dad", + "color": "#9271FD" + }, + + + { + "name": "Spookeez", + "icon": "spooky", + "color": "#223344" + }, + { + "name": "South", + "icon": "spooky", + "color": "#223344" + }, + { + "name": "Monster", + "icon": "monster", + "color": "#223344" + }, + + + { + "name": "Pico", + "icon": "pico", + "color": "#941653" + }, + { + "name": "Philly Nice", + "icon": "pico", + "color": "#941653" + }, + { + "name": "Blammed", + "icon": "pico", + "color": "#941653" + }, + + + { + "name": "Satin Panties", + "icon": "mom", + "color": "#FC96D7" + }, + { + "name": "High", + "icon": "mom", + "color": "#FC96D7" + }, + { + "name": "MILF", + "icon": "mom", + "color": "#FC96D7" + }, + + + { + "name": "Cocoa", + "icon": "parents-christmas", + "color": "#A0D1FF" + }, + { + "name": "Eggnog", + "icon": "parents-christmas", + "color": "#A0D1FF" + }, + { + "name": "Winter Horrorland", + "icon": "monster", + "color": "#A0D1FF" + }, + + + { + "name": "Senpai", + "icon": "senpai", + "color": "#FF78BF" + }, + { + "name": "Roses", + "icon": "senpai", + "color": "#FF78BF" + }, + { + "name": "Thorns", + "icon": "spirit", + "color": "#FF78BF" + }, + + + { + "name": "Ugh", + "icon": "tankman", + "color": "#F6B604" + }, + { + "name": "Guns", + "icon": "tankman", + "color": "#F6B604" + }, + { + "name": "Stress", + "icon": "tankman", + "color": "#F6B604" + } + ] +} \ No newline at end of file diff --git a/assets/data/freeplaySonglist.txt b/assets/data/freeplaySonglist.txt deleted file mode 100644 index 1b5bac2c..00000000 --- a/assets/data/freeplaySonglist.txt +++ /dev/null @@ -1 +0,0 @@ -Tutorial \ No newline at end of file diff --git a/assets/data/stages/mall-evil.xml b/assets/data/stages/mall-evil.xml index 8d72a943..1085d4bf 100644 --- a/assets/data/stages/mall-evil.xml +++ b/assets/data/stages/mall-evil.xml @@ -1,5 +1,5 @@ - + diff --git a/assets/data/stages/tank.hx b/assets/data/stages/tank.hx new file mode 100644 index 00000000..8de3c2ca --- /dev/null +++ b/assets/data/stages/tank.hx @@ -0,0 +1,9 @@ +var tankAngle:Float = FlxG.random.int(-90, 45); +var tankSpeed:Float = FlxG.random.float(5, 7); + +function update(elapsed:Float) { + tankAngle += elapsed * tankSpeed; + tankRolling.angle = tankAngle - 90 + 15; + tankRolling.x = 400 + (1500 * Math.cos(Math.PI / 180 * (1 * tankAngle + 180))); + tankRolling.y = 1300 + (1100 * Math.sin(Math.PI / 180 * (1 * tankAngle + 180))); +} \ No newline at end of file diff --git a/assets/data/stages/tank.xml b/assets/data/stages/tank.xml new file mode 100644 index 00000000..8ca44fb1 --- /dev/null +++ b/assets/data/stages/tank.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/stages/tank/tankRolling.png b/assets/images/stages/tank/tankRolling.png index 706d20d9..24c7d69f 100644 Binary files a/assets/images/stages/tank/tankRolling.png and b/assets/images/stages/tank/tankRolling.png differ diff --git a/assets/images/stages/tank/tankRolling.xml b/assets/images/stages/tank/tankRolling.xml index 6993b1da..f3125783 100644 --- a/assets/images/stages/tank/tankRolling.xml +++ b/assets/images/stages/tank/tankRolling.xml @@ -2,5 +2,7 @@ - + + + diff --git a/buildnumber.txt b/buildnumber.txt index 34578cc4..680cc9c3 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -239 \ No newline at end of file +263 \ No newline at end of file diff --git a/source/Alphabet.hx b/source/Alphabet.hx index 77ac5dc8..43f46b17 100644 --- a/source/Alphabet.hx +++ b/source/Alphabet.hx @@ -224,8 +224,8 @@ class Alphabet extends FlxSpriteGroup { var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3); - y = FlxMath.lerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16); - x = FlxMath.lerp(x, (targetY * 20) + 90, 0.16); + y = CoolUtil.fpsLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16); + x = CoolUtil.fpsLerp(x, (targetY * 20) + 90, 0.16); } super.update(elapsed); diff --git a/source/Discord.hx b/source/Discord.hx index dbd80057..b8d68606 100644 --- a/source/Discord.hx +++ b/source/Discord.hx @@ -11,7 +11,8 @@ class DiscordClient { trace("Discord Client starting..."); DiscordRpc.start({ - clientID: "814588678700924999", + // clientID: "814588678700924999", + clientID: "1027994136193810442", onReady: onReady, onError: onError, onDisconnected: onDisconnected diff --git a/source/funkin/data/FreeplaySonglist.hx b/source/funkin/data/FreeplaySonglist.hx new file mode 100644 index 00000000..33471f5f --- /dev/null +++ b/source/funkin/data/FreeplaySonglist.hx @@ -0,0 +1,74 @@ +package funkin.data; + +import flixel.util.FlxColor; +import openfl.utils.Assets; +import funkin.menus.FreeplayState; +import haxe.Json; + +class FreeplaySonglist { + public var addOGSongs:Bool = false; + public var songs:Array = []; + + public function new() { + + } + + private function _addJSONSongs(songs:Array) { + if (songs != null && songs is Array) { + for(e in songs) { + if (e is Dynamic) { + if (e.name == null) continue; + if (e.icon == null) e.icon = "bf"; + if (e.color == null) e.color = FreeplayState.defaultColor; + this.songs.push(new SongMetadata(e.name, + CoolUtil.getDefault(e.icon, "bf"), + CoolUtil.getDefault(CoolUtil.getColorFromDynamic(e.color), FreeplayState.defaultColor))); + } + } + } + } + + public static function get() { + var songList = new FreeplaySonglist(); + + var jsonPath = Paths.json("freeplaySonglist"); + var baseJsonPath = Paths.getPath('data/freeplaySonglist.json', TEXT, null, true); + + try { + var json:FreeplayJSON = Json.parse(Assets.getText(jsonPath)); + var addOGSongs = CoolUtil.getDefault(json.addOGSongs, true); + songList._addJSONSongs(json.songs); + if (addOGSongs && (jsonPath != baseJsonPath)) { + var json:FreeplayJSON = Json.parse(Assets.getText(baseJsonPath)); + songList._addJSONSongs(json.songs); + } + } + + return songList; + } +} + +typedef FreeplayJSON = { + public var addOGSongs:Null; + public var songs:Array; +} + +typedef FreeplaySong = { + public var name:String; + public var icon:String; + public var color:Dynamic; +} + +class SongMetadata +{ + public var songName:String = ""; + public var color:FlxColor = FreeplayState.defaultColor; + public var songCharacter:String = ""; + + public function new(song:String, songCharacter:String, color:FlxColor) + { + this.songName = song; + this.color = color; + this.songCharacter = songCharacter; + } +} diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index bcac0ba4..26447162 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -783,8 +783,8 @@ class PlayState extends MusicBeatState // FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight); // TODO: FPS-compatible lerping - iconP1.scale.set(FlxMath.lerp(iconP1.scale.x, 1, 0.33), FlxMath.lerp(iconP1.scale.y, 1, 0.33)); - iconP2.scale.set(FlxMath.lerp(iconP2.scale.x, 1, 0.33), FlxMath.lerp(iconP2.scale.y, 1, 0.33)); + iconP1.scale.set(lerp(iconP1.scale.x, 1, 0.33), lerp(iconP1.scale.y, 1, 0.33)); + iconP2.scale.set(lerp(iconP2.scale.x, 1, 0.33), lerp(iconP2.scale.y, 1, 0.33)); iconP1.updateHitbox(); iconP2.updateHitbox(); @@ -894,8 +894,8 @@ class PlayState extends MusicBeatState if (camZooming) { - FlxG.camera.zoom = FlxMath.lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); - camHUD.zoom = FlxMath.lerp(1, camHUD.zoom, 0.95); + FlxG.camera.zoom = lerp(defaultCamZoom, FlxG.camera.zoom, 0.95); + camHUD.zoom = lerp(1, camHUD.zoom, 0.95); } FlxG.watch.addQuick("beatShit", curBeat); diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx index 6306ccf4..484995c5 100644 --- a/source/funkin/game/Stage.hx +++ b/source/funkin/game/Stage.hx @@ -67,6 +67,15 @@ class Stage extends FlxBasic implements IBeatReceiver { if (node.has.scroll) { var scroll:Null = Std.parseFloat(node.att.scroll); if (scroll != null) spr.scrollFactor.set(scroll, scroll); + } else { + if (node.has.scrollx) { + var scroll:Null = Std.parseFloat(node.att.scrollx); + if (scroll != null) spr.scrollFactor.x = scroll; + } + if (node.has.scrolly) { + var scroll:Null = Std.parseFloat(node.att.scrolly); + if (scroll != null) spr.scrollFactor.y = scroll; + } } if (node.has.scale) { var scale:Null = Std.parseFloat(node.att.scale); diff --git a/source/funkin/menus/FreeplayState.hx b/source/funkin/menus/FreeplayState.hx index 8a14070b..7dedd698 100644 --- a/source/funkin/menus/FreeplayState.hx +++ b/source/funkin/menus/FreeplayState.hx @@ -6,6 +6,7 @@ import Discord.DiscordClient; import flash.text.TextField; import flixel.FlxG; import flixel.FlxSprite; +import flixel.FlxState; import flixel.addons.display.FlxGridOverlay; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.math.FlxMath; @@ -13,11 +14,22 @@ import flixel.text.FlxText; import flixel.util.FlxColor; import lime.utils.Assets; import funkin.system.Song; +import funkin.data.FreeplaySonglist; using StringTools; class FreeplayState extends MusicBeatState { + /** + * Default background colors for songs without bg color + */ + public inline static var defaultColor:FlxColor = 0xFF9271FD; + + /** + * How much time a song stays selected until it autoplays. + */ + public inline static var timeUntilAutoplay:Float = 1; + var songs:Array = []; var selector:FlxText; @@ -29,6 +41,11 @@ class FreeplayState extends MusicBeatState var lerpScore:Int = 0; var intendedScore:Int = 0; + var songList:FreeplaySonglist; + var scoreBG:FlxSprite; + + var bg:FlxSprite; + private var grpSongs:FlxTypedGroup; private var curPlaying:Bool = false; @@ -36,20 +53,10 @@ class FreeplayState extends MusicBeatState override function create() { - var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist')); + var initSonglist = CoolUtil.coolTextFile(Paths.json('freeplaySonglist')); - for (i in 0...initSonglist.length) - { - songs.push(new SongMetadata(initSonglist[i], 1, 'gf')); - } - - /* - if (FlxG.sound.music != null) - { - if (!FlxG.sound.music.playing) - FlxG.sound.playMusic(Paths.music('freakyMenu')); - } - */ + songList = FreeplaySonglist.get(); + songs = songList.songs; #if desktop // Updating Discord Rich Presence @@ -62,19 +69,11 @@ class FreeplayState extends MusicBeatState isDebug = true; #end - addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']); - addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky']); - addWeek(['Pico', 'Philly Nice', 'Blammed'], 3, ['pico']); - addWeek(['Satin Panties', 'High', 'Milf'], 4, ['mom']); - addWeek(['Cocoa', 'Eggnog', 'Winter Horrorland'], 5, ['parents-christmas', 'parents-christmas', 'monster']); - addWeek(['Senpai', 'Roses', 'Thorns'], 6, ['senpai', 'senpai', 'spirit']); - addWeek(['Ugh', 'Guns', 'Stress'], 7, ['tankman']); - - // LOAD MUSIC - // LOAD CHARACTERS - var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuBGBlue')); + bg = new FlxSprite(0, 0, Paths.image('menuDesat')); + if (songs.length > 0) + bg.color = songs[0].color; add(bg); grpSongs = new FlxTypedGroup(); @@ -104,7 +103,7 @@ class FreeplayState extends MusicBeatState scoreText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT); // scoreText.alignment = RIGHT; - var scoreBG:FlxSprite = new FlxSprite(scoreText.x - 6, 0).makeGraphic(Std.int(FlxG.width * 0.35), 66, 0xFF000000); + scoreBG = new FlxSprite(scoreText.x - 6, 0).makeGraphic(1, 1, 0xFF000000); scoreBG.alpha = 0.6; add(scoreBG); @@ -146,26 +145,13 @@ class FreeplayState extends MusicBeatState super.create(); } + - public function addSong(songName:String, weekNum:Int, songCharacter:String) - { - songs.push(new SongMetadata(songName, weekNum, songCharacter)); - } - - public function addWeek(songs:Array, weekNum:Int, ?songCharacters:Array) - { - if (songCharacters == null) - songCharacters = ['bf']; - - var num:Int = 0; - for (song in songs) - { - addSong(song, weekNum, songCharacters[num]); - - if (songCharacters.length != 1) - num++; - } - } + #if PRELOAD_ALL + var autoplayElapsed:Float = 0; + var songInstPlaying:Bool = false; + var curPlayingInst:String = null; + #end override function update(elapsed:Float) { @@ -176,12 +162,32 @@ class FreeplayState extends MusicBeatState FlxG.sound.music.volume += 0.5 * FlxG.elapsed; } - lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.4)); + lerpScore = Math.floor(lerp(lerpScore, intendedScore, 0.4)); if (Math.abs(lerpScore - intendedScore) <= 10) lerpScore = intendedScore; scoreText.text = "PERSONAL BEST:" + lerpScore; + scoreText.x = FlxG.width - scoreText.width - 4; + scoreBG.scale.set(scoreText.width + 8, 66); + scoreBG.updateHitbox(); + scoreBG.x = FlxG.width - scoreBG.width; + diffText.x = Std.int(scoreBG.x + ((scoreBG.width - diffText.width) / 2)); + + bg.color = CoolUtil.lerpColor(bg.color, songs[curSelected].color, 0.0625); + + + // putting it before so that its actually smooth + updateOptionsAlpha(); + + #if PRELOAD_ALL + autoplayElapsed += elapsed; + if (!songInstPlaying && (autoplayElapsed > timeUntilAutoplay || FlxG.keys.justPressed.SPACE)) { + if (curPlayingInst != (curPlayingInst = Paths.inst(songs[curSelected].songName))) + FlxG.sound.playMusic(curPlayingInst, 0); + songInstPlaying = true; + } + #end var upP = controls.UP_P; var downP = controls.DOWN_P; @@ -212,7 +218,7 @@ class FreeplayState extends MusicBeatState PlayState.SONG = Song.loadFromJson(songs[curSelected].songName, CoolUtil.difficultyString()); PlayState.isStoryMode = false; - PlayState.storyWeek = songs[curSelected].week; + // PlayState.storyWeek = songs[curSelected].week; trace('CUR WEEK' + PlayState.storyWeek); LoadingState.loadAndSwitchState(new PlayState()); } @@ -234,11 +240,11 @@ class FreeplayState extends MusicBeatState switch (curDifficulty) { case 0: - diffText.text = "EASY"; + diffText.text = "< EASY >"; case 1: - diffText.text = 'NORMAL'; + diffText.text = '< NORMAL >'; case 2: - diffText.text = "HARD"; + diffText.text = "< HARD >"; } } @@ -259,16 +265,19 @@ class FreeplayState extends MusicBeatState intendedScore = Highscore.getScore(songs[curSelected].songName, curDifficulty); // lerpScore = 0; #end - + #if PRELOAD_ALL - FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0); + autoplayElapsed = 0; + songInstPlaying = false; #end + } + function updateOptionsAlpha() { var bullShit:Int = 0; for (i in 0...iconArray.length) { - iconArray[i].alpha = 0.6; + iconArray[i].alpha = lerp(iconArray[i].alpha, songInstPlaying ? 0.45 : 0.6, 0.25); } iconArray[curSelected].alpha = 1; @@ -278,7 +287,7 @@ class FreeplayState extends MusicBeatState item.targetY = bullShit - curSelected; bullShit++; - item.alpha = 0.6; + item.alpha = lerp(item.alpha, songInstPlaying ? 0.45 : 0.6, 0.25); // item.setGraphicSize(Std.int(item.width * 0.8)); if (item.targetY == 0) @@ -288,18 +297,4 @@ class FreeplayState extends MusicBeatState } } } -} - -class SongMetadata -{ - public var songName:String = ""; - public var week:Int = 0; - public var songCharacter:String = ""; - - public function new(song:String, week:Int, songCharacter:String) - { - this.songName = song; - this.week = week; - this.songCharacter = songCharacter; - } -} +} \ No newline at end of file diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx index 6c9b42e8..02c45e41 100644 --- a/source/funkin/menus/MainMenuState.hx +++ b/source/funkin/menus/MainMenuState.hx @@ -6,6 +6,7 @@ import Discord.DiscordClient; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; +import flixel.FlxState; import flixel.addons.transition.FlxTransitionableState; import flixel.effects.FlxFlicker; import flixel.graphics.frames.FlxAtlasFrames; @@ -156,39 +157,27 @@ class MainMenuState extends MusicBeatState menuItems.forEach(function(spr:FlxSprite) { - if (curSelected != spr.ID) + if (spr.ID != curSelected) return; + FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker) { - FlxTween.tween(spr, {alpha: 0}, 0.4, { - ease: FlxEase.quadOut, - onComplete: function(twn:FlxTween) - { - spr.kill(); - } - }); - } - else - { - FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker) + var daChoice:String = optionShit[curSelected]; + + switch (daChoice) { - var daChoice:String = optionShit[curSelected]; + case 'story mode': + FlxG.switchState(new StoryMenuState()); + trace("Story Menu Selected"); + case 'freeplay': + FlxG.switchState(new FreeplayState()); - switch (daChoice) - { - case 'story mode': - FlxG.switchState(new StoryMenuState()); - trace("Story Menu Selected"); - case 'freeplay': - FlxG.switchState(new FreeplayState()); + trace("Freeplay Menu Selected"); - trace("Freeplay Menu Selected"); - - case 'options': - FlxTransitionableState.skipNextTransIn = true; - FlxTransitionableState.skipNextTransOut = true; - // FlxG.switchState(new OptionsMenu()); - } - }); - } + case 'options': + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + // FlxG.switchState(new OptionsMenu()); + } + }); }); } } @@ -202,6 +191,15 @@ class MainMenuState extends MusicBeatState }); } + + public override function switchTo(nextState:FlxState):Bool { + try { + menuItems.forEach(function(spr:FlxSprite) { + FlxTween.tween(spr, {alpha: 0}, 0.5, {ease: FlxEase.quintOut}); + }); + } + return super.switchTo(nextState); + } function changeItem(huh:Int = 0) { curSelected += huh; diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx index b6893976..938195e3 100644 --- a/source/funkin/menus/StoryMenuState.hx +++ b/source/funkin/menus/StoryMenuState.hx @@ -226,7 +226,7 @@ class StoryMenuState extends MusicBeatState override function update(elapsed:Float) { // scoreText.setFormat('VCR OSD Mono', 32); - lerpScore = Math.floor(FlxMath.lerp(lerpScore, intendedScore, 0.5)); + lerpScore = Math.floor(lerp(lerpScore, intendedScore, 0.5)); scoreText.text = "WEEK SCORE:" + lerpScore; diff --git a/source/funkin/system/CoolUtil.hx b/source/funkin/system/CoolUtil.hx index d920dfb6..8764c9a7 100644 --- a/source/funkin/system/CoolUtil.hx +++ b/source/funkin/system/CoolUtil.hx @@ -2,6 +2,9 @@ package funkin.system; import lime.utils.Assets; import flixel.animation.FlxAnimation; +import flixel.util.FlxColor; +import flixel.math.FlxMath; +import flixel.FlxG; using StringTools; @@ -9,6 +12,108 @@ class CoolUtil { public static var difficultyArray:Array = ['EASY', "NORMAL", "HARD"]; + /** + * Returns `v` if not null, `defaultValue` otherwise. + * @param v The value + * @param defaultValue The default value + * @return T The return value + */ + public static function getDefault(v:T, defaultValue:T):T { + return v == null ? defaultValue : v; + } + + public static function fpsLerp(v1:Float, v2:Float, ratio:Float):Float { + return FlxMath.lerp(v1, v2, getFPSRatio(ratio)); + } + /** + * Lerps from color1 into color2 in a cool way 😎 + * @param color1 Color 1 + * @param color2 Color 2 + * @param ratio Ratio + * @param fpsSensitive Whenever the ratio should be case sentivive (adapted when game is running at 120 instead of 60) + */ + public static function lerpColor(color1:FlxColor, color2:FlxColor, ratio:Float, fpsSensitive:Bool = false) { + var h1 = color1.hue; + var s1 = color1.saturation; + var b1 = color1.brightness; + + var h2 = color2.hue; + var s2 = color2.saturation; + var b2 = color2.brightness; + + if (!fpsSensitive) + ratio = getFPSRatio(ratio); + + if (Math.abs(h1-h2) > 180) h1 += 360; + + if (Math.abs(h1 - h2) > 90 || s2 < 0.125 || s1 < 0.125) { + // classic r,g,b lerp + var r1 = color1.redFloat; + var g1 = color1.greenFloat; + var b1 = color1.blueFloat; + + var r2 = color2.redFloat; + var g2 = color2.greenFloat; + var b2 = color2.blueFloat; + + return FlxColor.fromRGBFloat( + FlxMath.lerp(r1, r2, ratio), + FlxMath.lerp(g1, g2, ratio), + FlxMath.lerp(b1, b2, ratio)); + } + + + return FlxColor.fromHSB( + FlxMath.lerp(h1, h2, ratio), + FlxMath.lerp(s1, s2, ratio), + FlxMath.lerp(b1, b2, ratio)); + } + + /** + * Modifies a lerp ratio based on current FPS to keep a stable speed on higher framerate. + * @param ratio Ratio + * @return Float FPS-Modified Ratio + */ + public static function getFPSRatio(ratio:Float) { + return FlxMath.bound(ratio * 60 * FlxG.elapsed, 0, 1); + } + /** + * Tries to get a color from a `Dynamic` variable. + * @param c `Dynamic` color. + * @return Null The result color + */ + public static function getColorFromDynamic(c:Dynamic):Null { + // -1 + if (c is Int) return c; + + // -1.0 + if (c is Float) return Std.int(c); + + // "#FFFFFF" + if (c is String) return FlxColor.fromString(c); + + // [255, 255, 255] + if (c is Array) { + var r:Int = 0; + var g:Int = 0; + var b:Int = 0; + var a:Int = 255; + var array:Array = cast c; + for(k=>e in array) { + if (e is Int || e is Float) { + switch(k) { + case 0: r = Std.int(e); + case 1: g = Std.int(e); + case 2: b = Std.int(e); + case 3: a = Std.int(e); + } + } + } + return FlxColor.fromRGB(r, g, b, a); + } + return null; + } + public static function difficultyString():String { return difficultyArray[PlayState.storyDifficulty]; diff --git a/source/funkin/system/MusicBeatState.hx b/source/funkin/system/MusicBeatState.hx index 84c8f031..2b685b13 100644 --- a/source/funkin/system/MusicBeatState.hx +++ b/source/funkin/system/MusicBeatState.hx @@ -7,6 +7,7 @@ import flixel.FlxG; import flixel.addons.transition.FlxTransitionableState; import flixel.addons.ui.FlxUIState; import flixel.math.FlxRect; +import flixel.math.FlxMath; import flixel.util.FlxTimer; class MusicBeatState extends FlxUIState @@ -78,4 +79,11 @@ class MusicBeatState extends FlxUIState { for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat); } + + public function lerp(v1:Float, v2:Float, ratio:Float, fpsSensitive:Bool = false) { + if (fpsSensitive) + return FlxMath.lerp(v1, v2, ratio); + else + return CoolUtil.fpsLerp(v1, v2, ratio); + } } diff --git a/source/funkin/system/MusicBeatSubstate.hx b/source/funkin/system/MusicBeatSubstate.hx index 4ba4da15..0d646d41 100644 --- a/source/funkin/system/MusicBeatSubstate.hx +++ b/source/funkin/system/MusicBeatSubstate.hx @@ -4,6 +4,7 @@ import funkin.system.Conductor.BPMChangeEvent; import funkin.system.Conductor; import flixel.FlxG; import flixel.FlxSubState; +import flixel.math.FlxMath; class MusicBeatSubstate extends FlxSubState { @@ -63,4 +64,11 @@ class MusicBeatSubstate extends FlxSubState { //do literally nothing dumbass } + + public function lerp(v1:Float, v2:Float, ratio:Float, fpsSensitive:Bool = false) { + if (fpsSensitive) + return FlxMath.lerp(v1, v2, ratio); + else + return CoolUtil.fpsLerp(v1, v2, ratio); + } } diff --git a/source/funkin/system/Paths.hx b/source/funkin/system/Paths.hx index 565a06a2..7281b047 100644 --- a/source/funkin/system/Paths.hx +++ b/source/funkin/system/Paths.hx @@ -18,7 +18,7 @@ class Paths inline public static var SOUND_EXT = #if web "mp3" #else "ogg" #end; private static var __useSourceAssets = false; - static function getPath(file:String, type:AssetType, library:Null, skipModsVerification:Bool = false) + public static function getPath(file:String, type:AssetType, library:Null, skipModsVerification:Bool = false) { if (library != null && library.startsWith("mods/")) { library = library.toLowerCase();