Add Komodo enemy class and enhance enemy spawning logic

- Introduce Komodo class with high health and attack mechanics.
- Modify Enemy class to accept type parameter during initialization.
- Update EnemyAI to set speed based on enemy type.
- Implement random spawning of enemies in boss rooms.
- Adjust health bar calculations to use max health.
This commit is contained in:
2026-04-02 23:15:03 +01:00
parent 7c35419026
commit d0466599df
9 changed files with 44 additions and 22 deletions
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+7 -8
View File
@@ -1,28 +1,27 @@
class EnemyAI class EnemyAI
AGGRO_RADIUS = 2000
BASE_SPEED = 130.0
CORNER_OFFSET = 35 # how far from tile center to place corner waypoint CORNER_OFFSET = 35 # how far from tile center to place corner waypoint
ATTACK_COOLDOWN = 0.2 # seconds ATTACK_COOLDOWN = 0.2 # seconds
def initialize(enemy, type) def initialize(enemy, type)
@enemy = enemy @enemy = enemy
@type = type @type = type
@base_speed = case type
when :komodo then 60
when :force then 130
end
@tile_path = [] # raw tile coords from solver @tile_path = [] # raw tile coords from solver
@waypoints = [] # actual world positions to move through @waypoints = [] # actual world positions to move through
@last_player_tile = nil @last_player_tile = nil
@avoiding_obstacle = false @avoiding_obstacle = false
@speed = BASE_SPEED @speed = @base_speed
@time_since_attack = ATTACK_COOLDOWN @time_since_attack = ATTACK_COOLDOWN
end end
def update(player_x, player_y, dt, force = false) def update(player_x, player_y, dt, force = false)
distance = Math.sqrt((player_x - @enemy.x)**2 + (player_y - @enemy.y)**2)
return unless distance < AGGRO_RADIUS
if @enemy.lorentz && distance < 230 if @enemy.lorentz && distance < 230
@speed = BASE_SPEED * 0.3 @speed = @base_speed * 0.3
else else
@speed = BASE_SPEED @speed = @base_speed
end end
player_tile = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round) player_tile = [(player_x - 90) / 120, (player_y - 90) / 120].map(&:round)
+7 -4
View File
@@ -20,12 +20,14 @@ class Enemy
[@i_w, @i_h, @s] [@i_w, @i_h, @s]
end end
def initialize(x, y, health = 100) def initialize(x, y, type, health = 100)
@x = x @x = x
@y = y @y = y
@w = 25 @w = 25
@h = 30 @h = 30
@max_health = health
@health = health @health = health
@type = type
@stun = 0 @stun = 0
@last_lock = :none @last_lock = :none
@lorentz = $bus.get(:lorentz_field?) || false @lorentz = $bus.get(:lorentz_field?) || false
@@ -34,7 +36,7 @@ class Enemy
@lorentz = lorentz @lorentz = lorentz
end end
@ai = EnemyAI.new(self, :chase) @ai = EnemyAI.new(self, @type)
$bus.on(:collides?) do |rect| $bus.on(:collides?) do |rect|
next collides?(rect) ? :enemy : nil next collides?(rect) ? :enemy : nil
@@ -78,7 +80,7 @@ class Enemy
end end
player_pos = $bus.get(:player_position) player_pos = $bus.get(:player_position)
closest_event_horizon = $bus.get(:closest_event_horizon, @x, @y, 200) closest_event_horizon = $bus.get(:closest_event_horizon, @x, @y, 2000)
if closest_event_horizon if closest_event_horizon
@ai.update(*closest_event_horizon, dt, @last_lock != :event_horizon) @ai.update(*closest_event_horizon, dt, @last_lock != :event_horizon)
@last_lock = :event_horizon @last_lock = :event_horizon
@@ -108,7 +110,8 @@ class Enemy
# Health bar # Health bar
health_width = (@w * @health / 100.0) health_width = (@w * @health / @max_health)
Gosu::draw_rect(screen_x - @w / 2, screen_y - @h / 2 - 10, @w, 5, Gosu::Color.new(0xFF555555), Float::INFINITY)
Gosu.draw_rect(screen_x - @w / 2, screen_y - @h / 2 - 10, health_width, 5, Gosu::Color.new(0xFF00FF00), Float::INFINITY) Gosu.draw_rect(screen_x - @w / 2, screen_y - @h / 2 - 10, health_width, 5, Gosu::Color.new(0xFF00FF00), Float::INFINITY)
if $bus.get(:settings, :debug) if $bus.get(:settings, :debug)
+1 -1
View File
@@ -4,7 +4,7 @@ class Force < Enemy
load 'assets/images/force.png', 21, 32, 1.7 load 'assets/images/force.png', 21, 32, 1.7
def initialize(x, y) def initialize(x, y)
super(x, y, 100) super(x, y, :force, 100)
$bus.on(:attack) do |attack_x, attack_y, range, damage| $bus.on(:attack) do |attack_x, attack_y, range, damage|
# Whoa, did'nt know ruby had hypot functions built in! # Whoa, did'nt know ruby had hypot functions built in!
+6 -4
View File
@@ -1,4 +1,5 @@
require_relative 'force' require_relative 'force'
require_relative 'komodo'
class EnemyHandler class EnemyHandler
def initialize def initialize
@@ -16,10 +17,11 @@ class EnemyHandler
end end
def spawn! def spawn!
# For now, just spawn a single enemy at a fixed location boss_rooms = $bus.get(:boss_rooms) || []
start_room_coords = $bus.get(:start_room_coords) if @enemies.count < 4 && rand < (1.0 / (60 * 10))
if @enemies.empty? && start_room_coords boss_room = boss_rooms.sample
@enemies << Force.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30) type = rand < 0.1 ? Komodo : Force
@enemies << (type).new((boss_room[0] * 2 + 4) * 60 + 30, (boss_room[1] * 2 + 4) * 60 + 30)
end end
end end
+17
View File
@@ -0,0 +1,17 @@
require_relative 'base'
class Komodo < Enemy
load 'assets/images/komodo.png', 31, 48, 1.7
def initialize(x, y)
super(x, y, :komodo, 1000)
$bus.on(:attack) do |attack_x, attack_y, range, damage|
if Math.hypot(@x - attack_x, @y - attack_y) <= range
take_damage(damage)
next true
end
false
end
end
end
+2 -2
View File
@@ -2,8 +2,8 @@ So,
#landmines and event horizon should be easy - done #landmines and event horizon should be easy - done
make enemy spawn in the boss rooms with randomness + enemy count #make enemy spawn in the boss rooms with randomness + enemy count - done
make the lizard kind of enemy with very high health + dps but slow #make the lizard kind of enemy with very high health + dps but slow - done
make blade work as planned make blade work as planned
make bow just normal make bow just normal
+4 -3
View File
@@ -26,12 +26,13 @@ class MazeData
end end
end end
$bus.on(:boss_rooms) do
next @boss_rooms
end
return unless $bus.get(:settings, :debug) return unless $bus.get(:settings, :debug)
print_debug print_debug
$bus.on(:boss_room_coords) do
next @boss_rooms.first ? [@boss_rooms.first[0] * 2 + 1, @boss_rooms.first[1] * 2 + 1] : nil
end
end end
def solve(x1, y1, x2, y2) def solve(x1, y1, x2, y2)