From 51db2dc5b840fc2d485d2a59358e8392969e05e8 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Tue, 1 Oct 2019 08:25:02 -0500 Subject: [PATCH] Implemented Zoom --- lib/camera.rb | 34 ++++++++++++++++++++++++++++------ lib/states/closing.rb | 4 ++-- lib/states/game.rb | 26 ++++++++++++++------------ lib/window.rb | 4 ++++ 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/lib/camera.rb b/lib/camera.rb index 5e11a2b..d6f0070 100644 --- a/lib/camera.rb +++ b/lib/camera.rb @@ -1,12 +1,17 @@ class IMICRTS class Camera - attr_reader :position, :velocity, :drag + attr_reader :position, :velocity, :zoom, :drag def initialize(scroll_speed: 10, position: CyberarmEngine::Vector.new(0.0, 0.0)) @scroll_speed = scroll_speed @position = position @velocity = CyberarmEngine::Vector.new(0.0, 0.0) - @drag = 0.8 + @zoom = 1.0 + @min_zoom = 0.25 + @max_zoom = 4.0 + + @drag = 0.8 # Used to arrest velocity + @grab_drag = 0.5 # Used when camera is panned using middle mouse button end def window; $window; end @@ -14,7 +19,10 @@ class IMICRTS def draw(&block) if block Gosu.translate(@position.x, @position.y) do - block.call + center_point = center + Gosu.scale(@zoom, @zoom, center.x, center.y) do + block.call + end end end end @@ -26,8 +34,18 @@ class IMICRTS @position += @velocity * @scroll_speed end + def mouse_pick(x, y) + mouse = CyberarmEngine::Vector.new(x, y) + + normalized = (mouse / @zoom - @position / @zoom) * @zoom + normalized.x = normalized.x.floor + normalized.y = normalized.y.floor + + return normalized + end + def center - CyberarmEngine::Vector.new(window.width / 2, window.height / 2) - @position + (CyberarmEngine::Vector.new(window.width / 2, window.height / 2) / @zoom - @position / @zoom) * @zoom end def center_around(vector, factor) @@ -48,7 +66,7 @@ class IMICRTS if @drag_start @velocity *= 0.0 - @position = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @drag_start + @position = lerp(@position, CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @drag_start, @grab_drag) end end @@ -57,9 +75,13 @@ class IMICRTS 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 + @zoom = (@zoom - 0.25).clamp(@min_zoom, @max_zoom) when Gosu::MS_MIDDLE @position_start = @position.clone - @drag_start = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @position + @drag_start = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) end end diff --git a/lib/states/closing.rb b/lib/states/closing.rb index 7acc861..768fe8c 100644 --- a/lib/states/closing.rb +++ b/lib/states/closing.rb @@ -18,11 +18,11 @@ class IMICRTS factor = (1.0 - ((Gosu.milliseconds - @started_at) / @close_time.to_f)).clamp(0.0, 1.0) @color.alpha = 255 * (factor - 0.1) - window.close if Gosu.milliseconds - @started_at >= @close_time + window.close! if Gosu.milliseconds - @started_at >= @close_time end def button_up(id) - window.close if id == Gosu::KB_ESCAPE + window.close! end end end \ No newline at end of file diff --git a/lib/states/game.rb b/lib/states/game.rb index d464a4d..9b29c96 100644 --- a/lib/states/game.rb +++ b/lib/states/game.rb @@ -6,19 +6,18 @@ class IMICRTS @mouse_pos = CyberarmEngine::Text.new("X: 0\nY: 0", x: 500, y: 10, z: Float::INFINITY) @sidebar = stack(height: 1.0) do - background [0xff555555, Gosu::Color::GRAY] + background [0x55555555, 0x55666666] - label "SIDEBAR", text_size: 78 - label "" + label "SIDEBAR", text_size: 78, margin_bottom: 20 - button("Harvest", width: 1.0) do + @h = button("Harvester", width: 1.0) do @units << Entity.new( images: Gosu::Image.new("assets/vehicles/harvester/images/harvester.png", retro: true), position: CyberarmEngine::Vector.new(rand(window.width), rand(window.height), ZOrder::GROUND_VEHICLE), angle: rand(360) ) end - button("Construction Worker", width: 1.0) do + @c = button("Construction Worker", width: 1.0) do @units << Entity.new( images: Gosu::Image.new("assets/vehicles/construction_worker/images/construction_worker.png", retro: true), position: CyberarmEngine::Vector.new(rand(window.width), rand(window.height), ZOrder::GROUND_VEHICLE), @@ -27,11 +26,13 @@ class IMICRTS end - button("Leave", width: 1.0) do + button("Leave", width: 1.0, margin_top: 20) do finalize push_state(MainMenu) end end + + 100.times { |i| [@c, @h].sample.instance_variable_get("@block").call } end def draw @@ -43,10 +44,10 @@ class IMICRTS @units.each(&:draw) draw_rect(@anchor.x - 10, @anchor.y - 10, 20, 20, Gosu::Color::RED, Float::INFINITY) if @anchor - # draw_rect(@camera.center.x - 10, @camera.center.y - 10, 20, 20, Gosu::Color::BLACK, Float::INFINITY) + draw_rect(@camera.center.x - 10, @camera.center.y - 10, 20, 20, Gosu::Color::BLACK, Float::INFINITY) - # mouse_center = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @camera.position - # draw_rect(mouse_center.x - 10, mouse_center.y - 10, 20, 20, Gosu::Color::YELLOW, Float::INFINITY) + 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) end @mouse_pos.draw @@ -61,7 +62,8 @@ class IMICRTS @camera.center_around(@anchor, 0.9) end - @mouse_pos.text = "X: #{window.mouse_x}\nY: #{window.mouse_y}" + mouse = @camera.mouse_pick(window.mouse_x, window.mouse_y) + @mouse_pos.text = "Zoom: #{@camera.zoom}\nX: #{window.mouse_x}\nY: #{window.mouse_y}\n\nX: #{mouse.x}\nY: #{mouse.y}" end def button_down(id) @@ -70,12 +72,12 @@ class IMICRTS case id when Gosu::MS_LEFT unless @sidebar.hit?(window.mouse_x, window.mouse_y) - @anchor = CyberarmEngine::Vector.new(window.mouse_x, window.mouse_y) - @camera.position + @anchor = @camera.mouse_pick(window.mouse_x, window.mouse_y) end when Gosu::MS_RIGHT @anchor = nil end - @camera.button_down(id) + @camera.button_down(id) unless @sidebar.hit?(window.mouse_x, window.mouse_y) end def button_up(id) diff --git a/lib/window.rb b/lib/window.rb index a6b8364..9783e9b 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -14,6 +14,10 @@ class IMICRTS @last_update_time = Gosu.milliseconds end + def close + push_state(Closing) unless current_state.is_a?(Closing) + end + def delta_time Gosu.milliseconds - @last_update_time end