# some more OO wrappers for the low level thing functionality class Thing < Eruta::Thing extend Registry attr_reader :id attr_reader :sprite_id attr_reader :sprite attr_accessor :parent attr_reader :name def initialize(id, name) @id = id @name = name || "thing_#{id}" # child things, keyed by id @children = {} # parent thing @parent = nil self.sprite = Sprite.make(("sprite_" + @name.to_s).to_sym) self.class.register(self) end def self.make(name, kind, x, y, z, w, h) id = Eruta::Thing.thing_new(kind, x, y, z, w, h) p "Making thing #{name} #{id}" return nil if id < 0 return self.new(id, name) end # adds child as a child of self def add_child(child) child.parent = self @children[child.id] = child end def self.find_in_rectangle(x, y, w, h, self_id) ids = Eruta::Thing.find_in_rectangle(x, y, w, h) ids.delete(self_id) result = ids.map { |id| self.lookup(id) } end # Forwards methods to Eruta::Thing(@id, * args) def self.forward_thing(name) clean_name = name.to_s.gsub("=", "_").gsub('?', '_p').gsub('!', '_bang') method_name = "#{clean_name}".to_sym define_method(name) do |*args| Eruta::Thing.send(method_name, @id, *args) end end def v return Eruta::Thing.v @id end def v=(point) return Eruta::Thing.v_ @id, *point end forward_thing :x forward_thing :y forward_thing :cx forward_thing :cy forward_thing :w forward_thing :h forward_thing :z forward_thing :direction forward_thing :pose def is_facing?(direction) dir_now = self.direction return ((dir_now & direction) == direction) end # Returns the x, y w and h of a rectangle "in front" # of the direction the thing is facing. def rectangle_in_front(w = 32, h = 32) dire = self.direction cx = self.cx cy = self.cy sh = self.h sw = self.w # sh = 32 if sh > 32 if is_facing?(Eruta::Sprite::NORTH) cy -= ( h / 2.0 + sh / 2.0) elsif is_facing?(Eruta::Sprite::EAST) cx += ( w / 2.0 + sw / 2.0) elsif is_facing?(Eruta::Sprite::SOUTH) cy += ( h / 2.0 + sh / 2.0) elsif is_facing?(Eruta::Sprite::WEST) cx -= ( w / 2.0 + sw / 2.0) end x = cx # - (w / 2.0) y = cy # - (h / 2.0) return x, y, w, h end def find_in_front(w = 32, h = 32) x, y, w, h = self.rectangle_in_front(w, h) return Thing.find_in_rectangle(x, y, w, h, @id) end # Forces the camera to track this thing. def track camera_track(@id) end # Sets the sprite for this thing def sprite=(sprite) if (@sprite) @sprite = @sprite.delete end @sprite = sprite Eruta::Thing.sprite_(@id, @sprite.id) @sprite_id = @sprite.id # Set sprite's default one shot actions one_shot_default() puts "set sprite #{@sprite.id}" end # Sets the pose for this thing def pose=(pose_id) Eruta::Thing.pose_(@id, pose_id) end def direction=(dir_id) Eruta::Thing.direction_(@id, dir_id) end def self.actor=(new_actor) @actor = new_actor end def self.actor @actor end # Applies a tint to the given layer of the thing's sprite. def tint(layer, r, g, b, a = 255) Eruta::Thing.tint_rgba @id, layer, r, g, b, a end # Applies a tint to the torso layer of the thing's sprite. def tint_torso(r, g, b, a = 255) tint(Eruta::Sprite::Layer::TORSO, r, g, b, a) end # Applies a tint to the hair layer of the thing's sprite. def tint_hair(r, g, b, a = 255) tint(Eruta::Sprite::Layer::HAIR, r, g, b, a) end # Hides the thing's given sprite layer def hide_layer(layer) Eruta::Thing.hide_layer @id, layer, 1 end # Unhides the thing's given sprite layer def show_layer(layer) Eruta::Thing.hide_layer @id, layer, 0 end # Returns true if the layer is hidden false if not def layer_hidden?(layer) Eruta::Thing.layer_hidden?(@id, layer) end # Sets the loop mode of the Thing's action. def set_action_loop(action, loop) Eruta::Thing.set_action_loop(@id, action, loop) end # Gets the loop mode of the Thing's action. def get_action_loop(action) Eruta::Thing.get_action_loop(@id, action) end # Sets the loop mode of the Thing's pose and direction sprite. def set_pose_direction_loop(pose, direction, loop) Eruta::Thing.set_pose_direction_loop(@id, pose, direction, loop) end # Gets the loop mode of the Thing's pose and direction sprite. def get_pose_direction_loop(pose, direction) Eruta::Thing.get_pose_direction_loop(@id, pose, direction) end # Gets the status of the Thing's action. def action_done?(action) Eruta::Thing.action_done?(@id, action) end # Sets the action to loop mode. def loop_action(action) self.set_action_loop(action, Eruta::Sprite::State::ACTION_LOOP) end # Sets the action to one shot mode. def one_shot_action(action) self.set_action_loop(action, Sprite::State::ACTION_ONESHOT) end # Sets actions that should probably be one-shot to one shot. def one_shot_default() poses = [ Sprite::SLASH, Sprite::CAST, Sprite::STAB, Sprite::SHOOT, Sprite::HURT ] directions = [ Sprite::NORTH, Sprite::EAST, Sprite::SOUTH, Sprite::WEST ] poses.each do | pose | directions.each do | direction | self.set_pose_direction_loop(pose, direction, Sprite::State::ACTION_ONESHOT) end end # the "Drop down" action is a one stop action in ULPCSS sprites. res = self.set_pose_direction_loop(Sprite::DOWN, Sprite::ALL_DIRECTIONS, Sprite::State::ACTION_ONESTOP) end # Sets a flag of the main hull (physical presence) of the thing forward_thing :set_hull_flag # Unsets a flag of the main hull (physical presence) of the thing forward_thing :unset_hull_flag # Sets all flags of the main hull (physical presence) of the thing forward_thing :hull_flags= # Gets all flags of the main hull (physical presence) of the thing forward_thing :hull_flags # Sets the group of the thing forward_thing :group= # Gets the group of the thing forward_thing :group # Loads a sprite sheet with built in layout as a layer # of the sprite of this thing. def load_builtin(layer, vpath, layout = :ulpcss) return nil unless @sprite @sprite.load_builtin(layer, vpath, layout = :ulpcss) end # Loads a ULPCSS sprite sheet with built in layout as a layer # of the sprite of this thing. def load_ulpcss(layer, vpath) return nil unless @sprite @sprite.load_ulpcss(layer, vpath) end # Loads a ULPCSS sprite sheet for an oversized slashing weapon # with built in layout as a layer of the sprite of this thing.. def load_ulpcss_slash(layer, vpath) return nil unless @sprite @sprite.load_ulpcss_slash(layer, vpath) end # Loads a ULPCSS sprite sheet for an oversized stabbing weapon # with built in layout as a layer of the sprite of this thing.. def load_ulpcss_stab(layer, vpath) return nil unless @sprite @sprite.load_ulpcss_stab(layer, vpath) end # React to sprite event def on_sprite(spriteid, pose, direction, kind) p "Sprite event for #{name} #{spriteid}, #{pose}, #{direction}, #{kind}" p "Check: #{Sprite::SLASH} (#{Sprite::STAB}) #{Sprite::DOWN}" if (pose & Sprite::SLASH) == Sprite::SLASH p "Sprite event on attack" Attack.on_sprite(@id) end end # React to a collision event def on_bump(thing2, h1 = nil, h2 = nil) # split up per kind of thing, which will be a pain... end # Deletes the thing def delete Thing.unregister(self) Eruta::Thing.delete(@id) @id = nil return nil end end