How to prevent enemies from taking multiple damage hits in Scratch
💡 Struggling with collision detection and damage systems in your games? 🚀 Get Expert Help
CombatSystem_Dev
Posted on July 22, 2025 • Advanced
⚔️ Enemy taking multiple damage hits - need help!
I’m working on a combat system and having issues with my collision detection. When a projectile hits an enemy, it deals damage multiple times instead of just once.
Here’s my current collision code:
define CheckCollision
set [check index] to (0)
repeat (length of [ProjectileCollision])
if <touching (item (check index) of [ProjectileCollision])?>
switch costume to (Detect)
if <touching (item (check index) of [ProjectileCollision])?>
change [Clone health] by (item (check index) of [ProjectileDamage])
end
switch costume to (Costume)
end
end
The problem is that the enemy takes 2x more damage than it should because the projectile doesn’t disappear fast enough. The collision detection runs multiple times before the projectile is removed.
How can I fix this so each projectile only deals damage once per enemy? 🤔
DamageSystem_Expert
Replied 2 minutes later • ⭐ Best Answer
@CombatSystem_Dev This is a very common issue in game development! The problem is that collision detection runs every frame, but projectiles take time to be removed. Here are several robust solutions:
🛡️ Damage Prevention System Architecture
Here’s how a proper damage system should work:
🛡️ Solution 1: Invincibility Frames (Recommended)
The most professional approach - give enemies temporary invincibility after taking damage:
// In your enemy sprite when flag clicked set [invincible_timer v] to [0] set [max_invincible_time v] to [30] // 30 frames = 0.5 seconds forever // Decrease invincibility timer if <(invincible_timer) > [0]> then change [invincible_timer v] by [-1] // Visual feedback during invincibility if <((invincible_timer) mod [6]) < [3]> then set [ghost v] effect to [50] else set [ghost v] effect to [0] end else set [ghost v] effect to [0] end end // Updated collision detection define CheckCollision set [check_index v] to [1] repeat (length of [ProjectileCollision v]) set [projectile_name v] to (item (check_index) of [ProjectileCollision v]) if <<touching (projectile_name)?> and <(invincible_timer) = [0]>> then // Apply damage set [damage_amount v] to (item (check_index) of [ProjectileDamage v]) change [Clone_health v] by (damage_amount) // Start invincibility period set [invincible_timer v] to (max_invincible_time) // Visual/audio feedback play sound [hit v] // Optional: knockback effect broadcast [enemy_hit v] stop [this script v] // Exit after first hit end change [check_index v] by [1] end
🎯 Solution 2: Projectile-Specific Hit Tracking
Track which projectiles have already hit this enemy:
// In your enemy sprite - initialize when flag clicked delete all of [hit_by_projectiles v] // Updated collision detection with hit tracking define CheckCollision set [check_index v] to [1] repeat (length of [ProjectileCollision v]) set [projectile_name v] to (item (check_index) of [ProjectileCollision v]) if <touching (projectile_name)?> then // Check if we've already been hit by this projectile if <not <[hit_by_projectiles v] contains (projectile_name)?>> then // First time being hit by this projectile add (projectile_name) to [hit_by_projectiles v] // Apply damage set [damage_amount v] to (item (check_index) of [ProjectileDamage v]) change [Clone_health v] by (damage_amount) // Feedback play sound [hit v] broadcast [enemy_hit v] end else // Not touching anymore - remove from hit list if <[hit_by_projectiles v] contains (projectile_name)?> then delete (item # of (projectile_name) in [hit_by_projectiles v]) of [hit_by_projectiles v] end end change [check_index v] by [1] end
⚡ Solution 3: Projectile-Side Management
Let projectiles track what they’ve hit:
// In your projectile sprite when I start as a clone delete all of [enemies_hit v] set [can_hit_multiple v] to [false] // Set to true for piercing projectiles forever // Check collision with enemies if <touching [Enemy v]?> then set [enemy_id v] to [Enemy] // Or get specific enemy ID if <not <[enemies_hit v] contains (enemy_id)?>> then // First time hitting this enemy add (enemy_id) to [enemies_hit v] // Send damage info to enemy broadcast (join [damage_] (my_damage)) // If projectile can't hit multiple enemies, destroy it if <(can_hit_multiple) = [false]> then delete this clone end end end end // In enemy sprite - receive damage when I receive [damage_10 v] // Example for 10 damage if <touching [Projectile v]?> then change [health v] by [-10] play sound [hit v] end
🔄 Solution 4: Cooldown System for Multiple Projectiles
For handling multiple different projectile types:
// Advanced system with per-projectile-type cooldowns when flag clicked // Initialize cooldown lists delete all of [projectile_types v] delete all of [cooldown_timers v] // Add projectile types add [bullet] to [projectile_types v] add [0] to [cooldown_timers v] add [missile] to [projectile_types v] add [0] to [cooldown_timers v] add [laser] to [projectile_types v] add [0] to [cooldown_timers v] forever // Decrease all cooldown timers set [timer_index v] to [1] repeat (length of [cooldown_timers v]) if <(item (timer_index) of [cooldown_timers v]) > [0]> then replace item (timer_index) of [cooldown_timers v] with ((item (timer_index) of [cooldown_timers v]) - [1]) end change [timer_index v] by [1] end end // Check collision with cooldown system define check collision with (projectile_type) set [type_index v] to (item # of (projectile_type) in [projectile_types v]) set [current_cooldown v] to (item (type_index) of [cooldown_timers v]) if <<touching (projectile_type)?> and <(current_cooldown) = [0]>> then // Apply damage based on projectile type if <(projectile_type) = [bullet]> then change [health v] by [-10] replace item (type_index) of [cooldown_timers v] with [20] // 20 frame cooldown else if <(projectile_type) = [missile]> then change [health v] by [-25] replace item (type_index) of [cooldown_timers v] with [60] // 60 frame cooldown end end play sound [hit v] end
💡 Pro Tips for Damage Systems
- Visual Feedback: Use flashing or color effects during invincibility
- Audio Cues: Different sounds for hits vs blocked hits
- Knockback: Push enemies away slightly when hit
- Damage Numbers: Show floating damage text for player feedback
- Performance: Use broadcasts instead of checking every frame when possible
The invincibility frames method (Solution 1) is the most commonly used in professional games because it feels natural to players and prevents all forms of damage stacking! 🎮
CombatSystem_Dev
Replied 15 minutes later
@DamageSystem_Expert This is incredibly helpful! 🤩
I implemented the invincibility frames solution and it works perfectly! The flashing effect during invincibility is a nice touch that gives great visual feedback to the player.
My enemies now take exactly the right amount of damage, and the combat feels much more polished. Thank you so much! 🙏
GameDev_Mentor
Replied 30 minutes later
Excellent solutions! 👏 One additional tip: consider adding different invincibility durations for different damage types.
For example, small bullets might give 0.3 seconds of invincibility, while big explosions give 1 second. This prevents rapid-fire weapons from being overpowered while still allowing meaningful damage from heavy attacks.
Also, some games use “damage reduction” during invincibility instead of complete immunity - worth experimenting with! 🎯
Vibelf_Community
Pinned Message • Moderator
⚔️ Advanced Combat Systems
Fantastic discussion on damage prevention! For those building sophisticated combat systems, our tutors can help you implement:
- 🛡️ Complex damage types and resistances
- ⚡ Advanced collision optimization
- 🎯 Hitbox and hurtbox systems
- 💥 Combo systems and damage scaling
- 🎮 Professional game feel and juice
📚 Related Topics
- Building responsive combat systems
- Advanced collision detection techniques
- Game balance and damage tuning
Ready to create professional-grade combat systems? Get personalized guidance from our game development experts!