Programmation de Jeux Vidéos avec Canvas

Depuis que j’ai tapé mes premières lignes de code il y a maintenant une bonne quinzaine d’années l’idée de pouvoir faire un jeu moi même à régulièrement traîné dans ma tête. Pour tout dire, mes premières ligne de C/C++ se sont faites vraiment à l’arrache en modifiant des valeurs de variables dans le SDK de Half Life en suivant des tutos et des conseils sur Half Life Design (les vrais auront une grosse pointe de nostalgie).

Ayant tout appris par moi même, il m’a fallu énormément de temps pour absorber et comprendre les bases de la programmation. J’ai donc toujours assez vite déchanté en m’approchant ne serait-ce qu’un poil de l’idée de créer un jeu vidéo.

Moi en relisant mes vieux posts sur des vieux forums

D’ailleurs si je devais relire des posts de forums ou je déclarais vouloir faire le prochain MMORPG révolutionnaire, sans avoir une once de connaissance dans le sujet. A mon avis j’irais vite me cacher.

Les temps ont changés, j’ai appris, les technologies permettent beaucoup plus de choses que par le passé. On va donc reprendre les choses depuis le début.

Keep it simple

Je vais pas alourdir les choses en promettant de faire un projet de malade, cet article est le premier d’une série d’articles qui me serviront de carnet de route, de partage de connaissance. On gardera les choses simples et je me lancerai dans la programmation de jeux déjà connus tels que Pong, Mario, Snake, Sokoban, Pac Man, etc. (restons old school)

Pour rester dans la simplicité, je choisi le langage Javascript, d’abord parce que je le connais et je le pratique, parce qu’il est cross-platform (il suffit d’un bon browser) et qu’on peut autant faire du backend, du front end, du desktop, de la programmation réseau avec les websocket, etc.
Bref, un vrai couteau suisse, avec évidemment ses contraintes et limites.

Je n’ai pas la prétention de vouloir faire des tutos structurés, où on apprend tout de A à Z, je pense que beaucoup de sites sont vraiment bien mieux foutu et beaucoup plus sérieux que ce que je comptes partager ici (OpenClassRoom, Udemy pour ne citer qu’eux).

Avec un bon café et un peu de temps pour se détendre, je pense que c’est comme ça que j’imaginerais les lecteurs de ces articles.

Codons un peu

Fichier index.html :

<!DOCUMENT>
<html>
    <head></head>
    <body>
        <script src="game.js"></script>
    </body>
</html>

Fichier game.js :

// Création de l'élément Canvas
const canvas = document.createElement("canvas");
// Création du contexte
const ctx = canvas.getContext('2d');

// Initialisation de l'élément Canvas
canvas.id     = "game"; // On lui donne un ID
canvas.width  = 500;    // Une largeur
canvas.height = 500;    // Une hauteur

// Injection de l'élément Canvas
document.body.appendChild(canvas);

// On peut dessiner, création d'un carré rempli
ctx.fillRect(50, 50, 100, 100);

L’initialisation du Canvas est simple et permet de définir le contexte de travail. Le Contexte permettra de définir une utilisation simple du navigateur avec un contexte 2D simple, ou si l’on souhaite exécuter des tâches plus complexes avec un contexte utilisant la librairie WebGL qui donne accès aux ressources matérielle de la carte graphique.

L’idéal c’est de pouvoir définir l’ensemble de l’initialisation du canvas directement dans le code Javascript, je suis pas super fan du HTML pour être franc, moins j’en écrit, mieux je me porte. Je préfère laisser gérer ça par le code JS.

Penser à une mini lib réutilisable directement

Bon, comme je compte m’atteler à faire plusieurs jeux, il est intéressant de penser à la réutilisation des fondations histoire de pas recopier le code sans arrêt. Par exemple, en créant une classe Engine, qui permettra de tout configurer directement :

fichier engine.js :

/**
 * Une classe Engine permet d'initialiser le canvas quand on veut
 * et rend le code réutilisable
 */
class Engine {
    constructor(id, width, height, context) {
        // Création de l'élément Canvas
        const canvas = document.createElement("canvas");
        // Création du contexte
        const ctx = canvas.getContext(context || '2d');

        // Initialisation de l'élément Canvas
        canvas.id     = id     || "game"; // On lui donne un ID
        canvas.width  = width  || 500;    // Une largeur
        canvas.height = height || 500;    // Une hauteur

        // Injection de l'élément Canvas
        document.body.appendChild(canvas);

        this._canvas = () => {
            return canvas;
        };

        this._ctx = () => {
            return ctx;
        };
    }
}

Les fichier index.html et game.js se transforment alors :

Fichier index.html

<!DOCUMENT>
<html>
    <head>
        <script src="engine.js"></script>
    </head>
    <body>
        <script src="game.js"></script>
    </body>
</html>

Fichier game.js

// On créé le moteur, gestionnaire du canvas.
const myEngine = new Engine("game", 500, 500, '2d');
// On récupère le contexte
const ctx      = myEngine._ctx();

// Et on dessine
ctx.fillStyle = 'red';
ctx.fillRect(50, 50, 100, 100);

A noter également, qu’on peut créer plusieurs Canvas à la suite étant donné qu’on est dans le cas d’utilisation d’une classe 🙂
Par la suite évidemment il sera intéressant de discuter avec notre Engine pour lui demander de dessiner ce qu’on veut et selon des configurations simple.

Il y a toute une panoplie de méthodes permettant de dessiner des lignes, des points, des triangles, des ellipses, des carrés, des formes vectorielles, etc.
Un début de moteur 2D doit pouvoir donc offrir des raccourcis et proposer des méthodes qui facilite l’utilisation du Canvas.

Mais bon, ce sera pour la prochaine fois 😉