Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -157,14 +157,38 @@ THEME_EXAMPLES = {
|
|
| 157 |
|
| 158 |
def generate_image_prompts(theme: str, game_type: str) -> dict:
|
| 159 |
client = get_groq_client()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
seeds = {
|
| 161 |
-
"sprite_player.png":
|
| 162 |
-
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
}
|
| 165 |
if game_type == "Platformer":
|
| 166 |
-
seeds["sprite_platform.png"] =
|
| 167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
prompts = {}
|
| 169 |
for sprite_name, seed in seeds.items():
|
| 170 |
try:
|
|
@@ -256,56 +280,43 @@ def _inject_sprites(html_code: str, sprite_map: dict) -> str:
|
|
| 256 |
CODE_SYSTEM = (
|
| 257 |
"You are an expert HTML5 game developer. "
|
| 258 |
"Write a complete, working, single-file HTML5 game using canvas and vanilla JavaScript. "
|
| 259 |
-
"CRITICAL RULES
|
| 260 |
-
"1.
|
| 261 |
" const playerImg = new Image(); playerImg.src = 'sprite_player.png'; "
|
| 262 |
" const bgImg = new Image(); bgImg.src = 'sprite_background.png'; "
|
| 263 |
" const enemyImg = new Image(); enemyImg.src = 'sprite_enemy.png'; "
|
| 264 |
" const keys = new Set(); "
|
| 265 |
-
"2.
|
| 266 |
" function loadImg(img) { return new Promise(r => { img.onload = r; }); } "
|
| 267 |
" Promise.all([loadImg(playerImg), loadImg(bgImg), loadImg(enemyImg)]).then(startGame); "
|
| 268 |
-
"3.
|
| 269 |
-
" function startGame() { "
|
| 270 |
" window.addEventListener('keydown', e => keys.add(e.key)); "
|
| 271 |
" window.addEventListener('keyup', e => keys.delete(e.key)); "
|
| 272 |
" canvas.addEventListener('click', onShoot); "
|
| 273 |
" requestAnimationFrame(gameLoop); } "
|
| 274 |
-
"4. Define gameLoop() and ALL
|
| 275 |
-
"5.
|
| 276 |
-
"
|
| 277 |
-
"
|
| 278 |
-
"
|
| 279 |
-
" if (keys.has('
|
| 280 |
-
"
|
| 281 |
-
"
|
| 282 |
-
"
|
| 283 |
-
"
|
| 284 |
-
"
|
| 285 |
-
"
|
| 286 |
-
"
|
| 287 |
-
"
|
| 288 |
-
"
|
| 289 |
-
"
|
| 290 |
-
"
|
| 291 |
-
" STEP D - for shooting, add click listener on canvas inside startGame(): "
|
| 292 |
-
" canvas.addEventListener('click', function(e){ "
|
| 293 |
-
" const r=canvas.getBoundingClientRect(); "
|
| 294 |
-
" const mx=e.clientX-r.left; const my=e.clientY-r.top; "
|
| 295 |
-
" const dx=mx-(player.x+player.w/2); const dy=my-(player.y+player.h/2); "
|
| 296 |
-
" const d=Math.sqrt(dx*dx+dy*dy); "
|
| 297 |
-
" if(d>0) bullets.push({x:player.x+player.w/2, y:player.y+player.h/2, vx:dx/d*10, vy:dy/d*10, w:6, h:6}); }); "
|
| 298 |
-
" FOR PLATFORMER: use gravity velY += 0.5, grounded checks, jump with ArrowUp/W/Space (velY=-12). "
|
| 299 |
-
" Set grounded=false BEFORE platform loop. Set grounded=true and velY=0 only on landing. "
|
| 300 |
" Always include full-width ground platform at y=420. "
|
| 301 |
-
"
|
| 302 |
-
"
|
| 303 |
-
"7. Draw player/enemies with ctx.drawImage(playerImg, x, y, w, h). "
|
| 304 |
-
"8. Always keep player inside canvas boundaries. "
|
| 305 |
"Output ONLY the raw HTML - no markdown fences, no explanation, nothing else."
|
| 306 |
)
|
| 307 |
|
| 308 |
-
|
| 309 |
def generate_game_code(game_type: str, theme: str, temperature: float, max_new_tokens: int):
|
| 310 |
if not theme.strip():
|
| 311 |
return "", "", "Please enter a theme first.", _placeholder_html("Enter a theme and generate a game.")
|
|
|
|
| 157 |
|
| 158 |
def generate_image_prompts(theme: str, game_type: str) -> dict:
|
| 159 |
client = get_groq_client()
|
| 160 |
+
if game_type == "Top-Down Shooter":
|
| 161 |
+
perspective = "top-down aerial view"
|
| 162 |
+
char_style = "top-down aerial view sprite, character seen from directly above"
|
| 163 |
+
else:
|
| 164 |
+
perspective = "2D side-view flat"
|
| 165 |
+
char_style = "2D side-view flat sprite, full body visible from the side"
|
| 166 |
+
|
| 167 |
seeds = {
|
| 168 |
+
"sprite_player.png": (
|
| 169 |
+
f"pixel-art game player character, {char_style}, {theme} theme, "
|
| 170 |
+
f"vibrant colors, character ONLY with NO background, transparent background, "
|
| 171 |
+
f"clear silhouette, 64x64 pixel style"
|
| 172 |
+
),
|
| 173 |
+
"sprite_background.png": (
|
| 174 |
+
f"2D game background scene, {perspective}, {theme} theme, "
|
| 175 |
+
f"wide landscape, atmospheric, game art style, 800x450, no characters"
|
| 176 |
+
),
|
| 177 |
+
"sprite_enemy.png": (
|
| 178 |
+
f"pixel-art enemy character, {char_style}, {theme} theme, "
|
| 179 |
+
f"menacing, character ONLY with NO background, transparent background, "
|
| 180 |
+
f"clear silhouette, 64x64 pixel style"
|
| 181 |
+
),
|
| 182 |
}
|
| 183 |
if game_type == "Platformer":
|
| 184 |
+
seeds["sprite_platform.png"] = (
|
| 185 |
+
f"pixel-art solid platform tile, 2D side-view, {theme} theme, "
|
| 186 |
+
f"rectangular textured surface, NO background, transparent background, 128x24"
|
| 187 |
+
)
|
| 188 |
+
seeds["sprite_goal.png"] = (
|
| 189 |
+
f"pixel-art goal treasure chest or star, 2D side-view, {theme} theme, "
|
| 190 |
+
f"glowing, clearly visible, NO background, transparent background, 40x40"
|
| 191 |
+
)
|
| 192 |
prompts = {}
|
| 193 |
for sprite_name, seed in seeds.items():
|
| 194 |
try:
|
|
|
|
| 280 |
CODE_SYSTEM = (
|
| 281 |
"You are an expert HTML5 game developer. "
|
| 282 |
"Write a complete, working, single-file HTML5 game using canvas and vanilla JavaScript. "
|
| 283 |
+
"CRITICAL RULES: "
|
| 284 |
+
"1. Declare sprites at the very top of the script BEFORE anything else: "
|
| 285 |
" const playerImg = new Image(); playerImg.src = 'sprite_player.png'; "
|
| 286 |
" const bgImg = new Image(); bgImg.src = 'sprite_background.png'; "
|
| 287 |
" const enemyImg = new Image(); enemyImg.src = 'sprite_enemy.png'; "
|
| 288 |
" const keys = new Set(); "
|
| 289 |
+
"2. Use Promise.all to wait for ALL images before starting: "
|
| 290 |
" function loadImg(img) { return new Promise(r => { img.onload = r; }); } "
|
| 291 |
" Promise.all([loadImg(playerImg), loadImg(bgImg), loadImg(enemyImg)]).then(startGame); "
|
| 292 |
+
"3. function startGame() { "
|
|
|
|
| 293 |
" window.addEventListener('keydown', e => keys.add(e.key)); "
|
| 294 |
" window.addEventListener('keyup', e => keys.delete(e.key)); "
|
| 295 |
" canvas.addEventListener('click', onShoot); "
|
| 296 |
" requestAnimationFrame(gameLoop); } "
|
| 297 |
+
"4. Define gameLoop() and ALL functions at TOP LEVEL not inside startGame or .then(). "
|
| 298 |
+
"5. FOR TOP-DOWN SHOOTER movement - player moves in ALL 4 directions, NO gravity: "
|
| 299 |
+
" if (keys.has('w') || keys.has('W') || keys.has('ArrowUp')) player.y -= player.speed; "
|
| 300 |
+
" if (keys.has('s') || keys.has('S') || keys.has('ArrowDown')) player.y += player.speed; "
|
| 301 |
+
" if (keys.has('a') || keys.has('A') || keys.has('ArrowLeft')) player.x -= player.speed; "
|
| 302 |
+
" if (keys.has('d') || keys.has('D') || keys.has('ArrowRight')) player.x += player.speed; "
|
| 303 |
+
" Clamp player inside canvas after movement. "
|
| 304 |
+
"6. FOR TOP-DOWN SHOOTER bullets - shoot straight UPWARD on click, constant speed: "
|
| 305 |
+
" function onShoot(e) { bullets.push({x: player.x + player.w/2 - 4, y: player.y, w: 8, h: 16, vy: -10}); } "
|
| 306 |
+
" Each frame move every bullet: b.y += b.vy; "
|
| 307 |
+
" Remove bullets when b.y + b.h < 0. "
|
| 308 |
+
" Draw bullets with ctx.fillStyle and ctx.fillRect. "
|
| 309 |
+
"7. FOR TOP-DOWN SHOOTER enemies - draw with ctx.drawImage(enemyImg, e.x, e.y, e.w, e.h). "
|
| 310 |
+
" Enemies fall straight down: e.y += e.speed each frame. "
|
| 311 |
+
" Remove enemy if e.y > canvas.height. "
|
| 312 |
+
"8. FOR PLATFORMER: gravity velY+=0.5, grounded checks, jump ArrowUp/W/Space velY=-12. "
|
| 313 |
+
" Set grounded=false BEFORE platform loop, set grounded=true and velY=0 only on landing. "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
" Always include full-width ground platform at y=420. "
|
| 315 |
+
"9. Draw bgImg FIRST each frame: ctx.drawImage(bgImg, 0, 0, canvas.width, canvas.height). "
|
| 316 |
+
"10. Draw player: ctx.drawImage(playerImg, player.x, player.y, player.w, player.h). "
|
|
|
|
|
|
|
| 317 |
"Output ONLY the raw HTML - no markdown fences, no explanation, nothing else."
|
| 318 |
)
|
| 319 |
|
|
|
|
| 320 |
def generate_game_code(game_type: str, theme: str, temperature: float, max_new_tokens: int):
|
| 321 |
if not theme.strip():
|
| 322 |
return "", "", "Please enter a theme first.", _placeholder_html("Enter a theme and generate a game.")
|