• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 20/11/2019

Réalisez la conception détaillée du pad musical

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Dans le chapitre précédent, nous avons établi la liste des règles et des fonctionnalités pour la création d’un jeu musical basé sur des pads. Nous allons passer à la conception détaillée, qui consiste à essayer de traduire du point de vue technique la conception générale.

Éléments généraux 

Dans cette partie, rappelons-le, il nous faut penser aux éléments généraux, tels que la façon dont l’application est organisée à l’écran. Il faut également penser à l’esthétique générale, au choix des couleurs, des polices, etc., ainsi qu’aux dimensions générales de notre application.

Ici aussi, un petit croquis est utile pour rassembler la plus grande partie de ces informations. Je vous invite à le reproduire sur votre feuille.

Croquis
Croquis

Éléments communs aux écrans :

  • fond de page gris clair #ccc ;

  • un pied de page : Arial, noir, 12 pts.

Pour l'écran d'accueil :

  • le titre : Arial, rouge, 16 pts ;

  • une image du jeu 450*300 px ;

  • le texte expliquant les règles : Arial, noir, 12 pts ;

  • le bouton pour lancer le jeu : au milieu.

Pour l'écran de jeu :

  • le texte pour la consigne : à nouveau Arial, noir, 12 pts ;

  • un élément de type canvas 450*500, à l'intérieur duquel évolueront les bulles de couleurs sur un fond, par exemple blanc : #fff ;

  • le bouton pour quitter le jeu : à droite.

Dans l'écran de bilan, il y aura :

  • le texte du bilan : à nouveau Arial, noir, 12 pts ;

  • un bouton pour revenir à l'écran d'accueil à droite ;

  • un autre pour rejouer sans passer par l'écran d'accueil : à gauche du précédent.

Ce travail nous permet de lister certaines classes CSS. Créons par exemple la classe paragraphe — il est également possible de prendre tout simplement comme sélecteur la balise p — pour les textes de règles, de consignes, de bilan :

.paragraphe {
font...
color...
}

Structure du code JavaScript

Nous allons maintenant réfléchir à la façon dont le code JavaScript va créer la structure des écrans et leur contenu, et permettre toutes les règles et fonctionnalités que nous avons identifiées.

Intéressons-nous maintenant au code qui va :

  • créer la structure des écrans et leur contenu ;

  • permettre toutes les règles et fonctionnalités que nous avons identifiées.

Parlons structure. La première idée est ici de prévoir une page HTML pour chaque écran. Cependant, il est souvent plus pratique d’imaginer un seul fichier HTML contenant tous ces écrans ; nous ferons disparaître ou apparaître les éléments en fonction de l'écran où nous nous trouvons.

Ce qui est pratique du point de vue des fichiers CSS et JavaScript extérieurs : ils ne seront déclarés qu'une fois.

À nouveau, une petite figure est utile.

Structuration
Structuration

Vous noterez que nous avons un conteneur div (ce pourrait être un conteneur HTML5 section) pour chaque écran ; le footer, commun à chaque écran, sera affiché tout le temps. En termes de code, cela donne :

<!DOCTYPE html>
<html>
<head>...</head>
<body>
<div id="ecranAccueil">...</div>
<div id="ecranJeu">...</div>
<div id="ecranFin">...</div>
<footer>...</footer>
</body>

Il nous faut maintenant envisager les choses du point de vue de la programmation, en reprenant toutes les règles et fonctionnalités.

Concevons le code JavaScript qui va permettre cela, et construisons progressivement sa structure.

Pour simplifier le propos, imaginons que l'ensemble de ce code se trouve dans un fichier code.js.

Néanmoins, adoptons un principe important : commençons à donner des noms aux paramètres, variables et fonctions que nous identifions.

Quelle est la structure générale de ce code ?

Considérons ici une structure générale adaptée au travail de conception que nous avons déjà commencé, et qui doit pouvoir être mise en œuvre pour bon nombre d'interfaces, d’animations et de jeux. Dans des cas plus complexes, elle doit pouvoir être utilisée sur des sous-parties.

Une fois que l'ensemble du code sera chargé (événement que l'on sait détecter, par exemple grâce à l'instruction  window.onload), nous lancerons une fonction principale d'initialisation (pourquoi ne pas l'appeler init() ?). Elle est représentée sur notre feuille (cf ci-dessous) par une nouvelle boîte. Voyons dans les grandes lignes, avant de détailler plus avant, les tâches dont se charge cette fonction  init() :

  • d'abord, elle va créer la structure HTML, c'est-à-dire définir tous les éléments potentiels identifiés précédemment écran par écran. Notons que tout ou partie de ces éléments peuvent être directement définis dans le fichier HTML ;

  • ensuite, elle va définir les données, c'est-à-dire tous les paramètres dont l’application a besoin et dont nous avons parlé dans la vidéo précédente ;

  • puis, nous initialiserons les variables de notre application ;

  • étape suivante : il faut installer les gestionnaires qui permettront de mettre en œuvre les fonctionnalités ;

  • enfin, il faut installer le mécanisme par lequel les règles vont pouvoir être mises en œuvre. Nous appelons ici ce mécanisme « moteur de règles » ;

  • tout est prêt. S’affiche le premier écran : l'écran d'accueil.

En dessous, nous trouverons toutes les fonctions qu'il nous paraît pratique de créer, notamment pour ne pas répéter des parties de code. Ces fonctions seront progressivement identifiées.

Structure code
Structure code

Voici sur un dessin cette structure générale. La première boîte est le fichier code.js. En dessous du cadre  init(), il faudra progressivement ajouter toutes les fonctions.

Reprenons ces tâches l'une après l'autre.

Créer la structure HTML ne pose pas de problème particulier. Nous savons cibler un élément et modifier son contenu. Bien sûr, si le contenu de ces éléments ne change pas au cours de l’utilisation de l’application, comme le titre de l'écran d'accueil, vous pouvez les écrire directement dans le fichier HTML.Nous savons cibler un élément et modifier son contenu. Bien sûr, si le contenu de ces éléments ne change pas au cours de l’utilisation de l’application, comme le titre de l'écran d'accueil, vous pouvez les écrire directement dans le fichier HTML.

Définir les paramètres de l’application — c'est-à-dire les données non modifiées — consiste ici à définir par exemple la liste des sons qui vont être joués (que l’on appellera  listeSons),  le niveau de son de départ (niveauSonInitial), etc.

La liste précise de ces paramètres sera construite plus loin.

Initialiser les variables n'est pas forcément simple. Comme leur nom l'indique, les variables sont des éléments qui vont changer tout au long du jeu ; les variables vont avoir un rôle important, notamment au niveau des règles et fonctionnalités.

Parmi ces variables, on pense aux 4 sons associés aux pads (que l’on peut noter sonPad1, sonPad2, etc.), aux 4 niveaux de son courants (que l’on peut noter niveauSonPad1, niveauSonPad2, etc.), aux 4 tempos courants (tempoPad1, tempoPad1, etc.).

La liste précise de ces variables sera construite plus loin, au fur et à mesure que nous avancerons dans la conception du jeu.

Occupons-nous maintenant des gestionnaires pour les fonctionnalités. Les gestionnaires consistent à installer des écouteurs et à définir les fonctions qui vont être lancées lors des événements correspondants : clic sur un bouton, etc.

Qu'en est-il des règles ? Installer le mécanisme pour gérer les règles est très simple. Il s'agit d'un simple  setInterval()  associé à une fonction appelée par exemple  regles().

Cette fonction  regles()  va tester à intervalles réguliers toutes les règles qui ont été listées, ce qui nous impose de définir comme paramètre l'intervalle en millisecondes entre deux rafraîchissements :  intervalleRafraichissement.

Règles
Règles

Comme nous l'avons vu, ces règles sont des conditions de type : si, alors. Dans des animations contenant beaucoup d'écrans, il peut y avoir plusieurs dizaines de règles : il est donc normal de tester dans cette fonction uniquement les règles de l'écran où le joueur se trouve. C'est la raison d'être de la variable  ecranCourant.

Le lancement, enfin, consiste à afficher l'écran d'accueil.

Code JavaScript : règles et fonctionnalités

Dans la partie précédente, nous avons introduit la structure générale du code JavaScript. Voyons maintenant, écran par écran, comment installer les règles et les fonctionnalités qui sont de nature à modifier ces éléments, voire à changer d'écran.

Rappelons que nous sommes toujours dans la partie conception. Il ne s'agit donc pas ici d'écrire du code, mais d'imaginer comment toutes les règles et fonctionnalités vont être installées.

Intéressons-nous à l'écran d'accueil.

Au départ, tous les éléments potentiels s'affichent : le titre, une image et le bouton. Ceci se fait grâce à une fonction  afficheEcranAccueil()  qui affichera seulement l'écran d'accueil.

Comme ces éléments ne changeront pas lors de l’utilisation de l’interface, autant les définir dans le fichier HTML. Nous verrons cela dans le dernier chapitre de ce module.

Pour assurer cette fonctionnalité, il faut installer un gestionnaire sur le bouton #boutonJeu. Que fait ce gestionnaire ? En cas de clic, il affiche l'écran de jeu. Ceci se fait grâce à une fonction  afficheEcranJeu()  qui masquera l'écran d'accueil et affichera l'écran de jeu.

Intéressons-nous à l'écran de jeu. Au départ, tous les éléments potentiels s'affichent : la liste de samples, les 4 contrôles, le pad, la zone de visualisation et le bouton permettant de quitter l’interface.

Ecran d'accueil
Écran d'accueil

Du point de vue HTML :

  • la liste de samples peut consister en une boîte de type div, contenant une liste verticale de div portant les identifiants sample1, sample2, etc. ;

  • la première zone de contrôle est une boîte de type div, positionnée en ligne à droite de la liste de samples et contenant une liste verticale de 2 div portant les identifiants #controlsTL et controlsBL) ;

  • le pad consiste en une boîte de type div,  positionnée en ligne à droite de la première zone de contrôle et contenant 4 div nommés #boutonTL, #boutonTR, #boutonBL et #boutonBR ;

  • la seconde zone de contrôle est une boîte de type div, positionnée en ligne à droite du pad et contenant une liste verticale de 2 div portant les identifiants #controlsTL et controlsBL ;

  • la zone de visualisation est un canvas nommé #visu et situé en dessous des 4 boîtes précédentes ;

  • le bouton permettant de quitter l’interface est situé encore en dessous et nommé #boutonQuitter.

<div id="ecranJeu">
<div id="samples"></div>
<div id="padControlsVisu">
<div id="padControls">
<div id="controlsL">(controles gauche)</div>
<div id="pad">
<div id="padL"></div>
<div id="padR"></div>
</div>
<div id="controlsR">(controlsR)</div>
</div>
<div id="visu">
<canvas id="visuCanvas">
Ce navigateur ne supporte pas la balise canvas.
</canvas>
</div>
</div>
<div id="boutonQuitter"><input type="submit" value="Quitter"></div>
</div>

Aucune difficulté pour créer ces éléments dans le fichier HTML avec un peu de CSS.

Qu'avons-nous identifié comme fonctionnalités ?

  • si un glisser-déposer d’un sample depuis la liste des samples sur un des boutons du Pad est effectué, alors le son est associé à ce bouton (bien entendu, si une association existait avant ce glisser-déposer, elle est remplacée).

Symétriquement, il faut installer un gestionnaire de glisser-déposer avec les fonctions dragOver et drop sur chaque bouton du pad ; bien entendu, au moment du drop, il faudra identifier de quel bouton il s’agit, afin d’associer le sample qui est déplacé à ce bouton. Pas de difficulté particulière ici : cette fonctionnalité ressemble beaucoup à l’exercice de la leçon sur le glisser-déposer.

Jeu et visualisation des sons

Il y a plusieurs façons d’aborder les règles et fonctionnalités liées au jeu et à la visualisation des sons. Dans cet exercice simple, nous allons considérer que si le son associé à un pad est déjà joué en boucle, alors il n’est plus possible de jouer ce son (bien entendu, dans une autre version de cette interface, vous pourrez imaginer un autre scénario).

Si la case loop n’est pas cochée, le fait de jouer — sur un clic dans un pad — le son correspondant à ce pad une seule fois constitue effectivement une fonctionnalité, dans le sens où c’est le gestionnaire qui prend en charge cette action.

En revanche, si la case loop est cochée, le son sera joué en boucle à un tempo éventuellement changeant.

Ce deuxième cas relève d’une règle : à chaque instant, l’application doit vérifier pour chaque son si la case loop est cochée et si le son est en cours de jeu.

Contrôles
Règles / loop

Cette distinction entre règles et fonctionnalités est certes parfois formelle ; elle dépend finalement de la façon dont ces règles et fonctionnalités sont implémentées. Ici, en première approche (largement perfectible, vous allez vous en rendre compte), nous vous proposons d’appréhender les différents cas de jeu des sons à travers les fonctionnalités et règles suivantes :

  • fonctionnalité : si un des boutons du pad est cliqué, alors :

    • si ce son ne fait pas déjà l’objet d’une boucle :

      • si la case loop du contrôle associé à ce bouton n’est pas cochée, le son sera joué une fois (au volume défini par le curseur associé au volume) et visualisé dans la zone de visualisation,

      • si la case loop est cochée, le son sera joué en boucle selon le tempo et le volume définis, et visualisé dans la zone de visualisation.

Pour assurer cette fonctionnalité, un gestionnaire sur chaque bouton du pad doit être installé, par exemple à travers une classe.

Ce gestionnaire unique devra déterminer quel bouton est la cible du clic ; il est donc pertinent d’associer un identifiant à chaque bouton, par exemple les identifiants #padTL (pour top left), #padBR (pour bottom right), etc.

Nous constatons aussi qu’il est important de savoir si un son est en cours de boucle ou pas. Nous définissons donc pour chaque son :

  • une variable correspondant au moment où le pad correspondant à ce son a été cliqué, le tableau listeTempsInitiaux ;

  • un tableau qui va contenir les sons joués et qu’il faudra initialiser ;

Liste temps initiaux
Liste temps initiaux

  • règle n°1 : dans l’écran de jeu, en continu, boucler sur les différents contrôles :

    • si la case loop est cochée et que le son est en train d’être joué ou vient de s’arrêter, alors il continuera à être joué selon le tempo choisi,

    • si la case loop n’est pas cochée, mais qu’un clic sur le pas correspondant vient de se produire, alors ce son n’est joué qu’une fois ;

  • règle n°2 : la zone de visualisation affiche en continu le son qui est joué ; dans cette application, nous faisons le choix d’afficher simplement une barre verticale (dont la hauteur est liée au volume du son et la couleur est associée à la couleur du bouton du pad) pour chaque couleur.

Ces deux règles seront prises en charge par la fonction regles() dans laquelle on trouvera deux parties :

  • la première se chargera de déterminer si, à l’instant courant, un son doit être joué une fois ou en boucle et à quel volume ;

  • la seconde se chargera de visualiser les sons qui sont joués lors de cet instant courant.

 
Fonctionnalités suivantes :

  • si la case à cocher loop, non cochée préalablement, est cliquée, alors elle devient cochée et rend actif le curseur permettant de changer le tempo ;

  • si la case à cocher loop, déjà cochée préalablement, est cliquée, alors elle devient décochée et rend inactif le curseur permettant de changer le tempo (si un son était en train d’être joué, alors il s’arrête) ;

  • si le curseur associé au tempo est modifié, alors le tempo du son joué en boucle est ou sera modifié ;

  • si le curseur associé au volume est modifié, alors le volume du son joué en boucle est ou sera modifié.

Contrôles
Contrôles

Ces fonctionnalités sont faciles à mettre en œuvre à travers des gestionnaires de clic.

Enfin,

  • si le bouton #boutonJeu est cliqué, alors on passe à l'écran #ecranJeu.

À nouveau une fonctionnalité facile à mettre en œuvre à travers un gestionnaire de clic.

Voilà, nous sommes arrivés au terme de l'étape de conception.

Pour l'instant, ce travail est entièrement réalisé au brouillon sur une feuille A3. Je vous propose maintenant de rédiger le cahier de spécifications. Ce document textuel possède la structure présentée précédemment et dans laquelle vous pourrez insérer plusieurs scans des figures que vous avez dessinées.

Si nous avons détaillé ce processus consistant à balayer les écrans, les règles et les fonctionnalités jusqu'au bout, c'est pour tenter de vous montrer plusieurs choses :

  • ce n'est qu'en essayant d'imaginer comment une règle ou une fonctionnalité va être mise en oeuvre que l'on peut identifier quelles informations, quels attributs des objets que l'on manipule seront nécessaires lors de l'exécution du code ; en d'autres termes, quelle structure de données est nécessaire pour l'exécution ;

  • différents choix sont possibles ; certaines options peuvent se révéler difficiles à gérer ;

  • des écueils surgissent, qu'il faut contourner ;

  • toutes les variables importantes portent déjà un nom.

Bien évidemment, certaines choses peuvent avoir été oubliées, dont on va se rendre compte lors de la première tentative d'exécution du code.

Ce dont je suis convaincu après de nombreuses années de développement de projets plus ou moins importants, c'est que plus vous pousserez loin ce travail d'analyse, susceptible régulièrement de modifier la structure de données initiale, plus vous irez vite dans votre développement. Et plus vous réduirez les risques de mauvaises surprises en découvrant, après avoir écrit la presque totalité du code, un élément qui le remet complètement en cause.

Dernier point dans ces spécifications techniques détaillées : l'architecture de fichiers.

L'architecture de fichiers est ici très simple. Elle se résume à :

  • un fichier HTML : index.html ;

  • un dossier styles contenant le fichier styles.css ;

  • un dossier js contenant le fichier code.js et, si l'on souhaite travailler avec jQuery, le fichier jQuery.js ;

  • un dossier images contenant l'image affichée dans l'écran d'accueil.

Structure fichiers
Structure fichiers

En résumé

Cette partie nous a permis de détailler deux chapitres importants du cahier de spécifications :

  • le cahier des charges fonctionnel d'un jeu, qui détaille :

    • la liste des écrans et leur contenu potentiel,

    • la liste des règles et des fonctionnalités ;

  • les spécifications techniques détaillées :

    • les données importantes,

    • les éléments généraux,

    • le code,

    • l'architecture de fichiers.

Dans le prochain chapitre, nous allons aborder la phase de développement et examiner rapidement quelques bonnes pratiques.

À tout de suite !

Exemple de certificat de réussite
Exemple de certificat de réussite