Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions experiments/parallel_concepts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Parallel Game Concept Demos

<!-- Shared context: This README introduces four parallel concept slices for Marimo capture. -->

Each concept below pairs a concise pitch with feasibility notes and links to a minimal web-ready artefact. Every artefact is intentionally lightweight so multiple collaborators can iterate without stepping on each other.

## Version A — **Echoes in Neon** (Cyberpunk Rhythm Reflex)
- **Concept Flair:** Pilot a courier weaving through neon alleys where beats manifest as light pulses. Players tap cues to stay in rhythm while dodging obstacles that sync to the soundtrack.
- **Suitability / Feasibility:**
- *Technical Scope:* Moderate — core loop is timing-based, using lightweight input detection and beat scheduling. Extendable with procedural track authoring.
- *Gameplay Loop:* Hear beat → react via arrow keys → earn momentum boosts or stumble.
- *Audience Appeal:* Rhythm-action fans, streamers attracted by synthwave aesthetics.
- **Demo:** [`version_a_echoes_in_neon.html`](./version_a_echoes_in_neon.html)

## Version B — **Botanical Bard** (Cozy Narrative Composer)
- **Concept Flair:** Tend a living poem garden where each plant is a stanza that grows based on player-selected moods and inspirations.
- **Suitability / Feasibility:**
- *Technical Scope:* Lightweight — seeded text templates and unlockable descriptors; scalability via AI-assisted stanza generation.
- *Gameplay Loop:* Choose tone → sprout stanza → curate arrangement → share garden snapshots.
- *Audience Appeal:* Cozy gamers, creative writers, social sharers seeking mindful play.
- **Demo:** [`version_b_botanical_bard.html`](./version_b_botanical_bard.html)

## Version C — **Astral Weaver** (Tactical Pattern Puzzle)
- **Concept Flair:** Align constellations on a holographic loom to channel cosmic energy. Players rotate fragments to weave paths between stellar anchors.
- **Suitability / Feasibility:**
- *Technical Scope:* Mid-high — tile rotation logic with solvable procedural generation.
- *Gameplay Loop:* Rotate tiles → connect anchors → trigger chain reactions → unlock lore snippets.
- *Audience Appeal:* Puzzle aficionados craving tactile sci-fi aesthetics.
- **Demo:** [`version_c_astral_weaver.html`](./version_c_astral_weaver.html)

## Version D — **Quantum Jam Session** (Live Audio Sandbox)
- **Concept Flair:** Improvise in a zero-gravity lounge where orbital nodes emit harmonics. Players layer loops, modulate filters, and sculpt soundscapes.
- **Suitability / Feasibility:**
- *Technical Scope:* Moderate — Web Audio graph with loopers and lightweight visualizers.
- *Gameplay Loop:* Activate orbiting nodes → tweak parameters → capture live mixdowns.
- *Audience Appeal:* Music experimenters, ambient creators, streamers who mix live.
- **Demo:** [`version_d_quantum_jam.html`](./version_d_quantum_jam.html)

> **Collaboration Note:** Each HTML file contains inline comments marking extension hooks (`<!-- EXTENSION HOOK -->`) so new agents can bolt on features without guesswork.
158 changes: 158 additions & 0 deletions experiments/parallel_concepts/version_a_echoes_in_neon.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Echoes in Neon — Rhythm Reflex Slice</title>
<style>
/* Core visual identity: neon gradients, rhythmic pulses */
:root {
--bg: radial-gradient(circle at 20% 20%, #0ff, #105);
--accent: #f0f;
--success: #4ef0c8;
--miss: #ff5178;
}
body {
margin: 0;
min-height: 100vh;
font-family: 'Orbitron', sans-serif;
background: var(--bg);
color: #f8f8ff;
display: flex;
align-items: center;
justify-content: center;
}
.hud {
text-align: center;
backdrop-filter: blur(12px);
background: rgba(0,0,0,0.35);
border: 1px solid rgba(255,255,255,0.12);
padding: 2rem 3rem;
border-radius: 1.5rem;
box-shadow: 0 0 40px rgba(240,0,240,0.3);
}
.beat-stream {
display: grid;
grid-template-columns: repeat(4, 70px);
gap: 1.5rem;
margin: 2rem 0;
}
.cue {
border: 2px solid rgba(255,255,255,0.25);
border-radius: 16px;
padding: 1.25rem 0;
font-size: 2rem;
position: relative;
transition: transform 0.2s ease, border-color 0.2s ease;
}
.cue.active {
border-color: var(--accent);
transform: scale(1.1);
box-shadow: 0 0 20px rgba(240,0,240,0.4);
}
.cue.good {
border-color: var(--success);
box-shadow: 0 0 24px rgba(78,240,200,0.5);
}
.cue.bad {
border-color: var(--miss);
box-shadow: 0 0 24px rgba(255,81,120,0.5);
}
.log {
height: 4rem;
font-size: 0.9rem;
opacity: 0.8;
}
</style>
</head>
<body>
<main class="hud">
<h1>Echoes in Neon</h1>
<p>Hit the highlighted arrow on the beat. Beats land every 1.2 seconds — keep the courier sprinting.</p>
<div class="beat-stream" id="beatStream">
<!-- EXTENSION HOOK: Add more lanes or FX variations here. -->
<div class="cue" data-key="ArrowLeft">←</div>
<div class="cue" data-key="ArrowUp">↑</div>
<div class="cue" data-key="ArrowDown">↓</div>
<div class="cue" data-key="ArrowRight">→</div>
</div>
<p>Streak: <span id="streak">0</span> | Mood: <span id="mood">Steady</span></p>
<div class="log" id="log">Awaiting the pulse...</div>
</main>
<script>
// Control parameters for rhythm pacing.
const cues = Array.from(document.querySelectorAll('.cue'));
const logEl = document.getElementById('log');
const streakEl = document.getElementById('streak');
const moodEl = document.getElementById('mood');

let activeCue = null;
let streak = 0;
let beatTimer = null;

const moods = [
{ threshold: 0, label: 'Steady' },
{ threshold: 4, label: 'Surging' },
{ threshold: 8, label: 'Blazing' }
];

function updateMood() {
const current = moods
.slice()
.reverse()
.find(mood => streak >= mood.threshold);
moodEl.textContent = current ? current.label : 'Steady';
}

function highlightNextCue() {
if (activeCue) {
activeCue.classList.remove('active');
}
activeCue = cues[Math.floor(Math.random() * cues.length)];
activeCue.classList.remove('good', 'bad');
activeCue.classList.add('active');
logEl.textContent = 'Pulse incoming — focus.';
}

function resetCueState() {
cues.forEach(cue => cue.classList.remove('good', 'bad'));
}

function handleKeydown(event) {
if (!activeCue) return;
if (event.key === activeCue.dataset.key) {
streak += 1;
streakEl.textContent = streak;
updateMood();
resetCueState();
activeCue.classList.add('good');
logEl.textContent = 'Glide achieved! Maintain velocity.';
highlightNextCue();
} else if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
streak = Math.max(0, streak - 2);
streakEl.textContent = streak;
updateMood();
resetCueState();
activeCue.classList.add('bad');
logEl.textContent = 'Slip detected. Realign on the next beat.';
}
}

function startBeatLoop() {
highlightNextCue();
beatTimer = setInterval(() => {
// EXTENSION HOOK: Sync with audio beat callbacks here.
resetCueState();
activeCue.classList.add('bad');
logEl.textContent = 'Missed the beat — regain flow!';
streak = Math.max(0, streak - 1);
streakEl.textContent = streak;
updateMood();
setTimeout(highlightNextCue, 250);
}, 1200);
}

window.addEventListener('keydown', handleKeydown);
startBeatLoop();
</script>
</body>
</html>
144 changes: 144 additions & 0 deletions experiments/parallel_concepts/version_b_botanical_bard.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Botanical Bard — Poem Garden Slice</title>
<style>
body {
margin: 0;
min-height: 100vh;
font-family: 'Quicksand', sans-serif;
background: linear-gradient(180deg, #f2ffe6, #d4f0ff);
color: #32443f;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
.card {
background: rgba(255,255,255,0.8);
border-radius: 24px;
box-shadow: 0 30px 60px rgba(80,140,120,0.2);
padding: 2.5rem;
max-width: 680px;
width: 100%;
}
button {
background: #5fb38a;
color: white;
border: none;
border-radius: 14px;
padding: 0.8rem 1.4rem;
font-size: 1rem;
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 14px 28px rgba(95,179,138,0.35);
}
.poem {
margin-top: 1.5rem;
line-height: 1.6;
font-size: 1.1rem;
white-space: pre-line;
}
.mood-selector {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
margin-bottom: 1rem;
}
.badge {
background: rgba(95,179,138,0.15);
border-radius: 999px;
padding: 0.4rem 0.8rem;
font-size: 0.85rem;
}
</style>
</head>
<body>
<section class="card">
<h1>Botanical Bard</h1>
<p>Pick a mood and we will plant a stanza. Curate a pocket garden of verse.</p>
<div class="mood-selector" id="moodSelector">
<!-- EXTENSION HOOK: Append moods via CMS or AI suggestions. -->
</div>
<button id="grow">Grow New Stanza</button>
<div class="poem" id="poem">The garden awaits your first seed.</div>
<p class="badge" id="status">Status: Soil enriched.</p>
</section>
<script>
const moods = [
{ id: 'serene', label: 'Serene', palette: ['dew', 'silk', 'hush'] },
{ id: 'wistful', label: 'Wistful', palette: ['amber', 'echo', 'fall'] },
{ id: 'radiant', label: 'Radiant', palette: ['sun', 'glow', 'flare'] },
{ id: 'nocturne', label: 'Nocturne', palette: ['moon', 'shadow', 'glint'] }
];

const templates = [
'A {tone} whisper winds between the {flora},\nrooted in {texture} memories.',
'{flora} bloom in {tone} cadence,\ninviting {texture} wanderers.',
'We weave {texture} tales among the {flora},\nwhile {tone} skies listen.',
'Every {texture} breeze coaxes {flora} to rise,\na {tone} chorus unfurling.'
];

const flora = {
serene: ['mint-leaf lanterns', 'soft fern arches', 'cerulean moss'],
wistful: ['amber ivy', 'sleeping poppies', 'last-light thistle'],
radiant: ['helios blossoms', 'saffron reeds', 'cinder lilies'],
nocturne: ['midnight orchids', 'lunar reeds', 'starlit foxglove']
};

const textures = {
serene: ['silken', 'glimmering', 'featherlight'],
wistful: ['remembered', 'copper-toned', 'melancholy'],
radiant: ['ember-bright', 'auric', 'flaring'],
nocturne: ['dusklit', 'velvet', 'echoing']
};

let selectedMood = moods[0].id;

const moodSelector = document.getElementById('moodSelector');
const poemEl = document.getElementById('poem');
const statusEl = document.getElementById('status');

function renderMoodButtons() {
moodSelector.innerHTML = '';
moods.forEach(mood => {
const btn = document.createElement('button');
btn.textContent = mood.label;
btn.type = 'button';
btn.dataset.mood = mood.id;
btn.style.background = selectedMood === mood.id ? '#5fb38a' : 'rgba(95,179,138,0.3)';
btn.style.color = selectedMood === mood.id ? 'white' : '#2c4a3f';
btn.addEventListener('click', () => {
selectedMood = mood.id;
renderMoodButtons();
statusEl.textContent = `Status: Soil tuned for ${mood.label.toLowerCase()} blooms.`;
});
moodSelector.appendChild(btn);
});
}

function randomFrom(list) {
return list[Math.floor(Math.random() * list.length)];
}

function sproutStanza() {
const template = randomFrom(templates);
const replacements = {
tone: randomFrom(moods.find(m => m.id === selectedMood).palette),
flora: randomFrom(flora[selectedMood]),
texture: randomFrom(textures[selectedMood])
};
const stanza = template.replace(/\{(\w+)\}/g, (_, key) => replacements[key]);
poemEl.textContent = stanza;
statusEl.textContent = 'Status: New stanza thriving.';
}

document.getElementById('grow').addEventListener('click', sproutStanza);
renderMoodButtons();
</script>
</body>
</html>
Loading
Loading