feat: add Pokemon-style world mode with workshop integration

Two-mode game: explore a tile-based cyberpunk world, then enter
Workshop mode (the existing circuit editor) to craft components.

New modules (js/world/):
- sprites.js: programmatic pixel-art renderer (16x16 tiles, 3x scale)
- maps.js: tile-based map definitions (lab + town)
- worldState.js: player position, inventory, dialog, puzzle state
- worldRenderer.js: camera-following world renderer on shared canvas
- worldInput.js: WASD movement, E interaction, dialog system
- gameMode.js: central mode switcher (world ↔ workshop)

Changes to existing code:
- app.js: boots into world mode, registers circuit editor for workshop
- renderer.js: circuit draw loop now stoppable (start/stopCircuitLoop)
- index.html: added "Back to World" button for workshop mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-20 15:52:13 +01:00
parent bbde11dfc7
commit e4cf35701e
9 changed files with 1903 additions and 14 deletions

View File

@@ -1,22 +1,40 @@
// Entry point — initializes all modules
import { initRenderer } from './renderer.js';
// Entry point — initializes game (world + workshop modes)
import { initRenderer, resize } from './renderer.js';
import { initEvents } from './events.js';
import { initPuzzleUI } from './puzzleUI.js';
import { loadFromStorage, startAutoSave } from './saveLoad.js';
import { updateComponentButtons } from './components.js';
import { evaluateAll } from './gates.js';
import { startGame, registerCircuitEditor, enterWorldMode } from './world/gameMode.js';
document.addEventListener('DOMContentLoaded', () => {
initRenderer();
initEvents();
initPuzzleUI();
// Register circuit editor init/destroy so gameMode can switch to workshop
registerCircuitEditor(
// init workshop
() => {
initRenderer();
initEvents();
initPuzzleUI();
if (loadFromStorage()) {
updateComponentButtons();
evaluateAll();
}
startAutoSave(3000);
},
// destroy workshop (cleanup when switching back to world)
() => {
// Auto-save is fine to leave running
}
);
// Restore previous session from localStorage
if (loadFromStorage()) {
updateComponentButtons();
evaluateAll();
// Add back-to-world button handler
const backBtn = document.getElementById('back-to-world-btn');
if (backBtn) {
backBtn.addEventListener('click', () => {
enterWorldMode();
});
}
// Auto-save every 3 seconds + on page unload
startAutoSave(3000);
// Start the game in world mode
startGame();
});