diff --git a/source/funkin/objects/Character.hx b/source/funkin/objects/Character.hx index b80a186f..1aabdc81 100644 --- a/source/funkin/objects/Character.hx +++ b/source/funkin/objects/Character.hx @@ -12,7 +12,8 @@ typedef CharacterJson = { var isGF:Bool; } & SpriteJson; -class Character extends FlxSpriteExt { +class Character extends FlxSpriteExt +{ public static final DEFAULT_CHARACTER:CharacterJson = { anims: [], imagePath: "week1/BOYFRIEND", diff --git a/source/funkin/objects/NotesGroup.hx b/source/funkin/objects/NotesGroup.hx index fe96a77d..e2ea716e 100644 --- a/source/funkin/objects/NotesGroup.hx +++ b/source/funkin/objects/NotesGroup.hx @@ -8,9 +8,11 @@ import funkin.objects.note.StrumLineGroup; class NotesGroup extends Group { - public static var instance:NotesGroup = null; + public static var instance:NotesGroup; public var SONG:SwagSong; - var game:PlayState = null; + var game:PlayState; + var boyfriend:Character; + var dad:Character; public static var songSpeed:Float = 1.0; public var curSong:String = 'test'; @@ -44,12 +46,12 @@ class NotesGroup extends Group public var isPlayState:Bool = true; public function set_inBotplay(value:Bool) { - if (isPlayState) game.boyfriend.botMode = value; + if (boyfriend != null) boyfriend.botMode = value; return inBotplay = value; } public function set_dadBotplay(value:Bool) { - if (isPlayState) game.dad.botMode = value; + if (dad != null) dad.botMode = value; return dadBotplay = value; } @@ -57,11 +59,11 @@ class NotesGroup extends Group grpNoteSplashes.spawnSplash(note); } - inline function hitNote(note:Note, ?character:Character, botplayCheck:Bool = false, prefBot:Bool = false) { + inline function hitNote(note:Note, character:Character, botplayCheck:Bool = false, prefBot:Bool = false) { note.wasGoodHit = true; if (note.child != null) note.child.startedPress = true; - if (isPlayState) { + if (character != null) { character.sing(note.noteData, note.altAnim); Conductor.vocals.volume = 1; } @@ -77,11 +79,11 @@ class NotesGroup extends Group note.targetStrum.playStrumAnim('confirm', true); } - function pressSustain(sustain:Sustain, ?character:Character, botplayCheck:Bool = false, prefBot:Bool = false) { + function pressSustain(sustain:Sustain, character:Character, botplayCheck:Bool = false, prefBot:Bool = false) { if (!sustain.exists) return; - if (isPlayState) { + if (character != null) { character.sing(sustain.noteData, sustain.altAnim, false); Conductor.vocals.volume = 1; } @@ -105,6 +107,11 @@ class NotesGroup extends Group this.isPlayState = isPlayState; SONG = Song.checkSong(_SONG, null, false); //Double check null values curSong = SONG.song; + + if (isPlayState) { + boyfriend = game.boyfriend; + dad = game.dad; + } Conductor.mapBPMChanges(SONG); Conductor.bpm = SONG.bpm; @@ -127,28 +134,28 @@ class NotesGroup extends Group // Setup functions goodNoteHit.add((note:Note) -> { if (note.wasGoodHit) return; - hitNote(note, isPlayState ? game.boyfriend : null, inBotplay, getPref("botplay")); + hitNote(note, boyfriend, inBotplay, getPref("botplay")); ModdingUtil.addCall('goodNoteHit', [note]); ModdingUtil.addCall('noteHit', [note, true]); note.removeNote(); }); goodSustainPress.add((sustain:Sustain) -> { - pressSustain(sustain, isPlayState ? game.boyfriend : null, inBotplay, getPref("botplay")); + pressSustain(sustain, boyfriend, inBotplay, getPref("botplay")); ModdingUtil.addCall('goodSustainPress', [sustain]); ModdingUtil.addCall('sustainPress', [sustain, true]); }); opponentNoteHit.add((note:Note) -> { if (note.wasGoodHit) return; - hitNote(note, isPlayState ? game.dad : null, dadBotplay); + hitNote(note, dad, dadBotplay); ModdingUtil.addCall('opponentNoteHit', [note]); ModdingUtil.addCall('noteHit', [note, false]); note.removeNote(); }); opponentSustainPress.add((sustain:Sustain) -> { - pressSustain(sustain, isPlayState ? game.dad : null, dadBotplay); + pressSustain(sustain, dad, dadBotplay); ModdingUtil.addCall('opponentSustainPress', [sustain]); ModdingUtil.addCall('sustainPress', [sustain, false]); }); @@ -176,8 +183,7 @@ class NotesGroup extends Group ModdingUtil.addCall('noteMiss', [note]); - var char:Character = note.mustPress ? game.boyfriend : game.dad; - char.sing(note.noteData, 'miss'); + (note.mustPress ? boyfriend : game.dad).sing(note.noteData, "miss"); game.updateScore(); }); @@ -189,10 +195,10 @@ class NotesGroup extends Group ModdingUtil.addCall('badNoteHit', [data]); if (!inBotplay) - game.boyfriend.sing(data, 'miss'); + boyfriend.sing(data, 'miss'); if (!dadBotplay) - game.dad.sing(data, 'miss'); + dad.sing(data, 'miss'); game.updateScore(); }); @@ -604,16 +610,17 @@ class NotesGroup extends Group if (!inBotplay) checkStrums(playerStrums.members); if (!dadBotplay) checkStrums(opponentStrums.members); - // Check for sing animations in PlayState characters - if (isPlayState) { - if (!inBotplay) checkOverSinging(game.boyfriend, playerStrums); - if (!dadBotplay) checkOverSinging(game.dad, opponentStrums); - } + // Check for sing animations in characters + if (!inBotplay) checkOverSinging(boyfriend, playerStrums); + if (!dadBotplay) checkOverSinging(dad, opponentStrums); } - function checkOverSinging(char:Character, strums:StrumLineGroup):Void { + function checkOverSinging(char:Character, strums:StrumLineGroup):Void + { + if (char == null) return; + if (char.animation.curAnim == null) return; + var anim = char.animation.curAnim; - if (anim == null) return; var name:String = anim.name; var overSinging:Bool = diff --git a/source/funkin/objects/note/BasicNote.hx b/source/funkin/objects/note/BasicNote.hx index 0a23065b..06be9cfc 100644 --- a/source/funkin/objects/note/BasicNote.hx +++ b/source/funkin/objects/note/BasicNote.hx @@ -7,7 +7,8 @@ interface INoteData { public var noteData:Int; } -class BasicNote extends SmartSprite implements INoteData { +class BasicNote extends SmartSprite implements INoteData +{ public var strumTime:Float = 0.0; public var noteData:Int = 0; public var mustPress:Bool = false; diff --git a/source/funkin/objects/note/Note.hx b/source/funkin/objects/note/Note.hx index 56cbe616..484db3cf 100644 --- a/source/funkin/objects/note/Note.hx +++ b/source/funkin/objects/note/Note.hx @@ -10,9 +10,13 @@ class Note extends BasicNote override function updateSprites() { super.updateSprites(); - playAnim('scroll' + CoolUtil.directionArray[noteData]); + updateAnim(); } + public function updateAnim() { + playAnim('scroll' + CoolUtil.directionArray[noteData]); + } + override function applyCurOffset(forced:Bool = false) { if (animation.curAnim != null) { if(existsOffsets(animation.curAnim.name)) { diff --git a/source/funkin/objects/note/Sustain.hx b/source/funkin/objects/note/Sustain.hx index 46cfdf8b..32ba3f41 100644 --- a/source/funkin/objects/note/Sustain.hx +++ b/source/funkin/objects/note/Sustain.hx @@ -4,8 +4,11 @@ import flixel.graphics.frames.FlxFrame; class Sustain extends BasicNote { - public function new(noteData:Int = 0, strumTime:Float = 0.0, susLength:Float = 0.0, skin:String = "default", ?parent:Note):Void { - clipRect = FlxRect.get(); + public function new(noteData:Int = 0, strumTime:Float = 0.0, susLength:Float = 0.0, skin:String = "default", ?parent:Note):Void + { + var initSus:Bool = (susLength > 0); + if (initSus) clipRect = FlxRect.get(); + super(noteData, strumTime, skin); // Load skin this.parent = parent; @@ -13,9 +16,11 @@ class Sustain extends BasicNote drawStyle = BOTTOM_TOP; alpha = 0.6; - yDisplace = NoteUtil.noteHeight * 0.5; - this.susLength = susLength; - setSusLength(susLength); + if (initSus) { + yDisplace = NoteUtil.noteHeight * 0.5; + this.susLength = susLength; + setSusLength(susLength); + } } override function set_noteSpeed(value:Float):Float { @@ -126,7 +131,9 @@ class Sustain extends BasicNote setTiles(1, 1); calcHeight = frameHeight; repeatHeight = lastHeight; - clipRect.width = repeatWidth; + + if (clipRect != null) + clipRect.width = repeatWidth; } override function setupTile(tileX:Int, tileY:Int, baseFrame:FlxFrame):FlxPoint { diff --git a/source/funkin/states/editors/chart/ChartGridBase.hx b/source/funkin/states/editors/chart/ChartGridBase.hx index 4543dce0..c7f1b9e4 100644 --- a/source/funkin/states/editors/chart/ChartGridBase.hx +++ b/source/funkin/states/editors/chart/ChartGridBase.hx @@ -286,7 +286,6 @@ class ChartSustain extends Sustain { } repeatHeight = FlxMath.remapToRange(chartData[2], 0, Conductor.stepCrochet, 0, GRID_SIZE) + GRID_SIZE * .5; - clipRect.height = repeatHeight; } } diff --git a/source/funkin/states/newchart/ChartEditor.hx b/source/funkin/states/newchart/ChartEditor.hx index 16f49b09..c6b2488c 100644 --- a/source/funkin/states/newchart/ChartEditor.hx +++ b/source/funkin/states/newchart/ChartEditor.hx @@ -25,6 +25,7 @@ class ChartEditor extends MusicBeatState public static function setupSong(song:String, diff:String, ?input:SwagSong):SwagSong { SONG = input ?? Song.loadFromFile(diff, song); + Conductor.loadSong(SONG.song); Conductor.bpm = SONG.bpm; Conductor.songPosition = 0.0; return SONG; diff --git a/source/funkin/states/newchart/ChartGrid.hx b/source/funkin/states/newchart/ChartGrid.hx index c57607e0..15319063 100644 --- a/source/funkin/states/newchart/ChartGrid.hx +++ b/source/funkin/states/newchart/ChartGrid.hx @@ -13,6 +13,7 @@ class ChartGrid extends Group var notesGrid:FlxBackdrop; var eventsGrid:FlxBackdrop; + var content:ChartGridContent; var beats:FlxBackdrop; @@ -60,6 +61,9 @@ class ChartGrid extends Group strumline = new ChartStrumLine(notesGrid.x); add(strumline); + content = new ChartGridContent(); + add(content); + prepareBpmChanges(); prepareObjects(); @@ -87,14 +91,17 @@ class ChartGrid extends Group } } - function move(elapsed:Float):Void { - Conductor.songPosition += elapsed * 1000; - - if (Conductor.songPosition < 0) - Conductor.songPosition = 0; + function move(elapsed:Float):Void + { + Conductor.songPosition = boundTime(Conductor.songPosition + elapsed * 1000); - if (Conductor.songPosition >= sectionTimes[curSection + 1]) curSection++; - if (Conductor.songPosition < sectionTimes[curSection]) { + if (Conductor.songPosition >= sectionTimes[curSection + 1]) + { + if ((curSection + 1) != (sectionTimes.length - 1)) + curSection++; + } + else if (Conductor.songPosition < sectionTimes[curSection]) + { curSection--; Conductor.songPosition = sectionTimes[curSection + 1] - 1; // Adjust time } @@ -131,7 +138,12 @@ class ChartGrid extends Group // Get the conductor songPosition time Y inline function getCurrentTimeY():Float { - return getTimeY(Math.max(0, getTime())); + return getTimeY(boundTime(getTime())); + } + + // Bound a time value to the inst length + inline function boundTime(time:Float) { + return FlxMath.bound(time, 0, Conductor.inst.length - Conductor.offset[0] - Conductor.latency); } // TODO: @@ -139,19 +151,17 @@ class ChartGrid extends Group // Maybe generate notes first and make another function to position them at runtime? // Make a beats seperator class to accomodate for that too - public var sectionObjects:Array> = []; - function prepareObjects() { ChartEditor.SONG.notes.fastForEach((section, i) -> { - var array:Array = []; + var array:Array = []; section.sectionNotes.fastForEach((note, i) -> { - var note = makeNote(note[0], note[1]); + var note = makeNote(note[0], note[1], note[2]); array.push(note); }); - sectionObjects.push(array); + content.sectionNotes.push(array); }); } @@ -171,14 +181,16 @@ class ChartGrid extends Group time += 4 * (60000 / bpm); }); + + sectionTimes.push(time); } - function makeNote(strumTime:Float, noteData:Int) { - var note = new Note(noteData, strumTime); - note.x = notesGrid.x + (TILE * noteData); - note.y = getTimeY(strumTime); - note.setGraphicSize(TILE, TILE); - note.updateHitbox(); + function makeNote(strumTime:Float, noteData:Int, ?susLength:Float) { + var note = new ChartNote(noteData, susLength ?? 0, downscroll); + note.setPos( + notesGrid.x + (TILE * noteData), + getTimeY(strumTime) + ); return note; } @@ -190,24 +202,7 @@ class ChartGrid extends Group Conductor.songPosition = sectionTimes[value] ?? sectionTimes[sectionTimes.length - 1]; updatePosition(); - return curSection = value; - } - - override function draw() { - super.draw(); - - // Render the 3 current visible sections, maybe make this higher depending on the snap? - // TODO: replace with ChartGridContent - for (i in 0...3) - { - if (sectionObjects[curSection - 1 + i] != null) - { - sectionObjects[curSection - 1 + i].fastForEach((object, i) -> { - if (object != null) if (object.exists) if (object.visible) - object.draw(); - }); - } - } + return content.renderSection = curSection = value; } override function destroy() { diff --git a/source/funkin/states/newchart/ChartGridContent.hx b/source/funkin/states/newchart/ChartGridContent.hx index 445322ce..23224921 100644 --- a/source/funkin/states/newchart/ChartGridContent.hx +++ b/source/funkin/states/newchart/ChartGridContent.hx @@ -2,10 +2,9 @@ package funkin.states.newchart; class ChartGridContent extends FlxBasic { - public var sectionSustains:Array> = []; - public var sectionNotes:Array> = []; - public var sectionEvents:Array> = []; - public var sectionTexts:Array> = []; + public var sectionNotes:Array> = []; + public var sectionEvents:Array> = []; + public var sectionTexts:Array> = []; public var renderSection:Int = 0; public var renderRange:Int = 3; diff --git a/source/funkin/states/newchart/ChartNote.hx b/source/funkin/states/newchart/ChartNote.hx new file mode 100644 index 00000000..41dbfd16 --- /dev/null +++ b/source/funkin/states/newchart/ChartNote.hx @@ -0,0 +1,55 @@ +package funkin.states.newchart; + +class ChartNote extends Group +{ + var note:Note; + var sustain:Sustain; + + var hasSustain:Bool; + + public function new(noteData:Int, susLength:Float, downscroll:Bool) { + super(); + + note = new Note(0); + note.setGraphicSize(40, 40); + note.updateHitbox(); + + hasSustain = (susLength > 0); + + if (hasSustain) + { + sustain = new Sustain(0); + sustain.setScale(note.scale.x); + add(sustain); + + sustain.setTiles(1, 1); + sustain.repeatHeight = FlxMath.remapToRange(susLength, 0, Conductor.stepCrochet, 0, 40) + 20; + + sustain.offset.y = 0; + sustain.offset.x -= (20 - (sustain.width * 0.5)); + sustain.origin.set((sustain.width * .5) / sustain.scale.x, 0); + + sustain.approachAngle = downscroll ? 180 : 0; + } + + add(note); + set(noteData); + } + + public function setPos(x:Float, y:Float):Void + { + note.setPosition(x, y); + if (hasSustain) + sustain.setPosition(x, y + 20); + } + + public function set(noteData:Int):Void + { + noteData %= 4; + note.noteData = noteData; + note.updateAnim(); + + if (hasSustain) + sustain.noteData = noteData; + } +} \ No newline at end of file