lotu 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -3,11 +3,7 @@ LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
3
3
  require File.expand_path(LIB_PATH)
4
4
  include Gosu::Button
5
5
 
6
- class Player < Lotu::Actor
7
- is_drawable
8
- is_controllable
9
-
10
- attr_reader :speed
6
+ class MovingRuby < Lotu::Actor
11
7
 
12
8
  def initialize
13
9
  super
@@ -34,30 +30,26 @@ class Player < Lotu::Actor
34
30
  @y += 1
35
31
  end
36
32
 
37
- def warp(x, y)
38
- @x, @y = x, y
39
- end
40
33
  end
41
34
 
42
35
  class Example < Lotu::Window
43
- is_controllable
44
- is_resourceful
45
36
 
46
37
  def initialize
47
38
  super
48
39
  set_keys KbEscape => :close
40
+
49
41
  with_path(__FILE__) do
50
42
  load_images '../media'
51
- load_sounds '../media'
52
43
  end
53
44
 
54
- @player = Player.new
45
+ @ruby = MovingRuby.new
55
46
  end
56
47
 
57
48
  def draw
58
49
  super
59
50
  @fps_counter.draw
60
51
  end
52
+
61
53
  end
62
54
 
63
55
  Example.new.show
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
3
+ require File.expand_path(LIB_PATH)
4
+ include Gosu::Button
5
+
6
+ class WarpingRuby < Lotu::Actor
7
+ def initialize
8
+ super
9
+ set_image 'CptnRuby Gem.png'
10
+ end
11
+
12
+ def warp(x, y)
13
+ @x, @y = x, y
14
+ end
15
+ end
16
+
17
+ class Example < Lotu::Window
18
+ def initialize
19
+ super
20
+ set_keys KbEscape => :close
21
+
22
+ with_path __FILE__ do
23
+ load_images '../media'
24
+ end
25
+
26
+ @ruby = WarpingRuby.new
27
+ @cursor1 = Lotu::Cursor.new(:image => 'crosshair.png',
28
+ :keys => {MsLeft => [:click, false]})
29
+ @cursor2 = Lotu::Cursor.new(:image => 'crosshair.png',
30
+ :use_mouse => false,
31
+ :keys => {
32
+ KbSpace => [:click, false],
33
+ KbUp => :up,
34
+ KbDown => :down,
35
+ KbLeft => :left,
36
+ KbRight => :right
37
+ })
38
+
39
+ @cursor1.on(:click) do |x,y|
40
+ @ruby.warp(x,y)
41
+ end
42
+ @cursor2.on(:click) do |x,y|
43
+ @ruby.warp(x,y)
44
+ end
45
+ end
46
+
47
+ def draw
48
+ super
49
+ @fps_counter.draw
50
+ @font.draw("@cursor1: #{@cursor1.clicked_x}, #{@cursor1.clicked_y}", 10, 30, 0, 1.0, 1.0, 0xfffff000)
51
+ @font.draw("@cursor2: #{@cursor2.clicked_x}, #{@cursor2.clicked_y}", 10, 30+@font.height, 0, 1.0, 1.0, 0xfffff000)
52
+ end
53
+ end
54
+
55
+ Example.new.show
data/lib/lotu/actor.rb CHANGED
@@ -1,18 +1,25 @@
1
1
  module Lotu
2
2
  class Actor
3
- extend HasBehavior
4
-
5
3
  attr_accessor :parent, :x, :y
6
4
 
7
5
  def initialize(opts={})
8
- super()
9
- @x = opts[:x] || 0
10
- @y = opts[:y] || 0
6
+ default_opts = {
7
+ :x => 0,
8
+ :y => 0,
9
+ :color => 0xffffffff
10
+ }
11
+ opts = default_opts.merge!(opts)
12
+ @x = opts[:x]
13
+ @y = opts[:y]
14
+ @color = opts[:color]
11
15
  @parent = $window
12
16
  @parent.update_queue << self
13
17
 
14
- # Initialize the behaviors included in subclasses
15
- init_behavior
18
+ # Add extra functionality
19
+ self.extend Drawable
20
+ self.extend Controllable
21
+ self.extend Eventful
22
+ self.extend Collidable
16
23
  end
17
24
 
18
25
  # Easy access to delta-time
@@ -25,8 +32,6 @@ module Lotu
25
32
  @parent.update_queue.delete(self)
26
33
  end
27
34
 
28
- # Meant to be overriden by behaviors
29
- def init_behavior;end
30
35
  def update;end
31
36
  end
32
37
  end
@@ -0,0 +1,27 @@
1
+ module Lotu
2
+ module Collidable
3
+
4
+ def self.extended(instance)
5
+ instance.init_behavior
6
+ end
7
+
8
+ def init_behavior
9
+ @collision_tag = nil
10
+ end
11
+
12
+ def collides_as(tag)
13
+ @collision_tag = tag
14
+ @parent.systems[:collision].add_entity(self, tag)
15
+ end
16
+
17
+ def collides_with(other)
18
+ Gosu.distance(@x, @y, other.x, other.y) < @collision_radius + other.collision_radius
19
+ end
20
+
21
+ def die
22
+ super
23
+ @parent.systems[:collision].remove_entity(self, @collision_tag)
24
+ end
25
+
26
+ end
27
+ end
@@ -51,5 +51,6 @@ module Lotu
51
51
  def button_up(id)
52
52
  @actions.delete(@keys[id])
53
53
  end
54
+
54
55
  end
55
56
  end
@@ -1,28 +1,28 @@
1
1
  # Convenience module to set up an InputController
2
2
  module Lotu
3
3
  module Controllable
4
- def is_controllable
5
- include InstanceMethods
4
+
5
+ def self.extended(instance)
6
+ instance.init_behavior
7
+ end
8
+
9
+ def init_behavior
10
+ @input_controller = nil
6
11
  end
7
12
 
8
- module InstanceMethods
9
- def init_behavior
10
- super
11
- @_input_controller = nil
12
- end
13
- # This will call #go_up every game loop
14
- # Gosu::Button::KbUp => :go_up
15
- # This is the same as the above
16
- # Gosu::Button::KbUp => [:go_up, 0]
17
- #
18
- # This will call #go_up once
19
- # Gosu::Button::KbUp => [:go_up, false]
20
- #
21
- # This will call #go_up every 50ms
22
- # Gosu::Button::KbUp => [:go_up, 50]
23
- def set_keys(keys)
24
- @_input_controller = InputController.new(self, keys)
25
- end
13
+ # This will call #go_up every game loop
14
+ # Gosu::Button::KbUp => :go_up
15
+ # This is the same as the above
16
+ # Gosu::Button::KbUp => [:go_up, 0]
17
+ #
18
+ # This will call #go_up once
19
+ # Gosu::Button::KbUp => [:go_up, false]
20
+ #
21
+ # This will call #go_up every 50ms
22
+ # Gosu::Button::KbUp => [:go_up, 50]
23
+ def set_keys(keys)
24
+ @input_controller = InputController.new(self, keys)
26
25
  end
26
+
27
27
  end
28
28
  end
@@ -1,28 +1,36 @@
1
1
  module Lotu
2
2
  module Drawable
3
- def is_drawable
4
- include InstanceMethods
3
+
4
+ def self.extended(instance)
5
+ instance.init_behavior
5
6
  end
6
7
 
7
- module InstanceMethods
8
- def init_behavior
9
- super
10
- @_image = nil
11
- end
8
+ def init_behavior
9
+ @image = nil
10
+ @color = 0xffffffff
11
+ @z = 0
12
+ @angle = 0.0
13
+ @center_x = 0.5
14
+ @center_y = 0.5
15
+ @factor_x = 1.0
16
+ @factor_y = 1.0
17
+ @color = 0xffffffff
18
+ @mode = :default
19
+ end
12
20
 
13
- def set_image(image)
14
- @_image = $window.image(image)
15
- @parent.draw_queue << self unless @parent.draw_queue.include?(self)
16
- end
21
+ def set_image(image)
22
+ @image = @parent.image(image)
23
+ @parent.draw_queue << self unless @parent.draw_queue.include?(self)
24
+ end
17
25
 
18
- def draw
19
- @_image.draw(@x,@y,0)
20
- end
26
+ def draw
27
+ @image.draw_rot(@x, @y, @z, @angle, @center_x, @center_y, @factor_x, @factor_y, @color, @mode)
28
+ end
21
29
 
22
- def die
23
- super
24
- @parent.draw_queue.delete(self)
25
- end
30
+ def die
31
+ super
32
+ @parent.draw_queue.delete(self)
26
33
  end
34
+
27
35
  end
28
36
  end
@@ -17,23 +17,22 @@
17
17
 
18
18
  module Lotu
19
19
  module Eventful
20
- def is_eventful
21
- include InstanceMethods
20
+
21
+ def self.extended(instance)
22
+ instance.init_behavior
22
23
  end
23
24
 
24
- module InstanceMethods
25
- def init_behavior
26
- super
27
- @_events = {}
28
- end
25
+ def init_behavior
26
+ @events = {}
27
+ end
29
28
 
30
- def on(event, &blk)
31
- @_events[event] = blk
32
- end
29
+ def on(event, &blk)
30
+ @events[event] = blk
31
+ end
33
32
 
34
- def fire(event, *args)
35
- @_events[event].call(*args) if @_events[event]
36
- end
33
+ def fire(event, *args)
34
+ @events[event].call(*args) if @events[event]
37
35
  end
36
+
38
37
  end
39
38
  end
@@ -1,64 +1,63 @@
1
1
  # Add methods to load and access images, sounds & songs
2
2
  module Lotu
3
3
  module Resourceful
4
- def is_resourceful
5
- include InstanceMethods
6
- end
7
4
 
8
- module InstanceMethods
9
- def init_behavior
10
- @_images = {}
11
- @_sounds = {}
12
- @_songs = {}
13
- end
5
+ def self.extended(instance)
6
+ instance.init_behavior
7
+ end
14
8
 
15
- def image(name)
16
- @_images[name]
17
- end
9
+ def init_behavior
10
+ @images = {}
11
+ @sounds = {}
12
+ @songs = {}
13
+ end
18
14
 
19
- def sound(name)
20
- @_sounds[name]
21
- end
15
+ def image(name)
16
+ @images[name]
17
+ end
22
18
 
23
- def song(name)
24
- @_songs[name]
25
- end
19
+ def sound(name)
20
+ @sounds[name]
21
+ end
26
22
 
27
- def load_images(path)
28
- load_resources(@_images, /\.png|\.jpg|\.bmp/, path, Gosu::Image)
29
- end
23
+ def song(name)
24
+ @songs[name]
25
+ end
30
26
 
31
- def load_sounds(path)
32
- load_resources(@_sounds, /\.ogg|\.mp3|\.wav/, path, Gosu::Sample)
33
- end
27
+ def load_images(path)
28
+ load_resources(@images, /\.png|\.jpg|\.bmp/, path, Gosu::Image)
29
+ end
34
30
 
35
- def load_songs(path)
36
- load_resources(@_songs, /\.ogg|\.mp3|\.wav/, path, Gosu::Song)
37
- end
31
+ def load_sounds(path)
32
+ load_resources(@sounds, /\.ogg|\.mp3|\.wav/, path, Gosu::Sample)
33
+ end
38
34
 
39
- def with_path(path, &blk)
40
- @_path = File.expand_path(File.dirname path)
41
- yield
42
- end
35
+ def load_songs(path)
36
+ load_resources(@songs, /\.ogg|\.mp3|\.wav/, path, Gosu::Song)
37
+ end
43
38
 
44
- private
45
- def load_resources(container, regexp, path, klass)
46
- path = File.expand_path(File.join(@_path, path))
47
- puts "Loading from: #{path}"
39
+ def with_path(path, &blk)
40
+ @path = File.expand_path(File.dirname path)
41
+ yield
42
+ end
48
43
 
49
- count = 0
50
- Dir.entries(path).select do |entry|
51
- entry =~ regexp
52
- end.each do |entry|
53
- begin
54
- container[entry] = klass.new($window, File.join(path, entry))
55
- count += 1
56
- rescue Exception => e
57
- puts e, File.join(path, entry)
58
- end
44
+ def load_resources(container, regexp, path, klass)
45
+ path = File.expand_path(File.join(@path, path))
46
+ puts "Loading from: #{path}"
47
+
48
+ count = 0
49
+ Dir.entries(path).select do |entry|
50
+ entry =~ regexp
51
+ end.each do |entry|
52
+ begin
53
+ container[entry] = klass.new($window, File.join(path, entry))
54
+ count += 1
55
+ rescue Exception => e
56
+ puts e, File.join(path, entry)
59
57
  end
60
- puts "#{count} #{klass} files loaded."
61
58
  end
59
+ puts "#{count} #{klass} files loaded."
62
60
  end
61
+
63
62
  end
64
63
  end
data/lib/lotu/cursor.rb CHANGED
@@ -4,11 +4,18 @@ module Lotu
4
4
  attr_reader :clicked_x, :clicked_y
5
5
  attr_accessor :speed, :use_mouse
6
6
 
7
- def initialize
7
+ def initialize(opts={})
8
+ default_opts = {
9
+ :use_mouse => true,
10
+ :speed => 100
11
+ }
12
+ opts = default_opts.merge!(opts)
8
13
  super
9
14
  @clicked_x = @clicked_y = 0
10
- @speed = 100
11
- @use_mouse = true
15
+ @speed = opts[:speed]
16
+ @use_mouse = opts[:use_mouse]
17
+ set_image(opts[:image]) unless opts[:image].nil?
18
+ set_keys(opts[:keys]) unless opts[:keys].nil?
12
19
  end
13
20
 
14
21
  def update
@@ -52,5 +59,6 @@ module Lotu
52
59
  @x += @speed * dt
53
60
  adjust_mouse if use_mouse
54
61
  end
62
+
55
63
  end
56
64
  end
@@ -0,0 +1,42 @@
1
+ module Lotu
2
+ module Systems
3
+
4
+ module Collision
5
+ def self.extended(instance)
6
+ instance.systems[:collision] = CollisionSystem.new
7
+ end
8
+ end
9
+
10
+ class CollisionSystem
11
+
12
+ def initialize
13
+ @entities = Hash.new{ |h,k| h[k] = [] }
14
+ @actions = {}
15
+ end
16
+
17
+ def add_entity(obj, tag)
18
+ @entities[tag] << obj
19
+ end
20
+
21
+ def remove_entity(obj, tag)
22
+ @entities[tag].delete(obj)
23
+ end
24
+
25
+ def when_colliding(type1, type2, &blk)
26
+ @actions[[type1, type2]] = blk
27
+ end
28
+
29
+ def update
30
+ @actions.each do |tags, blk|
31
+ @entities[tags[0]].each do |ent1|
32
+ @entities[tags[1]].each do |ent2|
33
+ blk.call(ent1, ent2) if ent1.collides_with(ent2)
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
data/lib/lotu/window.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  module Lotu
2
2
  class Window < Gosu::Window
3
- extend HasBehavior
4
-
5
3
  # delta time
6
- attr_reader :dt
4
+ attr_reader :dt, :systems
7
5
  attr_accessor :update_queue, :draw_queue, :input_listeners, :font
8
6
 
9
7
  def initialize(params={})
@@ -13,16 +11,19 @@ module Lotu
13
11
  $window = self
14
12
 
15
13
  # Systems setup
14
+ @systems = {}
16
15
  @update_queue = []
17
16
  @draw_queue = []
18
17
  @input_register = Hash.new{|hash,key| hash[key] = []}
19
18
 
20
19
  @fps_counter = FpsCounter.new
21
20
  @last_time = Gosu::milliseconds
22
- @font = Gosu::Font.new(self, Gosu::default_font_name, 14)
21
+ @font = Gosu::Font.new(self, Gosu::default_font_name, 20)
23
22
 
24
- # Initialize the behaviors included in subclasses
25
- init_behavior
23
+ # Add extra functionality
24
+ self.extend Controllable
25
+ self.extend Resourceful
26
+ extend Systems::Collision
26
27
  end
27
28
 
28
29
  def update
@@ -31,6 +32,10 @@ module Lotu
31
32
  @last_time = new_time
32
33
  @fps_counter.update(@dt)
33
34
 
35
+ @systems.each_value do |system|
36
+ system.update
37
+ end
38
+
34
39
  @update_queue.each do |item|
35
40
  item.update
36
41
  end
@@ -65,8 +70,5 @@ module Lotu
65
70
  def register_for_draw(object)
66
71
  @draw_queue << object
67
72
  end
68
-
69
- # Meant to be overriden by behaviors
70
- def init_behavior;end
71
73
  end
72
74
  end
data/lib/lotu.rb CHANGED
@@ -2,5 +2,6 @@ LOTU_ROOT = File.expand_path(File.join(File.dirname(__FILE__), 'lotu'))
2
2
  $LOAD_PATH.unshift(LOTU_ROOT)
3
3
 
4
4
  require 'gosu'
5
- %w{controllable resourceful drawable input_controller eventful has_behavior}.each{|file| require "behaviors/#{file}"}
5
+ %w{collidable controllable resourceful drawable controllable/input_controller eventful}.each{|file| require "behaviors/#{file}"}
6
+ %w{collision}.each{|file| require "systems/#{file}"}
6
7
  %w{fps actor cursor window}.each{|file| require file}
data/lotu.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{lotu}
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["lobo_tuerto"]
12
- s.date = %q{2010-03-17}
12
+ s.date = %q{2010-03-19}
13
13
  s.description = %q{lotu aims to bring an agile and simple game development framework to life. It provides useful abstractions so you can concentrate on developing your game.}
14
14
  s.email = %q{dev@lobotuerto.com}
15
15
  s.extra_rdoc_files = [
@@ -42,17 +42,18 @@ Gem::Specification.new do |s|
42
42
  "examples/media/crosshair.png",
43
43
  "examples/media/lobo_tuerto.png",
44
44
  "examples/media/title.png",
45
- "examples/mouse_pointer/mouse.rb",
45
+ "examples/mouse_pointer/mouse_pointer.rb",
46
46
  "lib/lotu.rb",
47
47
  "lib/lotu/actor.rb",
48
+ "lib/lotu/behaviors/collidable.rb",
48
49
  "lib/lotu/behaviors/controllable.rb",
50
+ "lib/lotu/behaviors/controllable/input_controller.rb",
49
51
  "lib/lotu/behaviors/drawable.rb",
50
52
  "lib/lotu/behaviors/eventful.rb",
51
- "lib/lotu/behaviors/has_behavior.rb",
52
- "lib/lotu/behaviors/input_controller.rb",
53
53
  "lib/lotu/behaviors/resourceful.rb",
54
54
  "lib/lotu/cursor.rb",
55
55
  "lib/lotu/fps.rb",
56
+ "lib/lotu/systems/collision.rb",
56
57
  "lib/lotu/window.rb",
57
58
  "lotu.gemspec"
58
59
  ]
@@ -63,7 +64,7 @@ Gem::Specification.new do |s|
63
64
  s.summary = %q{A simple, agile Ruby game development framework.}
64
65
  s.test_files = [
65
66
  "examples/hello_world/hello_world.rb",
66
- "examples/mouse_pointer/mouse.rb"
67
+ "examples/mouse_pointer/mouse_pointer.rb"
67
68
  ]
68
69
 
69
70
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - lobo_tuerto
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-17 00:00:00 -06:00
17
+ date: 2010-03-19 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -66,17 +66,18 @@ files:
66
66
  - examples/media/crosshair.png
67
67
  - examples/media/lobo_tuerto.png
68
68
  - examples/media/title.png
69
- - examples/mouse_pointer/mouse.rb
69
+ - examples/mouse_pointer/mouse_pointer.rb
70
70
  - lib/lotu.rb
71
71
  - lib/lotu/actor.rb
72
+ - lib/lotu/behaviors/collidable.rb
72
73
  - lib/lotu/behaviors/controllable.rb
74
+ - lib/lotu/behaviors/controllable/input_controller.rb
73
75
  - lib/lotu/behaviors/drawable.rb
74
76
  - lib/lotu/behaviors/eventful.rb
75
- - lib/lotu/behaviors/has_behavior.rb
76
- - lib/lotu/behaviors/input_controller.rb
77
77
  - lib/lotu/behaviors/resourceful.rb
78
78
  - lib/lotu/cursor.rb
79
79
  - lib/lotu/fps.rb
80
+ - lib/lotu/systems/collision.rb
80
81
  - lib/lotu/window.rb
81
82
  - lotu.gemspec
82
83
  has_rdoc: true
@@ -111,4 +112,4 @@ specification_version: 3
111
112
  summary: A simple, agile Ruby game development framework.
112
113
  test_files:
113
114
  - examples/hello_world/hello_world.rb
114
- - examples/mouse_pointer/mouse.rb
115
+ - examples/mouse_pointer/mouse_pointer.rb
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env ruby
2
- LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
3
- require File.expand_path(LIB_PATH)
4
- include Gosu::Button
5
-
6
- class Cursor < Lotu::Cursor
7
- is_eventful
8
- is_controllable
9
- is_drawable
10
-
11
- def initialize
12
- super
13
- set_keys(MsLeft => [:click, false],
14
- KbSpace => [:click, false],
15
- KbUp => :up,
16
- KbDown => :down,
17
- KbLeft => :left,
18
- KbRight => :right)
19
- end
20
- end
21
-
22
- class Player < Lotu::Actor
23
- is_drawable
24
- is_controllable
25
-
26
- attr_reader :speed
27
-
28
- def initialize
29
- super
30
- set_image 'CptnRuby Gem.png'
31
- set_keys(KbRight => :move_right,
32
- KbLeft => :move_left,
33
- KbUp => :move_up,
34
- KbDown => :move_down)
35
- end
36
-
37
- def move_right
38
- @x += 1
39
- end
40
-
41
- def move_left
42
- @x -= 1
43
- end
44
-
45
- def move_up
46
- @y -= 1
47
- end
48
-
49
- def move_down
50
- @y += 1
51
- end
52
-
53
- def warp(x, y)
54
- @x, @y = x, y
55
- end
56
- end
57
-
58
- class Example < Lotu::Window
59
- is_controllable
60
- is_resourceful
61
-
62
- def initialize
63
- super
64
- set_keys KbEscape => :close
65
- with_path __FILE__ do
66
- load_images '../media'
67
- load_sounds '../media'
68
- end
69
-
70
- @player = Player.new
71
- @font = Gosu::Font.new(self, Gosu::default_font_name, 20)
72
- @cursor = Cursor.new
73
- @cursor.set_image('crosshair.png')
74
- @cursor.on(:click) do |x,y|
75
- @player.warp(x,y)
76
- end
77
- end
78
-
79
- def draw
80
- super
81
- @fps_counter.draw
82
- @font.draw("Clicked on? #{@cursor.clicked_x}, #{@cursor.clicked_y}", 10, 30, 0, 1.0, 1.0, 0xfffff000)
83
- end
84
- end
85
-
86
- Example.new.show
@@ -1,8 +0,0 @@
1
- module Lotu
2
- module HasBehavior
3
- include Eventful
4
- include Controllable
5
- include Drawable
6
- include Resourceful
7
- end
8
- end