@cedric-pouilleux/galexjs

Deterministic procedural galaxy board — runs on Node, vanilla Three.js, and Vue/TresJS.
1,543
Install
npm install @cedric-pouilleux/galexjs
Latest Version:0.4.0
Vue:3
License:Custom
Last Updated:Jun 8, 2026
Links: GitHub  ·  npm
Maintainer: cedric-pouilleux

GalexJS

Génération procédurale déterministe d'un plateau galactique. Une lib, trois cibles :

  • Backend Node — pure data, ni Three, ni DOM.
  • Vanilla Three.js — factories impératives qui montent les couches dans un THREE.Group.
  • Vue 3 + TresJS — composable réactif + composant drop-in <GalaxyScene>.

Pour le même (seed, opts), la lib produit des Float32Array byte-à-byte identiques sur V8, SpiderMonkey et JavaScriptCore. Donc le serveur (Node) et le client (Chrome / Firefox / Safari) voient la même galaxie sans payload de structure sur le réseau — seules les actions joueur transitent.

Pourquoi déterministe

Les jeux multi avec carte massive partagent traditionnellement la map en envoyant un dump des positions / cubes / contenus à la connexion. Avec GalexJS le serveur dérive la map depuis (seed, opts) ; le client la dérive aussi côté navigateur, à partir du même seed reçu en plaintext. Tous les bytes sont identiques cross-engine, donc :

  • Pas de protocole de sync pour la structure du monde
  • Validation serveur sans recharger d'état (le serveur reconstruit le cube cible à la volée)
  • Anti-triche trivial : si le client envoie un (cube, star) qui n'existe pas sur le seed, le serveur le sait

La compatibilité cross-engine repose sur de la math transcendante bit-stable (detSin, detCos, detPow…) auditée par un linter statique + un test hash byte-à-byte exécuté en CI sur Chromium / Firefox / WebKit.

Installation

npm install @cedric-pouilleux/galexjs three
# Pour la cible Vue / TresJS :
npm install vue @tresjs/core

three, vue et @tresjs/core sont des peer dependencies. Vue et TresJS sont optionnelles (consommées uniquement par view-vue/).

Usage par cible

Backend Node — pure data

import { createGalaxyData } from '@cedric-pouilleux/galexjs/sim';

const galaxy = createGalaxyData({ seed: 42, count: 15000, radius: 50 });

// Valider une action joueur sans charger d'état persistant.
const cube = galaxy.grid.get(action.cube.i, 0, action.cube.k);
if (!cube) return { ok: false, reason: 'cube does not exist' };
if (!cube.starIndices.includes(action.starIndex)) {
  return { ok: false, reason: 'star not in this cube' };
}
return { ok: true };

Vanilla Three — scène montée à la main

import * as THREE from 'three';
import { createGalaxyData, createGalaxyScene } from '@cedric-pouilleux/galexjs/core';

const galaxy = createGalaxyData({ seed: 42, count: 15000, radius: 50 });
const view = createGalaxyScene(galaxy, { gasDensity: 1.0 });
scene.add(view.object3D);

// Per-frame controls :
view.setDimming(0.5);                              // dim global (close-up)
view.setGasDim(0.45);                              // dim gaz seul (plan view)
view.setHaloVisible(false);                        // halo doux (fog of war)
view.setCoreVisible(false);                        // noyau galactique (fog of war)
view.setOrthoSize(zoom);                           // sprite size en mode ortho
view.setClipping(true, normal, point);             // plan de clipping monde
view.setVisibilityField({ focals: [cube], range: 3 });  // brouillard multi-focal

Vue / TresJS — déclaratif

<script setup lang="ts">
import { TresCanvas } from '@tresjs/core';
import { createGalaxyData, GalaxyScene } from '@cedric-pouilleux/galexjs';

const galaxy = createGalaxyData({ seed: 42, count: 15000, radius: 50 });
</script>

<template>
  <TresCanvas window-size clear-color="#04060b">
    <TresPerspectiveCamera :position="[0, 70, 70]" :look-at="[0, 0, 0]" make-default />
    <GalaxyScene :galaxy-data="galaxy" :gas-density="1.0" />
  </TresCanvas>
</template>

⚠️ Côté vite.config.ts, brancher la conf TresJS sinon <TresCanvas> est rendu comme un custom HTML element vide :

import { templateCompilerOptions } from '@tresjs/core';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue(templateCompilerOptions)],
});

Le sandbox

npm run dev lance le playground complet. Il sert d'exemple de référence : tout est composé à partir des primitives lib, aucun concept de jeu n'est codé dedans.

Geste / mode Effet
Clic gauche dans le vide + drag Rotation orbite
Clic droit + drag Rotation orbite (alternative)
Clic gauche sur un cube + drag Sélection rectangulaire multi-cubes (cf. RectSelection)
Clic court sur un cube Close-up sur le cube
Relâcher d'un rectangle Close-up sur tous les cubes contenus dans le rectangle (champ d'étoiles fusionné)
Molette Zoom
Esc Sortir du close-up
Espace (en mode mesure) Cadre sur le trajet courant — dim tout le reste (cf. MeasureTool / Focus trajet)
Toggle « Brouillard de guerre » Active le visibility-field multi-focal + masque halo + noyau galactique
Toggle « Vue plateau 2D » Bascule en caméra orthographique vue de dessus
Toggle « Mesurer une distance » Active le MeasureTool — cube↔cube en orbite, étoile↔étoile en close-up
Panneau « Génération » Régénère la galaxie avec d'autres options (count, bras, étalement, gaz, …)

La galaxie reste toujours centrée (enablePan = false sur les OrbitControls) — le pan est désactivé exprès pour éviter qu'elle dérive hors champ.

Architecture

core/           # Pure data, déterministe, sans Three
  GalaxyData      # Pipeline principal seed → buffers + grid
  CubeGrid        # Indexation spatiale + raycast Amanatides & Woo
  Astronomy       # Conversion world units ↔ années-lumière
  Random          # mulberry32 + dérivation de subseeds par label
  DetMath         # Math transcendantes bit-stables (sin, cos, log, exp, pow)
  Visibility      # Helper de calcul de fog of war

view/           # Vanilla Three — couches visuelles
  GalaxyScene     # Compose tout (stars + halo + gaz + bulbe), expose les contrôles
  CubeMarker      # Marqueur cube pour le concept "joueur" / "flotte" du client
  GridHelper      # Wireframes (occupied lines, visibility tiers)
  closeup/        # Sous-buffer + shader haute fidélité pour la vue rapprochée
  effects/        # Halo, nébuleuses, arm glow, gas streaks, inner ring, center dust

view-vue/       # Vue + TresJS
  composables/    # useGalaxyView (réactif), useGalaxyLayers (déclaratif)
  components/     # <GalaxyScene> drop-in

playground/     # Sandbox de démo (consomme les briques ci-dessus)
  Main.ts, Cameras, Picker, RectSelection, MeasureTool, Fog, PlanView, Closeup…

tools/          # CLI utilitaires
  CheckDeterminism  # Lint statique : interdit Math.sin/cos/etc dans core/
  server-example    # Exemple de validation serveur Node

docs/           # VitePress

Garanties

  • Déterminisme cross-engine : audité par tools/CheckDeterminism.ts (lint statique sur core/) + tests Node + Playwright sur Chromium / Firefox / WebKit.
  • TypeScript strict : tout le repo passe vue-tsc --noEmit.
  • Domaine jeu hors lib : aucun identifiant player / team / fleet / fog of war dans core/, view/, view-vue/. Les primitives sont neutres ; le client jeu compose ses concepts par-dessus (cf. primitives/).
  • Vocabulaire de plateau : cube, grid, world, marker, highlight, selection, hover, visibility, focal, range, closeup, plan view.

Scripts

npm run dev               # Playground vanilla Three
npm run example:server    # Exemple backend Node (validation déterministe)
npm run build             # Build de production (Vite)
npm test                  # typecheck strict + lint déterminisme + 72 tests
npm run test:cross        # Hash determinism sur Chromium / Firefox / WebKit
npm run docs:dev          # Site VitePress en hot-reload
npm run docs:build        # Build statique des docs

Documentation

Trois entry points publiés

Import Surface Dépendances runtime
@cedric-pouilleux/galexjs/sim Données pures déterministes (génération, grid, RNG, math bit-stable, visibilité, pathfinding) aucune
@cedric-pouilleux/galexjs/core /sim + couche Three.js (scène, layers, effets, closeup, paths) three
@cedric-pouilleux/galexjs /core + composables Vue + composant <GalaxyScene> three, vue, @tresjs/core

Publication

npm run build         # vite build (JS) + vue-tsc (.d.ts) + assemblage dist/package.json
npm run publish:dist  # npm publish ./dist

Le package.json source omet volontairement le champ exports pour que les imports relatifs continuent de résoudre vers la source pendant le dev. C'est le script scripts/prepare-dist.mjs qui écrit un dist/package.json publish-ready avec la map d'exports complète.

Licence

Tous droits réservés — voir le fichier LICENSE. Le package est publié sur npm pour faciliter la distribution, mais aucune licence d'usage n'est accordée par défaut.

Related Packages

genshin-world

Genshin Impact's world as a fan recreation: the catalogue of regions and areas,...

649 23
endset_three_editor

A 3D model editor built with Three.js and Vue 3

22,133
three-bg

基于Threejs的背景组件,目前仅支持8Vue3

1,793
@eleven.spectacles/virtual-try-on

Nuxt module: virtual try-on for 3D eyewear over a live camera feed (MediaPipe +...

1,646 0

Version History

Version Released Vue License
0.4.0 ^3.5.0 Custom
0.3.0 ^3.5.0 Custom
0.2.0 ^3.5.0 Custom
0.1.1 ^3.5.0 Custom
0.1.0 ^3.5.0 Custom