Skip to content

Commit

Permalink
Added virtual fretboard no guitar option [SG-122]
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelgfeller committed Feb 8, 2024
1 parent e958d6d commit 2674d57
Show file tree
Hide file tree
Showing 24 changed files with 334 additions and 158 deletions.
3 changes: 2 additions & 1 deletion index.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<?php

$version = '1.2.6';
$version = '1.3.0';

// If config/env.php exists, contains the 'env' key, and it's set to 'dev' add version to js imports
if (file_exists(__DIR__ . '/config/env.php')) {
$config = require __DIR__ . '/config/env.php';
if (array_key_exists('env', $config) && $config['env'] === 'dev') {
// $version = time();
require __DIR__ . '/JsImportVersionAdder.php';
(new JsImportVersionAdder())->addVersionToJsImports($version);
}
Expand Down
55 changes: 52 additions & 3 deletions src/assets/styles/virtual-fretboard.css
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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 {
Expand All @@ -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%;
}
}
4 changes: 2 additions & 2 deletions src/features/detected-note/detected-note-verifier.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {

Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {

Expand Down
16 changes: 12 additions & 4 deletions src/features/game-core/game-initialization/game-initializer.js
Original file line number Diff line number Diff line change
@@ -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() {
Expand All @@ -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();
});
}
Expand All @@ -44,7 +51,8 @@ export class GameInitializer {
// Check if the target is <body> or if a parent of the target is <main> (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();
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/features/game-core/game-loader.js
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
35 changes: 28 additions & 7 deletions src/features/game-core/game-start/core-game-coordinator.js
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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));
Expand All @@ -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) {
Expand Down Expand Up @@ -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();
}
}
2 changes: 1 addition & 1 deletion src/features/game-core/game-ui/game-elements-visualizer.js
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down
11 changes: 9 additions & 2 deletions src/features/game-core/game-ui/note-combination-visualizer.js
Original file line number Diff line number Diff line change
@@ -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 {

Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading

0 comments on commit 2674d57

Please sign in to comment.