Sprite, niveau et collision
Objectifs
- Créer un sprite
- Créer un niveau
- Gérer les collisions
- Utiliser la documentation
- Formater et organiser le code
Théorie
Sprite
Un sprite est une image qui représente un objet dans un jeu vidéo. Par exemple, dans un jeu de plateforme, les personnages, les ennemis, les pièces, etc. sont des sprites.
Ils peuvent être statiques ou animés. Dans le cas d'un sprite animé, il s'agit d'une succession d'images qui donne l'illusion du mouvement.
Kaboom
Initialisation
Pour utiliser la bibliothèque Kaboom, il faut d'abord commencer par l'initialiser avec la fonction kaboom()
.
kaboom({
background: [227, 242, 253],
width: 640,
height: 480,
});
// Supprimez la ligne suivante dans votre code,
// déplacez le code couleur dans le kaboom()
add(["background", rect(width(), height()), color(227, 242, 253)]);
Le code ci-dessus initialise une scène de 640x480 pixels avec un fond bleu clair.
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
"friendly", // on peut ajouter plusieurs tags
rect(40, 40), // c'est un rectangle de 40x40 pixels
color(244, 67, 54), // la couleur rgb du rectangle
pos(128, 256), // la position du rectangle 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...
]);
Documentation
Toutes les fonctions et composants sont documentés sur le site de Kaboom, par exemple pour body()
:
- La liste des paramètres possibles : options?: BodyCompOptjs
body({ isStatic: true, // objet statique (ne bouge pas) jumpForce: 128, // vitesse des sauts // ... });
- La liste des fonctions disponibles une fois ajouté à l'objet : BodyComp
body()
ajoute les fonctions.move()
,.jump()
,.isGrounded()
, etc.
Javascript
Fonction
Dans le code suivant qui permet de faire sauter un personnage, nous utilisons 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
- une fonction qui sera exécutée lorsque la touche est pressée
La syntaxe () => { ... }
permet de définir une fonction anonyme qu'on peut passer en paramètre.
Pratique
Sprite
Créez un dossier
sprites
dans le dossierprojet-jeu
Créez un sprite sur Piskel (ou un autre logiciel de dessin) et exportez-le en GIF dans le dossier
sprites
- Commencez par choisir la taille de votre sprite : 40x40 pixels
- Dessinez votre sprite (pour votre personnage principal)
- Exportez-le en GIF et mettez le dans le dossier
sprites
en le renommantplayer.gif
Pour charger le sprite dans votre code (mettez-le juste après le
kaboom()
)jskaboom({ background: [0, 0, 0], width: 640, height: 480, }); loadSprite("player", "sprites/player.gif");
player
est l'identifiant du sprite (le nom que vous lui donnez)sprites/player.gif
est le chemin vers le fichier GIF- Vous allez utiliser l'identifiant à chaque fois que vous souhaitez utiliser ce sprite dans votre code
Vous pouvez désormais l'utiliser dans votre code (remplacez les lignes en rouge par les lignes en vert)
jsconst player = add([ "player", circle(32), color(244, 67, 54), sprite("player", { width: 40, height: 40 }), pos(128, 256), area(), body(), ]);
Formater le code
Formater le code permet de le rendre plus lisible et plus facile à comprendre en étant régulier dans la mise en forme.
Vous pouvez formatter votre code directement dans Visual Studio Code en utilisant le raccourci Alt+Shift+F
.
Vous pouvez utiliser Prettier pour formater votre code.
- Coller votre code dans la fenêtre de gauche
- Le code formaté apparaît dans la fenêtre de droite
Niveau
Au lieu de positioner chaque élément du niveau avec des coordonnées, on peut aussi utiliser une "grille" pour définir le niveau.
On va choisir une taille de case de 40x40 pixels, ce qui vous fait 16x12 cases. On va ensuite définir le niveau avec des symboles.
Rajoutez les lignes suivantes dans votre code à la suite :
const level = addLevel(
[
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ^ ",
" === ",
" ",
" @ ^ $ $ $ ",
"================",
],
{
tileWidth: 40,
tileHeight: 40,
tiles: {
"@": () => [
"player",
circle(20),
color(33, 150, 243),
area(),
body(),
anchor("topleft"),
],
"=": () => [
"grass",
rect(40, 40),
color(27, 94, 32),
outline(),
area(),
body({ isStatic: true }),
anchor("topleft"),
],
$: () => [
"coin",
circle(20),
color(253, 216, 53),
area(),
anchor("topleft"),
],
"^": () => [
"danger",
rect(40, 40),
color(244, 67, 54),
area(),
anchor("topleft"),
],
},
}
);
Supprimez (ou commentez avec /* ... */
) vos précédents objets ajoutés avec add()
.
Pour récupérer notre personnage afin de lui ajouter des actions (par exemple le saut), nous pouvons utiliser la fonction .get()
sur notre variable level
:
const player = add([
"player",
sprite("player", { width: 40, height: 40 }),
pos(128, 256),
area(),
body(),
]);
const level = addLevel(
...
);
const player = level.get("player")[0];
La fonction .get()
renvoie un tableau avec tous les éléments qui ont "player" comme tag. Dans notre cas, il n'y a qu'un seul élément qui correspond à la recherche, donc nous pouvons récupérer le premier élément du tableau avec [0]
.
Migrer tout votre précédent code dans le niveau (plus aucun add()
dans votre code).
Organisation du code
Prenez le temps de réorganiser votre code pour le rendre plus lisible. Notamment pour l'ordre des déclarations :
- Initialisation de Kaboom
- Chargement des sprites
- Définition des paramètres globaux (par exemple la gravité)
- Définition des niveaux
- Définition des actions (doit être après les niveaux car besoin de récupérer les éléments du niveau, p. ex.
player
)
Collision
Pour détecter les collisions entre deux éléments, nous pouvons utiliser la fonction .onCollide()
. Pour définir ce qu'on fait lorsque un élément avec le tag "player" entre en collision avec un élément avec le tag "danger", nous pouvons écrire :
onCollide("player", "danger", (player, danger) => {
addKaboom(player.pos);
});
Faites en sorte que votre personnage meurt lorsqu'il entre en collision avec un élément avec le tag "danger". Vous pouvez utiliser la fonction destroy()
pour supprimer un élément.
Solution
onCollide("player", "danger", (player, danger) => {
addKaboom(player.pos);
player.destroy();
});
Faites en sorte que votre personnage ramasse les pièces lorsqu'il entre en collision avec un élément avec le tag "coin".
Indice
La pièce est détruite lorsqu'elle entre en collision avec le personnage.
Saut simple
Pour faire sauter le personnage, nous avons utilisé la fonction .jump()
:
onKeyPress("space", () => {
player.jump();
});
Faites en sorte que le personnage puisse sauter qu'une seule fois.
Vous pouvez utiliser la fonction .isGrounded()
pour savoir si le personnage touche le sol.
Indice
L'idée est de pouvoir sauter uniquement si le personnage touche le sol.
Solution
onKeyPress("space", () => {
if (player.isGrounded()) {
player.jump();
}
});
Checkpoint
Exemple
kaboom({
background: [227, 242, 253],
width: 640,
height: 480,
});
setGravity(1600);
const level = addLevel(
[
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ^ ",
" === ",
" ",
" @ ^ $ $ $ ",
"================",
],
{
tileWidth: 40,
tileHeight: 40,
tiles: {
"@": () => [
"player",
circle(20),
color(33, 150, 243),
area(),
body(),
anchor("topleft"),
],
"=": () => [
"grass",
rect(40, 40),
color(27, 94, 32),
outline(),
area(),
body({ isStatic: true }),
anchor("topleft"),
],
$: () => [
"coin",
circle(20),
color(253, 216, 53),
area(),
anchor("topleft"),
],
"^": () => [
"danger",
rect(40, 40),
color(244, 67, 54),
area(),
anchor("topleft"),
],
},
}
);
onCollide("player", "danger", (player, danger) => {
addKaboom(player.pos);
});
onCollide("player", "coin", (player, coin) => {
coin.destroy();
});
const player = level.get("player")[0];
onKeyPress("space", () => {
player.jump();
});
onKeyDown("right", () => {
player.move(256, 0);
});
onKeyDown("left", () => {
player.move(-256, 0);
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Kaboom</title>
<script src="https://unpkg.com/kaboom@3000.1/dist/kaboom.js"></script>
</head>
<body>
<script src="game.js"></script>
</body>
</html>