class AdventureRL::Quadtree

Constants

DEFAULT_SETTINGS

Public Class Methods

get_default_settings() click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 21
def self.get_default_settings
  window = Window.get_window
  return Settings.new(
    position: (window ? window.get_position : DEFAULT_SETTINGS.get(:window, :position) || DEFAULT_SETTINGS[:position]),
    size:     (window ? window.get_size     : DEFAULT_SETTINGS.get(:window, :size)     || DEFAULT_SETTINGS[:size]),
    origin:   (window ? window.get_origin   : DEFAULT_SETTINGS.get(:window, :origin)   || DEFAULT_SETTINGS[:origin]),
  )
end
new(settings = {}) click to toggle source
Calls superclass method AdventureRL::Mask::new
# File lib/AdventureRL/Quadtree.rb, line 30
def initialize settings = {}
  @settings = DEFAULT_SETTINGS.merge(Quadtree.get_default_settings).merge(settings)
  super @settings
  @max_objects     = @settings.get :max_objects
  @quadtrees = {
    top_left:     nil,
    top_right:    nil,
    bottom_left:  nil,
    bottom_right: nil
  }
  @objects = []
  add_object [@settings.get(:objects)].flatten.compact
end

Public Instance Methods

add(object)
Alias for: add_object
add_object(object) click to toggle source

Add the given Mask object(s) into the Quadtree, and split into smaller quadtrees if necessary.

# File lib/AdventureRL/Quadtree.rb, line 46
def add_object object
  objects = [object].flatten
  objects.each do |obj|
    validate_object_has_mask_or_point obj
    add_object_to_quadtree obj
  end
end
Also aliased as: add
add_object_to_quadtree(object) click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 55
def add_object_to_quadtree object
  return false  unless (collides_with? object)
  return false  if     (@objects.include? object)

  if (@objects.size < @max_objects)
    @objects << object
    return true
  end

  split_quadtrees  unless (has_quadtrees?)

  return get_quadtrees.map do |quadtree|
    next quadtree.add_object_to_quadtree(object)
  end .any?
end
collides?(object) click to toggle source

Returns true if the given object collides with any other object and false if not.

# File lib/AdventureRL/Quadtree.rb, line 73
def collides? object
  validate_object_has_mask_or_point object
  return collides_for?(object)
end
collides_for?(object) click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 78
def collides_for? object
  return false  unless (collides_with? object)
  return (
    @objects.any? do |obj|
      next obj != object && obj.collides_with?(object)
    end ||
    get_quadtrees.any? do |quadtree|
      next quadtree.collides_for?(object)
    end
  )
end
get_colliding_objects(object) click to toggle source

Returns all objects, that collide with object.

# File lib/AdventureRL/Quadtree.rb, line 91
def get_colliding_objects object
  validate_object_has_mask_or_point object
  return get_colliding_objects_for(object)
end
get_colliding_objects_for(object) click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 96
def get_colliding_objects_for object
  colliding_objects = []
  return colliding_objects  unless (collides_with? object)
  colliding_objects.concat(@objects.select do |obj|
    next obj != object && obj.collides_with?(object)
  end)
  get_quadtrees.each do |quadtree|
    colliding_objects.concat quadtree.get_colliding_objects_for(object)
  end
  return colliding_objects
end
remove_object(object) click to toggle source

Remove the given object(s) (single or multiple) from the Quadtree (or any children).

# File lib/AdventureRL/Quadtree.rb, line 125
def remove_object object
  objects = [object].flatten
  objects.each do |obj|
    @objects.delete obj
    get_quadtrees.each do |quadtree|
      quadtree.remove_object obj
    end
  end
end
reset() click to toggle source

Reset this and all child Quadtrees. Removes all stored objects.

# File lib/AdventureRL/Quadtree.rb, line 110
def reset
  @objects.clear
  get_quadtrees.each &:reset
end
reset_object(object) click to toggle source

Remove and (try to) re-add the given object(s) (single or multiple).

# File lib/AdventureRL/Quadtree.rb, line 116
def reset_object object
  objects = [object].flatten
  objects.each do |obj|
    @objects.delete obj
    add_object_to_quadtree obj
  end
end

Private Instance Methods

get_quadtrees() click to toggle source

Returns all the children Quadtrees.

# File lib/AdventureRL/Quadtree.rb, line 145
def get_quadtrees
  return @quadtrees.values.compact
end
get_split_quadtree_bottom_left() click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 197
def get_split_quadtree_bottom_left
  return Quadtree.new(Settings.new(
    position:    get_position.map do |axis, pos|
      next [axis, pos + (get_size(:height).to_f * 0.5).round]  if (axis == :y)
      next [axis, pos]
    end .to_h,
    size:        get_size.map do |side, size|
      next [side, (size.to_f * 0.5).round]
    end .to_h,
    origin:      get_origin,
    max_objects: @max_objects
  ))
end
get_split_quadtree_bottom_right() click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 211
def get_split_quadtree_bottom_right
  return Quadtree.new(Settings.new(
    position:    get_position.map do |axis, pos|
      next [axis, pos + (get_size(:width).to_f  * 0.5).round]  if (axis == :x)
      next [axis, pos + (get_size(:height).to_f * 0.5).round]  if (axis == :y)
    end .to_h,
    size:        get_size.map do |side, size|
      next [side, (size.to_f * 0.5).round]
    end .to_h,
    origin:      get_origin,
    max_objects: @max_objects
  ))
end
get_split_quadtree_for_corner(corner) click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 164
def get_split_quadtree_for_corner corner
  method_name = "get_split_quadtree_#{corner.to_s}".to_sym
  error(
    "Method `#{method_name.to_s}' doesn't exist for `#{self.inspect}:#{self.class}'."
  )  unless (method_exists? method_name)
  return method(method_name).call
end
get_split_quadtree_top_left() click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 172
def get_split_quadtree_top_left
  return Quadtree.new(Settings.new(
    position:    get_position,
    size:        get_size.map do |side, size|
      next [side, (size.to_f * 0.5).round]
    end .to_h,
    origin:      get_origin,
    max_objects: @max_objects
  ))
end
get_split_quadtree_top_right() click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 183
def get_split_quadtree_top_right
  return Quadtree.new(Settings.new(
    position:    get_position.map do |axis, pos|
      next [axis, pos + (get_size(:width).to_f * 0.5).round]  if (axis == :x)
      next [axis, pos]
    end .to_h,
    size:        get_size.map do |side, size|
      next [side, (size.to_f * 0.5).round]
    end .to_h,
    origin:      get_origin,
    max_objects: @max_objects
  ))
end
has_quadtrees?() click to toggle source

Returns true if this Quadtree has already been split and has children Quadtrees.

# File lib/AdventureRL/Quadtree.rb, line 151
def has_quadtrees?
  return @quadtrees.values.all?
end
move_objects_to_quadtrees() click to toggle source

NOTE: Shouldn't be used, breaks stuff currently.

Life is easier without this method.
# File lib/AdventureRL/Quadtree.rb, line 227
def move_objects_to_quadtrees
  return  if (@objects.empty?)
  @objects.each do |object|
    get_quadtrees.detect do |quadtree|
      next quadtree.add_object_to_quadtree(object)
    end
  end
  @objects.clear
end
split_quadtrees() click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 155
def split_quadtrees
  @quadtrees = @quadtrees.keys.map do |corner|
    new_quadtree = get_split_quadtree_for_corner corner
    next [corner, new_quadtree]  if (new_quadtree)
    next nil
  end .compact.to_h
  #move_objects_to_quadtrees  if (@objects.any?)  # NOTE: Doing this will break stuff.
end
validate_object_has_mask_or_point(object) click to toggle source
# File lib/AdventureRL/Quadtree.rb, line 137
def validate_object_has_mask_or_point object
  object.has_point?  rescue error(  # NOTE: #has_point? method must be available for both Point and Mask
    "Expected an instance of Mask/Point or an object that has a Mask/Point, but got",
    "`#{object.inspect}:#{object.class.name}'."
  )
end