module AdventureRL
class Point
# This array will be filled with any created Points.
# Just so they won't get garbage collected
# (not sure how garbage collection works).
POINTS = []
# Initialize with two arguments:
# x:: x position
# y:: y position
# args = {}:: Optional hash with extra options.
# Currently, the only valid hash key is :assign_to,
# to assign this Point to an object upon initialization.
def initialize x, y, args = {}
POINTS << self
@position = {
x: x,
y: y
}
@assigned_to = []
assign_to args[:assign_to] if (args[:assign_to])
@layer = nil
@real_point = nil
end
def assign_to object
Helpers::PipeMethods.pipe_methods_from object, to: self
@assigned_to << object
end
# Returns all objects this Point was assigned to.
def get_assigned
return @assigned_to
end
# Returns true if the Point has been
# assigned to the passed object.
def assigned_to? object
return @assigned_to.include? object
end
# Returns self.
def get_point
return self
end
def has_point?
return true
end
def x
return get_position :x
end
def y
return get_position :y
end
def get_position target = :all
target = target.to_sym
return @position if (target == :all)
return @position[target] if (@position.keys.include?(target))
return nil
end
# Set the new position with the given arguments.
# args may be:
# Two integers, representing the x and y axes, respectively.
# A hash containing one or both of the keys :x and :y.
def set_position *args
@real_point = nil
new_position = parse_position *args
@position[:x] = new_position[:x] if (new_position.key? :x)
@position[:y] = new_position[:y] if (new_position.key? :y)
return get_position
end
alias_method :move_to, :set_position
# Move the Point relative to the given arguments.
# args may be:
# Two integers, representing the x and y axes, respectively.
# A hash containing one or both of the keys :x and :y.
def move_by *args
@real_point = nil
incremental_position = parse_position *args
@position[:x] += incremental_position[:x] if (incremental_position.key? :x)
@position[:y] += incremental_position[:y] if (incremental_position.key? :y)
return get_position
end
def collides_with? other
return collides_with_mask? other if (defined? other.has_mask?)
return collides_with_point? other if (defined? other.has_point?)
return collides_with_hash? other if (other.is_a?(Hash))
end
def collides_with_mask? mask
return mask.collides_with_point? self
end
def collides_with_point? point
return get_real_position == point.get_real_position
end
def collides_with_hash? hash
if (hash.keys.include_all?(:x, :y))
point = Point.new hash[:x], hash[:y]
return collides_with_point? point
end
return nil
end
def keys
sorted_keys = [:x, :y]
return @position.keys.sort do |axis|
next sorted_keys.index axis
end
end
def values
return @position.sort_by_keys(keys).values
end
# Set the parent Layer.
def set_layer layer
error(
"Passed argument `layer' must be an instance of `Layer', but got",
"`#{layer.inspect}:#{layer.class.name}'."
) unless (layer.is_a? Layer)
@layer = layer
end
# Returns the parent Layer.
def get_layer
return @layer
end
# Returns true if this Point has a parent Layer.
def has_layer?
return !!@layer
end
# Returns a new Point with the real window position of this Point.
def get_real_point
return self unless (has_layer?)
return @real_point if (@real_point)
layer_point = get_layer.get_real_corner :left, :top
@real_point = Point.new(
(layer_point.x + x),
(layer_point.y + y)
)
return @real_point
end
# Returns the real window position of this Point as a Hash.
def get_real_position
return get_real_point.get_position
end
private
def parse_position *args
position = {}
args[0] = args[0].get_position if (args[0].is_a? Point)
case args.size
when 2
position[:x] = args[0]
position[:y] = args[1]
when 1
Helpers::Error.error(
"Ambiguous argument `#{args[0]}' for Point##{__method__}"
) unless (args[0].is_a?(Hash))
Helpers::Error.error(
"Hash must include either :x, :y, or both keys for Point##{__method__}"
) unless (args[0].keys.include_any?(:x, :y))
position[:x] = args[0][:x] if (args[0][:x])
position[:y] = args[0][:y] if (args[0][:y])
else
Helpers::Error.error(
"Invalid amount of arguments for Point##{__method__}.",
"Pass either two arguments representing the x and y axes, respectively, or",
"pass a single hash with the keys :x and :y with their respective axes values."
)
end
return position
end
end
end