the game

feat: add healing

dunkirk.sh e0161e21 db297c00

verified
+102 -31
+8 -1
src/enemy.ts
··· 161 162 // Damage player 163 if (playerObj.damage) { 164 - playerObj.damage(5); 165 } 166 167 // Knockback effect
··· 161 162 // Damage player 163 if (playerObj.damage) { 164 + // Get current difficulty level to scale damage 165 + const difficultyLevel = k.get("game-score-tracker")[0]?.difficultyLevel || 1; 166 + 167 + // Base damage is 5, increases with difficulty 168 + const baseDamage = 5; 169 + const scaledDamage = Math.round(baseDamage + (difficultyLevel - 1) * 2); 170 + 171 + playerObj.damage(scaledDamage); 172 } 173 174 // Knockback effect
+73 -30
src/main.ts
··· 91 let score = 0; 92 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 ]); 107 108 // Difficulty scaling 109 function updateDifficulty() { 110 if (!gameActive) return; 111 - 112 gameTime += 1; // Increment game time by 1 second 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 }), ··· 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, ··· 165 levelText.opacity = v; 166 } 167 }, 168 - k.easings.easeInQuad 169 ); 170 - 171 k.wait(2, () => { 172 if (levelText.exists()) levelText.destroy(); 173 }); ··· 188 // Random position at the edges of the screen 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 ··· 201 // Side spawn (left or right) 202 spawnSide = Math.floor(Math.random() * 2); // 0: left, 1: right 203 } 204 - 205 let x = 0, 206 y = 0; 207 ··· 235 236 // Update score display 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 } 244 245 if (Math.random() < 0.2 * Math.pow(difficultyLevel, 0.75)) spawnEnemy(); 246 }); 247 } 248 249 // Start spawning enemies 250 - k.loop(spawnInterval, spawnEnemy, "spawnEnemy"); 251 252 // Game loop 253 k.onUpdate(() => { ··· 258 // Listen for game over event 259 playerObj.on("death", () => { 260 gameActive = false; 261 - 262 // Get final score from tracker 263 const tracker = k.get("game-score-tracker")[0]; 264 if (tracker) { ··· 266 } else { 267 finalScore = score; 268 } 269 - 270 - // Stop enemy spawning 271 - k.cancel("spawnEnemy"); 272 273 // Wait a moment before showing game over screen 274 k.wait(2, () => {
··· 91 let score = 0; 92 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 + difficultyLevel: difficultyLevel, 102 updateScore(newScore: number) { 103 this.score = newScore; 104 score = newScore; // Update the main score variable 105 + }, 106 + updateDifficulty(newLevel: number) { 107 + this.difficultyLevel = newLevel; 108 + }, 109 + }, 110 ]); 111 112 // Difficulty scaling 113 function updateDifficulty() { 114 if (!gameActive) return; 115 + 116 gameTime += 1; // Increment game time by 1 second 117 + 118 // Check if it's time to increase difficulty based on score 119 // Use a formula that scales with difficulty level 120 const scoreThreshold = 50 * difficultyLevel; 121 + 122 if (score >= scoreThreshold && score % scoreThreshold < 10) { 123 // Only trigger once when crossing the threshold 124 if (!k.get("level-up-text").length) { 125 difficultyLevel += 1; 126 + 127 + // Update difficulty in tracker 128 + const tracker = k.get("game-score-tracker")[0]; 129 + if (tracker) { 130 + tracker.updateDifficulty(difficultyLevel); 131 + } 132 + 133 // Increase max enemies (cap at 15) 134 maxEnemies = Math.min(initialMaxEnemies + difficultyLevel, 15); 135 + 136 // Decrease spawn interval (minimum 0.5 seconds) 137 spawnInterval = Math.max( 138 initialSpawnInterval - difficultyLevel * 0.2, 139 + 0.5, 140 ); 141 + 142 console.log( 143 + `Difficulty increased to level ${difficultyLevel}. Max enemies: ${maxEnemies}, Spawn interval: ${spawnInterval}s`, 144 ); 145 + 146 // Cancel previous spawn loop and start a new one with updated interval 147 + k.loop(spawnInterval, spawnEnemy); 148 + 149 // Visual feedback for difficulty increase 150 const screenCenter = k.vec2(k.width() / 2, k.height() / 2); 151 if (k.addConfetti) { 152 k.addConfetti(screenCenter); 153 } 154 + 155 // Add difficulty level text 156 const levelText = k.add([ 157 k.text(`Difficulty Level ${difficultyLevel}!`, { size: 32 }), ··· 161 k.outline(2, k.rgb(0, 0, 0)), 162 k.z(100), 163 k.opacity(1), 164 + "level-up-text", 165 ]); 166 + 167 // Fade out and destroy the text 168 k.tween( 169 1, ··· 174 levelText.opacity = v; 175 } 176 }, 177 + k.easings.easeInQuad, 178 ); 179 + 180 k.wait(2, () => { 181 if (levelText.exists()) levelText.destroy(); 182 }); ··· 197 // Random position at the edges of the screen 198 // As difficulty increases, add chance to spawn in center 199 let spawnSide; 200 + 201 // Calculate center spawn chance based on difficulty level 202 // 0% at level 1-2, increasing to 30% at level 10+ 203 + const centerSpawnChance = 204 + difficultyLevel <= 2 ? 0 : Math.min((difficultyLevel - 2) * 0.04, 0.3); 205 + 206 // Determine spawn location 207 if (Math.random() < centerSpawnChance) { 208 // Center spawn ··· 211 // Side spawn (left or right) 212 spawnSide = Math.floor(Math.random() * 2); // 0: left, 1: right 213 } 214 + 215 let x = 0, 216 y = 0; 217 ··· 245 246 // Update score display 247 scoreText.text = `Score: ${score}`; 248 + 249 // Update score tracker 250 const tracker = k.get("game-score-tracker")[0]; 251 if (tracker) { 252 tracker.score = score; 253 } 254 255 + // Heal player when killing an enemy 256 + const player = k.get("player")[0]; 257 + if (player && player.heal) { 258 + // Heal amount is 5 health points 259 + const healAmount = 5; 260 + player.heal(healAmount); 261 + 262 + // Show healing effect 263 + const healText = k.add([ 264 + k.text(`+${healAmount} HP`, { size: 16 }), 265 + k.pos(player.pos.x, player.pos.y - 60), 266 + k.anchor("center"), 267 + k.color(0, 255, 0), 268 + k.z(100), 269 + k.opacity(1), 270 + ]); 271 + 272 + // Float upward and fade out 273 + k.tween( 274 + 1, 275 + 0, 276 + 0.8, 277 + (v) => { 278 + if (healText.exists()) { 279 + healText.opacity = v; 280 + healText.pos.y -= 0.5; 281 + } 282 + }, 283 + k.easings.easeOutQuad, 284 + ); 285 + 286 + k.wait(0.8, () => { 287 + if (healText.exists()) healText.destroy(); 288 + }); 289 + } 290 + 291 if (Math.random() < 0.2 * Math.pow(difficultyLevel, 0.75)) spawnEnemy(); 292 }); 293 } 294 295 // Start spawning enemies 296 + k.loop(spawnInterval, spawnEnemy); 297 298 // Game loop 299 k.onUpdate(() => { ··· 304 // Listen for game over event 305 playerObj.on("death", () => { 306 gameActive = false; 307 + 308 // Get final score from tracker 309 const tracker = k.get("game-score-tracker")[0]; 310 if (tracker) { ··· 312 } else { 313 finalScore = score; 314 } 315 316 // Wait a moment before showing game over screen 317 k.wait(2, () => {
+21
src/player.ts
··· 7 health: number; 8 maxHealth: number; 9 damage(amount: number): void; 10 attack(): void; 11 update(): void; 12 } ··· 108 109 // Emit death event for game over handling 110 this.trigger("death"); 111 } 112 }, 113
··· 7 health: number; 8 maxHealth: number; 9 damage(amount: number): void; 10 + heal(amount: number): void; 11 attack(): void; 12 update(): void; 13 } ··· 109 110 // Emit death event for game over handling 111 this.trigger("death"); 112 + } 113 + }, 114 + 115 + // Heal player 116 + heal(this: GameObj, amount: number) { 117 + // Add health but don't exceed max health 118 + health = Math.min(health + amount, maxHealth); 119 + 120 + // Flash green when healed 121 + this.color = k.rgb(0, 255, 0); 122 + 123 + // Reset color after a short time 124 + k.wait(0.1, () => { 125 + this.color = k.rgb(); 126 + }); 127 + 128 + // Update health bar 129 + if (healthBar) { 130 + const healthPercent = Math.max(0, health / maxHealth); 131 + healthBar.width = 60 * healthPercent; 132 } 133 }, 134