Gravity Lab - Build Your Solar System
by CosmicLion36271 lines8.0 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Gravity Lab</title>
<style>
*{box-sizing:border-box}
body{margin:0;background:#050711;color:#f4f5ff;font-family:Inter,Arial,sans-serif;overflow:hidden}
header{height:76px;padding:15px 22px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #20243b;background:#090c19}
.logo{font-size:20px;font-weight:900;letter-spacing:2px}
.logo span{color:#a78bfa}
.sub{font-size:10px;color:#858ca8;letter-spacing:2px;margin-top:5px}
button{background:#171c32;border:1px solid #343b59;color:white;padding:10px 14px;border-radius:9px;cursor:pointer}
button:hover{background:#292f4e}
button.active{background:#7048d9;border-color:#a78bfa}
main{display:grid;grid-template-columns:1fr 270px;height:calc(100dvh - 76px)}
#space{width:100%;height:100%;display:block;touch-action:none}
.panel{background:#0b0e1e;border-left:1px solid #252943;padding:20px;overflow:auto}
h3{font-size:12px;letter-spacing:2px;color:#a9afd0}
.stat{display:flex;justify-content:space-between;margin:18px 0;color:#a8afc9;font-size:13px}
.stat strong{color:white}
.control{margin:25px 0}
.control label{font-size:12px;color:#aab1cd;display:flex;justify-content:space-between;margin-bottom:12px}
input[type=range]{width:100%;accent-color:#a78bfa}
.actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.actions button{font-size:12px}
.hint{font-size:11px;line-height:1.7;color:#777f9d;margin-top:24px}
footer{position:absolute;bottom:14px;left:18px;color:#68708e;font-size:10px;pointer-events:none;letter-spacing:1px}
@media(max-width:650px){
main{grid-template-columns:1fr;grid-template-rows:1fr auto}
.panel{border-left:0;border-top:1px solid #252943;padding:12px 16px;max-height:220px}
.control{margin:12px 0}
.hint{display:none}
header{height:65px}
main{height:calc(100dvh - 65px)}
}
</style>
</head>
<body>
<header>
<div>
<div class="logo">GRAVITY<span>LAB</span> 🪐</div>
<div class="sub">CODE PLAYGROUND / EPISODE 001</div>
</div>
<div class="actions" style="display:flex">
<button id="pause">Ⅱ Pause</button>
<button id="reset">↻ Reset</button>
</div>
</header>
<main>
<div style="position:relative;min-height:0">
<canvas id="space"></canvas>
<footer>CLICK TO CREATE PLANETS · DRAG TO MOVE</footer>
</div>
<aside class="panel">
<h3>UNIVERSE CONTROL</h3>
<div class="stat"><span>Planets</span><strong id="count">0</strong></div>
<div class="stat"><span>Simulation</span><strong id="status">RUNNING</strong></div>
<div class="control">
<label>Gravity <strong id="gv">1.0x</strong></label>
<input id="gravity" type="range" min="0" max="3" step=".1" value="1">
</div>
<div class="control">
<label>Time speed <strong id="sv">1.0x</strong></label>
<input id="speed" type="range" min=".1" max="3" step=".1" value="1">
</div>
<div class="control">
<label>Planet size <strong id="rv">12</strong></label>
<input id="radius" type="range" min="5" max="25" value="12">
</div>
<h3>QUICK ACTIONS</h3>
<div class="actions">
<button id="add">+ Add planet</button>
<button id="sun">☀ Add star</button>
<button id="clear">✕ Clear all</button>
<button id="burst">✦ Random system</button>
</div>
<p class="hint">
EXPERIMENT 001<br><br>
Gravity is the invisible force that attracts objects with mass. Create your own planetary system and observe how bodies move through space.<br><br>
Try adding two large planets close together. Watch what happens!
</p>
</aside>
</main>
<script>
const canvas=document.getElementById('space');
const ctx=canvas.getContext('2d');
const $=id=>document.getElementById(id);
let W,H,planets=[],stars=[],running=true,drag=null;
let gravity=1,speed=1,radius=12,last=0;
const colors=['#a78bfa','#5eead4','#60a5fa','#fb7185','#fbbf24','#e879f9'];
function resize(){
const r=canvas.getBoundingClientRect();
W=canvas.width=r.width*devicePixelRatio;
H=canvas.height=r.height*devicePixelRatio;
ctx.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);
W=r.width;H=r.height;
stars=Array.from({length:130},()=>({
x:Math.random()*W,y:Math.random()*H,
r:Math.random()*1.4,alpha:Math.random()
}));
}
window.addEventListener('resize',resize);
resize();
function addPlanet(x=W/2,y=H/2,star=false){
const mass=star?1600:radius*radius;
planets.push({
x,y,vx:(Math.random()-.5)*1.5,
vy:(Math.random()-.5)*1.5,
mass,r:star?23:radius,
color:star?'#ffe9a6':colors[Math.floor(Math.random()*colors.length)],
star
});
updateCount();
}
function updateCount(){$('count').textContent=planets.length}
function reset(){
planets=[];
addPlanet(W/2,H/2,true);
for(let i=0;i<4;i++){
const a=i*Math.PI/2;
const d=85+i*48;
const x=W/2+Math.cos(a)*d;
const y=H/2+Math.sin(a)*d;
addPlanet(x,y);
const p=planets.at(-1);
const orbital=Math.sqrt(.5*1600/d);
p.vx=-Math.sin(a)*orbital;
p.vy=Math.cos(a)*orbital;
}
}
reset();
function physics(dt){
const n=planets.length;
const ax=Array(n).fill(0),ay=Array(n).fill(0);
for(let i=0;i<n;i++){
for(let j=i+1;j<n;j++){
const a=planets[i],b=planets[j];
let dx=b.x-a.x,dy=b.y-a.y;
let d2=dx*dx+dy*dy+100;
let d=Math.sqrt(d2);
let f=gravity*0.55/d2;
ax[i]+=f*b.mass*dx/d;
ay[i]+=f*b.mass*dy/d;
ax[j]-=f*a.mass*dx/d;
ay[j]-=f*a.mass*dy/d;
}
}
for(let i=0;i<n;i++){
const p=planets[i];
if(p===drag)continue;
p.vx+=ax[i]*dt;
p.vy+=ay[i]*dt;
p.vx*=.999;
p.vy*=.999;
p.x+=p.vx*dt;
p.y+=p.vy*dt;
}
}
function draw(){
ctx.fillStyle='#050711';
ctx.fillRect(0,0,W,H);
for(const s of stars){
ctx.fillStyle=`rgba(210,220,255,${.2+s.alpha*.6})`;
ctx.beginPath();ctx.arc(s.x,s.y,s.r,0,Math.PI*2);ctx.fill();
}
// Draw gravitational connections
for(let i=0;i<planets.length;i++){
for(let j=i+1;j<planets.length;j++){
const a=planets[i],b=planets[j];
const d=Math.hypot(a.x-b.x,a.y-b.y);
if(d<190){
ctx.strokeStyle=`rgba(140,130,255,${.13*(1-d/190)})`;
ctx.lineWidth=1;
ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.lineTo(b.x,b.y);ctx.stroke();
}
}
}
for(const p of planets){
const glow=ctx.createRadialGradient(p.x,p.y,0,p.x,p.y,p.r*3);
glow.addColorStop(0,p.color+'55');
glow.addColorStop(1,'transparent');
ctx.fillStyle=glow;
ctx.beginPath();ctx.arc(p.x,p.y,p.r*3,0,Math.PI*2);ctx.fill();
const g=ctx.createRadialGradient(p.x-p.r*.3,p.y-p.r*.3,1,p.x,p.y,p.r);
g.addColorStop(0,'#ffffff');
g.addColorStop(.25,p.color);
g.addColorStop(1,'#24233f');
ctx.fillStyle=g;
ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,Math.PI*2);ctx.fill();
}
}
function frame(t){
const dt=Math.min((t-last)/16.67||1,2)*speed;
last=t;
if(running)physics(dt);
draw();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
function pointer(e){
const r=canvas.getBoundingClientRect();
return {x:e.clientX-r.left,y:e.clientY-r.top};
}
canvas.addEventListener('pointerdown',e=>{
const q=pointer(e);
drag=[...planets].reverse().find(p=>Math.hypot(p.x-q.x,p.y-q.y)<p.r+8);
if(drag){canvas.setPointerCapture(e.pointerId)}
else addPlanet(q.x,q.y);
});
canvas.addEventListener('pointermove',e=>{
if(drag){
const q=pointer(e);
drag.x=q.x;drag.y=q.y;
drag.vx=0;drag.vy=0;
}
});
canvas.addEventListener('pointerup',()=>drag=null);
canvas.addEventListener('pointercancel',()=>drag=null);
$('gravity').oninput=e=>{
gravity=+e.target.value;$('gv').textContent=gravity.toFixed(1)+'x';
};
$('speed').oninput=e=>{
speed=+e.target.value;$('sv').textContent=speed.toFixed(1)+'x';
};
$('radius').oninput=e=>{
radius=+e.target.value;$('rv').textContent=radius;
};
$('pause').onclick=()=>{
running=!running;
$('pause').textContent=running?'Ⅱ Pause':'▶ Resume';
$('status').textContent=running?'RUNNING':'PAUSED';
};
$('reset').onclick=reset;
$('add').onclick=()=>addPlanet(W/2+(Math.random()-.5)*100,H/2+(Math.random()-.5)*100);
$('sun').onclick=()=>addPlanet(W/2,H/2,true);
$('clear').onclick=()=>{planets=[];updateCount()};
$('burst').onclick=()=>{
planets=[];
for(let i=0;i<12;i++){
const a=i*Math.PI*2/12;
addPlanet(W/2+Math.cos(a)*100,H/2+Math.sin(a)*100);
}
};
</script>
</body>
</html>
Game Source: Gravity Lab - Build Your Solar System
Creator: CosmicLion36
Libraries: none
Complexity: complex (271 lines, 8.0 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: gravity-lab-build-your-solar-system-cosmiclion36" to link back to the original. Then publish at arcadelab.ai/publish.