Skip to content

Développement API - Pierre Blarre

Les objets

Icône Présentation
1 / 1

La classe Balle

Plutôt que de manipuler directement le contexte du canvas, nous allons encapsuler les propriétés et les méthodes nécessaires pour gérer les balles dans une classe d’objet Balle.

Dans le fichier classes/Balle.mjs, ajoutez le code suivant :

Balle.mjs
import { Balles } from './Balles.mjs'; // Importe la classe Balles depuis le fichier Balles.mjs
export class Balle { // Définition de la classe Balle et exportation de la classe
/**
* Fonction constructeur de la classe Balle
*
* Si les paramètres x, y, velociteX, velociteY, rayon et couleur ne sont pas définis,
* ils sont initialisés avec des valeurs aléatoires
*
* @param { HTMLCanvasElement } canvas : Le canvas
* @param { CanvasRenderingContext 2D } context : Le contexte de rendu 2D du canvas
* @param { number } x : La position horizontale de la balle
* @param { number } y : La position verticale de la balle
* @param { number } velociteX : La vitesse de déplacement horizontale
* @param { number } velociteY : La vitesse de déplacement verticale
* @param { number } rayon : Le rayon de la balle
* @param { string } couleur : La couleur de la balle
* @returns { Balle } : Une instance de la classe Balle
*/
constructor(canvas, context, x, y, velociteX, velociteY, rayon, couleur) {
// Si le canvas ou le contexte de rendu 2D ne sont pas définis, on sort de la fonction
if (canvas === undefined || context === undefined) return;
this.canvas = canvas;
this.context = context;
this.x = x ? x : this.random(0, Balles.width);
this.y = y ? y : this.random(0, Balles.height);
this.rayon = rayon ? rayon : this.random(10, 20);
this.couleur = couleur ? couleur : this.randomRGB();
this.velociteX = velociteX ? velociteX : this.random(-7, 7);
this.velociteY = velociteY ? velociteY : this.random(-7, 7);
}
76 collapsed lines
/**
* Fonction qui génère un nombre aléatoire compris entre min et max
* @param { number } min : La valeur minimale
* @param { number } max : La valeur maximale
* @returns { number } : Un nombre aléatoire compris entre min et max
*/
random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
/**
* Fonction qui génère une couleur RGB aléatoire
* @returns { string } : Une couleur RGB aléatoire
*/
randomRGB() {
return `rgb(${this.random(0, 255)},${this.random(0, 255)},${this.random(0, 255)})`;
}
/**
* Fonction qui dessine la balle sur le canvas
*/
dessiner() {
this.context.beginPath();
this.context.fillStyle = this.couleur
this.context.arc(this.x, this.y, this.rayon, 0, 2 * Math.PI);
this.context.fill();
}
/**
* Fonction qui déplace la balle sur le canvas en fonction de sa vitesse
* Si la balle atteint un bord du canvas, sa vitesse est inversée
*/
deplacer() {
if ((this.x + this.rayon) >= Balles.width) { // Si la balle atteint le bord droit du canvas
this.velociteX = -(this.velociteX); // La vitesse horizontale est inversée
}
if ((this.x - this.rayon) <= 0) { // Si la balle atteint le bord gauche du canvas
this.velociteX = -(this.velociteX); // La vitesse horizontale est inversée
}
if ((this.y + this.rayon) >= Balles.height) { // Si la balle atteint le bord bas du canvas
this.velociteY = -(this.velociteY); // La vitesse verticale est inversée
}
if ((this.y - this.rayon) <= 0) { // Si la balle atteint le bord haut du canvas
this.velociteY = -(this.velociteY); // La vitesse verticale est inversée
}
// On modifie les positions horizontales et verticales en fonction de la vitesse, ce qui donnera l'illusion que la balle se déplace
this.x += this.velociteX;
this.y += this.velociteY;
}
/**
* Fonction qui vérifie si la balle est en collision avec une autre balle
*
* Si c'est le cas, la couleur des deux balles est modifiée avec une couleur aléatoire
*
* @param { Balle[] } balles : Un tableau contenant toutes les balles
*/
collision(balles) {
for (const ball of balles) {
if ((!(this.x === ball.x && this.y === ball.y && this.velX === ball.velX && this.velY === ball.velY))) {
const dx = this.x - ball.x;
const dy = this.y - ball.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.rayon + ball.rayon) {
ball.couleur = this.couleur = this.randomRGB();
}
}
}
};
}

Prenez un moment pour étudier le code de la classe Balle.

Notez que nous avons ajouté des méthodes pour dessiner la balle et pour la déplacer.

La classe Balles

Nous allons également encapsuler les balles dans une classe Balles.

Cette classe contiendra un tableau d’objets Balle et va gérer l’animation des balles.

Dans le fichier classes/Balles.mjs, ajoutez le code suivant :

Balles.mjs
import { Balle } from './Balle.mjs'; // Importe la classe Balle depuis le fichier Balle.mjs
export class Balles { // Définition de la classe Balles et exportation de la classe
static width = 0; // Propriété statique width initialisée à 0
static height = 0; // Propriété statique height initialisée à 0
/**
* Fonction constructeur de la classe Balles
*
* @param { HTMLCanvasElement } canvas : Le canvas
* @param { number } nombreBalles : Le nombre de balles à générer
* @param { number } width : La largeur du canvas
* @param { number } height : La hauteur du canvas
* @returns { Balles } : Une instance de la classe Balles
*/
constructor(canvas, nombreBalles, width, height) {
this.canvas = canvas; // Le canvas
this.context = canvas.getContext('2d'); // Le navigateur crée un contexte de rendu 2D pour le canvas
Balles.width = canvas.width = width; // La largeur du canvas est égale à la largeur de la fenêtre
Balles.height = canvas.height = height; // La hauteur du canvas est égale à la hauteur de la fenêtre
this.enMouvement = false; // La propriété enMouvement est initialisée à false. On utilisera cette propriété pour savoir si les balles sont en mouvement
this.animationRequest = null; // La propriété animationRequest est initialisée à null. On utilisera cette propriété pour stocker l'identifiant de la requête d'animation
this.context.fillStyle = 'rgba(0,0,0,0.25)'; // La couleur de remplissage est un gris semi-transparent
this.context.fillRect(0, 0, this.width, this.height); // Un rectangle semi-transparent est dessiné sur tout le canvas
this.balles = []; // Un tableau vide pour stocker les balles
for (let i = 0; i < nombreBalles; i++) {
this.balles.push(new Balle(this.canvas, this.context)); // On ajoute une nouvelle balle à chaque itération
}
90 collapsed lines
}
/**
* Getter de la propriété nombre
* @returns { number } : Le nombre de balles
*/
get nombreBalles() {
return this.balles.length;
}
/**
* Setter de la propriété width
* @param { number } value : La largeur du canvas
*/
set width(value) {
Balles.width = value;
this.canvas.width = value;
}
/**
* Setter de la propriété height
* @param { number } value : La hauteur du canvas
*/
set height(value) {
Balles.height = value;
this.canvas.height = value;
}
/**
* Fonction qui dessine les balles sur le canvas
* et gère les collisions entre les balles
* et les bords du canvas
*/
render() {
this.enMouvement = true; // On passe la propriété enMouvement à true
this.context.fillStyle = 'rgba(0,0,0,0.25)'; // La couleur de remplissage est un gris semi-transparent
this.context.fillRect(0, 0, Balles.width, Balles.height); // Un rectangle semi-transparent est dessiné sur tout le canvas
// Pour chaque balle dans le tableau balles
this.balles.forEach(balle => {
balle.dessiner(); // On dessine la balle
balle.deplacer(); // On déplace
balle.collision(this.balles); // On gère les collisions
});
// On stocke l'identifiant de la requête d'animation dans la propriété animationRequest
this.animationRequest = requestAnimationFrame(this.render.bind(this));
}
/**
* Fonction qui ajoute une nouvelle balle au canvas
* @param { number } x : La position horizontale de la balle
* @param { number } y : La position verticale de la balle
*/
ajouterBalle(x, y) {
this.balles.push(new Balle(this.canvas, this.context, x, y));
}
/**
* Fonction qui démarre l'animation des balles
*/
demarrer() {
if (this.enMouvement) return;
this.render();
}
/**
* Fonction qui arrête l'animation des balles
* en annulant la requête d'animation
* et en passant la propriété enMouvement à false
* pour indiquer que les balles ne sont plus en mouvement
*/
stop() {
if (!this.enMouvement) return;
cancelAnimationFrame(this.animationRequest);
this.enMouvement = false;
}
/**
* Fonction qui réinitialise le canvas
* en supprimant toutes les balles
* et en appelant la méthode render pour redessiner le canvas
*/
reinitialiser() {
this.balles.splice(0, this.balles.length);
this.render();
}
}

Prenez un moment pour étudier le code de la classe Balles.

Deuxième conclusion

Nous avons maintenant encapsulé les balles dans des classes d’objets Balle et Balles.

Cela nous permet de mieux organiser notre code et de le rendre plus lisible et maintenable.

Dans la prochaine partie, nous allons finaliser le programme principal et ajouter des interactions utilisateur.