This:
#########
Create a single-file index.html that implements a colorful, fully animated physics scene in vanilla JavaScript, no external libraries.
Goal
A polygonal container (default hexagon, but edges configurable, min 3) spins and moves inside a rectangular canvas. Inside it, multiple balls move under gravity, collide elastically with the polygon edges and with each other. The polygon itself bounces off the canvas boundaries. Gravity varies over time and direction, affecting both the polygon’s motion and the balls within it. All motion should feel natural and respect conservation of momentum and coefficient of restitution.
Requirements
1) Tech
- Single index.html with inline CSS and JS
- Vanilla JS only
- Responsive canvas that fits window
- High-DPI support with devicePixelRatio
- Use requestAnimationFrame; keep 60fps where possible
2) Controls (exposed via simple on-screen UI and via a single config object at top of JS)
- polygonSides: integer >= 3
- polygonSize: radius in pixels
- spinSpeed: radians per second (positive CW or CCW; also allow spinDirection boolean or sign)
- ballsCount: integer >= 1
- polygonSpinDirection: "cw" or "ccw"
- gravityMode: "varying" by default; gravity vector changes smoothly over time
- gravityMagnitudeRange: [min, max]
- gravityDirectionChangeSpeed: how fast gravity direction rotates
- polygonBounceRestitution: 0..1
- ballRestitution: 0..1
- wallRestitution: 0..1
- ballRadiusRange: [min, max]
- ballMassFromRadius: true to set mass proportional to area
- polygonLinearDamping and angularDamping
- polygonInitialVelocity and angularVelocity override when provided
- colorMode: "dynamic"
- trail: boolean with fade amount
- paused: boolean
- timeScale: number for slow/fast motion
3) Physics details
- Represent polygon as a rigid body with position, velocity, angle, angular velocity
- Polygon collides with rectangular canvas boundaries and bounces using restitution; correct penetration robustly
- Gravity applies to both polygon center of mass and balls; polygon’s response includes both translation and torque as appropriate (can simplify to center force)
- Balls move under gravity, collide with polygon edges (treat edges as line segments in world space) with elastic response
- Balls collide with each other via circle-circle collisions with impulse resolution and positional correction to avoid sinking
- Use stable, iterative solver per frame: integrate velocities, predict positions, detect collisions, resolve impulses, positional correction, then finalize positions
- Prevent tunneling at high speeds: use smaller substeps per frame or conservative advancement
- Use a small slop and baumgarte-style correction for stability
- Include friction (tangent impulse) optional; if added, keep simple Coulomb friction
- Preserve momentum as reasonably as possible for a simple engine
4) Animation and visuals
- Colorful, dynamic theme; polygon outline glows, balls have gradients
- Background can show gravity direction indicator (arrow) and magnitude
- Optionally draw velocity/force vectors as subtle lines
- Optionally add trails/fading for motion blur feel
- Show polygon rotation and spin visually; maybe color shift based on angular speed
- Show bounce effects with brief color flashes on contact
5) Interactivity
- Provide a simple UI panel: sliders or inputs for polygonSides, polygonSize, ballsCount, spinSpeed, spinDirection, gravityMagnitudeRange, timeScale, pause/resume, reset
- A “Randomize” button to re-seed balls' positions and velocities without overlaps
- Ensure polygonSides change rebuilds the shape safely without trapping balls outside; reposition as needed
- Keep balls inside polygon on creation; resolve any overlaps
6) Structure
- Top-level config object with defaults
- Utility functions: vector ops, polygon vertex generation, point-in-polygon, segment-circle collision, circle-circle collision, SAT for polygon-wall if needed
- Physics step(dt) with optional substeps
- Rendering step with clear layering: background, container bounds, polygon, balls, overlays (vectors/labels/UI)
- Initialization that seeds balls at non-overlapping positions inside polygon; reject or jitter to resolve overlaps
7) Edge cases
- Very small polygon size relative to balls: clamp minimum size or warn in UI
- High spinSpeed or timeScale: auto-increase substeps
- Large ballsCount: degrade gracefully, maybe cap, and keep >30fps if possible
- Keep numeric stability: use EPS, clamp impulses, limit max velocity
- Handle window resize cleanly; preserve state
8) Comments and readability
- Comment core physics: impulse equations, restitution, positional correction
- Explain gravity variation function
- Keep code tidy and modular within the single file
Deliverables
- A complete index.html that runs by opening in a browser
- Includes UI, canvas, styles, and fully working physics per above
- Sensible defaults: polygonSides=6, polygonSize=180px, ballsCount=12, spinSpeed=0.8 rad/s, gravity varying slowly
Optional enhancements (if time)
- Audio pings on collisions with volume scaled by impulse
- Toggle for wireframe/debug view showing normals and contact points
- Snapshot/export of current config as JSON and import button
Make sure everything is self-contained and works out of the box.