// indoor.js — Indoor environment background themes // Variants: laboratory, classroom, bedroom, kitchen, arcade, office, library, gym (function(engine) { if (!engine) return; var D = engine.Draw, H = engine.helpers; engine.registerTheme('indoor', { laboratory: { meta: { id: 'indoor_laboratory', mood: 'mysterious', colors: ['#1a1e2e', '#2a3040', '#0f6b5e', '#44eebb'], tags: ['science', 'lab', 'tech', 'glow'], description: 'Dark science lab with glowing equipment and bubbling vials', compatibleMusicMoods: ['mysterious', 'tense', 'ambient'], recommendedFor: ['puzzle', 'trivia', 'rpg'] }, colors: ['#1a1e2e', '#2a3040', '#0f6b5e', '#44eebb'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90); Draw.rect(ctx, 0, h * 0.75, w, h * 0.25, H.darken(c[0], 0.3)); ctx.strokeStyle = H.rgba(c[2], 0.15); ctx.lineWidth = 1; for (var i = 0; i < w; i += 60) { ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i, h); ctx.stroke(); } for (var j = 0; j < h; j += 60) { ctx.beginPath(); ctx.moveTo(0, j); ctx.lineTo(w, j); ctx.stroke(); } }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(101); // Lab benches Draw.rect(ctx, w * 0.05, h * 0.72, w * 0.4, h * 0.04, '#3a3a4a'); Draw.rect(ctx, w * 0.55, h * 0.72, w * 0.4, h * 0.04, '#3a3a4a'); // Beakers and vials for (var i = 0; i < 6; i++) { var bx = w * 0.08 + i * w * 0.07; var bh = 20 + rng() * 25; var glow = 0.4 + Math.sin(t * (1.5 + rng()) + i) * 0.3; Draw.rect(ctx, bx, h * 0.72 - bh, 12, bh, H.rgba(c[3], glow)); Draw.rect(ctx, bx - 2, h * 0.72 - bh, 16, 3, H.rgba('#FFFFFF', 0.2)); } // Glowing tanks for (var j = 0; j < 3; j++) { var tx = w * 0.58 + j * w * 0.13; var pulse = 0.15 + Math.sin(t * 0.8 + j * 2) * 0.1; Draw.rect(ctx, tx, h * 0.45, 30, h * 0.27, H.rgba(c[2], pulse)); Draw.rect(ctx, tx - 2, h * 0.44, 34, 4, '#555566'); Draw.rect(ctx, tx - 2, h * 0.72, 34, 4, '#555566'); Draw.glow(ctx, tx + 15, h * 0.58, 35, c[3]); } // Ceiling pipes for (var p = 0; p < 4; p++) { var py = h * 0.05 + p * 18; Draw.rect(ctx, 0, py, w, 6, H.rgba('#556677', 0.3)); } // Blinking lights on wall for (var k = 0; k < 8; k++) { var lx = w * 0.1 + rng() * w * 0.8; var ly = h * 0.1 + rng() * h * 0.3; var on = Math.sin(t * (2 + rng() * 3) + k * 1.7) > 0.3; Draw.circle(ctx, lx, ly, 3, on ? c[3] : H.rgba(c[2], 0.2)); if (on) Draw.glow(ctx, lx, ly, 12, c[3]); } }, particles: { type: 'bubbles', count: 15, color: '#44eebb' } }, classroom: { meta: { id: 'indoor_classroom', mood: 'cheerful', colors: ['#f5f0e0', '#d4c9a8', '#5b8c5a', '#8b5e3c'], tags: ['school', 'learning', 'education', 'cozy'], description: 'Bright classroom with chalkboard, desks, and warm sunlight', compatibleMusicMoods: ['cheerful', 'calm', 'upbeat'], recommendedFor: ['trivia', 'puzzle', 'story'] }, colors: ['#f5f0e0', '#d4c9a8', '#5b8c5a', '#8b5e3c'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], H.darken(c[0], 0.05)], 90); Draw.rect(ctx, 0, h * 0.78, w, h * 0.22, c[1]); // Baseboard Draw.rect(ctx, 0, h * 0.76, w, h * 0.03, H.darken(c[3], 0.2)); }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(202); // Chalkboard Draw.rect(ctx, w * 0.15, h * 0.15, w * 0.7, h * 0.35, '#2a4a2a'); Draw.rect(ctx, w * 0.14, h * 0.14, w * 0.72, h * 0.37, 'transparent'); ctx.strokeStyle = c[3]; ctx.lineWidth = 4; ctx.strokeRect(w * 0.14, h * 0.14, w * 0.72, h * 0.37); // Chalk text squiggles ctx.strokeStyle = H.rgba('#FFFFFF', 0.3); ctx.lineWidth = 1; for (var i = 0; i < 5; i++) { ctx.beginPath(); var ly = h * 0.22 + i * h * 0.06; ctx.moveTo(w * 0.2, ly); for (var x = w * 0.2; x < w * 0.75; x += 8) { ctx.lineTo(x, ly + (rng() - 0.5) * 3); } ctx.stroke(); } // Desks for (var d = 0; d < 3; d++) { var dy = h * 0.6 + d * h * 0.08; for (var dx = 0; dx < 4; dx++) { var xx = w * 0.12 + dx * w * 0.22; Draw.rect(ctx, xx, dy, w * 0.16, h * 0.025, c[3]); Draw.rect(ctx, xx + 5, dy + h * 0.025, 4, h * 0.04, H.darken(c[3], 0.3)); Draw.rect(ctx, xx + w * 0.14, dy + h * 0.025, 4, h * 0.04, H.darken(c[3], 0.3)); } } // Window with sunlight Draw.rect(ctx, w * 0.02, h * 0.15, w * 0.08, h * 0.35, '#88bbdd'); ctx.strokeStyle = '#FFFFFF'; ctx.lineWidth = 3; ctx.strokeRect(w * 0.02, h * 0.15, w * 0.08, h * 0.35); ctx.beginPath(); ctx.moveTo(w * 0.06, h * 0.15); ctx.lineTo(w * 0.06, h * 0.5); ctx.stroke(); var sunAlpha = 0.05 + Math.sin(t * 0.3) * 0.02; ctx.fillStyle = H.rgba('#FFE488', sunAlpha); ctx.beginPath(); ctx.moveTo(w * 0.1, h * 0.15); ctx.lineTo(w * 0.35, h * 0.78); ctx.lineTo(w * 0.1, h * 0.78); ctx.closePath(); ctx.fill(); // Clock var cx = w * 0.9, cy = h * 0.12; Draw.circle(ctx, cx, cy, 18, '#FFFFFF'); ctx.strokeStyle = '#333'; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(cx, cy, 18, 0, Math.PI * 2); ctx.stroke(); var angle = t * 0.1; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(cx + Math.cos(angle) * 12, cy + Math.sin(angle) * 12); ctx.stroke(); }, particles: { type: 'dust', count: 20, color: '#DDC888' } }, bedroom: { meta: { id: 'indoor_bedroom', mood: 'cozy', colors: ['#2a1f3d', '#3d2b5a', '#e8a87c', '#ffd166'], tags: ['cozy', 'night', 'home', 'warm'], description: 'Cozy bedroom at night with warm lamp glow and string lights', compatibleMusicMoods: ['calm', 'dreamy', 'ambient'], recommendedFor: ['story', 'creative', 'pet'] }, colors: ['#2a1f3d', '#3d2b5a', '#e8a87c', '#ffd166'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90); Draw.rect(ctx, 0, h * 0.8, w, h * 0.2, H.darken(c[1], 0.3)); }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(303); // Window with moonlight Draw.rect(ctx, w * 0.6, h * 0.1, w * 0.2, h * 0.3, '#1a1a3e'); Draw.circle(ctx, w * 0.72, h * 0.18, 15, '#dde8ff'); Draw.glow(ctx, w * 0.72, h * 0.18, 40, '#aabbee'); ctx.strokeStyle = H.rgba('#FFFFFF', 0.3); ctx.lineWidth = 3; ctx.strokeRect(w * 0.6, h * 0.1, w * 0.2, h * 0.3); ctx.beginPath(); ctx.moveTo(w * 0.7, h * 0.1); ctx.lineTo(w * 0.7, h * 0.4); ctx.stroke(); // Bed Draw.rect(ctx, w * 0.05, h * 0.55, w * 0.45, h * 0.25, '#6b4f7a'); Draw.rect(ctx, w * 0.05, h * 0.55, w * 0.12, h * 0.22, '#7a5f8a'); Draw.rect(ctx, w * 0.05, h * 0.5, w * 0.45, h * 0.06, H.darken('#6b4f7a', 0.3)); // Lamp with warm glow var lampX = w * 0.88, lampY = h * 0.45; Draw.rect(ctx, lampX - 3, lampY, 6, h * 0.35, '#666'); Draw.polygon(ctx, lampX, lampY - 5, 18, 3, c[2], -Math.PI / 2); var lampGlow = 0.2 + Math.sin(t * 0.5) * 0.05; Draw.glow(ctx, lampX, lampY - 10, 80, c[3]); ctx.fillStyle = H.rgba(c[3], lampGlow); ctx.beginPath(); ctx.moveTo(lampX - 40, lampY); ctx.lineTo(lampX + 40, lampY); ctx.lineTo(lampX + 80, h * 0.8); ctx.lineTo(lampX - 80, h * 0.8); ctx.closePath(); ctx.fill(); // String lights across top ctx.strokeStyle = H.rgba('#FFFFFF', 0.1); ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(0, h * 0.05); for (var x = 0; x < w; x += 5) { ctx.lineTo(x, h * 0.05 + Math.sin(x * 0.02) * 10); } ctx.stroke(); for (var i = 0; i < 12; i++) { var lx = w * 0.05 + i * w * 0.08; var ly = h * 0.05 + Math.sin(lx * 0.02) * 10; var flicker = 0.5 + Math.sin(t * 2 + i * 1.3) * 0.3; var lc = H.pick(['#ff6b6b', '#ffd166', '#06d6a0', '#118ab2', '#ef476f']); Draw.circle(ctx, lx, ly + 5, 4, H.rgba(lc, flicker)); Draw.glow(ctx, lx, ly + 5, 12, lc); } // Bookshelf Draw.rect(ctx, w * 0.55, h * 0.5, w * 0.15, h * 0.3, '#5a3e2b'); for (var s = 0; s < 3; s++) { Draw.rect(ctx, w * 0.55, h * 0.5 + s * h * 0.1, w * 0.15, 3, '#4a2e1b'); for (var b = 0; b < 4; b++) { var bw = 6 + rng() * 8; var bc = H.pick(['#cc4444', '#4477bb', '#44aa66', '#ddaa33', '#8855aa']); Draw.rect(ctx, w * 0.56 + b * (bw + 3), h * 0.5 + s * h * 0.1 + 4, bw, h * 0.09, bc); } } }, particles: { type: 'fireflies', count: 8, color: '#ffd166' } }, kitchen: { meta: { id: 'indoor_kitchen', mood: 'warm', colors: ['#fff8e7', '#f0d9a0', '#c97b3a', '#8b4513'], tags: ['cooking', 'home', 'warm', 'food'], description: 'Bright kitchen with checkered floor, cabinets, and warm appliance glow', compatibleMusicMoods: ['cheerful', 'upbeat', 'calm'], recommendedFor: ['creative', 'pet', 'puzzle'] }, colors: ['#fff8e7', '#f0d9a0', '#c97b3a', '#8b4513'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], H.darken(c[0], 0.05)], 90); // Checkered floor var tileSize = 30; for (var ty = h * 0.75; ty < h; ty += tileSize) { for (var tx = 0; tx < w; tx += tileSize) { var checker = ((Math.floor(tx / tileSize) + Math.floor(ty / tileSize)) % 2 === 0); Draw.rect(ctx, tx, ty, tileSize, tileSize, checker ? '#e8e0d0' : '#c8b8a0'); } } }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(404); // Upper cabinets for (var i = 0; i < 4; i++) { var cx = w * 0.05 + i * w * 0.24; Draw.rect(ctx, cx, h * 0.08, w * 0.2, h * 0.2, c[2]); Draw.rect(ctx, cx + 3, h * 0.1, w * 0.2 - 6, h * 0.16, H.lighten(c[2], 0.15)); Draw.circle(ctx, cx + w * 0.1, h * 0.18, 3, '#brass'); Draw.circle(ctx, cx + w * 0.1, h * 0.18, 3, '#aa8844'); } // Counter Draw.rect(ctx, 0, h * 0.42, w, h * 0.04, '#ddd0bb'); Draw.rect(ctx, 0, h * 0.46, w, h * 0.29, c[3]); // Stove var sx = w * 0.35; Draw.rect(ctx, sx, h * 0.32, w * 0.2, h * 0.1, '#444'); for (var b = 0; b < 4; b++) { var bx = sx + w * 0.025 + b * w * 0.045; var burnerGlow = Math.sin(t * 1.5 + b * 0.8) > 0.5 ? 0.4 : 0; Draw.circle(ctx, bx, h * 0.37, 8, H.rgba('#ff4400', burnerGlow)); Draw.circle(ctx, bx, h * 0.37, 12, '#555'); ctx.strokeStyle = '#666'; ctx.lineWidth = 1; ctx.beginPath(); ctx.arc(bx, h * 0.37, 10, 0, Math.PI * 2); ctx.stroke(); } // Fridge Draw.rect(ctx, w * 0.82, h * 0.15, w * 0.15, h * 0.6, '#d8d8d8'); Draw.rect(ctx, w * 0.83, h * 0.16, w * 0.13, h * 0.3, '#e8e8e8'); Draw.rect(ctx, w * 0.83, h * 0.48, w * 0.13, h * 0.25, '#e8e8e8'); Draw.rect(ctx, w * 0.95, h * 0.28, 3, 20, '#999'); Draw.rect(ctx, w * 0.95, h * 0.58, 3, 20, '#999'); // Sink Draw.rect(ctx, w * 0.1, h * 0.35, w * 0.15, h * 0.07, '#bbb'); Draw.rect(ctx, w * 0.15, h * 0.3, 4, h * 0.05, '#999'); // Hanging pots for (var p = 0; p < 3; p++) { var px = w * 0.62 + p * w * 0.06; var sway = Math.sin(t * 0.3 + p) * 2; ctx.strokeStyle = '#777'; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(px, h * 0.08); ctx.lineTo(px + sway, h * 0.14); ctx.stroke(); Draw.circle(ctx, px + sway, h * 0.16, 10 + p * 2, H.pick(['#884422', '#666', '#aa6633'])); } // Window light Draw.rect(ctx, w * 0.03, h * 0.08, w * 0.12, h * 0.18, '#aaddff'); ctx.strokeStyle = '#FFFFFF'; ctx.lineWidth = 3; ctx.strokeRect(w * 0.03, h * 0.08, w * 0.12, h * 0.18); }, particles: { type: 'dust', count: 12, color: '#EECC88' } }, arcade: { meta: { id: 'indoor_arcade', mood: 'energetic', colors: ['#0d0d1a', '#1a0a2e', '#ff00ff', '#00ffff'], tags: ['neon', 'retro', 'gaming', 'dark'], description: 'Dark arcade with neon-lit cabinets, glowing screens, and retro vibes', compatibleMusicMoods: ['energetic', 'retro', 'electronic'], recommendedFor: ['action', 'racing', 'sports'] }, colors: ['#0d0d1a', '#1a0a2e', '#ff00ff', '#00ffff'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90); // Dark reflective floor Draw.rect(ctx, 0, h * 0.8, w, h * 0.2, '#0a0a15'); Draw.grid(ctx, w, h * 0.2, 40, H.rgba(c[2], 0.05), 1); // Neon strip on ceiling var neonPulse = 0.3 + Math.sin(t * 1.2) * 0.15; Draw.rect(ctx, 0, 0, w, 4, H.rgba(c[2], neonPulse)); Draw.rect(ctx, 0, h * 0.8, w, 2, H.rgba(c[3], neonPulse * 0.6)); }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(505); // Arcade cabinets for (var i = 0; i < 6; i++) { var ax = w * 0.05 + i * w * 0.155; var cabColor = H.pick(['#222233', '#1a1a2e', '#2a1a2e']); Draw.rect(ctx, ax, h * 0.3, w * 0.1, h * 0.5, cabColor); // Screen glow var screenColor = H.pick([c[2], c[3], '#44ff44', '#ffaa00']); var flicker = 0.5 + Math.sin(t * (3 + rng()) + i * 2) * 0.2; Draw.rect(ctx, ax + 5, h * 0.33, w * 0.1 - 10, h * 0.18, H.rgba(screenColor, flicker)); Draw.glow(ctx, ax + w * 0.05, h * 0.42, 40, screenColor); // Control panel Draw.rect(ctx, ax + 3, h * 0.55, w * 0.1 - 6, h * 0.08, '#333'); // Joystick Draw.circle(ctx, ax + w * 0.03, h * 0.59, 4, '#888'); // Buttons for (var b = 0; b < 3; b++) { Draw.circle(ctx, ax + w * 0.06 + b * 10, h * 0.59, 3, H.pick(['#ff3333', '#33ff33', '#3333ff'])); } } // Neon signs on wall ctx.font = 'bold 16px monospace'; var signGlow = 0.6 + Math.sin(t * 2) * 0.3; ctx.fillStyle = H.rgba(c[2], signGlow); ctx.shadowColor = c[2]; ctx.shadowBlur = 15; ctx.fillText('PLAY', w * 0.15, h * 0.15); ctx.fillStyle = H.rgba(c[3], signGlow); ctx.shadowColor = c[3]; ctx.fillText('HIGH SCORE', w * 0.55, h * 0.15); ctx.shadowBlur = 0; // Floor reflections for (var r = 0; r < 6; r++) { var rx = w * 0.05 + r * w * 0.155 + w * 0.05; var refColor = H.pick([c[2], c[3], '#44ff44']); Draw.glow(ctx, rx, h * 0.85, 25, refColor); } // Scanlines Draw.scanlines(ctx, w, h, 3, H.rgba('#000000', 0.08)); }, particles: { type: 'sparkles', count: 20, color: '#ff00ff' } }, office: { meta: { id: 'indoor_office', mood: 'focused', colors: ['#e8e4dc', '#c5bfb2', '#4a6fa5', '#2c3e50'], tags: ['work', 'modern', 'clean', 'professional'], description: 'Modern office with monitor glow, clean desks, and large windows', compatibleMusicMoods: ['calm', 'focused', 'ambient'], recommendedFor: ['puzzle', 'trivia', 'creative'] }, colors: ['#e8e4dc', '#c5bfb2', '#4a6fa5', '#2c3e50'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], H.darken(c[0], 0.08)], 90); Draw.rect(ctx, 0, h * 0.8, w, h * 0.2, '#b0a898'); }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(606); // Large windows for (var i = 0; i < 3; i++) { var wx = w * 0.05 + i * w * 0.32; Draw.rect(ctx, wx, h * 0.05, w * 0.25, h * 0.4, '#aaccee'); ctx.strokeStyle = '#ddd'; ctx.lineWidth = 4; ctx.strokeRect(wx, h * 0.05, w * 0.25, h * 0.4); ctx.beginPath(); ctx.moveTo(wx + w * 0.125, h * 0.05); ctx.lineTo(wx + w * 0.125, h * 0.45); ctx.stroke(); // Sky through window Draw.circle(ctx, wx + w * 0.18, h * 0.15, 8, '#fff8dd'); } // Desks with monitors for (var d = 0; d < 3; d++) { var dx = w * 0.08 + d * w * 0.32; // Desk Draw.rect(ctx, dx, h * 0.6, w * 0.22, h * 0.03, '#8b7355'); Draw.rect(ctx, dx + 5, h * 0.63, 4, h * 0.17, '#7a6245'); Draw.rect(ctx, dx + w * 0.19, h * 0.63, 4, h * 0.17, '#7a6245'); // Monitor var monX = dx + w * 0.05; Draw.rect(ctx, monX, h * 0.48, w * 0.12, h * 0.1, '#222'); var screenGlow = 0.6 + Math.sin(t * 0.5 + d) * 0.15; Draw.rect(ctx, monX + 3, h * 0.49, w * 0.12 - 6, h * 0.08, H.rgba(c[2], screenGlow)); Draw.rect(ctx, monX + w * 0.055, h * 0.58, 6, h * 0.02, '#333'); Draw.rect(ctx, monX + w * 0.035, h * 0.598, w * 0.05, 3, '#333'); // Keyboard Draw.rect(ctx, dx + w * 0.04, h * 0.585, w * 0.08, h * 0.012, '#444'); } // Ceiling lights for (var l = 0; l < 4; l++) { var lx = w * 0.12 + l * w * 0.23; Draw.rect(ctx, lx, 0, w * 0.12, 6, '#eee'); var lightFlicker = 0.12 + Math.sin(t * 0.3 + l * 0.5) * 0.03; ctx.fillStyle = H.rgba('#FFFFFF', lightFlicker); ctx.beginPath(); ctx.moveTo(lx, 6); ctx.lineTo(lx + w * 0.12, 6); ctx.lineTo(lx + w * 0.18, h * 0.5); ctx.lineTo(lx - w * 0.06, h * 0.5); ctx.closePath(); ctx.fill(); } // Plant in corner Draw.rect(ctx, w * 0.92, h * 0.6, 14, h * 0.2, '#8b6914'); Draw.circle(ctx, w * 0.928, h * 0.55, 20, '#3a7a3a'); Draw.circle(ctx, w * 0.94, h * 0.5, 14, '#4a8a4a'); Draw.circle(ctx, w * 0.916, h * 0.48, 12, '#3a7a3a'); }, particles: { type: 'dust', count: 10, color: '#DDDDCC' } }, library: { meta: { id: 'indoor_library', mood: 'serene', colors: ['#2c1810', '#4a3020', '#c4956a', '#f4e4c1'], tags: ['books', 'quiet', 'knowledge', 'wood'], description: 'Grand library with towering bookshelves, warm wood, and reading lamps', compatibleMusicMoods: ['calm', 'serene', 'classical'], recommendedFor: ['story', 'trivia', 'puzzle', 'rpg'] }, colors: ['#2c1810', '#4a3020', '#c4956a', '#f4e4c1'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [H.darken(c[0], 0.2), c[0]], 90); Draw.rect(ctx, 0, h * 0.85, w, h * 0.15, H.darken(c[1], 0.3)); // Wooden floor planks for (var p = 0; p < 12; p++) { var px = p * (w / 12); ctx.strokeStyle = H.rgba('#000', 0.1); ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(px, h * 0.85); ctx.lineTo(px, h); ctx.stroke(); } }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(707); var bookColors = ['#8b2500', '#2e5090', '#1a6030', '#8b6914', '#6a1b6a', '#cc5533', '#336677']; // Tall bookshelves on sides for (var side = 0; side < 2; side++) { var sx = side === 0 ? 0 : w * 0.78; var sw = w * 0.22; Draw.rect(ctx, sx, h * 0.02, sw, h * 0.83, c[1]); // Shelves for (var sh = 0; sh < 7; sh++) { var sy = h * 0.05 + sh * h * 0.115; Draw.rect(ctx, sx, sy + h * 0.1, sw, 4, H.darken(c[1], 0.2)); // Books var bx = sx + 5; while (bx < sx + sw - 8) { var bw = 5 + rng() * 10; var bh = h * 0.08 + rng() * h * 0.02; var bc = bookColors[Math.floor(rng() * bookColors.length)]; Draw.rect(ctx, bx, sy + h * 0.1 - bh, bw, bh, bc); bx += bw + 1; } } } // Center reading area Draw.rect(ctx, w * 0.35, h * 0.65, w * 0.3, h * 0.04, c[2]); Draw.rect(ctx, w * 0.4, h * 0.69, 5, h * 0.16, H.darken(c[2], 0.3)); Draw.rect(ctx, w * 0.58, h * 0.69, 5, h * 0.16, H.darken(c[2], 0.3)); // Open book on table Draw.rect(ctx, w * 0.44, h * 0.62, w * 0.06, h * 0.03, c[3]); Draw.rect(ctx, w * 0.5, h * 0.62, w * 0.06, h * 0.03, H.darken(c[3], 0.05)); // Reading lamps for (var l = 0; l < 2; l++) { var lx = w * 0.38 + l * w * 0.24; Draw.rect(ctx, lx, h * 0.5, 3, h * 0.15, '#886644'); var lampGlow = 0.25 + Math.sin(t * 0.4 + l * Math.PI) * 0.08; Draw.polygon(ctx, lx + 1, h * 0.49, 14, 3, '#aa8855', -Math.PI / 2); Draw.glow(ctx, lx + 1, h * 0.47, 50, '#ffcc66'); ctx.fillStyle = H.rgba('#ffdd88', lampGlow); ctx.beginPath(); ctx.moveTo(lx - 18, h * 0.5); ctx.lineTo(lx + 20, h * 0.5); ctx.lineTo(lx + 40, h * 0.85); ctx.lineTo(lx - 38, h * 0.85); ctx.closePath(); ctx.fill(); } // Arched window in back center var awx = w * 0.4, awy = h * 0.08, aww = w * 0.2, awh = h * 0.35; Draw.rect(ctx, awx, awy + awh * 0.3, aww, awh * 0.7, '#334466'); ctx.fillStyle = '#334466'; ctx.beginPath(); ctx.arc(awx + aww / 2, awy + awh * 0.3, aww / 2, Math.PI, 0); ctx.fill(); ctx.strokeStyle = c[2]; ctx.lineWidth = 4; ctx.beginPath(); ctx.arc(awx + aww / 2, awy + awh * 0.3, aww / 2, Math.PI, 0); ctx.stroke(); ctx.strokeRect(awx, awy + awh * 0.3, aww, awh * 0.7); // Moonlight through window Draw.glow(ctx, awx + aww / 2, awy + awh * 0.3, 60, '#6688aa'); }, particles: { type: 'dust', count: 15, color: '#CCBB88' } }, gym: { meta: { id: 'indoor_gym', mood: 'energetic', colors: ['#1a1a24', '#2a2a3a', '#ff4444', '#ff8800'], tags: ['fitness', 'sports', 'energy', 'active'], description: 'Modern gym with equipment silhouettes, rubber floor, and bright overhead lights', compatibleMusicMoods: ['energetic', 'intense', 'upbeat'], recommendedFor: ['action', 'sports', 'racing'] }, colors: ['#1a1a24', '#2a2a3a', '#ff4444', '#ff8800'], renderBase: function(ctx, w, h, c, Draw, t) { Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90); // Rubber floor with subtle texture Draw.rect(ctx, 0, h * 0.78, w, h * 0.22, '#222230'); var rng = H.seededRandom(808); for (var i = 0; i < 40; i++) { Draw.circle(ctx, rng() * w, h * 0.78 + rng() * h * 0.22, 1, H.rgba('#333344', 0.5)); } }, renderMid: function(ctx, w, h, c, Draw, t) { var rng = H.seededRandom(809); // Wall mirror Draw.rect(ctx, w * 0.1, h * 0.1, w * 0.8, h * 0.45, H.rgba('#445566', 0.15)); ctx.strokeStyle = H.rgba('#666', 0.3); ctx.lineWidth = 3; ctx.strokeRect(w * 0.1, h * 0.1, w * 0.8, h * 0.45); // Dumbbells rack for (var d = 0; d < 6; d++) { var dx = w * 0.05 + d * w * 0.05; var dy = h * 0.7; Draw.rect(ctx, dx, dy, 8, 4, '#555'); Draw.circle(ctx, dx - 2, dy + 2, 5, '#444'); Draw.circle(ctx, dx + 10, dy + 2, 5, '#444'); } // Bench press Draw.rect(ctx, w * 0.55, h * 0.65, w * 0.15, h * 0.02, '#444'); Draw.rect(ctx, w * 0.57, h * 0.67, 4, h * 0.11, '#555'); Draw.rect(ctx, w * 0.68, h * 0.67, 4, h * 0.11, '#555'); // Barbell Draw.rect(ctx, w * 0.5, h * 0.6, w * 0.25, 3, '#888'); Draw.rect(ctx, w * 0.5, h * 0.585, 8, 18, '#666'); Draw.rect(ctx, w * 0.73, h * 0.585, 8, 18, '#666'); // Treadmill Draw.rect(ctx, w * 0.8, h * 0.55, w * 0.12, h * 0.23, '#333'); Draw.rect(ctx, w * 0.81, h * 0.63, w * 0.1, h * 0.13, '#222'); var beltMove = (t * 2) % 1; for (var s = 0; s < 6; s++) { var sy = h * 0.63 + (s / 6 + beltMove / 6) * h * 0.13; if (sy < h * 0.76) Draw.rect(ctx, w * 0.81, sy, w * 0.1, 1, H.rgba('#444', 0.5)); } // Overhead lights for (var l = 0; l < 5; l++) { var lx = w * 0.1 + l * w * 0.2; Draw.rect(ctx, lx, 0, w * 0.08, 8, '#eee'); var intensity = 0.08 + Math.sin(t * 0.2 + l * 0.3) * 0.02; ctx.fillStyle = H.rgba('#FFFFFF', intensity); ctx.beginPath(); ctx.moveTo(lx, 8); ctx.lineTo(lx + w * 0.08, 8); ctx.lineTo(lx + w * 0.14, h * 0.78); ctx.lineTo(lx - w * 0.06, h * 0.78); ctx.closePath(); ctx.fill(); } // Red accent stripe on wall var stripeGlow = 0.6 + Math.sin(t * 0.8) * 0.2; Draw.rect(ctx, 0, h * 0.55, w, 4, H.rgba(c[2], stripeGlow)); // Motivational poster (abstract rectangle) Draw.rect(ctx, w * 0.38, h * 0.15, w * 0.12, h * 0.15, '#333'); Draw.rect(ctx, w * 0.39, h * 0.16, w * 0.1, h * 0.13, c[2]); }, particles: { type: 'dust', count: 8, color: '#887766' } } }); })(window.BackgroundEngine);