diff options
| author | grothedev <grothedev@gmail.com> | 2026-05-29 21:49:20 -0400 |
|---|---|---|
| committer | grothedev <grothedev@gmail.com> | 2026-05-29 21:49:20 -0400 |
| commit | 6196004b51a6850909c154f5402ff4858eab479a (patch) | |
| tree | 126b8bb1600d0a656e0df016e25d08c390f3540e /web-timeplot/src/demos.js | |
| parent | 27dc5849c3eaf4824d79938e7077abdbe2c82e24 (diff) | |
mv web stuff to root project dirHEADprototypeframeworkmain
Diffstat (limited to 'web-timeplot/src/demos.js')
| -rw-r--r-- | web-timeplot/src/demos.js | 697 |
1 files changed, 0 insertions, 697 deletions
diff --git a/web-timeplot/src/demos.js b/web-timeplot/src/demos.js deleted file mode 100644 index 1dd6785..0000000 --- a/web-timeplot/src/demos.js +++ /dev/null @@ -1,697 +0,0 @@ -/** - * Preloaded Graphics Demos - * - * Each demo exports: - * - name: Display name - * - description: Short description - * - setup(app, state): Called once to create objects - * - update(app, state, objects): Called every frame - * - cleanup(app, objects): Called when switching demos - */ - -// ============================================================================ -// DEMO 1: BOUNCING PARTICLES -// ============================================================================ - -export const bouncingParticles = { - name: "Bouncing Particles", - description: "Colorful particles bouncing around the screen", - - setup(app, state) { - const particles = []; - const colors = [0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xf9ca24, 0x6c5ce7]; - - for (let i = 0; i < 50; i++) { - const particle = new PIXI.Graphics(); - const size = 5 + Math.random() * 10; - particle.circle(0, 0, size); - particle.fill(colors[Math.floor(Math.random() * colors.length)]); - - particle.x = Math.random() * app.screen.width; - particle.y = Math.random() * app.screen.height; - particle.vx = (Math.random() - 0.5) * 8; - particle.vy = (Math.random() - 0.5) * 8; - particle.size = size; - - app.stage.addChild(particle); - particles.push(particle); - } - - return { particles }; - }, - - update(app, state, objects) { - objects.particles.forEach(p => { - p.x += p.vx; - p.y += p.vy; - - // Bounce off edges - if (p.x < p.size || p.x > app.screen.width - p.size) p.vx *= -1; - if (p.y < p.size || p.y > app.screen.height - p.size) p.vy *= -1; - - // Clamp to screen - p.x = Math.max(p.size, Math.min(app.screen.width - p.size, p.x)); - p.y = Math.max(p.size, Math.min(app.screen.height - p.size, p.y)); - }); - }, - - cleanup(app, objects) { - objects.particles.forEach(p => p.destroy()); - } -}; - -// ============================================================================ -// DEMO 2: SPIROGRAPH -// ============================================================================ - -export const spirograph = { - name: "Spirograph", - description: "Mesmerizing geometric spiral patterns", - - setup(app, state) { - const graphics = new PIXI.Graphics(); - app.stage.addChild(graphics); - - return { - graphics, - angle: 0, - points: [] - }; - }, - - update(app, state, objects) { - const cx = app.screen.width / 2; - const cy = app.screen.height / 2; - const t = state.state.time.current; - - // Generate new point - const r1 = 150; - const r2 = 50; - const r3 = 30; - - const x = cx + Math.cos(t * 0.5) * r1 + Math.cos(t * 2) * r2 + Math.cos(t * 5) * r3; - const y = cy + Math.sin(t * 0.5) * r1 + Math.sin(t * 2) * r2 + Math.sin(t * 5) * r3; - - objects.points.push({ x, y }); - - // Keep only last 500 points - if (objects.points.length > 500) { - objects.points.shift(); - } - - // Draw trail - objects.graphics.clear(); - if (objects.points.length > 1) { - for (let i = 1; i < objects.points.length; i++) { - const alpha = i / objects.points.length; - const hue = (i / objects.points.length) * 360; - objects.graphics.moveTo(objects.points[i-1].x, objects.points[i-1].y); - objects.graphics.lineTo(objects.points[i].x, objects.points[i].y); - objects.graphics.stroke({ width: 2, color: hslToHex(hue, 100, 60), alpha }); - } - } - }, - - cleanup(app, objects) { - objects.graphics.destroy(); - } -}; - -// ============================================================================ -// DEMO 3: STARFIELD -// ============================================================================ - -export const starfield = { - name: "Starfield", - description: "Flying through space at warp speed", - - setup(app, state) { - const stars = []; - - for (let i = 0; i < 200; i++) { - const star = new PIXI.Graphics(); - star.circle(0, 0, 2); - star.fill(0xffffff); - - star.x = (Math.random() - 0.5) * app.screen.width * 2; - star.y = (Math.random() - 0.5) * app.screen.height * 2; - star.z = Math.random() * 1000; - - app.stage.addChild(star); - stars.push(star); - } - - return { stars }; - }, - - update(app, state, objects) { - const cx = app.screen.width / 2; - const cy = app.screen.height / 2; - const speed = 5; - - objects.stars.forEach(star => { - star.z -= speed; - - if (star.z <= 0) { - star.z = 1000; - star.x = (Math.random() - 0.5) * app.screen.width * 2; - star.y = (Math.random() - 0.5) * app.screen.height * 2; - } - - const screenX = cx + (star.x / star.z) * 200; - const screenY = cy + (star.y / star.z) * 200; - const size = (1 - star.z / 1000) * 4 + 1; - - star.x = star.x; - star.y = star.y; - star.position.set(screenX, screenY); - star.scale.set(size); - star.alpha = 1 - star.z / 1000; - }); - }, - - cleanup(app, objects) { - objects.stars.forEach(s => s.destroy()); - } -}; - -// ============================================================================ -// DEMO 4: WAVE INTERFERENCE -// ============================================================================ - -export const waveInterference = { - name: "Wave Interference", - description: "Rippling wave patterns", - - setup(app, state) { - const gridSize = 20; - const cols = Math.floor(app.screen.width / gridSize); - const rows = Math.floor(app.screen.height / gridSize); - const circles = []; - - for (let i = 0; i < cols; i++) { - for (let j = 0; j < rows; j++) { - const circle = new PIXI.Graphics(); - circle.circle(0, 0, 4); - circle.fill(0x4ecdc4); - circle.x = i * gridSize + gridSize / 2; - circle.y = j * gridSize + gridSize / 2; - circle.baseX = circle.x; - circle.baseY = circle.y; - - app.stage.addChild(circle); - circles.push(circle); - } - } - - return { circles, sources: [ - { x: app.screen.width * 0.3, y: app.screen.height * 0.5 }, - { x: app.screen.width * 0.7, y: app.screen.height * 0.5 } - ]}; - }, - - update(app, state, objects) { - const t = state.state.time.current; - - objects.circles.forEach(c => { - let totalOffset = 0; - - objects.sources.forEach(source => { - const dx = c.baseX - source.x; - const dy = c.baseY - source.y; - const dist = Math.sqrt(dx * dx + dy * dy); - totalOffset += Math.sin(dist * 0.05 - t * 3) * 10; - }); - - c.y = c.baseY + totalOffset; - c.alpha = 0.3 + (Math.sin(totalOffset * 0.1) + 1) * 0.35; - }); - }, - - cleanup(app, objects) { - objects.circles.forEach(c => c.destroy()); - } -}; - -// ============================================================================ -// DEMO 5: CIRCLE PACKING -// ============================================================================ - -export const circlePacking = { - name: "Circle Packing", - description: "Organic growth simulation", - - setup(app, state) { - const circles = []; - return { circles, attempts: 0 }; - }, - - update(app, state, objects) { - // Try to add a new circle each frame - const maxAttempts = 100; - const maxCircles = 150; - - if (objects.circles.length >= maxCircles) return; - - for (let i = 0; i < 10; i++) { - const x = Math.random() * app.screen.width; - const y = Math.random() * app.screen.height; - const minRadius = 5; - const maxRadius = 60; - - let valid = true; - let radius = minRadius; - - // Find largest radius that doesn't overlap - for (let r = minRadius; r < maxRadius; r++) { - let overlaps = false; - - for (const other of objects.circles) { - const dx = x - other.x; - const dy = y - other.y; - const dist = Math.sqrt(dx * dx + dy * dy); - - if (dist < r + other.radius + 2) { - overlaps = true; - break; - } - } - - if (overlaps) { - break; - } - radius = r; - } - - if (radius > minRadius) { - const circle = new PIXI.Graphics(); - circle.circle(0, 0, radius); - const hue = (objects.circles.length * 137.5) % 360; - circle.fill(hslToHex(hue, 70, 60)); - circle.x = x; - circle.y = y; - circle.radius = radius; - - app.stage.addChild(circle); - objects.circles.push(circle); - break; - } - } - }, - - cleanup(app, objects) { - objects.circles.forEach(c => c.destroy()); - } -}; - -// ============================================================================ -// DEMO 6: PERLIN FLOW FIELD -// ============================================================================ - -export const flowField = { - name: "Flow Field", - description: "Particles following a noise field", - - setup(app, state) { - const particles = []; - const colors = [0xff6b6b, 0x4ecdc4, 0x45b7d1, 0xf9ca24, 0x6c5ce7, 0xfeca57]; - - for (let i = 0; i < 300; i++) { - const particle = new PIXI.Graphics(); - particle.circle(0, 0, 2); - particle.fill(colors[Math.floor(Math.random() * colors.length)]); - particle.alpha = 0.6; - - particle.x = Math.random() * app.screen.width; - particle.y = Math.random() * app.screen.height; - particle.vx = 0; - particle.vy = 0; - particle.color = colors[Math.floor(Math.random() * colors.length)]; - - app.stage.addChild(particle); - particles.push(particle); - } - - return { particles }; - }, - - update(app, state, objects) { - const t = state.state.time.current; - - objects.particles.forEach(p => { - // Simple noise-like function using sin/cos - const angle = noise(p.x * 0.005, p.y * 0.005, t * 0.3) * Math.PI * 2; - - p.vx += Math.cos(angle) * 0.3; - p.vy += Math.sin(angle) * 0.3; - - // Damping - p.vx *= 0.95; - p.vy *= 0.95; - - p.x += p.vx; - p.y += p.vy; - - // Wrap around screen - if (p.x < 0) p.x = app.screen.width; - if (p.x > app.screen.width) p.x = 0; - if (p.y < 0) p.y = app.screen.height; - if (p.y > app.screen.height) p.y = 0; - }); - }, - - cleanup(app, objects) { - objects.particles.forEach(p => p.destroy()); - } -}; - -// ============================================================================ -// DEMO 7: DNA HELIX -// ============================================================================ - -export const dnaHelix = { - name: "DNA Helix", - description: "Rotating double helix structure", - - setup(app, state) { - const helix1 = []; - const helix2 = []; - const connectors = []; - const segments = 40; - - for (let i = 0; i < segments; i++) { - const sphere1 = new PIXI.Graphics(); - sphere1.circle(0, 0, 8); - sphere1.fill(0x4ecdc4); - app.stage.addChild(sphere1); - helix1.push(sphere1); - - const sphere2 = new PIXI.Graphics(); - sphere2.circle(0, 0, 8); - sphere2.fill(0xff6b6b); - app.stage.addChild(sphere2); - helix2.push(sphere2); - - const connector = new PIXI.Graphics(); - app.stage.addChild(connector); - connectors.push(connector); - } - - return { helix1, helix2, connectors }; - }, - - update(app, state, objects) { - const t = state.state.time.current; - const cx = app.screen.width / 2; - const cy = app.screen.height / 2; - const radius = 100; - const height = app.screen.height * 0.8; - const spacing = height / objects.helix1.length; - - objects.helix1.forEach((sphere, i) => { - const y = i * spacing - height / 2 + cy; - const angle = t + i * 0.3; - const x = cx + Math.cos(angle) * radius; - const z = Math.sin(angle) * radius; - - sphere.x = x; - sphere.y = y; - sphere.scale.set(1 + z / 200); - sphere.alpha = 0.5 + z / 400; - }); - - objects.helix2.forEach((sphere, i) => { - const y = i * spacing - height / 2 + cy; - const angle = t + i * 0.3 + Math.PI; - const x = cx + Math.cos(angle) * radius; - const z = Math.sin(angle) * radius; - - sphere.x = x; - sphere.y = y; - sphere.scale.set(1 + z / 200); - sphere.alpha = 0.5 + z / 400; - }); - - // Draw connectors - objects.connectors.forEach((connector, i) => { - connector.clear(); - connector.moveTo(objects.helix1[i].x, objects.helix1[i].y); - connector.lineTo(objects.helix2[i].x, objects.helix2[i].y); - connector.stroke({ width: 2, color: 0x666666, alpha: 0.3 }); - }); - }, - - cleanup(app, objects) { - objects.helix1.forEach(s => s.destroy()); - objects.helix2.forEach(s => s.destroy()); - objects.connectors.forEach(c => c.destroy()); - } -}; - -// ============================================================================ -// DEMO 8: FIREWORKS -// ============================================================================ - -export const fireworks = { - name: "Fireworks", - description: "Explosive particle celebration", - - setup(app, state) { - return { - explosions: [], - nextExplosion: 0 - }; - }, - - update(app, state, objects) { - const t = state.state.time.current; - - // Create new explosion every second - if (t > objects.nextExplosion) { - objects.nextExplosion = t + 0.5 + Math.random(); - - const explosion = { - x: Math.random() * app.screen.width, - y: Math.random() * app.screen.height * 0.7, - particles: [], - color: Math.random() * 0xffffff, - born: t - }; - - // Create particles - for (let i = 0; i < 50; i++) { - const angle = (i / 50) * Math.PI * 2; - const speed = 2 + Math.random() * 4; - const particle = new PIXI.Graphics(); - particle.circle(0, 0, 3); - particle.fill(explosion.color); - particle.x = explosion.x; - particle.y = explosion.y; - particle.vx = Math.cos(angle) * speed; - particle.vy = Math.sin(angle) * speed; - - app.stage.addChild(particle); - explosion.particles.push(particle); - } - - objects.explosions.push(explosion); - } - - // Update explosions - objects.explosions = objects.explosions.filter(explosion => { - const age = t - explosion.born; - - if (age > 3) { - explosion.particles.forEach(p => p.destroy()); - return false; - } - - explosion.particles.forEach(p => { - p.vx *= 0.98; - p.vy += 0.1; // Gravity - p.x += p.vx; - p.y += p.vy; - p.alpha = 1 - age / 3; - }); - - return true; - }); - }, - - cleanup(app, objects) { - objects.explosions.forEach(explosion => { - explosion.particles.forEach(p => p.destroy()); - }); - } -}; - -// ============================================================================ -// DEMO 9: MATRIX RAIN -// ============================================================================ - -export const matrixRain = { - name: "Matrix Rain", - description: "Falling digital rain effect", - - setup(app, state) { - const fontSize = 16; - const columns = Math.floor(app.screen.width / fontSize); - const drops = []; - const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*"; - - for (let i = 0; i < columns; i++) { - const text = new PIXI.Text('', { - fontFamily: 'monospace', - fontSize: fontSize, - fill: 0x00ff00 - }); - text.x = i * fontSize; - text.y = -Math.random() * app.screen.height; - - app.stage.addChild(text); - drops.push({ - text, - speed: 1 + Math.random() * 3, - chars: chars - }); - } - - return { drops }; - }, - - update(app, state, objects) { - objects.drops.forEach(drop => { - drop.y = (drop.y || drop.text.y) + drop.speed; - drop.text.y = drop.y; - - // Random character - if (Math.random() > 0.95) { - drop.text.text = drop.chars[Math.floor(Math.random() * drop.chars.length)]; - } - - // Reset to top - if (drop.y > app.screen.height) { - drop.y = -20; - drop.text.alpha = 1; - } - - // Fade trail - drop.text.alpha = Math.max(0.1, drop.text.alpha - 0.01); - }); - }, - - cleanup(app, objects) { - objects.drops.forEach(d => d.text.destroy()); - } -}; - -// ============================================================================ -// DEMO 10: SOLAR SYSTEM -// ============================================================================ - -export const solarSystem = { - name: "Solar System", - description: "Orbiting planets around a star", - - setup(app, state) { - const cx = app.screen.width / 2; - const cy = app.screen.height / 2; - - // Sun - const sun = new PIXI.Graphics(); - sun.circle(0, 0, 30); - sun.fill(0xffd700); - sun.x = cx; - sun.y = cy; - app.stage.addChild(sun); - - // Planets - const planets = [ - { radius: 60, size: 6, speed: 2.0, color: 0x8b7355 }, - { radius: 100, size: 10, speed: 1.5, color: 0xff6347 }, - { radius: 150, size: 12, speed: 1.0, color: 0x4169e1 }, - { radius: 200, size: 8, speed: 0.7, color: 0xff4500 }, - { radius: 260, size: 18, speed: 0.4, color: 0xdaa520 }, - ]; - - const planetObjects = planets.map(config => { - const planet = new PIXI.Graphics(); - planet.circle(0, 0, config.size); - planet.fill(config.color); - planet.config = config; - app.stage.addChild(planet); - return planet; - }); - - return { sun, planets: planetObjects, cx, cy }; - }, - - update(app, state, objects) { - const t = state.state.time.current; - - objects.planets.forEach((planet, i) => { - const angle = t * planet.config.speed; - planet.x = objects.cx + Math.cos(angle) * planet.config.radius; - planet.y = objects.cy + Math.sin(angle) * planet.config.radius; - }); - }, - - cleanup(app, objects) { - objects.sun.destroy(); - objects.planets.forEach(p => p.destroy()); - } -}; - -// ============================================================================ -// UTILITIES -// ============================================================================ - -function hslToHex(h, s, l) { - s /= 100; - l /= 100; - const c = (1 - Math.abs(2 * l - 1)) * s; - const x = c * (1 - Math.abs((h / 60) % 2 - 1)); - const m = l - c/2; - let r = 0, g = 0, b = 0; - - if (0 <= h && h < 60) { - r = c; g = x; b = 0; - } else if (60 <= h && h < 120) { - r = x; g = c; b = 0; - } else if (120 <= h && h < 180) { - r = 0; g = c; b = x; - } else if (180 <= h && h < 240) { - r = 0; g = x; b = c; - } else if (240 <= h && h < 300) { - r = x; g = 0; b = c; - } else if (300 <= h && h < 360) { - r = c; g = 0; b = x; - } - - r = Math.round((r + m) * 255); - g = Math.round((g + m) * 255); - b = Math.round((b + m) * 255); - - return (r << 16) | (g << 8) | b; -} - -function noise(x, y, z) { - return Math.sin(x + Math.cos(y)) * Math.cos(y + Math.sin(z)) * Math.sin(z + Math.cos(x)); -} - -// ============================================================================ -// EXPORT ALL DEMOS -// ============================================================================ - -export const allDemos = [ - bouncingParticles, - spirograph, - starfield, - waveInterference, - circlePacking, - flowField, - dnaHelix, - fireworks, - matrixRain, - solarSystem -]; |
