Creature Collection
Gemma 4 12b qat · full

Reviews & generation details
Reviews
Human review · Jul 17, 2026 · rubric 1
Historical path-based review. Association with these exact bytes is unverified.
- Visual design
- 3 / 5
- UX / feel
- 2 / 5
- Works
- 2 / 5
- Prompt spirit
- 2 / 5
- Delight
- 1 / 5
Generation context
Imported historical artifact. Its exact original instructions and lineage are not known.
Generation prompt · exact text unavailable
See the current prompt for reference. It may differ from the instructions used to generate this artifact.
Inspect original source 32,495 bytes · SHA-256 a75b4fff7e76
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Binding</title>
<style>
:root {
--bg-color: #0a0a0f;
--panel-bg: rgba(20, 20, 35, 0.8);
--accent-color: #70a1ff;
--text-color: #e0e0e0;
--border-color: rgba(255, 255, 255, 0.1);
--glass-bg: rgba(255, 255, 255, 0.05);
--font-main: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
--type-lumina: #ff7f50;
--type-umbra: #8a2be2;
--type-verdant: #32cd32;
--type-forge: #cd7f32;
--type-current: #00ffff;
--type-aeon: #ffffff;
--type-flux: #ff00ff;
}
* { margin: 0; padding: 0; box-sizing: border-box; user-select: none; }
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-main);
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
}
#game-container {
position: relative;
width: 100%;
height: 100%;
max-width: 1200px;
max-height: 800px;
border: 2px solid var(--border-color);
background: #000;
overflow: hidden;
}
canvas {
display: block;
image-rendering: pixelated;
}
/* UI Overlays */
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.75);
backdrop-filter: blur(8px);
z-index: 100;
}
.hidden { display: none !important; }
/* Menus */
.menu-card {
background: var(--panel-bg);
padding: 2rem;
border-radius: 15px;
border: 1px solid var(--border-color);
text-align: center;
max-width: 500px;
width: 90%;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
animation: fadeIn 0.5s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
h1 { font-size: 3rem; margin-bottom: 1rem; letter-spacing: 4px; color: var(--accent-color); text-shadow: 0 0 10px var(--accent-color); }
p { margin-bottom: 2rem; line-height: 1.6; }
button {
padding: 0.8rem 2rem;
font-size: 1.1rem;
background: transparent;
border: 1px solid var(--accent-color);
color: var(--accent-color);
border-radius: 5px;
cursor: pointer;
transition: all 0.3s;
margin: 0.5rem;
}
button:hover {
background: var(--accent-color);
color: #fff;
box-shadow: 0 0 15px var(--accent-color);
}
/* HUD */
#hud {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
pointer-events: none;
display: flex;
justify-content: space-between;
z-index: 50;
}
.hud-item {
background: var(--glass-bg);
padding: 5px 15px;
border-radius: 20px;
border: 1px solid var(--border-color);
pointer-events: auto;
}
/* Battle UI */
#battle-ui {
position: absolute;
bottom: 0;
width: 100%;
height: 30%;
background: linear-gradient(transparent, rgba(0,0,0,0.9));
padding: 20px;
display: flex;
justify-content: space-around;
align-items: flex-end;
z-index: 40;
}
.creature-slot {
width: 120px;
text-align: center;
}
.creature-sprite {
width: 80px;
height: 80px;
margin: 0 auto 5px;
background: rgba(255,255,255,0.1);
border-radius: 50%;
border: 2px solid var(--border-color);
}
.hp-bar-container {
width: 100%;
height: 8px;
background: #333;
border-radius: 4px;
overflow: hidden;
margin-top: 5px;
}
.hp-bar-fill {
height: 100%;
background: #4caf50;
width: 100%;
transition: width 0.3s;
}
.action-buttons {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
margin-top: 20px;
}
/* Dialogue Box */
#dialogue-box {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
width: 80%;
max-width: 800px;
background: var(--panel-bg);
padding: 20px;
border-radius: 10px;
border: 1px solid var(--border-color);
z-index: 60;
pointer-events: none;
}
#dialogue-text { font-size: 1.2rem; line-height: 1.4; }
/* Vignette for story */
#vignette {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
box-shadow: inset 0 0 150px rgba(0,0,0,1);
pointer-events: none;
z-index: 200;
opacity: 0;
transition: opacity 1s;
}
/* Notifications */
.notification {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 20px 40px;
font-size: 2rem;
font-weight: bold;
text-shadow: 0 0 10px #000;
pointer-events: none;
z-index: 1000;
animation: floatUp 2s forwards;
}
@keyframes floatUp {
0% { transform: translate(-50%, -50%); opacity: 1; }
100% { transform: translate(-50%, -150%); opacity: 0; }
}
.floating-damage {
position: absolute;
color: #ff4444;
font-weight: bold;
pointer-events: none;
z-index: 100;
animation: floatUp 1s forwards;
}
.btn-group {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
</style>
</head>
<body>
<div id="game-container">
<div id="vignette"></div>
<canvas id="game-canvas"></canvas>
<div id="hud" class="hidden">
<div class="hud-item" id="hud-zone">Zone: ---</div>
<div class="hud-item" id="hud-party">Party: 0/6</div>
<div class="hud-item" id="hud-items">Items: 0</div>
</div>
<!-- Title Screen -->
<div id="title-screen" class="overlay">
<div class="menu-card">
<h1>NEW BINDING</h1>
<p>The Echoes are fading. The Nodes are drifting.<br>Bind the remaining spirits to the Veil.</p>
<div class="btn-group">
<button onclick="game.start()">New Binding</button>
<button onclick="game.load()">Continue</button>
</div>
</div>
</div>
<!-- Main Menu (Pause / Inventory etc) -->
<div id="menu-screen" class="overlay hidden">
<div class="menu-card">
<h1>PAUSE</h1>
<div class="btn-group">
<button onclick="game.toggleMenu()">Back</button>
<button onclick="game.openBag()">Bag</button>
<button onclick="game.openTeam()">Team</button>
<button onclick="game.openEncyclopedia()">Lore</button>
<button onclick="game.saveGame()">Save</button>
</div>
</div>
</div>
<!-- Battle UI -->
<div id="battle-ui" class="hidden">
<div id="enemy-side" style="display: flex; gap: 20px;">
<!-- Enemies generated here -->
</div>
<div id="player-side" style="display: flex; gap: 10px;">
<!-- Party generated here -->
</div>
<div id="battle-actions" class="action-buttons">
<!-- Action buttons generated here -->
</div>
</div>
<!-- Dialogue Box -->
<div id="dialogue-box" class="hidden">
<div id="dialogue-text"></div>
</div>
</div>
<script>
/**
* WORLD DATA & CONSTANTS
*/
const TYPES = {
LUMINA: 'Lumina', // A
UMBRA: 'Umbra', // B
VERDANT: 'Verdant', // C
FORGE: 'Forge', // D
CURRENT: 'Current', // E
AEON: 'Aeon', // F
FLUX: 'Flux' // G
};
// Type Advantage Matrix
const TYPE_CHART = {
[TYPES.LUMINA]: { strong: [TYPES.UMBRA], weak: [TYPES.VERDANT, TYPES.FORGE] },
[TYPES.UMBRA]: { strong: [TYPES.VERDANT], weak: [TYPES.LUMINA, TYPES.CURRENT] },
[TYPES.VERDANT]: { strong: [TYPES.LUMINA], weak: [TYPES.UMBRA, TYPES.FORGE] },
[TYPES.FORGE]: { strong: [TYPES.LUMINA, TYPES.VERDANT], weak: [TYPES.CURRENT] },
[TYPES.CURRENT]: { strong: [TYPES.FORGE, TYPES.UMBRA], weak: [] },
[TYPES.AEON]: { strong: [TYPES.LUMINA, TYPES.UMBRA, TYPES.VERDANT, TYPES.FORGE, TYPES.CURRENT, TYPES.FLUX], weak: [] },
[TYPES.FLUX]: { strong: [], weak: [TYPES.AEON] }
};
const ABILITIES = [
{ name: "Lumina Flare", type: TYPES.LUMINA, power: 15, acc: 95, cost: 5, effect: "none", desc: "A burst of pure light." },
{ name: "Shadow Stitch", type: TYPES.UMBRA, power: 12, acc: 85, cost: 4, effect: "slow", desc: "Pins the shadow to the ground." },
{ name: "Verdant Growth", type: TYPES.VERDANT, power: 8, acc: 90, cost: 6, effect: "heal", desc: "Regenerates vitality." },
{ name: "Forge Strike", type: TYPES.FORGE, power: 20, acc: 80, cost: 8, effect: "none", desc: "A heavy metal smash." },
{ name: "Current Shock", type: TYPES.CURRENT, power: 14, acc: 90, cost: 5, effect: "shock", desc: "Rapid electricity." },
{ name: "Aeon Rift", type: TYPES.AEON, power: 25, acc: 70, cost: 15, effect: "none", desc: "A tear in time." },
{ name: "Flux Wobble", type: TYPES.FLUX, power: 10, acc: 100, cost: 3, effect: "random_type", desc: "Unpredictable energy." },
{ name: "Sunbeam", type: TYPES.LUMINA, power: 10, acc: 90, cost: 3, effect: "heal", desc: "Soft warming light." },
{ name: "Void Whisper", type: TYPES.UMBRA, power: 14, acc: 80, cost: 6, effect: "burn", desc: "Chilling necrotic words." },
{ name: "Root Bind", type: TYPES.VERDANT, power: 12, acc: 85, cost: 7, effect: "slow", desc: "Roots entwine the foe." },
{ name: "Iron Wall", type: TYPES.FORGE, power: 5, acc: 100, cost: 10, effect: "barrier", desc: "Creates a temporary shield." },
{ name: "Spark Jump", type: TYPES.CURRENT, power: 18, acc: 85, cost: 9, effect: "shock", desc: "A leaping electric strike." },
{ name: "Chronos Delay", type: TYPES.AEON, power: 10, acc: 80, cost: 12, effect: "slow", desc: "Slows the flow of time." },
{ name: "Chaos Pulse", type: TYPES.FLUX, power: 20, acc: 70, cost: 15, effect: "burn", desc: "Erratic energy explosion." },
{ name: "Lumina Beam", type: TYPES.LUMINA, power: 22, acc: 80, cost: 12, effect: "none", desc: "Focused beam of light." },
{ name: "Umbral Veil", type: TYPES.UMBRA, power: 15, acc: 85, cost: 8, effect: "barrier", desc: "Cloak in shadows." },
{ name: "Forest Call", type: TYPES.VERDANT, power: 18, acc: 80, cost: 10, effect: "heal", desc: "Calls on the forest's grace." },
{ name: "Hammer Drop", type: TYPES.FORGE, power: 28, acc: 70, cost: 20, effect: "none", desc: "Massive overhead slam." },
{ name: "Overload", type: TYPES.CURRENT, power: 35, acc: 60, cost: 25, effect: "shock", desc: "A massive electrical discharge." },
{ name: "Stasis Field", type: TYPES.AEON, power: 15, acc: 90, cost: 15, effect: "slow", desc: "Freeze the enemy in place." },
{ name: "Flux Warp", type: TYPES.FLUX, power: 12, acc: 95, cost: 5, effect: "none", desc: "Teleport slightly." },
{ name: "Radiance", type: TYPES.LUMINA, power: 8, acc: 100, cost: 5, effect: "heal", desc: "Gentle restorative aura." },
{ name: "Shadow Lash", type: TYPES.UMBRA, power: 16, acc: 88, cost: 7, effect: "burn", desc: "A whip of dark matter." },
{ name: "Vine Whip", type: TYPES.VERDANT, power: 14, acc: 90, cost: 6, effect: "slow", desc: "Fast whipping vines." },
{ name: "Molten Core", type: TYPES.FORGE, power: 24, acc: 82, cost: 14, effect: "burn", desc: "Heat from the forge." },
{ name: "Static Cage", type: TYPES.CURRENT, power: 15, acc: 85, cost: 10, effect: "shock", desc: "Traps in static energy." },
{ name: "Timeless Step", type: TYPES.AEON, power: 20, acc: 90, cost: 12, effect: "none", desc: "Move through time." },
{ name: "Reality Tear", type: TYPES.FLUX, power: 40, acc: 50, cost: 30, effect: "none", desc: "A catastrophic rift." },
{ name: "Prism Strike", type: TYPES.LUMINA, power: 18, acc: 85, cost: 8, effect: "none", desc: "Refracted light strike." },
{ name: "Abyssal Maw", type: TYPES.UMBRA, power: 25, acc: 75, cost: 15, effect: "burn", desc: "A bite from the deep." },
{ name: "Bloom", type: TYPES.VERDANT, power: 10, acc: 95, cost: 8, effect: "heal", desc: "Rapid floral growth." },
{ name: "Sledge Smash", type: TYPES.FORGE, power: 22, acc: 80, cost: 10, effect: "none", desc: "A heavy kinetic strike." },
{ name: "Storm Bolt", type: TYPES.CURRENT, power: 20, acc: 85, cost: 10, effect: "shock", desc: "A jagged bolt of lightning." },
{ name: "Eon Echo", type: TYPES.AEON, power: 18, acc: 80, cost: 12, effect: "none", desc: "A strike from the past." },
{ name: "Void Rift", type: TYPES.FLUX, power: 15, acc: 85, cost: 10, effect: "none", desc: "A rift to the void." },
{ name: "Light Burst", type: TYPES.LUMINA, power: 20, acc: 90, cost: 10, effect: "none", desc: "Explosive light." },
{ name: "Night Terror", type: TYPES.UMBRA, power: 22, acc: 70, cost: 15, effect: "burn", desc: "Induce pure fear." },
{ name: "Thorn Wall", type: TYPES.VERDANT, power: 12, acc: 90, cost: 8, effect: "barrier", desc: "Walls of sharp thorns." },
{ name: "Heat Forge", type: TYPES.FORGE, power: 18, acc: 85, cost: 12, effect: "burn", desc: "Forge the heat of the core." },
{ name: "Tesla Coil", type: TYPES.CURRENT, power: 25, acc: 75, cost: 15, effect: "shock", desc: "A coil of intense power." },
{ name: "Time Warp", type: TYPES.AEON, power: 30, acc: 60, cost: 25, effect: "none", desc: "Twist the fabric of time." },
{ name: "Glitch", type: TYPES.FLUX, power: 5, acc: 100, cost: 2, effect: "none", desc: "A minor reality error." }
];
// 27 Unique Creatures
const CREATURE_DATA = [
{ id: 0, name: "Solari", type: TYPES.LUMINA, lore: "A fox of woven starlight.", hp: 80, atk: 12, def: 8, spd: 15, growth: {hp: 1.2, atk: 1.1}, baseAbs: 0 },
{ id: 1, name: "Noctis", type: TYPES.UMBRA, lore: "A bat-like shadow that feeds on whispers.", hp: 95, atk: 10, def: 12, spd: 12, growth: {hp: 1.3, atk: 1.0}, baseAbs: 0 },
{ id: 2, name: "Floris", type: TYPES.VERDANT, lore: "A floating petal of eternal spring.", hp: 70, atk: 9, def: 10, spd: 18, growth: {hp: 1.1, atk: 0.9}, baseAbs: 0 },
{ id: 3, name: "Ironclad", type: TYPES.FORGE, lore: "A golem of living bronze.", hp: 150, atk: 14, def: 20, spd: 5, growth: {hp: 1.4, atk: 1.1}, baseAbs: 0 },
{ id: 4, name: "Volt", type: TYPES.CURRENT, lore: "A flickering spark of static.", hp: 60, atk: 18, def: 6, spd: 22, growth: {hp: 1.0, atk: 1.3}, baseAbs: 0 },
{ id: 5, name: "Chronos", type: TYPES.AEON, lore: "A shifting figure of clockwork sand.", hp: 100, atk: 15, def: 15, spd: 14, growth: {hp: 1.2, atk: 1.2}, baseAbs: 0 },
{ id: 6, name: "Maelstrom", type: TYPES.FLUX, lore: "A chaotic swirl of purple mist.", hp: 110, atk: 13, def: 12, spd: 16, growth: {hp: 1.2, atk: 1.1}, baseAbs: 0 },
{ id: 7, name: "Solara", type: TYPES.LUMINA, lore: "Sister to Solari, she burns with intensity.", hp: 90, atk: 14, def: 10, spd: 14, growth: {hp: 1.1, atk: 1.2}, baseAbs: 0 },
{ id: 8, name: "Umbral", type: TYPES.UMBRA, lore: "A stalker that leaves no footprints.", hp: 85, atk: 16, def: 9, spd: 13, growth: {hp: 1.0, atk: 1.3}, baseAbs: 0 },
{ id: 9, name: "Verdant", type: TYPES.VERDANT, lore: "A guardian of the deep woods.", hp: 120, atk: 10, def: 15, spd: 8, growth: {hp: 1.4, atk: 1.0}, baseAbs: 0 },
{ id: 10, name: "Forged", type: TYPES.FORGE, lore: "An ancient sentinel of the hills.", hp: 160, atk: 15, def: 22, spd: 4, growth: {hp: 1.5, atk: 1.1}, baseAbs: 0 },
{ id: 11, name: "Current", type: TYPES.CURRENT, lore: "A swift river of electricity.", hp: 70, atk: 20, def: 7, spd: 25, growth: {hp: 1.0, atk: 1.4}, baseAbs: 0 },
{ id: 12, name: "Aeon", type: TYPES.AEON, lore: "A witness to the beginning and end.", hp: 110, atk: 17, def: 16, spd: 15, growth: {hp: 1.2, atk: 1.2}, baseAbs: 0 },
{ id: 13, name: "Flux", type: TYPES.FLUX, lore: "A paradox in physical form.", hp: 95, atk: 14, def: 13, spd: 17, growth: {hp: 1.1, atk: 1.1}, baseAbs: 0 },
{ id: 14, name: "Lumina-Rex", type: TYPES.LUMINA, lore: "The apex of light.", hp: 200, atk: 30, def: 25, spd: 20, growth: {hp: 1.3, atk: 1.3}, baseAbs: 0 },
{ id: 15, name: "Umbra-King", type: TYPES.UMBRA, lore: "Lord of the silent void.", hp: 220, atk: 35, def: 30, spd: 25, growth: {hp: 1.4, atk: 1.4}, baseAbs: 0 },
{ id: 16, name: "Verdant-Titan", type: TYPES.VERDANT, lore: "A mountain that breathes.", hp: 250, atk: 25, def: 40, spd: 5, growth: {hp: 1.6, atk: 1.2}, baseAbs: 0 },
{ id: 17, name: "Forge-Colossus", type: TYPES.FORGE, lore: "The ultimate hammer.", hp: 300, atk: 40, def: 50, spd: 2, growth: {hp: 1.7, atk: 1.4}, baseAbs: 0 },
{ id: 18, name: "Current-Storm", type: TYPES.CURRENT, lore: "A living hurricane.", hp: 180, atk: 45, def: 20, spd: 35, growth: {hp: 1.3, atk: 1.5}, baseAbs: 0 },
{ id: 19, name: "Aeon-Sentinel", type: TYPES.AEON, lore: "A guardian of history.", hp: 220, atk: 30, def: 30, spd: 20, growth: {hp: 1.3, atk: 1.3}, baseAbs: 0 },
{ id: 20, name: "Flux-Entity", type: TYPES.FLUX, lore: "A glitch in existence.", hp: 150, atk: 30, def: 20, spd: 25, growth: {hp: 1.2, atk: 1.3}, baseAbs: 0 },
{ id: 21, name: "Solari-Prime", type: TYPES.LUMINA, lore: "A transformation of the first light.", hp: 250, atk: 45, def: 35, spd: 40, growth: {hp: 1.4, atk: 1.5}, baseAbs: 0 },
{ id: 22, name: "Noctis-Prime", type: TYPES.UMBRA, lore: "The shadow that consumed all.", hp: 300, atk: 50, def: 45, spd: 45, growth: {hp: 1.5, atk: 1.6}, baseAbs: 0 },
{ id: 23, name: "Floris-Prime", type: TYPES.VERDANT, lore: "A forest made manifest.", hp: 400, atk: 30, def: 60, spd: 10, growth: {hp: 1.8, atk: 1.4}, baseAbs: 0 },
{ id: 24, name: "Ironclad-Prime", type: TYPES.FORGE, lore: "The unbreakable bastion.", hp: 500, atk: 50, def: 80, spd: 1, growth: {hp: 2.0, atk: 1.8}, baseAbs: 0 },
{ id: 25, name: "Volt-Prime", type: TYPES.CURRENT, lore: "The lightning's heart.", hp: 250, atk: 70, def: 30, spd: 60, growth: {hp: 1.4, atk: 1.8}, baseAbs: 0 },
{ id: 26, name: "Chronos-Prime", type: TYPES.AEON, lore: "Master of the timeline.", hp: 350, atk: 40, def: 40, spd: 30, growth: {hp: 1.5, atk: 1.5}, baseAbs: 0 },
{ id: 27, name: "Maelstrom-Prime", type: TYPES.FLUX, lore: "The ultimate chaos.", hp: 300, atk: 50, def: 40, spd: 40, growth: {hp: 1.6, atk: 1.6}, baseAbs: 0 }
];
// Zone Data
const ZONES = [
{ name: "Whispering Glade", color: "#1a3c34", particle: "leaf", boss: "Grove Warden", boss_type: TYPES.VERDANT },
{ name: "Iron Crags", color: "#3c2a1a", particle: "dust", boss: "Steel Monarch", boss_type: TYPES.FORGE },
{ name: "Deep Currents", color: "#0a1a3c", particle: "spark", boss: "Tide Titan", boss_type: TYPES.CURRENT },
{ name: "Void Sump", color: "#2a0a3c", particle: "shadow", boss: "Echo King", boss_type: TYPES.UMBRA },
{ name: "Aether Peak", color: "#2a2a3c", particle: "glimmer", boss: "Time Weaver", boss_type: TYPES.AEON },
{ name: "The Nexus", color: "#3c0a3c", particle: "flux", boss: "Entropy Soul", boss_type: TYPES.FLUX }
];
/**
* GAME ENGINE
*/
class Game {
constructor() {
this.canvas = document.getElementById('game-canvas');
this.ctx = this.canvas.getContext('2d');
this.canvas.width = 1200;
this.canvas.height = 800;
this.state = {
running: false,
currentZone: 0,
playerPos: { x: 100, y: 100 },
party: [],
inventory: [],
unlocked: 1,
bossesDefeated: 0,
saveData: null,
battle: null,
tutorialStep: 0
};
this.keys = {};
this.particles = [];
this.init();
}
init() {
window.addEventListener('keydown', e => this.keys[e.code] = true);
window.addEventListener('keyup', e => this.keys[e.code] = false);
this.loop();
}
start() {
// Tutorial Starter: 3 creatures
this.state.party = [
{ ...CREATURE_DATA[0], level: 1, currentHp: 80, maxHp: 80, abilities: [ABILITIES[0], ABILITIES[1], ABILITIES[2], ABILITIES[3]] },
{ ...CREATURE_DATA[1], level: 1, currentHp: 95, maxHp: 95, abilities: [ABILITIES[1], ABILITIES[4], ABILITIES[5], ABILITIES[6]] },
{ ...CREATURE_DATA[2], level: 1, currentHp: 70, maxHp: 70, abilities: [ABILITIES[2], ABILITIES[0], ABILITIES[3], ABILITIES[4]] }
];
this.state.running = true;
document.getElementById('title-screen').classList.add('hidden');
document.getElementById('hud').classList.remove('hidden');
this.updateHUD();
this.spawnParticles();
}
saveGame() {
const data = {
zone: this.state.currentZone,
party: this.state.party,
unlocked: this.state.unlocked,
bosses: this.state.bossesDefeated
};
localStorage.setItem('new_binding_save', JSON.stringify(data));
this.showDialogue("Game Saved to Veil.");
}
load() {
const raw = localStorage.getItem('new_binding_save');
if (raw) {
const data = JSON.parse(raw);
this.state.currentZone = data.zone;
this.state.party = data.party;
this.state.unlocked = data.unlocked;
this.state.bossesDefeated = data.bosses;
this.state.running = true;
document.getElementById('title-screen').classList.add('hidden');
document.getElementById('hud').classList.remove('hidden');
this.updateHUD();
this.spawnParticles();
} else {
this.start();
}
}
updateHUD() {
document.getElementById('hud-zone').innerText = `Zone: ${ZONES[this.state.currentZone].name}`;
document.getElementById('hud-party').innerText = `Party: ${this.state.party.length}/6`;
document.getElementById('hud-items').innerText = `Items: ${this.state.inventory.length}`;
}
spawnParticles() {
for(let i=0; i<50; i++) {
this.particles.push({
x: Math.random() * this.canvas.width,
y: Math.random() * this.canvas.height,
vx: (Math.random() - 0.5) * 0.5,
vy: (Math.random() - 0.5) * 0.5,
size: Math.random() * 3,
color: 'rgba(255,255,255,0.2)'
});
}
}
drawOverworld() {
const zone = ZONES[this.state.currentZone];
// Background
const grad = this.ctx.createLinearGradient(0, 0, 0, this.canvas.height);
grad.addColorStop(0, '#101020');
grad.addColorStop(1, zone.color);
this.ctx.fillStyle = grad;
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// Particles
this.particles.forEach(p => {
this.ctx.fillStyle = p.color;
this.ctx.beginPath();
this.ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
this.ctx.fill();
p.x += p.vx;
p.y += p.vy;
if (p.x < 0 || p.x > this.canvas.width) p.vx *= -1;
if (p.y < 0 || p.y > this.canvas.height) p.vy *= -1;
});
// Player
this.ctx.fillStyle = 'white';
this.ctx.shadowBlur = 15;
this.ctx.shadowColor = 'white';
this.ctx.beginPath();
this.ctx.arc(this.state.playerPos.x, this.state.playerPos.y, 15, 0, Math.PI * 2);
this.ctx.fill();
this.ctx.shadowBlur = 0;
}
handleInput() {
if (!this.state.running) return;
const speed = 4;
if (this.keys['KeyW'] || this.keys['ArrowUp']) this.state.playerPos.y -= speed;
if (this.keys['KeyS'] || this.keys['ArrowDown']) this.state.playerPos.y += speed;
if (this.keys['KeyA'] || this.keys['ArrowLeft']) this.state.playerPos.x -= speed;
if (this.keys['KeyD'] || this.keys['ArrowRight']) this.state.playerPos.x += speed;
// Bounds
this.state.playerPos.x = Math.max(20, Math.min(this.canvas.width - 20, this.state.playerPos.x));
this.state.playerPos.y = Math.max(20, Math.min(this.canvas.height - 20, this.state.playerPos.y));
// Random Encounter
if (Math.random() < 0.002) {
this.startBattle();
}
}
startBattle() {
document.getElementById('battle-ui').classList.remove('hidden');
const enemyType = ZONES[this.state.currentZone].boss_type;
const enemy = {
name: "Wild " + (enemyType === TYPES.VERDANT ? "Sprout" : "Wisp"),
type: enemyType,
hp: 100,
maxHp: 100,
atk: 15,
def: 10,
spd: 10,
abilities: [ABILITIES[0], ABILITIES[1], ABILITIES[2], ABILITIES[3]],
isEnemy: true
};
this.state.battle = {
enemies: [enemy],
turn: 0,
log: "A wild spirit appears!"
};
this.updateBattleUI();
this.showDialogue(this.state.battle.log);
}
updateBattleUI() {
const enemySide = document.getElementById('enemy-side');
const playerSide = document.getElementById('player-side');
enemySide.innerHTML = '';
playerSide.innerHTML = '';
this.state.battle.enemies.forEach(e => {
const div = document.createElement('div');
div.className = 'creature-slot';
div.innerHTML = `
<div class="creature-sprite" style="background: var(--type-${e.type.toLowerCase()})"></div>
<div style="font-weight:bold">${e.name}</div>
<div class="hp-bar-container"><div class="hp-bar-fill" style="width: ${(e.hp/e.maxHp)*100}%"></div></div>
`;
enemySide.appendChild(div);
});
this.state.party.forEach((p, i) => {
const div = document.createElement('div');
div.className = 'creature-slot';
div.innerHTML = `
<div class="creature-sprite" style="background: var(--type-${p.type.toLowerCase()})"></div>
<div style="font-weight:bold">${p.name}</div>
<div class="hp-bar-container"><div class="hp-bar-fill" style="width: ${(p.currentHp/p.maxHp)*100}%"></div></div>
`;
playerSide.appendChild(div);
});
const actionBox = document.getElementById('battle-actions');
actionBox.innerHTML = '';
// Show first active creature's moves
const active = this.state.party[0]; // Simplified turn logic for now
if (active && active.currentHp > 0) {
active.abilities.forEach(a => {
const btn = document.createElement('button');
btn.innerText = a.name;
btn.onclick = () => this.executeMove(0, a);
actionBox.appendChild(btn);
});
}
}
executeMove(partyIdx, ability) {
if (!this.state.battle) return;
const p = this.state.party[partyIdx];
const e = this.state.battle.enemies[0];
// Damage calc
let multiplier = 1.0;
// Type Advantage
const eType = e.type;
const pType = p.type;
if (TYPE_CHART[pType].strong.includes(eType)) multiplier = 1.5;
if (TYPE_CHART[pType].weak.includes(eType)) multiplier = 0.8;
if (pType === TYPES.AEON) multiplier = 1.2;
if (eType === TYPES.FLUX) {
if (pType === TYPES.AEON) multiplier = 1.5;
else multiplier = 0.5;
}
const dmg = Math.floor((0.4 * p.level * p.atk / e.def * ability.power * multiplier) + (Math.random() * 5));
e.hp -= dmg;
this.showDialogue(`${p.name} uses ${ability.name}! Deals ${dmg} damage.`);
if (e.hp <= 0) {
this.state.battle.enemies = [];
this.showDialogue("Victory!");
setTimeout(() => {
this.state.battle = null;
document.getElementById('battle-ui').classList.add('hidden');
document.getElementById('hud').classList.remove('hidden');
}, 1500);
} else {
// Enemy turn
setTimeout(() => {
const eMove = this.state.battle.enemies[0].abilities[Math.floor(Math.random()*4)];
const pDmg = Math.floor((0.4 * 1 * e.atk / p.def * eMove.power) + (Math.random() * 5));
p.currentHp -= pDmg;
this.showDialogue(`${e.name} uses ${eMove.name}! Deals ${pDmg} damage.`);
this.updateBattleUI();
}, 1000);
}
}
showDialogue(text) {
const box = document.getElementById('dialogue-box');
const content = document.getElementById('dialogue-text');
box.classList.remove('hidden');
content.innerText = text;
setTimeout(() => {
box.classList.add('hidden');
}, 3000);
}
loop() {
this.handleInput();
this.drawOverworld();
requestAnimationFrame(() => this.loop());
}
}
const game = new Game();
</script>
</body>
</html>
<!-- agent-meta {"model":"google/gemma-4-12b-qat","provider":"lmstudio","persona":"full","sessionId":"72c87cd9-cc6c-4ed0-b259-7d8ba5502539","tokensIn":444113,"tokensOut":43117,"tokensTotal":487230,"turns":14,"toolCalls":13,"failedToolCalls":5,"timestamp":"2026-07-14T00:37:36.797Z"} -->