mirror of
https://framagit.org/JonathanMM/sutom.git
synced 2024-06-10 09:52:13 +02:00
Close #9 : Ajout des sons dans le jeu
This commit is contained in:
parent
1802f87f9f
commit
0c44ca57a0
|
@ -10,7 +10,17 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="contenu">
|
||||
<h1>SUTOM</h1>
|
||||
<header>
|
||||
<div></div>
|
||||
<h1>SUTOM</h1>
|
||||
<div>
|
||||
<a href="#" id="configuration-audio-bouton">
|
||||
<svg id="configuration-audio-icone">
|
||||
<use href="#icone-son-active" fill="var(--couleur-icone)"></use>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
<div id="notification"> </div>
|
||||
<div id="fin-de-partie-panel">
|
||||
<div id="victoire-panel">
|
||||
|
@ -79,6 +89,56 @@
|
|||
Merci à Emmanuel pour l'aide sur le dictionnaire.
|
||||
</p>
|
||||
</div>
|
||||
<div style="display: hidden">
|
||||
<audio preload src="sons/lettre-non-trouve.wav" id="son-lettre-non-trouve"></audio>
|
||||
<audio preload src="sons/lettre-mal-place.wav" id="son-lettre-mal-place"></audio>
|
||||
<audio preload src="sons/lettre-bien-place.wav" id="son-lettre-bien-place"></audio>
|
||||
|
||||
<svg>
|
||||
<symbol id="icone-son-active" width="36.471008" height="31.999998" viewBox="0 0 36.471009 31.999998">
|
||||
<path
|
||||
d="M 12.341228,3.8810322 7.0667848,7.7592153 v 8.2407827 8.237934 l 1.7467496,1.285129 c 0.9574354,0.703829 3.3310776,2.450578 5.2744426,3.881032 1.940517,1.427605 3.539092,2.595904 3.553339,2.595904 0.01425,0 0.02565,-6.813179 0.02565,-15.999999 0,-9.3292955 -0.0114,-15.9999984 -0.02565,-15.9999984 -0.01425,0 -2.399287,1.7467496 -5.300088,3.8810326 z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
<path
|
||||
d="m 29.814423,1.835084 c -0.390383,0.128228 -0.612645,0.4359751 -0.615494,0.843455 0,0.2934995 0.06839,0.4274265 0.40748,0.7836153 0.92894,0.9830809 1.541585,1.7439001 2.174176,2.7070344 1.518789,2.3109527 2.453428,4.8783613 2.795369,7.6651823 0.09403,0.757969 0.11683,1.165449 0.11683,2.165627 0,1.855031 -0.202315,3.308281 -0.69813,5.029385 -0.806411,2.798219 -2.26536,5.288691 -4.396794,7.514158 -0.333392,0.35049 -0.398931,0.473019 -0.398931,0.777916 0,0.262155 0.09118,0.481568 0.270703,0.64114 0.185219,0.170971 0.341942,0.227961 0.606946,0.225112 0.327694,-0.0029 0.421728,-0.05699 0.852004,-0.490116 2.481923,-2.527516 4.282813,-5.847195 5.060729,-9.332145 C 36.835616,16.5699 36.562063,12.603382 35.205696,9.0186987 34.288154,6.5994648 32.948884,4.4594827 31.136596,2.5161169 30.717718,2.0658944 30.566694,1.9319674 30.390024,1.8550306 30.264646,1.8008899 29.954049,1.7894919 29.814423,1.835084 Z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
<path
|
||||
d="m 25.072838,6.5624211 c -0.381834,0.1424755 -0.601246,0.4445236 -0.604096,0.8320569 -0.0057,0.2991986 0.07694,0.4502226 0.46447,0.8605521 1.672663,1.7638469 2.695637,3.9408719 3.011933,6.4056989 0.07979,0.621193 0.07124,2.142831 -0.01425,2.766874 -0.339092,2.461976 -1.330721,4.547818 -3.011932,6.331611 -0.373286,0.396082 -0.453072,0.549955 -0.453072,0.846304 0.0057,0.692431 0.769368,1.097062 1.356367,0.720926 0.156723,-0.09688 0.732324,-0.718076 1.125556,-1.211041 1.413357,-1.769546 2.365093,-3.940873 2.687088,-6.149243 0.11398,-0.775067 0.128228,-0.991629 0.128228,-1.966162 0,-0.974532 -0.01425,-1.191095 -0.128228,-1.966162 C 29.3699,12.224397 28.697415,10.460551 27.677291,8.8961698 27.039,7.9187879 26.038822,6.7504888 25.716828,6.6080133 c -0.17667,-0.076937 -0.495815,-0.099733 -0.64399,-0.045592 z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
<path
|
||||
d="M 0,15.999998 V 24.24933 L 2.5018698,24.24363 5.00089,24.23513 V 15.999998 7.7649144 L 2.5018698,7.7563658 0,7.7506668 Z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
<path
|
||||
d="m 20.373996,11.28121 c -0.515761,0.159572 -0.783615,0.726625 -0.564202,1.202493 0.04274,0.09688 0.165271,0.262155 0.307747,0.413179 0.789314,0.854853 1.202493,1.923419 1.202493,3.103116 0,1.219591 -0.421728,2.27106 -1.265183,3.168655 -0.22796,0.242209 -0.319145,0.447373 -0.319145,0.712378 0.0028,0.46447 0.35049,0.826358 0.823509,0.857702 0.387533,0.0228 0.626892,-0.133927 1.119857,-0.740872 1.270882,-1.564381 1.715405,-3.644524 1.202493,-5.624933 -0.265004,-1.028673 -0.837756,-2.0374 -1.581478,-2.79252 -0.153873,-0.156723 -0.236509,-0.216563 -0.364737,-0.265004 -0.168121,-0.05984 -0.418878,-0.07694 -0.561354,-0.03419 z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="icone-son-desactive" width="33.355648" height="31.999998" viewBox="0 0 33.355647 31.999997">
|
||||
<g transform="translate(10.205845,-122.61621)">
|
||||
<path
|
||||
style="stroke-linecap: round"
|
||||
d="m 12.986328,132.82227 a 1.42465,1.42465 0 0 0 -1.007812,0.41796 1.42465,1.42465 0 0 0 0,2.01368 l 8.740234,8.73828 a 1.42465,1.42465 0 0 0 2.013672,0 1.42465,1.42465 0 0 0 0,-2.01367 l -8.738281,-8.73829 a 1.42465,1.42465 0 0 0 -1.007813,-0.41796 z"
|
||||
/>
|
||||
<path
|
||||
style="stroke-linecap: round"
|
||||
d="m 21.724609,132.82227 a 1.42465,1.42465 0 0 0 -1.005859,0.41796 l -8.740234,8.73829 a 1.42465,1.42465 0 0 0 0,2.01367 1.42465,1.42465 0 0 0 2.015625,0 l 8.738281,-8.73828 a 1.42465,1.42465 0 0 0 0,-2.01368 1.42465,1.42465 0 0 0 -1.007813,-0.41796 z"
|
||||
/>
|
||||
<path
|
||||
d="m 2.1353828,126.49724 -5.274443,3.87818 v 8.24079 8.23793 l 1.7467496,1.28513 c 0.95743539,0.70383 3.3310772,2.45058 5.274443,3.88103 1.9405163,1.42761 3.5390915,2.5959 3.553339,2.5959 0.014248,0 0.025646,-6.81317 0.025646,-15.99999 0,-9.3293 -0.011398,-16 -0.025646,-16 -0.014247,0 -2.3992874,1.74675 -5.3000886,3.88103 z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
<path
|
||||
d="m -10.205845,138.61621 v 8.24933 l 2.5018698,-0.006 2.4990203,-0.009 v -8.23508 -8.23509 l -2.4990203,-0.009 -2.5018698,-0.006 z"
|
||||
style="stroke: none; stroke-width: 0.00284951"
|
||||
/>
|
||||
</g>
|
||||
</symbol>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
requirejs(["main"], function (Main) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
--couleur-mal-place: #ffbd00;
|
||||
--couleur-fond-grille: #0077c7;
|
||||
--couleur-non-trouve: rgb(112, 112, 112);
|
||||
--couleur-icone: rgb(200, 200, 200);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
|
@ -40,11 +41,26 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
header {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 6fr 1fr;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid white;
|
||||
margin-top: 0.1em;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#configuration-audio-icone {
|
||||
height: 32px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
#grille {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
|
BIN
public/sons/lettre-bien-place.wav
Normal file
BIN
public/sons/lettre-bien-place.wav
Normal file
Binary file not shown.
BIN
public/sons/lettre-mal-place.wav
Normal file
BIN
public/sons/lettre-mal-place.wav
Normal file
Binary file not shown.
BIN
public/sons/lettre-non-trouve.wav
Normal file
BIN
public/sons/lettre-non-trouve.wav
Normal file
Binary file not shown.
76
ts/audioPanel.ts
Normal file
76
ts/audioPanel.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
import Configuration from "./configuration";
|
||||
import Sauvegardeur from "./sauvegardeur";
|
||||
|
||||
export default class AudioPanel {
|
||||
private readonly _configAudioBouton: HTMLElement;
|
||||
private readonly _iconeAudio: HTMLElement;
|
||||
|
||||
private readonly _audioLettreBienPlace: HTMLAudioElement;
|
||||
private readonly _audioLettreMalPlace: HTMLAudioElement;
|
||||
private readonly _audioLettreNonTrouve: HTMLAudioElement;
|
||||
|
||||
private _hasAudio: boolean = false;
|
||||
|
||||
public constructor(configuration: Configuration) {
|
||||
this._configAudioBouton = document.getElementById("configuration-audio-bouton") as HTMLElement;
|
||||
this._iconeAudio = document.getElementById("configuration-audio-icone") as HTMLElement;
|
||||
this._audioLettreBienPlace = document.getElementById("son-lettre-bien-place") as HTMLAudioElement;
|
||||
this._audioLettreMalPlace = document.getElementById("son-lettre-mal-place") as HTMLAudioElement;
|
||||
this._audioLettreNonTrouve = document.getElementById("son-lettre-non-trouve") as HTMLAudioElement;
|
||||
|
||||
this.toggleSon(configuration.hasAudio, true);
|
||||
|
||||
this._configAudioBouton.addEventListener(
|
||||
"click",
|
||||
((event: MouseEvent) => {
|
||||
event.stopPropagation();
|
||||
this.toggleSon(!this._hasAudio);
|
||||
Sauvegardeur.sauvegarderConfig({
|
||||
...(Sauvegardeur.chargerConfig() ?? Configuration.Default),
|
||||
hasAudio: this._hasAudio,
|
||||
});
|
||||
this._configAudioBouton.blur();
|
||||
}).bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
private toggleSon(hasAudio: boolean, chargement: boolean = false): void {
|
||||
this._hasAudio = hasAudio;
|
||||
if (!hasAudio) {
|
||||
this._iconeAudio.innerHTML = '<use href="#icone-son-desactive" fill="var(--couleur-icone)"></use>';
|
||||
} else {
|
||||
this._iconeAudio.innerHTML = '<use href="#icone-son-active" fill="var(--couleur-icone)"></use>';
|
||||
this._audioLettreBienPlace.preload = "auto";
|
||||
if (!chargement) this.jouerSonLettreBienPlace();
|
||||
this._audioLettreMalPlace.preload = "auto";
|
||||
this._audioLettreNonTrouve.preload = "auto";
|
||||
}
|
||||
}
|
||||
|
||||
public jouerSonLettreBienPlace(callback?: () => void): void {
|
||||
this.jouerSon(this._audioLettreBienPlace, callback);
|
||||
}
|
||||
|
||||
public jouerSonLettreMalPlace(callback?: () => void): void {
|
||||
this.jouerSon(this._audioLettreMalPlace, callback);
|
||||
}
|
||||
|
||||
public jouerSonLettreNonTrouve(callback?: () => void): void {
|
||||
this.jouerSon(this._audioLettreNonTrouve, callback);
|
||||
}
|
||||
|
||||
private jouerSon(baliseAudio: HTMLAudioElement, callback?: () => void): void {
|
||||
if (!this._hasAudio) {
|
||||
if (callback) setTimeout(callback, 250);
|
||||
return;
|
||||
}
|
||||
baliseAudio.currentTime = 0;
|
||||
if (callback) baliseAudio.addEventListener("ended", callback, { once: true });
|
||||
baliseAudio.play().catch(
|
||||
(() => {
|
||||
this._hasAudio = false;
|
||||
if (callback) setTimeout(callback, 250);
|
||||
}).bind(this)
|
||||
);
|
||||
}
|
||||
}
|
5
ts/configuration.ts
Normal file
5
ts/configuration.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export default class Configuration {
|
||||
public static Default: Configuration = { hasAudio: false };
|
||||
|
||||
hasAudio: boolean = false;
|
||||
}
|
|
@ -7,12 +7,12 @@ import FinDePartiePanel from "./finDePartiePanel";
|
|||
import NotificationMessage from "./notificationMessage";
|
||||
import SauvegardeStats from "./sauvegardeStats";
|
||||
import Sauvegardeur from "./sauvegardeur";
|
||||
import Configuration from "./configuration";
|
||||
|
||||
export default class Gestionnaire {
|
||||
private readonly _dictionnaire: Dictionnaire;
|
||||
private readonly _grille: Grille;
|
||||
private readonly _input: Input;
|
||||
private readonly _sauvegardeur: Sauvegardeur;
|
||||
private readonly _victoirePanel: FinDePartiePanel;
|
||||
private readonly _propositions: Array<string>;
|
||||
private readonly _resultats: Array<Array<LettreResultat>>;
|
||||
|
@ -22,13 +22,14 @@ export default class Gestionnaire {
|
|||
private _maxNbPropositions: number = 6;
|
||||
private _datePartieEnCours: Date | undefined;
|
||||
private _stats: SauvegardeStats = { partiesJouees: 0, partiesGagnees: 0 };
|
||||
private _config: Configuration = Configuration.Default;
|
||||
|
||||
public constructor() {
|
||||
this._config = Sauvegardeur.chargerConfig() ?? this._config;
|
||||
this._dictionnaire = new Dictionnaire();
|
||||
this._motATrouver = this.choisirMot();
|
||||
this._grille = new Grille(this._motATrouver.length, this._maxNbPropositions, this._motATrouver[0]);
|
||||
this._grille = new Grille(this._motATrouver.length, this._maxNbPropositions, this._motATrouver[0], this._config);
|
||||
this._input = new Input(this, this._motATrouver.length);
|
||||
this._sauvegardeur = new Sauvegardeur();
|
||||
this._victoirePanel = new FinDePartiePanel();
|
||||
this._propositions = new Array<string>();
|
||||
this._resultats = new Array<Array<LettreResultat>>();
|
||||
|
@ -38,14 +39,14 @@ export default class Gestionnaire {
|
|||
}
|
||||
|
||||
private chargerSauvegarde(): void {
|
||||
let sauvegardePartieEnCours = this._sauvegardeur.chargerSauvegardePartieEnCours();
|
||||
let sauvegardePartieEnCours = Sauvegardeur.chargerSauvegardePartieEnCours();
|
||||
if (sauvegardePartieEnCours) {
|
||||
this._datePartieEnCours = sauvegardePartieEnCours.datePartie;
|
||||
for (let mot of sauvegardePartieEnCours.propositions) {
|
||||
this.verifierMot(mot, true);
|
||||
}
|
||||
}
|
||||
this._stats = this._sauvegardeur.chargerSauvegardeStats() ?? { partiesJouees: 0, partiesGagnees: 0 };
|
||||
this._stats = Sauvegardeur.chargerSauvegardeStats() ?? { partiesJouees: 0, partiesGagnees: 0 };
|
||||
}
|
||||
|
||||
private enregistrerPartieDansStats(): void {
|
||||
|
@ -53,13 +54,13 @@ export default class Gestionnaire {
|
|||
if (this._resultats.some((resultat) => resultat.every((item) => item.statut === LettreStatut.BienPlace))) this._stats.partiesGagnees++;
|
||||
this._stats.dernierePartie = this._datePartieEnCours;
|
||||
|
||||
this._sauvegardeur.sauvegarderStats(this._stats);
|
||||
Sauvegardeur.sauvegarderStats(this._stats);
|
||||
}
|
||||
|
||||
private sauvegarderPartieEnCours(): void {
|
||||
let datePartieEnCours = this._datePartieEnCours ?? new Date();
|
||||
|
||||
this._sauvegardeur.sauvegarderPartieEnCours(this._propositions, datePartieEnCours);
|
||||
Sauvegardeur.sauvegarderPartieEnCours(this._propositions, datePartieEnCours);
|
||||
}
|
||||
|
||||
private choisirMot(): string {
|
||||
|
|
15
ts/grille.ts
15
ts/grille.ts
|
@ -1,3 +1,5 @@
|
|||
import AudioPanel from "./audioPanel";
|
||||
import Configuration from "./configuration";
|
||||
import LettreResultat from "./lettreResultat";
|
||||
import { LettreStatut } from "./lettreStatut";
|
||||
|
||||
|
@ -7,12 +9,14 @@ export default class Grille {
|
|||
private readonly _resultats: Array<Array<LettreResultat>>;
|
||||
private readonly _longueurMot: number;
|
||||
private readonly _maxPropositions: number;
|
||||
private readonly _audioPanel: AudioPanel;
|
||||
|
||||
private _indice: Array<string | undefined>;
|
||||
private _motActuel: number;
|
||||
|
||||
public constructor(longueurMot: number, maxPropositions: number, indice: string) {
|
||||
public constructor(longueurMot: number, maxPropositions: number, indice: string, configuration: Configuration) {
|
||||
this._grille = document.getElementById("grille") as HTMLElement;
|
||||
//console.log("Chargement de la grille");
|
||||
this._audioPanel = new AudioPanel(configuration);
|
||||
|
||||
this._longueurMot = longueurMot;
|
||||
this._maxPropositions = maxPropositions;
|
||||
|
@ -119,19 +123,20 @@ export default class Grille {
|
|||
let cellule = td[numLettre];
|
||||
let resultat = resultats[numLettre];
|
||||
cellule.innerHTML = resultat.lettre;
|
||||
let callback = (() => this.animerLettre(td, resultats, numLettre + 1)).bind(this);
|
||||
switch (resultat.statut) {
|
||||
case LettreStatut.BienPlace:
|
||||
cellule.classList.add("bien-place", "resultat");
|
||||
|
||||
this._audioPanel.jouerSonLettreBienPlace(callback);
|
||||
break;
|
||||
case LettreStatut.MalPlace:
|
||||
cellule.classList.add("mal-place", "resultat");
|
||||
|
||||
this._audioPanel.jouerSonLettreMalPlace(callback);
|
||||
break;
|
||||
default:
|
||||
cellule.classList.add("non-trouve", "resultat");
|
||||
this._audioPanel.jouerSonLettreNonTrouve(callback);
|
||||
}
|
||||
setTimeout((() => this.animerLettre(td, resultats, numLettre + 1)).bind(this), 250);
|
||||
}
|
||||
|
||||
private mettreAJourIndice(resultats: Array<LettreResultat>): void {
|
||||
|
|
|
@ -1,31 +1,34 @@
|
|||
import Configuration from "./configuration";
|
||||
import SauvegardePartie from "./sauvegardePartie";
|
||||
import SauvegardeStats from "./sauvegardeStats";
|
||||
|
||||
export default class Sauvegardeur {
|
||||
public constructor() {}
|
||||
private static readonly _cleStats = "stats";
|
||||
private static readonly _clePartieEnCours = "partieEnCours";
|
||||
private static readonly _cleConfiguration = "configuration";
|
||||
|
||||
public sauvegarderStats(stats: SauvegardeStats): void {
|
||||
localStorage.setItem("stats", JSON.stringify(stats));
|
||||
public static sauvegarderStats(stats: SauvegardeStats): void {
|
||||
localStorage.setItem(this._cleStats, JSON.stringify(stats));
|
||||
}
|
||||
|
||||
public chargerSauvegardeStats(): SauvegardeStats | undefined {
|
||||
let dataStats = localStorage.getItem("stats");
|
||||
public static chargerSauvegardeStats(): SauvegardeStats | undefined {
|
||||
let dataStats = localStorage.getItem(this._cleStats);
|
||||
if (!dataStats) return;
|
||||
|
||||
let stats = JSON.parse(dataStats) as SauvegardeStats;
|
||||
return stats;
|
||||
}
|
||||
|
||||
public sauvegarderPartieEnCours(propositions: Array<string>, datePartie: Date): void {
|
||||
public static sauvegarderPartieEnCours(propositions: Array<string>, datePartie: Date): void {
|
||||
let partieEnCours: SauvegardePartie = {
|
||||
propositions: propositions,
|
||||
datePartie,
|
||||
};
|
||||
localStorage.setItem("partieEnCours", JSON.stringify(partieEnCours));
|
||||
localStorage.setItem(this._clePartieEnCours, JSON.stringify(partieEnCours));
|
||||
}
|
||||
|
||||
public chargerSauvegardePartieEnCours(): { propositions: Array<string>; datePartie: Date } | undefined {
|
||||
let dataPartieEnCours = localStorage.getItem("partieEnCours");
|
||||
public static chargerSauvegardePartieEnCours(): { propositions: Array<string>; datePartie: Date } | undefined {
|
||||
let dataPartieEnCours = localStorage.getItem(this._clePartieEnCours);
|
||||
if (!dataPartieEnCours) return;
|
||||
|
||||
let partieEnCours = JSON.parse(dataPartieEnCours) as SauvegardePartie;
|
||||
|
@ -36,7 +39,7 @@ export default class Sauvegardeur {
|
|||
aujourdhui.getMonth() !== datePartieEnCours.getMonth() ||
|
||||
aujourdhui.getFullYear() !== datePartieEnCours.getFullYear()
|
||||
) {
|
||||
localStorage.removeItem("partieEnCours");
|
||||
localStorage.removeItem(this._clePartieEnCours);
|
||||
return;
|
||||
}
|
||||
return {
|
||||
|
@ -44,4 +47,16 @@ export default class Sauvegardeur {
|
|||
propositions: partieEnCours.propositions,
|
||||
};
|
||||
}
|
||||
|
||||
public static sauvegarderConfig(config: Configuration): void {
|
||||
localStorage.setItem(this._cleConfiguration, JSON.stringify(config));
|
||||
}
|
||||
|
||||
public static chargerConfig(): Configuration | null {
|
||||
let dataConfig = localStorage.getItem(this._cleConfiguration);
|
||||
if (!dataConfig) return null;
|
||||
|
||||
let config = JSON.parse(dataConfig) as Configuration;
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue