diff --git a/assets/tilesets/default.png b/assets/tilesets/default.png index b9942df..aaddf19 100644 Binary files a/assets/tilesets/default.png and b/assets/tilesets/default.png differ diff --git a/lib/camera.rb b/lib/camera.rb index e8808ea..fd20e85 100644 --- a/lib/camera.rb +++ b/lib/camera.rb @@ -21,18 +21,14 @@ class IMICRTS if block Gosu.clip_to(@viewport.min.x, @viewport.min.y, @viewport.max.x, @viewport.max.y) do center_point = center - Gosu.translate(@position.x, @position.y) do - Gosu.scale(@zoom, @zoom, center.x, center.y) do - block.call - end + Gosu.transform(*worldspace.elements) do + block.call end end end end def update - @zoom = 1.0 - move @velocity *= @drag @@ -42,14 +38,12 @@ class IMICRTS @viewport.max.y = window.height end - def mouse_pick(x, y) - mouse = CyberarmEngine::Vector.new(x, y) + def pick(vector) + inverse = (vector - @position) / @zoom + inverse.x = inverse.x.floor + inverse.y = inverse.y.floor - worldspace = (mouse - @position) / @zoom - worldspace.x = worldspace.x.floor - worldspace.y = worldspace.y.floor - - return worldspace + return inverse end def center @@ -61,6 +55,13 @@ class IMICRTS @position += center.lerp(vector, factor) * window.dt end + def worldspace + zoom_vector = CyberarmEngine::Vector.new(@zoom, @zoom) + position_matrix = CyberarmEngine::Matrix.translate(@position) + + CyberarmEngine::Matrix.concat(CyberarmEngine::Matrix.scale(zoom_vector, center), position_matrix) + end + def visible?(object) if object.is_a?(Map::Tile) object.position.x - object.size >= @viewport.min.x - @position.x && @@ -99,7 +100,7 @@ class IMICRTS when Gosu::MS_WHEEL_DOWN @zoom = (@zoom - 0.25).clamp(@min_zoom, @max_zoom) when Gosu::MS_MIDDLE - @drag_start = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @position + @drag_start = pick(CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y)) end end diff --git a/lib/map.rb b/lib/map.rb index 6e0ce34..81e20d1 100644 --- a/lib/map.rb +++ b/lib/map.rb @@ -1,11 +1,13 @@ class IMICRTS class Map - Tile = Struct.new(:position, :color, :size) + Tile = Struct.new(:position, :color, :image) def initialize(width:, height:, tile_size: 32) @width, @height = width, height @tile_size = tile_size + @tileset = Gosu::Image.load_tiles("#{ASSETS_PATH}/tilesets/default.png", tile_size, tile_size, retro: true) + @tiles = [] height.times do |y| @@ -14,7 +16,7 @@ class IMICRTS Tile.new( CyberarmEngine::Vector.new(x * @tile_size, y * @tile_size, ZOrder::TILE), Gosu::Color.rgb(rand(25), rand(150..200), rand(25)), - @tile_size + @tileset.sample ) ) end @@ -23,11 +25,7 @@ class IMICRTS def draw(camera) visible_tiles(camera).each do |tile| - Gosu.draw_rect( - tile.position.x, tile.position.y, - @tile_size, @tile_size, - tile.color, tile.position.z - ) + tile.image.draw(tile.position.x, tile.position.y, tile.position.z) end end @@ -38,10 +36,10 @@ class IMICRTS top_left.x = top_left.x.ceil top_left.y = top_left.y.ceil - top_left /= @tiles.first.size + top_left /= @tile_size # +1 to overdraw a bit to hide pop-in - _width = ($window.width / @tile_size) + 1 + _width = ($window.width / @tile_size) + 1 _height = ($window.height / @tile_size) + 1 _height.times do |y| diff --git a/lib/orders/selected_units.rb b/lib/orders/selected_units.rb index 65756b0..08c3aae 100644 --- a/lib/orders/selected_units.rb +++ b/lib/orders/selected_units.rb @@ -1,5 +1,5 @@ IMICRTS::Order.define_handler(IMICRTS::Order::SELECTED_UNITS, arguments: [:player_id, :ids]) do |order, director| director.player(order.player_id).selected_entities.clear - director.player(order.player_id).selected_entities.push(order.ids) + director.player(order.player_id).selected_entities.push(*order.ids) end diff --git a/lib/states/game.rb b/lib/states/game.rb index 09f5068..ac78f34 100644 --- a/lib/states/game.rb +++ b/lib/states/game.rb @@ -53,17 +53,20 @@ class IMICRTS def draw super - Gosu.draw_rect(0, 0, window.width, window.height, Gosu::Color.rgb(10, 175, 35)) + # Gosu.draw_rect(0, 0, window.width, window.height, Gosu::Color.rgb(10, 175, 35)) @player.camera.draw do @director.map.draw(@player.camera) @director.entities.each(&:draw) @selected_entities.each(&:selected_draw) - # draw_rect(@camera.center.x - 10, @camera.center.y - 10, 20, 20, Gosu::Color::BLACK, Float::INFINITY) + draw_rect(@player.camera.center.x - 10, @player.camera.center.y - 10, 20, 20, Gosu::Color::RED, Float::INFINITY) + + mouse = @player.camera.pick(window.mouse) + draw_rect(mouse.x - 10, mouse.y - 10, 20, 20, Gosu::Color::YELLOW, Float::INFINITY) + + draw_rect(@goal.x - 10, @goal.y - 10, 20, 20, Gosu::Color::WHITE, Float::INFINITY) if @goal - # mouse = @camera.mouse_pick(window.mouse_x, window.mouse_y) - # draw_rect(mouse.x - 10, mouse.y - 10, 20, 20, Gosu::Color::YELLOW, Float::INFINITY) Gosu.draw_rect(@box.min.x, @box.min.y, @box.width, @box.height, Gosu::Color.rgba(50, 50, 50, 150), Float::INFINITY) if @box end @@ -76,7 +79,7 @@ class IMICRTS @director.update @player.camera.update - @selected_entities.each do |ent| + @player.selected_entities.each do |ent| ent.rotate_towards(@goal) if @goal end @@ -84,13 +87,13 @@ class IMICRTS select_entities end - mouse = @player.camera.mouse_pick(window.mouse_x, window.mouse_y) + mouse = @player.camera.pick(window.mouse) @debug_info.text = %( FPS: #{Gosu.fps} Aspect Ratio: #{@player.camera.aspect_ratio} Zoom: #{@player.camera.zoom} - Window Mouse X: #{window.mouse_x} - Window Mouse Y: #{window.mouse_y} + Window Mouse X: #{window.mouse.x} + Window Mouse Y: #{window.mouse.y} World Mouse X: #{mouse.x} World Mouse Y: #{mouse.y} @@ -107,7 +110,7 @@ class IMICRTS case id when Gosu::MS_LEFT unless @sidebar.hit?(window.mouse_x, window.mouse_y) - @selection_start = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @player.camera.position + @selection_start = @player.camera.pick(window.mouse) end when Gosu::MS_RIGHT @anchor = nil @@ -120,7 +123,7 @@ class IMICRTS case id when Gosu::MS_RIGHT - @goal = @player.camera.mouse_pick(window.mouse_x, window.mouse_y) + @goal = @player.camera.pick(window.mouse) when Gosu::MS_LEFT @box = nil @selection_start = nil @@ -132,7 +135,7 @@ class IMICRTS end def select_entities - @box = CyberarmEngine::BoundingBox.new(@selection_start, CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @player.camera.position) + @box = CyberarmEngine::BoundingBox.new(@selection_start, @player.camera.pick(window.mouse)) selected_entities = @player.entities.select do |ent| @box.point?(ent.position - ent.radius) || diff --git a/lib/window.rb b/lib/window.rb index 46c90e6..56b25af 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -1,7 +1,9 @@ class IMICRTS class Window < CyberarmEngine::Engine + attr_reader :mouse def setup @last_update_time = Gosu.milliseconds + @mouse = CyberarmEngine::Vector.new self.caption = "#{IMICRTS::NAME} (#{IMICRTS::VERSION} #{IMICRTS::VERSION_NAME})" if ARGV.join.include?("--fast") @@ -14,6 +16,7 @@ class IMICRTS end def update + @mouse.x, @mouse.y = self.mouse_x, self.mouse_y super @last_update_time = Gosu.milliseconds