Aller au contenu principal

Déplacement dans le Labyrinthe

Objectif

Apprendre à gérer les événements clavier en JavaScript pour permettre à l'utilisateur d'interagir avec le jeu.

Notions théoriques

Le JavaScript est un langage événementiel, ce qui signifie que beaucoup de code s'exécute en réponse à des événements.

Dans un jeu comme Pacman, les événements clavier sont essentiels pour contrôler les mouvements du personnage.

info

En JavaScript, l'écoute d'événements se fait grâce à la méthode addEventListener, qui permet de réagir à des actions de l'utilisateur, comme appuyer sur une touche.

Pour Pacman, nous utiliserons addEventListener pour écouter les événements keydown, qui sont déclenchés lorsque l'utilisateur appuie sur une touche.

La propriété event.key nous permet de savoir quelle touche a été pressée.

Voici en Javascript comment écouter un évènement keydown du clavier :

// Ecouter l'évènement keydown du clavier et exécuter une fonction   
useEffect(() => {
function handleKeyDown(event) {
// Il suffit de placer ici le nom de la fonction qui doit être appelée
// lorsque l'utilisateur a appuyé sur une touche du clavier.
}

// Ajouter l'écouteur de l'évènement 'Appui sur une touche'
document.addEventListener("keydown", handleKeyDown);

// Retirer l'écouteur de l'évènement 'Appui sur une touche' lorsque l'appui a été traité
return () => document.removeEventListener("keydown", handleKeyDown);

// Indiquer ici le nom de la variable dépendante qui sera modifiée suite à l'appel
// de la fonction indiquée dans handleKeyDown(event) {...}
}, [positionDeObjet]);
attention

Il est important de gérer correctement ces événements pour que le personnage ne traverse pas les murs ;-) et se déplace seulement là où c'est possible !

Exemple pratique

Dans notre jeu de Pacman, nous pourrons écouter l'évènement keydown du clavier et exécuter la fonction deplacerPacman, avec ce code :

// Ecouter l'évènement keydown du clavier et exécuter la fonction deplacerPacman   
useEffect(() => {
function handleKeyDown(event) {
deplacerPacman(event.key, pacmanPosition, labyrinthe, setPacmanPosition);
}

document.addEventListener("keydown", handleKeyDown);

return () => document.removeEventListener("keydown", handleKeyDown);
}, [pacmanPosition]);

Et voici un extrait de la fonction deplacerPacman qui va pouvoir déplacer le Pacman en fonction de la touche appuyée :

document.addEventListener('keydown', function(event) {
switch(event.key) {
case 'ArrowUp':
// Déplacer Pacman vers le haut si possible
break;
case 'ArrowDown':
// Déplacer Pacman vers le bas si possible
break;
case 'ArrowLeft':
// Déplacer Pacman vers la gauche si possible
break;
case 'ArrowRight':
// Déplacer Pacman vers la droite si possible
break;
}
});

Quelques éléments de code à connaître

  • addEventListener(type, listener): Attache une fonction à appeler chaque fois que l'événement spécifié est délivré à la cible.
  • removeEventListener(type, listener): Supprime un écouteur d'événement.
  • event.key: Retourne la valeur de la touche du clavier qui a été pressée lors d'un événement clavier.

Test de mémorisation/compréhension


Quelle méthode permet d'attacher un écouteur d'événements en JavaScript ?


Quel événement clavier est utilisé pour détecter quand une touche est pressée ?


Quelle propriété de l'objet event est utilisée pour déterminer la touche spécifique pressée ?


Que faut-il faire pour empêcher Pacman de traverser les murs ?



TP pour réfléchir et résoudre des problèmes

Votre mission

Votre mission consiste à créer un composant Pacman et à ajouter la gestion des événements de touches pour déplacer Pacman en fonction des touches directionnelles pressées.

Etapes

Voici un exemple de code qui permet à Pacman de se déplacer dans le labyrinthe en utilisant les touches fléchées du clavier, sans traverser les murs :

  1. Créez un nouveau fichier Pacman.js à la racine de votre projet (à côté de App.js) :

    // Pacman.js
    import React from 'react';
    import { View } from 'react-native';

    const tailleCase = 40;
  2. Ajoutez la fonction Pacman dans votre fichier Pacman.js :

    // Pacman.js
    import React from 'react';
    import { View } from 'react-native';

    const tailleCase = 40;

    function Pacman(props) {
    ...
    }
  3. Complétez la fonction Pacman, dans votre fichier Pacman.js, afin de définir les attributs et le style d'affichage de votre Pacman :

    // Pacman.js
    import React from 'react';
    import { View } from 'react-native';

    const tailleCase = 40;

    function Pacman(props) {
    const position = props.position;
    const stylePacman = {
    width: tailleCase,
    height: tailleCase,
    borderRadius: tailleCase / 2,
    backgroundColor: 'yellow',
    position: 'absolute',
    left: position.x * tailleCase,
    top: position.y * tailleCase,
    transition: 'left 0.5s, top 0.5s', // Transition douce pour le mouvement
    };

    return <View style={stylePacman} />;
    }
  4. Ajoutez l'export de la fonction Pacman à la fin du fichier Pacman.js :

    export default Pacman;
  5. Ajouter l'import de notre composant Pacman dans le code du fichier App.js :

    // App.js
    import { StyleSheet, View } from 'react-native';
    import Labyrinthe from './Labyrinthe';
    import genererLabyrinthe from './genererLabyrinthe';
    import Pacman from './Pacman';

    ...

  1. Créez un nouveau fichier DeplacementPacman.js à la racine de votre projet (à côté de App.js), avec une fonction deplacerPacman :

    // DeplacementPacman.js

    function deplacerPacman(direction, pacmanPosition, labyrinthe, setPacmanPosition) {

    ...

    }
  2. Complétez le code de la fonction deplacerPacman :

    // DeplacementPacman.js

    function deplacerPacman(direction, pacmanPosition, labyrinthe, setPacmanPosition) {
    var nouvellePosition = { ...pacmanPosition };

    switch (direction) {
    case "ArrowUp":
    nouvellePosition.y -= 1;
    break;
    case "ArrowDown":
    nouvellePosition.y += 1;
    break;
    case "ArrowLeft":
    nouvellePosition.x -= 1;
    break;
    case "ArrowRight":
    nouvellePosition.x += 1;
    break;
    default:
    return; // Si la touche n'est pas reconnue, on ne fait rien.
    }

    // Vérifier si la nouvelle position est un chemin.
    if (
    labyrinthe[nouvellePosition.y] &&
    labyrinthe[nouvellePosition.y][nouvellePosition.x] === 0
    ) {
    setPacmanPosition(nouvellePosition);
    }
    }
  3. Ajoutez l'export de la fonction deplacerPacman à la fin du fichier DeplacementPacman.js :

    export default deplacerPacman;
  4. Ajouter l'import de notre fonction deplacerPacman dans le code du fichier App.js :

    // App.js
    import { StyleSheet, View } from 'react-native';
    import Labyrinthe from './Labyrinthe';
    import genererLabyrinthe from './genererLabyrinthe';
    import Pacman from './Pacman';
    import deplacerPacman from "./DeplacementPacman";
    ...
  5. Ajouter l'import des composants useStateet useEffect, dans le code du fichier App.js, pour mémoriser la position de Pacman et ajouter un écouteur d'événements :

    // App.js
    import React, { useState, useEffect } from 'react';
    import { StyleSheet, View } from 'react-native';
    import Labyrinthe from './Labyrinthe';
    import genererLabyrinthe from './genererLabyrinthe';
    import Pacman from './Pacman';

    ...
    Que signifient useState et useEffect ?

    Imaginez que vous construisez une maison avec des pièces qui ont des boitiers pour contrôler la température de chaque pièce.

    • useState :

      Pour que les choses fonctionnent, chaque pièce a besoin de se souvenir de la température souhaitée dans cette pièce.

      Dans le monde de la programmation, cette mémoire s'appelle "état". useState est un petit boitier/mémoire que vous pouvez mettre dans n'importe quelle pièce. Ce boitier vous permet de fixer la température de la pièce.

    • useEffect :

      Maintenant, parfois, vous voulez que certaines choses se passent automatiquement dans une pièce, comme éteindre le chauffage quand vous ouvrez la fenêtre.

      Dans le monde de la programmation, ces actions automatiques s'appellent des "effets de bord". useEffect est comme un petit boitier/robot dans la pièce qui s'occupe de ces actions automatiques. Vous lui dites quoi faire et quand le faire (par exemple, éteindre le chauffage quand vous ouvrez la fenêtre).

    En résumé, useState et useEffect sont des outils qui rendent la construction et la gestion des pièces de votre maison beaucoup plus flexible.

  6. Modifiez le code du fichier App.js pour mémoriser la position du Pacman (et démarrer dans la case { x: 1, y: 1 }) :

    ...

    export default function App() {
    const [pacmanPosition, setPacmanPosition] = useState({ x: 1, y: 1 }); // Démarre en position x=1 et y=1

    ...
  7. Modifiez le code du fichier App.js pour écouter l'évènement keydown du clavier et exécuter la fonction deplacerPacman :

    ...

    // Ecouter l'évènement keydown du clavier et exécuter la fonction deplacerPacman
    useEffect(() => {
    function handleKeyDown(event) {
    deplacerPacman(event.key, pacmanPosition, labyrinthe, setPacmanPosition);
    }

    document.addEventListener("keydown", handleKeyDown);

    return () => document.removeEventListener("keydown", handleKeyDown);
    }, [pacmanPosition]);

    ...

  8. Modifiez le code du fichier App.js pour ajouter notre composant Pacman :

    ...

    return (
    <View style={styles.container}>
    <View>
    <Labyrinthe labyrinthe={labyrinthe} />
    <Pacman position={pacmanPosition} />
    </View>
    </View>
    );

    ...

Dans ce code, nous avons :

  1. Créé un composant Pacman qui dessine Pacman sur l'écran à la position spécifiée.
  2. Ajouté un style de transition pour que le mouvement de Pacman soit fluide à l'écran (transition douce).
  3. Créé une fonction deplacerPacman qui dessine Pacman sur l'écran à la position spécifiée.
  4. Importé useState pour mémoriser la position de Pacman.
  5. Utilisé useEffect pour ajouter un écouteur d'événements qui écoute les appuis sur les touches directionnelles et appelle deplacerPacman en conséquence.

Ce code permet ainsi à Pacman de se déplacer dans le labyrinthe en utilisant les touches fléchées du clavier, sans traverser les murs.

Une solution