LeafCat79 commited on
Commit
c437906
·
verified ·
1 Parent(s): f9787b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -21
app.py CHANGED
@@ -317,50 +317,70 @@ CODE_SYSTEM = (
317
  " const canvas = document.getElementById('gameCanvas'); "
318
  " const ctx = canvas.getContext('2d'); "
319
  " const playerImg = new Image(); playerImg.src = 'sprite_player.png'; "
320
- " const bgImg = new Image(); bgImg.src = 'sprite_background.png'; "
321
- " const enemyImg = new Image(); enemyImg.src = 'sprite_enemy.png'; "
322
  " const keys = new Set(); "
323
  " const bullets = []; "
324
  " const enemies = []; "
325
  " let score = 0; let health = 3; let frameCount = 0; let gameOver = false; "
326
- "2. FOR TOP-DOWN SHOOTER declare player right after: "
327
  " let player = {x: canvas.width/2-24, y: canvas.height/2-24, w:48, h:48, speed:4}; "
328
- "3. Use Promise.all to wait for images AFTER all declarations: "
 
329
  " function loadImg(img) { return new Promise(r => { img.onload = r; }); } "
330
  " Promise.all([loadImg(playerImg), loadImg(bgImg), loadImg(enemyImg)]).then(startGame); "
331
- "4. startGame() only sets up listeners and starts the loop - NO canvas/ctx/player here: "
332
  " function startGame() { "
333
  " window.addEventListener('keydown', e => keys.add(e.key)); "
334
  " window.addEventListener('keyup', e => keys.delete(e.key)); "
335
  " canvas.addEventListener('click', onShoot); "
336
  " requestAnimationFrame(gameLoop); } "
337
- "5. gameLoop() uses the top-level canvas and ctx - NEVER redeclare them inside gameLoop: "
338
  " function gameLoop() { "
339
  " if (gameOver) return; "
340
  " ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height); "
341
- " ... game logic ... "
342
  " requestAnimationFrame(gameLoop); } "
343
- "6. FOR TOP-DOWN SHOOTER movement - copy EXACTLY: "
344
  " if (keys.has('w')||keys.has('W')||keys.has('ArrowUp')) player.y -= player.speed; "
345
  " if (keys.has('s')||keys.has('S')||keys.has('ArrowDown')) player.y += player.speed; "
346
  " if (keys.has('a')||keys.has('A')||keys.has('ArrowLeft')) player.x -= player.speed; "
347
  " if (keys.has('d')||keys.has('D')||keys.has('ArrowRight')) player.x += player.speed; "
348
- " player.x = Math.max(0, Math.min(canvas.width-player.w, player.x)); "
349
- " player.y = Math.max(0, Math.min(canvas.height-player.h, player.y)); "
350
- "7. FOR TOP-DOWN SHOOTER bullets - fire on MOUSE CLICK straight UPWARD: "
351
  " function onShoot(e) { "
352
- " bullets.push({x:player.x+player.w/2-4, y:player.y-16, w:8, h:16, vy:-10}); } "
353
- " Each frame: bullets[i].y += bullets[i].vy; draw yellow rect; remove when y+h<0. "
 
 
 
 
 
 
 
 
354
  "8. FOR TOP-DOWN SHOOTER enemies - spawn every 120 frames, fall straight down: "
355
  " frameCount++; "
356
- " if (frameCount % 120 === 0) enemies.push({x:Math.random()*(canvas.width-32), y:0, w:32, h:32, speed:1.5}); "
357
- " Each frame: e.y += e.speed; draw with ctx.drawImage(enemyImg,e.x,e.y,32,32); "
 
 
 
 
358
  " Remove if e.y > canvas.height. If overlaps player: health--; remove enemy. "
359
- " Check bullet-enemy collision: remove both. score += 10. "
360
  "9. Draw player: ctx.drawImage(playerImg, player.x, player.y, player.w, player.h). "
361
- "10. GAME OVER when health<=0: set gameOver=true, draw Game Over + score on canvas, "
362
- " draw Restart button on canvas, add ONE-TIME click listener calling reset(). "
363
- "11. reset() resets all variables: player pos, bullets, enemies, score, health, frameCount, gameOver=false, then requestAnimationFrame(gameLoop). "
 
 
 
 
 
 
 
 
364
  "12. FOR PLATFORMER: gravity velY+=0.5, jump ArrowUp/W/Space velY=-12 when grounded. "
365
  " Set grounded=false BEFORE platform loop. Set true and velY=0 only on landing. "
366
  " Full-width ground at y=420. "
@@ -451,9 +471,11 @@ def _wrap_in_html(snippet: str, theme: str) -> str:
451
  def _build_preview(html_code: str) -> str:
452
  encoded = base64.b64encode(html_code.encode("utf-8")).decode("ascii")
453
  return (
 
454
  f'<iframe src="data:text/html;base64,{encoded}" '
455
- f'style="width:{CANVAS_W}px;height:{CANVAS_H}px;border:none;border-radius:12px;background:#000;display:block;" '
456
- 'sandbox="allow-scripts" title="Game Preview"></iframe>'
 
457
  )
458
 
459
 
 
317
  " const canvas = document.getElementById('gameCanvas'); "
318
  " const ctx = canvas.getContext('2d'); "
319
  " const playerImg = new Image(); playerImg.src = 'sprite_player.png'; "
320
+ " const bgImg = new Image(); bgImg.src = 'sprite_background.png'; "
321
+ " const enemyImg = new Image(); enemyImg.src = 'sprite_enemy.png'; "
322
  " const keys = new Set(); "
323
  " const bullets = []; "
324
  " const enemies = []; "
325
  " let score = 0; let health = 3; let frameCount = 0; let gameOver = false; "
326
+ "2. FOR TOP-DOWN SHOOTER declare player right after (center of canvas, NOT at bottom): "
327
  " let player = {x: canvas.width/2-24, y: canvas.height/2-24, w:48, h:48, speed:4}; "
328
+ " DO NOT set player.y = canvas.height - 24. Player starts in the CENTER. "
329
+ "3. Use Promise.all AFTER all declarations: "
330
  " function loadImg(img) { return new Promise(r => { img.onload = r; }); } "
331
  " Promise.all([loadImg(playerImg), loadImg(bgImg), loadImg(enemyImg)]).then(startGame); "
332
+ "4. startGame() ONLY sets up listeners and starts the loop: "
333
  " function startGame() { "
334
  " window.addEventListener('keydown', e => keys.add(e.key)); "
335
  " window.addEventListener('keyup', e => keys.delete(e.key)); "
336
  " canvas.addEventListener('click', onShoot); "
337
  " requestAnimationFrame(gameLoop); } "
338
+ "5. gameLoop() NEVER redeclares canvas or ctx: "
339
  " function gameLoop() { "
340
  " if (gameOver) return; "
341
  " ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height); "
342
+ " ... update and draw everything ... "
343
  " requestAnimationFrame(gameLoop); } "
344
+ "6. FOR TOP-DOWN SHOOTER movement - 4 directions, clamp inside canvas: "
345
  " if (keys.has('w')||keys.has('W')||keys.has('ArrowUp')) player.y -= player.speed; "
346
  " if (keys.has('s')||keys.has('S')||keys.has('ArrowDown')) player.y += player.speed; "
347
  " if (keys.has('a')||keys.has('A')||keys.has('ArrowLeft')) player.x -= player.speed; "
348
  " if (keys.has('d')||keys.has('D')||keys.has('ArrowRight')) player.x += player.speed; "
349
+ " player.x = Math.max(0, Math.min(canvas.width - player.w, player.x)); "
350
+ " player.y = Math.max(0, Math.min(canvas.height - player.h, player.y)); "
351
+ "7. FOR TOP-DOWN SHOOTER bullets - MOUSE CLICK fires bullet straight UP ONLY, NO vx: "
352
  " function onShoot(e) { "
353
+ " bullets.push({x: player.x+player.w/2-4, y: player.y-16, w:8, h:16, vy:-10}); } "
354
+ " Inside gameLoop update bullets like this EXACTLY: "
355
+ " for (let i = bullets.length-1; i >= 0; i--) { "
356
+ " bullets[i].y += bullets[i].vy; "
357
+ " ctx.fillStyle='yellow'; ctx.fillRect(bullets[i].x, bullets[i].y, 8, 16); "
358
+ " if (bullets[i].y + 16 < 0) { bullets.splice(i,1); continue; } "
359
+ " for (let j = enemies.length-1; j >= 0; j--) { "
360
+ " if (bullets[i] && bullets[i].x < enemies[j].x+32 && bullets[i].x+8 > enemies[j].x "
361
+ " && bullets[i].y < enemies[j].y+32 && bullets[i].y+16 > enemies[j].y) { "
362
+ " enemies.splice(j,1); bullets.splice(i,1); score+=10; break; } } } "
363
  "8. FOR TOP-DOWN SHOOTER enemies - spawn every 120 frames, fall straight down: "
364
  " frameCount++; "
365
+ " if (frameCount % 120 === 0) { "
366
+ " enemies.push({x: Math.random()*(canvas.width-32), y:0, w:32, h:32, "
367
+ " speed: Math.min(1 + score/500, 3.5)}); } "
368
+ " speed formula Math.min(1 + score/500, 3.5) means enemies start slow and "
369
+ " get faster as score increases but NEVER exceed speed 3.5. "
370
+ " Each frame: e.y += e.speed; ctx.drawImage(enemyImg,e.x,e.y,32,32); "
371
  " Remove if e.y > canvas.height. If overlaps player: health--; remove enemy. "
 
372
  "9. Draw player: ctx.drawImage(playerImg, player.x, player.y, player.w, player.h). "
373
+ "10. GAME OVER when health<=0: set gameOver=true, draw dark overlay + "
374
+ " 'GAME OVER' text + score on canvas center, draw a green Restart button rect, "
375
+ " add ONE-TIME canvas click listener: canvas.addEventListener('click', restartHandler); "
376
+ " function restartHandler() { canvas.removeEventListener('click', restartHandler); reset(); } "
377
+ "11. reset() resets ALL variables to initial values then calls requestAnimationFrame(gameLoop): "
378
+ " function reset() { "
379
+ " player.x=canvas.width/2-24; player.y=canvas.height/2-24; "
380
+ " bullets.length=0; enemies.length=0; "
381
+ " score=0; health=3; frameCount=0; gameOver=false; "
382
+ " canvas.addEventListener('click', onShoot); "
383
+ " requestAnimationFrame(gameLoop); } "
384
  "12. FOR PLATFORMER: gravity velY+=0.5, jump ArrowUp/W/Space velY=-12 when grounded. "
385
  " Set grounded=false BEFORE platform loop. Set true and velY=0 only on landing. "
386
  " Full-width ground at y=420. "
 
471
  def _build_preview(html_code: str) -> str:
472
  encoded = base64.b64encode(html_code.encode("utf-8")).decode("ascii")
473
  return (
474
+ f'<div style="width:{CANVAS_W}px;height:{CANVAS_H}px;overflow:hidden;border-radius:12px;">'
475
  f'<iframe src="data:text/html;base64,{encoded}" '
476
+ f'style="width:{CANVAS_W}px;height:{CANVAS_H}px;border:none;background:#000;display:block;" '
477
+ f'scrolling="no" '
478
+ 'sandbox="allow-scripts" title="Game Preview"></iframe></div>'
479
  )
480
 
481