Fluid simulation · qwen3-30b-a3b-instruct-2507
Create a real-time fluid simulation on a full-screen canvas where dragging the mouse pushes swirling colored dye through the fluid.
This one-shot run produced no runnable artifact.
agent produced no index.html
The transcript below shows what the model did — read it to see why the one shot fell short.
transcript · 2 messages
Create a real-time fluid simulation on a full-screen canvas where dragging the mouse pushes swirling colored dye through the fluid.
I'll create a real-time fluid simulation with swirling colored dye that responds to mouse movement. This will be a single HTML file with embedded CSS and JavaScript. ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Real-time Fluid Simulation</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body, html { width: 100%; height: 100%; overflow: hidden; background-color: #000; } #canvas { display: block; width: 100%; height: 100%; } </style> </head> <body> <canvas id="canvas"></canvas> <script> // Get the canvas and context const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // Set canvas to full screen function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } // Initialize fluid simulation parameters const GRID_SIZE = 64; // Smaller grid for better performance const CELL_SIZE = Math.max(1, Math.min(4, Math.min( canvas.width / GRID_SIZE, canvas.height / GRID_SIZE ))); const WIDTH = Math.floor(canvas.width / CELL_SIZE); const HEIGHT = Math.floor(canvas.height / CELL_SIZE); // Fluid simulation variables let velocityX = new Array(WIDTH * HEIGHT).fill(0); let velocityY = new Array(WIDTH * HEIGHT).fill(0); let dye = new Array(WIDTH * HEIGHT).fill(0); let dyeR = new Array(WIDTH * HEIGHT).fill(0); let dyeG = new Array(WIDTH * HEIGHT).fill(0); let dyeB = new Array(WIDTH * HEIGHT).fill(0); // Color palette for the fluid const COLORS = [ [255, 0, 0], // Red [255, 165, 0], // Orange [255, 255, 0], // Yellow [0, 255, 0], // Green [0, 0, 255], // Blue [128, 0, 128], // Purple [255, 192, 203] // Pink ]; // Mouse state let mouseX = 0; let mouseY = 0; let mouseDown = false; // Physics parameters const DIFFUSION = 0.0002; const VISCOSITY = 0.0001; const DT = 0.1; // Initialize canvas size resizeCanvas(); window.addEventListener('resize', resizeCanvas); // Mouse event handlers canvas.addEventListener('mousedown', (e) => { mouseDown = true; mouseX = e.clientX; mouseY = e.clientY; }); canvas.addEventListener('mousemove', (e) => { mouseX = e.clientX; mouseY = e.clientY; }); canvas.addEventListener('mouseup', () => { mouseDown = false; }); // Get grid position from mouse coordinates function getGridPos(x, y) { const col = Math.floor(x / CELL_SIZE); const row = Math.floor(y / CELL_SIZE); return row * WIDTH + col; } // Add dye at mouse position function addDyeAtMouse() { if (mouseDown) { const pos = getGridPos(mouseX, mouseY); const colorIndex = Math.floor(Math.random() * COLORS.length); const [r, g, b] = COLORS[colorIndex]; // Add dye with velocity const maxVelocity = 0.5; const angle = Math.random() * Math.PI * 2; const velocity = Math.random() * maxVelocity; // Add dye and velocity in a small area around mouse const radius = 2; for (let dy = -radius; dy <= radius; dy++) { for (let dx = -radius; dx <= radius; dy++) { const nx = Math.floor(mouseX / CELL_SIZE) + dx; const ny = Math.floor(mouseY / CELL_SIZE) + dy; if (nx >= 0 && nx < WIDTH && ny >= 0 && ny < HEIGHT) { const npos = ny * WIDTH + nx; // Add dye dyeR[npos] += r * 0.1; dyeG[npos] += g * 0.1; dyeB[npos] += b * 0.1; // Add velocity velocityX[npos] += Math.cos(angle) * velocity; velocityY[npos] += Math.sin(angle) * velocity; } } } } } // Apply diffusion to fluids function diffuse(dest, source, diff) { const a = DT * diff * (WIDTH - 2) * (HEIGHT - 2); const c = 1 / (1 + 4 * a); for (let k = 0; k < 20; k++) { for (let j = 1; j < HEIGHT - 1; j++) { for (let i = 1; i < WIDTH - 1; i++) { const idx = j * WIDTH + i; dest[idx] = c * (source[idx] + a * ( source[idx - 1] + source[idx + 1] + source[idx - WIDTH] + source[idx + WIDTH] )); } } // Swap arrays [source, dest] = [dest, source]; } } // Apply advection (velocity to dye) function advect(dest, source, velocityX, velocityY) { for (let j = 1; j < HEIGHT - 1; j++) { for (let i = 1; i < WIDTH - 1; i++) { const idx = j * WIDTH + i; const x = i - DT * velocityX[idx]; const y = j - DT * velocityY[idx]; // Clamp coordinates if (x < 0.5) x = 0.5; if (x > WIDTH - 0.5) x = WIDTH - 0.5; if (y < 0.5) y = 0.5; if (y > HEIGHT - 0.5) y = HEIGHT - 0.5; const i0 = Math.floor(x); const i1 = i0 + 1; const j0 = Math.floor(y); const j1 = j0 + 1; const s1 = x - i0; const t1 = y - j0; const s0 = 1 - s1; const t0 = 1 - t1; // Bilinear interpolation const p0 = source[j0 * WIDTH + i0]; const p1 = source[j0 * WIDTH + i1]; const p2 = source[j1 * WIDTH + i0]; const p3 = source[j1 * WIDTH + i1]; dest[idx] = s0 * (t0 * p0 + t1 * p2) + s1 * (t0 * p1 + t1 * p3); } } } // Apply velocity divergence and pressure function project() { const div = new Array(WIDTH * HEIGHT).fill(0); const p = new Array(WIDTH * HEIGHT).fill(0); // Calculate divergence for (let j = 1; j < HEIGHT - 1; j++) { for (let i = 1; i < WIDTH - 1; i++) { const idx = j * WIDTH + i; div[idx] = -0.5 * ( velocityX[idx + 1] - velocityX[idx - 1] + velocityY[idx + WIDTH] - velocityY[idx - WIDTH] ) / WIDTH; p[idx] = 0; } } // Solve Poisson equation for (let k = 0; k < 20; k++) { for (let j = 1; j < HEIGHT - 1; j++) { for (let i = 1; i < WIDTH - 1; i++) { const idx = j * WIDTH + i; p[idx] = (div[idx] + p[idx - 1] + p[idx + 1] + p[idx - WIDTH] + p[idx + WIDTH]) / 4; } } } // Subtract pressure gradient for (let j = 1; j < HEIGHT - 1; j++) { for (let i = 1; i < WIDTH - 1; i++) { const idx = j * WIDTH + i; velocityX[idx] -= 0.5 * (p[idx + 1] - p[idx - 1]) / WIDTH; velocityY[idx] -= 0.5 * (p[idx + WIDTH] - p[idx - WIDTH]) / HEIGHT; } } } // Update the fluid simulation function updateFluid() { // Add dye at mouse position addDyeAtMouse(); // Copy velocity for advection const velocityX2 = [...velocityX]; const velocityY2 = [...velocityY]; // Apply advection to velocity advect(velocityX, velocityX2, velocityX2, velocityY2); advect(velocityY, velocityY2, velocityX2, velocityY2); // Apply viscosity diffuse(velocityX2, velocityX, VISCOSITY); diffuse(velocityY2, velocityY, VISCOSITY); // Project velocity to ensure incompressibility project(); // Apply advection to dye const dyeR2 = [...dyeR]; const dyeG2 = [...dyeG]; const dyeB2 = [...dyeB]; advect(dyeR, dyeR2, velocityX, velocityY); advect(dyeG, dyeG2, velocityX, velocityY); advect(dyeB, dyeB2, velocityX, velocityY); // Apply diffusion to dye diffuse(dyeR2, dyeR, DIFFUSION); diffuse(dyeG2, dyeG, DIFFUSION); diffuse(dyeB2, dyeB, DIFFUSION); // Update arrays velocityX = velocityX2; velocityY = velocityY2; dyeR = dyeR2; dyeG = dyeG2; dyeB = dyeB2; } // Render the fluid simulation function renderFluid() { // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw dye for (let j = 0; j < HEIGHT; j++) { for (let i = 0; i < WIDTH; i++) { const idx = j * WIDTH + i; const x = i * CELL_SIZE; const y = j * CELL_SIZE; const r = Math.min(255, dyeR[idx]); const g = Math.min(255, dyeG[idx]); const b = Math.min(255, dyeB[idx]); // Draw colored pixel ctx.fillStyle = `rgb(${r}, ${g}, ${b})`; ctx.fillRect(x, y, CELL_SIZE, CELL_SIZE); // Apply some transparency to create glowing effect ctx.globalAlpha = Math.min(1, dye[idx] * 0.01); ctx.fillRect(x, y, CELL_SIZE, CELL_SIZE); ctx.globalAlpha = 1; } } // Add a subtle glow effect ctx.globalCompositeOperation = 'lighter'; for (let j = 0; j < HEIGHT; j++) { for (let i = 0; i < WIDTH; i++) { const idx = j * WIDTH + i; const x = i * CELL_SIZE; const y = j * CELL_SIZE; const r = Math.min(255, dyeR[idx]); const g = Math.min(255, dyeG[idx]); const b = Math.min(255, dyeB[idx]); // Draw glow with reduced intensity if (dye[idx] > 0.1) { ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${dye[idx] * 0.05})`; ctx.fillRect(x, y, CELL_SIZE, CELL_SIZE); } } } ctx.globalCompositeOperation = 'source-over'; } // Main animation loop function animate() { updateFluid(); renderFluid(); requestAnimationFrame(animate); } // Start the animation animate(); </script> </body> </html> ``` This fluid simulation features: 1. Real-time fluid dynamics with velocity and pressure calculations 2. Mouse interaction that adds swirling colored dye when dragging 3. Smooth diffusion and advection of the fluid 4. Subtle glow effects to enhance the visual appeal 5. Full-screen canvas that adapts to window size 6. A vibrant color palette with multiple colors that mix naturally The simulation uses the Navier-Stokes equations for fluid dynamics, with diffusion, advection, and pressure projection to create realistic fluid behavior. When you drag the mouse, it injects colored dye with velocity, creating swirling patterns that propagate through the fluid.
TAKE IT TO CODE
This run produced no artifact — reuse the prompt with a different model or your own pi-agent run.