Refactor weapon system: update BladeOfRecursion and QuantumBow classes with improved attack mechanics, damage handling, and drawing logic; enhance WeaponHandler for better weapon management.
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 233 B |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 352 B |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 386 B |
+1
-1
@@ -95,7 +95,7 @@ class Game < Scene
|
|||||||
|
|
||||||
return if @hud.button_down(id, pos)
|
return if @hud.button_down(id, pos)
|
||||||
return if @props.button_down(id, pos)
|
return if @props.button_down(id, pos)
|
||||||
#return if @weapons.button_down(id, pos)
|
return if @weapons.button_down(id, pos)
|
||||||
|
|
||||||
#@character.button_down(id)
|
#@character.button_down(id)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
class BladeOfRecursion
|
class BladeOfRecursion
|
||||||
def initialize
|
def initialize
|
||||||
@damage = 1
|
@damage = 1
|
||||||
@range = 200
|
@range = 150
|
||||||
@speed = 500
|
@speed = 400
|
||||||
@x = 0
|
@x = 0
|
||||||
@y = 0
|
@y = 0
|
||||||
|
@start_x = 0
|
||||||
|
@start_y = 0
|
||||||
@direction = nil
|
@direction = nil
|
||||||
|
|
||||||
|
# the knife is pointed top-right
|
||||||
|
@sprite = Gosu::Image.new('assets/images/blade_of_recursion.png', retro: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def attack(direction)
|
def attack(direction)
|
||||||
|
return if @direction
|
||||||
@direction = direction
|
@direction = direction
|
||||||
@x, @y = $bus.get(:player_position)
|
@x, @y = $bus.get(:player_position)
|
||||||
|
@start_x, @start_y = @x, @y
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(dt)
|
def update(dt)
|
||||||
@@ -19,12 +26,63 @@ class BladeOfRecursion
|
|||||||
@x += Math.cos(@direction) * @speed * dt
|
@x += Math.cos(@direction) * @speed * dt
|
||||||
@y += Math.sin(@direction) * @speed * dt
|
@y += Math.sin(@direction) * @speed * dt
|
||||||
|
|
||||||
$bus.get(:attack, @x, @y, @range, @damage)
|
if Math.hypot(@x - @start_x, @y - @start_y) > @range
|
||||||
|
|
||||||
# If the blade has traveled its max range, reset it
|
|
||||||
player_x, player_y = $bus.get(:player_position)
|
|
||||||
if Math.hypot(@x - player_x, @y - player_y) > @range
|
|
||||||
@direction = nil
|
@direction = nil
|
||||||
|
@damage = 1
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
collides = $bus.get_all(:collides?, [@x - 5, @y - 5, 10, 10])
|
||||||
|
if collides.include?(:enemy)
|
||||||
|
$bus.emit(:attack, @x, @y, 30, @damage)
|
||||||
|
@direction = nil
|
||||||
|
@damage *= 2
|
||||||
|
if @damage > 512
|
||||||
|
damage = 1
|
||||||
|
$bus.emit(:consume, :blade_of_recursion, 1)
|
||||||
|
end
|
||||||
|
elsif collides.include?(:wall)
|
||||||
|
@direction = nil
|
||||||
|
@damage = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||||
|
|
||||||
|
# Draw the blade if active
|
||||||
|
if @direction
|
||||||
|
# Convert radians to degrees
|
||||||
|
angle_deg = @direction * 180 / Math::PI
|
||||||
|
# Adjust for knife pointing top-right
|
||||||
|
angle_deg += 45
|
||||||
|
|
||||||
|
@sprite.draw_rot(
|
||||||
|
@x - cam_x, # x in world coords
|
||||||
|
@y - cam_y, # y in world coords
|
||||||
|
1, # z-order
|
||||||
|
angle_deg, # rotation
|
||||||
|
0.5, 0.5, # pivot center
|
||||||
|
2, 2,
|
||||||
|
Gosu::Color::WHITE
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Draw memory bar as HUD in top-right of screen
|
||||||
|
# this should be in the HUD layer but due to time constraints im putting it here, sorry
|
||||||
|
bar_width = 100
|
||||||
|
bar_height = 10
|
||||||
|
padding = 10
|
||||||
|
|
||||||
|
bar_x = SCREEN_SIZE[0] - bar_width - padding
|
||||||
|
bar_y = padding
|
||||||
|
|
||||||
|
# full red background
|
||||||
|
Gosu.draw_rect(bar_x, bar_y, bar_width, bar_height, Gosu::Color::RED, Float::INFINITY)
|
||||||
|
|
||||||
|
# green foreground representing current damage
|
||||||
|
damage_ratio = Math.log2(@damage) / 9.0
|
||||||
|
damage_width = bar_width * [damage_ratio, 1.0].min
|
||||||
|
Gosu.draw_rect(bar_x, bar_y, damage_width, bar_height, Gosu::Color::GREEN, Float::INFINITY)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
+26
-20
@@ -1,39 +1,45 @@
|
|||||||
require_relative 'lorentz_field'
|
require_relative 'lorentz_field'
|
||||||
require_relative 'occams_razor'
|
require_relative 'occams_razor'
|
||||||
#require_relative 'quantum_bow'
|
require_relative 'quantum_bow'
|
||||||
#require_relative 'blade_of_recursion'
|
require_relative 'blade_of_recursion'
|
||||||
|
|
||||||
class WeaponHandler
|
class WeaponHandler
|
||||||
def initialize
|
def initialize
|
||||||
@weapons = {
|
@weapons = {
|
||||||
lorentz_field: LorentzField.new,
|
lorentz_field: LorentzField.new,
|
||||||
occams_razor: OccamsRazor.new,
|
occams_razor: OccamsRazor.new,
|
||||||
#quantum_bow: QuantumBow.new,
|
quantum_bow: QuantumBow.new,
|
||||||
#blade_of_recursion: BladeOfRecursion.new
|
blade_of_recursion: BladeOfRecursion.new
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def update(dt)
|
def update(dt)
|
||||||
@weapons.each_value { |weapon| weapon.update(dt) }
|
@weapons.each_value { |weapon| weapon.update(dt) }
|
||||||
|
|
||||||
selected_item = $bus.get(:selected_item)
|
|
||||||
return unless @weapons.key?(selected_item)
|
|
||||||
|
|
||||||
weapon = @weapons[selected_item]
|
|
||||||
if $bus.get(:count, selected_item) > 0
|
|
||||||
if Gosu.button_down?(Gosu::KB_SPACE)
|
|
||||||
direction = $bus.get(:player_direction)
|
|
||||||
weapon.attack(direction)
|
|
||||||
elsif Gosu.button_down?(Gosu::MS_LEFT)
|
|
||||||
player_x, player_y = $bus.get(:player_position)
|
|
||||||
mouse_x, mouse_y = $bus.get(:mouse_pos)
|
|
||||||
direction = Math.atan2(mouse_y - player_y, mouse_x - player_x)
|
|
||||||
weapon.attack(direction)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
@weapons.each_value(&:draw)
|
@weapons.each_value(&:draw)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def button_down(id, pos)
|
||||||
|
selected_item = $bus.get(:selected_item)
|
||||||
|
return unless @weapons.key?(selected_item)
|
||||||
|
|
||||||
|
weapon = @weapons[selected_item]
|
||||||
|
if $bus.get(:count, selected_item) > 0
|
||||||
|
if id == Gosu::KB_SPACE
|
||||||
|
player_x, player_y = $bus.get(:player_position)
|
||||||
|
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||||
|
mouse_x, mouse_y = $bus.get(:mouse_pos) || [0, 0]
|
||||||
|
direction = Math.atan2((mouse_y + cam_y - player_y), (mouse_x + cam_x - player_x))
|
||||||
|
weapon.attack(direction)
|
||||||
|
elsif id == Gosu::MS_LEFT
|
||||||
|
player_x, player_y = $bus.get(:player_position)
|
||||||
|
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||||
|
mouse_x, mouse_y = pos
|
||||||
|
direction = Math.atan2((mouse_y + cam_y - player_y), (mouse_x + cam_x - player_x))
|
||||||
|
weapon.attack(direction)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
class QuantumBow
|
||||||
|
ARROW_SPEED = 700
|
||||||
|
LOW_DAMAGE = 10
|
||||||
|
HIGH_DAMAGE = 50
|
||||||
|
FACING_THRESHOLD = Math::PI / 2.0 # 90° in radians
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@arrows = []
|
||||||
|
#@sprite = Gosu::Image.new('assets/images/quantum_bow.png', retro: true)
|
||||||
|
@arrow_sprite = Gosu::Image.new('assets/images/arrow.png', retro: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def clamp_angle(intended, player)
|
||||||
|
# it takes the direction from the attack function and only allows attacks facing forwards from the player,
|
||||||
|
# and if it is not in 90 deg from players direction then it will return the extreme angle possible else the intended angle
|
||||||
|
angle_diff = ((intended - player + Math::PI) % (2 * Math::PI)) - Math::PI
|
||||||
|
if angle_diff > FACING_THRESHOLD
|
||||||
|
return player + FACING_THRESHOLD
|
||||||
|
elsif angle_diff < -FACING_THRESHOLD
|
||||||
|
return player - FACING_THRESHOLD
|
||||||
|
else
|
||||||
|
return intended
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def attack(direction)
|
||||||
|
player_x, player_y = $bus.get(:player_position)
|
||||||
|
return unless $bus.get(:consume, :wood, 3) && $bus.get(:consume, :metal, 1)
|
||||||
|
|
||||||
|
@arrows << { x: player_x, y: player_y, direction: clamp_angle(direction, $bus.get(:player_direction)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(dt)
|
||||||
|
player_x, player_y = $bus.get(:player_position)
|
||||||
|
player_dir = $bus.get(:player_direction)
|
||||||
|
|
||||||
|
@arrows.each do |arrow|
|
||||||
|
arrow[:x] += Math.cos(arrow[:direction]) * ARROW_SPEED * dt
|
||||||
|
arrow[:y] += Math.sin(arrow[:direction]) * ARROW_SPEED * dt
|
||||||
|
|
||||||
|
rect = [arrow[:x] - 5, arrow[:y] - 2, 10, 4]
|
||||||
|
collides = $bus.get_all(:collides?, rect)
|
||||||
|
|
||||||
|
if collides.include?(:enemy)
|
||||||
|
# compute if player is facing the arrow
|
||||||
|
vec_x = arrow[:x] - player_x
|
||||||
|
vec_y = arrow[:y] - player_y
|
||||||
|
angle_to_arrow = Math.atan2(vec_y, vec_x)
|
||||||
|
angle_diff = ((angle_to_arrow - player_dir + Math::PI) % (2 * Math::PI)) - Math::PI
|
||||||
|
angle_diff = angle_diff.abs
|
||||||
|
|
||||||
|
if angle_diff > FACING_THRESHOLD
|
||||||
|
$bus.emit(:blast, arrow[:x], arrow[:y], 30, HIGH_DAMAGE, :safe)
|
||||||
|
else
|
||||||
|
$bus.emit(:attack, arrow[:x], arrow[:y], 30, LOW_DAMAGE)
|
||||||
|
end
|
||||||
|
|
||||||
|
arrow[:hit] = true
|
||||||
|
elsif collides.include?(:wall)
|
||||||
|
arrow[:hit] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@arrows.reject! { |a| a[:hit] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
cam_x, cam_y = $bus.get(:camera_pos) || [0, 0]
|
||||||
|
|
||||||
|
@arrows.each do |arrow|
|
||||||
|
angle_deg = arrow[:direction] * 180 / Math::PI
|
||||||
|
angle_deg -= 45 + 180
|
||||||
|
@arrow_sprite.draw_rot(arrow[:x] - cam_x, arrow[:y] - cam_y, 1, angle_deg, 0.5, 0.5, 2, 2, Gosu::Color::WHITE)
|
||||||
|
end
|
||||||
|
|
||||||
|
#player_x, player_y = $bus.get(:player_position)
|
||||||
|
#@sprite.draw(player_x - cam_x - 16, player_y - cam_y - 16, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user