← back to Model Arena
data/artifacts/08a1b73bf7ac/qwen3-14b.html
490 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Comet's Gravity Dance</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: #000;
color: #fff;
font-family: 'Arial', sans-serif;
overflow: hidden;
user-select: none;
}
canvas {
display: block;
width: 100%;
height: 100vh;
background: radial-gradient(ellipse at center, #000 0%, #111 100%);
}
#controls {
position: absolute;
top: 20px;
left: 20px;
z-index: 10;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
font-size: 16px;
}
#controls h2 {
margin-bottom: 10px;
}
#status {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 10;
text-align: center;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 10px;
font-size: 16px;
max-width: 80%;
}
#score {
position: absolute;
top: 20px;
right: 20px;
z-index: 10;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-size: 16px;
min-width: 100px;
}
.input-group {
margin-bottom: 10px;
}
.input-group label {
display: block;
margin-bottom: 5px;
}
.input-group input, .input-group select {
width: 100%;
padding: 6px;
font-size: 14px;
border: 1px solid #666;
border-radius: 6px;
background: #111;
color: #fff;
}
.input-group input:focus, .input-group select:focus {
outline: none;
border-color: #00f;
}
.input-group .error {
color: #f00;
font-size: 12px;
margin-top: 4px;
}
.empty-state {
display: none;
padding: 10px;
background: rgba(255, 255, 255, 0.1);
border-radius: 6px;
color: #ccc;
}
.error-state {
display: none;
padding: 10px;
background: rgba(255, 0, 0, 0.2);
border-radius: 6px;
color: #f00;
}
.success-state {
display: none;
padding: 10px;
background: rgba(0, 255, 0, 0.2);
border-radius: 6px;
color: #0f0;
}
@media (min-width: 768px) {
#controls {
left: 50%;
transform: translateX(-50%);
max-width: 400px;
width: 100%;
}
}
</style>
</head>
<body>
<div id="controls">
<h2>Comet's Gravity Dance</h2>
<div class="input-group">
<label for="constellationName">Constellation Name:</label>
<input type="text" id="constellationName" placeholder="e.g., Orion's Veil" />
<div class="error error-state" id="nameError"></div>
</div>
<div class="input-group">
<label for="highScore">High Score (optional):</label>
<input type="number" id="highScore" min="0" />
<div class="error error-state" id="scoreError"></div>
</div>
<button id="saveScore">Save Constellation</button>
<div class="success success-state" id="saveSuccess">Saved constellation: <span id="savedName"></span></div>
<div class="empty empty-state" id="emptyState">No constellation saved yet.</div>
</div>
<div id="score">Score: 0</div>
<div id="status">Welcome to the shrinking galaxy. Control your comet with arrow keys. Eat stars to grow your tail and bend gravity. Avoid collisions or slow down time!</div>
<canvas id="galaxy"></canvas>
<script>
const canvas = document.getElementById('galaxy');
const ctx = canvas.getContext('2d');
const controls = document.getElementById('controls');
const saveScoreButton = document.getElementById('saveScore');
const constellationNameInput = document.getElementById('constellationName');
const highScoreInput = document.getElementById('highScore');
const nameError = document.getElementById('nameError');
const scoreError = document.getElementById('scoreError');
const saveSuccess = document.getElementById('saveSuccess');
const savedName = document.getElementById('savedName');
const emptyState = document.getElementById('emptyState');
const status = document.getElementById('status');
let score = 0;
let savedConstellation = null;
let isPaused = false;
let isSlowMo = false;
let slowMoTimer = 0;
let comet = {
x: canvas.width / 2,
y: canvas.height / 2,
vx: 0,
vy: 0,
radius: 8,
color: 'white',
tail: []
};
let stars = [];
let gravityPoints = [];
let gravityPointsActive = [];
let gravityActive = false;
let shrinkFactor = 0.999;
let galaxyRadius = canvas.width / 2;
let lastStarEaten = null;
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
galaxyRadius = Math.min(canvas.width, canvas.height) / 2;
generateStars();
generateGravityPoints();
}
function generateStars() {
stars = [];
for (let i = 0; i < 150; i++) {
let angle = Math.random() * 2 * Math.PI;
let radius = Math.random() * galaxyRadius * 0.8;
let x = canvas.width / 2 + Math.cos(angle) * radius;
let y = canvas.height / 2 + Math.sin(angle) * radius;
let size = Math.random() * 4 + 1;
let speed = Math.random() * 0.1 + 0.05;
stars.push({ x, y, size, speed, color: `hsl(${Math.random() * 360}, 100%, 80%)` });
}
}
function generateGravityPoints() {
gravityPoints = [];
gravityPointsActive = [];
for (let i = 0; i < 30; i++) {
let angle = Math.random() * 2 * Math.PI;
let radius = Math.random() * galaxyRadius * 0.6;
let x = canvas.width / 2 + Math.cos(angle) * radius;
let y = canvas.height / 2 + Math.sin(angle) * radius;
let mass = Math.random() * 10 + 10;
gravityPoints.push({ x, y, mass, color: `hsl(${Math.random() * 360}, 70%, 60%)` });
}
}
function drawGalaxy() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw shrinking galaxy background
ctx.beginPath();
ctx.arc(canvas.width / 2, canvas.height / 2, galaxyRadius * shrinkFactor, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
ctx.fill();
// Draw stars
ctx.fillStyle = 'white';
stars.forEach(star => {
ctx.beginPath();
ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
ctx.fill();
});
// Draw gravity points
gravityPoints.forEach(gp => {
ctx.beginPath();
ctx.arc(gp.x, gp.y, Math.sqrt(gp.mass) * 1.5, 0, Math.PI * 2);
ctx.fillStyle = gp.color;
ctx.fill();
});
// Draw comet and tail
ctx.strokeStyle = comet.color;
ctx.lineWidth = 2;
comet.tail.forEach((pos, idx) => {
ctx.beginPath();
ctx.arc(pos.x, pos.y, 3, 0, Math.PI * 2);
ctx.fillStyle = comet.color;
ctx.fill();
});
ctx.beginPath();
ctx.arc(comet.x, comet.y, comet.radius, 0, Math.PI * 2);
ctx.fillStyle = comet.color;
ctx.fill();
}
function updateStars() {
stars.forEach(star => {
star.x += Math.cos(star.angle) * star.speed;
star.y += Math.sin(star.angle) * star.speed;
if (Math.random() < 0.01) {
star.angle = Math.random() * 2 * Math.PI;
}
});
}
function updateGravityPoints() {
gravityPoints.forEach(gp => {
// Orbit around galaxy center
let distanceToCenter = Math.sqrt(Math.pow(gp.x - canvas.width / 2, 2) + Math.pow(gp.y - canvas.height / 2, 2));
let maxDistance = galaxyRadius * 0.6;
if (distanceToCenter > maxDistance) {
// Move inward
let dx = gp.x - canvas.width / 2;
let dy = gp.y - canvas.height / 2;
let angle = Math.atan2(dy, dx);
gp.x -= Math.cos(angle) * 1;
gp.y -= Math.sin(angle) * 1;
} else {
// Orbit
let speed = 0.01;
let angle = Math.atan2(gp.y - canvas.height / 2, gp.x - canvas.width / 2);
gp.x += Math.cos(angle) * speed;
gp.y += Math.sin(angle) * speed;
}
});
}
function moveComet() {
let dx = comet.vx;
let dy = comet.vy;
comet.x += dx;
comet.y += dy;
// Tail
if (comet.tail.length > 50) {
comet.tail.shift();
}
comet.tail.push({ x: comet.x, y: comet.y });
// Boundaries
if (comet.x < 0 || comet.x > canvas.width || comet.y < 0 || comet.y > canvas.height) {
if (!isPaused) {
triggerSlowMo();
}
}
}
function detectCollisions() {
// Check for star collisions
for (let i = stars.length - 1; i >= 0; i--) {
let star = stars[i];
let dx = comet.x - star.x;
let dy = comet.y - star.y;
let distance = Math.sqrt(dx * dx + dy * dy);
if (distance < star.size + comet.radius) {
// Eat star
score++;
comet.radius += 1;
comet.tail.forEach((pos, idx) => {
pos.x += dx * 0.02;
pos.y += dy * 0.02;
});
stars.splice(i, 1);
lastStarEaten = star;
triggerGravityBend();
}
}
// Check for gravity points
for (let i = gravityPoints.length - 1; i >= 0; i--) {
let gp = gravityPoints[i];
let dx = comet.x - gp.x;
let dy = comet.y - gp.y;
let distance = Math.sqrt(dx * dx + dy * dy);
if (distance < Math.sqrt(gp.mass)) {
// Gravity point consumed
comet.tail.forEach((pos, idx) => {
pos.x += dx * 0.05;
pos.y += dy * 0.05;
});
gravityPoints.splice(i, 1);
}
}
}
function triggerGravityBend() {
if (lastStarEaten && !gravityActive) {
gravityActive = true;
let radius = lastStarEaten.size * 5;
gravityPointsActive = [];
for (let i = 0; i < 10; i++) {
let angle = Math.random() * 2 * Math.PI;
let x = lastStarEaten.x + Math.cos(angle) * radius;
let y = lastStarEaten.y + Math.sin(angle) * radius;
let mass = lastStarEaten.size * 0.5;
gravityPointsActive.push({ x, y, mass });
}
setTimeout(() => gravityActive = false, 1500);
}
}
function applyGravityBend() {
gravityPointsActive.forEach(gp => {
let dx = comet.x - gp.x;
let dy = comet.y - gp.y;
let distance = Math.sqrt(dx * dx + dy * dy);
let force = 0.01 * gp.mass / (distance * distance);
comet.vx += dx * force;
comet.vy += dy * force;
});
}
function triggerSlowMo() {
if (isSlowMo) return;
isSlowMo = true;
slowMoTimer = 10;
status.textContent = "Slow-mo triggered. Avoid collisions!";
}
function update() {
if (isSlowMo) {
slowMoTimer--;
if (slowMoTimer <= 0) isSlowMo = false;
return;
}
galaxyRadius *= shrinkFactor;
moveComet();
detectCollisions();
updateStars();
updateGravityPoints();
if (gravityActive) applyGravityBend();
drawGalaxy();
document.getElementById('score').textContent = 'Score: ' + score;
}
function gameLoop() {
if (isPaused) return;
update();
requestAnimationFrame(gameLoop);
}
function resetGame() {
score = 0;
comet = {
x: canvas.width / 2,
y: canvas.height / 2,
vx: 0,
vy: 0,
radius: 8,
color: 'white',
tail: []
};
generateStars();
generateGravityPoints();
}
window.addEventListener('keydown', e => {
if (isPaused) return;
switch (e.key) {
case 'ArrowUp':
comet.vy -= 0.2;
break;
case 'ArrowDown':
comet.vy += 0.2;
break;
case 'ArrowLeft':
comet.vx -= 0.2;
break;
case 'ArrowRight':
comet.vx += 0.2;
break;
case ' ':
comet.vx = 0;
comet.vy = 0;
break;
}
});
window.addEventListener('resize', () => {
resizeCanvas();
});
resizeCanvas();
gameLoop();
// Save constellation
saveScoreButton.addEventListener('click', () => {
let name = constellationNameInput.value.trim();
let scoreValue = highScoreInput.value;
if (name === '') {
nameError.textContent = 'Please enter a constellation name.';
nameError.style.display = 'block';
return;
}
nameError.style.display = 'none';
if (scoreValue && isNaN(scoreValue) || scoreValue < 0) {
scoreError.textContent = 'Please enter a valid score (optional).';
scoreError.style.display = 'block';
return;
}
scoreError.style.display = 'none';
savedConstellation = {
name: name,
score: scoreValue ? parseInt(scoreValue) : null
};
saveSuccess.style.display = 'block';
savedName.textContent = name;
setTimeout(() => {
saveSuccess.style.display = 'none';
}, 3000);
});
// Initialize state
if (savedConstellation) {
savedName.textContent = savedConstellation.name;
saveSuccess.style.display = 'none';
emptyState.style.display = 'none';
} else {
emptyState.style.display = 'block';
}
</script>
</body>
</html>