GLM 5.3 Flash
by Z.aiReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 28.4 s
- Cost
- $0.0017
- Output tokens
- 4,478
- Spent thinking
- 18 tokens
- Speed
- 164.4 tok/s
- Console errors
- 0
- First token after
- 1.2 s
- First visible text after
- 1.4 s
- Prompt tokens
- 507
- Code size
- 12.5 KB
- Finish reason
- stop
- Served by
- DigitalOcean
- Model id
z-ai/glm-5.3-flash- Reasoning sent
{"effort":"low"}- Max output
- 64,000 tokens
- Generated
- Nov 10, 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 · 303 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Breakout</title>
<style>
html,body{margin:0;padding:0;background:#0b0e1a;height:100%;overflow:hidden;font-family:'Segoe UI',system-ui,sans-serif;color:#eef;}
#wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;}
canvas{background:linear-gradient(180deg,#0d1030,#131740);border-radius:10px;box-shadow:0 0 40px rgba(80,120,255,.25);touch-action:none;max-width:100vw;}
#hud{width:800px;max-width:98vw;display:flex;justify-content:space-between;padding:8px 4px;font-size:16px;letter-spacing:1px;text-shadow:0 0 8px rgba(120,150,255,.6);}
#hud span b{color:#ffd76a;font-weight:600;}
.overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(8,10,25,.72);backdrop-filter:blur(3px);border-radius:10px;text-align:center;z-index:5;}
.overlay h1{font-size:52px;margin:0 0 12px;text-shadow:0 0 25px rgba(130,160,255,.8);}
.overlay p{margin:6px 0;font-size:17px;color:#aab4e8;}
.overlay .blink{margin-top:22px;font-size:20px;color:#ffd76a;animation:bl 1.2s infinite;}
@keyframes bl{50%{opacity:.25}}
#stage{position:relative;}
</style>
</head>
<body>
<div id="wrap">
<div id="hud"><span>SCORE <b id="score">0</b></span><span>LIVES <b id="lives">♥♥♥</b></span><span id="buff"></span></div>
<div id="stage">
<canvas id="c" width="800" height="560"></canvas>
<div class="overlay" id="ov" style="display:none"><h1 id="ovT">BREAKOUT</h1><p id="ovP">Mouse or ← → keys to move · catch power-ups</p><div class="blink">Click or press a key to start</div></div>
</div>
</div>
<script>
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
const W=800,H=560;
const ov=document.getElementById('ov'),ovT=document.getElementById('ovT'),ovP=document.getElementById('ovP');
let started=false,gameOver=false,won=false;
let score=0,lives=3;
let paddle={x:W/2-55,w:110,h:14,y:H-40,speed:7,dir:0};
let balls=[],bricks=[],parts=[],drops=[],floats=[];
let wideTimer=0;
const COLS=10,ROWS=7,BW=72,BH=24,GX=(W-COLS*BW)/2+ (COLS-1)*0, TOP=70,GAP=4;
const colors=['#ff5d6c','#ffa14a','#ffd76a','#6be08a','#5ac8ff','#b98bff','#ff8bd6'];
function makeBricks(){
bricks=[];
const toughPattern=[1,0,1,1,0,1,1,0,1,1, 0,1,1,0,1,0,1,1,0,1];
for(let r=0;r<ROWS;r++)for(let c=0;c<COLS;c++){
const tough=(r<2)? (c%3!==2) : (r<4? (c%4===1):(c%5===2));
const hp=tough?2:1;
const pu=(Math.random()<0.14)&&!bricks.some(b=>b.power);
const power=pu?(Math.random()<0.5?'wide':'multi'):null;
bricks.push({x:GX+c*(BW+GAP),y:TOP+r*(BH+GAP),w:BW,h:BH,hp,maxhp:hp,row:r,color:tough?'#8fa2ff':colors[r%colors.length],power,alive:true});
}
// guarantee at least 2 power-ups
if(!bricks.some(b=>b.power)){bricks[12].power='wide';bricks[40].power='multi';}
}
function newBall(x,y,vx,vy){return{x,y,vx,vy,r:7,stuck:false};}
function resetBall(){balls=[newBall(paddle.x+paddle.w/2,paddle.y-12,0,0)];balls[0].stuck=true;}
function startGame(){
score=0;lives=3;wideTimer=0;paddle.w=110;drops=[];parts=[];floats=[];
makeBricks();resetBall();gameOver=false;won=false;updHUD();
}
function updHUD(){
document.getElementById('score').textContent=score;
document.getElementById('lives').textContent='♥'.repeat(Math.max(0,lives));
document.getElementById('buff').textContent=wideTimer>0?('WIDE '+Math.ceil(wideTimer)+'s'):'';
}
function launch(){
const b=balls.find(b=>b.stuck);
if(b){b.stuck=false;b.vx=(Math.random()*2-1)*2.2;b.vy=-5;}
}
// ---------- input ----------
let mouseX=null;
cv.addEventListener('mousemove',e=>{
const r=cv.getBoundingClientRect();
mouseX=(e.clientX-r.left)*(W/r.width);
});
cv.addEventListener('click',()=>{if(started&&!gameOver&&!won)launch();});
window.addEventListener('keydown',e=>{
if(!started){startPlay();return;}
if(e.key==='ArrowLeft')paddle.dir=-1;
if(e.key==='ArrowRight')paddle.dir=1;
if(e.key===' '&&started&&!gameOver&&!won)launch();
});
window.addEventListener('keyup',e=>{if(e.key==='ArrowLeft'&&paddle.dir<0)paddle.dir=0;if(e.key==='ArrowRight'&&paddle.dir>0)paddle.dir=0;});
ov.addEventListener('click',()=>{if(!started)startPlay();else if(gameOver||won)startPlay();});
function startPlay(){started=true;ov.style.display='none';startGame();}
function showOv(t,p){ovT.textContent=t;ovP.textContent=p;ov.style.display='flex';}
// ---------- physics ----------
function collideBricks(){
for(const b of balls){
if(b.stuck)continue;
for(const br of bricks){
if(!br.alive)continue;
// closest point
const cx=Math.max(br.x,Math.min(b.x,br.x+br.w));
const cy=Math.max(br.y,Math.min(b.y,br.y+br.h));
const dx=b.x-cx,dy=b.y-cy;
if(dx*dx+dy*dy<=b.r*b.r){
// resolve: push out along smallest penetration axis
const ox=(b.x<br.x+br.w/2)?(b.x+b.r-br.x):(b.x-b.r-(br.x+br.w));
const oy=(b.y<br.y+br.h/2)?(b.y+b.r-br.y):(b.y-b.r-(br.y+br.h));
if(Math.abs(ox)<Math.abs(oy)){b.vx=(ox<0?-1:1)*Math.abs(b.vx);b.x=(ox<0?br.x-b.r:br.x+br.w+b.r);}
else{b.vy=(oy<0?-1:1)*Math.abs(b.vy);b.y=(oy<0?br.y-b.r:br.y+br.h+b.r);}
hitBrick(br,b);
break;
}
}
}
}
function hitBrick(br,ball){
br.hp--;
if(br.hp<=0){
br.alive=false;
score+=br.maxhp>1?30:15;
spawnParts(br.x+br.w/2,br.y+br.h/2,br.color,br.power?26:14);
if(br.power){drops.push({x:br.x+br.w/2,y:br.y+br.h/2,type:br.power,vy:2.4});}
updHUD();
}else{
score+=5;updHUD();
}
}
function spawnParts(x,y,color,n){
for(let i=0;i<n;i++){
const a=Math.random()*Math.PI*2,s=1+Math.random()*4;
parts.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s-1,life:1,color,size:2+Math.random()*3});
}
}
function paddleBounce(b){
// angle from hit position: center = straight up, edges = sharp
const rel=(b.x-(paddle.x+paddle.w/2))/(paddle.w/2);
const cl=Math.max(-1,Math.min(1,rel));
const ang=cl*(Math.PI/3); // up to 60° from vertical
const sp=Math.hypot(b.vx,b.vy);
b.vx=Math.sin(ang)*sp;
b.vy=-Math.abs(Math.cos(ang)*sp);
b.y=paddle.y-b.r-0.1;
}
function update(dt){
// paddle
if(mouseX!==null)paddle.x=mouseX-paddle.w/2;
paddle.x+=paddle.dir*paddle.speed;
paddle.x=Math.max(8,Math.min(W-paddle.w-8,paddle.x));
if(wideTimer>0){wideTimer-=dt;if(wideTimer<=0){paddle.w=110;updHUD();}}
// balls
for(let i=balls.length-1;i>=0;i--){
const b=balls[i];
if(b.stuck){b.x=paddle.x+paddle.w/2;b.y=paddle.y-b.r-2;continue;}
// substep to avoid tunneling
const steps=Math.ceil(Math.max(Math.abs(b.vx),Math.abs(b.vy))/4)||1;
let dead=false;
for(let s=0;s<steps&&!dead;s++){
b.x+=b.vx/steps;b.y+=b.vy/steps;
if(b.x-b.r<0){b.x=b.r;b.vx=Math.abs(b.vx);}
if(b.x+b.r>W){b.x=W-b.r;b.vx=-Math.abs(b.vx);}
if(b.y-b.r<0){b.y=b.r;b.vy=Math.abs(b.vy);}
// paddle
if(b.vy>0&&b.y+b.r>=paddle.y&&b.y+b.r<=paddle.y+paddle.h+b.vy&&b.x>paddle.x-b.r&&b.x<paddle.x+paddle.w+b.r){
paddleBounce(b);
}
if(b.y-b.r>H){dead=true;}
}
if(dead){balls.splice(i,1);continue;}
// wall-bottom handled; bricks inside substeps:
collideBricks();
}
if(balls.length===0&&!gameOver&&!won){
lives--;updHUD();
if(lives<=0){gameOver=true;showOv('GAME OVER','Score: '+score);}
else resetBall();
}
// drops
for(let i=drops.length-1;i>=0;i--){
const d=drops[i];d.y+=d.vy;
if(d.y>paddle.y-8&&d.y<paddle.y+paddle.h+10&&d.x>paddle.x-12&&d.x<paddle.x+paddle.w+12){
if(d.type==='wide'){paddle.w=170;wideTimer=10;floats.push({x:d.x,y:d.y,t:'WIDE PADDLE',life:1.2,c:'#6be08a'});}
else{
const src=balls[0]||{x:d.x,y:d.y,vx:0,vy:-5};
for(let k=-1;k<=1;k+=2){
const nb=newBall(src.x,src.y-4,(src.stuck?2.5*k:src.vx+k*1.4),src.stuck?-5:src.vy);
if(src.stuck){nb.stuck=false;}
balls.push(nb);
}
floats.push({x:d.x,y:d.y,t:'MULTI-BALL',life:1.2,c:'#ff8bd6'});
}
drops.splice(i,1);updHUD();
}else if(d.y>H+20)drops.splice(i,1);
}
// particles
for(let i=parts.length-1;i>=0;i--){
const p=parts[i];p.x+=p.vx;p.y+=p.vy;p.vy+=0.12;p.life-=0.025;
if(p.life<=0)parts.splice(i,1);
}
for(let i=floats.length-1;i>=0;i--){floats[i].y-=0.6;floats[i].life-=0.02;if(floats[i].life<=0)floats.splice(i,1);}
// victory
if(!gameOver&&!won&&bricks.every(b=>!b.alive)){won=true;showOv('VICTORY!','Score: '+score);}
}
function draw(){
ctx.clearRect(0,0,W,H);
// subtle grid bg
ctx.fillStyle='rgba(255,255,255,0.03)';
for(let y=0;y<H;y+=40)ctx.fillRect(0,y,W,1);
// bricks
for(const br of bricks){
if(!br.alive)continue;
ctx.fillStyle=br.color;
ctx.shadowColor=br.color;ctx.shadowBlur=8;
roundRect(br.x,br.y,br.w,br.h,5);ctx.fill();
ctx.shadowBlur=0;
// cracked overlay
if(br.hp<br.maxhp){
ctx.strokeStyle='rgba(20,20,40,0.85)';ctx.lineWidth=1.6;
ctx.beginPath();
ctx.moveTo(br.x+br.w*0.2,br.y);ctx.lineTo(br.x+br.w*0.4,br.y+br.h*0.55);
ctx.lineTo(br.x+br.w*0.28,br.y+br.h);ctx.moveTo(br.x+br.w*0.4,br.y+br.h*0.55);
ctx.lineTo(br.x+br.w*0.68,br.y+br.h*0.4);
ctx.stroke();
ctx.fillStyle='rgba(0,0,20,0.28)';roundRect(br.x,br.y,br.w,br.h,5);ctx.fill();
}
// power icon
if(br.power){
ctx.fillStyle='rgba(255,255,255,0.92)';
ctx.beginPath();
const cx=br.x+br.w/2,cy=br.y+br.h/2;
if(br.power==='wide'){ctx.fillRect(cx-9,cy-2,18,4);ctx.fillRect(cx-3,cy-8,6,16);}
else{ctx.arc(cx,cy,6.5,0,7);ctx.fill();ctx.fillStyle=br.color;ctx.beginPath();ctx.arc(cx,cy,2.6,0,7);ctx.fill();}
}
}
// drops
for(const d of drops){
const col=d.type==='wide'?'#6be08a':'#ff8bd6';
ctx.shadowColor=col;ctx.shadowBlur=12;
ctx.fillStyle=col;
ctx.beginPath();ctx.arc(d.x,d.y,9,0,7);ctx.fill();
ctx.shadowBlur=0;
ctx.fillStyle='#0b0e1a';ctx.font='bold 11px sans-serif';ctx.textAlign='center';ctx.textBaseline='middle';
ctx.fillText(d.type==='wide'?'W':'M',d.x,d.y+0.5);
}
// paddle
ctx.shadowColor='#5ac8ff';ctx.shadowBlur=14;
const pg=ctx.createLinearGradient(paddle.x,paddle.y,paddle.x,paddle.y+paddle.h);
pg.addColorStop(0,'#9fd8ff');pg.addColorStop(1,'#3f8fd8');
ctx.fillStyle=pg;roundRect(paddle.x,paddle.y,paddle.w,paddle.h,7);ctx.fill();
ctx.shadowBlur=0;
// balls
for(const b of balls){
ctx.shadowColor='#fff';ctx.shadowBlur=12;
const g=ctx.createRadialGradient(b.x-2,b.y-2,1,b.x,b.y,b.r);
g.addColorStop(0,'#fff');g.addColorStop(1,'#aac8ff');
ctx.fillStyle=g;ctx.beginPath();ctx.arc(b.x,b.y,b.r,0,7);ctx.fill();
ctx.shadowBlur=0;
}
// particles
for(const p of parts){
ctx.globalAlpha=Math.max(0,p.life);
ctx.fillStyle=p.color;ctx.fillRect(p.x,p.y,p.size,p.size);
}
ctx.globalAlpha=1;
// floating labels
ctx.font='bold 15px sans-serif';ctx.textAlign='center';
for(const f of floats){ctx.globalAlpha=Math.min(1,f.life);ctx.fillStyle=f.c;ctx.fillText(f.t,f.x,f.y);}
ctx.globalAlpha=1;
// stuck hint
if(balls.some(b=>b.stuck)&&started&&!gameOver&&!won){
ctx.fillStyle='rgba(255,255,255,0.55)';ctx.font='14px sans-serif';ctx.fillText('Click or press Space to launch',W/2,paddle.y-40);
}
}
function roundRect(x,y,w,h,r){ctx.beginPath();ctx.moveTo(x+r,y);ctx.arcTo(x+w,y,x+w,y+h,r);ctx.arcTo(x+w,y+h,x,y+h,r);ctx.arcTo(x,y+h,x,y,r);ctx.arcTo(x,y,x+w,y,r);ctx.closePath();}
// ---------- demo AI (before start) ----------
function demoAI(){
if(started)return;
// keep bricks alive for demo backdrop
if(!bricks.length)makeBricks();
// a demo ball bouncing
if(!balls.length){const b=newBall(W/2,300,3.4,-4.2);b.stuck=false;balls.push(b);}
for(const b of balls){
b.x+=b.vx;b.y+=b.vy;
if(b.x<b.r||b.x>W-b.r)b.vx*=-1;
if(b.y<b.r)b.vy=Math.abs(b.vy);
if(b.y>H-10){b.y=H/2;b.vy=-Math.abs(b.vy);}
// paddle follow
const tgt=b.x-paddle.w/2;
paddle.x+=(tgt-paddle.x)*0.15;
paddle.x=Math.max(8,Math.min(W-paddle.w-8,paddle.x));
if(b.vy>0&&b.y+b.r>=paddle.y&&b.y<paddle.y+16&&b.x>paddle.x-b.r&&b.x<paddle.x+paddle.w+b.r){
paddleBounce(b);collideBricks();
}
}
collideBricks();
for(let i=parts.length-1;i>=0;i--){const p=parts[i];p.x+=p.vx;p.y+=p.vy;p.vy+=0.12;p.life-=0.025;if(p.life<=0)parts.splice(i,1);}
}
let last=0;
function loop(t){
const dt=Math.min(0.05,(t-last)/1000);last=t;
if(started&&!gameOver&&!won)update(dt);
else if(!started)demoAI();
else{ // frozen scenes still animate particles
for(let i=parts.length-1;i>=0;i--){const p=parts[i];p.x+=p.vx;p.y+=p.vy;p.vy+=0.12;p.life-=0.025;if(p.life<=0)parts.splice(i,1);}
}
draw();
requestAnimationFrame(loop);
}
makeBricks();
requestAnimationFrame(loop);
</script>
</body>
</html>Reasoning trace (18 tokens)
Output single HTML file. Build breakout game with all features. Keep reasonably concise but polished.