Models 44

GLM 5.3 Flash

by Z.aiReasoningClean
Open in new window

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.