Module: AdventureRL::Modifiers::Solid
- Defined in:
- lib/AdventureRL/Modifiers/Solid.rb
Overview
This module is supposed to be included in Mask child classes. It will tag that Mask instance as 'solid', and check collision with other solid Masks when calling #move_by. You can give it a specific solid_tag, which can be passed as the :solid_tag key’s value upon initialization. Multiple solid tags may be passed as an array. Solid Masks will only collide with other Solid Masks that have a mutual solid tag. The default solid tag is :default.
Constant Summary collapse
- DEFAULT_SOLID_SETTINGS =
NOTE: possible
:precision_over_performancevalues:- :low (or anything other than the higher values)
-
Lowest precision, highest performance. Never check every pixel between previous and new positions. If there is collision at new position, jump to previous position and return. The larger the movement steps, the more distance there will be to the colliding object.
-
– __CANNOT__ fully close gaps to Solids.
-
– __CAN__ phase through Solids at high speeds (especially when it lags).
-
– __CAN__ get stuck in place temporarily when moving on both axes but only colliding on one of them.
-
+ Only __one collision check__ per call to #move_by, highest performance.
-
- :medium
-
Medium precision, medium (varying) performance. Only checks every pixel in path if the expected destination collides. Even then, collision checking is used somewhat sparingly.
-
– __CAN__ phase through Solids at high speeds (especially when it lags).
-
– __CAN__ get stuck in place temporarily when moving on both axes but only colliding on one of them.
-
+ __CAN__ almost fully close gaps to Solids (no sub-pixel collision checks).
-
- :high
-
High precision, low to medium (varying) performance. Only checks every pixel in path if the expected destination collides. When checking every pixel in path, check both axes separately, to improve precision.
-
– __CAN__ phase through Solids at high speeds (especially when it lags).
-
+ __CANNOT__ get stuck in place temporarily when moving on both axes but only colliding on one of them.
-
+ __CAN__ fully close gaps to Solids.
-
- :highest
-
Highest precision, least performance. Always check every pixel between previous and new positions. Depending on the amount of (moving) Solid objects on screen,
-
– Depending on the amount of (moving) Solids, this can get very laggy at high speeds => lag produces larger steps (usually), because of Deltatime => larger steps produce more collision checks and more lag.
-
+ __CANNOT__ phase through Solids, no matter what the speed is.
-
+ __CANNOT__ get stuck in place temporarily when moving on both axes but only colliding on one of them.
-
+ __CAN__ fully close gaps to Solids.
-
Settings.new( solid_tag: SolidsManager::DEFAULT_SOLID_TAG, solid_tag_collides_with: nil, precision_over_performance: :medium, static: false, auto_update: false )
Instance Method Summary collapse
- #add_to_solids_manager(solids_manager) ⇒ Object
-
#get_colliding_objects ⇒ Object
Returns all currently colliding objects (if any).
-
#get_solid_tags ⇒ Object
Returns this Mask’s solid tags, which other Masks use to check collision against this Mask.
-
#get_solid_tags_collides_with ⇒ Object
Returns the solid tags, which this Mask uses to check collision against other Masks.
-
#in_collision? ⇒ Boolean
Returns
trueif this Mask is currently in collision with another solid Mask which has a mutual solid tag. -
#initialize(settings = {}) ⇒ Object
Additionally to the Mask’s settings Hash or Settings instance, you may pass the extra key
:solid_tag, to define a custom solid tag (or multiple solid tags) upon initialization. -
#is_static? ⇒ Boolean
Returns
trueif this is a static solid Mask, which means it cannot be moved with #move_by. -
#make_static ⇒ Object
Makes this Solid Mask static.
-
#move_by(*args) ⇒ Object
Overwrite #move_by method, so that collision checking with other objects with a mutual solid tag is done, and movement prevented if necessary.
-
#move_to(*args) ⇒ Object
Overwrite the #move_to method, so we can reset the object for the solids_manager if necessary.
-
#remove_from_solids_manager ⇒ Object
When it is removed, also remove it from the SolidsManager.
-
#removed ⇒ Object
This method is called when this object is removed from an Inventory.
-
#set_layer(layer) ⇒ Object
Overwrite #set_layer method, so we can get the SolidsManager from the Layer, if it has one.
- #set_solid_tags(*new_solid_tags) ⇒ Object
- #set_solid_tags_collides_with(*new_solid_tags_collides_with) ⇒ Object
Instance Method Details
#add_to_solids_manager(solids_manager) ⇒ Object
73 74 75 76 77 78 79 80 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 73 def add_to_solids_manager solids_manager Helpers::Error.error( "Expected argument to be a SolidsManager, but got", "'#{solids_manager.inspect}:#{solids_manager.class.name}`." ) unless (solids_manager.is_a? SolidsManager) @solids_manager = solids_manager @solids_manager.add_object self, end |
#get_colliding_objects ⇒ Object
Returns all currently colliding objects (if any). TODO: Write documentation for callback method.
166 167 168 169 170 171 172 173 174 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 166 def get_colliding_objects if (@solids_manager) colliding_objects = @solids_manager.get_colliding_objects(self, ) else colliding_objects = [] end is_colliding_with_objects colliding_objects if (colliding_objects.any? && methods.include?(:is_colliding_with_objects)) return colliding_objects end |
#get_solid_tags ⇒ Object
Returns this Mask’s solid tags, which other Masks use to check collision against this Mask.
199 200 201 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 199 def return @solid_tags end |
#get_solid_tags_collides_with ⇒ Object
Returns the solid tags, which this Mask uses to check collision against other Masks.
205 206 207 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 205 def return @solid_tags_collides_with || @solid_tags end |
#in_collision? ⇒ Boolean
Returns true if this Mask is currently in collision with another solid Mask which has a mutual solid tag. TODO: Write documentation for callback method.
154 155 156 157 158 159 160 161 162 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 154 def in_collision? if (@solids_manager) is_colliding = @solids_manager.collides?(self, ) else is_colliding = false end is_colliding if (is_colliding && methods.include?(:is_colliding)) return is_colliding end |
#initialize(settings = {}) ⇒ Object
Additionally to the Mask’s settings Hash or Settings instance, you may pass the extra key :solid_tag, to define a custom solid tag (or multiple solid tags) upon initialization. They are used for collision checking with other Solid Mask objects that have a mutual solid tag.
63 64 65 66 67 68 69 70 71 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 63 def initialize settings = {} @settings = DEFAULT_SOLID_SETTINGS.merge settings @solid_tags = [@settings.get(:solid_tag)].flatten.sort @solid_tags_collides_with = [@settings.get(:solid_tag_collides_with) || @solid_tags].flatten.sort @solid_static = @settings.get :static # Basically disables #move_by @precision_over_performance = @settings.get :precision_over_performance assign_to_solids_manager if (@settings.get :auto_update) super @settings end |
#is_static? ⇒ Boolean
Returns true if this is a static solid Mask, which means it cannot be moved with #move_by.
183 184 185 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 183 def is_static? return !!@solid_static end |
#make_static ⇒ Object
Makes this Solid Mask static.
177 178 179 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 177 def make_static @solid_static = true end |
#move_by(*args) ⇒ Object
Overwrite #move_by method, so that collision checking with other objects with a mutual solid tag is done, and movement prevented if necessary.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 103 def move_by *args return false if (is_static?) return super unless (@solids_manager) @real_point = nil previous_position = get_position.dup incremental_position = parse_position(*args) expected_position = { x: (previous_position[:x] + (incremental_position.key?(:x) ? incremental_position[:x] : 0)), y: (previous_position[:y] + (incremental_position.key?(:y) ? incremental_position[:y] : 0)) } # NOTE: # This is a bit of a hacky workaround for some # weird Pusher behavior with Velocity and Gravity. previous_precision_over_performance = @precision_over_performance.dup opts = args.last.is_a?(Hash) ? args.last : nil @precision_over_performance = opts[:precision_over_performance] if (opts && opts.key?(:precision_over_performance)) if ([:highest].include? @precision_over_performance) move_by_steps incremental_position else @position[:x] += incremental_position[:x] if (incremental_position.key? :x) @position[:y] += incremental_position[:y] if (incremental_position.key? :y) # TODO #puts 'PUSHING' if (is_a?(Player) && opts && opts[:pushed_by_pusher]) unless (move_by_handle_collision_with_previous_position previous_position) move_by_steps incremental_position if ([:medium, :high].include? @precision_over_performance) end end @precision_over_performance = previous_precision_over_performance @solids_manager.reset_object self, unless (@position == previous_position) return @position == expected_position end |
#move_to(*args) ⇒ Object
Overwrite the #move_to method, so we can reset the object for the solids_manager if necessary.
144 145 146 147 148 149 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 144 def move_to *args previous_position = get_position.dup super return unless (@solids_manager) @solids_manager.reset_object self, if (@position != previous_position) end |
#remove_from_solids_manager ⇒ Object
When it is removed, also remove it from the SolidsManager. TODO: Do this properly.
96 97 98 99 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 96 def remove_from_solids_manager #@solids_manager.remove_object self, [get_solid_tags, get_solid_tags_collides_with].flatten if (@solids_manager) @solids_manager.remove_object_from_all_quadtrees self if (@solids_manager) end |
#removed ⇒ Object
This method is called when this object is removed from an Inventory.
90 91 92 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 90 def removed remove_from_solids_manager end |
#set_layer(layer) ⇒ Object
Overwrite #set_layer method, so we can get the SolidsManager from the Layer, if it has one.
84 85 86 87 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 84 def set_layer layer super assign_to_solids_manager if (@settings.get :auto_update) end |
#set_solid_tags(*new_solid_tags) ⇒ Object
187 188 189 190 191 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 187 def * @solids_manager.remove_object self, if (@solids_manager) @solid_tags = [].flatten.compact @solids_manager.add_object self, if (@solids_manager) end |
#set_solid_tags_collides_with(*new_solid_tags_collides_with) ⇒ Object
193 194 195 |
# File 'lib/AdventureRL/Modifiers/Solid.rb', line 193 def * @solid_tags_collides_with = [].flatten.compact end |