← back to Model Arena
data/artifacts/1109202cb075/qwen3-14b.html
518 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dragon's Slumber</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html, body {
margin: 0;
padding: 0;
overflow: hidden;
background: #111;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
canvas {
display: block;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, #1a1a1a, #2a2a2a);
touch-action: none;
}
#ui {
position: absolute;
top: 10px;
left: 10px;
color: #eee;
z-index: 10;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 8px;
font-size: 16px;
}
#ui h1 {
margin: 0 0 8px 0;
font-size: 18px;
}
#ui .status {
font-size: 14px;
margin: 2px 0;
padding: 2px 5px;
border-radius: 4px;
background: #2a2a2a;
white-space: nowrap;
}
.success {
color: #0f0;
}
.warning {
color: #f90;
}
.error {
color: #f00;
}
#ui button {
margin: 4px 0;
padding: 4px 8px;
font-size: 14px;
border: none;
border-radius: 4px;
cursor: pointer;
}
#ui button:focus {
outline: 2px solid #0ff;
}
</style>
</head>
<body>
<div id="ui">
<h1>Dragon's Slumber</h1>
<div class="status">Use arrow keys to move the shield</div>
<div class="status">Press space to shoot</div>
<div id="status" class="status"></div>
</div>
<canvas id="game"></canvas>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
window.addEventListener('resize', () => {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
reset();
});
const scale = Math.min(width / 1440, height / 810);
const scaleWidth = width / 1440;
const scaleHeight = height / 810;
const ui = document.getElementById('status');
let keys = {};
let mouse = { x: 0, y: 0 };
let isMouseDown = false;
let shieldColor = 'lightgreen';
let shieldSize = 80;
let shieldPos = { x: width / 2, y: height - 60 };
let dragonEye = { open: 0, openSpeed: 0.02 };
let dragonBreath = 0;
let breathSpeed = 0.001;
let ball = {
x: width / 2,
y: height - 30,
radius: 8,
vx: (Math.random() - 0.5) * 4,
vy: -4,
active: true
};
let bricks = [];
let maxBricks = 100;
let brickCount = maxBricks;
let powerUps = [];
let paintColor = 'orange';
let canPaint = false;
let paintCooldown = 0;
let paintDuration = 300;
function reset() {
dragonEye.open = 0;
dragonBreath = 0;
ball.active = true;
ball.x = width / 2;
ball.y = height - 30;
ball.vx = (Math.random() - 0.5) * 4;
ball.vy = -4;
bricks = [];
brickCount = maxBricks;
powerUps = [];
canPaint = false;
paintCooldown = 0;
shieldPos.x = width / 2;
shieldPos.y = height - 60;
}
function drawDragon() {
ctx.save();
ctx.fillStyle = 'rgb(30, 30, 30)';
ctx.beginPath();
ctx.moveTo(0, height / 2);
ctx.lineTo(width, height / 2);
ctx.lineTo(width, height * 0.8);
ctx.lineTo(0, height * 0.8);
ctx.closePath();
ctx.fill();
ctx.restore();
// Dragon eyes
ctx.save();
ctx.translate(width * 0.4, height * 0.6);
ctx.beginPath();
ctx.arc(0, 0, 16, 0, Math.PI * 2);
ctx.fillStyle = 'gray';
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, 5, 0, Math.PI * 2);
ctx.fillStyle = 'black';
ctx.fill();
ctx.restore();
ctx.save();
ctx.translate(width * 0.6, height * 0.6);
ctx.beginPath();
ctx.arc(0, 0, 16, 0, Math.PI * 2);
ctx.fillStyle = 'gray';
ctx.fill();
ctx.beginPath();
ctx.arc(0, 0, 5, 0, Math.PI * 2);
ctx.fillStyle = 'black';
ctx.fill();
ctx.restore();
// Dragon eye opening
ctx.save();
ctx.translate(width * 0.4, height * 0.6);
ctx.beginPath();
ctx.arc(0, 0, 5 * dragonEye.open, 0, Math.PI * 2);
ctx.fillStyle = 'white';
ctx.fill();
ctx.restore();
ctx.save();
ctx.translate(width * 0.6, height * 0.6);
ctx.beginPath();
ctx.arc(0, 0, 5 * dragonEye.open, 0, Math.PI * 2);
ctx.fillStyle = 'white';
ctx.fill();
ctx.restore();
// Dragon breath
ctx.save();
ctx.globalAlpha = dragonBreath;
ctx.translate(width / 2, height * 0.65);
ctx.fillStyle = 'rgba(255, 200, 0, 0.5)';
ctx.beginPath();
ctx.arc(0, 0, 30, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
// Dragon scales
for (let i = 0; i < bricks.length; i++) {
const brick = bricks[i];
ctx.save();
ctx.translate(brick.x, brick.y);
ctx.fillStyle = brick.color;
ctx.fillRect(-brick.w / 2, -brick.h / 2, brick.w, brick.h);
ctx.restore();
}
// Power ups
for (let i = 0; i < powerUps.length; i++) {
const power = powerUps[i];
ctx.save();
ctx.translate(power.x, power.y);
ctx.fillStyle = 'gold';
ctx.beginPath();
ctx.arc(0, 0, 10, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
}
function drawShield() {
ctx.save();
ctx.translate(shieldPos.x, shieldPos.y);
ctx.fillStyle = shieldColor;
ctx.beginPath();
ctx.moveTo(-shieldSize / 2, -shieldSize / 2);
ctx.lineTo(shieldSize / 2, -shieldSize / 2);
ctx.lineTo(shieldSize / 2, shieldSize / 2);
ctx.lineTo(-shieldSize / 2, shieldSize / 2);
ctx.closePath();
ctx.fill();
ctx.restore();
}
function drawBall() {
if (!ball.active) return;
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = 'white';
ctx.fill();
}
function update() {
// Handle keys
if (keys['ArrowLeft'] || keys['a']) {
shieldPos.x -= 6;
}
if (keys['ArrowRight'] || keys['d']) {
shieldPos.x += 6;
}
if (keys['ArrowUp'] || keys['w']) {
shieldPos.y -= 6;
}
if (keys['ArrowDown'] || keys['s']) {
shieldPos.y += 6;
}
if (keys[' ']) {
if (ball.active) {
keys[' '] = false;
shootBall();
}
}
// Clamp shield
shieldPos.x = Math.max(shieldSize / 2, Math.min(width - shieldSize / 2, shieldPos.x));
shieldPos.y = Math.max(shieldSize / 2, Math.min(height - shieldSize / 2, shieldPos.y));
// Update ball
if (ball.active) {
ball.x += ball.vx;
ball.y += ball.vy;
// Wall collision
if (ball.x < ball.radius || ball.x > width - ball.radius) {
ball.vx *= -1;
}
if (ball.y < ball.radius) {
ball.vy *= -1;
}
// Shield collision
const dx = ball.x - shieldPos.x;
const dy = ball.y - shieldPos.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < shieldSize / 2 + ball.radius) {
const angle = Math.atan2(dy, dx);
const hitX = Math.cos(angle) * (shieldSize / 2 + ball.radius);
const hitY = Math.sin(angle) * (shieldSize / 2 + ball.radius);
ball.x = shieldPos.x + hitX;
ball.y = shieldPos.y + hitY;
const normalX = Math.cos(angle);
const normalY = Math.sin(angle);
const dot = (ball.vx * normalX + ball.vy * normalY);
const reflectX = ball.vx - 2 * dot * normalX;
const reflectY = ball.vy - 2 * dot * normalY;
ball.vx = reflectX;
ball.vy = reflectY;
}
// Brick collisions
for (let i = 0; i < bricks.length; i++) {
const brick = bricks[i];
const dx = ball.x - brick.x;
const dy = ball.y - brick.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < brick.radius + ball.radius) {
const angle = Math.atan2(dy, dx);
const hitX = Math.cos(angle) * (brick.radius + ball.radius);
const hitY = Math.sin(angle) * (brick.radius + ball.radius);
ball.x = brick.x + hitX;
ball.y = brick.y + hitY;
const normalX = Math.cos(angle);
const normalY = Math.sin(angle);
const dot = (ball.vx * normalX + ball.vy * normalY);
const reflectX = ball.vx - 2 * dot * normalX;
const reflectY = ball.vy - 2 * dot * normalY;
ball.vx = reflectX;
ball.vy = reflectY;
bricks.splice(i, 1);
brickCount--;
i--;
if (brickCount === 0) {
// Dragon wakes up
if (dragonEye.open < 1) {
dragonEye.open += 0.1;
}
if (dragonBreath < 1) {
dragonBreath += 0.01;
}
} else {
// Dragon is still sleeping
if (dragonEye.open > 0) {
dragonEye.open -= 0.05;
}
if (dragonBreath > 0) {
dragonBreath -= 0.005;
}
}
}
}
// Power-up collisions
for (let i = 0; i < powerUps.length; i++) {
const power = powerUps[i];
const dx = ball.x - power.x;
const dy = ball.y - power.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 10 + ball.radius) {
powerUps.splice(i, 1);
canPaint = true;
paintCooldown = paintDuration;
i--;
}
}
// Game over
if (ball.y > height) {
ball.active = false;
ui.textContent = 'Game Over! Press R to restart.';
ui.className = 'status error';
}
}
// Update paint cooldown
if (paintCooldown > 0) {
paintCooldown -= 1;
}
// Update dragon eye and breath
if (dragonEye.open < 1) {
dragonEye.open += dragonEye.openSpeed;
}
if (dragonBreath < 1) {
dragonBreath += breathSpeed;
}
}
function draw() {
ctx.clearRect(0, 0, width, height);
drawDragon();
drawShield();
drawBall();
// UI status
if (brickCount === 0) {
ui.textContent = 'Dragon Awakened!';
ui.className = 'status success';
} else if (brickCount < 5) {
ui.textContent = 'Dragon Stirring!';
ui.className = 'status warning';
} else {
ui.textContent = `${brickCount} scales left.`;
ui.className = 'status';
}
if (canPaint) {
ui.innerHTML += '<div class="status success">You can paint a new scale! (Press P)</div>';
} else {
ui.innerHTML = '';
}
}
function shootBall() {
if (!ball.active) {
ball.active = true;
ball.x = shieldPos.x;
ball.y = shieldPos.y - shieldSize / 2 - ball.radius;
ball.vx = (Math.random() - 0.5) * 4;
ball.vy = -4;
}
}
function startGame() {
reset();
generateBricks();
generatePowerUps();
}
function generateBricks() {
bricks = [];
brickCount = maxBricks;
for (let i = 0; i < maxBricks; i++) {
const w = 40 + Math.random() * 20;
const h = 20 + Math.random() * 10;
const x = Math.random() * (width - w);
const y = (height / 2) * Math.random();
bricks.push({
x: x,
y: y,
w: w,
h: h,
radius: Math.sqrt((w / 2) ** 2 + (h / 2) ** 2),
color: `hsl(${Math.random() * 360}, 80%, 60%)`
});
}
}
function generatePowerUps() {
powerUps = [];
for (let i = 0; i < Math.floor(maxBricks / 10); i++) {
const x = Math.random() * width;
const y = Math.random() * height;
powerUps.push({ x: x, y: y });
}
}
function handleInput(e) {
if (e.type === 'keydown') {
keys[e.key] = true;
if (e.key === 'r' || e.key === 'R') {
startGame();
}
if (e.key === 'p' || e.key === 'P') {
if (canPaint) {
const x = shieldPos.x;
const y = shieldPos.y - shieldSize / 2 - 30;
const w = 40 + Math.random() * 20;
const h = 20 + Math.random() * 10;
bricks.push({
x: x,
y: y,
w: w,
h: h,
radius: Math.sqrt((w / 2) ** 2 + (h / 2) ** 2),
color: paintColor
});
brickCount++;
canPaint = false;
paintCooldown = 0;
}
}
} else if (e.type === 'keyup') {
keys[e.key] = false;
}
}
function init() {
startGame();
window.addEventListener('keydown', handleInput);
window.addEventListener('keyup', handleInput);
window.addEventListener('mousedown', (e) => {
isMouseDown = true;
mouse.x = e.clientX;
mouse.y = e.clientY;
});
window.addEventListener('mouseup', () => isMouseDown = false);
window.addEventListener('mousemove', (e) => {
mouse.x = e.clientX;
mouse.y = e.clientY;
});
let lastTime = 0;
function loop(time) {
const deltaTime = time - lastTime;
lastTime = time;
update();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
init();
</script>
</body>
</html>