cours n°12 · Découverte

L'ARPG multijoueur en navigateur

Un monde bâti, une base qui se souvient, un serveur qui répond, un websocket qui pousse — et tes deux joueurs dans le même navigateur.

~11 min7 stations
▶ vidéo🧩 exercices📄 cheat sheet

42 secondes · sous-titres Français inclus · 8.6 Mo

Les 7 trucs que tu vas savoir faire

Leçon 12 : L'ARPG multijoueur en navigateur

Regarde la leçon (42 s) : un monde bâti, une base qui se souvient, un serveur qui répond, un websocket qui pousse — quatre étapes, et ton ARPG tourne dans un onglet.

Bâtir le monde, case par case

Écris `cellule(x, y, sol)` : une case du monde — un Hash avec `"x"`, `"y"` et `"sol"` (ex: `"herbe"`). Le monde 8-bit commence par UNE case.

La base qui se souvient

Écris `charge(rows, id)` : lire la base — `rows` est un tableau de lignes Hash (avec `"id"`), renvoie LA ligne dont l'id vaut `id`, sinon `nil`. Sans ce lire, la partie recommence à zéro.

Le serveur répond aux routes

Écris `route(chemin)` : le petit routeur — `"/joueurs"` → `:joueurs` · `"/monde"` → `:monde` · `"/parties"` → `:parties` · tout autre chemin → `nil`. Le serveur ne fait QUE ça : un chemin, un symbole.

Le websocket diffuse les coups

Écris `evenement(msg)` : le serveur reçoit `msg` (un Hash avec `"type"`) — `"tire"` → `:inflige` · `"parle"` → `:diffuse` · tout autre type → `:ignore`. Le websocket ne fait que ça : type → action.

Livrer à BON acteur

Écris `remets?(element, acteur)` : un élément venu de la base porte `"pour"` (un id) et `"role"` (`"pnj"` ou `"joueur"`) ; l'acteur porte `"id"` et `"role"`. true SEULEMENT si l'id correspond ET le rôle correspond — au bon joueur, au bon PNJ.

Leçon 12 : OK

Sans aide : `transfert(rows, id, acteur)` — 1) cherche la ligne `id` dans la base `rows` (absente → `false`) · 2) livre seulement si `"pour"` == `"id"` de l'acteur ET `"role"` == `"role"` de l'acteur. Le reste, c'est `false`.

Partage la leçon

← tous les cours

📄 La feuille de chute

imprime-la, colle-la à ton écran, fais semblant que c'est ton idée

📄 Cheat sheet — L'ARPG multijoueur en navigateur (monde · base · flux · websocket)

Un ARPG 8-bit qui tourne dans un onglet, c'est 4 étapes : bâtir le monde, le retenir dans une base, répondre aux appels, pousser les coups — puis livrer chaque élément au BON acteur.

Les 4 étapes du trajet

case → base → route → websocket        (puis : livraison au bon acteur)
cellule()  charge()  route()  evenement()

1. Le monde : des cases, pas un moteur

def cellule(x, y, sol)
  { "x" => x, "y" => y, "sol" => sol }
end
cellule(2, 5, "herbe")   # => {"x"=>2, "y"=>5, "sol"=>"herbe"}

Le monde entier = un tableau de ces hashes (leçon 6 + leçon 8, revues). Le tileset vient après — d'abord les données.

2. La mémoire : la base qui se souvient

def charge(rows, id)
  rows.find { |r| r["id"] == id }   # la ligne… ou nil
end

Entre deux parties, la base est la seule chose qui survive à l'onglet. Tu charges, tu joues, tu sauves : trois appels, et le monde a une mémoire.

3. Le flux : un chemin, un symbole

case chemin
when "/joueurs"  then :joueurs
when "/monde"    then :monde
when "/parties"  then :parties
else nil                 # inconnu : le serveur dit non
end

Une requête n'est rien d'autre : le client crie un chemin, le serveur répond par un symbole (ou par nil — un 404 honnête).

4. Le websocket : type → action, poussé

case msg["type"]
when "tire"  then :inflige     # le serveur applique…
when "parle" then :diffuse     # …et RETRANSMET aux autres
else :ignore                   # pas du jeu : on jette
end

La différence avec la route : c'est le serveur qui parle en premier. Le socket reste ouvert, les coups partent à tout le monde en direct.

5. La livraison : au bon acteur, jamais « presque »

def remets?(element, acteur)
  element["pour"] == acteur["id"] && element["role"] == acteur["role"]
end

Un élément venu de la base porte sa destination (pour) et son public (role : "pnj" ou "joueur"). Les deux conditions — l'id seul livre au mauvais PNJ, le rôle seul livre au premier venu. C'est le && du tri multijoueur.

Le tour complet (ce que fait ton serveur par message)

def transfert(rows, id, acteur)
  el = rows.find { |r| r["id"] == id }   # 1. la base
  return false unless el                # 2. rien trouvé → rien ne part
  el["pour"] == acteur["id"] && el["role"] == acteur["role"]   # 3. bon destinataire
end

Base → recherche → double condition → livré. Cinq lignes de Ruby pour tout un back-end de MMO. (Le vrai, en plus : persistance, ids secrets, latence — mais la forme est celle-là.)

À ne plus jamais dire

  • "il faut un moteur de jeu pour faire un multijoueur" → une base, une route, un socket
  • "le serveur décide de tout" → il décide de CE QUI EST VRAI : la base dit qui a quoi
  • "websocket = magie temps réel" → un case/when sur les messages, poussé en boucle

SlopCourse Microduck — du slop au code propre.