8420 views
owned this note
<style>
#doc>div, #doc>p, #doc>ul {
text-align: justify;
}
</style>
<center>
Créer un jeu de la Vie avec JS
===
</center>
Aujourd'hui, nous attaquons le langage JavsScript, grandement répandu dans le Web pour dynamiser vos pages ou encore gérer des serveurs. L'objectif est de se familiariser avec le langage et le dynanisme qu'il propose pour la création des sites Web. Pour cela nous allons essayer de coder un jeu de la Vie dans notre navigateur.
## Récupérer le projet
Pour aller à l'essentiel un template du projet est disponible :
[Récupérer le projet](https://perso.ensta-paristech.fr/~lin/formations/js/starter.tar.gz)
Dézippez le et ouvrez le projet dans votre éditeur préféré. Vous devriez avoir l'arborescence suivante :
![Arboresence.png](https://perso.ensta-paristech.fr/~lin/formations/media/Arborescence.png)
Nous retrouvons notre fichier *HTML* qui contient le contenu de notre page Web. Ajouté à celui-ci, le dossier `src` contient les ressources dont avons besoin à savoir les images et les fichiers *CSS* et *JS*.
## Quelques points sur le JavaScript
Aujourdh'hui nous n'allons pas nous attarder sur le code *CSS* utilisé pour donner du style à la page, ni modifier la page *HTML* qui possède déjà tous les éléments dont nous avons besoin. Des tutoriels sur ces sujets sont proposés sur le [site de DaTA](https://data-ensta.fr/#formations).
Notre travail de programmation va uniquement s'appliquer aujourd'hui aux fichiers JavaScript. Le langage est haut niveau, proche du python, et ne présente pas de difficultés particulières. L'intérêt premier de cette formation est la gestion des évènements tels que l'appui sur un bouton ou le mouvement de la souris sur l'écran par l'utilisateur pour activer en conséquences certaines actions particulières.
## Le fichier HTML
Avant de commencer à coder, il faut jeter un coup d'œil au fichier *index.html*. Tout la partie affichage est effectuée dans la balise `<canvas>`. Il s'agit d'une balise qui délimite un espace de dessin sur la page. Nous ne nous intéresserons pas à cette balise dans ce tutoriel.
Nous pouvons voir un attribut `id` pour chaque balise `<button>` et pour le `<canvas>`. Cet attribut permet d'identifier de façon unique les balises html. Il faut bien évidemment s'assurer que ces identifiants soient uniques dans le fichier *HTML*. Nous allons avoir besoin de cet attribut plus tard.
## Les fichiers javascript
Les fichiers javascript sont habituellement placés dans le répertoire `/src/js`.
Pour importer un fichier javascript dans le fichier *HTML* rien de plus simple, il suffit d'utiliser une balise `<script>` dans laquelle nous renseignons le chemin d'accès du fichier.
```xml
<script type="text/javascript" src="src/js/drawing.js"></script>
```
Voyez par vous-mêmes dans le fichier html fourni.
Nous ne sommes pas limités par le nombre de fichiers JS importés. En l'occurence il n'en est présenté qu'un, mais vous allez par la suite en créer de nouveaux et les importer dans le fichier html.
L'intérêt est tout simplement de clarifier et structurer le code. Cela ne change rien au code et cela est parfaitement équivalent à tout écrire dans un seul fichier. L'ordre d'importation des fichiers a d'ailleurs de l'importance car les variables et les fonctions déclarées dans un fichier ne pourront pas être utilisées dans les fichers précédents.
# Jeu de la vie
L'objet de ce tuto est de programmer un jeu de la vie, si vous ne savez pas ce qu'est le jeu de la vie [cliquez ici](https://fr.wikipedia.org/wiki/Jeu_de_la_vie) pour aller sur la page wikipédia.
Nous allons nous intéresser seulement à la partie javascript, les fichiers de styles et le fichier html sont donnés ainsi que les fonctions de dessins.
## I - Les variables d'état
En javascript, il y a 2 manières de déclarer une variable :
```javascript=
let maVariable
var maVariable
```
Il n'y a pas de différence dans l'utilisation des variables. Une différence entre ces deux déclarations se trouve dans l'accessibilité de la variable dans le code (voir [ceci](https://stackoverflow.com/a/11444416/5459467)) mais pour nous ces deux déclarations sont équivalentes.
javascript étant un langage interprété, il est possible de déclarer et d'instancier en même temps une variable sans les mots clés `var` et `let` :
```javascript=
maVariable = uneValeur
```
Cette caractéristique a un inconvénient majeur, en effet si quelqu'un écrit :
```javascript=
maVariable = uneValeur
...
maVairable = uneAutreValeur // l'interpréteur considère que c'est une déclaration d'une variable.
```
L'interpréteur considère que la seconde ligne est une déclaration d'un autre variable alors qu'il pourrait s'agir d'un erreur de frappe. Il faut donc se méfier de ce genre de déclaration.
Nous pouvons aussi définir des constantes de la manière suivante
```javascript=
const maConstante = uneValeur
```
Pour le jeu, nous avons besoin de définir des variables d'état et des variables caractérisant l'affichage dans la page web. Nous allons définir ces variables au début d'un fichier nommé `init.js`. Il ne faudra pas oublier d'importer le fichier dans `index.html`:
```javascript=
const nbX = 100 // nombre d'élément sur l'axe X
const nbY = 50 // nombre d'élément sur l'axe Y
var sizeX // taille des éléments sur l'axe X
var sizeY // taille des éléments sur l'axe Y
var states // matrice d'état des cellules
```
Les variables sont définies de manière globales, elles sont visibles et accessibles par tous les fichiers javascript que nous utiliserons.
Dans ce tuto nous avons fait le choix de fixer le nombre de cellule plutôt que leur taille ce qui explique la déclaration en `const` des variables `nbX`, `nbY`.
Les axes dans le canvas sont définis comme sur l'image :
![image](https://mdn.mozillademos.org/files/224/Canvas_default_grid.png)
## II - Intialisation
Dans la section précédente, nous avons déclaré les variables sans leur donner de valeur.
Pour définir la taille du canvas nous pouvons utiliser le code suivant :
```javascript=
const canvas = document.getElementById('zone')
canvas.width = window.innerWidth - (window.innerWidth % 100)
canvas.height = window.innerHeight - (window.innerHeight % 100)
```
Pour initialiser la matrice des états nous pouvons utiliser le code suivant :
```javascript=
let states = new Array(nbY).fill(null)
for (let i = 0; i < states.length; i++) {
states[i] = new Array(nbX).fill(false)
}
```
Un `listener` est généralement une fonction qui permet de gérer un évènement produit au moment de l'utilisation de la page web.
Avant de pouvoir ajouter un `listener` aux boutons, il faut être capable de sélectionner la bonne balise auquelle on ajout le `listener`. La syntaxe est :
```javascript=
document.getElementById('id') // id est la valeur de l'attibut id donné à la balise en question.
```
la syntaxe pour l'ajout d'un `listener` est :
```javascript=
element.addEventListener('event', listener) // event est le nom de l'évènement.
```
Le nom des `'event'` les plus communs sont : `'change'`, `'click'`, `'mouseover'`, `'mouseout'`, `'keydown'` et `'load'`.
Les `listeners` peuvent aussi être ajouté directement dans le fichier HTML. Par exemple pour la balise `<body>`, on fait un appel à la fonction `init()` lors du déclenchement de l'évènement `onload`. Cela veut dire que lorsque le chargement de la page est fini, cette fonction est appelée. Dans un fichier *HTML* on ajoute le préfixe `on` aux noms des évènements.
La déclaration d'une fonction se fait de la manière suivante :
```javascript=
function name(arg){
//corps de la fonction
}
```
Une fonction peut être définie n'importe où dans le code mais elle ne sera visible que là où elle est déclarée.
## III - Peupler la grille
Nous pouvons utiliser la fonction suivante pour générer une population aléatoire :
```javascript=
function randomPopulate() {
const canvas = document.getElementById('zone')
const ctx = canvas.getContext('2d')
for (let i = 0; i < nbY; i++) {
for (let j = 0; j < nbX; j++) {
states[i][j] = Math.random() < 0.1 ? true : false
}
}
updatefront()
}
```
Cette fonction est appelée lorsque l'utilisateur appuit sur le bouton "Random population".
## IV - Règle du jeu
Si la cellule est morte et qu'elle a exactement 3 voisins alors elle revit sinon elle reste morte
si la cellule est vivante et qu'elle a 2 ou 3 voisins, la cellule reste vivante sinon elle meurt.
## V - Gestion des itérations
Pour pouvoir calculer les itérations suivantes, nous pouvons utiliser :
```javascript=
setInterval(callback,interval) // interval est donné en milliseconde.
```
## VI - Snippets
Voici un bout de code pour les personnes n'ayant aucune idée de la manière de coder le jeu. Cette fonction retourne un `array` contenant l'état des voisins de la cellule à la ligne `row` et à la colonne `column`.
```javascript=
function getNeighbours(row, column) {
return [
row - 1 < 0 || column - 1 < 0 ? false : states[row - 1][column - 1],
row - 1 < 0 ? false : states[row - 1][column],
row - 1 < 0 || column + 1 >= nbX ? false : states[row - 1][column + 1],
column - 1 < 0 ? false : states[row][column - 1],
column + 1 >= nbX ? false : states[row][column + 1],
row + 1 >= nbY || column - 1 < 0 ? false : states[row + 1][column - 1],
row + 1 >= nbY ? false : states[row + 1][column],
row + 1 >= nbY || column + 1 >= nbX
? false
: states[row + 1][column + 1],
]
}
```