your personal website on atproto - mirror blento.app

improve dino game card

Florian 0faab9c0 c6a7b011

+39 -13
+39 -13
src/lib/cards/GameCards/DinoGameCard/DinoGameCard.svelte
··· 58 59 let gameSpeed = 5; 60 let frameCount = 0; 61 62 // Sprite positions in tilemap (row, column - 1-indexed based on cells.txt) 63 const SPRITE_POSITIONS: Record<string, { row: number; col: number }> = { ··· 151 frame: 0 152 }; 153 obstacles = []; 154 - gameSpeed = 3.5 * (scale / 2.5); 155 score = 0; 156 frameCount = 0; 157 initGroundTiles(); 158 } 159 ··· 293 ctx.drawImage(sprites[spriteKey], x, y, width, height); 294 } 295 296 - function gameLoop() { 297 if (!ctx || !canvas || !spritesLoaded) { 298 animationId = requestAnimationFrame(gameLoop); 299 return; 300 } 301 302 const canvasWidth = canvas.width; 303 const canvasHeight = canvas.height; 304 const groundY = canvasHeight - groundHeight; ··· 312 } 313 314 if (gameState === 'playing') { 315 - frameCount++; 316 317 // Update ground tiles - seamless scrolling 318 for (const tile of groundTiles) { 319 - tile.x -= gameSpeed; 320 } 321 322 // Find the rightmost tile and reposition tiles that went off-screen ··· 329 330 // Update player physics 331 if (player.isJumping) { 332 - player.velocityY += gravity; 333 - player.y += player.velocityY; 334 335 if (player.y >= groundY - player.height) { 336 player.y = groundY - player.height; ··· 342 } 343 344 // Animate player (3 walk frames) 345 - if (frameCount % 8 === 0) { 346 player.frame = (player.frame + 1) % 3; 347 } 348 349 // Animate flying obstacles 350 for (const obs of obstacles) { 351 - if (obs.type === 'air' && frameCount % 12 === 0) { 352 obs.frame = obs.frame === 1 ? 2 : 1; 353 obs.sprite = `bat${obs.frame}`; 354 } 355 } 356 357 // Spawn obstacles 358 const baseSpawnRate = 120; 359 const spawnRate = Math.max(60, baseSpawnRate - Math.floor(score / 100) * 5); 360 - if (frameCount % spawnRate === 0 || (obstacles.length === 0 && frameCount > 60)) { 361 spawnObstacle(canvasWidth, groundY); 362 } 363 364 // Update obstacles 365 obstacles = obstacles.filter((obs) => { 366 - obs.x -= gameSpeed; 367 return obs.x > -obs.width; 368 }); 369 ··· 407 // Update score 408 score = Math.floor(frameCount / 5); 409 410 - // Increase speed over time (slower progression) 411 - if (frameCount % 700 === 0) { 412 - gameSpeed = Math.min(gameSpeed + 0.2 * (scale / 2.5), 8 * (scale / 2.5)); 413 } 414 } 415
··· 58 59 let gameSpeed = 5; 60 let frameCount = 0; 61 + let lastFrameTimestamp = 0; 62 + let lastSpawnFrame = 0; 63 + let lastWalkFrame = 0; 64 + let lastBatFrame = 0; 65 + let lastSpeedScore = 0; 66 + const FRAME_TIME_MS = 1000 / 60; 67 + const MAX_SPEED_BASE = 10.5; 68 69 // Sprite positions in tilemap (row, column - 1-indexed based on cells.txt) 70 const SPRITE_POSITIONS: Record<string, { row: number; col: number }> = { ··· 158 frame: 0 159 }; 160 obstacles = []; 161 + gameSpeed = 4.2 * (scale / 2.5); 162 score = 0; 163 frameCount = 0; 164 + lastSpawnFrame = 0; 165 + lastWalkFrame = 0; 166 + lastBatFrame = 0; 167 + lastSpeedScore = 0; 168 initGroundTiles(); 169 } 170 ··· 304 ctx.drawImage(sprites[spriteKey], x, y, width, height); 305 } 306 307 + function gameLoop(timestamp = 0) { 308 if (!ctx || !canvas || !spritesLoaded) { 309 animationId = requestAnimationFrame(gameLoop); 310 return; 311 } 312 313 + if (!lastFrameTimestamp) { 314 + lastFrameTimestamp = timestamp; 315 + } 316 + 317 + const deltaMs = timestamp - lastFrameTimestamp; 318 + lastFrameTimestamp = timestamp; 319 + const deltaFrames = Math.min(deltaMs / FRAME_TIME_MS, 3); 320 + 321 const canvasWidth = canvas.width; 322 const canvasHeight = canvas.height; 323 const groundY = canvasHeight - groundHeight; ··· 331 } 332 333 if (gameState === 'playing') { 334 + frameCount += deltaFrames; 335 336 // Update ground tiles - seamless scrolling 337 for (const tile of groundTiles) { 338 + tile.x -= gameSpeed * deltaFrames; 339 } 340 341 // Find the rightmost tile and reposition tiles that went off-screen ··· 348 349 // Update player physics 350 if (player.isJumping) { 351 + player.velocityY += gravity * deltaFrames; 352 + player.y += player.velocityY * deltaFrames; 353 354 if (player.y >= groundY - player.height) { 355 player.y = groundY - player.height; ··· 361 } 362 363 // Animate player (3 walk frames) 364 + if (frameCount - lastWalkFrame >= 8) { 365 player.frame = (player.frame + 1) % 3; 366 + lastWalkFrame = frameCount; 367 } 368 369 // Animate flying obstacles 370 for (const obs of obstacles) { 371 + if (obs.type === 'air' && frameCount - lastBatFrame >= 12) { 372 obs.frame = obs.frame === 1 ? 2 : 1; 373 obs.sprite = `bat${obs.frame}`; 374 + lastBatFrame = frameCount; 375 } 376 } 377 378 // Spawn obstacles 379 const baseSpawnRate = 120; 380 const spawnRate = Math.max(60, baseSpawnRate - Math.floor(score / 100) * 5); 381 + if ( 382 + frameCount - lastSpawnFrame >= spawnRate || 383 + (obstacles.length === 0 && frameCount > 60) 384 + ) { 385 spawnObstacle(canvasWidth, groundY); 386 + lastSpawnFrame = frameCount; 387 } 388 389 // Update obstacles 390 obstacles = obstacles.filter((obs) => { 391 + obs.x -= gameSpeed * deltaFrames; 392 return obs.x > -obs.width; 393 }); 394 ··· 432 // Update score 433 score = Math.floor(frameCount / 5); 434 435 + // Increase speed every 100 points up to a cap 436 + if (score >= lastSpeedScore + 100) { 437 + gameSpeed = Math.min(gameSpeed + 0.25 * (scale / 2.5), MAX_SPEED_BASE * (scale / 2.5)); 438 + lastSpeedScore = score - (score % 100); 439 } 440 } 441