Mon studio de développement d'expériences numériques.
Avec de vrais morceaux de codes, je conçoit des choses utiles - parfois et
d'autres moins inutiles - souvent.

Découvrez moi, mes articles, ou mes réalisations.

Créer un jeu vidéo - Journal de bord partie 1

Créer un jeu vidéo - Journal de bord partie 1

gamedev, javascript, threejs Publié le mar. 7 janv. 2025

Comme beaucoup de développeur·euse·s, j’ai un grand rêve dans ma to-do list : créer mon propre jeu vidéo. Mais attention, je ne parle pas d’un remake basique de Pong. Je parle d’un projet en 3D, avec des visuels bluffants et une histoire qui claque. Bon, d’accord, peut-être que je ne viserai pas aussi haut, mais l’idée reste de sortir un jeu complet, jouable, avec une boucle de gameplay satisfaisante, et surtout qui me plaise en tant que joueur.

J’ai déjà bricolé quelques prototypes et ébauches par-ci par-là, sans jamais aller au bout. Cette fois, je me lance pour de vrai, et pour garder la motivation, je compte partager mon avancement à travers une série de journaux de bord.

Il y a de fortes chances que ce projet ne voie jamais le jour, ou que les publications deviennent de plus en plus rares. Vous êtes prévenu·e·s !

Le projet

Comme je l’évoquais, mon objectif est de créer un RPG en 3D se déroulant dans un univers médiéval-fantastique. C’est un cadre qui me parle beaucoup : j’ai déjà une foule de références en tête et je possède même mon propre univers, puisque je masterise régulièrement des parties de jeu de rôle papier.

Côté gameplay, je compte partir sur un style « tacticle », autrement dit des combats au tour par tour sur une grille. Je ne vais pas entrer dans les détails pour le moment, j’y reviendrai dans de futurs articles. Mais pour donner un aperçu, on pourra incarner un personnage qui progresse en niveaux, dans la plus pure tradition du RPG : il y aura des quêtes, du loot et de l’exploration de donjons.

Et bien entendu, je ne me limiterai pas à un simple mode solo : le jeu sera multijoueur en ligne, car tant qu’à faire, autant ajouter un peu de complexité. De là à dire “MEUPORG”, il n’y a qu’un pas.

La technologie

Étant passionné par tout ce qui touche au web, il était évident pour moi de développer ce jeu directement dans un navigateur. Pour cela, je vais m’appuyer sur Three.js, une bibliothèque JavaScript spécialisée dans la 3D. Je ne suis pas un expert de Three.js, mais j’ai déjà expérimenté quelques projets, ce qui me met suffisamment à l’aise pour me lancer. En prime, j’ai la possibilité de m’appuyer sur la formation de Bruno Simon, Three.js Journey, qui est vraiment excellente.

Pour ce qui est du multijoueur, mon choix se porte sur Node.js, une technologie que je maîtrise bien et qui me semble adaptée tant sur le plan des performances que de la mise en place et de la scalabilité. D’autant plus que Node.js gère maintenant TypeScript de manière native, ce qui tombe à pic pour expérimenter un peu plus avec ce langage.

Direction artistique

Ah, voilà le point le plus délicat : je ne suis absolument pas graphiste, je ne sais pas dessiner, je ne sais pas modéliser et je ne sais pas texturer. Je pourrais toujours me débrouiller en récupérant des assets trouvés un peu partout sur Internet, mais j’ai deux craintes : d’une part, la difficulté de dénicher des éléments qui s’accordent bien entre eux; d’autre part, l’influence trop forte que ces assets pourraient avoir sur l’identité de mon jeu. En conséquence, pour commencer, je vais miser sur de jolis cubes disposés sur un beau damier.

Ceci dit, j’ai quand même une idée d’ensemble : j’adore le rendu low poly façon Valheim, et plus récemment j’ai été séduit par l’aspect « texture pixel » de Luma Island. De toute manière, l’aspect visuel n’est pas ma priorité immédiate. Je préfère me laisser la possibilité de peaufiner et faire évoluer la direction artistique au fur et à mesure que le projet avance.

Let’s coder

On ne va pas terminer cet article sans coder un petit quelque chose. On va commencer par créer la base d’une expérience 3D avec Three.js. Pour faire un scène 3D il va nous falloir :

Commençons pas initialiser le projet.

Initialisation du projet

On va aller à l’essentiel et créer un nouveau projet Vite. On va activer Typescript et installer Three.js.

npm create vite@latest my-game -- --template vanilla-ts
cd my-game
npm install three
npm install -D @types/three

Enfin on lance le serveur de développement.

npm run dev

Normalement, vous devez vous retrouver avec un début de projet démo. On va faire le ménage en supprimant ce qui ne sert pas et en vidant le fichier src/main.ts. Ensuite, on va créer notre première scène avec Three.js.

Première scène

On va commencer par importer Three.js et initialiser notre scène dans notre fichier src/main.ts.

import * as THREE from 'three'

const scene = new THREE.Scene()

Ensuite, on va créer un plan, un cube, une caméra et une lumière.

// En 3D les objets sont appelés Mesh (maillage)
// et sont composés d'une géométrie et d'un matériau (couleur, texture, etc.)
const planeGeometry = new THREE.PlaneGeometry(5, 5)
const planeMaterial = new THREE.MeshStandardMaterial({ color: 'greenyellow', side: THREE.DoubleSide })
const plane = new THREE.Mesh(planeGeometry, planeMaterial)
plane.position.y = -1 // On décale le plan pour qu'il soit en dessous de l'origine
plane.rotation.x = Math.PI / 2 // On le tourne pour qu'il soit horizontal
scene.add(plane) // On ajoute le plan à la scène

const cubeGeometry = new THREE.BoxGeometry()
const cubeMaterial = new THREE.MeshStandardMaterial({ color: 'darkorange' })
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial)
cube.position.set(0, 0, 2)
scene.add(cube)

// La caméra est un point de vue sur la scène,
// elle définit ce que l'on voit et comment on le voit (angle, distance de vue, etc.)
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5

// On ajoute une lumière ambiante pour éclairer la scène de manière uniforme
const ambientLight = new THREE.AmbientLight(0x404040)
ambientLight.intensity = 1
scene.add(ambientLight)

// Ensuite on ajoute une lumière directionnelle pour donner du relief à la scène
const light = new THREE.DirectionalLight(0xffffff, 2)
light.position.set(2, 2, 2)
scene.add(light)

Enfin, on va ajouter une boucle de rendu.

// On crée un renderer qui va afficher la scène dans le navigateur
const renderer = new THREE.WebGLRenderer()
// On définit la taille du rendu en fonction de la taille de la fenêtre
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement) // On ajoute le rendu à la page

// On crée une boucle de rendu pour animer la scène
function animate() {
  requestAnimationFrame(animate) // On demande au navigateur de rappeler la fonction animate à chaque frame

  cube.rotation.x += 0.01
  cube.rotation.y += 0.01

  renderer.render(scene, camera) // On affiche la scène du point de vue de la caméra
}

animate()

And voilà !

Il y aurait beaucoup à dire sur ce code, mais comme le sujet de l’article n’est pas l’apprentissage des bases de la 3D, je pense que l’extrait parle de lui-même. Pour info, je suis parti du code fourni dans la documentation officielle de Three.js, auquel j’ai ajouté quelques adaptations mineures.

On peut quand même souligner qu’avec Three.js, il est extrêmement simple de mettre en place une scène 3D. En revanche, le code tel qu’il est écrit ici est loin d’être optimal pour un projet plus ambitieux. Nous verrons dans de futurs articles comment structurer notre code afin de le rendre plus maintenable et évolutif.

Voilà pour ce premier journal de bord ! J’espère que vous avez apprécié et que vous êtes curieux·ses de découvrir la suite. Quant à moi, j’ai hâte de voir où tout cela va me mener.