diff --git a/assets/fencing/fencing.png b/assets/fencing/fencing.png
new file mode 100644
index 0000000..545b12b
Binary files /dev/null and b/assets/fencing/fencing.png differ
diff --git a/assets/fencing/fencing_edge.png b/assets/fencing/fencing_edge.png
new file mode 100644
index 0000000..ab53d22
Binary files /dev/null and b/assets/fencing/fencing_edge.png differ
diff --git a/assets/svg/fencing/fencing.svg b/assets/svg/fencing/fencing.svg
new file mode 100644
index 0000000..e9c48c3
--- /dev/null
+++ b/assets/svg/fencing/fencing.svg
@@ -0,0 +1,135 @@
+
+
+
+
diff --git a/assets/svg/fencing/fencing_edge.svg b/assets/svg/fencing/fencing_edge.svg
new file mode 100644
index 0000000..506fcd3
--- /dev/null
+++ b/assets/svg/fencing/fencing_edge.svg
@@ -0,0 +1,112 @@
+
+
+
+
diff --git a/lib/component.rb b/lib/component.rb
index cec2908..3973a62 100644
--- a/lib/component.rb
+++ b/lib/component.rb
@@ -15,6 +15,33 @@ class IMICRTS
@@components[name] = klass
end
end
+
+ attr_reader :parent
+ def initialize(parent:)
+ @parent = parent
+
+ setup
+ end
+
+ def data
+ @parent.data
+ end
+
+ def data=(key, value)
+ @parent.data[key] = value
+ end
+
+ def setup
+ end
+
+ def draw
+ end
+
+ def update
+ end
+
+ def tick(tick_id)
+ end
end
end
diff --git a/lib/components/build_queue.rb b/lib/components/build_queue.rb
index 7d7ae8d..25e26d4 100644
--- a/lib/components/build_queue.rb
+++ b/lib/components/build_queue.rb
@@ -1,9 +1,7 @@
class IMICRTS
class BuildQueue < Component
Item = Struct.new(:entity, :progress)
- def initialize(parent:)
- @parent = parent
-
+ def setup
@queue = []
end
diff --git a/lib/components/building.rb b/lib/components/building.rb
new file mode 100644
index 0000000..38f52cc
--- /dev/null
+++ b/lib/components/building.rb
@@ -0,0 +1,95 @@
+class IMICRTS
+ class Building < Component
+ def setup
+ data.construction_progress ||= 0
+ data.construction_goal ||= 100
+
+ @text = CyberarmEngine::Text.new("", y: @parent.position.y, z: Float::INFINITY, size: 12)
+ data.state = :construct # deconstruct, building, idle
+ end
+
+ def draw
+ case data.state
+ when :construct
+ draw_construction unless @text.text.empty?
+ @text.text = "Building: #{(construction_progress * 100.0).round}%"
+ @text.x = @parent.position.x - @text.width / 2
+ @text.draw
+ when :deconstruct
+ when :building
+ when :idle
+ else
+ raise "Unknown state!"
+ end
+ end
+
+ def update
+ case data.state
+ when :construct
+ @parent.color.alpha = 255 * construction_progress
+ data.state = :idle if construction_complete?
+ end
+ end
+
+ def construction_complete?
+ data.construction_progress >= data.construction_goal
+ end
+
+ # WARNING: returns a floating point number, not network safe!
+ def construction_progress
+ data.construction_progress.to_f / data.construction_goal
+ end
+
+ def construction_work(work)
+ raise TypeError, "Got a non integer value!" unless work.is_a?(Integer)
+
+ data.construction_progress += work
+ data.construction_progress = data.construction_goal if construction_complete?
+ end
+
+ def draw_construction
+ @fencing ||= Gosu::Image.new(IMICRTS::ASSETS_PATH + "/fencing/fencing.png")
+ @fencing_edge ||= Gosu::Image.new(IMICRTS::ASSETS_PATH + "/fencing/fencing_edge.png")
+
+ tiles = []
+ each_tile(@parent.position / @parent.director.map.tile_size) do |tile, data, x, y|
+ tiles << tile
+ end
+
+ tiles.each do |tile|
+ # X
+ if tiles.find { |t| t.grid_position.x < tile.grid_position.x && t.grid_position.y == tile.grid_position.y} == nil
+ @fencing_edge.draw(tile.position.x - 30, tile.position.y, Float::INFINITY)
+ end
+ if tiles.find { |t| t.grid_position.x > tile.grid_position.x && t.grid_position.y == tile.grid_position.y} == nil
+ @fencing_edge.draw(tile.position.x, tile.position.y, Float::INFINITY)
+ end
+ # Y
+ if tiles.find { |t| t.grid_position.x == tile.grid_position.x && t.grid_position.y < tile.grid_position.y} == nil
+ @fencing.draw(tile.position.x, tile.position.y - 24, Float::INFINITY)
+ end
+ if tiles.find { |t| t.grid_position.x == tile.grid_position.x && t.grid_position.y > tile.grid_position.y} == nil
+ @fencing.draw(tile.position.x, tile.position.y, Float::INFINITY)
+ end
+ end
+ end
+
+ def each_tile(vector, &block)
+ if tile = @parent.director.map.tile_at(vector.x, vector.y)
+ ent = Entity.get(@parent.name)
+ origin = (tile.grid_position - 2)
+
+ ent.tiles.each_with_index do |array, y|
+ array.each_with_index do |space_required, x|
+ next unless space_required.is_a?(TrueClass)
+
+ other_tile = @parent.director.map.tile_at(origin.x + x, origin.y + y)
+ if other_tile
+ block.call(other_tile, space_required, origin.x + x, origin.y + y)
+ end
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/components/movement.rb b/lib/components/movement.rb
index 94c79bf..314964d 100644
--- a/lib/components/movement.rb
+++ b/lib/components/movement.rb
@@ -1,8 +1,13 @@
class IMICRTS
class Movement < Component
attr_accessor :pathfinder
- def initialize(parent:)
- @parent = parent
+
+ def update
+ if pathfinder && pathfinder.path_current_node
+ rotate_towards(pathfinder.path_current_node.tile.position + @parent.director.map.tile_size / 2)
+ end
+
+ follow_path
end
def rotate_towards(vector)
diff --git a/lib/components/sidebar_actions.rb b/lib/components/sidebar_actions.rb
index 1d7d468..6a1c99f 100644
--- a/lib/components/sidebar_actions.rb
+++ b/lib/components/sidebar_actions.rb
@@ -3,9 +3,7 @@ class IMICRTS
Action = Struct.new(:label, :image, :description, :block)
attr_reader :actions
- def initialize(parent:)
- @parent = parent
-
+ def setup
@actions = []
end
diff --git a/lib/components/turret.rb b/lib/components/turret.rb
index ccb2d3b..f235926 100644
--- a/lib/components/turret.rb
+++ b/lib/components/turret.rb
@@ -1,9 +1,7 @@
class IMICRTS
class Turret < Component
attr_accessor :angle, :center
- def initialize(parent:)
- @parent = parent
-
+ def setup
@angle = 0
@center = CyberarmEngine::Vector.new(0.5, 0.5)
end
diff --git a/lib/entities/buildings/barracks.rb b/lib/entities/buildings/barracks.rb
index 29ffbac..9d717be 100644
--- a/lib/entities/buildings/barracks.rb
+++ b/lib/entities/buildings/barracks.rb
@@ -7,6 +7,7 @@ tiles = [
]
IMICRTS::Entity.define_entity(:barracks, :building, 400, "Builds and soldiers", tiles) do |entity|
+ entity.has(:building)
entity.has(:build_queue)
entity.radius = 44
diff --git a/lib/entities/buildings/construction_yard.rb b/lib/entities/buildings/construction_yard.rb
index ab05f06..dedb78c 100644
--- a/lib/entities/buildings/construction_yard.rb
+++ b/lib/entities/buildings/construction_yard.rb
@@ -7,6 +7,7 @@ tiles = [
]
IMICRTS::Entity.define_entity(:construction_yard, :building, 2_000, "Provides radar and builds construction workers", tiles) do |entity|
+ entity.has(:building)
entity.has(:build_queue)
entity.has(:sidebar_actions)
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :construction_worker})
diff --git a/lib/entities/buildings/helipad.rb b/lib/entities/buildings/helipad.rb
index a81ac49..b5a6a37 100644
--- a/lib/entities/buildings/helipad.rb
+++ b/lib/entities/buildings/helipad.rb
@@ -7,6 +7,7 @@ tiles = [
]
IMICRTS::Entity.define_entity(:helipad, :building, 1_000, "Builds and rearms helicopters", tiles) do |entity|
+ entity.has(:building)
entity.has(:build_queue)
entity.has(:sidebar_actions)
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :helicopter})
diff --git a/lib/entities/buildings/power_plant.rb b/lib/entities/buildings/power_plant.rb
index ea371a6..33abde8 100644
--- a/lib/entities/buildings/power_plant.rb
+++ b/lib/entities/buildings/power_plant.rb
@@ -7,6 +7,8 @@ tiles = [
]
IMICRTS::Entity.define_entity(:power_plant, :building, 800, "Generates power", tiles) do |entity|
+ entity.has(:building)
+
entity.radius = 24
entity.max_health = 100.0
diff --git a/lib/entities/buildings/refinery.rb b/lib/entities/buildings/refinery.rb
index 9e6d9ca..a77259b 100644
--- a/lib/entities/buildings/refinery.rb
+++ b/lib/entities/buildings/refinery.rb
@@ -7,6 +7,8 @@ tiles = [
]
IMICRTS::Entity.define_entity(:refinery, :building, 1_400, "Generates credits", tiles) do |entity|
+ entity.has(:building)
+
entity.radius = 44
entity.max_health = 100.0
diff --git a/lib/entities/buildings/war_factory.rb b/lib/entities/buildings/war_factory.rb
index 69d8490..3acc8b2 100644
--- a/lib/entities/buildings/war_factory.rb
+++ b/lib/entities/buildings/war_factory.rb
@@ -7,6 +7,7 @@ tiles = [
]
IMICRTS::Entity.define_entity(:war_factory, :building, 2_000, "Builds units", tiles) do |entity|
+ entity.has(:building)
entity.has(:build_queue)
entity.has(:sidebar_actions)
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :jeep})
diff --git a/lib/entity.rb b/lib/entity.rb
index 8bd785f..21caec3 100644
--- a/lib/entity.rb
+++ b/lib/entity.rb
@@ -15,16 +15,20 @@ class IMICRTS
end
end
- attr_reader :director, :player, :id, :name, :type, :speed
+ attr_reader :director, :player, :id, :name, :type, :speed, :data
attr_accessor :position, :angle, :radius, :target, :state,
:movement, :health, :max_health,
:turret, :center, :particle_emitters, :color
- def initialize(name:, player:, id:, position:, angle:, director:)
+ def initialize(name:, player:, id:, position:, angle:, director:, proto_entity: false)
@player = player
@id = id
@position = position
@angle = angle
@director = director
+ @proto_entity = proto_entity
+
+ @data = FriendlyHash.new
+
@speed = 0.5
@color = Gosu::Color.rgba(255, 255, 255, 255)
@@ -125,18 +129,14 @@ class IMICRTS
render unless @render
@render.draw_rot(@position.x, @position.y, @position.z, @angle, @center.x, @center.y, 1, 1, @color)
- component(:turret).draw if component(:turret)
- @particle_emitters.each(&:draw)
+ unless @proto_entity
+ @components.values.each(&:draw)
+ @particle_emitters.each(&:draw)
+ end
end
def update
- if component(:movement)
- if component(:movement).pathfinder && component(:movement).pathfinder.path_current_node
- component(:movement).rotate_towards(component(:movement).pathfinder.path_current_node.tile.position + @director.map.tile_size / 2)
- end
-
- component(:movement).follow_path
- end
+ @components.values.each(&:update)
@particle_emitters.each do |emitter|
@particle_emitters.delete(emitter) if emitter.die?
@@ -146,6 +146,7 @@ class IMICRTS
def tick(tick_id)
@on_tick.call if @on_tick
+ component(:building).construction_work(1) if component(:building)
end
def on_tick(&block)
diff --git a/lib/friendly_hash.rb b/lib/friendly_hash.rb
index d109a2f..0590bbd 100644
--- a/lib/friendly_hash.rb
+++ b/lib/friendly_hash.rb
@@ -12,10 +12,13 @@ class IMICRTS
@hash[key.to_sym] = value
end
- def method_missing(method)
+ def method_missing(method, argument = nil)
if value = @hash.dig(method)
value
+ elsif argument != nil
+ @hash[method.to_s.sub("=", "").to_sym] = argument
else
+ return false unless argument # May result in bugginess!
raise "Unknown value for: #{method}"
end
end
diff --git a/lib/tools/place_entity.rb b/lib/tools/place_entity.rb
index de396e3..cb3ef3a 100644
--- a/lib/tools/place_entity.rb
+++ b/lib/tools/place_entity.rb
@@ -6,7 +6,7 @@ class IMICRTS
@entity = @options[:entity]
@construction_worker = @options[:construction_worker]
- @preview = Entity.new(name: @entity, player: @player, id: 0, position: CyberarmEngine::Vector.new, angle: 0, director: @director)
+ @preview = Entity.new(name: @entity, player: @player, id: 0, position: CyberarmEngine::Vector.new, angle: 0, director: @director, proto_entity: true)
end
def draw