From ca73a2d8e814df23c232b45a976259a4ea33b24c Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Sun, 5 Jun 2022 09:19:30 -0500 Subject: [PATCH] Added all the callbacks to Window and GameState, removed all but one usage of global variables (). --- lib/cyberarm_engine/common.rb | 2 +- lib/cyberarm_engine/game_object.rb | 40 +++---- lib/cyberarm_engine/game_state.rb | 105 +++++++++++------- .../opengl/renderer/renderer.rb | 2 +- lib/cyberarm_engine/text.rb | 4 +- lib/cyberarm_engine/ui/dsl.rb | 6 +- lib/cyberarm_engine/ui/elements/container.rb | 22 +++- lib/cyberarm_engine/ui/elements/list_box.rb | 2 +- lib/cyberarm_engine/ui/gui_state.rb | 12 +- lib/cyberarm_engine/ui/theme.rb | 1 + lib/cyberarm_engine/window.rb | 79 ++++++++++--- 11 files changed, 178 insertions(+), 97 deletions(-) diff --git a/lib/cyberarm_engine/common.rb b/lib/cyberarm_engine/common.rb index 0691098..f11e997 100644 --- a/lib/cyberarm_engine/common.rb +++ b/lib/cyberarm_engine/common.rb @@ -95,7 +95,7 @@ module CyberarmEngine end def window - $window + CyberarmEngine::Window.instance end def control_down? diff --git a/lib/cyberarm_engine/game_object.rb b/lib/cyberarm_engine/game_object.rb index dbc25ac..e4cd6ec 100644 --- a/lib/cyberarm_engine/game_object.rb +++ b/lib/cyberarm_engine/game_object.rb @@ -7,7 +7,7 @@ module CyberarmEngine attr_reader :alpha def initialize(options = {}) - $window.current_state.add_game_object(self) if options[:auto_manage] || options[:auto_manage].nil? + window.current_state.add_game_object(self) if options[:auto_manage] || options[:auto_manage].nil? @options = options @image = options[:image] ? image(options[:image]) : nil @@ -55,9 +55,9 @@ module CyberarmEngine if $debug show_debug_heading - $window.draw_circle(@position.x, @position.y, radius, 9999, @debug_color) + Gosu.draw_circle(@position.x, @position.y, radius, 9999, @debug_color) if @debug_text.text != "" - $window.draw_rect(@debug_text.x - 10, (@debug_text.y - 10), @debug_text.width + 20, @debug_text.height + 20, + Gosu.draw_rect(@debug_text.x - 10, (@debug_text.y - 10), @debug_text.width + 20, @debug_text.height + 20, Gosu::Color.rgba(0, 0, 0, 200), 9999) @debug_text.draw end @@ -102,13 +102,13 @@ module CyberarmEngine end def _x_visible - x.between?(($window.width / 2) - @world_center_point.x, ($window.width / 2) + @world_center_point.x) || - x.between?((@world_center_point.x - $window.width / 2), ($window.width / 2) + @world_center_point.x) + x.between?((window.width / 2) - @world_center_point.x, (window.width / 2) + @world_center_point.x) || + x.between?((@world_center_point.x - window.width / 2), (window.width / 2) + @world_center_point.x) end def _y_visible - y.between?(($window.height / 2) - @world_center_point.y, ($window.height / 2) + @world_center_point.y) || - y.between?(@world_center_point.y - ($window.height / 2), ($window.height / 2) + @world_center_point.y) + y.between?((window.height / 2) - @world_center_point.y, (window.height / 2) + @world_center_point.y) || + y.between?(@world_center_point.y - (window.height / 2), (window.height / 2) + @world_center_point.y) end def heading(ahead_by = 100, _object = nil, angle_only = false) @@ -153,10 +153,6 @@ module CyberarmEngine @color = Gosu::Color.rgba(@color.red, @color.green, @color.blue, int) end - def draw_rect(x, y, width, height, color, z = 0) - $window.draw_rect(x, y, width, height, color, z) - end - def button_up(id) end @@ -190,12 +186,12 @@ module CyberarmEngine # Duplication... so DRY. def each_circle_collision(object, _resolve_with = :width, &block) if object.class != Class && object.instance_of?(object.class) - $window.current_state.game_objects.select { |i| i.instance_of?(object.class) }.each do |o| + window.current_state.game_objects.select { |i| i.instance_of?(object.class) }.each do |o| distance = Gosu.distance(x, y, object.x, object.y) block.call(o, object) if distance <= radius + object.radius && block end else - list = $window.current_state.game_objects.select { |i| i.instance_of?(object) } + list = window.current_state.game_objects.select { |i| i.instance_of?(object) } list.each do |o| next if self == o @@ -206,9 +202,9 @@ module CyberarmEngine end def destroy - if $window.current_state - $window.current_state.game_objects.each do |o| - $window.current_state.game_objects.delete(o) if o.is_a?(self.class) && o == self + if window.current_state + window.current_state.game_objects.each do |o| + window.current_state.game_objects.delete(o) if o.is_a?(self.class) && o == self end end end @@ -220,13 +216,13 @@ module CyberarmEngine def self.each_circle_collision(object, _resolve_with = :width, &block) if object.class != Class && object.instance_of?(object.class) - $window.current_state.game_objects.select { |i| i.instance_of?(self) }.each do |o| + window.current_state.game_objects.select { |i| i.instance_of?(self) }.each do |o| distance = Gosu.distance(o.x, o.y, object.x, object.y) block.call(o, object) if distance <= o.radius + object.radius && block end else - lista = $window.current_state.game_objects.select { |i| i.instance_of?(self) } - listb = $window.current_state.game_objects.select { |i| i.instance_of?(object) } + lista = window.current_state.game_objects.select { |i| i.instance_of?(self) } + listb = window.current_state.game_objects.select { |i| i.instance_of?(object) } lista.product(listb).each do |o, o2| next if o == o2 @@ -238,9 +234,9 @@ module CyberarmEngine def self.destroy_all INSTANCES.clear - if $window.current_state - $window.current_state.game_objects.each do |o| - $window.current_state.game_objects.delete(o) if o.is_a?(self.class) + if window.current_state + window.current_state.game_objects.each do |o| + window.current_state.game_objects.delete(o) if o.is_a?(self.class) end end end diff --git a/lib/cyberarm_engine/game_state.rb b/lib/cyberarm_engine/game_state.rb index bce0ace..4479625 100644 --- a/lib/cyberarm_engine/game_state.rb +++ b/lib/cyberarm_engine/game_state.rb @@ -9,7 +9,7 @@ module CyberarmEngine @options = options @game_objects = [] @global_pause = false - $window.text_input = nil unless options[:preserve_text_input] + window.text_input = nil unless options[:preserve_text_input] @down_keys = {} end @@ -30,48 +30,23 @@ module CyberarmEngine @game_objects.each(&:update) end - def draw_bounding_box(box) - x = box.x - y = box.y - max_x = box.max_x - max_y = box.max_y - - color = Gosu::Color.rgba(255, 127, 64, 240) - - # pipe = 4 - # Gosu.draw_rect(x-width, y-height, x+(width*2), y+(height*2), color, Float::INFINITY) - # puts "BB render: #{x}:#{y} w:#{x.abs+width} h:#{y.abs+height}" - # Gosu.draw_rect(x, y, x.abs+width, y.abs+height, color, Float::INFINITY) - - # TOP LEFT to BOTTOM LEFT - $window.draw_line( - x, y, color, - x, max_y, color, - Float::INFINITY - ) - # BOTTOM LEFT to BOTTOM RIGHT - $window.draw_line( - x, max_y, color, - max_x, max_y, color, - Float::INFINITY - ) - # BOTTOM RIGHT to TOP RIGHT - $window.draw_line( - max_x, max_y, color, - max_x, y, color, - Float::INFINITY - ) - # TOP RIGHT to TOP LEFT - $window.draw_line( - max_x, y, color, - x, y, color, - Float::INFINITY - ) + def needs_redraw? + true end - def destroy - @options.clear - @game_objects.clear + def drop(filename) + end + + def gamepad_connected(index) + end + + def gamepad_disconnected(index) + end + + def gain_focus + end + + def lose_focus end def button_down(id) @@ -90,6 +65,54 @@ module CyberarmEngine end end + def close + window.close! + end + + def draw_bounding_box(box) + x = box.x + y = box.y + max_x = box.max_x + max_y = box.max_y + + color = Gosu::Color.rgba(255, 127, 64, 240) + + # pipe = 4 + # Gosu.draw_rect(x-width, y-height, x+(width*2), y+(height*2), color, Float::INFINITY) + # puts "BB render: #{x}:#{y} w:#{x.abs+width} h:#{y.abs+height}" + # Gosu.draw_rect(x, y, x.abs+width, y.abs+height, color, Float::INFINITY) + + # TOP LEFT to BOTTOM LEFT + Gosu.draw_line( + x, y, color, + x, max_y, color, + Float::INFINITY + ) + # BOTTOM LEFT to BOTTOM RIGHT + Gosu.draw_line( + x, max_y, color, + max_x, max_y, color, + Float::INFINITY + ) + # BOTTOM RIGHT to TOP RIGHT + Gosu.draw_line( + max_x, max_y, color, + max_x, y, color, + Float::INFINITY + ) + # TOP RIGHT to TOP LEFT + Gosu.draw_line( + max_x, y, color, + x, y, color, + Float::INFINITY + ) + end + + def destroy + @options.clear + @game_objects.clear + end + def add_game_object(object) @game_objects << object end diff --git a/lib/cyberarm_engine/opengl/renderer/renderer.rb b/lib/cyberarm_engine/opengl/renderer/renderer.rb index 26c8ad9..3e58575 100644 --- a/lib/cyberarm_engine/opengl/renderer/renderer.rb +++ b/lib/cyberarm_engine/opengl/renderer/renderer.rb @@ -4,7 +4,7 @@ module CyberarmEngine def initialize @bounding_box_renderer = BoundingBoxRenderer.new - @opengl_renderer = OpenGLRenderer.new(width: $window.width, height: $window.height) + @opengl_renderer = OpenGLRenderer.new(width: CyberarmEngine::Window.instance.width, height: CyberarmEngine::Window.instance.height) end def draw(camera, lights, entities) diff --git a/lib/cyberarm_engine/text.rb b/lib/cyberarm_engine/text.rb index 5dc3ded..1853090 100644 --- a/lib/cyberarm_engine/text.rb +++ b/lib/cyberarm_engine/text.rb @@ -43,9 +43,9 @@ module CyberarmEngine when :left @x = 0 + BUTTON_PADDING when :center - @x = ($window.width / 2) - (@textobject.text_width(@text) / 2) + @x = (CyberarmEngine::Window.instance.width / 2) - (@textobject.text_width(@text) / 2) when :right - @x = $window.width - BUTTON_PADDING - @textobject.text_width(@text) + @x = CyberarmEngine::Window.instance.width - BUTTON_PADDING - @textobject.text_width(@text) end end end diff --git a/lib/cyberarm_engine/ui/dsl.rb b/lib/cyberarm_engine/ui/dsl.rb index e7d1980..8e3a5ca 100644 --- a/lib/cyberarm_engine/ui/dsl.rb +++ b/lib/cyberarm_engine/ui/dsl.rb @@ -116,7 +116,7 @@ module CyberarmEngine end private def element_parent - $__current_container__ + CyberarmEngine::Element::Container.current_container end private def container(klass, options = {}, &block) @@ -126,12 +126,12 @@ module CyberarmEngine _container = klass.new(options, block) old_parent = element_parent - $__current_container__ = _container + CyberarmEngine::Element::Container.current_container = _container _container.build _container.parent.add(_container) - $__current_container__ = old_parent + CyberarmEngine::Element::Container.current_container = old_parent _container end diff --git a/lib/cyberarm_engine/ui/elements/container.rb b/lib/cyberarm_engine/ui/elements/container.rb index 88127e2..16afac6 100644 --- a/lib/cyberarm_engine/ui/elements/container.rb +++ b/lib/cyberarm_engine/ui/elements/container.rb @@ -6,6 +6,16 @@ module CyberarmEngine attr_accessor :stroke_color, :fill_color attr_reader :children, :gui_state, :scroll_position + def self.current_container + @@current_container + end + + def self.current_container=(container) + raise ArgumentError, "Expected container to an an instance of CyberarmEngine::Element::Container, got #{container.class}" unless container.is_a?(CyberarmEngine::Element::Container) + + @@current_container = container + end + def initialize(options = {}, block = nil) @gui_state = options.delete(:gui_state) super @@ -35,23 +45,23 @@ module CyberarmEngine def clear(&block) @children.clear - old_container = $__current_container__ + old_container = CyberarmEngine::Element::Container.current_container - $__current_container__ = self + CyberarmEngine::Element::Container.current_container = self block.call(self) if block - $__current_container__ = old_container + CyberarmEngine::Element::Container.current_container = old_container root.gui_state.request_recalculate end def append(&block) - old_container = $__current_container__ + old_container = CyberarmEngine::Element::Container.current_container - $__current_container__ = self + CyberarmEngine::Element::Container.current_container = self block.call(self) if block - $__current_container__ = old_container + CyberarmEngine::Element::Container.current_container = old_container root.gui_state.request_recalculate end diff --git a/lib/cyberarm_engine/ui/elements/list_box.rb b/lib/cyberarm_engine/ui/elements/list_box.rb index fee4664..73e0d2a 100644 --- a/lib/cyberarm_engine/ui/elements/list_box.rb +++ b/lib/cyberarm_engine/ui/elements/list_box.rb @@ -35,7 +35,7 @@ module CyberarmEngine super w = @text.textobject.text_width("▼") - @text.textobject.draw("▼", @x + content_width - w, @y + @style.padding_top, @z, 1, 1, @text.color) + @text.textobject.draw_text("▼", @x + content_width - w, @y + @style.padding_top, @z, 1, 1, @text.color) end def choose=(item) diff --git a/lib/cyberarm_engine/ui/gui_state.rb b/lib/cyberarm_engine/ui/gui_state.rb index 3f8369c..4c168b9 100644 --- a/lib/cyberarm_engine/ui/gui_state.rb +++ b/lib/cyberarm_engine/ui/gui_state.rb @@ -12,7 +12,7 @@ module CyberarmEngine @root_container = Element::Stack.new(gui_state: self) @game_objects << @root_container - $__current_container__ = @root_container + CyberarmEngine::Element::Container.current_container = @root_container @active_width = window.width @active_height = window.height @@ -90,6 +90,8 @@ module CyberarmEngine @menu&.update super + return unless window.has_focus? + new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y) @@ -135,10 +137,6 @@ module CyberarmEngine @active_height = window.height end - def tool_tip_delay - 250 # ms - end - def button_down(id) super @@ -175,6 +173,10 @@ module CyberarmEngine @focus.button_up(id) if @focus.respond_to?(:button_up) end + def tool_tip_delay + @tip.style.delay || 250 # ms + end + def redirect_mouse_button(button) hide_menu unless @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu) diff --git a/lib/cyberarm_engine/ui/theme.rb b/lib/cyberarm_engine/ui/theme.rb index 01eaa55..2b420ad 100644 --- a/lib/cyberarm_engine/ui/theme.rb +++ b/lib/cyberarm_engine/ui/theme.rb @@ -154,6 +154,7 @@ module CyberarmEngine }, ToolTip: { # < TextBlock + delay: 100, # ms color: Gosu::Color::WHITE, padding_top: 4, padding_bottom: 4, diff --git a/lib/cyberarm_engine/window.rb b/lib/cyberarm_engine/window.rb index 67d4441..763589a 100644 --- a/lib/cyberarm_engine/window.rb +++ b/lib/cyberarm_engine/window.rb @@ -8,21 +8,33 @@ module CyberarmEngine attr_accessor :show_cursor attr_writer :exit_on_opengl_error - attr_reader :last_frame_time + attr_reader :last_frame_time, :states def self.now Gosu.milliseconds end def self.dt - $window.last_frame_time / 1000.0 + instance.last_frame_time / 1000.0 + end + + def self.instance=(window) + raise ArgumentError, "Expected window to be a subclass of CyberarmEngine::Window, got: #{window.class}" unless window.is_a?(CyberarmEngine::Window) + + @@instance = window + end + + def self.instance + @@instance end def initialize(width: 800, height: 600, fullscreen: false, update_interval: 1000.0 / 60, resizable: false, borderless: false) @show_cursor = false + @has_focus = false super(width, height, fullscreen: fullscreen, update_interval: update_interval, resizable: resizable, borderless: borderless) - $window = self + Window.instance = self + @last_frame_time = Gosu.milliseconds - 1 @current_frame_time = Gosu.milliseconds self.caption = "CyberarmEngine #{CyberarmEngine::VERSION} #{Gosu.language}" @@ -34,13 +46,14 @@ module CyberarmEngine end def draw - current_state.draw if current_state + current_state&.draw end def update Stats.clear - current_state.update if current_state + current_state&.update + @last_frame_time = Gosu.milliseconds - @current_frame_time @current_frame_time = Gosu.milliseconds end @@ -49,6 +62,48 @@ module CyberarmEngine @show_cursor end + def needs_redraw? + current_state ? current_state.needs_redraw? : true + end + + def drop(filename) + current_state&.drop(filename) + end + + def gamepad_connected(index) + current_state&.gamepad_connected(index) + end + + def gamepad_disconnected(index) + current_state&.gamepad_disconnected(index) + end + + def gain_focus + @has_focus = true + + current_state&.gain_focus + end + + def lose_focus + @has_focus = false + + current_state&.lose_focus + end + + def button_down(id) + super + current_state&.button_down(id) + end + + def button_up(id) + super + current_state&.button_up(id) + end + + def close + current_state ? current_state.close : super + end + def dt @last_frame_time / 1000.0 end @@ -61,16 +116,6 @@ module CyberarmEngine @exit_on_opengl_error end - def button_down(id) - super - current_state.button_down(id) if current_state - end - - def button_up(id) - super - current_state.button_up(id) if current_state - end - def push_state(klass, options = {}) options = { setup: true }.merge(options) @@ -108,6 +153,10 @@ module CyberarmEngine @states.shift end + def has_focus? + @has_focus + end + # Sourced from https://gist.github.com/ippa/662583 def draw_circle(cx, cy, r, z = 9999, color = Gosu::Color::GREEN, step = 10) 0.step(360, step) do |a1|