lotu 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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