From 0c22996b9f88d1fcf9b9acf9bb063208dc2001ec Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Thu, 3 Oct 2019 17:19:59 -0500 Subject: [PATCH] Stubbed Map, implemented optimized Map tile rendering, made Camera viewport explicitly defined --- i-mic-rts.rb | 1 + lib/camera.rb | 32 ++++++++++++++++++------ lib/director.rb | 2 +- lib/map.rb | 62 ++++++++++++++++++++++++++++++++++++++++++++++ lib/player.rb | 2 +- lib/states/game.rb | 8 +++--- 6 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 lib/map.rb diff --git a/i-mic-rts.rb b/i-mic-rts.rb index 58eb75b..8969202 100644 --- a/i-mic-rts.rb +++ b/i-mic-rts.rb @@ -22,6 +22,7 @@ require_relative "lib/states/menus/multiplayer_lobby_menu" require_relative "lib/zorder" require_relative "lib/entity" # require_relative "lib/entities/" +require_relative "lib/map" require_relative "lib/order" require_relative "lib/friendly_hash" diff --git a/lib/camera.rb b/lib/camera.rb index 4b91e9a..e8808ea 100644 --- a/lib/camera.rb +++ b/lib/camera.rb @@ -1,7 +1,8 @@ class IMICRTS class Camera - attr_reader :position, :velocity, :zoom, :drag - def initialize(scroll_speed: 10, position: CyberarmEngine::Vector.new(0.0, 0.0)) + attr_reader :viewport, :position, :velocity, :zoom, :drag + def initialize(viewport:, scroll_speed: 10, position: CyberarmEngine::Vector.new(0.0, 0.0)) + @viewport = CyberarmEngine::BoundingBox.new(viewport[0], viewport[1], viewport[2], viewport[3]) @scroll_speed = scroll_speed @position = position @velocity = CyberarmEngine::Vector.new(0.0, 0.0) @@ -16,12 +17,14 @@ class IMICRTS def window; $window; end - def draw(*args, &block) + def draw(&block) if block - center_point = center - Gosu.translate(@position.x, @position.y) do - Gosu.scale(@zoom, @zoom, center.x, center.y) do - block.call + 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 end end end @@ -34,6 +37,9 @@ class IMICRTS @velocity *= @drag @position += @velocity * @scroll_speed + + @viewport.max.x = window.width + @viewport.max.y = window.height end def mouse_pick(x, y) @@ -55,6 +61,18 @@ class IMICRTS @position += center.lerp(vector, factor) * window.dt end + 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 + else + pp object.class + exit + end + end + def aspect_ratio window.height / window.width.to_f end diff --git a/lib/director.rb b/lib/director.rb index 7afa055..47f8ae8 100644 --- a/lib/director.rb +++ b/lib/director.rb @@ -1,6 +1,6 @@ class IMICRTS class Director - attr_reader :current_tick + attr_reader :current_tick, :map def initialize(map:, players:, networking_mode: :virtual, tick_rate: 10) @map = map @players = players diff --git a/lib/map.rb b/lib/map.rb new file mode 100644 index 0000000..6e0ce34 --- /dev/null +++ b/lib/map.rb @@ -0,0 +1,62 @@ +class IMICRTS + class Map + Tile = Struct.new(:position, :color, :size) + + def initialize(width:, height:, tile_size: 32) + @width, @height = width, height + @tile_size = tile_size + + @tiles = [] + + height.times do |y| + width.times do |x| + @tiles.push( + 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 + ) + ) + end + end + end + + 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 + ) + end + end + + def visible_tiles(camera) + _tiles = [] + + top_left = camera.center - CyberarmEngine::Vector.new($window.width / 2, $window.height / 2) / camera.zoom + top_left.x = top_left.x.ceil + top_left.y = top_left.y.ceil + + top_left /= @tiles.first.size + + # +1 to overdraw a bit to hide pop-in + _width = ($window.width / @tile_size) + 1 + _height = ($window.height / @tile_size) + 1 + + _height.times do |y| + _width.times do |x| + if tile = tile_at(x + top_left.x, y + top_left.y) + _tiles.push(tile) + end + end + end + + return _tiles + end + + def tile_at(x, y) + @tiles[x + y * @width] + end + end +end \ No newline at end of file diff --git a/lib/player.rb b/lib/player.rb index 09f3a0f..142f487 100644 --- a/lib/player.rb +++ b/lib/player.rb @@ -8,7 +8,7 @@ class IMICRTS @entities = [] @orders = [] - @camera = Camera.new + @camera = Camera.new(viewport: [0, 0, $window.width, $window.height]) @selected_entities = [] @current_entity_id = 0 diff --git a/lib/states/game.rb b/lib/states/game.rb index 03c98d7..09f5068 100644 --- a/lib/states/game.rb +++ b/lib/states/game.rb @@ -4,11 +4,11 @@ class IMICRTS window.show_cursor = true @player = Player.new(id: 0) - @director = Director.new(map: nil, players: [@player]) + @director = Director.new(map: Map.new(width: 256, height: 256), players: [@player]) @selected_entities = [] - @debug_info = CyberarmEngine::Text.new("X: 0\nY: 0", x: 500, y: 10, z: Float::INFINITY) + @debug_info = CyberarmEngine::Text.new("", y: 10, z: Float::INFINITY) @sidebar = stack(height: 1.0) do background [0x55555555, 0x55666666] @@ -55,7 +55,8 @@ class IMICRTS Gosu.draw_rect(0, 0, window.width, window.height, Gosu::Color.rgb(10, 175, 35)) - @player.camera.draw(0, 0, window.width, window.height) do + @player.camera.draw do + @director.map.draw(@player.camera) @director.entities.each(&:draw) @selected_entities.each(&:selected_draw) @@ -85,6 +86,7 @@ class IMICRTS mouse = @player.camera.mouse_pick(window.mouse_x, window.mouse_y) @debug_info.text = %( + FPS: #{Gosu.fps} Aspect Ratio: #{@player.camera.aspect_ratio} Zoom: #{@player.camera.zoom} Window Mouse X: #{window.mouse_x}