diff --git a/assets/data/weeks.xml b/assets/data/weeks.xml index bbae5b33..bf90f983 100644 --- a/assets/data/weeks.xml +++ b/assets/data/weeks.xml @@ -2,19 +2,19 @@ - - + + - - - - - - - + + + + + + + @@ -61,5 +61,11 @@ + + + + + + \ No newline at end of file diff --git a/assets/images/menus/storymenu/characters/spooky.png b/assets/images/menus/storymenu/characters/spooky.png index 7bd966dd..e4eb1b65 100644 Binary files a/assets/images/menus/storymenu/characters/spooky.png and b/assets/images/menus/storymenu/characters/spooky.png differ diff --git a/buildnumber.txt b/buildnumber.txt index 318d1517..0a678c62 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -1055 \ No newline at end of file +1081 \ No newline at end of file diff --git a/source/funkin/menus/StoryMenuState.hx b/source/funkin/menus/StoryMenuState.hx index 5b80d362..3bd13ccf 100644 --- a/source/funkin/menus/StoryMenuState.hx +++ b/source/funkin/menus/StoryMenuState.hx @@ -1,5 +1,6 @@ package funkin.menus; +import flixel.math.FlxPoint; import funkin.system.XMLUtil; import flixel.graphics.frames.FlxFramesCollection; import flixel.group.FlxGroup.FlxTypedGroup; @@ -93,6 +94,11 @@ class StoryMenuState extends MusicBeatState { e.scrollFactor.set(); add(e); } + + characterSprites = new FlxTypedGroup(); + for(i in 0...3) { + characterSprites.add(new MenuCharacterSprite(i)); + } add(characterSprites); for(i=>week in weeks) { @@ -143,11 +149,27 @@ class StoryMenuState extends MusicBeatState { } } + public function changeWeek(change:Int, force:Bool = false) { + if (change == 0 && !force) return; + + curWeek = FlxMath.wrap(curWeek + change, 0, weeks.length-1); + + if (!force) CoolUtil.playMenuSFX(); + for(k=>e in weekSprites.members) { + e.targetY = k - curWeek; + } + tracklist.text = 'TRACKS\n\n${[for(e in weeks[curWeek].songs) if (!e.hide) e.name.toUpperCase()].join('\n')}'; + + for(i in 0...3) + characterSprites.members[i].changeCharacter(characters[weeks[curWeek].chars[i]]); + + changeDifficulty(0, true); + } + var __oldDiffName = null; public function changeDifficulty(change:Int, force:Bool = false) { if (change == 0 && !force) return; - CoolUtil.playMenuSFX(0, 0.7); curDifficulty = FlxMath.wrap(curDifficulty + change, 0, weeks[curWeek].difficulties.length-1); if (__oldDiffName != (__oldDiffName = weeks[curWeek].difficulties[curDifficulty].toLowerCase())) { @@ -169,23 +191,17 @@ class StoryMenuState extends MusicBeatState { } } - public function changeWeek(change:Int, force:Bool = false) { - if (change == 0 && !force) return; - - curWeek = FlxMath.wrap(curWeek + change, 0, weeks.length-1); - - CoolUtil.playMenuSFX(); - for(k=>e in weekSprites.members) { - e.targetY = k - curWeek; - } - tracklist.text = 'TRACKS\n\n${[for(e in weeks[curWeek].songs) if (!e.hide) e.name.toUpperCase()].join('\n')}'; - changeDifficulty(0, true); - } - public function loadXMLs() { loadXML(Paths.xml('weeks')); } + public override function destroy() { + super.destroy(); + for(e in characters) + if (e != null && e.offset != null) + e.offset.put(); + } + public function loadXML(xmlPath:String) { try { var xml = new Access(Xml.parse(Assets.getText(xmlPath)).firstElement()); @@ -202,7 +218,11 @@ class StoryMenuState extends MusicBeatState { var charObj:MenuCharacter = { spritePath: Paths.image(char.getAtt('sprite').getDefault('menus/storymenu/characters/${char.att.name}')), scale: Std.parseFloat(char.getAtt('scale')).getDefault(1), - xml: char + xml: char, + offset: FlxPoint.get( + Std.parseFloat(char.getAtt('x')).getDefault(0), + Std.parseFloat(char.getAtt('y')).getDefault(0) + ) }; characters[char.att.name] = charObj; } @@ -279,6 +299,7 @@ typedef MenuCharacter = { var spritePath:String; var xml:Access; var scale:Float; + var offset:FlxPoint; // var frames:FlxFramesCollection; } @@ -286,14 +307,38 @@ class MenuCharacterSprite extends FlxSprite { public var character:String; - public function new(pos:Int, path:String) { - super(FlxG.width * (0.25 * pos), 80); + var pos:Int; + + public function new(pos:Int) { + super(0, 70); + this.pos = pos; + visible = false; + antialiasing = true; } + public var oldChar:MenuCharacter = null; + public function changeCharacter(data:MenuCharacter) { - CoolUtil.loadAnimatedGraphic(this, Paths.image(data.spritePath)); - for(e in data.xml.nodes.anim) - XMLUtil.addXMLAnimation(this, e); + visible = (data != null); + if (!visible) + return; + + if (oldChar != (oldChar = data)) { + CoolUtil.loadAnimatedGraphic(this, data.spritePath); + for(e in data.xml.nodes.anim) { + if (e.getAtt("name") == "idle") + animation.remove("idle"); + + XMLUtil.addXMLAnimation(this, e); + } + animation.play("idle"); + scale.set(data.scale, data.scale); + updateHitbox(); + offset.x += data.offset.x; + offset.y += data.offset.y; + + x = (FlxG.width * 0.25) * (1 + pos) - 150; + } } } class MenuItem extends FlxSprite diff --git a/source/funkin/system/CoolUtil.hx b/source/funkin/system/CoolUtil.hx index c639ba84..72f2f801 100644 --- a/source/funkin/system/CoolUtil.hx +++ b/source/funkin/system/CoolUtil.hx @@ -31,7 +31,13 @@ class CoolUtil * @return The return value */ public static function getDefault(v:T, defaultValue:T):T { - return v == null ? defaultValue : v; + return (v == null || isNaN(v)) ? defaultValue : v; + } + + public static function isNaN(v:Dynamic) { + if (v is Float || v is Int) + return Math.isNaN(cast(v, Float)); + return false; } public static function setFieldDefault(v:Dynamic, name:String, defaultValue:T):T { @@ -254,7 +260,9 @@ class CoolUtil public static function loadAnimatedGraphic(spr:FlxSprite, path:String) { spr.frames = loadFrames(path); - spr.animation.add("idle", [for(i in 0...spr.frames.frames.length) i], 24, true); - spr.animation.play("idle"); + if (spr.frames != null && spr.frames.frames != null) { + spr.animation.add("idle", [for(i in 0...spr.frames.frames.length) i], 24, true); + spr.animation.play("idle"); + } } } \ No newline at end of file diff --git a/source/funkin/system/XMLUtil.hx b/source/funkin/system/XMLUtil.hx index 24ea0f16..672fa46b 100644 --- a/source/funkin/system/XMLUtil.hx +++ b/source/funkin/system/XMLUtil.hx @@ -44,12 +44,12 @@ class XMLUtil { * @param sprite Destination sprite * @param anim Animation (Must be a `anim` XML node) */ - public static function addXMLAnimation(sprite:FlxSprite, anim:Access):ErrorCode { + public static function addXMLAnimation(sprite:FlxSprite, anim:Access, loop:Bool = false):ErrorCode { var animData:AnimData = { name: null, anim: null, fps: 24, - loop: false, + loop: loop, x: 0, y: 0, indices: [] @@ -60,6 +60,7 @@ class XMLUtil { if (anim.has.fps) animData.fps = Std.parseInt(anim.att.fps); if (anim.has.x) animData.x = Std.parseFloat(anim.att.x); if (anim.has.y) animData.y = Std.parseFloat(anim.att.y); + if (anim.has.loop) animData.loop = anim.att.loop == "true"; if (anim.has.indices) { var indicesSplit = anim.att.indices.split(","); for(indice in indicesSplit) {