/// <summary> /// Handles an individual key release during gameplay. /// </summary> private void HandleKeyRelease(HitObjectManagerKeys manager, GameplayHitObjectKeys gameplayHitObject) { // Get judgement and references var lane = gameplayHitObject.Info.Lane - 1; var playfield = (GameplayPlayfieldKeys)Ruleset.Playfield; var hitDifference = (int)(manager.HeldLongNoteLanes[lane].Peek().Info.EndTime - manager.CurrentAudioPosition); var judgement = ((ScoreProcessorKeys)Ruleset.ScoreProcessor).CalculateScore(hitDifference, KeyPressType.Release); // Update animations playfield.Stage.HitLightingObjects[lane].StopHolding(); gameplayHitObject.StopLongNoteAnimation(); // Dequeue from pool gameplayHitObject = manager.HeldLongNoteLanes[lane].Dequeue(); // If LN has been released during a window if (judgement != Judgement.Ghost) { // Update stats Ruleset.ScoreProcessor.Stats.Add( new HitStat( HitStatType.Hit, KeyPressType.Release, gameplayHitObject.Info, (int)manager.CurrentAudioPosition, judgement, hitDifference, Ruleset.ScoreProcessor.Accuracy, Ruleset.ScoreProcessor.Health )); // Update scoreboard ((GameplayScreenView)Ruleset.Screen.View).UpdateScoreboardUsers(); // Update Playfield playfield.Stage.ComboDisplay.MakeVisible(); playfield.Stage.HitError.AddJudgement(judgement, (int)(gameplayHitObject.Info.EndTime - manager.CurrentAudioPosition)); playfield.Stage.JudgementHitBurst.PerformJudgementAnimation(judgement); // If the player recieved an early miss or "okay", // show the player that they were inaccurate by killing the object instead of recycling it if (judgement == Judgement.Miss || judgement == Judgement.Okay) { manager.KillHoldPoolObject(gameplayHitObject); } else { manager.RecyclePoolObject(gameplayHitObject); } return; } // If LN has been released early // Judgement for when the player releases too early const Judgement missedJudgement = Judgement.Miss; // Add new hit stat data and update score Ruleset.ScoreProcessor.Stats.Add( new HitStat( HitStatType.Hit, KeyPressType.Release, gameplayHitObject.Info, (int)manager.CurrentAudioPosition, Judgement.Miss, hitDifference, Ruleset.ScoreProcessor.Accuracy, Ruleset.ScoreProcessor.Health )); Ruleset.ScoreProcessor.CalculateScore(missedJudgement); // Update scoreboard var view = (GameplayScreenView)Ruleset.Screen.View; view.UpdateScoreboardUsers(); view.UpdateScoreAndAccuracyDisplays(); // Perform hit burst animation playfield.Stage.JudgementHitBurst.PerformJudgementAnimation(Judgement.Miss); // Update Object Pool manager.KillHoldPoolObject(gameplayHitObject); }
/// <summary> /// Handles an individual key press during gameplay. /// </summary> /// <param name="manager"></param> /// <param name="gameplayHitObject"></param> /// <param name="objectIndex"></param> private void HandleKeyPress(HitObjectManagerKeys manager, GameplayHitObjectKeys gameplayHitObject) { // Play the HitSounds of closest hit object. if (ConfigManager.EnableHitsounds.Value) { HitObjectManager.PlayObjectHitSounds(gameplayHitObject.Info); } // Get Judgement and references var time = (int)manager.CurrentAudioPosition; var hitDifference = gameplayHitObject.Info.StartTime - time; var judgement = ((ScoreProcessorKeys)Ruleset.ScoreProcessor).CalculateScore(hitDifference, KeyPressType.Press); var lane = gameplayHitObject.Info.Lane - 1; // Ignore Ghost Taps if (judgement == Judgement.Ghost) { return; } // Remove HitObject from Object Pool. Will be recycled/killed as necessary. gameplayHitObject = manager.ActiveNoteLanes[lane].Dequeue(); // Update stats Ruleset.ScoreProcessor.Stats.Add( new HitStat( HitStatType.Hit, KeyPressType.Press, gameplayHitObject.Info, time, judgement, hitDifference, Ruleset.ScoreProcessor.Accuracy, Ruleset.ScoreProcessor.Health )); // Update Scoreboard var view = (GameplayScreenView)Ruleset.Screen.View; view.UpdateScoreboardUsers(); view.UpdateScoreAndAccuracyDisplays(); // Update Playfield var playfield = (GameplayPlayfieldKeys)Ruleset.Playfield; playfield.Stage.ComboDisplay.MakeVisible(); playfield.Stage.HitError.AddJudgement(judgement, gameplayHitObject.Info.StartTime - manager.CurrentAudioPosition); playfield.Stage.JudgementHitBurst.PerformJudgementAnimation(judgement); // Update Object Pooling switch (judgement) { // Handle early miss cases here. case Judgement.Miss when gameplayHitObject.Info.IsLongNote: manager.KillPoolObject(gameplayHitObject); break; // Handle miss cases. case Judgement.Miss: manager.RecyclePoolObject(gameplayHitObject); break; // Handle non-miss cases. Perform Hit Lighting Animation and Handle Object pooling. default: playfield.Stage.HitLightingObjects[lane].PerformHitAnimation(gameplayHitObject.Info.IsLongNote); if (gameplayHitObject.Info.IsLongNote) { manager.ChangePoolObjectStatusToHeld(gameplayHitObject); gameplayHitObject.StartLongNoteAnimation(); } else { manager.RecyclePoolObject(gameplayHitObject); } break; } }