feat: update level system

dunkirk.sh c09b4d3e 20559584

verified
Changed files
+56 -37
src
+13 -11
src/enemy.ts
···
k.color(255, 0, 0),
k.z(1),
]);
-
+
// Handle collisions with sword
this.onCollide("sword", (sword) => {
if (sword.isAttacking && !isHit) {
···
this.flipX = normalizedDir.x < 0;
}
}
-
+
// Check for collision with player and apply damage if in contact
// Only apply damage if cooldown has passed
if (k.time() - lastDamageTime > DAMAGE_COOLDOWN) {
const playerObj = k.get("player")[0];
if (playerObj && this.isColliding(playerObj)) {
lastDamageTime = k.time();
-
+
// Damage player
if (playerObj.damage) {
playerObj.damage(5);
}
-
+
// Knockback effect
const knockback = 200;
-
const knockbackDir = k.vec2(
-
playerObj.pos.x - this.pos.x,
-
playerObj.pos.y - this.pos.y
-
).unit();
-
-
playerObj.move(knockbackDir.x * knockback, knockbackDir.y * knockback);
+
const knockbackDir = k
+
.vec2(playerObj.pos.x - this.pos.x, playerObj.pos.y - this.pos.y)
+
.unit();
+
+
playerObj.move(
+
knockbackDir.x * knockback,
+
knockbackDir.y * knockback,
+
);
}
}
···
enemy(k, target),
"enemy", // Add tag for collision detection
]);
-
+
return newEnemy;
}
+31 -20
src/main.ts
···
let spawnInterval = initialSpawnInterval;
let gameTime = 0; // Track game time in seconds
let difficultyLevel = 1;
-
let spawnLoopId: any = null;
+
let score = 0;
+
+
const scoreText = k.add([k.text(`Score: ${score}`), k.pos(16, 16)]);
// Difficulty scaling
function updateDifficulty() {
gameTime += 1; // Increment game time by 1 second
-
+
// Every 30 seconds, increase difficulty
-
if (gameTime % 30 === 0) {
+
if (score != 0 && score % (50 * difficultyLevel) === 0) {
difficultyLevel += 1;
-
+
// Increase max enemies (cap at 15)
-
maxEnemies = Math.min(initialMaxEnemies + difficultyLevel, 15);
-
+
maxEnemies = Math.min(initialMaxEnemies + difficultyLevel * 3, 15);
+
// Decrease spawn interval (minimum 0.5 seconds)
-
spawnInterval = Math.max(initialSpawnInterval - (difficultyLevel * 0.3), 0.5);
-
-
console.log(`Difficulty increased to level ${difficultyLevel}. Max enemies: ${maxEnemies}, Spawn interval: ${spawnInterval}s`);
-
+
spawnInterval = Math.max(initialSpawnInterval - difficultyLevel * 0.3, 0.5);
+
+
console.log(
+
`Difficulty increased to level ${difficultyLevel}. Max enemies: ${maxEnemies}, Spawn interval: ${spawnInterval}s`,
+
);
+
// Cancel previous spawn loop and start a new one with updated interval
-
if (spawnLoopId !== null) {
-
k.cancel(spawnLoopId);
-
}
-
spawnLoopId = k.loop(spawnInterval, spawnEnemy);
-
+
k.cancel();
+
k.loop(spawnInterval, spawnEnemy);
+
// Visual feedback for difficulty increase
const screenCenter = k.vec2(k.width() / 2, k.height() / 2);
if (k.addConfetti) {
k.addConfetti(screenCenter);
}
-
+
// Add difficulty level text
const levelText = k.add([
k.text(`Difficulty Level ${difficultyLevel}!`, { size: 32 }),
···
k.z(100),
k.opacity(1),
]);
-
+
// Fade out and destroy the text
k.tween(
1,
···
},
k.easings.easeInQuad,
);
-
+
k.wait(2, () => {
levelText.destroy();
});
···
// Random position at the edges of the screen
const side = Math.floor(Math.random() * 4); // 0: top, 1: right, 2: bottom, 3: left
-
let x, y;
+
let x = 0,
+
y = 0;
switch (side) {
case 0: // top
···
// Remove from array when destroyed
newEnemy.on("destroy", () => {
enemies = enemies.filter((e) => e !== newEnemy);
+
+
// Increase score when enemy is destroyed
+
score += 10 + Math.pow(difficultyLevel, 0.75);
+
+
// Update score display
+
scoreText.text = `Score: ${score}`;
+
+
if (Math.random() < 0.5) spawnEnemy();
});
}
// Start spawning enemies
-
spawnLoopId = k.loop(spawnInterval, spawnEnemy);
+
k.loop(spawnInterval, spawnEnemy);
// Game loop
k.onUpdate(() => {
+12 -6
src/player.ts
···
enemies.forEach((enemy) => {
const dist = k.vec2(enemy.pos).dist(clampedPos);
if (dist < explosionRadius) {
-
// Calculate damage based on distance from center
-
// At center (dist = 0): 70 damage (70% of enemy health)
-
// At edge (dist = explosionRadius): 20 damage (20% of enemy health)
-
const damagePercent = 0.7 - (0.5 * dist) / explosionRadius;
-
const damage = Math.floor(100 * damagePercent); // 100 is enemy max health
+
// Normalize distance to 0-1 range
+
const normalizedDist = dist / explosionRadius;
+
+
const maxDamage = 80;
+
const minDamage = 10;
+
const logFalloff = Math.log(10 * normalizedDist) / Math.log(20);
+
const damagePercent = 1 - logFalloff;
+
const damage = Math.max(
+
Math.floor(maxDamage * damagePercent),
+
minDamage,
+
);
console.log(
-
`Direct damage to enemy: ${damage}, distance: ${dist}, percent: ${damagePercent}`,
+
`Explosion damage to enemy: ${damage}, distance: ${dist}, normalized: ${normalizedDist}, falloff: ${logFalloff}`,
);
// Add type assertion to tell TypeScript that enemy has a damage method
(enemy as any).damage(damage);