Enhance enemy AI and introduce Force class: update speed dynamics based on Lorentz field effects, refactor enemy spawning to utilize Force, and add sprite loading for Force.
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 811 B |
+20
-4
@@ -1,6 +1,6 @@
|
|||||||
class EnemyAI
|
class EnemyAI
|
||||||
AGGRO_RADIUS = 2000
|
AGGRO_RADIUS = 2000
|
||||||
SPEED = 120.0
|
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
|
||||||
|
|
||||||
def initialize(enemy, type)
|
def initialize(enemy, type)
|
||||||
@@ -10,12 +10,28 @@ class EnemyAI
|
|||||||
@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
|
||||||
|
@lorentz_effect_active = false
|
||||||
|
|
||||||
|
$bus.on(:lorentz_field) do
|
||||||
|
@lorentz_effect_active = true
|
||||||
|
end
|
||||||
|
|
||||||
|
$bus.on(:lorentz_field_end) do
|
||||||
|
@lorentz_effect_active = false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(player_x, player_y, dt)
|
def update(player_x, player_y, dt)
|
||||||
distance = Gosu.distance(@enemy.x, @enemy.y, player_x, player_y)
|
distance = Math.sqrt((player_x - @enemy.x)**2 + (player_y - @enemy.y)**2)
|
||||||
return unless distance < AGGRO_RADIUS
|
return unless distance < AGGRO_RADIUS
|
||||||
|
|
||||||
|
if @lorentz_effect_active && distance < 230
|
||||||
|
@speed = BASE_SPEED * 0.3
|
||||||
|
else
|
||||||
|
@speed = BASE_SPEED
|
||||||
|
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)
|
||||||
enemy_tile = [(@enemy.x - 90) / 120, (@enemy.y - 90) / 120].map(&:round)
|
enemy_tile = [(@enemy.x - 90) / 120, (@enemy.y - 90) / 120].map(&:round)
|
||||||
|
|
||||||
@@ -135,8 +151,8 @@ class EnemyAI
|
|||||||
|
|
||||||
def move_towards(target_x, target_y, dt)
|
def move_towards(target_x, target_y, dt)
|
||||||
angle = Gosu.angle(@enemy.x, @enemy.y, target_x, target_y)
|
angle = Gosu.angle(@enemy.x, @enemy.y, target_x, target_y)
|
||||||
dx = Gosu.offset_x(angle, SPEED * dt)
|
dx = Gosu.offset_x(angle, @speed * dt)
|
||||||
dy = Gosu.offset_y(angle, SPEED * dt)
|
dy = Gosu.offset_y(angle, @speed * dt)
|
||||||
|
|
||||||
@enemy.x += dx
|
@enemy.x += dx
|
||||||
@enemy.y += dy
|
@enemy.y += dy
|
||||||
|
|||||||
+26
-7
@@ -3,6 +3,23 @@ require_relative 'ai'
|
|||||||
class Enemy
|
class Enemy
|
||||||
attr_accessor :x, :y, :w, :h
|
attr_accessor :x, :y, :w, :h
|
||||||
|
|
||||||
|
def self.load(path, w, h, s)
|
||||||
|
# Once artwork is done need to load each animation here.
|
||||||
|
# But as artwork takes time, for now just load a single image.
|
||||||
|
@sprite = Gosu::Image.new(path, retro: true)
|
||||||
|
@i_w = w
|
||||||
|
@i_h = h
|
||||||
|
@s = s
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.sprite
|
||||||
|
@sprite
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.frame_size
|
||||||
|
[@i_w, @i_h, @s]
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(x, y)
|
def initialize(x, y)
|
||||||
@x = x
|
@x = x
|
||||||
@y = y
|
@y = y
|
||||||
@@ -36,15 +53,17 @@ class Enemy
|
|||||||
screen_x = @x - cam_x
|
screen_x = @x - cam_x
|
||||||
screen_y = @y - cam_y
|
screen_y = @y - cam_y
|
||||||
|
|
||||||
Gosu.draw_rect(
|
|
||||||
screen_x - @w / 2,
|
self.class.sprite.draw(
|
||||||
screen_y - @h / 2,
|
screen_x - self.class.frame_size[0],
|
||||||
@w,
|
screen_y - self.class.frame_size[1],
|
||||||
@h,
|
screen_y - self.class.frame_size[1],
|
||||||
Gosu::Color::RED,
|
self.class.frame_size[2],
|
||||||
screen_y - @h / 2
|
self.class.frame_size[2]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Gosu.draw_rect(screen_x - @w / 2, screen_y - @h / 2, @w, @h, Gosu::Color.new(0x40FF0000), Float::INFINITY) if $bus.get(:settings, :debug)
|
||||||
|
|
||||||
@ai.draw
|
@ai.draw
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
require_relative 'base'
|
||||||
|
|
||||||
|
class Force < Enemy
|
||||||
|
load 'assets/images/force.png', 21, 32, 1.7
|
||||||
|
|
||||||
|
def initialize(x, y)
|
||||||
|
super
|
||||||
|
@w = 20
|
||||||
|
@h = 20
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
require_relative 'base'
|
require_relative 'force'
|
||||||
|
|
||||||
class EnemyHandler
|
class EnemyHandler
|
||||||
def initialize
|
def initialize
|
||||||
@@ -14,7 +14,7 @@ class EnemyHandler
|
|||||||
# For now, just spawn a single enemy at a fixed location
|
# For now, just spawn a single enemy at a fixed location
|
||||||
start_room_coords = $bus.get(:start_room_coords)
|
start_room_coords = $bus.get(:start_room_coords)
|
||||||
if @enemies.empty?
|
if @enemies.empty?
|
||||||
@enemies << Enemy.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30)
|
@enemies << Force.new((start_room_coords[0] * 2 + 1 + 4) * 60 + 30, (start_room_coords[1] * 2 + 1 + 4) * 60 + 30)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class LorentzField
|
|||||||
$bus.emit(:consume, :lorentz_field, 1)
|
$bus.emit(:consume, :lorentz_field, 1)
|
||||||
@active = true
|
@active = true
|
||||||
@time = 0
|
@time = 0
|
||||||
|
$bus.emit(:lorentz_field)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(dt)
|
def update(dt)
|
||||||
@@ -41,6 +42,7 @@ class LorentzField
|
|||||||
if @time >= BASE_TIME
|
if @time >= BASE_TIME
|
||||||
@time = 0
|
@time = 0
|
||||||
@active = false
|
@active = false
|
||||||
|
$bus.emit(:lorentz_field_end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user