Qwen3 Coder Next
by Qwenreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 33 s
- Cost
- $0.0044
- Output tokens
- 5,426
- Spent thinking
- 0 tokens
- Speed
- 58.3 tok/s
- Console errors
- 0
- First token after
- 498 ms
- First visible text after
- 498 ms
- Prompt tokens
- 513
- Code size
- 20.5 KB
- Finish reason
- stop
- Served by
- Parasail
- Model id
qwen/qwen3-coder-next- Reasoning sent
model default- Max output
- 235,929 tokens
- Generated
- Nov 13, 2026
What it was asked
The prompt
Build a polished Breakout (brick breaker) game in a single HTML file using vanilla JavaScript and a <canvas>. Requirements: - A paddle controlled with the mouse and with the left/right arrow keys. - The bounce angle off the paddle depends on where the ball hits it (center = straight up, edges = sharp angle). - One level with at least 6 rows of bricks, mixing normal bricks and tougher bricks that need 2 hits and visibly crack after the first one. - Some bricks visibly carry a power-up icon; when broken they drop it, and catching it with the paddle gives either a wider paddle (10 seconds) or multi-ball (3 balls). - The ball must never pass through bricks or the paddle. - Particles when a brick breaks. - 3 lives, score displayed. Game over and victory screens with a restart option.
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task. Output rules: - Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block. - Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task. - Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw. - The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar. - Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction. - Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session. - Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing. - The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message. - The code must run with zero errors in the console of the latest Chrome.
Code run-1.html · 743 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neon Breakout</title>
<style>
:root {
--bg-color: #0f0f1a;
--text-color: #ffffff;
--accent-color: #00f3ff;
--danger-color: #ff0055;
--success-color: #00ff9d;
}
body {
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-color);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
user-select: none;
}
h1 {
margin: 10px 0;
font-weight: 300;
letter-spacing: 3px;
text-transform: uppercase;
text-shadow: 0 0 10px var(--accent-color);
font-size: 2.5rem;
}
#game-container {
position: relative;
box-shadow: 0 0 30px rgba(0, 243, 255, 0.2);
border: 2px solid #333;
border-radius: 4px;
}
canvas {
display: block;
background: radial-gradient(circle at center, #1a1a2e 0%, #0f0f1a 100%);
cursor: none; /* Hide default cursor during gameplay */
}
#ui-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 20px;
box-sizing: border-box;
}
.hud {
display: flex;
justify-content: space-between;
font-size: 1.2rem;
font-weight: bold;
text-shadow: 1px 1px 2px black;
}
.hud span {
color: var(--accent-color);
}
#overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
pointer-events: auto;
z-index: 10;
transition: opacity 0.3s;
}
#overlay.hidden {
opacity: 0;
pointer-events: none;
}
#overlay h2 {
font-size: 4rem;
margin-bottom: 20px;
text-transform: uppercase;
letter-spacing: 5px;
}
.win-text { color: var(--success-color); text-shadow: 0 0 20px var(--success-color); }
.lose-text { color: var(--danger-color); text-shadow: 0 0 20px var(--danger-color); }
button {
background: transparent;
color: var(--accent-color);
border: 2px solid var(--accent-color);
padding: 15px 40px;
font-size: 1.5rem;
cursor: pointer;
text-transform: uppercase;
transition: all 0.3s ease;
font-weight: bold;
letter-spacing: 2px;
border-radius: 50px;
box-shadow: 0 0 10px rgba(0, 243, 255, 0.2);
}
button:hover {
background: var(--accent-color);
color: var(--bg-color);
box-shadow: 0 0 30px rgba(0, 243, 255, 0.6);
transform: scale(1.05);
}
.controls-hint {
margin-top: 30px;
font-size: 0.9rem;
color: #888;
text-align: center;
line-height: 1.6;
}
.powerup-indicator {
display: flex;
gap: 10px;
margin-top: 10px;
}
.active-powerup {
padding: 5px 10px;
border-radius: 15px;
font-size: 0.8rem;
color: #000;
font-weight: bold;
animation: pulse 1s infinite;
}
.pw-wide { background: var(--accent-color); }
.pw-multi { background: var(--success-color); }
@keyframes pulse {
0% { box-shadow: 0 0 5px currentColor; }
50% { box-shadow: 0 0 15px currentColor; }
100% { box-shadow: 0 0 5px currentColor; }
}
</style>
</head>
<body>
<h1>Neon Breakout</h1>
<div id="game-container">
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="ui-layer">
<div class="hud">
<div>SCORE: <span id="scoreDisplay">0</span></div>
<div>LIVES: <span id="livesDisplay">3</span></div>
</div>
<div class="powerup-indicator" id="activeEffects">
<!-- Active effects appear here -->
</div>
</div>
<div id="overlay">
<h2 id="overlayTitle">BREAKOUT</h2>
<button id="startBtn">Start Game</button>
<div class="controls-hint">
Mouse to Move / Click to Launch<br>
Arrow Keys (Left/Right) also supported
</div>
</div>
</div>
<script>
/**
* GAME CONSTANTS & CONFIGURATION
*/
const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 600;
const PADDLE_WIDTH_BASE = 100;
const PADDLE_HEIGHT = 15;
const BALL_RADIUS = 8;
const BALL_SPEED_BASE = 6;
const BRICK_ROWS = 6;
const BRICK_COLS = 9;
const BRICK_GAP = 8;
const BRICK_HEIGHT = 25;
// Brick Types
const TYPE_NORMAL = 0; // 1 Hit
const TYPE_HEAVY = 1; // 2 Hits (Cracks)
// PowerUps
const PU_WIDE = 'wide'; // Wider paddle
const PU_MULTI = 'multi'; // Multi-ball
// Colors
const COLORS = {
paddle: '#00f3ff',
ball: '#ffffff',
brickNormal: '#ff0055',
brickHeavy: '#aa00aa',
brickHeavyCracked: '#ff9900',
text: '#ffffff',
powerups: {
[PU_WIDE]: '#00f3ff',
[PU_MULTI]: '#00ff9d'
}
};
/**
* GAME STATE
*/
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('scoreDisplay');
const livesEl = document.getElementById('livesDisplay');
const overlay = document.getElementById('overlay');
const overlayTitle = document.getElementById('overlayTitle');
const startBtn = document.getElementById('startBtn');
const activeEffectsEl = document.getElementById('activeEffects');
let gameLoopId;
let animationFrameId;
let score = 0;
let lives = 3;
let gameState = 'MENU'; // MENU, PLAYING, GAMEOVER, VICTORY
let particles = [];
let powerUps = [];
// Input State
let mouseX = CANVAS_WIDTH / 2;
let keys = { ArrowLeft: false, ArrowRight: false };
let isMouseDown = false;
// Entities
let paddle = {
x: CANVAS_WIDTH / 2 - PADDLE_WIDTH_BASE / 2,
y: CANVAS_HEIGHT - 40,
width: PADDLE_WIDTH_BASE,
height: PADDLE_HEIGHT,
color: COLORS.paddle,
widthTimer: null
};
let balls = [];
let bricks = [];
/**
* CLASSES
*/
class Ball {
constructor(x, y, dx, dy) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.radius = BALL_RADIUS;
this.speed = BALL_SPEED_BASE;
this.active = true;
this.color = COLORS.ball;
}
update() {
// Wall Collisions
if (this.x - this.radius < 0) {
this.x = this.radius;
this.dx = -this.dx;
} else if (this.x + this.radius > CANVAS_WIDTH) {
this.x = CANVAS_WIDTH - this.radius;
this.dx = -this.dx;
}
if (this.y - this.radius < 0) {
this.y = this.radius;
this.dy = -this.dy;
} else if (this.y - this.radius > CANVAS_HEIGHT) {
this.active = false; // Ball lost
}
// Paddle Collision
if (
this.y + this.radius >= paddle.y &&
this.y - this.radius <= paddle.y + paddle.height &&
this.x >= paddle.x &&
this.x <= paddle.x + paddle.width
) {
// Physics: Calculate angle based on where it hit the paddle
let hitPoint = this.x - (paddle.x + paddle.width / 2);
// Normalize hit point (-1 to 1)
hitPoint = hitPoint / (paddle.width / 2);
// Clamp to avoid extreme angles
hitPoint = Math.max(-1, Math.min(1, hitPoint));
// Calculate angle (Max 60 degrees)
let angle = hitPoint * (Math.PI / 3);
// Calculate new velocity
// Keep speed constant, change direction
this.dx = this.speed * Math.sin(angle);
this.dy = -this.speed * Math.cos(angle);
// Push ball out of paddle to prevent sticking
this.y = paddle.y - this.radius - 1;
}
this.x += this.dx;
this.y += this.dy;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = 10;
ctx.shadowColor = this.color;
ctx.fill();
ctx.shadowBlur = 0;
ctx.closePath();
}
}
class Brick {
constructor(col, row, type) {
this.width = (CANVAS_WIDTH - (BRICK_COLS + 1) * BRICK_GAP) / BRICK_COLS;
this.height = BRICK_HEIGHT;
this.x = BRICK_GAP + col * (this.width + BRICK_GAP);
this.y = BRICK_GAP + row * (this.height + BRICK_GAP);
this.type = type;
this.status = 1; // 1 = Active, 0 = Broken
this.hits = type === TYPE_HEAVY ? 2 : 1;
}
hit() {
this.hits--;
if (this.hits <= 0) {
this.status = 0;
return true; // Broken
}
return false; // Still standing
}
draw() {
if (this.status === 0) return;
let color = COLORS.brickNormal;
if (this.type === TYPE_HEAVY) {
color = this.hits === 2 ? COLORS.brickHeavy : COLORS.brickHeavyCracked;
}
ctx.fillStyle = color;
ctx.shadowBlur = 5;
ctx.shadowColor = color;
// Draw rounded rect
const r = 5;
ctx.beginPath();
ctx.roundRect(this.x, this.y, this.width, this.height, r);
ctx.fill();
// Detail for cracked heavy bricks
if (this.type === TYPE_HEAVY && this.hits === 1) {
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.shadowBlur = 0;
ctx.beginPath();
ctx.moveTo(this.x + this.width/4, this.y);
ctx.lineTo(this.x + this.width/2, this.y + this.height/2);
ctx.lineTo(this.x + 3*this.width/4, this.y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, this.y + this.height/2);
ctx.lineTo(this.x + this.width/2, this.y + this.height);
ctx.stroke();
} else {
ctx.shadowBlur = 0;
}
// PowerUp Chance Icon
if (this.type === TYPE_NORMAL && Math.random() < 0.15 && this.status === 1) {
// Only draw icon if it's a potential powerup brick (decided on creation but we render a generic icon)
// For better design, we'd set a property on creation.
// Let's cheat slightly and draw a small icon if it's the first row (higher chance)
if (Math.random() > 0.6) {
this.hasPowerUp = true;
ctx.fillStyle = '#fff';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('?', this.x + this.width/2, this.y + this.height/2);
}
}
}
}
class Particle {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
this.size = Math.random() * 4 + 2;
this.speedX = Math.random() * 6 - 3;
this.speedY = Math.random() * 6 - 3;
this.life = 1.0; // Opacity/Life
this.decay = Math.random() * 0.03 + 0.01;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.life -= this.decay;
this.size *= 0.95;
}
draw() {
ctx.globalAlpha = this.life;
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1.0;
}
}
class PowerUp {
constructor(x, y, type) {
this.x = x;
this.y = y;
this.type = type;
this.width = 20;
this.height = 20;
this.dy = 3;
this.active = true;
this.color = COLORS.powerups[type];
this.icon = type === PU_WIDE ? 'W' : 'M';
}
update() {
this.y += this.dy;
if (this.y > CANVAS_HEIGHT) this.active = false;
// Paddle Collision
if (
this.y + this.height >= paddle.y &&
this.y <= paddle.y + paddle.height &&
this.x + this.width >= paddle.x &&
this.x <= paddle.x + paddle.width
) {
this.collect();
}
}
collect() {
this.active = false;
if (this.type === PU_WIDE) {
paddle.width = PADDLE_WIDTH_BASE * 1.5;
if (paddle.widthTimer) clearTimeout(paddle.widthTimer);
paddle.widthTimer = setTimeout(() => {
paddle.width = PADDLE_WIDTH_BASE;
}, 10000);
} else if (this.type === PU_MULTI) {
// Spawn 2 additional balls if only 1 exists
if (balls.length === 1) {
let b = balls[0];
balls.push(new Ball(b.x, b.y, b.dx * 0.8, b.dy * 0.8)); // Slightly different angle
balls.push(new Ball(b.x, b.y, b.dx * -0.8, b.dy * 0.8));
}
}
// Update UI
updatePowerUpUI();
}
draw() {
ctx.fillStyle = this.color;
ctx.shadowBlur = 10;
ctx.shadowColor = this.color;
ctx.beginPath();
ctx.arc(this.x + 10, this.y + 10, 10, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#000';
ctx.font = 'bold 12px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.shadowBlur = 0;
ctx.fillText(this.icon, this.x + 10, this.y + 10);
}
}
/**
* GAME LOGIC
*/
function initGame() {
score = 0;
lives = 3;
scoreEl.innerText = score;
livesEl.innerText = lives;
// Reset Paddle
paddle.width = PADDLE_WIDTH_BASE;
paddle.x = (CANVAS_WIDTH - paddle.width) / 2;
if (paddle.widthTimer) clearTimeout(paddle.widthTimer);
// Clear Entities
particles = [];
powerUps = [];
balls = [];
bricks = [];
createLevel();
// Create first ball
resetBall();
gameState = 'PLAYING';
overlay.classList.add('hidden');
if (gameLoopId) cancelAnimationFrame(gameLoopId);
gameLoop();
}
function createLevel() {
for (let r = 0; r < BRICK_ROWS; r++) {
for (let c = 0; c < BRICK_COLS; c++) {
let type = TYPE_NORMAL;
// Heavy bricks in bottom 3 rows, random distribution
if (r >= 3 && Math.random() > 0.7) {
type = TYPE_HEAVY;
}
bricks.push(new Brick(c, r, type));
}
}
}
function resetBall() {
balls = [new Ball(CANVAS_WIDTH / 2, CANVAS_HEIGHT - 60, 0, 0)];
// Ball sticks to paddle initially
}
function spawnParticles(x, y, color) {
for (let i = 0; i < 15; i++) {
particles.push(new Particle(x, y, color));
}
}
function updatePowerUpUI() {
activeEffectsEl.innerHTML = '';
// Check Wide Paddle
if (paddle.width > PADDLE_WIDTH_BASE) {
const el = document.createElement('div');
el.className = 'active-powerup pw-wide';
el.innerText = 'WIDE PADDLE';
activeEffectsEl.appendChild(el);
}
// Check Multi-ball
if (balls.length > 1) {
const el = document.createElement('div');
el.className = 'active-powerup pw-multi';
el.innerText = `MULTI-BALL (${balls.length} BALLS)`;
activeEffectsEl.appendChild(el);
}
}
function gameOver(victory) {
gameState = victory ? 'VICTORY' : 'GAMEOVER';
overlayTitle.innerText = victory ? "VICTORY!" : "GAME OVER";
overlayTitle.className = victory ? "win-text" : "lose-text";
startBtn.innerText = "Play Again";
overlay.classList.remove('hidden');
}
function gameLoop() {
// Clear Canvas
ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
// Update Paddle Position
if (keys.ArrowLeft) paddle.x -= 8;
if (keys.ArrowRight) paddle.x += 8;
// Clamp Paddle
if (paddle.x < 0) paddle.x = 0;
if (paddle.x + paddle.width > CANVAS_WIDTH) paddle.x = CANVAS_WIDTH - paddle.width;
// Draw Paddle
ctx.fillStyle = paddle.color;
ctx.shadowBlur = 15;
ctx.shadowColor = paddle.color;
ctx.beginPath();
ctx.roundRect(paddle.x, paddle.y, paddle.width, paddle.height, 5);
ctx.fill();
ctx.shadowBlur = 0;
// Handle Balls
let activeBalls = 0;
balls.forEach(ball => {
if (ball.active) {
ball.update();
ball.draw();
activeBalls++;
// Brick Collision
for (let b of bricks) {
if (b.status === 1) {
if (
ball.x > b.x &&
ball.x < b.x + b.width &&
ball.y > b.y &&
ball.y < b.y + b.height
) {
ball.dy = -ball.dy;
b.hit();
score += 10;
scoreEl.innerText = score;
spawnParticles(b.x + b.width/2, b.y + b.height/2, b.type === TYPE_HEAVY ? COLORS.brickHeavy : COLORS.brickNormal);
// Check for PowerUp
if (b.hasPowerUp && Math.random() > 0.5) {
const type = Math.random() > 0.5 ? PU_WIDE : PU_MULTI;
powerUps.push(new PowerUp(b.x + b.width/2, b.y + b.height/2, type));
}
break; // Only hit one brick per frame per ball to prevent weirdness
}
}
}
}
});
if (activeBalls === 0) {
lives--;
livesEl.innerText = lives;
if (lives > 0) {
resetBall();
} else {
gameOver(false);
}
}
// Handle PowerUps
powerUps.forEach(p => {
p.update();
p.draw();
});
powerUps = powerUps.filter(p => p.active);
// Handle Particles
for (let i = particles.length - 1; i >= 0; i--) {
particles[i].update();
particles[i].draw();
if (particles[i].life <= 0) {
particles.splice(i, 1);
}
}
// Check Victory
const remainingBricks = bricks.filter(b => b.status === 1).length;
if (remainingBricks === 0) {
gameOver(true);
}
if (gameState === 'PLAYING') {
gameLoopId = requestAnimationFrame(gameLoop);
}
}
/**
* EVENT LISTENERS
*/
// Mouse
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const root = document.documentElement;
mouseX = e.clientX - rect.left - root.scrollLeft;
// Center paddle on mouse
paddle.x = mouseX - paddle.width / 2;
// Clamp
if (paddle.x < 0) paddle.x = 0;
if (paddle.x + paddle.width > CANVAS_WIDTH) paddle.x = CANVAS_WIDTH - paddle.width;
});
canvas.addEventListener('mousedown', () => {
if (gameState === 'PLAYING' && balls.every(b => b.dx === 0)) {
// Launch ball if it's stuck
balls[0].dx = (Math.random() * 4 - 2) + 0.5; // Slight random angle
balls[0].dy = -BALL_SPEED_BASE;
}
});
// Keyboard
window.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft') keys.ArrowLeft = true;
if (e.key === 'ArrowRight') keys.ArrowRight = true;
// Launch ball with Space or Up
if ((e.key === ' ' || e.key === 'ArrowUp') && gameState === 'PLAYING' && balls.every(b => b.dx === 0)) {
balls[0].dx = (Math.random() * 4 - 2) + 0.5;
balls[0].dy = -BALL_SPEED_BASE;
}
});
window.addEventListener('keyup', (e) => {
if (e.key === 'ArrowLeft') keys.ArrowLeft = false;
if (e.key === 'ArrowRight') keys.ArrowRight = false;
});
// Start Button
startBtn.addEventListener('click', () => {
initGame();
});
// Initial Draw (Background)
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
</script>
</body>
</html>