mirror of
https://github.com/cyberarm/i-mic-rts.git
synced 2025-12-13 06:52:33 +00:00
Building units now uses orders 😃
This commit is contained in:
BIN
assets/audio/music/EmptyCity.ogg
Normal file
BIN
assets/audio/music/EmptyCity.ogg
Normal file
Binary file not shown.
2
assets/audio/music/README.md
Normal file
2
assets/audio/music/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Music Source
|
||||
* EmptyCity - CC0 - yd - https://opengameart.org/content/emptycity-background-music
|
||||
@@ -70,9 +70,9 @@ class IMICRTS
|
||||
def visible?(object)
|
||||
if object.is_a?(Map::Tile)
|
||||
object.position.x - object.size >= @viewport.min.x - @position.x &&
|
||||
object.position.y - object.size >= @viewport.min.y - @position.y &&
|
||||
object.position.x <= @viewport.max.x - @position.x &&
|
||||
object.position.y <= @viewport.max.y - @position.y
|
||||
object.position.y - object.size >= @viewport.min.y - @position.y &&
|
||||
object.position.x <= @viewport.max.x - @position.x &&
|
||||
object.position.y <= @viewport.max.y - @position.y
|
||||
else
|
||||
pp object.class
|
||||
exit
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
class IMICRTS
|
||||
class Component
|
||||
include CyberarmEngine::Common
|
||||
|
||||
@@components = {}
|
||||
|
||||
def self.get(name)
|
||||
|
||||
@@ -2,13 +2,13 @@ class IMICRTS
|
||||
class BuildQueue < Component
|
||||
attr_reader :queue
|
||||
|
||||
Item = Struct.new(:entity, :progress)
|
||||
Item = Struct.new(:entity, :progress, :completed)
|
||||
def setup
|
||||
@queue = []
|
||||
end
|
||||
|
||||
def add(type)
|
||||
@queue << Item.new(Entity.get(type), 0.0)
|
||||
@queue << Item.new(Entity.get(type), 0.0, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,7 +2,7 @@ class IMICRTS
|
||||
class Building < Component
|
||||
def setup
|
||||
data.construction_progress ||= 0
|
||||
data.construction_goal ||= 100
|
||||
data.construction_goal ||= Entity.get(@parent.name).build_steps
|
||||
|
||||
@text = CyberarmEngine::Text.new("", y: @parent.position.y, z: Float::INFINITY, size: 12)
|
||||
data.state = :construct # deconstruct, building, idle
|
||||
@@ -48,8 +48,8 @@ class IMICRTS
|
||||
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")
|
||||
@fencing ||= get_image(IMICRTS::ASSETS_PATH + "/fencing/fencing.png")
|
||||
@fencing_edge ||= get_image(IMICRTS::ASSETS_PATH + "/fencing/fencing_edge.png")
|
||||
|
||||
tiles = []
|
||||
each_tile(@parent.position / @parent.director.map.tile_size) do |tile, data, x, y|
|
||||
|
||||
@@ -16,12 +16,12 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def rotate_towards(vector)
|
||||
_angle = Gosu.angle(@parent.position.x, @parent.position.y, vector.x, vector.y)
|
||||
a = (360.0 + (_angle - @parent.angle)) % 360.0
|
||||
angle = Gosu.angle(@parent.position.x, @parent.position.y, vector.x, vector.y)
|
||||
a = (360.0 + (angle - @parent.angle)) % 360.0
|
||||
|
||||
# FIXME: Fails if vector is directly behind entity
|
||||
if a.round == 180
|
||||
@parent.angle = (_angle + 180.0) % 360.0
|
||||
@parent.angle = (angle + 180.0) % 360.0
|
||||
elsif a < 180
|
||||
@parent.angle -= 1.0
|
||||
else
|
||||
|
||||
@@ -17,7 +17,9 @@ class IMICRTS
|
||||
|
||||
action.label = ent.name.to_s.split("_").map{ |s| s.capitalize }.join(" ")
|
||||
action.description = "Cost: #{ent.cost}\n#{ent.description}"
|
||||
action.block = proc { @parent.component(:build_queue).add(data[:entity]) }
|
||||
action.block = proc do
|
||||
@parent.director.schedule_order(IMICRTS::Order::BUILD_UNIT, @parent.player.id, @parent.id, data[:entity])
|
||||
end
|
||||
|
||||
when :set_tool
|
||||
ent = IMICRTS::Entity.get(data[:entity])
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
class IMICRTS
|
||||
class Spawner < Component
|
||||
def tick(tick_id)
|
||||
# TODO: Ensure that a build order is created before working on entity
|
||||
|
||||
item = @parent.component(:build_queue).queue.first
|
||||
|
||||
if item
|
||||
item.progress += 1
|
||||
return unless item
|
||||
|
||||
if item.progress >= 100 # TODO: Define work units required for construction
|
||||
@parent.component(:build_queue).queue.shift
|
||||
item.progress += 1
|
||||
|
||||
spawn_point = @parent.position.clone
|
||||
spawn_point.y += 96 # TODO: Use one of entity's reserved tiles for spawning
|
||||
if item.progress >= item.entity.build_steps
|
||||
unless item.completed
|
||||
item.completed = true
|
||||
|
||||
ent = @parent.director.spawn_entity(player_id: @parent.player.id, name: item.entity.name, position: spawn_point)
|
||||
ent.target = @parent.component(:waypoint).waypoint if @parent.component(:waypoint)
|
||||
@parent.director.schedule_order(IMICRTS::Order::BUILD_UNIT_COMPLETE, @parent.player.id, @parent.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,15 +7,15 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def body_image=(image)
|
||||
@body_image = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
@body_image = get_image("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
end
|
||||
|
||||
def shell_image=(image)
|
||||
@shell_image = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
@shell_image = get_image("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
end
|
||||
|
||||
def overlay_image=(image)
|
||||
@overlay_image = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
@overlay_image = get_image("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
end
|
||||
|
||||
def render
|
||||
@@ -28,8 +28,11 @@ class IMICRTS
|
||||
|
||||
def draw
|
||||
render unless @render
|
||||
@angle += 0.1
|
||||
@render.draw_rot(@parent.position.x, @parent.position.y, @parent.position.z, @angle, @center.x, @center.y)
|
||||
end
|
||||
|
||||
def update
|
||||
@angle = @parent.angle
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,6 +3,7 @@ class IMICRTS
|
||||
def setup
|
||||
@waypoint = @parent.position.clone
|
||||
@waypoint.y += @parent.director.map.tile_size
|
||||
@waypoint_color = 0xffffff00
|
||||
end
|
||||
|
||||
def set(vector)
|
||||
@@ -17,11 +18,11 @@ class IMICRTS
|
||||
return unless @parent.player.selected_entities.include?(@parent)
|
||||
|
||||
Gosu.draw_line(
|
||||
@parent.position.x, @parent.position.y, @parent.player.color,
|
||||
@waypoint.x, @waypoint.y, @parent.player.color, ZOrder::ENTITY_GIZMOS
|
||||
@parent.position.x, @parent.position.y, @waypoint_color,
|
||||
@waypoint.x, @waypoint.y, @waypoint_color, ZOrder::ENTITY_GIZMOS
|
||||
)
|
||||
|
||||
Gosu.draw_circle(@waypoint.x, @waypoint.y, 4, 9, @parent.player.color, ZOrder::ENTITY_GIZMOS)
|
||||
Gosu.draw_circle(@waypoint.x, @waypoint.y, 4, 9, @waypoint_color, ZOrder::ENTITY_GIZMOS)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,7 +6,7 @@ tiles = [
|
||||
[false, :path, :path, :path, false],
|
||||
]
|
||||
|
||||
IMICRTS::Entity.define_entity(:barracks, :building, 400, "Builds and soldiers", tiles) do |entity|
|
||||
IMICRTS::Entity.define_entity(:barracks, :building, 400, 40, "Builds and soldiers", tiles) do |entity|
|
||||
entity.has(:building)
|
||||
entity.has(:waypoint)
|
||||
entity.has(:spawner)
|
||||
|
||||
@@ -6,13 +6,13 @@ tiles = [
|
||||
[false, :path, :path, :path, false],
|
||||
]
|
||||
|
||||
IMICRTS::Entity.define_entity(:construction_yard, :building, 2_000, "Provides radar and builds construction workers", tiles) do |entity|
|
||||
IMICRTS::Entity.define_entity(:construction_yard, :building, 2_000, 310, "Provides radar and builds construction workers", tiles) do |entity|
|
||||
entity.has(:building)
|
||||
entity.has(:waypoint)
|
||||
entity.has(:spawner)
|
||||
entity.has(:build_queue)
|
||||
entity.has(:sidebar_actions)
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :construction_worker})
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, { entity: :construction_worker })
|
||||
|
||||
entity.radius = 40
|
||||
entity.max_health = 100.0
|
||||
|
||||
@@ -6,13 +6,13 @@ tiles = [
|
||||
[false, false, false, false, false],
|
||||
]
|
||||
|
||||
IMICRTS::Entity.define_entity(:helipad, :building, 1_000, "Builds and rearms helicopters", tiles) do |entity|
|
||||
IMICRTS::Entity.define_entity(:helipad, :building, 1_000, 100, "Builds and rearms helicopters", tiles) do |entity|
|
||||
entity.has(:building)
|
||||
entity.has(:waypoint)
|
||||
entity.has(:spawner)
|
||||
entity.has(:build_queue)
|
||||
entity.has(:sidebar_actions)
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :helicopter})
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, { entity: :helicopter })
|
||||
|
||||
entity.radius = 26
|
||||
entity.max_health = 100.0
|
||||
|
||||
@@ -6,7 +6,7 @@ tiles = [
|
||||
[false, false, :path, false, false],
|
||||
]
|
||||
|
||||
IMICRTS::Entity.define_entity(:power_plant, :building, 800, "Generates power", tiles) do |entity|
|
||||
IMICRTS::Entity.define_entity(:power_plant, :building, 800, 45, "Generates power", tiles) do |entity|
|
||||
entity.has(:building)
|
||||
|
||||
entity.radius = 24
|
||||
|
||||
@@ -6,7 +6,7 @@ tiles = [
|
||||
[false, false, :path, :path, false],
|
||||
]
|
||||
|
||||
IMICRTS::Entity.define_entity(:refinery, :building, 1_400, "Generates credits", tiles) do |entity|
|
||||
IMICRTS::Entity.define_entity(:refinery, :building, 1_400, 200, "Generates credits", tiles) do |entity|
|
||||
entity.has(:building)
|
||||
|
||||
entity.radius = 44
|
||||
|
||||
@@ -6,15 +6,15 @@ tiles = [
|
||||
[false, :path, :path, :path, false],
|
||||
]
|
||||
|
||||
IMICRTS::Entity.define_entity(:war_factory, :building, 2_000, "Builds units", tiles) do |entity|
|
||||
IMICRTS::Entity.define_entity(:war_factory, :building, 2_000, 310, "Builds units", tiles) do |entity|
|
||||
entity.has(:building)
|
||||
entity.has(:waypoint)
|
||||
entity.has(:spawner)
|
||||
entity.has(:build_queue)
|
||||
entity.has(:sidebar_actions)
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :jeep})
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :tank})
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, {entity: :harvester})
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, { entity: :jeep })
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, { entity: :tank })
|
||||
entity.component(:sidebar_actions).add(:add_to_build_queue, { entity: :harvester })
|
||||
|
||||
entity.radius = 48
|
||||
entity.max_health = 100.0
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
IMICRTS::Entity.define_entity(:construction_worker, :unit, 1000, "Constructs buildings") do |entity|
|
||||
IMICRTS::Entity.define_entity(:construction_worker, :unit, 1000, 75, "Constructs buildings") do |entity|
|
||||
entity.has(:movement)
|
||||
entity.has(:build_queue)
|
||||
entity.has(:sidebar_actions)
|
||||
[:power_plant, :refinery, :barracks, :war_factory, :helipad, :construction_yard].each do |ent|
|
||||
entity.component(:sidebar_actions).add(:set_tool, {tool: :place_entity, entity: ent, construction_worker: entity})
|
||||
entity.component(:sidebar_actions).add(:set_tool, { tool: :place_entity, entity: ent, construction_worker: entity })
|
||||
end
|
||||
|
||||
entity.radius = 14
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
IMICRTS::Entity.define_entity(:harvester, :unit, 1400, "Harvests ore") do |entity, director|
|
||||
IMICRTS::Entity.define_entity(:harvester, :unit, 1400, 140, "Harvests ore") do |entity, director|
|
||||
entity.has(:movement)
|
||||
|
||||
entity.radius = 10
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
IMICRTS::Entity.define_entity(:helicopter, :unit, 400, "Attacks ground targets") do |entity|
|
||||
IMICRTS::Entity.define_entity(:helicopter, :unit, 400, 40, "Attacks ground targets") do |entity|
|
||||
entity.has(:movement)
|
||||
|
||||
entity.speed = 2.5
|
||||
entity.radius = 14
|
||||
entity.movement = :air
|
||||
entity.max_health = 100.0
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
IMICRTS::Entity.define_entity(:jeep, :unit, 400, "Attacks ground targets") do |entity|
|
||||
IMICRTS::Entity.define_entity(:jeep, :unit, 400, 40, "Attacks ground targets") do |entity|
|
||||
entity.has(:movement)
|
||||
entity.has(:turret)
|
||||
|
||||
entity.speed = 1.5
|
||||
entity.radius = 14
|
||||
entity.movement = :ground
|
||||
entity.max_health = 100.0
|
||||
@@ -14,4 +15,8 @@ IMICRTS::Entity.define_entity(:jeep, :unit, 400, "Attacks ground targets") do |e
|
||||
|
||||
entity.on_tick do
|
||||
end
|
||||
|
||||
entity.component(:movement).define_singleton_method(:rotate_towards) do |target|
|
||||
entity.angle = Gosu.angle(target.x, target.y, entity.position.x, entity.position.y)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
IMICRTS::Entity.define_entity(:tank, :unit, 800, "Attacks ground targets") do |entity|
|
||||
IMICRTS::Entity.define_entity(:tank, :unit, 800, 80, "Attacks ground targets") do |entity|
|
||||
entity.has(:movement)
|
||||
entity.has(:turret)
|
||||
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
class IMICRTS
|
||||
class Entity
|
||||
Stub = Struct.new(:name, :type, :cost, :description, :tiles, :setup)
|
||||
include CyberarmEngine::Common
|
||||
Stub = Struct.new(:name, :type, :cost, :build_steps, :description, :tiles, :setup)
|
||||
@entities = {}
|
||||
|
||||
def self.get(name)
|
||||
@entities.dig(name)
|
||||
end
|
||||
|
||||
def self.define_entity(name, type, cost, description, tiles = [[]], &block)
|
||||
if entity = get(name)
|
||||
raise "#{name.inspect} is already defined!"
|
||||
else
|
||||
@entities[name] = Stub.new(name, type, cost, description, tiles, block)
|
||||
end
|
||||
def self.define_entity(name, type, cost, build_steps, description, tiles = [[]], &block)
|
||||
raise "#{name.inspect} is already defined!" if get(name)
|
||||
|
||||
@entities[name] = Stub.new(name, type, cost, build_steps, description, tiles, block)
|
||||
end
|
||||
|
||||
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
|
||||
attr_reader :director, :player, :id, :name, :type, :data
|
||||
attr_accessor :position, :angle, :radius, :target, :state, :movement, :health, :max_health,
|
||||
:speed, :turret, :center, :particle_emitters, :color
|
||||
|
||||
def initialize(name:, player:, id:, position:, angle:, director:, proto_entity: false)
|
||||
@player = player
|
||||
@id = id
|
||||
@@ -77,11 +76,9 @@ class IMICRTS
|
||||
def has(symbol)
|
||||
component = Component.get(symbol)
|
||||
|
||||
if component
|
||||
@components[symbol] = component.new(parent: self)
|
||||
else
|
||||
raise "Unknown component: #{symbol.inspect}"
|
||||
end
|
||||
raise "Unknown component: #{symbol.inspect}" unless component
|
||||
|
||||
@components[symbol] = component.new(parent: self)
|
||||
end
|
||||
|
||||
def component(symbol)
|
||||
@@ -89,15 +86,15 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def body_image=(image)
|
||||
@body_image = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
@body_image = get_image("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
end
|
||||
|
||||
def shell_image=(image)
|
||||
@shell_image = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
@shell_image = get_image("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
end
|
||||
|
||||
def overlay_image=(image)
|
||||
@overlay_image = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
@overlay_image = get_image("#{IMICRTS::ASSETS_PATH}/#{image}", retro: true)
|
||||
end
|
||||
|
||||
def target=(entity)
|
||||
@@ -153,10 +150,11 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def tick(tick_id)
|
||||
@components.values.each { |com| com.tick(tick_id) }
|
||||
@components.each_value { |com| com.tick(tick_id) }
|
||||
|
||||
@on_tick.call if @on_tick
|
||||
data.assigned_construction_workers ||= 4
|
||||
@on_tick&.call
|
||||
|
||||
data.assigned_construction_workers ||= 1
|
||||
data.construction_speed ||= 1
|
||||
component(:building).construction_work(data.assigned_construction_workers * data.construction_speed) if component(:building)
|
||||
end
|
||||
|
||||
18
lib/order.rb
18
lib/order.rb
@@ -29,6 +29,7 @@ class IMICRTS
|
||||
end
|
||||
|
||||
attr_reader :id, :arguments
|
||||
|
||||
def initialize(id:, arguments:, &handler)
|
||||
@id = id
|
||||
@arguments = arguments
|
||||
@@ -36,7 +37,7 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def execute(director, *arguments)
|
||||
pp Order.order_name(self.id)
|
||||
pp Order.order_name(id)
|
||||
@handler.call(struct(arguments), director)
|
||||
end
|
||||
|
||||
@@ -48,7 +49,7 @@ class IMICRTS
|
||||
hash[key] = args[value]
|
||||
end
|
||||
|
||||
return hash
|
||||
hash
|
||||
end
|
||||
|
||||
def serialize(order, director)
|
||||
@@ -76,13 +77,18 @@ class IMICRTS
|
||||
:ATTACK,
|
||||
:PATROL,
|
||||
|
||||
:BUILD_ORDER,
|
||||
:CANCEL_BUILD_ORDER,
|
||||
:BUILD_ORDER_COMPLETE,
|
||||
:CONSTRUCT,
|
||||
:CANCEL_CONSTRUCTION,
|
||||
:CONSTRUCTION_COMPLETE,
|
||||
|
||||
:BUILD_UNIT,
|
||||
:CANCEL_BUILD_UNIT,
|
||||
:BUILD_UNIT_COMPLETE,
|
||||
|
||||
:BUILDING_SET_WAYPOINT,
|
||||
:BUILDING_POWER_STATE,
|
||||
:BUILDING_REPAIR,
|
||||
:REPAIR_BUILDING,
|
||||
:CANCEL_BUILDING_REPAIR,
|
||||
:BUILDING_SELL,
|
||||
|
||||
:MESSAGE_BROADCAST,
|
||||
|
||||
18
lib/orders/build_unit.rb
Normal file
18
lib/orders/build_unit.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
IMICRTS::Order.define_handler(IMICRTS::Order::BUILD_UNIT, arguments: [:player_id, :entity_id, :unit_type]) do |order, director|
|
||||
director.player(order.player_id).entity(order.entity_id).component(:build_queue)&.add(order.unit_type)
|
||||
end
|
||||
|
||||
IMICRTS::Order.define_serializer(IMICRTS::Order::BUILD_UNIT) do |order, director|
|
||||
# Order ID | Player ID | Entity ID | Unit Type
|
||||
# char | char | integer | string
|
||||
|
||||
[IMICRTS::Order::BUILD_UNIT, order.player_id, order.entity_id, order.unit_type.to_s].pack("CCNA*")
|
||||
end
|
||||
|
||||
IMICRTS::Order.define_deserializer(IMICRTS::Order::BUILD_UNIT) do |string, director|
|
||||
# String fed into deserializer has Order ID removed
|
||||
# Player ID |
|
||||
# char | integer | string
|
||||
data = string.unpack("CNA*")
|
||||
[data[0], data[1], data[2].to_sym]
|
||||
end
|
||||
25
lib/orders/build_unit_complete.rb
Normal file
25
lib/orders/build_unit_complete.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
IMICRTS::Order.define_handler(IMICRTS::Order::BUILD_UNIT_COMPLETE, arguments: [:player_id, :entity_id]) do |order, director|
|
||||
entity = director.player(order.player_id).entity(order.entity_id)
|
||||
item = entity.component(:build_queue).queue.shift
|
||||
|
||||
spawn_point = entity.position.clone
|
||||
spawn_point.y += 96 # TODO: Use entity defined spawnpoint
|
||||
|
||||
ent = entity.director.spawn_entity(player_id: entity.player.id, name: item.entity.name, position: spawn_point)
|
||||
ent.target = entity.component(:waypoint).waypoint if entity.component(:waypoint)
|
||||
end
|
||||
|
||||
IMICRTS::Order.define_serializer(IMICRTS::Order::BUILD_UNIT_COMPLETE) do |order, director|
|
||||
# Order ID | Player ID
|
||||
# char | char
|
||||
|
||||
[IMICRTS::Order::BUILD_UNIT_COMPLETE, order.player_id, order.entity_id].pack("CCN")
|
||||
end
|
||||
|
||||
IMICRTS::Order.define_deserializer(IMICRTS::Order::BUILD_UNIT_COMPLETE) do |string, director|
|
||||
# String fed into deserializer has Order ID removed
|
||||
# Player ID | Entity ID
|
||||
# char | integer
|
||||
data = string.unpack("CN")
|
||||
[data[0], data[1]]
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
IMICRTS::Order.define_handler(IMICRTS::Order::BUILD_ORDER, arguments: [:player_id, :vector, :building]) do |order, director|
|
||||
IMICRTS::Order.define_handler(IMICRTS::Order::CONSTRUCT, arguments: [:player_id, :vector, :building]) do |order, director|
|
||||
tile = director.map.tile_at(order.vector.x, order.vector.y)
|
||||
position = tile.position + director.map.tile_size / 2
|
||||
|
||||
@@ -20,14 +20,14 @@ IMICRTS::Order.define_handler(IMICRTS::Order::BUILD_ORDER, arguments: [:player_i
|
||||
end
|
||||
end
|
||||
|
||||
IMICRTS::Order.define_serializer(IMICRTS::Order::BUILD_ORDER) do |order, director|
|
||||
IMICRTS::Order.define_serializer(IMICRTS::Order::CONSTRUCT) do |order, director|
|
||||
# Order ID | Player ID | Vector X | Vector Y | Entity Name
|
||||
# char | char | integer | integer | string
|
||||
|
||||
[IMICRTS::Order::BUILD_ORDER, order.player_id, order.vector.x, order.vector.y, order.building.to_s].pack("CCNNA*")
|
||||
[IMICRTS::Order::CONSTRUCT, order.player_id, order.vector.x, order.vector.y, order.building.to_s].pack("CCNNA*")
|
||||
end
|
||||
|
||||
IMICRTS::Order.define_deserializer(IMICRTS::Order::BUILD_ORDER) do |string, director|
|
||||
IMICRTS::Order.define_deserializer(IMICRTS::Order::CONSTRUCT) do |string, director|
|
||||
# String fed into deserializer has Order ID removed
|
||||
# Player ID | Vector X | Vector Y | Entity Name
|
||||
# char | integer | integer | string
|
||||
@@ -147,7 +147,6 @@ class IMICRTS
|
||||
# DOWN
|
||||
add_node create_node(@current_node.tile.grid_position.x, @current_node.tile.grid_position.y + 1, @current_node)
|
||||
|
||||
# TODO: Add diagonal nodes, if requested
|
||||
if @allow_diagonal
|
||||
# LEFT-UP
|
||||
if node_above? && node_above_left?
|
||||
|
||||
@@ -4,7 +4,7 @@ class IMICRTS
|
||||
@title = Gosu::Font.new(56, name: "Noto Sans Display", bold: true)
|
||||
@text = Gosu::Font.new(18, name: "Noto Sans Thaana", bold: true)
|
||||
@name = IMICRTS::NAME
|
||||
@logo = Gosu::Image.new("#{ASSETS_PATH}/logo.png")
|
||||
@logo = get_image("#{ASSETS_PATH}/logo.png")
|
||||
|
||||
@messages = ["Loading", "Compiling Protons", "Launching Warhead", "git push origin --force"]
|
||||
@messages_index = 0
|
||||
|
||||
@@ -2,7 +2,7 @@ class IMICRTS
|
||||
class Closing < CyberarmEngine::GuiState
|
||||
def setup
|
||||
window.show_cursor = false
|
||||
@logo = Gosu::Image.new("#{ASSETS_PATH}/logo.png")
|
||||
@logo = get_image("#{ASSETS_PATH}/logo.png")
|
||||
@color = Gosu::Color.new(0xffffffff)
|
||||
|
||||
@started_at = Gosu.milliseconds
|
||||
|
||||
@@ -41,7 +41,7 @@ class IMICRTS
|
||||
player_id: player.id, name: :construction_yard,
|
||||
position: CyberarmEngine::Vector.new(player.spawnpoint.x, player.spawnpoint.y, ZOrder::BUILDING)
|
||||
)
|
||||
construction_yard.component(:building).data.construction_progress = 100
|
||||
construction_yard.component(:building).data.construction_progress = Entity.get(construction_yard.name).build_steps
|
||||
@director.each_tile(@director.map.world_to_grid(construction_yard.position), construction_yard.name) do |tile, space_required|
|
||||
if space_required == true
|
||||
tile.entity = construction_yard
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
class IMICRTS
|
||||
class Tool
|
||||
include CyberarmEngine::Common
|
||||
|
||||
@@tools = {}
|
||||
def self.get(tool)
|
||||
@@tools.dig(tool)
|
||||
|
||||
@@ -3,14 +3,17 @@ class IMICRTS
|
||||
class EntityController < Tool
|
||||
def setup
|
||||
@drag_start = CyberarmEngine::Vector.new
|
||||
@box_color = 0xaa99ff99
|
||||
@box_border_size = 2
|
||||
end
|
||||
|
||||
def draw
|
||||
Gosu.draw_rect(
|
||||
@box.min.x, @box.min.y,
|
||||
@box.width, @box.height,
|
||||
Gosu::Color.rgba(50, 50, 50, 150), ZOrder::SELECTION_BOX
|
||||
) if @box
|
||||
return unless @box
|
||||
|
||||
Gosu.draw_rect(@box.min.x, @box.min.y, @box.width, @box_border_size, @box_color, ZOrder::SELECTION_BOX)
|
||||
Gosu.draw_rect(@box.min.x + @box.width, @box.min.y, @box_border_size, @box.height, @box_color, ZOrder::SELECTION_BOX)
|
||||
Gosu.draw_rect(@box.min.x, @box.min.y + @box.height, @box.width, @box_border_size, @box_color, ZOrder::SELECTION_BOX)
|
||||
Gosu.draw_rect(@box.min.x, @box.min.y, @box_border_size, @box.height, @box_color, ZOrder::SELECTION_BOX)
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -40,16 +43,16 @@ class IMICRTS
|
||||
@selection_start = @player.camera.transform(@game.window.mouse)
|
||||
end
|
||||
when Gosu::MS_RIGHT
|
||||
if @player.selected_entities.size > 0
|
||||
unless @player.selected_entities.empty?
|
||||
if @player.selected_entities.any? { |ent| ent.component(:movement) }
|
||||
@director.schedule_order(Order::MOVE, @player.id, @player.camera.transform(@game.window.mouse))
|
||||
|
||||
@game.overlays << Game::Overlay.new(Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/cursors/move.png"), @player.camera.transform(@game.window.mouse), 0, 255)
|
||||
@game.overlays << Game::Overlay.new(get_image("#{IMICRTS::ASSETS_PATH}/cursors/move.png"), @player.camera.transform(@game.window.mouse), 0, 255)
|
||||
@game.overlays.last.position.z = ZOrder::OVERLAY
|
||||
elsif @player.selected_entities.size == 1 && @player.selected_entities.first.component(:waypoint)
|
||||
@director.schedule_order(Order::BUILDING_SET_WAYPOINT, @player.id, @player.selected_entities.first.id, @player.camera.transform(@game.window.mouse))
|
||||
|
||||
@game.overlays << Game::Overlay.new(Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/cursors/move.png"), @player.camera.transform(@game.window.mouse), 0, 255)
|
||||
@game.overlays << Game::Overlay.new(get_image("#{IMICRTS::ASSETS_PATH}/cursors/move.png"), @player.camera.transform(@game.window.mouse), 0, 255)
|
||||
@game.overlays.last.position.z = ZOrder::OVERLAY
|
||||
end
|
||||
end
|
||||
@@ -63,11 +66,13 @@ class IMICRTS
|
||||
@box = nil
|
||||
@selection_start = nil
|
||||
|
||||
return if @game.sidebar.hit?(@game.window.mouse_x, @game.window.mouse_y)
|
||||
|
||||
diff = (@player.selected_entities - @game.selected_entities)
|
||||
@game.sidebar_actions.clear
|
||||
|
||||
@director.schedule_order(Order::DESELECTED_UNITS, @player.id, diff) if diff.size > 0
|
||||
if @game.selected_entities.size > 0
|
||||
@director.schedule_order(Order::DESELECTED_UNITS, @player.id, diff) if diff.size.positive?
|
||||
if @game.selected_entities.size.positive?
|
||||
@director.schedule_order(Order::SELECTED_UNITS, @player.id, @game.selected_entities)
|
||||
else
|
||||
pick_entity
|
||||
@@ -79,7 +84,7 @@ class IMICRTS
|
||||
@game.sidebar_actions.clear do
|
||||
ent.component(:sidebar_actions).actions.each do |action|
|
||||
@game.button action.label, tip: action.description, width: 1.0 do
|
||||
action.block.call if action.block
|
||||
action.block&.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,11 +30,10 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def update
|
||||
# TODO: ensure that construction worker is alive
|
||||
cancel_tool if @construction_worker.die?
|
||||
cancel_tool unless @construction_worker.player.entity(@construction_worker.id)
|
||||
vector = vector_to_grid(@game.window.mouse)
|
||||
|
||||
if tile = @director.map.tile_at(vector.x, vector.y)
|
||||
if (tile = @director.map.tile_at(vector.x, vector.y))
|
||||
position = tile.position.clone
|
||||
@preview.position = position + @director.map.tile_size / 2
|
||||
@preview.position.z = ZOrder::OVERLAY
|
||||
@@ -58,7 +57,7 @@ class IMICRTS
|
||||
# position: CyberarmEngine::Vector.new(position.x, position.y, ZOrder::BUILDING)
|
||||
# )
|
||||
|
||||
@director.schedule_order(Order::BUILD_ORDER, @player.id, vector, @entity)
|
||||
@director.schedule_order(Order::CONSTRUCT, @player.id, vector, @entity)
|
||||
|
||||
# each_tile(vector) do |tile, space_required|
|
||||
# if space_required == true
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class IMICRTS
|
||||
class Window < CyberarmEngine::Window
|
||||
attr_reader :mouse
|
||||
|
||||
def setup
|
||||
@last_update_time = Gosu.milliseconds
|
||||
@mouse = CyberarmEngine::Vector.new
|
||||
@cursor = Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/cursors/pointer.png")
|
||||
@cursor = get_image("#{IMICRTS::ASSETS_PATH}/cursors/pointer.png")
|
||||
|
||||
self.caption = "#{IMICRTS::NAME} (#{IMICRTS::VERSION} #{IMICRTS::VERSION_NAME})"
|
||||
if ARGV.join.include?("--debug-game")
|
||||
@@ -14,6 +15,10 @@ class IMICRTS
|
||||
else
|
||||
push_state(Boot)
|
||||
end
|
||||
|
||||
# TODO: Jukebox
|
||||
s = get_song("#{GAME_ROOT_PATH}/assets/audio/music/EmptyCity.ogg")
|
||||
s.play(true)
|
||||
end
|
||||
|
||||
def draw
|
||||
@@ -23,14 +28,16 @@ class IMICRTS
|
||||
end
|
||||
|
||||
def update
|
||||
@mouse.x, @mouse.y = self.mouse_x, self.mouse_y
|
||||
@mouse.x = mouse_x
|
||||
@mouse.y = mouse_y
|
||||
|
||||
super
|
||||
|
||||
@last_update_time = Gosu.milliseconds
|
||||
end
|
||||
|
||||
def needs_cursor?
|
||||
return false
|
||||
false
|
||||
end
|
||||
|
||||
def close
|
||||
|
||||
Reference in New Issue
Block a user