Projet Jeu 2
Objectifs
- Créer un niveau
- Gérer les collisions
Théorie
À lire pour comprendre le code.
Kaplay
Explication du code utilisé la semaine précédente.
Initialisation
Pour utiliser la bibliothèque Kaplay, il faut d'abord commencer par l'initialiser avec la fonction kaplay() :
kaplay({
background: "#000000", // couleur de fond avec les bordures
width: 640, // largeur de la scène en pixels
height: 480, // hauteur de la scène en pixels
letterbox: true, // ajuste la taille de la scène à la taille de la fenêtre en gardant les proportions
});
Add
Pour ajouter un objet dans la scène, on utilise la fonction add() qui prend un tableau de composants en paramètre :
const player = add([
"player", // les chaines de caractères sont des tags pour identifier l'objet par la suite.
"friendly", // on peut ajouter plusieurs tags.
rect(40, 40), // c'est un rectangle de 40x40 pixels.
color("#f44336"), // la couleur rgb du rectangle.
pos(128, 256), // la position du point d'ancrage dans la scène.
area(), // défini le masque de collision (hitbox).
body(), // applique la physique à l'objet.
rotate(0), // rotation en degrés.
opacity(1), // opacité entre 0 et 1.
anchor("center"), // point d'ancrage (l'origine de l'objet).
// et bien d'autres...
]);
Javascript
Fonction
Dans le code qui permet de faire sauter un personnage, on utilise une fonction :
onKeyPress("space", () => {
player.jump();
});
onKeyPress est une fonction qui permet de définir une action lorsqu'une touche est pressée. Elle prend deux paramètres :
- le nom de la touche (ici "space" pour la barre d'espace).
- une fonction qui sera exécutée lorsque la touche est pressée. La syntaxe
() => { ... }permet de définir une fonction anonyme qu'on passe en paramètre.
Pratique
Niveau
Au lieu de positioner chaque élément du niveau avec des coordonnées, on va utiliser une "grille" pour définir le niveau.
Chaque case aura une taille de 40x40 pixels, ce qui donne 16x12 cases. On va ensuite définir le niveau avec des symboles.
- Renommer le fichier
main.jsenold-main.jspour garder une trace du code précédent. - Créer un nouveau fichier
main.jsavec le contenu suivant :
kaplay({
width: 640,
height: 480,
background: "#000000",
letterbox: true,
});
add(["background", rect(width(), height()), pos(0, 0), color("#eee8d5")]);
setGravity(1600);
const level = addLevel(
[
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ^ ",
" === ",
" ",
" @ ^ $ $ $ ",
"================",
],
{
tileWidth: 40,
tileHeight: 40,
tiles: {
"@": () => [
"player",
circle(20),
color("#dc322f"),
area(),
body(),
anchor("topleft"),
],
"=": () => [
"grass",
rect(40, 40),
color("#859900"),
outline(),
area(),
body({ isStatic: true }),
anchor("topleft"),
],
"$": () => [
"coin",
circle(20),
color("#b58900"),
area(),
anchor("topleft"),
],
"^": () => [
"danger",
rect(40, 40),
color("#d33682"),
area(),
anchor("topleft"),
],
},
},
);
const player = level.get("player")[0];
- Chaque caractère dans le tableau représente une case du niveau.
- "@" représente le personnage du joueur.
- "=" représente une plateforme.
- "$" représente une pièce à ramasser.
- "^" représente un danger à éviter.
- Remplacer un espace par un "=" pour observer l'effet sur le niveau.
- La dernière ligne récupère le personnage du niveau pour pouvoir lui ajouter des actions par la suite (saut, déplacement, …).
- La fonction
.get()sur la variablelevelpermet de récupérer tous les éléments du niveau qui ont le tag "player". Comme il n'y a qu'un seul élément avec ce tag, on récupère le premier élément du tableau avec[0].
- La fonction
- Reprendre le code de
old-main.jspour :- Faire bouger le personnage à gauche et à droite avec les touches fléchées.
- Faire sauter le personnage avec la barre d'espace et la touche fléchée (
.onKeyPress()peut prendre une liste de touches comme premier argument).main.jsonKeyPress(["space", "up"], () => {
player.jump();
}); - Reprendre les sprites qui ont été faits.
- Une fois que tout est fonctionnel, supprimer le fichier
old-main.js.
- Faire bouger le personnage avec les touches WASD en plus des touches fléchées.
- W pour sauter, A pour aller à gauche et D pour aller à droite.
Sprite du joueur
Reprendre le chargement du sprite :
kaplay({
width: 640,
height: 480,
background: "#000000",
letterbox: true,
});
loadSprite("player", "sprites/player.gif");
Modifier la déclaration du personnage dans le niveau pour utiliser le sprite à la place du cercle et de la couleur :
...
"@": () => [
"player",
sprite("player", { width: 40, height: 40 }),
area(),
body(),
anchor("topleft"),
],
...
Organisation du code
Prendre le temps de nettoyer et réorganiser le code pour le rendre plus lisible. Notamment pour l'ordre des déclarations :
- Initialisation de Kaplay
- Chargement des sprites
- Définition des paramètres globaux (par exemple la gravité)
- Ajout d'un fond
- Définition du niveau
- Définition des actions (doit être après le niveau car besoin de récupérer les éléments du niveau, p. ex.
player)
Ajouter des commentaires pour séparer les différentes parties et expliquer le code.
// Initialisation de Kaplay
kaplay({
width: 640,
height: 480,
background: "#000000",
letterbox: true,
});
// Chargement des sprites
loadSprite("player", "sprites/player.png");
// Définition des paramètres globaux
setGravity(1600);
// Ajout d'un fond
add(["background", pos(0, 0), rect(width(), height()), color("#eee8d5")]);
...
Continuer à commenter les différentes parties du code pour expliquer ce qu'elles font.
Collision
Pour détecter les collisions entre deux éléments, utiliser la fonction .onCollide(). Pour définir ce qui est exécuté lorsque un élément avec le tag "player" entre en collision avec un élément avec le tag "danger", on écrit :
- Utiliser la fonction
.onCollide()pour définir une action lorsqu'un élément avec le tag "player" entre en collision avec un élément avec le tag "danger" :
onCollide("player", "danger", (player, danger) => {
addKaboom(player.pos);
});
.addKaboom()ajoute une animation d'explosion à la position donnée.
- Ajouter le code
player.destroy();dans la fonction de collision pour faire disparaître le personnage lorsqu'il entre en collision avec un élément avec le tag "danger". - Ajouter la collision entre le personnage (
player) et les pièces (coin) pour les faire disparaître lorsqu'elles sont ramassées.
Niveau
- Modifier le niveau pour ajouter plus de plateformes, de pièces et de dangers.
Sprites
- Créer les sprites avec Piskel pour tous les éléments du niveau (personnage, plateformes, pièces, danger, …).
- Ajouter les sprites dans le code à la place des formes géométriques.
- Ajouter une image de fond pour remplacer le fond uni.
- Cette ligne permet d'ajouter un fond uni :
main.js
add(["background", pos(0, 0), rect(width(), height()), color("#eee8d5")]); - Charger le sprite avant cette ligne.
- Remplacer le rectangle et la couleur par un sprite.
- Cette ligne permet d'ajouter un fond uni :
Code d'exemple
Exemple
kaplay({
width: 640,
height: 480,
background: "#000000",
letterbox: true,
});
setGravity(1600);
add(["background", pos(0, 0), rect(width(), height()), color("#eee8d5")]);
const level = addLevel(
[
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ^ ",
" === ",
" ",
" @ ^ $ $ $ ",
"================",
],
{
tileWidth: 40,
tileHeight: 40,
tiles: {
"@": () => [
"player",
circle(20),
color("#dc322f"),
area(),
body(),
anchor("topleft"),
],
"=": () => [
"grass",
rect(40, 40),
color("#859900"),
outline(),
area(),
body({ isStatic: true }),
anchor("topleft"),
],
"$": () => [
"coin",
circle(20),
color("#b58900"),
area(),
anchor("topleft"),
],
"^": () => [
"danger",
rect(40, 40),
color("#d33682"),
area(),
anchor("topleft"),
],
},
},
);
const player = level.get("player")[0];
onKeyPress(["space", "up"], () => {
player.jump();
});
onKeyDown("right", () => {
player.move(256, 0);
});
onCollide("player", "danger", (player, danger) => {
addKaboom(player.pos);
});