ArcLycée est un RPG 2D écrit en JavaScript vanilla (ES Modules) sans frameworks ni bundlers. Tout le rendu est réalisé avec HTML5 Canvas, les effets sonores sont générés par code avec Web Audio API, la musique de fond utilise des fichiers MP3 avec fondu enchaîné, et tous les sprites sont dessinés de manière procédurale.
| Métrique | Valeur |
|---|---|
| Fichiers JavaScript | 53 |
| Total de lignes de code | ~37 500 |
| Résolution du canvas | 960 × 540 px (16:9) |
| FPS cible | 60 |
| Langues supportées | 3 (Español, Français, English) |
| Clés de traduction | ~1 100+ |
| Effets sonores procéduraux | 60 méthodes |
| Mondes jouables | 12 + carte du monde |
| Mini-jeux | 4 (batú, calibration, programmation, câbles) |
| Répertoire | Contenu | Fichiers |
|---|---|---|
js/motor/ | Boucle de jeu, entrée, rendu, son, sauvegarde, configuration | 6 |
js/escenas/ | Menu principal, sélection du personnage, intro, cinématique finale | 4 |
js/mundos/ | 13 niveaux jouables : grottes, villages, montagne, colonial, aquatique, juridique, laboratoire, LFSD, lac, cenote, musée | 13 |
js/mecanicas/ | Combat, dialogue, inventaire, album photo, 4 mini-jeux, quêtes, réputation, journal | 11 |
js/personajes/ | Joueur (Pepito/Pepita) + 3 compagnons (Magnoboot, Viralata, Cemí) | 4 |
js/idiomas/ | Traductions ES/FR/EN + gestionnaire de langues | 4 |
js/mapas/ | Carte Leaflet avec couches de données réelles (taïno, colonial, naufrages, musées) | 4 |
js/clima/ | Système météo + ouragans | 2 |
| Technologie | Utilisation |
|---|---|
| HTML5 Canvas | Rendu du jeu — tout est dessiné par code, aucun sprite externe |
| JavaScript ES Modules | Architecture modulaire sans frameworks ni bundlers |
| Web Audio API | 60 effets sonores procéduraux + musique de fond avec 24 MP3 |
| LeafletJS + Stadia Maps | Cartes interactives avec 76 sites archéologiques réels de RD et Haïti |
| Kaplay.js | Entrée tactile (joystick analogique et D-pad) |
| CSS3 | Écran de chargement, contrôles tactiles responsive |
velocidadJugador), fonctions (estaPresionada), constantes (ANCHO_JUEGO)Fichier : js/motor/juego.js (1 659 lignes) — l'orchestrateur principal du jeu.
Le jeu tourne à ~60 FPS grâce à requestAnimationFrame.
Chaque image calcule le delta time et exécute deux phases : mise à jour (logique) et dessin (rendu).
Le delta time est plafonné à 0,1 seconde pour éviter la « téléportation » du joueur lorsqu'il revient d'un autre onglet :
dt = Math.min((currentTime - previousTime) / 1000, 0.1)
Le jeu possède 15 scènes enregistrées. Une seule scène est active à la fois.
| Type | Scènes |
|---|---|
| Interface | Menu principal, sélection du personnage, cinématique d'intro, cinématique finale |
| Mondes jouables (9) | Grottes de Pomier, Asentamiento I, Asentamiento II, La Isabela, Zone Coloniale, Monde Aquatique, Aéroport, Laboratoire, LFSD |
| Navigation | Carte du monde (carte en tuiles) |
| Secret | Sélecteur de niveaux (Code Konami) |
Chaque scène implémente trois méthodes :
iniciar(juego) — initialisation lors de l'entrée dans la scèneactualizar(dt, entrada, jugador, companeros) — logique par image (mouvement, collisions, IA)dibujar(renderizador, ancho, alto, textos, jugador, companeros) — rendu visuel
Les changements de scène utilisent juego.cambiarEscena('nom'), qui appelle salir() sur la scène précédente,
crée le joueur si la nouvelle scène est jouable, et appelle iniciar(juego) sur la nouvelle.
Le retour à la carte du monde déclenche la sauvegarde automatique.
Les couches superposées sont dessinées par-dessus la scène active, dans cet ordre (de bas en haut) :
juego.mostrarToast(texte, durée) ajoute un message flottant. Ils s'empilent verticalement
(max 4), avec un fondu de 0,3 s à l'apparition et dans la dernière seconde. Utilisé pour la collecte d'objets,
l'achèvement des quêtes, les alertes de danger, etc.
Quand le joueur atteint 0 point de vie : son comique « wah wah waaah », message de mort aléatoire (4 s),
pause de 2,5 s, puis réapparition sur la carte du monde avec 30 % de vie restaurée.
Un drapeau _muerteEnCurso empêche de déclencher la mort plusieurs fois.
Fichier : js/motor/entrada.js (494 lignes) — couche d'abstraction unifiée pour clavier et tactile.
| Action | Touches | Utilisation |
|---|---|---|
| Se déplacer | ZQSD / Flèches | Exploration et menus |
| Sauter | Espace | Grottes uniquement (plateforme) |
| Interagir | E / Entrée | Parler aux PNJ, utiliser des objets |
| Inventaire | I | Ouvrir/fermer le sac à dos |
| Spécial | F | Détecteur de métaux (Magnoboot) |
| Retour à la carte | M | Quitter le niveau en cours |
| Carte réelle | R | Ouvrir la carte Leaflet de référence |
| Journal | L | Journal de jeu (quêtes) |
| Photo | T | Photographier une entité proche |
| Selfie | G | Selfie avec une entité |
| Album | P | Consulter la galerie photo |
| Zoom | + / - | Zoom sur la carte du monde |
| Code Konami | ↑↑↓↓←→←→ | Sélecteur de niveaux secret |
Toutes les requêtes d'entrée passent par entrada.estaPresionada(action), qui combine clavier et tactile.
En interne, deux objets Map sont utilisés : teclasPresionadas pour le clavier et accionesTocadas pour le tactile.
Deux modes commutables depuis le menu Options (préférence sauvegardée dans localStorage) :
5 boutons d'action à droite : A (action), B (annuler), X (inventaire), Y (spécial), SAUT.
Utilise touchstart/touchend au lieu de click pour éviter le délai de 300 ms sur mobile.
Pour empêcher une touche de se « répéter » quand elle est maintenue, un drapeau bloqueoEntrada est utilisé :
activé lors du traitement de l'action et désactivé uniquement au relâchement de la touche.
Initialisé à true en entrant dans les scènes où la touche d'activation pourrait être enfoncée.
L'événement window.blur efface toutes les touches enfoncées. Cela empêche le joueur de
continuer à se déplacer en revenant d'un autre onglet avec une touche de mouvement maintenue.
Fichier : js/motor/renderizado.js (199 lignes) — wrapper Canvas 2D.
Résolution fixe de 960×540 (moitié de 1080p, facile à agrandir). Le lissage d'image est désactivé
(imageSmoothingEnabled = false) pour conserver la netteté du pixel art.
| Méthode | Description |
|---|---|
limpiar() | Efface l'image précédente avec clearRect |
dibujarRectangulo() | Rectangle plein (collisions, placeholders) |
dibujarTexto() | Texte avec police, couleur et alignement configurables |
dibujarBarra() | Barre de progression avec pourcentage limité à [0, 1] et bordure noire |
aplicarFiltroCueva(playerX, playerY, lightRadius) crée un effet de torche grâce à un
dégradé radial avec un centre transparent et des bords opaques :
Les mondes aquatiques utilisent un minuteur _sacudida qui, lorsqu'il est activé (par collision avec une vedette,
morsure de requin ou méduse), applique une oscillation horizontale au sprite du joueur :
ctx.translate(Math.sin(totalTime * 50) * amplitude * intensity, 0) // intensity = _sacudida / initialDuration (décroît linéairement)
Dans les mondes aquatiques, les entités (PNJ, tortues, méduses, joueur) sont triées par leur coordonnée Y avant le dessin, créant un effet de profondeur naturel où les objets proches recouvrent les plus éloignés.
Fichier : js/motor/sonido-procedural.js (1 931 lignes) — 60 effets sonores générés par code.
Les effets sonores sont synthétisés en temps réel en combinant des oscillateurs (sinusoïdal, carré, dent de scie, triangle), des filtres (passe-bas, passe-haut, passe-bande), des tampons de bruit blanc et des enveloppes de gain. La musique de fond est lue depuis des fichiers MP3 avec fondu enchaîné automatique.
Les navigateurs bloquent Web Audio jusqu'à la première interaction utilisateur.
_asegurarContexto() crée l'AudioContext uniquement à la première utilisation.
La plupart des sons utilisent un balayage de fréquence (rampe exponentielle ou linéaire) pour créer une sensation de mouvement :
osc.frequency.setValueAtTime(startFreq, now) osc.frequency.exponentialRampToValueAtTime(endFreq, now + duration)
Contrôle le volume dans le temps : attaque rapide → maintien → décroissance exponentielle vers le silence.
Généré en remplissant un tampon avec des valeurs aléatoires (-1 à 1), puis filtré pour créer différentes textures : pas (passe-bas 800 Hz), étincelles (passe-haut 2000 Hz), foule (passe-bande 600 Hz).
Un oscillateur basse fréquence (4-30 Hz) module un autre paramètre (généralement la fréquence principale) pour créer du vibrato, du wobble ou des sirènes :
lfo.frequency.value = 4 // wobble à 4 Hz lfoGain.gain.value = 8 // profondeur de modulation ±8 Hz lfo → lfoGain → osc.frequency
| Méthode | Technique | Description |
|---|---|---|
salto() | Carré 150→400 Hz | Saut du joueur |
aterrizar() | Sinusoïdal 100→40 Hz | Atterrissage |
recoger() | Deux notes carrées (523, 659 Hz) | Collecte d'objet |
paso() | Bruit blanc 40 ms, passe-bas 800 Hz | Pas |
goteo() | Sinusoïdal 800→240 Hz, aléatoire | Goutte d'eau |
dano() | Dent de scie 200→50 Hz | Dégât générique |
muerte() | Trois notes descendantes en dent de scie avec LFO | Comique « wah wah waaah » |
| Méthode | Description |
|---|---|
combateAtacar() | Dent de scie agressive 400→100 Hz |
combateHablar() | Deux sinusoïdales simultanées (300, 350 Hz), paisible |
combateNegociar() | Deux notes carrées alternées avec pause |
combateRedesSociales() | Deux « ding-ding » sinusoïdaux (notification téléphone) |
combateProtestas() | Trois impulsions carrées (rythme de slogan de manifestation) |
combateDenuncia() | Bruit + sinusoïdal 150→60 Hz (tampon officiel) |
combateViaLegal() | Triangle 180→90 Hz (marteau de juge) |
combateAtrapar() | Bruit passe-bande 1200 Hz (filet de pêche) |
combatePescar() | Sinusoïdal 200→800 Hz + bruit passe-bas (harpon + éclaboussure) |
combateProtegerCoral() | Accord majeur chaleureux à trois notes |
combateAlertarBuzos() | Carré 700 Hz avec LFO 8 Hz (sifflet sous-marin) |
combateLey318() | Triangle 200→100 Hz (coup de marteau judiciaire) |
combateEvidenciaForense() | Deux bips sinusoïdaux (caméra/scanner) |
combateInterpol() | Carré 600→800→600 Hz (bip de sirène de police) |
combateUnesco() | Accord majeur solennel (autorité diplomatique) |
combateVictoria() | Arpège ascendant triomphal |
combatePacificado() | Accord majeur soutenu 0,5 s (paix atteinte) |
| Méthode | Description |
|---|---|
batuGolpe() | Triangle 120→60 Hz (impact balle sur pierre) |
batuRebote() | Sinusoïdal 300→150 Hz (rebond caoutchouc) |
batuPunto() | Arpège ascendant à trois notes (point marqué) |
batuSaque() | Sinusoïdal 600→800 Hz (coup de sifflet de service) |
batuMultitud() | Bruit blanc passe-bande 600 Hz (rugissement de foule) |
| Méthode | Description |
|---|---|
cantoBallenaCerca() | Trois longues notes sinusoïdales avec LFO individuel, passe-bas 600 Hz (vocalisation de baleine à bosse) |
manatiLlamada() | Sinusoïdal 80→120→90→110 Hz oscillant (appel ondulant du lamantin) |
lanchaImpacto() | 3 couches : impact triangle 200→40 Hz + éclaboussure de bruit + cri de Wilhelm synthétique (dent de scie avec LFO 30 Hz) |
mordidaTiburon() | 3 couches : craquement de mâchoire (bruit passe-haut 3000 Hz) + impact profond + grognement avec LFO 12 Hz |
| Méthode | Description |
|---|---|
calibracionTono(freq) | Sinusoïdal à la fréquence donnée, 0,2 s |
calibracionExito() | Arpège majeur ascendant (4 notes) |
calibracionFallo() | Deux impulsions descendantes en dent de scie |
calibracionAjuste() | Bruit passe-haut 2000 Hz, 20 ms (clic de molette) |
bloqueColocar() | Carré 800→400 Hz + bruit (bloc enclenché) |
bloqueQuitar() | Sinusoïdal ascendant 300→600 Hz (bloc retiré) |
robotMoverse() | Dent de scie modulée 120→180→120 Hz (servomoteur) |
robotExito() | Arpège triomphal en carré à 4 notes |
robotFallo() | Deux bips carrés descendants |
cableConectar() | Sinusoïdal 1200→600 Hz + bruit de contact |
cableError() | Dent de scie + bruit passe-haut 3000 Hz (étincelle électrique) |
circuitoCompleto() | Sinusoïdal exponentiel + triangle (mise sous tension du circuit) |
robotFLLIniciar() | Dent de scie continue avec ronronnement de moteur (démarrage du robot FLL à chenilles) |
robotFLLDetener() | Arrête le moteur avec fondu sortant progressif (arrêt du robot FLL) |
robotFLLClick() | Clic mécanique court (inutilisé actuellement) |
| Méthode | Description |
|---|---|
dialogo() | « Bleep » carré rapide 380±40 Hz (caractère de texte style Undertale) |
fotoCaptura() | Bruit 0,08 s + carré 1200→300 Hz (obturateur + clic mécanique) |
selfieCaptura() | Bruit 0,06 s + sinusoïdal ascendant 400→1200 Hz (obturateur + flash) |
lluviaAmbiente() | Boucle continue : bruit filtré + gouttes périodiques toutes les 150-350 ms |
js/motor/musica.js)
La classe SistemaMusica gère la musique de fond du jeu à l'aide de fichiers MP3.
Contrairement aux effets sonores (procéduraux), la musique utilise 24 fichiers audio réels
organisés en 12 groupes thématiques (2 pistes par groupe).
| Groupe | Scène(s) | Description |
|---|---|---|
menu | menuPrincipal | Musique du menu principal |
cuevas | cuevasPomier | Ambiance de grottes |
taino | Mondes taïnos (villages) | Musique indigène |
colonial | Mondes coloniaux | Époque coloniale |
acuatico | Monde Aquatique | Ambiance sous-marine |
aeropuerto | Monde Juridique | Aéroport de Punta Cana |
museo | Monde Laboratoire | Intérieur de musée |
lfsd | LFSD | Salle de robotique |
mapa | mapaPrincipal | Carte du monde |
creditos | finalCinematica | Cinématique finale et crédits |
Chaque groupe possède 2 pistes (A et B). Lorsqu'une piste se termine, le système effectue un fondu enchaîné
de 2 secondes vers l'autre piste, créant une boucle continue sans silence (A → B → A → B...).
Les deux pistes utilisent HTMLAudioElement et le volume est interpolé linéairement pendant la transition.
Lorsqu'un combat ou une partie de batú commence, la musique de fond est temporairement mise en pause. À la fin de l'overlay, la musique du scénario est automatiquement restaurée.
Le volume de la musique (0-100 %) se configure depuis le menu Options.
La préférence est sauvegardée dans localStorage sous la clé arclycee_volumen_musica
et restaurée au démarrage du jeu.
Les navigateurs bloquent la lecture automatique de l'audio jusqu'à la première interaction utilisateur. Si la tentative de lecture initiale échoue, le système réessaie automatiquement lorsque la première pression de touche est détectée dans le menu principal.
Fichier : js/mecanicas/combate.js (932 lignes) — combat au tour par tour style Undertale avec voie pacifiste.
Le combat dans ArcLycée n'est pas un échange de dégâts traditionnel. L'objectif est de convaincre l'ennemi par des actions diplomatiques. Deux jauges émotionnelles :
Chaque ennemi peut avoir des opcionesPersonalizadas — un tableau d'actions uniques avec des
plages aléatoires de patience/hostilité et des contre-réponses spécifiques :
| Ennemi | Options | Étiquette |
|---|---|---|
| Constructor Méndez | Réseaux sociaux, Manifestations, Dénonciation, Voie légale | « Convaincu : » |
| Poisson-lion | Capturer, Pêcher, Protéger le corail, Alerter les plongeurs | « Contrôlé : » |
| Rodrigo Torres | Loi 318, Preuves médico-légales, INTERPOL, UNESCO 1970 | « Preuves : » |
4 types de sprites dessinés de manière procédurale : _dibujarSoldado(), _dibujarConstructor(),
_dibujarPezLeon(), _dibujarTraficante(). Chacun avec un design et une animation uniques.
Lorsque le joueur choisit d'attaquer et a des compagnons actifs, un sous-menu apparaît demandant « Avec qui attaquez-vous ? » avec les options : Solo / Magnoboot +3 / Viralata +2 / Cemí +4. Navigation avec les flèches (haut/bas), E pour confirmer, Q pour annuler et revenir au menu principal de combat.
Un overlay basculable avec la touche H qui explique les objectifs du combat, les différences entre la voie pacifiste et la voie agressive, la signification des jauges (patience, hostilité, vie) et les récompenses de réputation selon le type de victoire.
Texte dynamique indiquant qui a l'avantage dans le combat. Change selon les valeurs de patience et d'hostilité : « Presque convaincu », « Très hostile », « En progression », « Situation tendue ».
Les messages d'action du joueur et les contre-attaques de l'ennemi s'affichent pendant 2,5 secondes. Ensuite, un bouton pulsant [E] Continuer apparaît, que le joueur doit presser pour passer au tour suivant.
Pour les ennemis ayant des opcionesPersonalizadas, la barre de vie de l'ennemi est masquée.
Ces ennemis se battent par conviction (patience = 100), pas par dégâts de vie.
Victoire pacifiste = +15 réputation. Victoire par la force = +5. De plus, la réputation actuelle du joueur
confère un avantage initial : initialPatience = min(reputation / 2, 25).
Fichier : js/mecanicas/dialogo.js (326 lignes) — moteur de dialogue avec effet machine à écrire.
Les caractères apparaissent un par un. Un compteur _caracteresVisibles s'incrémente à chaque image,
et le texte affiché est text.substring(0, Math.floor(characters)). Chaque caractère déclenche
un « bleep » de dialogue (son procédural).
Les lignes de dialogue peuvent inclure opciones: [{texto, valor}]. Quand des options sont présentes,
l'avancement est bloqué jusqu'à ce que le joueur en sélectionne une (↑↓ pour naviguer, E pour confirmer).
alTerminar permet d'enchaîner des événements après la fin d'un dialogue : lancer un combat,
donner un objet, découvrir une quête, etc.
Les PNJ mentors (Roberto Cassá, Lcda. Carmen Vidal) utilisent un compteur qui s'incrémente après chaque conversation.
L'indice est calculé comme counter % array.length pour boucler indéfiniment sur les sujets.
Répertoire : js/personajes/companeros/ — trois compagnons qui suivent le joueur à travers les scènes.
Tous partagent : une propriété tipo (chaîne), un drapeau activo,
des méthodes activar()/desactivar(), et un mouvement par interpolation linéaire (lerp)
pour un suivi fluide au lieu d'une téléportation.
| Nom | Type | Capacité | Facteur Lerp | Position Relative |
|---|---|---|---|---|
| Magnoboot | Robot excavateur | Détecteur de métaux (touche F), excavation (coûte 10 énergie) | 0,05 | À droite du joueur (+30, +5) |
| Viralata | Chien pisteur | Flair (rayon 50 px), remue la queue quand des objets sont détectés | 0,06 | À gauche du joueur (-25, +10) |
| Cemí Murciélago | Esprit des grottes | 6 niveaux de pouvoir débloqués avec des botijas (écho-location → vision cemí) | 0,08 | En haut à gauche (-20, -25) avec flottement sinusoïdal |
Les compagnons persistent entre les scènes via juego.companeros[]. Dans les sauvegardes, ils sont sérialisés comme
{tipo, activo} et reconstruits avec _crearCompaneroBasico(tipo, activo).
Fichier : js/mecanicas/inventario.js (742 lignes) — sac à dos visuel avec grille de 20 emplacements.
Grille de 5 colonnes × 4 lignes. Chaque emplacement mesure 52×52 px avec 4 px de marge. Le panneau est centré sur le canvas.
Navigation avec les flèches, utilisation de l'objet avec E (si esUsable).
| Objet | Soin | Source |
|---|---|---|
| Guanábana | +30 PV | Guarionex (Asentamiento II) |
| Vasija curativa | +35 PV | Anacaona (Asentamiento I) |
| Casabe | +25 PV | Divers |
Plus de 24 icônes uniques dessinées avec Canvas 2D : torche avec rayons lumineux, cemí doré avec yeux,
boussole avec aiguilles rouge/blanche, arquebuse coloniale, pièce avec couronne, etc.
_dibujarIconoObjeto(ctx, id, x, y, size) dispatche vers l'icône correcte selon l'ID.
Fichier : js/mecanicas/album-fotos.js (1 140 lignes) — système de capture avec rendu dédié par type d'entité.
Le champ tipoEntidad détermine quel moteur de rendu utiliser. Les scènes exposent un
tableau fotografiables[] pour les entités supplémentaires au-delà des PNJ :
| tipoEntidad | Moteur de rendu | Détail |
|---|---|---|
'npc' | _renderizarNPCCentrado() | Dessine le PNJ sur un canvas auxiliaire 200×200, détecte la boîte englobante par pixels, recadre et centre |
'tortuga' | _renderizarTortuga() | 4 sprites dédiés : imbriquée (olive avec rayures ambrées), luth (bleu-noir avec 7 crêtes), caouanne (brun-rouge avec marque en cœur), verte (olive avec taches) |
'coral' | _renderizarCoral() | 4 sprites : cerveau (hémisphère avec sillons sinueux), corne de cerf (5 branches bifurquées), éventail (violet-rose avec nervures radiales), table (plateforme elliptique sur tronc) |
'petroglifo' | _renderizarPetroglifo() | 4 types : soleil, chauve-souris, visage, spirale |
'objeto' | _renderizarObjeto() | Objet de collection générique avec lueur |
La détection de la cible photo utilise la distance euclidienne avec un rayon de 80 px (RANGO_FOTO).
La recherche s'effectue d'abord parmi les PNJ, puis les objets, puis les fotografiables[].
Fichier : js/mundos/mapa-tiles.js (784 lignes) — génération procédurale de terrain pour l'île.
Le littoral d'Hispaniola est défini avec ISLA_BITMAP : un tableau de 68 chaînes de 128 caractères chacune.
Chaque caractère est '1' (terre) ou '0' (eau). Tracé manuellement à partir d'une image de référence NASA,
mis à l'échelle 2× depuis un bitmap original de 64×34.
DEEP_WATERISLA_BITMAP| Type | Praticable | Décoration |
|---|---|---|
| Eau profonde | Non | Courbes de vagues animées |
| Eau peu profonde | Oui | Écume |
| Sable | Oui | Texture granuleuse |
| Prairie | Oui | — |
| Forêt | Oui | Couronnes d'arbres (cercles) |
| Montagne | Non | Triangles avec sommets rocheux |
| Rivière | Oui | Lignes de courant animées |
| Chemin | Oui | — |
Les rivières sont tracées en reliant des points de passage avec l'algorithme de Bresenham. Seules les tuiles déjà terrestres sont peintes (les tuiles d'eau sont ignorées), créant des rivières qui coulent naturellement le long du terrain.
8 chaînes de montagnes définies comme des séquences de points de passage. Pour chaque tuile terrestre, la distance minimale à chaque segment de chaîne est calculée. Si elle est inférieure à 3,6 tuiles, la tuile devient une montagne (non praticable).
dibujarTilesVisibles() ne rend que les tuiles situées dans le champ de la caméra,
en calculant les colonnes et lignes de début et de fin. Cela est crucial pour les performances étant donné que la carte fait
128×68 = 8 704 tuiles au total.
Fichier : js/mundos/mapa-principal.js (809 lignes) — navigation entre les nœuds de niveau.
13 nœuds placés à des coordonnées de tuiles praticables vérifiées. Chacun possède : un ID, une position, un type (grotte, village, ville, naufrage, etc.), une scène de destination, et le nœud précédent dans la chaîne de progression.
Affichage : cercle (18-22 px) + bordure + icône emoji + nom. Les couleurs indiquent l'état :
gris (verrouillé), or (actif), vert (complété). Un indicateur doré pulsant [E] apparaît quand le joueur est à proximité.
Coin supérieur droit (120×75 px). Affiche des tuiles simplifiées (pas de 2 pour les performances), les nœuds colorés par état, la position du joueur et le champ de la caméra.
_puedeMoverse() teste les 4 coins du sprite (avec 4 px de marge)
par rapport au esCaminable() de la carte en tuiles.
Fichiers : js/mundos/acuatico/mundo-acuatico.js (2 174 lignes)
+ santuario-manati.js (2 905 lignes).
| Condition | Facteur de Vitesse |
|---|---|
| Normal (sous l'eau) | × 0,7 |
| Avec effet de méduse | × 0,4 |
| Avec effet de requin | × 0,4 (durée 2 s) |
4 méduses avec mouvement sinusoïdal entre deux points de passage :
t = (sin(phase + dt*0.8) + 1) / 2 → lerp entre pointA et pointB.
Contact (rayon 15-20 px) = 5 PV de dégâts + 2,5 s de lenteur + 2 s d'invulnérabilité.
Math.sinLe joueur nage en apnée avec un tuba. Barre d'O₂ de 100 à 0 :
3 requins patrouillent entre des points de passage avec décalage de phase (0, π/2, π).
Morsure : -8 PV + 2 s de lenteur + effet de secousse (0,5 s) + son mordidaTiburon().
Apparition toutes les 5-15 s dans la zone de surface. Collision : -10 PV + secousse (0,6 s) + cri de Wilhelm synthétique
(lanchaImpacto()). La zone d'hélice cause des dégâts périodiques (-2 PV avec intervalle).
Notification d'avertissement affichée une seule fois par entrée dans la zone.
Fichiers : js/clima/clima.js (442 lignes) + huracan.js (324 lignes).
| État | Probabilité | Intensité | Effet sur le Joueur |
|---|---|---|---|
| Ensoleillé | 45 % | 0,1 | Aucun |
| Nuageux | 25 % | 0,3 | Aucun |
| Pluie | 20 % | 0,6 | Vitesse × (1 − 0,15×i) |
| Orage | 7 % | 0,8 | Vitesse × (1 − 0,25×i) + tonnerre |
| Ouragan | 2 % | 1,0 | Poussée du vent 2px×i + vitesse × (1 − 0,35×i) |
| Tremblement de terre | 1 % | — | 2 % de chance de trébucher par image |
Jusqu'à 500 particules recyclées. Taux d'apparition : 3-8 particules/image selon l'intensité. Chaque particule subit la gravité + la poussée du vent.
Catégories 1-5 avec vitesse du vent = catégorie × 2 px/image. Trois phases : début (0-25 %, intensité croissante) → pic (25-75 %, intensité maximale) → fin (75-100 %, intensité décroissante). Physique des débris avec jusqu'à 500 objets rebondissant sur le terrain. Direction : typiquement depuis l'est (réaliste pour les Caraïbes).
Pluie continue (lluviaAmbiente()) avec intensité dynamique pendant les transitions.
Tonnerre aléatoire toutes les 4-15 s pendant les orages.
Fichier : js/mundos/lfsd/mundo-lfsd.js — niveau intérieur de la salle de robotique du Lycée Français de Saint-Domingue.
Le Prof. Nicolas Droulers (cheveux blancs et barbe blanche) guide le joueur.
La salle contient des tables de travail avec des écrans de programmation Scratch, un tableau,
une imprimante 3D avec une étiquette traduite selon la langue active,
et une table FIRST LEGO League avec des chemins noirs de suivi de ligne
où un robot LEGO animé à chenilles suit les pistes avec un son de moteur (robotFLLIniciar/robotFLLDetener).
9 PNJ étudiants (3 donneurs de quêtes avec des T-shirts de couleur) et 4 postes de travail.
Fichier : js/mecanicas/batu.js (935 lignes) — physique 2D avec IA adaptative.
| Paramètre | Valeur |
|---|---|
| Gravité | 480 px/s² |
| Coefficient de rebond (sol) | 0,8 |
| Coefficient de rebond (murs) | 0,9 |
| Friction de l'air | 0,998 par image |
| Rayon de la balle | 8 px |
| Condition de victoire | Premier à 3 points |
| Zone | Partie du corps | Vitesse | Angle |
|---|---|---|---|
| < 25 % | Tête | 290 px/s | -70° (quasi vertical) |
| 25-50 % | Épaule | 425 px/s | -60° |
| 50-75 % | Hanche/yugo | 500 px/s (max) | -45° (le plus puissant) |
| > 75 % | Genou | 280 px/s | -30° (défensif) |
Chaque frappe a une variation de ±25 % en vitesse et ±8° en angle pour l'imprévisibilité.
Entre chaque point, un fait historique sur le batú est affiché : matériau de la balle (latex de l'arbre cupey), pétroglyphes du batey, le yugo cérémoniel, les festivals areíto, la résolution pacifique des conflits, et des sites archéologiques réels (Chacuey, La Aleta).
intro → service → jeu → point → éducation → service → ... → finPartie
Fichier : js/mecanicas/calibracion-senal.js (330 lignes) — puzzle d'oscilloscope.
3 cadrans (fréquence, amplitude, phase) contrôlant une onde sinusoïdale affichée sur un oscilloscope (vert sur noir). Le joueur doit reproduire l'onde cible avec une tolérance de ±15 %.
y = centerY + sin(t + phase) × amplitude where t = (x − 40) / (width − 80) × π × 2 × frequency
↑↓ pour changer de cadran, ←→ pour ajuster (±2), E pour confirmer. Limite de temps : 45 secondes.
Récompense : magnétomètre calibré (progreso.magnetometroCalibrado = true), +15 réputation.
Fichier : js/mecanicas/programacion-bloques.js (491 lignes) — navigation par blocs.
Disposer 5-6 blocs d'instructions (avancer, tourner à gauche/droite, scanner, plonger, remonter) pour guider un robot sous-marin à travers une grille 6×4. Le robot commence à (0,1) face à droite, cible à (5,2).
Max 12 blocs. Intervalle d'exécution : 0,6 s entre les étapes. Échec : le robot sort de la grille ou percute un obstacle (s'il n'est pas immergé). Phase de programmation : 60 s. Exécution : automatique, sans limite de temps.
Récompense : couche de sites archéologiques sur la carte Leaflet (progreso.robotProgramado = true), +15 réputation.
Fichier : js/mecanicas/conexion-cables.js (408 lignes) — puzzle d'appariement sur un circuit imprimé.
Connecter 6 entrées (gauche) à 6 sorties (droite) par couleur et symbole. Sorties en ordre aléatoire. Les connexions sont dessinées sous forme de courbes de Bézier cubiques. Mauvaise connexion = animation d'étincelle.
↑↓ pour sélectionner l'entrée/sortie, E pour connecter. Limite de temps : 30 secondes.
Récompense : +15 réputation (bonus +5 si complété en moins de 15 s), article de journal dans l'inventaire.
Fichier : js/mecanicas/reputacion.js (74 lignes) — score de 0 à 100 avec 4 niveaux.
| Plage | Niveau | Couleur de la Barre |
|---|---|---|
| 0-24 | Inconnu | Rouge |
| 25-49 | Connu | Jaune |
| 50-74 | Respecté | Vert |
| 75-100 | Légendaire | Or |
La réputation affecte le combat (bonus de patience initial) et s'affiche dans l'épilogue final. Gagnée par les victoires pacifistes (+15), les victoires par la force (+5), les mini-jeux (+15 chacun) et les actions écologiques (+10).
Fichier : js/mecanicas/misiones-secundarias.js (89 lignes) — machine à états par quête.
| Quête | Description | Déclencheur |
|---|---|---|
| Batú | Jouer au jeu de balle taïno avec Higüemota | Parler à Higüemota dans l'Asentamiento II |
| Sauvetage du Lamantin | Libérer le lamantin + nettoyer le récif | Parler à la Dra. Sofía dans le Sanctuaire |
| Bonnes Vibrations | Calibrer le magnétomètre | Parler à un PNJ à La Isabela |
| Full Metal Archeologist | Programmer le robot sous-marin | Parler au biologiste dans le Sanctuaire |
| Weird Science | Réparer l'équipement d'analyse | Parler au mentor dans le Laboratoire |
Chaque quête progresse : non_découverte → découverte → en_cours → complétée.
Le Journal de jeu (touche L) affiche tous les états de quête dans deux onglets :
Histoire Principale (13 nœuds avec ✅/🔓/🔒) et Quêtes Secondaires (avec coches).
Fichier : js/motor/guardado.js (243 lignes) — persistance par localStorage.
Le jeu sauvegarde automatiquement en revenant à la carte du monde. « Continuer la partie » dans le menu principal restaure tout l'état et renvoie à la carte.
Les compagnons sont sauvegardés comme {tipo: 'magnoboot', activo: true} et reconstruits
en instances réelles via _crearCompaneroBasico(tipo, activo) en utilisant les imports Magnoboot,
Viralata et CemiMurcielago.
Répertoire : js/mapas/ (4 fichiers, ~700 lignes) — carte géographique réelle avec sites archéologiques.
Centre : 19,0°N, -70,5°O (République Dominicaine). Zoom par défaut : 8. S'ouvre avec la touche R depuis n'importe quelle scène jouable (pas seulement la carte du monde). Tuiles Stadia Maps (6 couches esthétiques : Watercolor, Terrain, Toner, Dark, Smooth, OSM Bright) avec CARTO Voyager en solution de repli.
| Couche | Icône | Nombre |
|---|---|---|
| Sites taïnos | 🗿 | 16 (asentamientos, grottes, pétroglyphes en RD et Haïti) |
| Sites coloniaux | 🏰 | 8 (La Isabela, Zone Coloniale, Cap-Haïtien, etc.) |
| Naufrages | ⚓ | 12 (Santa María 1492, San Miguel 1551, Concepción 1641, etc.) |
| Musées | 🏛 | 30 (RD + Haïti) |
| Sites inexplorés | 🔍 | 8 (visibles uniquement après le mini-jeu du robot) |
Marqueurs avec popup (nom + description) au clic.
Voyage au clic : window._viajarANodo(id) pour un vol animé et changement de scène.
État visuel : complété (bordure verte + luminosité), verrouillé (niveaux de gris + opacité 0,4), actif (bordure blanche).
Fichier : js/escenas/final-cinematica.js (673 lignes) — 5 fins + générique cinématographique.
| Fin | Condition | Titre |
|---|---|---|
| Complète | 8 nœuds + 7 quêtes secondaires + plus de pacifiés que de violents | « Légende de Quisqueya » |
| Pacifiste | 8 nœuds + plus de pacifiés, aucun violent | « Gardien du Patrimoine » |
| Écologique | 3+ actions écologiques + aucune violence | « Protecteur de l'Écosystème Marin » |
| Sombre | Plus de combats violents que de pacifiés | « Le patrimoine mérite un autre chemin » |
| Musée | Solution par défaut | « Conservateur de l'Histoire » |
5 étapes de texte avec avancement automatique (5-6 s chacune), saut avec E. Fonds thématiques par fin : dégradés dorés (complète/pacifiste), bleu marin avec bulles (écologique), rouge avec fractures (sombre), chaleureux avec point lumineux (musée). Niveau de réputation affiché dans l'épilogue.
Défilement vertical automatique à 40 px/s. Liste des 8 créateurs (les fous du robot), le Liceo Francés de Santo Domingo et l'année 2026. E pour accélérer/sauter.
Répertoire : js/idiomas/ (4 fichiers, ~4 400 lignes).
3 fichiers de traduction (es.js, en.js, fr.js) avec ~1 100+ clés chacun,
organisés en objets JavaScript imbriqués. Un gestionnaire idiomas.js (73 lignes) fournit :
cambiarIdioma(code) — bascule entre 'es', 'fr', 'en't(key) — accès par notation pointée : t('dialogos.cueva.petroSol')| Section | Contenu |
|---|---|
menu | Titres, options du menu principal |
seleccion | Sélection du personnage |
interfaz | HUD (vie, oxygène, inventaire), phrases de mort (10 variantes) |
dialogos | Tous les dialogues par monde (grotte, village, isabela, colonial, aquatique, juridique, laboratoire, LFSD, fins) |
combate | Actions et messages de combat |
batu | 25 clés de mini-jeu (règles, faits, messages) |
objetos | 32+ objets avec nom et description |
inventario | Interface de l'inventaire |
clima | Noms des états météorologiques |
guardado | Chaînes du système de sauvegarde |
// Dans les scènes et mécaniques :
const texts = juego.idiomas.traducciones[juego.idiomas.idiomaActual];
const name = texts.menu.titulo;
// Ou avec l'accesseur par notation pointée :
const text = juego.idiomas.t('dialogos.cueva.petroSol');
Fichier : js/personajes/pepito.js (258 lignes).
| Propriété | Valeur |
|---|---|
| Dimensions | 28×32 px (plus étroit que la tuile de 32 px pour un passage plus facile) |
| Vie maximale | 100 PV |
| Genre | 'pepito' (masculin) ou 'pepita' (féminin) |
Les jambes s'animent avec Math.sin(cuadroAnimacion * 5) * 3 — un mouvement sinusoïdal
simulant les pas. Les bras avec Math.sin(cuadroAnimacion * 2) * 1.
L'animation n'avance que quand esAnimando = true.
js/escenas/seleccion-personaje.js (291 lignes) : le sprite du jeu est affiché en échelle ×2,5
avec animation de marche en direct. Pepito est bleu (#4488ff) avec des cheveux en pétard ; Pepita est violette (#aa44ff) avec des tresses.
Fichier : js/motor/configuracion.js (95 lignes) — point de configuration central.
| Constante | Valeur | Utilisation |
|---|---|---|
ANCHO_JUEGO | 960 | Largeur du canvas en pixels |
ALTO_JUEGO | 540 | Hauteur du canvas (16:9) |
TAMANO_TILE | 32 | Taille standard d'une tuile |
GRAVEDAD | 0,6 | Accélération verticale en mode plateforme |
VELOCIDAD_JUGADOR | 3 | Pixels par image |
FPS_OBJETIVO | 60 | Images par seconde |
ESCALA_MINIMA | 0,5 | Échelle minimale du canvas |
ESCALA_MAXIMA | 3,0 | Échelle maximale du canvas |
CLAVE_GUARDADO | 'arclycee_guardado' | Clé localStorage |
| Type | Largeur × Hauteur |
|---|---|
| Joueur | 32 × 32 |
| Compagnon | 24 × 24 |
| Cemí | 16 × 16 |
| PNJ | 32 × 32 |
| Boss | 64 × 64 |
| Grand Boss | 96 × 96 |
| Objet | 16 × 16 |
| Pétroglyphe | 48 × 48 |
| # | Fichier | Lignes | Responsabilité |
|---|---|---|---|
| 1 | santuario-manati.js | 2 905 | Sanctuaire : oxygène, requins, vedettes, écologie |
| 2 | mundo-acuatico.js | 2 174 | Naufrage : méduses, tortues, baleines, combat |
| 3 | sonido-procedural.js | 1 931 | 60 effets audio générés par code |
| 4 | zona-colonial.js | 1 923 | Zone Coloniale : PNJ, combat, activisme |
| 5 | juego.js | 1 659 | Boucle de jeu, scènes, couches, notifications |
| 6 | es.js | 1 523 | Traductions espagnoles |
| 7 | fr.js | 1 472 | Traductions françaises |
| 8 | en.js | 1 408 | Traductions anglaises |
| 9 | cuevas-pomier.js | 1 340 | Plateforme en grotte avec effet de torche |
| 10 | mundo-juridico.js | 1 335 | Aéroport : combat juridique, INTERPOL |