DeepSeek V4 Flash 0423
by DeepSeekreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 46.8 s
- Cost
- $0.0011
- Output tokens
- 6,069
- Spent thinking
- 0 tokens
- Speed
- 131.2 tok/s
- Console errors
- 0
- First token after
- 560 ms
- First visible text after
- 560 ms
- Prompt tokens
- 508
- Code size
- 19.3 KB
- Finish reason
- stop
- Served by
- DeepInfra
- Model id
deepseek/deepseek-v4-flash- Reasoning sent
model default- Max output
- 393,216 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 · 650 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>BREAKOUT · brick breaker</title>
<style>
* {
box-sizing: border-box;
user-select: none;
}
body {
margin: 0;
min-height: 100vh;
background: radial-gradient(circle at 30% 10%, #0f172a, #020617);
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
}
.game-container {
background: #1e293b;
padding: 24px 24px 32px;
border-radius: 48px 48px 32px 32px;
box-shadow: 0 20px 30px rgba(0,0,0,0.7), inset 0 1px 3px rgba(255,255,255,0.1);
}
canvas {
display: block;
margin: 0 auto;
width: 800px;
height: 500px;
border-radius: 24px;
box-shadow: inset 0 0 0 1px #334155, 0 12px 20px -6px black;
background: #0b1120;
cursor: none;
touch-action: none;
}
.status-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin: 18px 8px 0;
color: #e2e8f0;
font-weight: 600;
letter-spacing: 0.3px;
text-shadow: 0 2px 3px #00000060;
}
.lives span {
color: #ef4444;
font-size: 1.2rem;
margin-right: 6px;
}
.score span {
color: #facc15;
font-size: 1.3rem;
}
.message-overlay {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: rgba(0,0,0,0.55);
backdrop-filter: blur(2.5px);
color: white;
border-radius: 24px;
pointer-events: none;
opacity: 0;
transition: opacity 0.25s;
}
.message-overlay.show {
opacity: 1;
pointer-events: auto;
}
.message-overlay h2 {
font-size: 2.8rem;
margin: 0 0 6px;
background: linear-gradient(135deg, #fcd34d, #f59e0b);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 4px 10px black;
letter-spacing: 1px;
}
.message-overlay p {
font-size: 1.2rem;
background: #1e293be0;
padding: 10px 28px;
border-radius: 80px;
backdrop-filter: blur(2px);
border: 1px solid #ffffff30;
cursor: pointer;
transition: 0.2s;
margin-top: 16px;
font-weight: 500;
}
.message-overlay p:hover {
background: #2d3b50e0;
transform: scale(1.02);
border-color: #facc15;
}
.canvas-wrapper {
position: relative;
display: inline-block;
}
@media (max-width: 860px) {
.game-container { padding: 12px; border-radius: 28px; }
canvas { width: 100%; height: auto; aspect-ratio: 800/500; }
}
</style>
</head>
<body>
<div class="game-container">
<div class="canvas-wrapper">
<canvas id="gameCanvas" width="800" height="500"></canvas>
<div id="overlay" class="message-overlay">
<h2 id="overlayTitle">BREAKOUT</h2>
<p id="overlayAction">Click or press a key to start</p>
</div>
</div>
<div class="status-bar">
<div class="lives"><span>❤️</span> <span id="livesDisplay">3</span></div>
<div class="score"><span>🏆</span> <span id="scoreDisplay">0</span></div>
</div>
</div>
<script>
(function() {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const overlay = document.getElementById('overlay');
const overlayTitle = document.getElementById('overlayTitle');
const overlayAction = document.getElementById('overlayAction');
const livesSpan = document.getElementById('livesDisplay');
const scoreSpan = document.getElementById('scoreDisplay');
// ---------- GAME STATE ----------
const W = 800, H = 500;
let gameState = 'idle'; // 'idle' | 'running' | 'gameover' | 'victory'
let score = 0;
let lives = 3;
// paddle
const PADDLE_W = 110, PADDLE_H = 16;
let paddle = { x: (W - PADDLE_W) / 2, y: H - 35, w: PADDLE_W, h: PADDLE_H };
// ball(s)
let balls = [];
const BALL_RADIUS = 7;
const BASE_SPEED = 4.8;
// bricks
let bricks = [];
const BRICK_W = 70, BRICK_H = 22;
const BRICK_ROWS = 7;
const BRICK_COLS = 10;
// power ups
let powerups = []; // { x, y, w, h, type, speed }
// particles
let particles = [];
// timers
let widePaddleTimer = 0;
const WIDE_DURATION = 600; // frames (10 sec at 60fps)
const WIDE_PADDLE_W = 165;
// multi-ball flag (only from brick)
let multiBallActive = false;
// keys
let leftPressed = false, rightPressed = false;
// mouse
let mouseX = null;
// ---------- INIT LEVEL ----------
function buildLevel() {
bricks = [];
for (let row = 0; row < BRICK_ROWS; row++) {
for (let col = 0; col < BRICK_COLS; col++) {
let type = 'normal';
let hp = 1;
// tougher bricks: rows 1, 3, 5 (0-indexed)
if (row === 1 || row === 3 || row === 5) {
type = 'tough';
hp = 2;
}
// power-up bricks: random 20% on normal bricks (and some tough)
let powerUp = null;
const r = Math.random();
if ((type === 'normal' && r < 0.20) || (type === 'tough' && r < 0.15)) {
powerUp = Math.random() < 0.5 ? 'wide' : 'multiball';
}
const x = col * (BRICK_W + 7) + 23;
const y = row * (BRICK_H + 7) + 35;
bricks.push({
x, y, w: BRICK_W, h: BRICK_H,
type, hp, maxHp: hp,
powerUp,
cracked: false
});
}
}
}
// ---------- BALL HELPERS ----------
function spawnBall(x, y, angle = null) {
let speed = BASE_SPEED;
let dx, dy;
if (angle !== null) {
dx = Math.cos(angle) * speed;
dy = -Math.sin(angle) * speed;
} else {
// default: slight random variation upward
let a = -Math.PI/2 + (Math.random() - 0.5) * 0.8;
dx = Math.cos(a) * speed;
dy = -Math.sin(a) * speed;
}
balls.push({ x, y, r: BALL_RADIUS, dx, dy, speed });
}
function resetBall(keepMultiball = false) {
balls = [];
if (!keepMultiball) multiBallActive = false;
spawnBall(W/2, paddle.y - 18);
}
// ---------- RESET GAME ----------
function fullReset() {
score = 0;
lives = 3;
widePaddleTimer = 0;
multiBallActive = false;
paddle.w = PADDLE_W;
paddle.x = (W - paddle.w) / 2;
buildLevel();
resetBall(false);
powerups = [];
particles = [];
leftPressed = false;
rightPressed = false;
updateUI();
}
// ---------- UI UPDATE ----------
function updateUI() {
livesSpan.textContent = lives;
scoreSpan.textContent = score;
}
// ---------- COLLISION & PHYSICS ----------
function ballBrickCollision(ball, brick) {
// closest point on brick to ball
let cx = Math.max(brick.x, Math.min(ball.x, brick.x + brick.w));
let cy = Math.max(brick.y, Math.min(ball.y, brick.y + brick.h));
let dx = ball.x - cx;
let dy = ball.y - cy;
let dist = Math.sqrt(dx*dx + dy*dy);
if (dist < ball.r) {
// normal
let nx = dx / dist || 0;
let ny = dy / dist || -1;
// reflect
let dot = ball.dx * nx + ball.dy * ny;
ball.dx -= 2 * dot * nx;
ball.dy -= 2 * dot * ny;
// push outside
let overlap = ball.r - dist;
ball.x += nx * overlap;
ball.y += ny * overlap;
return true;
}
return false;
}
function ballPaddleCollision(ball) {
if (ball.y + ball.r > paddle.y && ball.y - ball.r < paddle.y + paddle.h &&
ball.x + ball.r > paddle.x && ball.x - ball.r < paddle.x + paddle.w) {
// relative hit position -1 .. 1
let rel = (ball.x - (paddle.x + paddle.w/2)) / (paddle.w/2);
rel = Math.max(-1, Math.min(1, rel));
let angle = -Math.PI/2 + rel * (Math.PI/3.2); // max 60° deflection
let speed = Math.sqrt(ball.dx*ball.dx + ball.dy*ball.dy);
ball.dx = Math.cos(angle) * speed;
ball.dy = -Math.sin(angle) * speed;
// push above
ball.y = paddle.y - ball.r;
return true;
}
return false;
}
// ---------- POWER UPS ----------
function spawnPowerup(x, y, type) {
powerups.push({
x, y, w: 24, h: 14,
type,
speed: 2.2
});
}
// ---------- PARTICLES ----------
function emitParticles(x, y, color, count = 14) {
for (let i = 0; i < count; i++) {
const angle = Math.random() * 2 * Math.PI;
const speed = 1.2 + Math.random() * 3.2;
particles.push({
x, y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
life: 1.0,
decay: 0.012 + Math.random() * 0.025,
size: 3 + Math.random() * 7,
color: color
});
}
}
// ---------- UPDATE ----------
function update() {
if (gameState !== 'running') return;
// paddle movement
if (leftPressed) paddle.x -= 7;
if (rightPressed) paddle.x += 7;
if (mouseX !== null) {
let target = mouseX - paddle.w/2;
paddle.x += (target - paddle.x) * 0.26;
}
paddle.x = Math.max(0, Math.min(W - paddle.w, paddle.x));
// wide timer
if (widePaddleTimer > 0) {
widePaddleTimer--;
if (widePaddleTimer === 0) {
paddle.w = PADDLE_W;
paddle.x = Math.min(paddle.x, W - paddle.w);
}
}
// move balls
for (let i = balls.length-1; i>=0; i--) {
let b = balls[i];
b.x += b.dx;
b.y += b.dy;
// walls
if (b.x - b.r < 0) { b.x = b.r; b.dx = -b.dx; }
if (b.x + b.r > W) { b.x = W - b.r; b.dx = -b.dx; }
if (b.y - b.r < 0) { b.y = b.r; b.dy = -b.dy; }
// bottom => lose ball
if (b.y + b.r > H) {
balls.splice(i, 1);
continue;
}
// paddle collision
ballPaddleCollision(b);
// brick collision
for (let j = bricks.length-1; j>=0; j--) {
let brick = bricks[j];
if (ballBrickCollision(b, brick)) {
brick.hp--;
if (brick.hp <= 0) {
// destroy brick
let col = brick.powerUp ? '#facc15' : (brick.type === 'tough' ? '#a78bfa' : '#38bdf8');
emitParticles(brick.x + brick.w/2, brick.y + brick.h/2, col, 18);
if (brick.powerUp) {
spawnPowerup(brick.x + brick.w/2, brick.y, brick.powerUp);
}
bricks.splice(j, 1);
score += 10;
updateUI();
} else {
brick.cracked = true;
emitParticles(brick.x + brick.w/2, brick.y + brick.h/2, '#cbd5e1', 6);
}
break; // only one brick per frame
}
}
}
// game over if no balls and lives
if (balls.length === 0) {
lives--;
updateUI();
if (lives <= 0) {
gameState = 'gameover';
overlayTitle.textContent = '💀 GAME OVER';
overlayAction.textContent = '🔄 Play again';
overlay.classList.add('show');
return;
} else {
// reset ball (keep multiball status?)
resetBall(multiBallActive);
if (multiBallActive && balls.length === 1) {
// add second & third balls
for (let k=0; k<2; k++) {
let angle = -Math.PI/2 + (k===0? -0.4 : 0.4);
spawnBall(W/2, paddle.y - 18, angle);
}
}
}
}
// powerups
for (let i=powerups.length-1; i>=0; i--) {
let p = powerups[i];
p.y += p.speed;
// catch with paddle
if (p.y + p.h > paddle.y && p.y < paddle.y + paddle.h &&
p.x + p.w > paddle.x && p.x < paddle.x + paddle.w) {
if (p.type === 'wide') {
widePaddleTimer = WIDE_DURATION;
paddle.w = WIDE_PADDLE_W;
paddle.x = Math.min(paddle.x, W - paddle.w);
} else if (p.type === 'multiball') {
multiBallActive = true;
// add 2 extra balls near existing ones
let existing = balls.length > 0 ? balls : [null];
for (let k=0; k<2; k++) {
let ref = balls.length > 0 ? balls[0] : { x: W/2, y: paddle.y - 18 };
let angle = -Math.PI/2 + (k===0? -0.5 : 0.5);
spawnBall(ref.x, ref.y, angle);
}
}
powerups.splice(i,1);
continue;
}
if (p.y > H + 30) powerups.splice(i,1);
}
// particles
for (let i=particles.length-1; i>=0; i--) {
let p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.life -= p.decay;
if (p.life <= 0) particles.splice(i,1);
}
// victory?
if (bricks.length === 0) {
gameState = 'victory';
overlayTitle.textContent = '🎉 VICTORY!';
overlayAction.textContent = '⭐ Play again';
overlay.classList.add('show');
}
}
// ---------- DRAW ----------
function draw() {
ctx.clearRect(0, 0, W, H);
// background
ctx.fillStyle = '#0b1120';
ctx.fillRect(0,0,W,H);
// bricks
for (let brick of bricks) {
let color = brick.type === 'tough' ? '#7c3aed' : '#0ea5e9';
ctx.fillStyle = brick.cracked ? '#94a3b8' : color;
ctx.shadowColor = '#ffffff20';
ctx.shadowBlur = 6;
ctx.beginPath();
ctx.roundRect(brick.x, brick.y, brick.w, brick.h, 6);
ctx.fill();
// power up icon
if (brick.powerUp) {
ctx.shadowBlur = 0;
ctx.font = 'bold 16px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = '#fde047';
ctx.fillText(brick.powerUp === 'wide' ? '⬛' : '🔮', brick.x + brick.w/2, brick.y + brick.h/2 - 1);
}
// crack lines
if (brick.cracked) {
ctx.strokeStyle = '#1e293b';
ctx.lineWidth = 1.8;
ctx.beginPath();
ctx.moveTo(brick.x+8, brick.y+4);
ctx.lineTo(brick.x+22, brick.y+18);
ctx.moveTo(brick.x+brick.w-12, brick.y+6);
ctx.lineTo(brick.x+brick.w-20, brick.y+19);
ctx.stroke();
}
}
ctx.shadowBlur = 0;
// paddle
ctx.shadowColor = '#38bdf880';
ctx.shadowBlur = 16;
ctx.fillStyle = '#f1f5f9';
ctx.beginPath();
ctx.roundRect(paddle.x, paddle.y, paddle.w, paddle.h, 12);
ctx.fill();
ctx.shadowBlur = 0;
// balls
for (let b of balls) {
ctx.shadowColor = '#facc1590';
ctx.shadowBlur = 20;
ctx.beginPath();
ctx.arc(b.x, b.y, b.r, 0, Math.PI*2);
ctx.fillStyle = '#fde047';
ctx.fill();
}
ctx.shadowBlur = 0;
// powerups
for (let p of powerups) {
ctx.fillStyle = p.type === 'wide' ? '#60a5fa' : '#a78bfa';
ctx.shadowColor = '#ffffff40';
ctx.shadowBlur = 12;
ctx.beginPath();
ctx.roundRect(p.x, p.y, p.w, p.h, 8);
ctx.fill();
ctx.shadowBlur = 0;
ctx.font = 'bold 14px sans-serif';
ctx.fillStyle = '#fff';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(p.type === 'wide' ? '⬛' : '⚡', p.x + p.w/2, p.y + p.h/2);
}
// particles
for (let p of particles) {
ctx.globalAlpha = p.life;
ctx.fillStyle = p.color;
ctx.shadowBlur = 0;
ctx.fillRect(p.x - p.size/2, p.y - p.size/2, p.size, p.size);
}
ctx.globalAlpha = 1;
// wide timer indicator
if (widePaddleTimer > 0) {
ctx.fillStyle = '#60a5fa60';
ctx.font = '13px monospace';
ctx.textAlign = 'right';
ctx.fillText(`⬛ ${(widePaddleTimer/60).toFixed(1)}s`, W-16, 26);
}
}
// roundRect polyfill
CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) {
if (r > w/2) r = w/2;
if (r > h/2) r = h/2;
this.moveTo(x+r, y);
this.arcTo(x+w, y, x+w, y+h, r);
this.arcTo(x+w, y+h, x, y+h, r);
this.arcTo(x, y+h, x, y, r);
this.arcTo(x, y, x+w, y, r);
return this;
};
// ---------- GAME LOOP ----------
function loop() {
update();
draw();
requestAnimationFrame(loop);
}
// ---------- START / RESTART ----------
function startGame() {
fullReset();
gameState = 'running';
overlay.classList.remove('show');
mouseX = null;
leftPressed = false;
rightPressed = false;
}
// ---------- EVENT LISTENERS ----------
function handleKey(e) {
const key = e.key;
if (key === 'ArrowLeft' || key === 'Left' || key === 'a' || key === 'A') {
leftPressed = true; e.preventDefault();
} else if (key === 'ArrowRight' || key === 'Right' || key === 'd' || key === 'D') {
rightPressed = true; e.preventDefault();
}
if (gameState === 'idle' || gameState === 'gameover' || gameState === 'victory') {
startGame();
}
}
function handleKeyUp(e) {
const key = e.key;
if (key === 'ArrowLeft' || key === 'Left' || key === 'a' || key === 'A') {
leftPressed = false; e.preventDefault();
} else if (key === 'ArrowRight' || key === 'Right' || key === 'd' || key === 'D') {
rightPressed = false; e.preventDefault();
}
}
document.addEventListener('keydown', handleKey);
document.addEventListener('keyup', handleKeyUp);
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
mouseX = (e.clientX - rect.left) * scaleX;
mouseX = Math.max(0, Math.min(W, mouseX));
});
canvas.addEventListener('mouseleave', () => { mouseX = null; });
canvas.addEventListener('click', () => {
if (gameState === 'idle' || gameState === 'gameover' || gameState === 'victory') {
startGame();
}
});
overlayAction.addEventListener('click', (e) => {
e.stopPropagation();
startGame();
});
// touch support (mobile)
canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
const touch = e.touches[0];
const scaleX = canvas.width / rect.width;
mouseX = (touch.clientX - rect.left) * scaleX;
mouseX = Math.max(0, Math.min(W, mouseX));
}, { passive: false });
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
if (gameState === 'idle' || gameState === 'gameover' || gameState === 'victory') startGame();
const rect = canvas.getBoundingClientRect();
const touch = e.touches[0];
const scaleX = canvas.width / rect.width;
mouseX = (touch.clientX - rect.left) * scaleX;
}, { passive: false });
canvas.addEventListener('touchend', () => { mouseX = null; });
// ---------- INIT ----------
fullReset();
gameState = 'idle';
overlay.classList.add('show');
overlayTitle.textContent = '🧱 BREAKOUT';
overlayAction.textContent = 'Click or press a key to start';
updateUI();
loop();
})();
</script>
</body>
</html>