Initial commit

This commit is contained in:
Allen
2026-04-30 02:14:25 +00:00
commit 7090e6f01d
243 changed files with 115122 additions and 0 deletions
@@ -0,0 +1,275 @@
// space.js — Space theme for procedural background system
// 8 variants: nebula, asteroidField, deepSpace, planets, spaceStation, warpSpeed, satellites, blackHole
(function(engine) {
if (!engine) return;
var D = engine.Draw, H = engine.helpers;
engine.registerTheme('space', {
nebula: {
meta: { id: 'space_nebula', mood: 'wonder', colors: ['#0B0B2B', '#1A0A3E', '#3D1A78', '#7B2FBE'], tags: ['cosmic', 'colorful', 'calm'], description: 'Swirling nebula clouds with twinkling stars', compatibleMusicMoods: ['ambient', 'dreamy', 'epic'], recommendedFor: ['puzzle', 'story', 'creative'] },
colors: ['#0B0B2B', '#1A0A3E', '#3D1A78', '#7B2FBE'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1], c[2]], 90);
var rng = H.seededRandom(101);
for (var i = 0; i < 5; i++) {
var cx = rng() * w, cy = rng() * h;
var r = 80 + rng() * 200;
var pulse = 0.9 + Math.sin(t * 0.3 + i) * 0.1;
Draw.glow(ctx, cx, cy, r * pulse, c[3]);
Draw.glow(ctx, cx + 40, cy - 30, r * 0.6 * pulse, c[2]);
}
},
renderMid: function(ctx, w, h, c, Draw, t) {
Draw.stars(ctx, w, h, 180, '#FFFFFF', 10, [0.5, 2]);
Draw.stars(ctx, w, h, 40, c[3], 20, [1, 3]);
var rng = H.seededRandom(102);
for (var i = 0; i < 3; i++) {
var x = rng() * w, y = rng() * h * 0.8;
var flicker = 0.5 + Math.sin(t * 2 + i * 1.7) * 0.3;
Draw.glow(ctx, x, y, 4 + rng() * 4, H.rgba('#FFFFFF', flicker));
}
},
particles: { type: 'sparkles', count: 40, color: '#CCBBFF' }
},
asteroidField: {
meta: { id: 'space_asteroidField', mood: 'tense', colors: ['#0A0A14', '#1C1C2E', '#4A3A2A', '#8B7355'], tags: ['rocky', 'danger', 'dark'], description: 'Rocky asteroids drifting through dark space', compatibleMusicMoods: ['tense', 'action', 'ambient'], recommendedFor: ['action', 'racing', 'sports'] },
colors: ['#0A0A14', '#1C1C2E', '#4A3A2A', '#8B7355'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90);
Draw.stars(ctx, w, h, 100, '#FFFFFF', 30, [0.3, 1.5]);
},
renderMid: function(ctx, w, h, c, Draw, t) {
var rng = H.seededRandom(200);
for (var i = 0; i < 18; i++) {
var ax = (rng() * w + t * (5 + rng() * 15)) % (w + 100) - 50;
var ay = rng() * h;
var ar = 8 + rng() * 35;
var sides = 5 + Math.floor(rng() * 4);
var rot = rng() * Math.PI * 2 + t * (rng() - 0.5) * 0.2;
var shade = H.blendColor(c[2], c[3], rng());
Draw.polygon(ctx, ax, ay, ar, sides, shade, rot);
Draw.polygon(ctx, ax - ar * 0.15, ay - ar * 0.15, ar * 0.85, sides, H.lighten(shade, 0.15), rot);
}
},
particles: { type: 'dust', count: 25, color: '#887766' }
},
deepSpace: {
meta: { id: 'space_deepSpace', mood: 'serene', colors: ['#000005', '#050510', '#0A0A20', '#111133'], tags: ['dark', 'vast', 'minimal'], description: 'The void of deep space with distant starlight', compatibleMusicMoods: ['ambient', 'calm', 'dreamy'], recommendedFor: ['puzzle', 'story', 'rpg'] },
colors: ['#000005', '#050510', '#0A0A20', '#111133'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1], c[2]], 90);
Draw.glow(ctx, w * 0.8, h * 0.15, 150, H.rgba('#1A1A55', 0.3));
},
renderMid: function(ctx, w, h, c, Draw, t) {
Draw.stars(ctx, w, h, 300, '#FFFFFF', 50, [0.2, 1.5]);
Draw.stars(ctx, w, h, 20, '#AABBFF', 51, [1.5, 3]);
var rng = H.seededRandom(300);
for (var i = 0; i < 5; i++) {
var x = rng() * w, y = rng() * h;
var twinkle = 0.3 + Math.sin(t * 1.5 + rng() * 10) * 0.3;
Draw.glow(ctx, x, y, 8 + rng() * 12, H.rgba('#4466CC', twinkle));
}
},
particles: { type: 'stars', count: 60, color: '#FFFFFF' }
},
planets: {
meta: { id: 'space_planets', mood: 'wonder', colors: ['#0B0B2B', '#0F1640', '#CC5533', '#44BBAA'], tags: ['planetary', 'colorful', 'majestic'], description: 'Colorful planets against a starry backdrop', compatibleMusicMoods: ['epic', 'dreamy', 'ambient'], recommendedFor: ['creative', 'rpg', 'story'] },
colors: ['#0B0B2B', '#0F1640', '#CC5533', '#44BBAA'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90);
Draw.stars(ctx, w, h, 150, '#FFFFFF', 40, [0.3, 1.8]);
},
renderMid: function(ctx, w, h, c, Draw, t) {
var rng = H.seededRandom(400);
// Large planet
var px = w * 0.7, py = h * 0.35, pr = 60 + rng() * 40;
var g = Draw.radialGradient(ctx, px - pr * 0.3, py - pr * 0.3, pr * 1.2, [[0, H.lighten(c[2], 0.3)], [0.6, c[2]], [1, H.darken(c[2], 0.6)]]);
ctx.fillStyle = g;
ctx.beginPath(); ctx.arc(px, py, pr, 0, Math.PI * 2); ctx.fill();
// Ring
ctx.strokeStyle = H.rgba(c[2], 0.4);
ctx.lineWidth = 3;
ctx.beginPath(); ctx.ellipse(px, py, pr * 1.8, pr * 0.3, -0.2, 0, Math.PI * 2); ctx.stroke();
// Small planet
var sx = w * 0.25, sy = h * 0.6, sr = 25 + rng() * 15;
var g2 = Draw.radialGradient(ctx, sx - sr * 0.3, sy - sr * 0.3, sr * 1.2, [[0, H.lighten(c[3], 0.3)], [0.7, c[3]], [1, H.darken(c[3], 0.5)]]);
ctx.fillStyle = g2;
ctx.beginPath(); ctx.arc(sx, sy, sr, 0, Math.PI * 2); ctx.fill();
// Moon
var bob = Math.sin(t * 0.5) * 5;
var mx = w * 0.15, my = h * 0.25 + bob;
Draw.circle(ctx, mx, my, 10, '#AAAAAA');
Draw.glow(ctx, mx, my, 18, H.rgba('#AAAAAA', 0.2));
},
particles: { type: 'sparkles', count: 30, color: '#FFFFFF' }
},
spaceStation: {
meta: { id: 'space_spaceStation', mood: 'focused', colors: ['#0A0A1E', '#151530', '#3A3A55', '#88AACC'], tags: ['tech', 'structure', 'industrial'], description: 'Orbital station with geometric structures', compatibleMusicMoods: ['ambient', 'tense', 'electronic'], recommendedFor: ['puzzle', 'action', 'physics'] },
colors: ['#0A0A1E', '#151530', '#3A3A55', '#88AACC'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90);
Draw.stars(ctx, w, h, 100, '#FFFFFF', 60, [0.3, 1.2]);
// Earth glow on horizon
Draw.glow(ctx, w * 0.5, h * 1.1, h * 0.5, H.rgba('#2255AA', 0.25));
},
renderMid: function(ctx, w, h, c, Draw, t) {
var rng = H.seededRandom(500);
// Station core
Draw.rect(ctx, w * 0.35, h * 0.38, w * 0.3, h * 0.06, c[2]);
Draw.rect(ctx, w * 0.33, h * 0.4, w * 0.34, h * 0.02, H.lighten(c[2], 0.1));
// Solar panels
for (var s = 0; s < 2; s++) {
var sx = s === 0 ? w * 0.15 : w * 0.7;
Draw.rect(ctx, sx, h * 0.36, w * 0.14, h * 0.1, H.rgba(c[3], 0.5));
Draw.grid(ctx, w * 0.14, h * 0.1, 10, H.rgba(c[2], 0.3), 0.5);
ctx.save(); ctx.translate(sx, h * 0.36);
Draw.grid(ctx, w * 0.14, h * 0.1, 12, H.rgba('#4466AA', 0.3), 0.5);
ctx.restore();
}
// Struts
Draw.rect(ctx, w * 0.29, h * 0.4, w * 0.04, h * 0.005, c[2]);
Draw.rect(ctx, w * 0.67, h * 0.4, w * 0.04, h * 0.005, c[2]);
// Blinking lights
for (var i = 0; i < 6; i++) {
var lx = w * 0.36 + i * (w * 0.28 / 5);
var blink = Math.sin(t * 3 + i * 1.2) > 0.3 ? 0.9 : 0.15;
Draw.circle(ctx, lx, h * 0.38, 2, H.rgba('#FF3333', blink));
}
},
particles: { type: 'dust', count: 15, color: '#667788' }
},
warpSpeed: {
meta: { id: 'space_warpSpeed', mood: 'energetic', colors: ['#000010', '#0A0A30', '#2244AA', '#66BBFF'], tags: ['fast', 'streaks', 'intense'], description: 'Light streaks from faster-than-light travel', compatibleMusicMoods: ['energetic', 'electronic', 'epic'], recommendedFor: ['racing', 'action', 'sports'] },
colors: ['#000010', '#0A0A30', '#2244AA', '#66BBFF'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90);
// Central tunnel glow
var pulse = 0.6 + Math.sin(t * 2) * 0.15;
Draw.glow(ctx, w * 0.5, h * 0.5, Math.min(w, h) * 0.4 * pulse, c[2]);
Draw.glow(ctx, w * 0.5, h * 0.5, Math.min(w, h) * 0.15, H.rgba(c[3], 0.4));
},
renderMid: function(ctx, w, h, c, Draw, t) {
var rng = H.seededRandom(600);
var cx = w * 0.5, cy = h * 0.5;
ctx.lineWidth = 1.5;
for (var i = 0; i < 60; i++) {
var angle = rng() * Math.PI * 2;
var dist = 30 + rng() * Math.min(w, h) * 0.45;
var len = 20 + rng() * 60;
var speed = 0.5 + rng() * 2;
var offset = (t * speed * 40 + rng() * 200) % (dist + len);
var x1 = cx + Math.cos(angle) * offset;
var y1 = cy + Math.sin(angle) * offset;
var x2 = cx + Math.cos(angle) * (offset + len);
var y2 = cy + Math.sin(angle) * (offset + len);
var alpha = H.clamp(0.15 + (offset / dist) * 0.6, 0, 0.8);
var col = rng() > 0.7 ? c[3] : '#FFFFFF';
ctx.strokeStyle = H.rgba(col, alpha);
ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke();
}
},
particles: { type: 'particles', count: 30, color: '#88CCFF' }
},
satellites: {
meta: { id: 'space_satellites', mood: 'calm', colors: ['#060615', '#101030', '#334466', '#AACCDD'], tags: ['orbital', 'tech', 'night'], description: 'Satellites orbiting above a dark Earth', compatibleMusicMoods: ['ambient', 'calm', 'dreamy'], recommendedFor: ['puzzle', 'trivia', 'creative'] },
colors: ['#060615', '#101030', '#334466', '#AACCDD'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[1]], 90);
// Earth curve at bottom
var g = Draw.radialGradient(ctx, w * 0.5, h * 1.6, h * 0.9, [[0, '#1A3355'], [0.5, '#0D1B2A'], [1, H.rgba(c[0], 0)]]);
ctx.fillStyle = g;
ctx.beginPath(); ctx.arc(w * 0.5, h * 1.6, h * 0.9, 0, Math.PI * 2); ctx.fill();
// Atmosphere glow
Draw.glow(ctx, w * 0.5, h * 1.05, h * 0.3, H.rgba('#3388CC', 0.15));
Draw.stars(ctx, w, h * 0.7, 120, '#FFFFFF', 70, [0.3, 1.5]);
},
renderMid: function(ctx, w, h, c, Draw, t) {
var rng = H.seededRandom(700);
for (var i = 0; i < 5; i++) {
var orbit = 0.15 + rng() * 0.5;
var speed = 0.1 + rng() * 0.25;
var angle = t * speed + rng() * Math.PI * 2;
var ox = w * 0.5 + Math.cos(angle) * w * orbit;
var oy = h * 0.5 + Math.sin(angle) * h * orbit * 0.3;
// Satellite body
Draw.rect(ctx, ox - 4, oy - 2, 8, 4, c[2]);
// Solar panels
Draw.rect(ctx, ox - 14, oy - 1, 9, 2, H.rgba(c[3], 0.7));
Draw.rect(ctx, ox + 5, oy - 1, 9, 2, H.rgba(c[3], 0.7));
// Signal blink
var blink = Math.sin(t * 4 + i * 2) > 0.5 ? 0.8 : 0.1;
Draw.circle(ctx, ox, oy, 1.5, H.rgba('#FF4444', blink));
}
// Orbit lines (faint)
ctx.strokeStyle = H.rgba(c[2], 0.08);
ctx.lineWidth = 0.5;
for (var j = 0; j < 3; j++) {
var orb = 0.2 + j * 0.15;
ctx.beginPath();
ctx.ellipse(w * 0.5, h * 0.5, w * orb, h * orb * 0.3, 0, 0, Math.PI * 2);
ctx.stroke();
}
},
particles: { type: 'stars', count: 40, color: '#FFFFFF' }
},
blackHole: {
meta: { id: 'space_blackHole', mood: 'intense', colors: ['#000000', '#0A0510', '#220A33', '#FF6622'], tags: ['dark', 'gravity', 'dramatic'], description: 'A black hole bending light around its event horizon', compatibleMusicMoods: ['tense', 'epic', 'ambient'], recommendedFor: ['action', 'rpg', 'physics'] },
colors: ['#000000', '#0A0510', '#220A33', '#FF6622'],
renderBase: function(ctx, w, h, c, Draw, t) {
Draw.fillGradient(ctx, w, h, [c[0], c[0], c[1]], 90);
Draw.stars(ctx, w, h, 80, '#FFFFFF', 80, [0.3, 1]);
},
renderMid: function(ctx, w, h, c, Draw, t) {
var cx = w * 0.5, cy = h * 0.45;
var r = Math.min(w, h) * 0.15;
// Accretion disk
var rng = H.seededRandom(800);
ctx.save();
ctx.translate(cx, cy);
for (var ring = 5; ring >= 0; ring--) {
var rr = r * (1.3 + ring * 0.4);
var alpha = 0.08 + ring * 0.04;
var spin = t * (0.2 + ring * 0.05);
ctx.save();
ctx.rotate(spin);
var col = ring < 3 ? c[3] : c[2];
ctx.strokeStyle = H.rgba(col, alpha + Math.sin(t + ring) * 0.03);
ctx.lineWidth = 3 + ring * 1.5;
ctx.beginPath();
ctx.ellipse(0, 0, rr, rr * 0.22, 0, 0, Math.PI * 2);
ctx.stroke();
ctx.restore();
}
// Core glow
Draw.glow(ctx, 0, 0, r * 1.5, H.rgba(c[3], 0.35 + Math.sin(t * 1.5) * 0.1));
Draw.glow(ctx, 0, 0, r * 0.8, H.rgba(c[2], 0.4));
// Black center
var gc = Draw.radialGradient(ctx, 0, 0, r * 0.6, [[0, '#000000'], [0.7, '#000000'], [1, H.rgba('#000000', 0)]]);
ctx.fillStyle = gc;
ctx.beginPath(); ctx.arc(0, 0, r * 0.6, 0, Math.PI * 2); ctx.fill();
ctx.restore();
// Gravitational lensing — bent stars near hole
for (var i = 0; i < 12; i++) {
var a = rng() * Math.PI * 2;
var d = r * (1.1 + rng() * 0.8);
var sx = cx + Math.cos(a + t * 0.15) * d;
var sy = cy + Math.sin(a + t * 0.15) * d * 0.4;
var stretch = 1 + 2 / (1 + d / r);
ctx.fillStyle = H.rgba('#FFCC88', 0.4 + rng() * 0.3);
ctx.beginPath(); ctx.ellipse(sx, sy, 1.5 * stretch, 1, a, 0, Math.PI * 2); ctx.fill();
}
},
particles: { type: 'particles', count: 35, color: '#FF8844' }
}
});
})(window.BackgroundEngine);