diff --git a/i-mic-rts.rb b/i-mic-rts.rb index 361bc99..af25eb3 100755 --- a/i-mic-rts.rb +++ b/i-mic-rts.rb @@ -40,6 +40,7 @@ require_relative "lib/order" require_relative "lib/friendly_hash" require_relative "lib/director" require_relative "lib/player" +require_relative "lib/entity_controller" require_relative "lib/connection" require_relative "lib/networking/protocol" diff --git a/lib/camera.rb b/lib/camera.rb index 4549423..bdda513 100644 --- a/lib/camera.rb +++ b/lib/camera.rb @@ -97,15 +97,13 @@ class IMICRTS end def move_to(x, y, zoom) + @velocity *= 0.0 @position.x, @position.y = x, y @zoom = zoom end def button_down(id) case id - when Gosu::KB_H - @position.x, @position.y = 0.0, 0.0 - @velocity *= 0.0 when Gosu::MS_WHEEL_UP @zoom = (@zoom + 0.25).clamp(@min_zoom, @max_zoom) when Gosu::MS_WHEEL_DOWN diff --git a/lib/director.rb b/lib/director.rb index 9bd7eee..5c1d048 100644 --- a/lib/director.rb +++ b/lib/director.rb @@ -100,6 +100,18 @@ class IMICRTS end end + def spawn_entity(player_id:, name:, position:) + _player = player(player_id) + _player.entities << Entity.new( + name: name, + director: self, + player: _player, + id: _player.next_entity_id, + position: position, + angle: 0 + ) + end + def entities @players.map { |player| player.entities }.flatten diff --git a/lib/entity_controller.rb b/lib/entity_controller.rb new file mode 100644 index 0000000..ec58d80 --- /dev/null +++ b/lib/entity_controller.rb @@ -0,0 +1,86 @@ +class IMICRTS + # Handles entity de/selection and order manipulation + class EntityController + attr_reader :selected_entities + def initialize(game:, director:, player:) + @game = game + @director = director + @player = player + + @drag_start = CyberarmEngine::Vector.new + @selected_entities = [] + 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 + end + + def update + if @selection_start + select_entities + end + end + + def button_down(id) + case id + when Gosu::KB_H + ent = @player.entities.find { |ent| ent.name == :construction_yard } + ent ||= @player.entities.find { |ent| ent.name == :construction_worker } + ent ||= @player.starting_position + + @player.camera.move_to( + @game.window.width / 2 - ent.position.x, + @game.window.height / 2 - ent.position.y, + @player.camera.zoom + ) + + when Gosu::KB_S + @director.schedule_order(Order::STOP, @player.id) + + when Gosu::MS_LEFT + unless @game.sidebar.hit?(@game.window.mouse_x, @game.window.mouse_y) + @selection_start = @player.camera.transform(@game.window.mouse) + end + when Gosu::MS_RIGHT + @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.last.position.z = ZOrder::OVERLAY + end + end + + def button_up(id) + case id + when Gosu::MS_RIGHT + when Gosu::MS_LEFT + @box = nil + @selection_start = nil + + diff = (@player.selected_entities - @selected_entities) + + @director.schedule_order(Order::DESELECTED_UNITS, @player.id, diff) + @director.schedule_order(Order::SELECTED_UNITS, @player.id, @selected_entities) + end + end + + def select_entities + transform = @player.camera.transform(@game.window.mouse) + @box = CyberarmEngine::BoundingBox.new(@selection_start.xy, transform.xy) + + selected_entities = @player.entities.select do |ent| + @box.point?(ent.position) || + @box.point?(ent.position - ent.radius) || @box.point?(ent.position + ent.radius) + end + + if Gosu.button_down?(Gosu::KB_LEFT_SHIFT) || Gosu.button_down?(Gosu::KB_RIGHT_SHIFT) + @selected_entities = @selected_entities.union(selected_entities) + else + @selected_entities = selected_entities + end + end + end +end \ No newline at end of file diff --git a/lib/particle_emitter.rb b/lib/particle_emitter.rb index 17e0cc4..284e2ed 100644 --- a/lib/particle_emitter.rb +++ b/lib/particle_emitter.rb @@ -88,6 +88,5 @@ class IMICRTS end Dir.glob("#{IMICRTS::GAME_ROOT_PATH}/lib/particle_emitters/**/*.rb").each do |emitter| - p emitter require_relative emitter end \ No newline at end of file diff --git a/lib/states/game.rb b/lib/states/game.rb index 48e1e9e..6652e77 100644 --- a/lib/states/game.rb +++ b/lib/states/game.rb @@ -1,14 +1,16 @@ class IMICRTS class Game < CyberarmEngine::GuiState Overlay = Struct.new(:image, :position, :angle, :alpha) + + attr_reader :sidebar, :overlays def setup window.show_cursor = true @options[:networking_mode] ||= :host @player = Player.new(id: 0) @director = Director.new(map: Map.new(map_file: "maps/test_map.tmx"), networking_mode: @options[:networking_mode], players: [@player]) + @entity_controller = EntityController.new(game: self, director: @director, player: @player) - @selected_entities = [] @overlays = [] @debug_info = CyberarmEngine::Text.new("", y: 10, z: Float::INFINITY, shadow_color: Gosu::Color.rgba(0, 0, 0, 200)) @@ -67,62 +69,40 @@ class IMICRTS # 100.times { |i| [@c, @h, @t].sample.instance_variable_get("@block").call } spawnpoint = @director.map.spawnpoints.last - @player.entities << Entity.new( - name: :construction_yard, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x, spawnpoint.y, ZOrder::BUILDING), - angle: 0 - ) - @player.entities << Entity.new( - name: :construction_worker, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x - 64, spawnpoint.y + 64, ZOrder::GROUND_VEHICLE), - angle: 0 - ) - @player.entities << Entity.new( - name: :power_plant, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x + 64, spawnpoint.y + 64, ZOrder::BUILDING), - angle: 0 - ) - @player.entities << Entity.new( - name: :refinery, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x + 130, spawnpoint.y + 64, ZOrder::BUILDING), - angle: 0 - ) - @player.entities << Entity.new( - name: :war_factory, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x + 130, spawnpoint.y - 64, ZOrder::BUILDING), - angle: 0 - ) - @player.entities << Entity.new( - name: :helipad, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x - 32, spawnpoint.y - 96, ZOrder::BUILDING), - angle: 0 - ) - @player.entities << Entity.new( - name: :barracks, - director: @director, - player: @player, - id: @player.next_entity_id, - position: CyberarmEngine::Vector.new(spawnpoint.x - 32, spawnpoint.y + 128, ZOrder::BUILDING), - angle: 0 - ) + @director.spawn_entity( + player_id: @player.id, name: :construction_yard, + position: CyberarmEngine::Vector.new(spawnpoint.x, spawnpoint.y, ZOrder::BUILDING) + ) + + @director.spawn_entity( + player_id: @player.id, name: :construction_worker, + position: CyberarmEngine::Vector.new(spawnpoint.x - 64, spawnpoint.y + 64, ZOrder::GROUND_VEHICLE) + ) + + @director.spawn_entity( + player_id: @player.id, name: :power_plant, + position: CyberarmEngine::Vector.new(spawnpoint.x + 64, spawnpoint.y + 64, ZOrder::BUILDING) + ) + + @director.spawn_entity( + player_id: @player.id, name: :refinery, + position: CyberarmEngine::Vector.new(spawnpoint.x + 130, spawnpoint.y + 64, ZOrder::BUILDING) + ) + + @director.spawn_entity( + player_id: @player.id, name: :war_factory, + position: CyberarmEngine::Vector.new(spawnpoint.x + 130, spawnpoint.y - 64, ZOrder::BUILDING) + ) + + @director.spawn_entity( + player_id: @player.id, name: :helipad, + position: CyberarmEngine::Vector.new(spawnpoint.x - 32, spawnpoint.y - 96, ZOrder::BUILDING) + ) + + @director.spawn_entity( + player_id: @player.id, name: :barracks, + position: CyberarmEngine::Vector.new(spawnpoint.x - 32, spawnpoint.y + 128, ZOrder::BUILDING) + ) end def draw @@ -133,7 +113,7 @@ class IMICRTS @player.camera.draw do @director.map.draw(@player.camera) @director.entities.each(&:draw) - @selected_entities.each(&:selected_draw) + @entity_controller.selected_entities.each(&:selected_draw) @overlays.each do |overlay| overlay.image.draw_rot(overlay.position.x, overlay.position.y, overlay.position.z, overlay.angle, 0.5, 0.5, 1, 1, Gosu::Color.rgba(255, 255, 255, overlay.alpha)) @@ -143,7 +123,7 @@ class IMICRTS @overlays.delete(overlay) if overlay.alpha <= 0 end - 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 + @entity_controller.draw end @debug_info.draw if Setting.enabled?(:debug_info_bar) @@ -154,10 +134,7 @@ class IMICRTS @director.update @player.camera.update - - if @selection_start - select_entities - end + @entity_controller.update mouse = @player.camera.transform(window.mouse) tile = @director.map.tile_at(mouse.x / @director.map.tile_size, mouse.y / @director.map.tile_size) @@ -184,57 +161,17 @@ class IMICRTS def button_down(id) super - case id - when Gosu::KB_S - @director.schedule_order(Order::STOP, @player.id) - - when Gosu::MS_LEFT - unless @sidebar.hit?(window.mouse_x, window.mouse_y) - @selection_start = @player.camera.transform(window.mouse) - end - when Gosu::MS_RIGHT - @director.schedule_order(Order::MOVE, @player.id, @player.camera.transform(window.mouse)) - - @overlays << Overlay.new(Gosu::Image.new("#{IMICRTS::ASSETS_PATH}/cursors/move.png"), @player.camera.transform(window.mouse), 0, 255) - @overlays.last.position.z = ZOrder::OVERLAY - end - + @entity_controller.button_down(id) @player.camera.button_down(id) unless @sidebar.hit?(window.mouse_x, window.mouse_y) end def button_up(id) super - case id - when Gosu::MS_RIGHT - when Gosu::MS_LEFT - @box = nil - @selection_start = nil - - diff = (@player.selected_entities - @selected_entities) - - @director.schedule_order(Order::DESELECTED_UNITS, @player.id, diff) - @director.schedule_order(Order::SELECTED_UNITS, @player.id, @selected_entities) - end - + @entity_controller.button_up(id) @player.camera.button_up(id) end - def select_entities - @box = CyberarmEngine::BoundingBox.new(@selection_start, @player.camera.transform(window.mouse)) - - selected_entities = @player.entities.select do |ent| - @box.point?(ent.position - ent.radius) || - @box.point?(ent.position + ent.radius) - end - - if Gosu.button_down?(Gosu::KB_LEFT_SHIFT) || Gosu.button_down?(Gosu::KB_RIGHT_SHIFT) - @selected_entities = @selected_entities.union(selected_entities) - else - @selected_entities = selected_entities - end - end - def finalize @director.finalize end