Work in progress on redoing hold note rendering

This commit is contained in:
EliteMasterEric 2023-06-26 20:40:26 -04:00
parent 6d5c5f5acb
commit 47d8d9e4db
3 changed files with 91 additions and 40 deletions

View file

@ -1014,8 +1014,9 @@ class PlayState extends MusicBeatState
// super.stepHit() returns false if a module cancelled the event. // super.stepHit() returns false if a module cancelled the event.
if (!super.stepHit()) return false; if (!super.stepHit()) return false;
if (Math.abs(FlxG.sound.music.time - (Conductor.songPosition - Conductor.offset)) > 200 if (FlxG.sound.music != null
|| Math.abs(vocals.checkSyncError(Conductor.songPosition - Conductor.offset)) > 200) && (Math.abs(FlxG.sound.music.time - (Conductor.songPosition - Conductor.offset)) > 200
|| Math.abs(vocals.checkSyncError(Conductor.songPosition - Conductor.offset)) > 200))
{ {
trace("VOCALS NEED RESYNC"); trace("VOCALS NEED RESYNC");
if (vocals != null) trace(vocals.checkSyncError(Conductor.songPosition - Conductor.offset)); if (vocals != null) trace(vocals.checkSyncError(Conductor.songPosition - Conductor.offset));
@ -1473,7 +1474,6 @@ class PlayState extends MusicBeatState
// } // }
// Reset the notes on each strumline. // Reset the notes on each strumline.
var noteData:Array<SongNoteData> = currentChart.notes;
var playerNoteData:Array<SongNoteData> = []; var playerNoteData:Array<SongNoteData> = [];
var opponentNoteData:Array<SongNoteData> = []; var opponentNoteData:Array<SongNoteData> = [];
@ -1698,6 +1698,9 @@ class PlayState extends MusicBeatState
onNoteMiss(note); onNoteMiss(note);
} }
} }
// Process hold notes on the player's side.
// This handles scoring so we don't need it on the opponent's side.
} }
/** /**
@ -1737,6 +1740,8 @@ class PlayState extends MusicBeatState
{ {
var input:PreciseInputEvent = inputPressQueue.shift(); var input:PreciseInputEvent = inputPressQueue.shift();
playerStrumline.pressKey(input.noteDirection);
var notesInDirection:Array<NoteSprite> = notesByDirection[input.noteDirection]; var notesInDirection:Array<NoteSprite> = notesByDirection[input.noteDirection];
if (canMiss && notesInDirection.length == 0) if (canMiss && notesInDirection.length == 0)
@ -1777,6 +1782,8 @@ class PlayState extends MusicBeatState
// Play the strumline animation. // Play the strumline animation.
playerStrumline.playStatic(input.noteDirection); playerStrumline.playStatic(input.noteDirection);
playerStrumline.releaseKey(input.noteDirection);
} }
} }
@ -2004,10 +2011,6 @@ class PlayState extends MusicBeatState
note.active = false; note.active = false;
note.visible = false; note.visible = false;
// Kill the note.
// NOTE: This is what handles recycling the note graphic.
playerStrumline.killNote(note);
} }
/** /**

View file

@ -53,6 +53,8 @@ class Strumline extends FlxSpriteGroup
var noteData:Array<SongNoteData> = []; var noteData:Array<SongNoteData> = [];
var nextNoteIndex:Int = -1; var nextNoteIndex:Int = -1;
var heldKeys:Array<Bool> = [];
public function new(isPlayer:Bool) public function new(isPlayer:Bool)
{ {
super(); super();
@ -60,19 +62,23 @@ class Strumline extends FlxSpriteGroup
this.isPlayer = isPlayer; this.isPlayer = isPlayer;
this.strumlineNotes = new FlxTypedSpriteGroup<StrumlineNote>(); this.strumlineNotes = new FlxTypedSpriteGroup<StrumlineNote>();
this.strumlineNotes.zIndex = 10;
this.add(this.strumlineNotes); this.add(this.strumlineNotes);
// Hold notes are added first so they render behind regular notes. // Hold notes are added first so they render behind regular notes.
this.holdNotes = new FlxTypedSpriteGroup<SustainTrail>(); this.holdNotes = new FlxTypedSpriteGroup<SustainTrail>();
this.holdNotes.zIndex = 20;
this.add(this.holdNotes); this.add(this.holdNotes);
this.notes = new FlxTypedSpriteGroup<NoteSprite>(); this.notes = new FlxTypedSpriteGroup<NoteSprite>();
this.notes.zIndex = 30;
this.add(this.notes); this.add(this.notes);
this.noteSplashes = new FlxTypedSpriteGroup<NoteSplash>(0, 0, NOTE_SPLASH_CAP); this.noteSplashes = new FlxTypedSpriteGroup<NoteSplash>(0, 0, NOTE_SPLASH_CAP);
this.noteSplashes.zIndex = 40;
this.add(this.noteSplashes); this.add(this.noteSplashes);
for (i in 0...DIRECTIONS.length) for (i in 0...KEY_COUNT)
{ {
var child:StrumlineNote = new StrumlineNote(isPlayer, DIRECTIONS[i]); var child:StrumlineNote = new StrumlineNote(isPlayer, DIRECTIONS[i]);
child.x = getXPos(DIRECTIONS[i]); child.x = getXPos(DIRECTIONS[i]);
@ -81,13 +87,18 @@ class Strumline extends FlxSpriteGroup
this.strumlineNotes.add(child); this.strumlineNotes.add(child);
} }
for (i in 0...KEY_COUNT)
{
heldKeys.push(false);
}
// This MUST be true for children to update! // This MUST be true for children to update!
this.active = true; this.active = true;
} }
override function get_width():Float override function get_width():Float
{ {
return 4 * Strumline.NOTE_SPACING; return KEY_COUNT * Strumline.NOTE_SPACING;
} }
public override function update(elapsed:Float):Void public override function update(elapsed:Float):Void
@ -183,11 +194,11 @@ class Strumline extends FlxSpriteGroup
if (note == null) continue; if (note == null) continue;
if (note.time > renderWindowStart) break; if (note.time > renderWindowStart) break;
buildNoteSprite(note); var noteSprite = buildNoteSprite(note);
if (note.length > 0) if (note.length > 0)
{ {
buildHoldNoteSprite(note); noteSprite.holdNoteSprite = buildHoldNoteSprite(note);
} }
nextNoteIndex++; // Increment the nextNoteIndex rather than splicing the array, because splicing is slow. nextNoteIndex++; // Increment the nextNoteIndex rather than splicing the array, because splicing is slow.
@ -198,7 +209,8 @@ class Strumline extends FlxSpriteGroup
{ {
if (note == null || note.hasBeenHit) continue; if (note == null || note.hasBeenHit) continue;
note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime); var vwoosh:Bool = note.holdNoteSprite == null;
note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime, vwoosh);
// Check if the note is outside the hit window, and if so, mark it as missed. // Check if the note is outside the hit window, and if so, mark it as missed.
// TODO: Check to make sure this doesn't happen when the note is on screen because it'll probably get deleted. // TODO: Check to make sure this doesn't happen when the note is on screen because it'll probably get deleted.
@ -221,6 +233,17 @@ class Strumline extends FlxSpriteGroup
{ {
if (holdNote == null || !holdNote.alive) continue; if (holdNote == null || !holdNote.alive) continue;
if (Conductor.songPosition > holdNote.strumTime && holdNote.hitNote && !holdNote.missedNote)
{
if (isPlayer && !isKeyHeld(holdNote.noteDirection))
{
// Stopped pressing the hold note.
playStatic(holdNote.noteDirection);
holdNote.missedNote = true;
holdNote.alpha = 0.6;
}
}
var renderWindowEnd = holdNote.strumTime + holdNote.fullSustainLength + Conductor.HIT_WINDOW_MS + RENDER_DISTANCE_MS / 8; var renderWindowEnd = holdNote.strumTime + holdNote.fullSustainLength + Conductor.HIT_WINDOW_MS + RENDER_DISTANCE_MS / 8;
if (holdNote.missedNote && Conductor.songPosition >= renderWindowEnd) if (holdNote.missedNote && Conductor.songPosition >= renderWindowEnd)
@ -241,6 +264,28 @@ class Strumline extends FlxSpriteGroup
// TODO: Better handle the weird edge case where the hold note is almost completed. // TODO: Better handle the weird edge case where the hold note is almost completed.
holdNote.visible = false; holdNote.visible = false;
} }
else if (holdNote.missedNote && (holdNote.fullSustainLength > holdNote.sustainLength))
{
// Hold note was dropped before completing, keep it in its clipped state.
holdNote.visible = true;
var yOffset:Float = (holdNote.fullSustainLength - holdNote.sustainLength) * Conductor.PIXELS_PER_MS;
trace('yOffset: ' + yOffset);
trace('holdNote.fullSustainLength: ' + holdNote.fullSustainLength);
trace('holdNote.sustainLength: ' + holdNote.sustainLength);
var vwoosh:Bool = false;
if (PreferencesMenu.getPref('downscroll'))
{
holdNote.y = this.y + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2;
}
else
{
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2;
}
}
else if (Conductor.songPosition > holdNote.strumTime && holdNote.hitNote) else if (Conductor.songPosition > holdNote.strumTime && holdNote.hitNote)
{ {
// Hold note is currently being hit, clip it off. // Hold note is currently being hit, clip it off.
@ -258,38 +303,19 @@ class Strumline extends FlxSpriteGroup
holdNote.y = this.y - INITIAL_OFFSET + STRUMLINE_SIZE / 2; holdNote.y = this.y - INITIAL_OFFSET + STRUMLINE_SIZE / 2;
} }
} }
else if (holdNote.missedNote && (holdNote.fullSustainLength > holdNote.sustainLength))
{
// Hold note was dropped before completing, keep it in its clipped state.
holdNote.visible = true;
var yOffset:Float = (holdNote.fullSustainLength - holdNote.sustainLength) * Conductor.PIXELS_PER_MS;
trace('yOffset: ' + yOffset);
trace('holdNote.fullSustainLength: ' + holdNote.fullSustainLength);
trace('holdNote.sustainLength: ' + holdNote.sustainLength);
if (PreferencesMenu.getPref('downscroll'))
{
holdNote.y = this.y + calculateNoteYPos(holdNote.strumTime) - holdNote.height + STRUMLINE_SIZE / 2;
}
else
{
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime) + yOffset + STRUMLINE_SIZE / 2;
}
}
else else
{ {
// Hold note is new, render it normally. // Hold note is new, render it normally.
holdNote.visible = true; holdNote.visible = true;
var vwoosh:Bool = false;
if (PreferencesMenu.getPref('downscroll')) if (PreferencesMenu.getPref('downscroll'))
{ {
holdNote.y = this.y + calculateNoteYPos(holdNote.strumTime, false) - holdNote.height + STRUMLINE_SIZE / 2; holdNote.y = this.y + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2;
} }
else else
{ {
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, false) + STRUMLINE_SIZE / 2; holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + STRUMLINE_SIZE / 2;
} }
} }
} }
@ -302,6 +328,21 @@ class Strumline extends FlxSpriteGroup
if (holdNotes.members.length > 1) holdNotes.members.insertionSort(compareHoldNoteSprites.bind(FlxSort.ASCENDING)); if (holdNotes.members.length > 1) holdNotes.members.insertionSort(compareHoldNoteSprites.bind(FlxSort.ASCENDING));
} }
public function pressKey(dir:NoteDirection):Void
{
heldKeys[dir] = true;
}
public function releaseKey(dir:NoteDirection):Void
{
heldKeys[dir] = false;
}
public function isKeyHeld(dir:NoteDirection):Bool
{
return heldKeys[dir];
}
public function applyNoteData(data:Array<SongNoteData>):Void public function applyNoteData(data:Array<SongNoteData>):Void
{ {
this.notes.clear(); this.notes.clear();
@ -395,7 +436,7 @@ class Strumline extends FlxSpriteGroup
} }
} }
public function buildNoteSprite(note:SongNoteData):Void public function buildNoteSprite(note:SongNoteData):NoteSprite
{ {
var noteSprite:NoteSprite = constructNoteSprite(); var noteSprite:NoteSprite = constructNoteSprite();
@ -411,9 +452,11 @@ class Strumline extends FlxSpriteGroup
// noteSprite.x += INITIAL_OFFSET; // noteSprite.x += INITIAL_OFFSET;
noteSprite.y = -9999; noteSprite.y = -9999;
} }
return noteSprite;
} }
public function buildHoldNoteSprite(note:SongNoteData):Void public function buildHoldNoteSprite(note:SongNoteData):SustainTrail
{ {
var holdNoteSprite:SustainTrail = constructHoldNoteSprite(); var holdNoteSprite:SustainTrail = constructHoldNoteSprite();
@ -427,13 +470,16 @@ class Strumline extends FlxSpriteGroup
holdNoteSprite.missedNote = false; holdNoteSprite.missedNote = false;
holdNoteSprite.hitNote = false; holdNoteSprite.hitNote = false;
holdNoteSprite.alpha = 1.0;
holdNoteSprite.x = this.x; holdNoteSprite.x = this.x;
holdNoteSprite.x += getXPos(DIRECTIONS[note.getDirection() % KEY_COUNT]); holdNoteSprite.x += getXPos(DIRECTIONS[note.getDirection() % KEY_COUNT]);
// holdNoteSprite.x += INITIAL_OFFSET;
holdNoteSprite.x += STRUMLINE_SIZE / 2; holdNoteSprite.x += STRUMLINE_SIZE / 2;
holdNoteSprite.x -= holdNoteSprite.width / 2; holdNoteSprite.x -= holdNoteSprite.width / 2;
holdNoteSprite.y = -9999; holdNoteSprite.y = -9999;
} }
return holdNoteSprite;
} }
/** /**

View file

@ -283,8 +283,9 @@ class SongDifficulty
return timeChanges[0].bpm; return timeChanges[0].bpm;
} }
public function getPlayableChar(id:String):SongPlayableChar public function getPlayableChar(id:String):Null<SongPlayableChar>
{ {
if (id == null || id == '') return null;
return chars.get(id); return chars.get(id);
} }
@ -300,9 +301,10 @@ class SongDifficulty
public inline function cacheInst(?currentPlayerId:String = null):Void public inline function cacheInst(?currentPlayerId:String = null):Void
{ {
if (currentPlayerId != null) var currentPlayer:Null<SongPlayableChar> = getPlayableChar(currentPlayerId);
if (currentPlayer != null)
{ {
FlxG.sound.cache(Paths.inst(this.song.songId, getPlayableChar(currentPlayerId).inst)); FlxG.sound.cache(Paths.inst(this.song.songId, currentPlayer.inst));
} }
else else
{ {