the game
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: tweak spawning and ult

+178 -70
+118 -70
src/main.ts
··· 91 91 let score = 0; 92 92 93 93 const scoreText = k.add([k.text(`Score: ${score}`), k.pos(16, 16), "score"]); 94 + 95 + // Add a hidden score tracker that can be accessed by other components 96 + const scoreTracker = k.add([ 97 + k.pos(0, 0), 98 + "game-score-tracker", 99 + { 100 + score: score, 101 + updateScore(newScore: number) { 102 + this.score = newScore; 103 + score = newScore; // Update the main score variable 104 + } 105 + } 106 + ]); 94 107 95 108 // Difficulty scaling 96 109 function updateDifficulty() { 97 110 if (!gameActive) return; 98 - 111 + 99 112 gameTime += 1; // Increment game time by 1 second 100 - 101 - // Every 30 seconds, increase difficulty 102 - if (score != 0 && score % (50 + 5 * difficultyLevel) === 0) { 103 - difficultyLevel += 1; 104 - 105 - // Increase max enemies (cap at 15) 106 - maxEnemies = Math.min(initialMaxEnemies + difficultyLevel * 3, 15); 107 - 108 - // Decrease spawn interval (minimum 0.5 seconds) 109 - spawnInterval = Math.max( 110 - initialSpawnInterval - difficultyLevel * 0.3, 111 - 0.5, 112 - ); 113 - 114 - console.log( 115 - `Difficulty increased to level ${difficultyLevel}. Max enemies: ${maxEnemies}, Spawn interval: ${spawnInterval}s`, 116 - ); 117 - 118 - // Cancel previous spawn loop and start a new one with updated interval 119 - k.cancel(); 120 - k.loop(spawnInterval, spawnEnemy); 121 - 122 - // Visual feedback for difficulty increase 123 - const screenCenter = k.vec2(k.width() / 2, k.height() / 2); 124 - if (k.addConfetti) { 125 - k.addConfetti(screenCenter); 113 + 114 + // Check if it's time to increase difficulty based on score 115 + // Use a formula that scales with difficulty level 116 + const scoreThreshold = 50 * difficultyLevel; 117 + 118 + if (score >= scoreThreshold && score % scoreThreshold < 10) { 119 + // Only trigger once when crossing the threshold 120 + if (!k.get("level-up-text").length) { 121 + difficultyLevel += 1; 122 + 123 + // Increase max enemies (cap at 15) 124 + maxEnemies = Math.min(initialMaxEnemies + difficultyLevel, 15); 125 + 126 + // Decrease spawn interval (minimum 0.5 seconds) 127 + spawnInterval = Math.max( 128 + initialSpawnInterval - difficultyLevel * 0.2, 129 + 0.5 130 + ); 131 + 132 + console.log( 133 + `Difficulty increased to level ${difficultyLevel}. Max enemies: ${maxEnemies}, Spawn interval: ${spawnInterval}s` 134 + ); 135 + 136 + // Cancel previous spawn loop and start a new one with updated interval 137 + k.cancel("spawnEnemy"); 138 + k.loop(spawnInterval, spawnEnemy, "spawnEnemy"); 139 + 140 + // Visual feedback for difficulty increase 141 + const screenCenter = k.vec2(k.width() / 2, k.height() / 2); 142 + if (k.addConfetti) { 143 + k.addConfetti(screenCenter); 144 + } 145 + 146 + // Add difficulty level text 147 + const levelText = k.add([ 148 + k.text(`Difficulty Level ${difficultyLevel}!`, { size: 32 }), 149 + k.pos(screenCenter), 150 + k.anchor("center"), 151 + k.color(255, 255, 255), 152 + k.outline(2, k.rgb(0, 0, 0)), 153 + k.z(100), 154 + k.opacity(1), 155 + "level-up-text" 156 + ]); 157 + 158 + // Fade out and destroy the text 159 + k.tween( 160 + 1, 161 + 0, 162 + 2, 163 + (v) => { 164 + if (levelText.exists()) { 165 + levelText.opacity = v; 166 + } 167 + }, 168 + k.easings.easeInQuad 169 + ); 170 + 171 + k.wait(2, () => { 172 + if (levelText.exists()) levelText.destroy(); 173 + }); 126 174 } 127 - 128 - // Add difficulty level text 129 - const levelText = k.add([ 130 - k.text(`Difficulty Level ${difficultyLevel}!`, { size: 32 }), 131 - k.pos(screenCenter), 132 - k.anchor("center"), 133 - k.color(255, 255, 255), 134 - k.outline(2, k.rgb(0, 0, 0)), 135 - k.z(100), 136 - k.opacity(1), 137 - ]); 138 - 139 - // Fade out and destroy the text 140 - k.tween( 141 - 1, 142 - 0, 143 - 2, 144 - (v) => { 145 - levelText.opacity = v; 146 - }, 147 - k.easings.easeInQuad, 148 - ); 149 - 150 - k.wait(2, () => { 151 - levelText.destroy(); 152 - }); 153 175 } 154 176 } 155 177 ··· 164 186 if (enemies.length >= maxEnemies) return; 165 187 166 188 // Random position at the edges of the screen 167 - const side = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left 189 + // As difficulty increases, add chance to spawn in center 190 + let spawnSide; 191 + 192 + // Calculate center spawn chance based on difficulty level 193 + // 0% at level 1-2, increasing to 30% at level 10+ 194 + const centerSpawnChance = difficultyLevel <= 2 ? 0 : Math.min((difficultyLevel - 2) * 0.04, 0.3); 195 + 196 + // Determine spawn location 197 + if (Math.random() < centerSpawnChance) { 198 + // Center spawn 199 + spawnSide = 2; // Center 200 + } else { 201 + // Side spawn (left or right) 202 + spawnSide = Math.floor(Math.random() * 2); // 0: left, 1: right 203 + } 204 + 168 205 let x = 0, 169 206 y = 0; 170 207 171 - switch (side) { 172 - case 0: // top 173 - x = Math.random() * (k.width() - 40) + 20; // Avoid spawning behind side walls 174 - y = 10; // Just inside the top wall 208 + switch (spawnSide) { 209 + case 0: // left 210 + x = 10; // Just inside the left wall 211 + y = Math.random() * (k.height() - 48 - 20) + 20; // Avoid spawning behind top wall or inside ground 175 212 break; 176 213 case 1: // right 177 214 x = k.width() - 10; // Just inside the right wall 178 215 y = Math.random() * (k.height() - 48 - 20) + 20; // Avoid spawning behind top wall or inside ground 179 216 break; 180 - case 2: // bottom 181 - x = Math.random() * (k.width() - 40) + 20; // Avoid spawning behind side walls 182 - y = k.height() - 58; // Just above the ground (ground is at height-48 with height 48) 183 - break; 184 - case 3: // left 185 - x = 10; // Just inside the left wall 186 - y = Math.random() * (k.height() - 48 - 20) + 20; // Avoid spawning behind top wall or inside ground 217 + case 2: // center (mid-air) 218 + // Random position in the middle area of the screen 219 + x = k.width() * (0.3 + Math.random() * 0.4); // 30-70% of screen width 220 + y = k.height() * (0.2 + Math.random() * 0.5); // 20-70% of screen height 187 221 break; 188 222 } 189 223 ··· 196 230 enemies = enemies.filter((e) => e !== newEnemy); 197 231 198 232 // Increase score when enemy is destroyed 199 - score += Math.round(10 + Math.pow(difficultyLevel, 0.75)); 233 + const pointsEarned = Math.round(10 + Math.pow(difficultyLevel, 0.75)); 234 + score += pointsEarned; 200 235 201 236 // Update score display 202 237 scoreText.text = `Score: ${score}`; 238 + 239 + // Update score tracker 240 + const tracker = k.get("game-score-tracker")[0]; 241 + if (tracker) { 242 + tracker.score = score; 243 + } 203 244 204 - if (Math.random() < 0.5) spawnEnemy(); 245 + if (Math.random() < 0.2 * Math.pow(difficultyLevel, 0.75)) spawnEnemy(); 205 246 }); 206 247 } 207 248 208 249 // Start spawning enemies 209 - k.loop(spawnInterval, spawnEnemy); 250 + k.loop(spawnInterval, spawnEnemy, "spawnEnemy"); 210 251 211 252 // Game loop 212 253 k.onUpdate(() => { ··· 217 258 // Listen for game over event 218 259 playerObj.on("death", () => { 219 260 gameActive = false; 220 - finalScore = score; 221 - 261 + 262 + // Get final score from tracker 263 + const tracker = k.get("game-score-tracker")[0]; 264 + if (tracker) { 265 + finalScore = tracker.score; 266 + } else { 267 + finalScore = score; 268 + } 269 + 222 270 // Stop enemy spawning 223 271 k.cancel("spawnEnemy"); 224 272
+60
src/player.ts
··· 307 307 308 308 // Damage all enemies with high damage 309 309 const enemies = k.get("enemy"); 310 + let enemiesKilled = 0; 311 + 310 312 enemies.forEach((enemy) => { 311 313 const dist = k.vec2(enemy.pos).dist(this.pos); 312 314 if (dist < explosionRadius) { 315 + // Count enemies killed 316 + enemiesKilled++; 317 + 313 318 // Instant kill any enemy within the explosion radius 314 319 (enemy as any).damage(1000); // Extremely high damage to ensure death 315 320 ··· 321 326 }); 322 327 } 323 328 }); 329 + 330 + // Calculate bonus score based on health and enemies killed 331 + // Higher health = higher score multiplier 332 + const healthPercent = health / maxHealth; 333 + const scoreBonus = Math.round(500 * healthPercent * (1 + enemiesKilled * 0.5)); 334 + 335 + // Add score bonus 336 + if (scoreBonus > 0) { 337 + // Get score object 338 + const scoreObj = k.get("score")[0]; 339 + if (scoreObj) { 340 + // Extract current score 341 + const currentScore = parseInt(scoreObj.text.split(": ")[1]); 342 + // Add bonus 343 + const newScore = currentScore + scoreBonus; 344 + // Update score display 345 + scoreObj.text = `Score: ${newScore}`; 346 + 347 + // Update the actual score variable in the game scene 348 + // This is needed for the game over screen to show the correct score 349 + const gameScores = k.get("game-score-tracker"); 350 + if (gameScores.length > 0) { 351 + gameScores[0].updateScore(newScore); 352 + } 353 + 354 + // Show bonus text 355 + const bonusText = k.add([ 356 + k.text(`+${scoreBonus} ULTIMATE BONUS!`, { size: 32 }), 357 + k.pos(k.width() / 2, k.height() / 2 - 100), 358 + k.anchor("center"), 359 + k.color(255, 255, 0), 360 + k.outline(2, k.rgb(0, 0, 0)), 361 + k.z(100), 362 + k.opacity(1), 363 + ]); 364 + 365 + // Fade out and destroy the text 366 + k.tween( 367 + 1, 368 + 0, 369 + 1.5, 370 + (v) => { 371 + if (bonusText.exists()) { 372 + bonusText.opacity = v; 373 + bonusText.pos.y -= 0.5; // Float upward 374 + } 375 + }, 376 + k.easings.easeInQuad, 377 + ); 378 + 379 + k.wait(1.5, () => { 380 + if (bonusText.exists()) bonusText.destroy(); 381 + }); 382 + } 383 + } 324 384 325 385 // Kill the player (sacrifice) 326 386 this.damage(health); // Use current health to ensure death