thing.rb 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. # some more OO wrappers for the low level thing functionality
  2. class Thing < Eruta::Thing
  3. extend Registry
  4. attr_reader :id
  5. attr_reader :sprite_id
  6. attr_reader :sprite
  7. attr_accessor :parent
  8. attr_reader :name
  9. def initialize(id, name)
  10. @id = id
  11. @name = name || "thing_#{id}"
  12. # child things, keyed by id
  13. @children = {}
  14. # parent thing
  15. @parent = nil
  16. self.sprite = Sprite.make(("sprite_" + @name.to_s).to_sym)
  17. self.class.register(self)
  18. end
  19. def self.make(name, kind, x, y, z, w, h)
  20. id = Eruta::Thing.thing_new(kind, x, y, z, w, h)
  21. p "Making thing #{name} #{id}"
  22. return nil if id < 0
  23. return self.new(id, name)
  24. end
  25. # adds child as a child of self
  26. def add_child(child)
  27. child.parent = self
  28. @children[child.id] = child
  29. end
  30. def self.find_in_rectangle(x, y, w, h, self_id)
  31. ids = Eruta::Thing.find_in_rectangle(x, y, w, h)
  32. ids.delete(self_id)
  33. result = ids.map { |id| self.lookup(id) }
  34. end
  35. # Forwards methods to Eruta::Thing(@id, * args)
  36. def self.forward_thing(name)
  37. clean_name = name.to_s.gsub("=", "_").gsub('?', '_p').gsub('!', '_bang')
  38. method_name = "#{clean_name}".to_sym
  39. define_method(name) do |*args|
  40. Eruta::Thing.send(method_name, @id, *args)
  41. end
  42. end
  43. def v
  44. return Eruta::Thing.v @id
  45. end
  46. def v=(point)
  47. return Eruta::Thing.v_ @id, *point
  48. end
  49. forward_thing :x
  50. forward_thing :y
  51. forward_thing :cx
  52. forward_thing :cy
  53. forward_thing :w
  54. forward_thing :h
  55. forward_thing :z
  56. forward_thing :direction
  57. forward_thing :pose
  58. def is_facing?(direction)
  59. dir_now = self.direction
  60. return ((dir_now & direction) == direction)
  61. end
  62. # Returns the x, y w and h of a rectangle "in front"
  63. # of the direction the thing is facing.
  64. def rectangle_in_front(w = 32, h = 32)
  65. dire = self.direction
  66. cx = self.cx
  67. cy = self.cy
  68. sh = self.h
  69. sw = self.w
  70. # sh = 32 if sh > 32
  71. if is_facing?(Eruta::Sprite::NORTH)
  72. cy -= ( h / 2.0 + sh / 2.0)
  73. elsif is_facing?(Eruta::Sprite::EAST)
  74. cx += ( w / 2.0 + sw / 2.0)
  75. elsif is_facing?(Eruta::Sprite::SOUTH)
  76. cy += ( h / 2.0 + sh / 2.0)
  77. elsif is_facing?(Eruta::Sprite::WEST)
  78. cx -= ( w / 2.0 + sw / 2.0)
  79. end
  80. x = cx # - (w / 2.0)
  81. y = cy # - (h / 2.0)
  82. return x, y, w, h
  83. end
  84. def find_in_front(w = 32, h = 32)
  85. x, y, w, h = self.rectangle_in_front(w, h)
  86. return Thing.find_in_rectangle(x, y, w, h, @id)
  87. end
  88. # Forces the camera to track this thing.
  89. def track
  90. camera_track(@id)
  91. end
  92. # Sets the sprite for this thing
  93. def sprite=(sprite)
  94. if (@sprite)
  95. @sprite = @sprite.delete
  96. end
  97. @sprite = sprite
  98. Eruta::Thing.sprite_(@id, @sprite.id)
  99. @sprite_id = @sprite.id
  100. # Set sprite's default one shot actions
  101. one_shot_default()
  102. puts "set sprite #{@sprite.id}"
  103. end
  104. # Sets the pose for this thing
  105. def pose=(pose_id)
  106. Eruta::Thing.pose_(@id, pose_id)
  107. end
  108. def direction=(dir_id)
  109. Eruta::Thing.direction_(@id, dir_id)
  110. end
  111. def self.actor=(new_actor)
  112. @actor = new_actor
  113. end
  114. def self.actor
  115. @actor
  116. end
  117. # Applies a tint to the given layer of the thing's sprite.
  118. def tint(layer, r, g, b, a = 255)
  119. Eruta::Thing.tint_rgba @id, layer, r, g, b, a
  120. end
  121. # Applies a tint to the torso layer of the thing's sprite.
  122. def tint_torso(r, g, b, a = 255)
  123. tint(Eruta::Sprite::Layer::TORSO, r, g, b, a)
  124. end
  125. # Applies a tint to the hair layer of the thing's sprite.
  126. def tint_hair(r, g, b, a = 255)
  127. tint(Eruta::Sprite::Layer::HAIR, r, g, b, a)
  128. end
  129. # Hides the thing's given sprite layer
  130. def hide_layer(layer)
  131. Eruta::Thing.hide_layer @id, layer, 1
  132. end
  133. # Unhides the thing's given sprite layer
  134. def show_layer(layer)
  135. Eruta::Thing.hide_layer @id, layer, 0
  136. end
  137. # Returns true if the layer is hidden false if not
  138. def layer_hidden?(layer)
  139. Eruta::Thing.layer_hidden?(@id, layer)
  140. end
  141. # Sets the loop mode of the Thing's action.
  142. def set_action_loop(action, loop)
  143. Eruta::Thing.set_action_loop(@id, action, loop)
  144. end
  145. # Gets the loop mode of the Thing's action.
  146. def get_action_loop(action)
  147. Eruta::Thing.get_action_loop(@id, action)
  148. end
  149. # Sets the loop mode of the Thing's pose and direction sprite.
  150. def set_pose_direction_loop(pose, direction, loop)
  151. Eruta::Thing.set_pose_direction_loop(@id, pose, direction, loop)
  152. end
  153. # Gets the loop mode of the Thing's pose and direction sprite.
  154. def get_pose_direction_loop(pose, direction)
  155. Eruta::Thing.get_pose_direction_loop(@id, pose, direction)
  156. end
  157. # Gets the status of the Thing's action.
  158. def action_done?(action)
  159. Eruta::Thing.action_done?(@id, action)
  160. end
  161. # Sets the action to loop mode.
  162. def loop_action(action)
  163. self.set_action_loop(action, Eruta::Sprite::State::ACTION_LOOP)
  164. end
  165. # Sets the action to one shot mode.
  166. def one_shot_action(action)
  167. self.set_action_loop(action, Sprite::State::ACTION_ONESHOT)
  168. end
  169. # Sets actions that should probably be one-shot to one shot.
  170. def one_shot_default()
  171. poses = [ Sprite::SLASH, Sprite::CAST,
  172. Sprite::STAB, Sprite::SHOOT,
  173. Sprite::HURT ]
  174. directions = [ Sprite::NORTH, Sprite::EAST, Sprite::SOUTH, Sprite::WEST ]
  175. poses.each do | pose |
  176. directions.each do | direction |
  177. self.set_pose_direction_loop(pose, direction, Sprite::State::ACTION_ONESHOT)
  178. end
  179. end
  180. # the "Drop down" action is a one stop action in ULPCSS sprites.
  181. res = self.set_pose_direction_loop(Sprite::DOWN, Sprite::ALL_DIRECTIONS, Sprite::State::ACTION_ONESTOP)
  182. end
  183. # Sets a flag of the main hull (physical presence) of the thing
  184. forward_thing :set_hull_flag
  185. # Unsets a flag of the main hull (physical presence) of the thing
  186. forward_thing :unset_hull_flag
  187. # Sets all flags of the main hull (physical presence) of the thing
  188. forward_thing :hull_flags=
  189. # Gets all flags of the main hull (physical presence) of the thing
  190. forward_thing :hull_flags
  191. # Sets the group of the thing
  192. forward_thing :group=
  193. # Gets the group of the thing
  194. forward_thing :group
  195. # Loads a sprite sheet with built in layout as a layer
  196. # of the sprite of this thing.
  197. def load_builtin(layer, vpath, layout = :ulpcss)
  198. return nil unless @sprite
  199. @sprite.load_builtin(layer, vpath, layout = :ulpcss)
  200. end
  201. # Loads a ULPCSS sprite sheet with built in layout as a layer
  202. # of the sprite of this thing.
  203. def load_ulpcss(layer, vpath)
  204. return nil unless @sprite
  205. @sprite.load_ulpcss(layer, vpath)
  206. end
  207. # Loads a ULPCSS sprite sheet for an oversized slashing weapon
  208. # with built in layout as a layer of the sprite of this thing..
  209. def load_ulpcss_slash(layer, vpath)
  210. return nil unless @sprite
  211. @sprite.load_ulpcss_slash(layer, vpath)
  212. end
  213. # Loads a ULPCSS sprite sheet for an oversized stabbing weapon
  214. # with built in layout as a layer of the sprite of this thing..
  215. def load_ulpcss_stab(layer, vpath)
  216. return nil unless @sprite
  217. @sprite.load_ulpcss_stab(layer, vpath)
  218. end
  219. # React to sprite event
  220. def on_sprite(spriteid, pose, direction, kind)
  221. p "Sprite event for #{name} #{spriteid}, #{pose}, #{direction}, #{kind}"
  222. p "Check: #{Sprite::SLASH} (#{Sprite::STAB}) #{Sprite::DOWN}"
  223. if (pose & Sprite::SLASH) == Sprite::SLASH
  224. p "Sprite event on attack"
  225. Attack.on_sprite(@id)
  226. end
  227. end
  228. # React to a collision event
  229. def on_bump(thing2, h1 = nil, h2 = nil)
  230. # split up per kind of thing, which will be a pain...
  231. end
  232. # Deletes the thing
  233. def delete
  234. Thing.unregister(self)
  235. Eruta::Thing.delete(@id)
  236. @id = nil
  237. return nil
  238. end
  239. end