diff --git a/index.php b/index.php
index cb64fa5..4efb465 100644
--- a/index.php
+++ b/index.php
@@ -1,11 +1,12 @@
addVersionToJsImports($version);
}
diff --git a/src/assets/styles/virtual-fretboard.css b/src/assets/styles/virtual-fretboard.css
index c8e9243..f814731 100644
--- a/src/assets/styles/virtual-fretboard.css
+++ b/src/assets/styles/virtual-fretboard.css
@@ -1,10 +1,14 @@
@media (min-width: 100px) {
+ #treble-clef-output {
+ display: none;
+ }
+
#fretboard {
display: flex;
flex-direction: column;
- width: 80%;
+ width: 100%;
margin: auto;
- border-right: 3px solid lightgrey;
+ padding-right: 40px;
}
.string {
@@ -15,15 +19,21 @@
justify-content: space-between;
position: relative;
height: 30px;
+ border-right: 3px solid #b7b7b7;
+
}
.fret {
- width: calc(100% / 12);
+ flex-grow: 1;
height: 100%;
border-left: 1px solid white;
border-right: 1px solid white;
margin: 1px 0;
cursor: pointer;
+ position: relative;
+ }
+ .fret:hover, .string-name:hover{
+ background-color: rgba(255, 255, 255, 0.1);
}
.string hr {
@@ -33,4 +43,43 @@
width: 100%;
height: 1px;
}
+
+ .string-name{
+ position: absolute;
+ right: -40px;
+ font-size: 20px;
+ color: #d0d0d0;
+ width: 40px;
+ cursor: pointer;
+ }
+ .fret-helper{
+ top: -10px;
+ /*left: 50%;*/
+ max-width: 10px;
+ height: 10px;
+ background-color: #868686;
+ border-radius: 50%;
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+ .key-note-indicator{
+ max-width: 10px;
+ height: 10px;
+ background-color: #005400;
+ border: 1px solid #129b00;
+ /*border-radius: 50%;*/
+ bottom: 50%;
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%) translateY(50%);
+ z-index: 2;
+ }
+
+}
+
+@media (min-width: 961px) {
+ #fretboard {
+ width: 80%;
+ }
}
diff --git a/src/features/detected-note/detected-note-verifier.js b/src/features/detected-note/detected-note-verifier.js
index f6d6b31..74df881 100644
--- a/src/features/detected-note/detected-note-verifier.js
+++ b/src/features/detected-note/detected-note-verifier.js
@@ -1,5 +1,5 @@
-import {DetectedNoteVisualizer} from "./detected-note-visualizer.js?v=1.2.6";
-import {NoteCombinationVisualizer} from "../game-core/game-ui/note-combination-visualizer.js?v=1.2.6";
+import {DetectedNoteVisualizer} from "./detected-note-visualizer.js?v=1.3.0";
+import {NoteCombinationVisualizer} from "../game-core/game-ui/note-combination-visualizer.js?v=1.3.0";
export class DetectedNoteVerifier {
// Variable is set in note-combination-coordinator each time new note is displayed
diff --git a/src/features/game-core/frequency-bars/frequency-bars-controller.js b/src/features/game-core/frequency-bars/frequency-bars-controller.js
index 1df2c09..c6a797a 100644
--- a/src/features/game-core/frequency-bars/frequency-bars-controller.js
+++ b/src/features/game-core/frequency-bars/frequency-bars-controller.js
@@ -1,4 +1,4 @@
-import {FrequencyBarsVisualizer} from "./frequency-bars-visualizer.js?v=1.2.6";
+import {FrequencyBarsVisualizer} from "./frequency-bars-visualizer.js?v=1.3.0";
export class FrequencyBarsController {
diff --git a/src/features/game-core/game-initialization/core-game-coordination-initializer.js b/src/features/game-core/game-initialization/core-game-coordination-initializer.js
index fa8d6a0..c5e7b27 100644
--- a/src/features/game-core/game-initialization/core-game-coordination-initializer.js
+++ b/src/features/game-core/game-initialization/core-game-coordination-initializer.js
@@ -1,19 +1,14 @@
-import {CoreGameCoordinator} from "../game-start/core-game-coordinator.js?v=1.2.6";
+import {CoreGameCoordinator} from "../game-start/core-game-coordinator.js?v=1.3.0";
import {
FretboardNoteGameCoordinator
-} from "../../game-modes/note-on-fretboard/fretboard-note-game-coordinator.js?v=1.2.6";
-import {NoteInKeyGameCoordinator} from "../../game-modes/note-in-key/note-in-key-game-coordinator.js?v=1.2.6";
-import {GameConfigurationManager} from "./game-configuration-manager.js?v=1.2.6";
-import {GameElementsVisualizer} from "../game-ui/game-elements-visualizer.js?v=1.2.6";
-import {MetronomePracticeCoordinator} from "../../game-modes/metronome/metronome-practice-coordinator.js?v=1.2.6";
+} from "../../game-modes/note-on-fretboard/fretboard-note-game-coordinator.js?v=1.3.0";
+import {NoteInKeyGameCoordinator} from "../../game-modes/note-in-key/note-in-key-game-coordinator.js?v=1.3.0";
+import {GameConfigurationManager} from "./game-configuration-manager.js?v=1.3.0";
+import {MetronomePracticeCoordinator} from "../../game-modes/metronome/metronome-practice-coordinator.js?v=1.3.0";
export class CoreGameCoordinationInitializer {
- /**
- * @param {GameInitializer} gameInitializer
- */
- constructor(gameInitializer) {
- this.gameInitializer = gameInitializer;
+ constructor() {
this.coreGameCoordinator = new CoreGameCoordinator(this);
}
@@ -22,69 +17,55 @@ export class CoreGameCoordinationInitializer {
* All game coordinators MUST implement destroy(), play() and stop() methods (setup is in constructor)
*/
setCorrectAndInitGameCoordinator() {
- // Remove game mode specific elements / reset for new game mode
- if (this.coreGameCoordinator.gameCoordinator !== null) {
- this.coreGameCoordinator.gameCoordinator?.destroy();
- // Reset game area
- GameElementsVisualizer.hideGameElementsAndDisplayInstructions();
- }
+
// Remove game mode options from previous game mode
document.querySelector('#game-mode-options').innerHTML = '';
// Make sure that the start button is enabled
document.querySelector('#start-stop-btn').disabled = false;
- // Default values
- // Enable tuner that detects note to true as default value
- this.coreGameCoordinator.noteDetectorEnabled = true;
-
// Figure out which game mode should be started
// All game coordinators MUST implement a play() and stop() method.
// Initialization is done in the constructor
if (document.querySelector('#metronome-game-mode input').checked) {
this.coreGameCoordinator.gameCoordinator = new MetronomePracticeCoordinator();
- this.coreGameCoordinator.noteDetectorEnabled = false;
- this.coreGameCoordinator.metronomeEnabled = true;
- this.coreGameCoordinator.scoreEnabled = false;
- this.coreGameCoordinator.progressBarEnabled = false;
+ this.setMetronomeGameModeVariables();
} else if (document.querySelector('#fretboard-note-game-mode input').checked) {
this.coreGameCoordinator.gameCoordinator = new FretboardNoteGameCoordinator();
- this.coreGameCoordinator.metronomeEnabled = true;
- this.coreGameCoordinator.scoreEnabled = true;
- this.coreGameCoordinator.progressBarEnabled = true;
+ this.setFretboardNoteGameModeVariables();
} else if (document.querySelector('#note-in-key-game-mode input').checked) {
this.coreGameCoordinator.gameCoordinator = new NoteInKeyGameCoordinator();
- this.coreGameCoordinator.metronomeEnabled = false;
- this.coreGameCoordinator.scoreEnabled = false;
- this.coreGameCoordinator.progressBarEnabled = true;
+ // Needs to be in own function for no guitar change event handler
+ this.setNoteInKeyGameModeVariables();
} else {
// If no game mode is selected, disable the play button
document.querySelector('#start-stop-btn').disabled = true;
}
// All game coordinators MUST implement a play() and stop() method
- // Disable metronome and note detector if no guitar option is selected
- this.noGuitarOption();
-
// Init game mode options after they have been added via instantiation of the correct gameModeCoordinator above
GameConfigurationManager.initGameModeOptions();
}
- noGuitarOption(){
- // Overwrite noteDetectorEnabled and metronomeEnabled if the user has selected "no guitar"
- const noGuitarCheckbox = document.querySelector('#no-guitar-option input');
- noGuitarCheckbox?.addEventListener('change', function () {
- disableNoteDetectorIfNoGuitarChecked();
- });
- const self = this;
- const disableNoteDetectorIfNoGuitarChecked = function() {
- if (noGuitarCheckbox?.checked) {
- self.coreGameCoordinator.metronomeEnabled = false;
- self.coreGameCoordinator.noteDetectorEnabled = false;
- }
- }
- disableNoteDetectorIfNoGuitarChecked();
+ setMetronomeGameModeVariables() {
+ this.coreGameCoordinator.noteDetectorEnabled = false;
+ this.coreGameCoordinator.metronomeEnabled = true;
+ this.coreGameCoordinator.scoreEnabled = false;
+ this.coreGameCoordinator.progressBarEnabled = false;
+ }
+
+ setFretboardNoteGameModeVariables() {
+ this.coreGameCoordinator.metronomeEnabled = true;
+ this.coreGameCoordinator.scoreEnabled = true;
+ this.coreGameCoordinator.progressBarEnabled = true;
+ this.coreGameCoordinator.noteDetectorEnabled = true;
}
+ setNoteInKeyGameModeVariables() {
+ this.coreGameCoordinator.metronomeEnabled = false;
+ this.coreGameCoordinator.scoreEnabled = false;
+ this.coreGameCoordinator.progressBarEnabled = true;
+ this.coreGameCoordinator.noteDetectorEnabled = true;
+ }
/**
* Start and stop game or metronome
diff --git a/src/features/game-core/game-initialization/game-configuration-manager.js b/src/features/game-core/game-initialization/game-configuration-manager.js
index 46706bc..988fd6b 100644
--- a/src/features/game-core/game-initialization/game-configuration-manager.js
+++ b/src/features/game-core/game-initialization/game-configuration-manager.js
@@ -1,4 +1,4 @@
-import {GameProgressVisualizer} from "../game-progress/game-progress-visualizer.js?v=1.2.6";
+import {GameProgressVisualizer} from "../game-progress/game-progress-visualizer.js?v=1.3.0";
export class GameConfigurationManager {
diff --git a/src/features/game-core/game-initialization/game-initializer.js b/src/features/game-core/game-initialization/game-initializer.js
index 7bbb097..6970914 100644
--- a/src/features/game-core/game-initialization/game-initializer.js
+++ b/src/features/game-core/game-initialization/game-initializer.js
@@ -1,6 +1,7 @@
-import {GameConfigurationManager} from "./game-configuration-manager.js?v=1.2.6";
-import {CoreGameCoordinationInitializer} from "./core-game-coordination-initializer.js?v=1.2.6";
-import {VisibilityChangeHandler} from "./visibility-change-handler.js?v=1.2.6";
+import {GameConfigurationManager} from "./game-configuration-manager.js?v=1.3.0";
+import {CoreGameCoordinationInitializer} from "./core-game-coordination-initializer.js?v=1.3.0";
+import {VisibilityChangeHandler} from "./visibility-change-handler.js?v=1.3.0";
+import {GameElementsVisualizer} from "../game-ui/game-elements-visualizer.js?v=1.3.0";
export class GameInitializer {
constructor() {
@@ -27,6 +28,12 @@ export class GameInitializer {
this.coreGameCoordinationInitializer.setCorrectAndInitGameCoordinator();
document.addEventListener('game-mode-change', (e) => {
+ // Remove game mode specific elements / reset for new game mode
+ if (this.coreGameCoordinationInitializer.coreGameCoordinator.gameCoordinator !== null) {
+ this.coreGameCoordinationInitializer.coreGameCoordinator.gameCoordinator?.destroy();
+ // Reset game area
+ GameElementsVisualizer.hideGameElementsAndDisplayInstructions();
+ }
this.coreGameCoordinationInitializer.setCorrectAndInitGameCoordinator();
});
}
@@ -44,7 +51,8 @@ export class GameInitializer {
// Check if the target is
or if a parent of the target is (to avoid catching dblclicks in
// header, but only if the modal is not open)
if ((e.target === document.body || e.target.closest('main'))
- && (e.target.id !== 'modal' && !e.target.closest('#modal') && e.target.nodeName !== 'INPUT')) {
+ && (e.target.id !== 'modal' && !e.target.closest('#modal') && e.target.nodeName !== 'INPUT')
+ && !e.target.closest('#fretboard')) {
self.coreGameCoordinationInitializer.startOrStopButtonActionHandler();
}
});
diff --git a/src/features/game-core/game-loader.js b/src/features/game-core/game-loader.js
index 2e85a13..076444c 100644
--- a/src/features/game-core/game-loader.js
+++ b/src/features/game-core/game-loader.js
@@ -1,4 +1,4 @@
-import {GameInitializer} from "./game-initialization/game-initializer.js?v=1.2.6";
+import {GameInitializer} from "./game-initialization/game-initializer.js?v=1.3.0";
export class GameLoader {
constructor() {
diff --git a/src/features/game-core/game-progress/game-progress-updater.js b/src/features/game-core/game-progress/game-progress-updater.js
index 6d9fe97..92d19ce 100644
--- a/src/features/game-core/game-progress/game-progress-updater.js
+++ b/src/features/game-core/game-progress/game-progress-updater.js
@@ -1,4 +1,4 @@
-import {GameProgressVisualizer} from "./game-progress-visualizer.js?v=1.2.6";
+import {GameProgressVisualizer} from "./game-progress-visualizer.js?v=1.3.0";
/**
* Progress update for games that use the metronome and have challenging
diff --git a/src/features/game-core/game-start/core-game-coordinator.js b/src/features/game-core/game-start/core-game-coordinator.js
index e723acc..fb4c3b6 100644
--- a/src/features/game-core/game-start/core-game-coordinator.js
+++ b/src/features/game-core/game-start/core-game-coordinator.js
@@ -1,8 +1,8 @@
-import {MetronomeOperator} from "../metronome/metronome-operator.js?v=1.2.6";
-import {TuneOperator} from "../tuner/tune-operator.js?v=1.2.6";
-import {FrequencyBarsController} from "../frequency-bars/frequency-bars-controller.js?v=1.2.6";
-import {GameElementsVisualizer} from "../game-ui/game-elements-visualizer.js?v=1.2.6";
-import {ScreenWakeLocker} from "../wake-lock/screen-wake-locker.js?v=1.2.6";
+import {MetronomeOperator} from "../metronome/metronome-operator.js?v=1.3.0";
+import {TuneOperator} from "../tuner/tune-operator.js?v=1.3.0";
+import {FrequencyBarsController} from "../frequency-bars/frequency-bars-controller.js?v=1.3.0";
+import {GameElementsVisualizer} from "../game-ui/game-elements-visualizer.js?v=1.3.0";
+import {ScreenWakeLocker} from "../wake-lock/screen-wake-locker.js?v=1.3.0";
export class CoreGameCoordinator {
metronomeOperator = new MetronomeOperator();
@@ -23,8 +23,8 @@ export class CoreGameCoordinator {
gameRunning = false;
manuallyPaused = false;
- constructor() {
-
+ constructor(coreGameInitializer) {
+ this.coreGameInitializer = coreGameInitializer;
// Listen for game stop event to stop game
document.addEventListener('game-stop', this.stopGame.bind(this));
document.addEventListener('game-start', this.startGame.bind(this));
@@ -40,6 +40,9 @@ export class CoreGameCoordinator {
this.gameRunning = true;
+ // Disable metronome and note detector if no guitar option is selected
+ this.noGuitarOption();
+
// Start metronome only if tuner is fully started (if it needs to)
this.startTuner().then(() => {
if (this.metronomeEnabled) {
@@ -126,4 +129,22 @@ export class CoreGameCoordinator {
this.stopAndResumeAfterVisibilityChange = true;
}
}
+ noGuitarOption(){
+ // Overwrite noteDetectorEnabled and metronomeEnabled if the user has selected "no guitar"
+ const noGuitarCheckbox = document.querySelector('#no-guitar-option input');
+ noGuitarCheckbox?.addEventListener('change', function () {
+ toggleNoteDetectorIfNoGuitarChecked();
+ });
+ const self = this;
+ const toggleNoteDetectorIfNoGuitarChecked = function() {
+ if (noGuitarCheckbox?.checked) {
+ self.metronomeEnabled = false;
+ self.noteDetectorEnabled = false;
+ } else {
+ // Init game core game logic such as metronome, note detector
+ self.coreGameInitializer.setNoteInKeyGameModeVariables();
+ }
+ }
+ toggleNoteDetectorIfNoGuitarChecked();
+ }
}
\ No newline at end of file
diff --git a/src/features/game-core/game-ui/game-elements-visualizer.js b/src/features/game-core/game-ui/game-elements-visualizer.js
index 9852fe0..b25b10a 100644
--- a/src/features/game-core/game-ui/game-elements-visualizer.js
+++ b/src/features/game-core/game-ui/game-elements-visualizer.js
@@ -1,4 +1,4 @@
-import {GameLevelTracker} from "../game-progress/game-level-tracker.js?v=1.2.6";
+import {GameLevelTracker} from "../game-progress/game-level-tracker.js?v=1.3.0";
export class GameElementsVisualizer {
static hideGameElementsAndDisplayInstructions() {
diff --git a/src/features/game-core/game-ui/note-combination-visualizer.js b/src/features/game-core/game-ui/note-combination-visualizer.js
index 94b5a85..3c7c69d 100644
--- a/src/features/game-core/game-ui/note-combination-visualizer.js
+++ b/src/features/game-core/game-ui/note-combination-visualizer.js
@@ -1,4 +1,4 @@
-import {TrebleClefVisualizer} from "../../treble-clef/treble-clef-visualizer.js?v=1.2.6";
+import {TrebleClefVisualizer} from "../../treble-clef/treble-clef-visualizer.js?v=1.3.0";
export class NoteCombinationVisualizer {
@@ -11,7 +11,14 @@ export class NoteCombinationVisualizer {
this.frequencyBarsController.updateFrequencyBarsFillStyle(color);
}
- static displayCombination(stringName, noteName, displayInTrebleClef = false, displayTrebleClefAndNoteName = false) {
+ static displayCombinationWithNoteNumber(stringName, noteNumber, noteName = null){
+ const noteSpan = document.getElementById('note-span');
+ noteSpan.dataset.noteName = noteName;
+ noteSpan.innerHTML = noteNumber;
+ document.getElementById('string-span').innerHTML = stringName;
+ }
+
+ static displayCombinationWithNoteName(stringName, noteName, displayInTrebleClef = false, displayTrebleClefAndNoteName = false) {
// Adds the treble-clef-enabled class if displayInTrebleClef is truthy, removes it otherwise
document.getElementById('string-span').classList
.toggle('treble-clef-enabled', displayInTrebleClef || displayTrebleClefAndNoteName);
diff --git a/src/features/game-modes/metronome/metronome-practice-coordinator.js b/src/features/game-modes/metronome/metronome-practice-coordinator.js
index c0850d9..d867dac 100644
--- a/src/features/game-modes/metronome/metronome-practice-coordinator.js
+++ b/src/features/game-modes/metronome/metronome-practice-coordinator.js
@@ -1,5 +1,5 @@
-import {MetronomePracticeInitializer} from "./metronome-practice-initializer.js?v=1.2.6";
-import {MetronomePracticeTimer} from "./metronome-practice-timer.js?v=1.2.6";
+import {MetronomePracticeInitializer} from "./metronome-practice-initializer.js?v=1.3.0";
+import {MetronomePracticeTimer} from "./metronome-practice-timer.js?v=1.3.0";
export class MetronomePracticeCoordinator {
diff --git a/src/features/game-modes/metronome/metronome-practice-initializer.js b/src/features/game-modes/metronome/metronome-practice-initializer.js
index 6d8ff89..25ab18e 100644
--- a/src/features/game-modes/metronome/metronome-practice-initializer.js
+++ b/src/features/game-modes/metronome/metronome-practice-initializer.js
@@ -1,6 +1,6 @@
-import {GameConfigurationManager} from "../../game-core/game-initialization/game-configuration-manager.js?v=1.2.6";
-import {MetronomePracticeTimer} from "./metronome-practice-timer.js?v=1.2.6";
-import {LevelUpVisualizer} from "../../game-core/game-ui/level-up-visualizer.js?v=1.2.6";
+import {GameConfigurationManager} from "../../game-core/game-initialization/game-configuration-manager.js?v=1.3.0";
+import {MetronomePracticeTimer} from "./metronome-practice-timer.js?v=1.3.0";
+import {LevelUpVisualizer} from "../../game-core/game-ui/level-up-visualizer.js?v=1.3.0";
export class MetronomePracticeInitializer {
// Changed in metronome-practice-coordinator
diff --git a/src/features/game-modes/note-in-key/note-in-key-game-coordinator.js b/src/features/game-modes/note-in-key/note-in-key-game-coordinator.js
index 57a7d45..dbfe0d7 100644
--- a/src/features/game-modes/note-in-key/note-in-key-game-coordinator.js
+++ b/src/features/game-modes/note-in-key/note-in-key-game-coordinator.js
@@ -1,5 +1,5 @@
-import {NoteInKeyGameInitializer} from "./note-in-key-game-initializer.js?v=1.2.6";
-import {NoteInKeyGameNoGuitar} from "./note-in-key-game-no-guitar.js?v=1.2.6";
+import {NoteInKeyGameInitializer} from "./note-in-key-game-initializer.js?v=1.3.0";
+import {NoteInKeyGameNoGuitar} from "./note-in-key-game-no-guitar.js?v=1.3.0";
export class NoteInKeyGameCoordinator {
string;
@@ -37,7 +37,8 @@ export class NoteInKeyGameCoordinator {
// Init event listeners that will automatically call displayNotes() when correct note has been played
this.noteDisplayer.beingGame();
- NoteInKeyGameNoGuitar.playNoGuitarNoteInKey();
+ // Start no guitar game if no guitar option is checked
+ NoteInKeyGameNoGuitar.playNoGuitarNoteInKey(this.noteInKeyGenerator.diatonicNotesOnStrings, this.keyString, this.keyNote);
// Start the timer
this.timerInterval = setInterval(() => {
@@ -53,6 +54,9 @@ export class NoteInKeyGameCoordinator {
this.gameIsRunning = false;
// Hide current key and string
document.querySelector('#current-key-and-string').style.display = 'none';
+ if (document.querySelector('#fretboard')) {
+ document.querySelector('#fretboard').style.display = 'none';
+ }
}
destroy() {
diff --git a/src/features/game-modes/note-in-key/note-in-key-game-initializer.js b/src/features/game-modes/note-in-key/note-in-key-game-initializer.js
index 15ae3f5..4fc5f09 100644
--- a/src/features/game-modes/note-in-key/note-in-key-game-initializer.js
+++ b/src/features/game-modes/note-in-key/note-in-key-game-initializer.js
@@ -1,14 +1,14 @@
-import {NoteInKeyGameCoordinator} from "./note-in-key-game-coordinator.js?v=1.2.6";
-import {LevelUpVisualizer} from "../../game-core/game-ui/level-up-visualizer.js?v=1.2.6";
-import {GameConfigurationManager} from "../../game-core/game-initialization/game-configuration-manager.js?v=1.2.6";
-import {GameProgressVisualizer} from "../../game-core/game-progress/game-progress-visualizer.js?v=1.2.6";
-import {NoteInKeyGenerator} from "./note-in-key-generator.js?v=1.2.6";
-import {PracticeNoteDisplayer} from "../../practice-note-combination/practice-note-displayer.js?v=1.2.6";
-import {NoteInKeyGameNoGuitar} from "./note-in-key-game-no-guitar.js?v=1.2.6";
+import {NoteInKeyGameCoordinator} from "./note-in-key-game-coordinator.js?v=1.3.0";
+import {LevelUpVisualizer} from "../../game-core/game-ui/level-up-visualizer.js?v=1.3.0";
+import {GameConfigurationManager} from "../../game-core/game-initialization/game-configuration-manager.js?v=1.3.0";
+import {GameProgressVisualizer} from "../../game-core/game-progress/game-progress-visualizer.js?v=1.3.0";
+import {NoteInKeyGenerator} from "./note-in-key-generator.js?v=1.3.0";
+import {PracticeNoteDisplayer} from "../../practice-note-combination/practice-note-displayer.js?v=1.3.0";
+import {NoteInKeyGameNoGuitar} from "./note-in-key-game-no-guitar.js?v=1.3.0";
export class NoteInKeyGameInitializer {
-
- possibleKeysOnStrings = {
+ // Possible keys
+ availableNotesOnStrings = {
// String name: [possible keys for string]
'E': ['E', 'F', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B', 'C'],
'A': ['A', 'A♯', 'B', 'C', 'C♯', 'D', 'D♯', 'E', 'F'],
@@ -17,7 +17,7 @@ export class NoteInKeyGameInitializer {
'B': ['B', 'C', 'C♯', 'D', 'D♯', 'E', 'F', 'F♯', 'G'],
'E2': ['E', 'F', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B', 'C'],
};
- possibleKeysOnStringsFullFretboard = {
+ availableNotesOnStringsFullFretboard = {
// String name: [possible keys for string]
'E': ['E', 'F', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B', 'C', 'C♯', 'D', 'D♯'],
'A': ['A', 'A♯', 'B', 'C', 'C♯', 'D', 'D♯', 'E', 'F', 'F♯', 'G', 'G♯'],
@@ -54,7 +54,7 @@ export class NoteInKeyGameInitializer {
// Note in key generator initialized here in case the user clicks "pause" and wants to continue the game
this.noteInKeyGameCoordinator.noteInKeyGenerator = new NoteInKeyGenerator();
- this.setPossibleKeysOnStrings();
+ this.setAvailableNotesOnStrings();
// Instantiate object with note displayer function that will be called when a new note should be displayed
// after a correct one has been played.
@@ -68,10 +68,8 @@ export class NoteInKeyGameInitializer {
document.addEventListener('leveled-up', this.levelUpEventHandler);
// Init no guitar game option
- if (document.querySelector('#no-guitar-option input')?.checked) {
- // Add no-guitar classname to game-container
- document.querySelector('#game-container').classList.add('no-guitar');
- NoteInKeyGameNoGuitar.initNoGuitarGameOption();
+ if (document.querySelector('#no-guitar-option input')) {
+ NoteInKeyGameNoGuitar.initNoGuitarGameOption(this.noteInKeyGameCoordinator);
}
}
@@ -80,7 +78,7 @@ export class NoteInKeyGameInitializer {
const stringOptions = document.querySelectorAll('#note-in-key-game-strings-div input');
stringOptions.forEach((stringOption) => {
stringOption.addEventListener('change', () => {
- this.setPossibleKeysOnStrings();
+ this.setAvailableNotesOnStrings();
this.reloadKeyAndStringEventHandler();
});
});
@@ -154,14 +152,14 @@ export class NoteInKeyGameInitializer {
document.dispatchEvent(new Event('game-start'));
}
- setPossibleKeysOnStrings() {
+ setAvailableNotesOnStrings() {
let notesOnStrings;
if (document.querySelector('#note-in-key-entire-fretboard-option input')?.checked) {
// Using the spread operator to create a copy of this.possibleKeysOnStrings otherwise it would
// be a reference, and the original object would be modified
- notesOnStrings = {...this.possibleKeysOnStringsFullFretboard};
+ notesOnStrings = {...this.availableNotesOnStringsFullFretboard};
} else {
- notesOnStrings = {...this.possibleKeysOnStrings};
+ notesOnStrings = {...this.availableNotesOnStrings};
}
// Remove strings that were not selected from notesOnStrings
const strings = document.querySelectorAll('#note-in-key-game-strings-div input');
@@ -175,7 +173,9 @@ export class NoteInKeyGameInitializer {
});
console.debug('Possible keys on strings', notesOnStrings);
- this.noteInKeyGameCoordinator.noteInKeyGenerator.possibleStringsAndKeys = notesOnStrings;
+ this.noteInKeyGameCoordinator.noteInKeyGenerator.availableNotesOnStrings = notesOnStrings;
+ NoteInKeyGameNoGuitar.availableNotesOnStrings = notesOnStrings;
+
}
/**
@@ -243,7 +243,7 @@ export class NoteInKeyGameInitializer {
// Add note in key entire fretboard option event listener
document.querySelector('#note-in-key-entire-fretboard-option input')
.addEventListener('change', () => {
- this.setPossibleKeysOnStrings();
+ this.setAvailableNotesOnStrings();
this.reloadKeyAndStringEventHandler();
});
@@ -252,6 +252,7 @@ export class NoteInKeyGameInitializer {
// Has to be added before key and string are reloaded as they depend on this div existence
+ // Add current-key-and-string if it doesn't already exist
document.querySelector('#game-progress-div').insertAdjacentHTML('afterend',
``);
diff --git a/src/features/game-modes/note-in-key/note-in-key-game-no-guitar.js b/src/features/game-modes/note-in-key/note-in-key-game-no-guitar.js
index eda7d63..0c23df7 100644
--- a/src/features/game-modes/note-in-key/note-in-key-game-no-guitar.js
+++ b/src/features/game-modes/note-in-key/note-in-key-game-no-guitar.js
@@ -1,22 +1,44 @@
-import {GameProgressVisualizer} from "../../game-core/game-progress/game-progress-visualizer.js?v=1.2.6";
+import {GameProgressVisualizer} from "../../game-core/game-progress/game-progress-visualizer.js?v=1.3.0";
export class NoteInKeyGameNoGuitar {
- static initNoGuitarGameOption() {
+ static diatonicNotesOnStrings;
+ static availableNotesOnStrings;
+
+ static initNoGuitarGameOption(noteInKeyGameCoordinator) {
document.querySelector('#no-guitar-option input').addEventListener('click', () => {
console.log('no guitar option changed');
+
document.dispatchEvent(new Event('game-stop'));
GameProgressVisualizer.resetProgress();
+ noteInKeyGameCoordinator.reloadKeyAndString();
+
+ if (document.querySelector('#no-guitar-option input').checked) {
+ // Add no-guitar classname to game-container
+ document.querySelector('#game-container').classList.add('no-guitar');
+ } else {
+ this.destroyNoGuitarGameOption();
+ }
});
}
static destroyNoGuitarGameOption() {
document.querySelector('#game-container').classList.remove('no-guitar');
// By removing the fretboard, the event listeners are also removed
- document.querySelector('#fretboard').remove();
+ document.querySelector('#fretboard')?.remove();
}
- static playNoGuitarNoteInKey() {
+ static playNoGuitarNoteInKey(diatonicNotesOnStrings, keyString, keyNote) {
+ this.diatonicNotesOnStrings = diatonicNotesOnStrings;
+ this.keyString = keyString;
+ this.keyNote = keyNote;
+
if (document.querySelector('#no-guitar-option input')?.checked) {
+
+ // If the fretboard already exists, remove it before adding it again in case the string options changed
+ if (document.querySelector('#fretboard')) {
+ this.destroyNoGuitarGameOption();
+ }
+
// Add no-guitar classname to game-container
document.querySelector('#game-container').classList.add('no-guitar');
this.addVirtualFretboard();
@@ -28,34 +50,113 @@ export class NoteInKeyGameNoGuitar {
static addVirtualFretboard() {
document.querySelector('#game-container').insertAdjacentHTML('beforeend', ``);
const fretboard = document.querySelector('#fretboard');
- let numberOfStrings = 6;
- let numberOfFrets = 12;
-
- for (let i = 1; i <= numberOfStrings; i++) {
+ /**
+ * diatonicNotesOnStrings looks like this.
+ * Object is for e.g. {noteName: "G", number: 3}:
+ *
+ * E = Array(3) [{noteName: "G", number: 3}, Object, Object]
+ * A = Array(3) [Object, Object, Object]
+ * D = Array(3) [Object, Object, Object]
+ * G = Array(3) [Object, Object, Object]
+ * B = Array(3) [Object, Object, Object]
+ * E2 = Array(3) [Object, Object, Object]
+ */
+ let stringIndex = 0;
+ // Construct fretboard with available notes on strings
+ for (const [stringName, notes] of Object.entries(this.availableNotesOnStrings)) {
let string = document.createElement('div');
string.className = 'string';
- string.id = 'string-' + i;
+ string.dataset.stringName = stringName;
+
+ // Create a new div for the string name
+ let stringNameDiv = document.createElement('div');
+ let stringNameSpan = document.createElement('span');
+ stringNameDiv.className = 'string-name';
+ // Set the text content to the string name
+ stringNameSpan.textContent = stringName;
+ // Set the noteName data attribute to the first note of the string
+ stringNameSpan.dataset.noteName = stringName;
+ // Append the string name div to the string div
+ stringNameDiv.appendChild(stringNameSpan);
+ string.appendChild(stringNameDiv);
- for (let j = 1; j <= numberOfFrets; j++) {
+ // Reverse the note array to so that the fretboard starts on the right side
+ let reversedNotes = [...notes].reverse();
+ // Remove the last note from the reversed array copy as it's the string name
+ reversedNotes.pop();
+
+ // Store the total number of frets on the string to place indicator helpers
+ let totalFrets = reversedNotes.length;
+
+ for (const index in reversedNotes) {
let fret = document.createElement('div');
fret.className = 'fret';
- fret.id = 'fret-' + i + '-' + j;
+ fret.dataset.noteName = reversedNotes[index];
string.appendChild(fret);
+
+ // Highlight key note
+ if (reversedNotes[index] === this.keyNote && stringName === this.keyString) {
+ let keyNoteIndicator = document.createElement('span');
+ keyNoteIndicator.className = 'key-note-indicator';
+ fret.appendChild(keyNoteIndicator);
+ }
+
+ // If the fret index is 3, 5, 7, or 9 and the string is the first string, add a circle to the fret
+ // Calculate the fret number from the right
+ let fretNumberFromRight = totalFrets - parseInt(index);
+ // If the fret number from the right is 3, 5, 7, or 9 and the string is the first string, add a circle to the fret
+ if ([3, 5, 7, 9].includes(fretNumberFromRight) && stringIndex === 0) {
+ let fretHelper = document.createElement('span');
+ fretHelper.className = 'fret-helper';
+ fret.appendChild(fretHelper);
+ }
+ }
+
+ // If note number 1 is the open string, color the string letter to green
+ if (stringName === this.keyString && this.keyNote === stringName) {
+ stringNameSpan.style.color = 'green';
}
let hr = document.createElement('hr');
string.appendChild(hr);
-
fretboard.appendChild(string);
- }
+ stringIndex++;
+ }
}
static addEventListenersToVirtualFretboard() {
+ // Add event listeners to the frets
document.querySelectorAll('.fret').forEach(fret => {
- fret.addEventListener('click', function () {
- console.log('Fret clicked', fret.id);
- });
+ fret.addEventListener('click', this.noteClickedEventHandler);
});
+ // Add event listeners to the strings
+ document.querySelectorAll('.string-name').forEach(string => {
+ string.addEventListener('click', this.noteClickedEventHandler);
+ });
+ }
+
+ static wrongColorTimeout;
+
+ static noteClickedEventHandler(event) {
+ // Clear the wrong color timeout
+ clearTimeout(this.wrongColorTimeout);
+
+ // If fret indicator helper is clicked, get the note name from the parent fret
+ const noteName = event.target.dataset.noteName ?? event.target.closest('.fret').dataset.noteName;
+ const stringName = event.target.closest('.string').dataset.stringName;
+ // Output note and string name to console
+ console.log(`Note ${noteName} on string ${stringName} clicked`);
+ // Check if the pressed note was correct
+ if (document.querySelector('#note-span').dataset.noteName === noteName
+ && document.querySelector('#string-span').textContent === stringName) {
+ document.dispatchEvent(new Event('correct-note-played'));
+ } else {
+ // Color note-span orange for 700ms before reverting to default
+ document.querySelector('#note-span').style.color = '#a96f00';
+ this.wrongColorTimeout = setTimeout(() => {
+ document.querySelector('#note-span').style.color = null;
+ }, 2000);
+ }
}
}
\ No newline at end of file
diff --git a/src/features/game-modes/note-in-key/note-in-key-generator.js b/src/features/game-modes/note-in-key/note-in-key-generator.js
index aac6a90..834e190 100644
--- a/src/features/game-modes/note-in-key/note-in-key-generator.js
+++ b/src/features/game-modes/note-in-key/note-in-key-generator.js
@@ -1,8 +1,8 @@
-import {ArrayShuffler} from "../../shuffler/array-shuffler.js?v=1.2.6";
+import {ArrayShuffler} from "../../shuffler/array-shuffler.js?v=1.3.0";
export class NoteInKeyGenerator {
- notesOnStrings;
- possibleStringsAndKeys;
+ diatonicNotesOnStrings;
+ availableNotesOnStrings;
combinationsToBeShuffled = [];
shuffledCombinations;
// Index of the current combination to be displayed from the shuffledCombinations array
@@ -15,11 +15,11 @@ export class NoteInKeyGenerator {
* Return random string and random key from that string
*/
getNewStringAndKey() {
- console.log(`All available strings and notes`, this.possibleStringsAndKeys);
- const strings = Object.keys(this.possibleStringsAndKeys);
+ console.debug(`All available strings and notes`, this.availableNotesOnStrings);
+ const strings = Object.keys(this.availableNotesOnStrings);
this.string = strings[Math.floor(Math.random() * strings.length)];
// Keys for given string
- const keys = this.possibleStringsAndKeys[this.string];
+ const keys = this.availableNotesOnStrings[this.string];
// Get random key from possible keys for string
this.key = keys[Math.floor(Math.random() * keys.length)];
return {keyString: this.string, keyNote: this.key};
@@ -33,8 +33,8 @@ export class NoteInKeyGenerator {
*/
loadShuffledCombinations(keyString, keyNote) {
// Convert the range of possibleKeysOnStrings to the diatonic scale of the given keyNote
- let diatonicNotesOnStrings = this.getPossibleStringsAndKeysInDiatonicScale(
- keyNote, this.possibleStringsAndKeys
+ let diatonicNotesOnStrings = this.getAvailableNotesOnStringsInDiatonicScale(
+ keyNote, this.availableNotesOnStrings
);
// const keyIndex = this.possibleKeysOnStrings[keyString].indexOf(keyNote);
@@ -46,7 +46,7 @@ export class NoteInKeyGenerator {
console.debug(`Diatonic notes`, diatonicNotesOnStrings);
// Remove notes that are not nearby the key note, according to the difficulty level
- this.notesOnStrings = this.removeNotesAccordingToDifficultyLevel(diatonicNotesOnStrings, keyIndex, difficulty);
+ this.diatonicNotesOnStrings = this.removeNotesAccordingToDifficultyLevel(diatonicNotesOnStrings, keyIndex, difficulty);
// Fill the combinationsToBeShuffled array with all possible combinations
this.createArrayWithCombinationsToBeShuffled();
@@ -61,11 +61,11 @@ export class NoteInKeyGenerator {
createArrayWithCombinationsToBeShuffled() {
this.combinationsToBeShuffled = [];
// Shuffle the notes on each string
- for (let string in this.notesOnStrings) {
+ for (let string in this.diatonicNotesOnStrings) {
// Fretboard game mote shuffler cannot be taken as it shuffles creates combinations with all strings with
// every note.
// We want combinations with only specific notes going with each string.
- this.combinationsToBeShuffled.push(...this.notesOnStrings[string].map(noteObject => [string, noteObject.noteName]));
+ this.combinationsToBeShuffled.push(...this.diatonicNotesOnStrings[string].map(noteObject => [string, noteObject.noteName]));
}
console.debug('Combinations to be shuffled', this.combinationsToBeShuffled);
}
@@ -95,21 +95,21 @@ export class NoteInKeyGenerator {
// Split the string into an array containing the string and the note
// let [string, note] = combination.split('|');
// Get the note number from the note object
- let noteNumber = this.notesOnStrings[string].find(noteObject => noteObject.noteName === note).number;
+ let noteNumber = this.diatonicNotesOnStrings[string].find(noteObject => noteObject.noteName === note).number;
return {stringName: string, noteName: {noteName: note, number: noteNumber}};
- const strings = Object.keys(this.notesOnStrings);
+ const strings = Object.keys(this.diatonicNotesOnStrings);
const stringToPlayNote = strings[Math.floor(Math.random() * strings.length)];
// Available note numbers
- const notes = this.notesOnStrings[stringToPlayNote];
+ const notes = this.diatonicNotesOnStrings[stringToPlayNote];
// Get the number of the object chosen by randomness
const noteNameAndNumber = notes[Math.floor(Math.random() * notes.length)];
return {stringName: stringToPlayNote, noteName: noteNameAndNumber};
}
- getPossibleStringsAndKeysInDiatonicScale(keyNote, possibleKeysOnStrings) {
+ getAvailableNotesOnStringsInDiatonicScale(keyNote, possibleKeysOnStrings) {
let diatonicScale = this.generateDiatonicScale(keyNote);
let diatonicNotesOnStrings = [];
// For each string, filter-out notes that should not be playable
@@ -133,20 +133,21 @@ export class NoteInKeyGenerator {
* @return {*[]}
*/
removeNotesAccordingToDifficultyLevel(diatonicNotesOnStrings, keyIndex, difficulty) {
- let possibleNotesOnStrings = [];
+ let strippedDiatonicNotes = [];
// Remove notes that are hard to reach, according to the difficulty level,
// Calculate the start and end indices for the slice method
let start = Math.max(0, keyIndex - difficulty);
let end = keyIndex + difficulty;
- console.log(`Key index ${keyIndex} Start ${start} End ${end}`);
+ console.debug(`Key index: ${keyIndex}; Start: ${start}; End ${end}`);
+ // console.log()
for (let string in diatonicNotesOnStrings) {
// Use the slice method to get the nearby notes +1 because the end index is not included in the slice
- possibleNotesOnStrings[string] = diatonicNotesOnStrings[string].slice(start, end + 1);
+ strippedDiatonicNotes[string] = diatonicNotesOnStrings[string].slice(start, end + 1);
}
- console.debug(`Notes after removal. Difficulty ${difficulty}`, possibleNotesOnStrings);
- this.notesOnStrings = possibleNotesOnStrings;
- return possibleNotesOnStrings;
+ console.debug(`Notes after removal. Difficulty ${difficulty}`, strippedDiatonicNotes);
+ this.diatonicNotesOnStrings = strippedDiatonicNotes;
+ return strippedDiatonicNotes;
}
/**
diff --git a/src/features/game-modes/note-in-key/practice-progress-updater.js b/src/features/game-modes/note-in-key/practice-progress-updater.js
index 368c439..6428441 100644
--- a/src/features/game-modes/note-in-key/practice-progress-updater.js
+++ b/src/features/game-modes/note-in-key/practice-progress-updater.js
@@ -1,4 +1,4 @@
-import {GameProgressVisualizer} from "./game-progress-visualizer.js?v=1.2.6";
+import {GameProgressVisualizer} from "./game-progress-visualizer.js?v=1.3.0";
export class GameProgressUpdater {
diff --git a/src/features/game-modes/note-on-fretboard/fretboard-note-game-combination-generator.js b/src/features/game-modes/note-on-fretboard/fretboard-note-game-combination-generator.js
index 84d9dc8..dedd1be 100644
--- a/src/features/game-modes/note-on-fretboard/fretboard-note-game-combination-generator.js
+++ b/src/features/game-modes/note-on-fretboard/fretboard-note-game-combination-generator.js
@@ -1,5 +1,5 @@
-import {NoteShuffler} from "../../shuffler/note-shuffler.js?v=1.2.6";
-import {NoteCombinationVisualizer} from "../../game-core/game-ui/note-combination-visualizer.js?v=1.2.6";
+import {NoteShuffler} from "../../shuffler/note-shuffler.js?v=1.3.0";
+import {NoteCombinationVisualizer} from "../../game-core/game-ui/note-combination-visualizer.js?v=1.3.0";
export class FretboardNoteGameCombinationGenerator {
constructor(strings, notes) {
diff --git a/src/features/game-modes/note-on-fretboard/fretboard-note-game-coordinator.js b/src/features/game-modes/note-on-fretboard/fretboard-note-game-coordinator.js
index cc14b70..d01e771 100644
--- a/src/features/game-modes/note-on-fretboard/fretboard-note-game-coordinator.js
+++ b/src/features/game-modes/note-on-fretboard/fretboard-note-game-coordinator.js
@@ -1,10 +1,10 @@
// const notes = ['C', 'C♯', 'D', 'D♯', 'E', 'F', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B'];
// const strings = ['D', 'E', 'G', 'A', 'B'];
-import {GameNoteDisplayer} from "../../game-note-combination/game-note-displayer.js?v=1.2.6";
-import {FretboardGameChallengingNotesProvider} from "./fretboard-game-challenging-notes-provider.js?v=1.2.6";
-import {FretboardNoteGameCombinationGenerator} from "./fretboard-note-game-combination-generator.js?v=1.2.6";
-import {FretboardNoteGameInitializer} from "./fretboard-note-game-initializer.js?v=1.2.6";
+import {GameNoteDisplayer} from "../../game-note-combination/game-note-displayer.js?v=1.3.0";
+import {FretboardGameChallengingNotesProvider} from "./fretboard-game-challenging-notes-provider.js?v=1.3.0";
+import {FretboardNoteGameCombinationGenerator} from "./fretboard-note-game-combination-generator.js?v=1.3.0";
+import {FretboardNoteGameInitializer} from "./fretboard-note-game-initializer.js?v=1.3.0";
/**
* Game mode "note-on-fretboard" core logic
diff --git a/src/features/game-modes/note-on-fretboard/fretboard-note-game-initializer.js b/src/features/game-modes/note-on-fretboard/fretboard-note-game-initializer.js
index 88fbc3c..717e381 100644
--- a/src/features/game-modes/note-on-fretboard/fretboard-note-game-initializer.js
+++ b/src/features/game-modes/note-on-fretboard/fretboard-note-game-initializer.js
@@ -1,7 +1,7 @@
-import {GameLevelTracker} from "../../game-core/game-progress/game-level-tracker.js?v=1.2.6";
-import {GameElementsVisualizer} from "../../game-core/game-ui/game-elements-visualizer.js?v=1.2.6";
-import {LevelUpVisualizer} from "../../game-core/game-ui/level-up-visualizer.js?v=1.2.6";
-import {GameConfigurationManager} from "../../game-core/game-initialization/game-configuration-manager.js?v=1.2.6";
+import {GameLevelTracker} from "../../game-core/game-progress/game-level-tracker.js?v=1.3.0";
+import {GameElementsVisualizer} from "../../game-core/game-ui/game-elements-visualizer.js?v=1.3.0";
+import {LevelUpVisualizer} from "../../game-core/game-ui/level-up-visualizer.js?v=1.3.0";
+import {GameConfigurationManager} from "../../game-core/game-initialization/game-configuration-manager.js?v=1.3.0";
export class FretboardNoteGameInitializer {
constructor() {
diff --git a/src/features/game-note-combination/game-note-displayer.js b/src/features/game-note-combination/game-note-displayer.js
index b8c3642..6f477db 100644
--- a/src/features/game-note-combination/game-note-displayer.js
+++ b/src/features/game-note-combination/game-note-displayer.js
@@ -1,7 +1,7 @@
-import {GameProgressUpdater} from "../game-core/game-progress/game-progress-updater.js?v=1.2.6";
-import {DetectedNoteVerifier} from "../detected-note/detected-note-verifier.js?v=1.2.6";
-import {NoteCombinationVisualizer} from "../game-core/game-ui/note-combination-visualizer.js?v=1.2.6";
-import {GameProgressVisualizer} from "../game-core/game-progress/game-progress-visualizer.js?v=1.2.6";
+import {GameProgressUpdater} from "../game-core/game-progress/game-progress-updater.js?v=1.3.0";
+import {DetectedNoteVerifier} from "../detected-note/detected-note-verifier.js?v=1.3.0";
+import {NoteCombinationVisualizer} from "../game-core/game-ui/note-combination-visualizer.js?v=1.3.0";
+import {GameProgressVisualizer} from "../game-core/game-progress/game-progress-visualizer.js?v=1.3.0";
/**
* Note display coordinator when playing the "game" which
@@ -98,7 +98,7 @@ export class GameNoteDisplayer {
}
// Display next note and string and if with treble clef
- NoteCombinationVisualizer.displayCombination(stringName, noteNumber ?? noteName,
+ NoteCombinationVisualizer.displayCombinationWithNoteName(stringName, noteNumber ?? noteName,
document.querySelector('#fretboard-note-game-treble-clef input').checked,
document.querySelector('#fretboard-note-game-treble-clef-and-name input').checked
);
diff --git a/src/features/practice-note-combination/practice-note-displayer.js b/src/features/practice-note-combination/practice-note-displayer.js
index 044415e..f91a21f 100644
--- a/src/features/practice-note-combination/practice-note-displayer.js
+++ b/src/features/practice-note-combination/practice-note-displayer.js
@@ -1,6 +1,6 @@
-import {DetectedNoteVerifier} from "../detected-note/detected-note-verifier.js?v=1.2.6";
-import {NoteCombinationVisualizer} from "../game-core/game-ui/note-combination-visualizer.js?v=1.2.6";
-import {GameProgressVisualizer} from "../game-core/game-progress/game-progress-visualizer.js?v=1.2.6";
+import {DetectedNoteVerifier} from "../detected-note/detected-note-verifier.js?v=1.3.0";
+import {NoteCombinationVisualizer} from "../game-core/game-ui/note-combination-visualizer.js?v=1.3.0";
+import {GameProgressVisualizer} from "../game-core/game-progress/game-progress-visualizer.js?v=1.3.0";
/**
* Note displayer for "practice" mode, which means
@@ -76,7 +76,7 @@ export class PracticeNoteDisplayer {
noteName = noteName.noteName;
}
// Display next note and string
- NoteCombinationVisualizer.displayCombination(stringName, noteNumber ?? noteName);
+ NoteCombinationVisualizer.displayCombinationWithNoteNumber(stringName, noteNumber ?? noteName, noteName);
// console.debug(`Displaying combination ${stringName}|${noteName}`);
this.detectedNoteVerifier.noteToPlay = noteName;
};
@@ -87,6 +87,8 @@ export class PracticeNoteDisplayer {
if (firstCall) {
displayNoteCombination();
} else {
+ // Color spans and detected note in green when correct
+ document.querySelector('#note-span').style.color = 'green';
setTimeout(() => {
displayNoteCombination();
}, 700);