Prompt utilisé pour régénérer cette page :
Page: Materia - Tower Defense with Rune Crafting
Title: "Tower Defense"
Description: "Strategic tower defense with A* pathfinding, elemental damage types, and upgrade trees"
Icon: castle
Tags: strategy, pathfinding, game
Status: new
Category: games
Front matter: no js/scss keys (uses default convention)
HTML structure in index.md:
<section class="container visual size-800 ratio-1-1 canvas-contain">
<!-- War view -->
<div class="td-view td-view-war is-active">
<canvas id="td-canvas"></canvas>
</div>
<!-- Shop view (display:none) -->
<div class="td-view td-view-shop" style="display:none">
div.td-shop-header (h4 "Shop" + span.td-shop-gold "0g")
div.td-shop-modal-grid#td-shop-grid (populated by JS)
</div>
<!-- Craft view (display:none) -->
<div class="td-view td-view-craft" style="display:none">
div.td-craft-modal-header (h4 "Craft")
div.td-craft-slots: 3 slots (A + B = C pattern)
<button data-craft-slot="a" class="td-rune">A</button>
<span class="td-craft-plus">+</span>
<button data-craft-slot="b" class="td-rune">B</button>
<span class="td-craft-plus">=</span>
<button data-craft-slot="c" class="td-rune">C</button>
div.td-craft-actions:
<button data-craft-action="fuse" class="td-action-btn" disabled>Fuse (3->1)</button>
<button data-craft-action="craft" class="td-action-btn" disabled>Craft (2->1)</button>
<button data-craft-action="autofuse" class="td-action-btn">Auto-Fuse</button>
div.td-craft-result (display:none)
h5 "Inventory" + span.td-craft-inv-count.td-inv-count "0/64"
div.td-craft-modal-inv-grid#td-craft-inv-grid (populated by JS)
</section>
Widget files:
_nav.before.md (weight: 10, title: "Navigation", _build: render: never):
nav.td-nav[role="tablist"] with 3 tab buttons:
<button class="td-nav-tab is-active" data-view="war">War</button>
<button class="td-nav-tab" data-view="shop">Shop</button>
<button class="td-nav-tab" data-view="craft">Craft</button>
_controls.right.md (weight: 20, title: "Controls"):
div.td-controls[role="group"]:
<button id="btn-play" class="item button is-play"> {{< icon name="play" >}}
<button id="btn-pause" class="item button is-pause"> {{< icon name="pause" >}}
<button id="btn-reset" class="item button"> {{< icon name="refresh" >}}
<button id="btn-next-wave" class="item button" title="Skip to next wave (N)"> {{< icon name="chevron-double-right" >}}
<select id="td-speed">: 1x, 2x, 3x
<select id="td-mode">: Baby, Easy, Normal (selected), Hard, Nightmare, Endless
<select id="td-map">: Valley, Crossroads, Fortress, Maze, Islands, Arena
div.td-tower-select[role="group"]:
##### Bases
3 base type buttons (data-base="light/medium/heavy"):
Light: 40g, 3 slots, hotkey 1
Medium: 90g, 4 slots, hotkey 2
Heavy: 160g, 5 slots, hotkey 3
Each: <kbd class="td-hotkey">{N}</kbd> + .td-tower-icon.{type} + name + .td-cost + .td-slots
div.td-inventory#td-inventory:
##### Inventory <span id="td-inv-count" class="td-inv-count">0/64</span>
div#td-inv-grid.td-inv-grid (populated by JS)
_info.right.md (weight: 30, title: "Tower Info"):
div.td-info#td-info (display:none initially):
##### Selected Tower
<dl> with 6 dt/dd pairs: Base (#info-type), HP (#info-hp), Weapons (#info-weapons),
DPS (#info-dps), Kills (#info-kills), Targeting (#info-targeting, default "First")
div.td-rune-slots#td-rune-slots: h6 "Rune Slots" + div#rune-slot-list.td-slot-grid
div.td-info-actions:
<button id="btn-repair" class="td-action-btn" style="display:none">Repair (<span id="info-repair-cost">-</span>g)</button>
<button id="btn-sell" class="td-action-btn sell">Sell (<span id="info-sell-value">-</span>g)</button>
_help.after.md (title): Help section explaining gameplay
_algorithm.after.md (title): Algorithm explanation (A* pathfinding, tower mechanics)
Architecture (18 JS modules + SCSS):
default.js — Game orchestrator (IIFE, ES module imports):
Imports: panic, Pathfinding, { GameMap, MAPS, CELL }, { TowerFactory, BASE_TYPES },
{ RuneFactory }, Inventory, Shop, { EnemyFactory, ENEMY_TYPES }, Obstacle,
Projectile, EffectPool, WaveManager/{ GAME_MODES }, WeatherManager,
AchievementManager, { cachedColors, cacheColors, getBaseColor, getWidth, getHeight, render },
{ setupControls, selectTowerType, updateInfoPanel, updateTowerButtons,
updateControlState, updateShopPanel, updateInventoryPanel, switchView },
Entity, Craft
CONFIG: gridWidth=20, gridHeight=20, canvasWidth=800, canvasHeight=800,
startingGold=200, startingLives=20, respiteDelay=5
Game modes: NORMAL, BOSS, ENDLESS
Core loop: requestAnimationFrame-based with: updateEnemies -> updateTowers -> updateProjectiles -> updateEffects -> updateWeather -> render
_pathfinding.lib.js: A* pathfinding on grid, path caching, obstacle-aware
_map.lib.js: GameMap class, MAPS registry (valley/crossroads/fortress/maze/islands/arena), CELL enum (EMPTY/PATH/TOWER/SPAWN/BASE/OBSTACLE)
_tower.lib.js: TowerFactory + BASE_TYPES (light/medium/heavy with different HP, cost, rune slot counts)
_rune.lib.js: RuneFactory, rune system for tower augmentation (elements, damage modifiers)
_inventory.lib.js: Inventory management (64 slots max)
_shop.lib.js: Shop system for purchasing towers/runes with gold
_enemy.lib.js: EnemyFactory + ENEMY_TYPES, movement along path, HP, armor, speed, rewards
_obstacle.lib.js: Obstacle class + EnemyTurret (enemy-placed obstacles that attack towers)
_projectile.lib.js: Projectile class (tracking, AoE, damage types)
_effect.lib.js: EffectPool for visual effects (explosions, hits, buffs, pooled for performance)
_wave.lib.js: WaveManager + GAME_MODES (baby/easy/normal/hard/nightmare/endless), wave composition, escalation
_weather.lib.js: WeatherManager, environmental effects on gameplay (affects tower/enemy stats)
_achievement.lib.js: AchievementManager, milestone tracking
_renderer.lib.js: Canvas rendering — cachedColors, cacheColors(), getBaseColor(), getWidth/getHeight(), render() (grid, path, towers with rune indicators, enemies, projectiles, effects, weather overlay)
_input.lib.js: Input handling — setupControls(), selectTowerType(), updateInfoPanel(), updateTowerButtons(), updateControlState(), updateShopPanel(), updateInventoryPanel(), switchView() (war/shop/craft)
_entity.lib.js: Base entity class shared by towers/enemies/projectiles
_craft.lib.js: Crafting system — fuse (3 same runes -> 1 higher tier), craft (2 different runes -> 1 combined), auto-fuse
default.scss: Game-specific styles with .td-* prefix
View system: .td-view with display toggling via switchView()
Nav tabs: .td-nav with .td-nav-tab, .is-active
Controls: .td-controls flex row, button/select styling
Tower select: .td-tower-select with .td-tower-btn (hotkey + icon + name + cost + slots)
Inventory: .td-inv-grid CSS grid, rune slot coloring
Info panel: .td-info with <dl> grid, rune slots display, action buttons (repair/sell)
Shop: .td-shop-modal-grid layout
Craft: .td-craft-slots (A+B=C layout), action buttons, result display
Canvas: td-canvas full size within container
Important implementation notes:
- All lib files are ES modules with named exports
- Canvas 800x800 with DPR scaling
- Grid: 20x20, cell size = 40px
- A* pathfinding recalculated when towers placed/removed
- 3 views (war/shop/craft) toggled by switchView() — unlike grimoire which has 4 views
- Tower bases: light (40g, 3 rune slots), medium (90g, 4 slots), heavy (160g, 5 slots)
- Rune system: runes inserted into tower base slots for elemental/damage augmentation
- Craft: fuse 3 same -> 1 higher tier, craft 2 different -> 1 combined, auto-fuse convenience
- Inventory: 64 slots max (vs grimoire's 32)
- Weather system affects gameplay (unique to materia, not in grimoire)
- Enemy turrets (obstacle.lib.js) can attack towers (unique to materia)
- Keyboard hotkeys: 1/2/3 for tower base selection, N for next wave
- Starting gold: 200g, starting lives: 20
- 6 maps, 6 difficulty modes (same as grimoire)
- Complex HTML in index.md (craft slots A+B=C not generated by JS)
- Uses /_lib/panic_v3.js for logging
Page entièrement générée et maintenue par IA, sans intervention humaine.