lotu 0.1.11 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/examples/hello_world/moving_portraits.rb +92 -0
- data/examples/screen_cursor/mouse_and_keyboard_cursors.rb +141 -0
- data/examples/steering_behaviors/pursuit_and_evade.rb +109 -0
- data/examples/steering_behaviors/pursuit_and_evade_multiple.rb +116 -0
- data/lib/lotu/actor.rb +39 -9
- data/lib/lotu/cursor.rb +2 -2
- data/lib/lotu/game.rb +34 -10
- data/lib/lotu/systems/steering_system.rb +31 -9
- data/lib/lotu/systems/transformation_system.rb +122 -0
- data/lib/lotu/text_box.rb +14 -2
- data/lib/lotu.rb +1 -1
- data/lotu.gemspec +11 -8
- metadata +12 -9
- data/examples/hello_world/hello_world.rb +0 -77
- data/examples/mouse_pointer/mouse_pointer.rb +0 -92
- data/examples/steering_behaviors/steering.rb +0 -86
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.12
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Hello world for lotu
|
4
|
+
# Here you will learn about:
|
5
|
+
# * Loading image resources
|
6
|
+
# * Binding keys to window and actors
|
7
|
+
# * How to display text on screen using a text box
|
8
|
+
|
9
|
+
|
10
|
+
LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
|
11
|
+
require File.expand_path(LIB_PATH)
|
12
|
+
|
13
|
+
include Gosu
|
14
|
+
include Lotu
|
15
|
+
|
16
|
+
# We want to move something around the screen so we create a new Actor
|
17
|
+
# subclass, set the image all instances of it are going to use and
|
18
|
+
# define the movement methods
|
19
|
+
class Lobo < Actor
|
20
|
+
|
21
|
+
def initialize(opts={})
|
22
|
+
# It's important to call super so we take advantage of automatic
|
23
|
+
# management for this object (being added to draw and update queue)
|
24
|
+
super
|
25
|
+
# Use the image which filename is "lobo_tuerto.png", and scale
|
26
|
+
# it's appearance to half width and half height
|
27
|
+
set_image 'lobo_tuerto.png', :factor_x => 0.5, :factor_y => 0.5
|
28
|
+
end
|
29
|
+
|
30
|
+
# Let's define some basic movement methods
|
31
|
+
def move_right; @x += 1 end
|
32
|
+
def move_left; @x -= 1 end
|
33
|
+
def move_up; @y -= 1 end
|
34
|
+
def move_down; @y += 1 end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
# Let's subclass the Game class and write some code!
|
39
|
+
class Portraits < Game
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
# This will call the hooks:
|
43
|
+
# load_resources, setup_systems, setup_input and setup_actors
|
44
|
+
# declared in the parent class
|
45
|
+
super
|
46
|
+
# When the Escape key is pressed, call the close method on
|
47
|
+
# instance of class Portraits, when D key is pressed turn on
|
48
|
+
# debug, we pass false into the array to tell the input system we
|
49
|
+
# don't want autofire on, else pass the number of milliseconds
|
50
|
+
# (zero and no array is the same)
|
51
|
+
set_keys(KbEscape => :close,
|
52
|
+
KbD => [:debug!, false])
|
53
|
+
end
|
54
|
+
|
55
|
+
# This method is called when we call super inside initialize
|
56
|
+
def load_resources
|
57
|
+
# From this file,
|
58
|
+
with_path_from_file(__FILE__) do
|
59
|
+
# go back one dir and search inside media/images
|
60
|
+
load_images '../media/images'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# This method is called when we call super inside initialize
|
65
|
+
def setup_actors
|
66
|
+
# Create a lobo in the middle of the screen
|
67
|
+
@lobo1 = Lobo.new(:x => width/2, :y => height/2)
|
68
|
+
# Map keys to some methods
|
69
|
+
@lobo1.set_keys(KbRight => :move_right,
|
70
|
+
KbLeft => :move_left,
|
71
|
+
KbUp => :move_up,
|
72
|
+
KbDown => :move_down)
|
73
|
+
|
74
|
+
# Rinse and repeat... but invert some keys
|
75
|
+
@lobo2 = Lobo.new(:x => width/2, :y => height/2)
|
76
|
+
@lobo2.set_keys(KbRight => :move_left,
|
77
|
+
KbLeft => :move_right,
|
78
|
+
KbUp => :move_up,
|
79
|
+
KbDown => :move_down)
|
80
|
+
|
81
|
+
# Create a TextBox so we can display a message on screen
|
82
|
+
@info = TextBox.new
|
83
|
+
# Add some text
|
84
|
+
@info.text("Hello world!")
|
85
|
+
# Add more text, but specify the color and size in pixels
|
86
|
+
@info.text("Move the portraits around with arrow keys", :size => 16, :color => 0xff33ccff)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
# Create and show the app
|
92
|
+
Portraits.new.show
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# lotu's cursors
|
4
|
+
# Here you will learn about:
|
5
|
+
# * The Cursor class included in lotu
|
6
|
+
# * How to register events
|
7
|
+
# * How to use the systems provided by lotu
|
8
|
+
|
9
|
+
LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
|
10
|
+
require File.expand_path(LIB_PATH)
|
11
|
+
|
12
|
+
include Gosu
|
13
|
+
include Lotu
|
14
|
+
|
15
|
+
# Create a class for displaying something on screen
|
16
|
+
class Lobo < Actor
|
17
|
+
def initialize(opts={})
|
18
|
+
super
|
19
|
+
set_image 'lobo_tuerto.png', :width => 100
|
20
|
+
end
|
21
|
+
|
22
|
+
# Define a method for teleporting our instances around
|
23
|
+
def teleport(x, y)
|
24
|
+
@x, @y = x, y
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Cursors < Game
|
29
|
+
def initialize
|
30
|
+
# This will call the hooks:
|
31
|
+
# load_resources, setup_systems, setup_input and setup_actors
|
32
|
+
# declared in the parent class
|
33
|
+
super
|
34
|
+
# Custom setup methods for this class
|
35
|
+
setup_events
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_resources
|
39
|
+
with_path_from_file(__FILE__) do
|
40
|
+
load_images '../media/images'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def setup_systems
|
45
|
+
# It's important to call super here to setup the InputSystem in
|
46
|
+
# the parent class
|
47
|
+
super
|
48
|
+
# To use the systems lotu provides, you just "use" them
|
49
|
+
# Let's activate the FPS system, so we can track the frames per
|
50
|
+
#second our app is pushing out
|
51
|
+
use(FpsSystem)
|
52
|
+
# Activate the stalker system to track how many objects of these
|
53
|
+
# classes are around
|
54
|
+
use(StalkerSystem, :stalk => [Actor, Cursor, TextBox, Lobo, Object])
|
55
|
+
end
|
56
|
+
|
57
|
+
# Setup some input handling for our Cursors app
|
58
|
+
def setup_input
|
59
|
+
set_keys(KbEscape => :close,
|
60
|
+
KbD => [:debug!, false],
|
61
|
+
KbT => [:toggle_text, false])
|
62
|
+
end
|
63
|
+
|
64
|
+
# Now onto define some events
|
65
|
+
def setup_events
|
66
|
+
# When the left mouse button is clicked (as defined below in
|
67
|
+
# setup_actors) call the teleport method in @lobo
|
68
|
+
@cursor1.on(:click) do |x,y|
|
69
|
+
@lobo.teleport(x,y)
|
70
|
+
end
|
71
|
+
# When the space bar is pressed (see below in setup_actors) call
|
72
|
+
# the teleport method in @lobo
|
73
|
+
@cursor2.on(:click) do |x,y|
|
74
|
+
@lobo.teleport(x,y)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup_actors
|
79
|
+
# Create a portrait to teleport around with "clicks"
|
80
|
+
@lobo = Lobo.new(:x => width/2, :y => height/2)
|
81
|
+
|
82
|
+
# The cursor class defines a method named (you guessed) "click",
|
83
|
+
# when this method is called, it fires an event named (again)
|
84
|
+
# "click", that's why we attached some code to that event in
|
85
|
+
# setup_events
|
86
|
+
@cursor1 = Cursor.new(:image => 'crosshair-1.png',
|
87
|
+
:keys => {MsLeft => [:click, false]},
|
88
|
+
:width => 100,
|
89
|
+
:rand_color => true,
|
90
|
+
:mode => :additive)
|
91
|
+
@cursor1.transform_angle(:init => 0, :end => 359, :duration => 10, :loop => true)
|
92
|
+
|
93
|
+
@cursor2 = Cursor.new(:image => 'crosshair-2.png',
|
94
|
+
:use_mouse => false,
|
95
|
+
:keys => {
|
96
|
+
KbSpace => [:click, false],
|
97
|
+
KbUp => :up,
|
98
|
+
KbDown => :down,
|
99
|
+
KbLeft => :left,
|
100
|
+
KbRight => :right},
|
101
|
+
:width => 100,
|
102
|
+
:rand_color => true,
|
103
|
+
:mode => :additive)
|
104
|
+
@cursor2.transform_angle(:init => 359, :end => 0, :duration => 1, :loop => true)
|
105
|
+
|
106
|
+
# Center @cursor2 vertically and move it to the right 3/4 of the
|
107
|
+
# screen
|
108
|
+
@cursor2.x = width*3/4
|
109
|
+
@cursor2.y = height/2
|
110
|
+
|
111
|
+
# Here we tell the TextBox to watch some objects, the TextBox will
|
112
|
+
# call the to_s method on the objects it's watching
|
113
|
+
# Create a TextBox with default option :size => 15
|
114
|
+
@info = TextBox.new(:size => 15)
|
115
|
+
@info.text("Press T to hide this text", :size => 24)
|
116
|
+
# Watch the FPS, so we get a nice FPS report on the screen
|
117
|
+
@info.watch(@systems[FpsSystem], :size => 20)
|
118
|
+
# Watch the Stalker system, so we know how many objects of the
|
119
|
+
# classes we specified up in setup_systems are around
|
120
|
+
@info.watch(@systems[StalkerSystem], :color => 0xff3ffccf)
|
121
|
+
# We can change the size for a specific line of text
|
122
|
+
@info.text("@cursor1 data:", :size => 20)
|
123
|
+
@info.text("move with Mouse | click with LeftMouseButton")
|
124
|
+
# And color
|
125
|
+
@info.watch(@cursor1, :color => @cursor1.color)
|
126
|
+
|
127
|
+
# Lets watch @cursor2 too
|
128
|
+
@info.text("@cursor2 data:", :size => 20)
|
129
|
+
@info.text("move with Arrow keys | click with Space")
|
130
|
+
@info.watch(@cursor2, :color => @cursor2.color)
|
131
|
+
@info.text("click to teleport the portrait!")
|
132
|
+
end
|
133
|
+
|
134
|
+
def toggle_text
|
135
|
+
@info.toggle!
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
# Create and start the game loop by showing the app
|
141
|
+
Cursors.new.show
|
@@ -0,0 +1,109 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Here you will learn about:
|
4
|
+
# * The steering system
|
5
|
+
# * How to play animations
|
6
|
+
# * How to attach a text box to an actor
|
7
|
+
|
8
|
+
LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
|
9
|
+
require File.expand_path(LIB_PATH)
|
10
|
+
|
11
|
+
include Gosu
|
12
|
+
include Lotu
|
13
|
+
|
14
|
+
# Let's define a Missile class that will use a Steering system to
|
15
|
+
# control it's movement
|
16
|
+
class Missile < Actor
|
17
|
+
def initialize(opts={})
|
18
|
+
super
|
19
|
+
# Activate the steering system and pass the opts, since they might
|
20
|
+
# have some config info for the system
|
21
|
+
use(SteeringSystem, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
def teleport(x, y)
|
25
|
+
@pos.x, @pos.y = x, y
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# The main app class
|
30
|
+
class SteeringMissiles < Game
|
31
|
+
def initialize
|
32
|
+
# This will call the hooks:
|
33
|
+
# load_resources, setup_systems, setup_input and setup_actors
|
34
|
+
# declared in the parent class
|
35
|
+
super
|
36
|
+
# Custom setup methods for this class
|
37
|
+
setup_events
|
38
|
+
end
|
39
|
+
|
40
|
+
# Let's load some images and animations, check out the animations
|
41
|
+
# directory, the animation there was created with:
|
42
|
+
# {Sprite Sheet Packer}[http://spritesheetpacker.codeplex.com/]
|
43
|
+
def load_resources
|
44
|
+
with_path_from_file(__FILE__) do
|
45
|
+
load_images '../media/images'
|
46
|
+
load_animations '../media/animations'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup_input
|
51
|
+
set_keys(KbEscape => :close,
|
52
|
+
MsRight => :teleport_big_missile_to_midscreen,
|
53
|
+
KbD => [:debug!, false],
|
54
|
+
KbT => [:toggle_missile_info, false])
|
55
|
+
end
|
56
|
+
|
57
|
+
def setup_systems
|
58
|
+
# It's important to call super here to setup the InputSystem
|
59
|
+
super
|
60
|
+
use(FpsSystem)
|
61
|
+
use(StalkerSystem, :stalk => [Actor, Missile, Vector2d, Object])
|
62
|
+
end
|
63
|
+
|
64
|
+
def setup_actors
|
65
|
+
@big_missile = Missile.new(:mass => 0.3, :max_speed => 100, :max_turn_rate => 140)
|
66
|
+
@big_missile.teleport(width/2, height/2)
|
67
|
+
@big_missile.activate(:evade)
|
68
|
+
@big_missile.play_animation('missile.png')
|
69
|
+
|
70
|
+
@little_missile = Missile.new
|
71
|
+
@little_missile.activate(:pursuit)
|
72
|
+
@little_missile.play_animation('missile.png', :fps => 60, :height => 20)
|
73
|
+
|
74
|
+
@cursor = Cursor.new(:image => 'crosshair-3.png',
|
75
|
+
:keys => {MsLeft => [:click, false]},
|
76
|
+
:rand_color => true)
|
77
|
+
|
78
|
+
@window_info = TextBox.new(:size => 15)
|
79
|
+
@window_info.text("Press T to hide this text", :size => 24)
|
80
|
+
@window_info.watch(@systems[FpsSystem], :size => 20)
|
81
|
+
@window_info.watch(@systems[StalkerSystem], :color => 0xff33ccff)
|
82
|
+
@window_info.watch(@cursor, :color => @cursor.color)
|
83
|
+
@window_info.text("Click to start the simulation", :color => 0xffffff00)
|
84
|
+
@window_info.text("One will pursuit while the other evades, right click to center evader on screen")
|
85
|
+
|
86
|
+
@missile_info = TextBox.new(:attach_to => @big_missile, :size => 14)
|
87
|
+
@missile_info.watch(@big_missile)
|
88
|
+
end
|
89
|
+
|
90
|
+
def setup_events
|
91
|
+
@cursor.on(:click) do |x,y|
|
92
|
+
@big_missile.pursuer = @little_missile
|
93
|
+
@little_missile.evader = @big_missile
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def teleport_big_missile_to_midscreen
|
98
|
+
@big_missile.pos.x = width/2
|
99
|
+
@big_missile.pos.y = height/2
|
100
|
+
end
|
101
|
+
|
102
|
+
def toggle_missile_info
|
103
|
+
@missile_info.toggle!
|
104
|
+
@window_info.toggle!
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Create and start the application
|
109
|
+
SteeringMissiles.new.show
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Here you will learn about:
|
4
|
+
# * The steering system pursuit, and evade_multiple behaviors
|
5
|
+
# * How to play animations
|
6
|
+
# * How to attach a text box to an actor
|
7
|
+
|
8
|
+
LIB_PATH = File.join(File.dirname(__FILE__), '..', '..', 'lib', 'lotu.rb')
|
9
|
+
require File.expand_path(LIB_PATH)
|
10
|
+
|
11
|
+
include Gosu
|
12
|
+
include Lotu
|
13
|
+
|
14
|
+
# Let's define a Missile class that will use a Steering system to
|
15
|
+
# control it's movement
|
16
|
+
class Missile < Actor
|
17
|
+
def initialize(opts={})
|
18
|
+
super
|
19
|
+
# Activate the steering system and pass the opts, since they might
|
20
|
+
# have some config info for the system
|
21
|
+
use(SteeringSystem, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
def teleport(x, y)
|
25
|
+
@pos.x, @pos.y = x, y
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# The main app class
|
30
|
+
class EvadeMultiple < Game
|
31
|
+
def initialize
|
32
|
+
# This will call the hooks:
|
33
|
+
# load_resources, setup_systems, setup_input and setup_actors
|
34
|
+
# declared in the parent class
|
35
|
+
super
|
36
|
+
# Custom setup methods for this class
|
37
|
+
setup_events
|
38
|
+
end
|
39
|
+
|
40
|
+
# Let's load some images and animations, check out the animations
|
41
|
+
# directory, the animation there was created with:
|
42
|
+
# {Sprite Sheet Packer}[http://spritesheetpacker.codeplex.com/]
|
43
|
+
def load_resources
|
44
|
+
with_path_from_file(__FILE__) do
|
45
|
+
load_images '../media/images'
|
46
|
+
load_animations '../media/animations'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup_input
|
51
|
+
set_keys(KbEscape => :close,
|
52
|
+
MsRight => :teleport_big_missile_to_midscreen,
|
53
|
+
KbD => [:debug!, false],
|
54
|
+
KbT => [:toggle_info, false],
|
55
|
+
KbSpace => [:pause!, false])
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup_systems
|
59
|
+
# It's important to call super here to setup the InputSystem
|
60
|
+
super
|
61
|
+
use(FpsSystem)
|
62
|
+
use(StalkerSystem, :stalk => [Actor, Missile, Vector2d, Object])
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup_actors
|
66
|
+
@big_missile = Missile.new(:mass => 0.3, :max_speed => 100, :max_turn_rate => 140)
|
67
|
+
@big_missile.teleport(width/2, height/2)
|
68
|
+
@big_missile.activate(:evade_multiple)
|
69
|
+
@big_missile.play_animation('missile.png')
|
70
|
+
|
71
|
+
@little_missiles = []
|
72
|
+
5.times do |i|
|
73
|
+
@little_missiles << Missile.new(:x => 200 - rand(400), :y => 200 - rand(400), :rand_color => true)
|
74
|
+
@little_missiles[i].activate(:pursuit)
|
75
|
+
@little_missiles[i].play_animation('missile.png', :fps => 60+rand(60), :height => 10+rand(30))
|
76
|
+
end
|
77
|
+
|
78
|
+
@cursor = Cursor.new(:image => 'crosshair-3.png',
|
79
|
+
:keys => {MsLeft => [:click, false]},
|
80
|
+
:rand_color => true)
|
81
|
+
|
82
|
+
@window_info = TextBox.new(:size => 15)
|
83
|
+
@window_info.text("Press T to hide this text", :size => 24)
|
84
|
+
@window_info.watch(@systems[FpsSystem], :size => 20)
|
85
|
+
@window_info.watch(@systems[StalkerSystem], :color => 0xff33ccff)
|
86
|
+
@window_info.watch(@cursor, :color => @cursor.color)
|
87
|
+
@window_info.text("Click to start the simulation", :color => 0xffffff00)
|
88
|
+
@window_info.text("Little missiles will pursuit while the big one evades, right click to center big one on screen")
|
89
|
+
|
90
|
+
@missile_info = TextBox.new(:attach_to => @big_missile, :size => 14)
|
91
|
+
@missile_info.watch(@big_missile)
|
92
|
+
end
|
93
|
+
|
94
|
+
def setup_events
|
95
|
+
@cursor.on(:click) do |x,y|
|
96
|
+
@big_missile.pursuers = @little_missiles
|
97
|
+
@little_missiles.each do |lil_missile|
|
98
|
+
lil_missile.evader = @big_missile
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def teleport_big_missile_to_midscreen
|
104
|
+
@big_missile.pos.x = width/2
|
105
|
+
@big_missile.pos.y = height/2
|
106
|
+
end
|
107
|
+
|
108
|
+
def toggle_info
|
109
|
+
@missile_info.toggle!
|
110
|
+
@window_info.toggle!
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
# Create and start the application
|
116
|
+
EvadeMultiple.new.show
|
data/lib/lotu/actor.rb
CHANGED
@@ -27,12 +27,16 @@ module Lotu
|
|
27
27
|
@parent.manage_me(self)
|
28
28
|
set_image(opts[:image], opts) if opts[:image]
|
29
29
|
parse_options(opts)
|
30
|
+
@color = rand_color if opts[:rand_color]
|
30
31
|
@systems = {}
|
31
32
|
|
33
|
+
set_keys(opts[:keys]) unless opts[:keys].nil?
|
34
|
+
|
32
35
|
# Add extra functionality
|
33
36
|
self.extend Eventful
|
34
37
|
self.extend Collidable
|
35
38
|
use(AnimationSystem)
|
39
|
+
use(TransformationSystem)
|
36
40
|
end
|
37
41
|
|
38
42
|
# Easy access to delta-time
|
@@ -50,36 +54,60 @@ module Lotu
|
|
50
54
|
@factor_x = opts[:factor_x] || @factor_x
|
51
55
|
@factor_y = opts[:factor_y] || @factor_y
|
52
56
|
@color = opts[:color] || @color
|
57
|
+
if @color.kind_of?(Integer)
|
58
|
+
@color = Gosu::Color.new(opts[:color])
|
59
|
+
end
|
53
60
|
@mode = opts[:mode] || @mode
|
54
61
|
end
|
55
62
|
|
63
|
+
def rand_color
|
64
|
+
Gosu::Color.from_hsv(rand(360), 1, 1)
|
65
|
+
end
|
66
|
+
|
56
67
|
def set_image(image, opts={})
|
57
68
|
@image = @parent.image(image)
|
58
|
-
|
69
|
+
if @image.nil?
|
70
|
+
puts "Image \"#{image}\" not found".red
|
71
|
+
return
|
72
|
+
end
|
59
73
|
parse_options(opts)
|
60
|
-
|
61
|
-
@height = opts[:height] || @image.height
|
74
|
+
adjust_width_and_height(opts)
|
62
75
|
calc_zoom
|
63
76
|
end
|
64
77
|
|
65
78
|
def set_gosu_image(image, opts={})
|
66
79
|
@image = image
|
67
80
|
parse_options(opts)
|
68
|
-
|
69
|
-
@height = opts[:height] || @image.height
|
81
|
+
adjust_width_and_height(opts)
|
70
82
|
calc_zoom
|
71
83
|
end
|
72
84
|
|
73
85
|
def width=(width)
|
74
|
-
@width = width
|
86
|
+
@width = Float(width)
|
75
87
|
calc_zoom
|
76
88
|
end
|
77
89
|
|
78
90
|
def height=(height)
|
79
|
-
@height = height
|
91
|
+
@height = Float(height)
|
80
92
|
calc_zoom
|
81
93
|
end
|
82
94
|
|
95
|
+
def adjust_width_and_height(opts)
|
96
|
+
if(opts[:width] && opts[:height])
|
97
|
+
@width = Float(opts[:width])
|
98
|
+
@height = Float(opts[:height])
|
99
|
+
elsif(opts[:width])
|
100
|
+
@width = Float(opts[:width])
|
101
|
+
@height = @width * @image.height / @image.width
|
102
|
+
elsif(opts[:height])
|
103
|
+
@height = Float(opts[:height])
|
104
|
+
@width = @height * @image.width / @image.height
|
105
|
+
else
|
106
|
+
@width = Float(@image.width)
|
107
|
+
@height = Float(@image.height)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
83
111
|
def calc_zoom
|
84
112
|
@zoom_x = Float(@width)/@image.width
|
85
113
|
@zoom_y = Float(@height)/@image.height
|
@@ -97,8 +125,10 @@ module Lotu
|
|
97
125
|
end
|
98
126
|
|
99
127
|
def draw
|
100
|
-
|
101
|
-
|
128
|
+
unless @image.nil?
|
129
|
+
@image.draw_rot(@x, @y, @z, @angle, @center_x, @center_y, @factor_x*@zoom_x, @factor_y*@zoom_y, @color, @mode)
|
130
|
+
draw_debug if $lotu.debug?
|
131
|
+
end
|
102
132
|
end
|
103
133
|
|
104
134
|
def draw_debug
|
data/lib/lotu/cursor.rb
CHANGED
@@ -7,7 +7,7 @@ module Lotu
|
|
7
7
|
def initialize(opts={})
|
8
8
|
default_opts = {
|
9
9
|
:use_mouse => true,
|
10
|
-
:speed =>
|
10
|
+
:speed => 300,
|
11
11
|
:x => $lotu.width/2,
|
12
12
|
:y => $lotu.height/2
|
13
13
|
}
|
@@ -18,10 +18,10 @@ module Lotu
|
|
18
18
|
@clicked_x = @clicked_y = 0
|
19
19
|
@speed = opts[:speed]
|
20
20
|
@use_mouse = opts[:use_mouse]
|
21
|
-
set_keys(opts[:keys]) unless opts[:keys].nil?
|
22
21
|
end
|
23
22
|
|
24
23
|
def update
|
24
|
+
super
|
25
25
|
if @use_mouse
|
26
26
|
@x = $lotu.mouse_x
|
27
27
|
@y = $lotu.mouse_y
|
data/lib/lotu/game.rb
CHANGED
@@ -7,12 +7,18 @@ module Lotu
|
|
7
7
|
|
8
8
|
include SystemUser
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
|
10
|
+
def initialize(opts={})
|
11
|
+
default_opts = {
|
12
|
+
:width => 1024,
|
13
|
+
:height => 768,
|
14
|
+
:fullscreen => false
|
15
|
+
}
|
16
|
+
opts = default_opts.merge!(opts)
|
17
|
+
super(opts[:width], opts[:height], opts[:fullscreen])
|
12
18
|
|
13
19
|
# Handy global window variable
|
14
20
|
$lotu = self
|
15
|
-
@debug = false
|
21
|
+
@debug = opts[:debug] || false
|
16
22
|
setup_containers
|
17
23
|
|
18
24
|
# For timer initialization
|
@@ -27,6 +33,14 @@ module Lotu
|
|
27
33
|
setup_input
|
28
34
|
end
|
29
35
|
|
36
|
+
def pause!
|
37
|
+
@pause = !@pause
|
38
|
+
end
|
39
|
+
|
40
|
+
def paused?
|
41
|
+
@pause
|
42
|
+
end
|
43
|
+
|
30
44
|
def debug!
|
31
45
|
@debug = !@debug
|
32
46
|
end
|
@@ -75,7 +89,7 @@ module Lotu
|
|
75
89
|
# Update each actor
|
76
90
|
@update_queue.each do |actor|
|
77
91
|
actor.update
|
78
|
-
end
|
92
|
+
end unless paused?
|
79
93
|
end
|
80
94
|
|
81
95
|
# Main draw loop
|
@@ -140,24 +154,34 @@ module Lotu
|
|
140
154
|
end
|
141
155
|
|
142
156
|
def load_images(path)
|
157
|
+
count = 0
|
143
158
|
with_files(/\.png|\.jpg|\.bmp/, path) do |file_name, file_path|
|
159
|
+
count += 1
|
144
160
|
@images[file_name] = Gosu::Image.new($lotu, file_path)
|
145
161
|
end
|
162
|
+
puts "\n#{count} image(s) loaded."
|
146
163
|
end
|
147
164
|
|
148
165
|
def load_sounds(path)
|
166
|
+
count = 0
|
149
167
|
with_files(/\.ogg|\.mp3|\.wav/, path) do |file_name, file_path|
|
168
|
+
count += 1
|
150
169
|
@sounds[file_name] = Gosu::Sample.new($lotu, file_path)
|
151
170
|
end
|
171
|
+
puts "\n#{count} sounds(s) loaded."
|
152
172
|
end
|
153
173
|
|
154
174
|
def load_songs(path)
|
175
|
+
count = 0
|
155
176
|
with_files(/\.ogg|\.mp3|\.wav/, path) do |file_name, file_path|
|
177
|
+
count += 1
|
156
178
|
@songs[file_name] = Gosu::Song.new($lotu, file_path)
|
157
179
|
end
|
180
|
+
puts "\n#{count} song(s) loaded."
|
158
181
|
end
|
159
182
|
|
160
183
|
def load_animations(path)
|
184
|
+
count = 0
|
161
185
|
coords = Hash.new{|h,k| h[k] = []}
|
162
186
|
|
163
187
|
with_files(/\.txt/, path) do |file_name, file_path|
|
@@ -167,14 +191,17 @@ module Lotu
|
|
167
191
|
coords[name] << line.scan(/\d+/).map!(&:to_i)
|
168
192
|
end
|
169
193
|
end
|
194
|
+
false
|
170
195
|
end
|
171
196
|
|
172
197
|
with_files(/\.png|\.jpg|\.bmp/, path) do |file_name, file_path|
|
173
198
|
name, extension = file_name.split('.')
|
199
|
+
count += 1 if coords[name]
|
174
200
|
coords[name].each do |index, x, y, width, height|
|
175
201
|
@animations[file_name] << Gosu::Image.new($lotu, file_path, true, x, y, width, height)
|
176
202
|
end
|
177
203
|
end
|
204
|
+
puts "\n#{count} animation(s) loaded."
|
178
205
|
end
|
179
206
|
|
180
207
|
def with_path_from_file(path, &blk)
|
@@ -184,20 +211,17 @@ module Lotu
|
|
184
211
|
|
185
212
|
def with_files(regexp, path)
|
186
213
|
path = File.expand_path(File.join(@path, path))
|
187
|
-
puts "\nLoading from: #{path}"
|
214
|
+
puts "\nLoading from: #{path}".blue if @debug
|
188
215
|
|
189
|
-
count = 0
|
190
216
|
Dir.entries(path).grep(regexp).each do |entry|
|
191
217
|
begin
|
192
|
-
yield(entry, File.join(path, entry))
|
193
|
-
|
194
|
-
print '.'.green
|
218
|
+
report = yield(entry, File.join(path, entry))
|
219
|
+
print '.'.green if report
|
195
220
|
rescue Exception => e
|
196
221
|
print '.'.red
|
197
222
|
puts e, File.join(path, entry) if @debug
|
198
223
|
end
|
199
224
|
end
|
200
|
-
puts "\n#{count} file(s) loaded."
|
201
225
|
end
|
202
226
|
|
203
227
|
end
|
@@ -135,6 +135,23 @@ module Lotu
|
|
135
135
|
return flee
|
136
136
|
end
|
137
137
|
|
138
|
+
def evade_multiple
|
139
|
+
return @zero if @user.pursuers.empty?
|
140
|
+
combined_velocities = Vector2d.new
|
141
|
+
combined_positions = Vector2d.new
|
142
|
+
@user.pursuers.each do |p|
|
143
|
+
combined_velocities += p.vel
|
144
|
+
combined_positions += p.pos
|
145
|
+
end
|
146
|
+
combined_velocities /= @user.pursuers.length
|
147
|
+
combined_positions /= @user.pursuers.length
|
148
|
+
to_pursuers = combined_positions - @user.pos
|
149
|
+
look_ahead_time = to_pursuers.length / (@user.max_speed + combined_velocities.length)
|
150
|
+
predicted_position = combined_positions + combined_velocities * look_ahead_time
|
151
|
+
@user.target = combined_positions
|
152
|
+
return flee
|
153
|
+
end
|
154
|
+
|
138
155
|
# TODO: Fix wander
|
139
156
|
def wander
|
140
157
|
wander_jitter = 10
|
@@ -166,9 +183,11 @@ module Lotu
|
|
166
183
|
attr_accessor :mass, :pos, :heading, :vel, :accel,
|
167
184
|
:max_speed, :max_turn_rate, :max_force,
|
168
185
|
:wander_radius, :wander_distance, :wander_target,
|
169
|
-
:target, :evader, :pursuer
|
186
|
+
:target, :evader, :pursuer, :pursuers
|
170
187
|
end
|
171
188
|
|
189
|
+
# TODO: move these inside the SteeringSystem?
|
190
|
+
# and just delegate with accessors?
|
172
191
|
# Some defaults
|
173
192
|
@pos = Vector2d.new(@x, @y)
|
174
193
|
offset_x = Gosu.offset_x(@angle, 1)
|
@@ -177,6 +196,13 @@ module Lotu
|
|
177
196
|
@vel = Vector2d.new
|
178
197
|
@accel = Vector2d.new
|
179
198
|
@wander_target = Vector2d.new
|
199
|
+
@pursuers = []
|
200
|
+
|
201
|
+
@colors = {
|
202
|
+
:position => 0xff666666,
|
203
|
+
:heading => 0xffff0000,
|
204
|
+
:target => rand_color
|
205
|
+
}
|
180
206
|
end
|
181
207
|
|
182
208
|
def activate(behavior)
|
@@ -191,15 +217,11 @@ module Lotu
|
|
191
217
|
@heading.facing_to?(@target - @pos)
|
192
218
|
end
|
193
219
|
|
194
|
-
def draw
|
195
|
-
super
|
196
|
-
draw_debug if $lotu.debug?
|
197
|
-
end
|
198
|
-
|
199
220
|
def draw_debug
|
200
|
-
|
201
|
-
$lotu.draw_line(
|
202
|
-
$lotu.draw_line(@pos.x, @pos.y,
|
221
|
+
super
|
222
|
+
$lotu.draw_line(0, 0, @colors[:position], @pos.x, @pos.y, @colors[:position])
|
223
|
+
$lotu.draw_line(@pos.x, @pos.y, @colors[:heading], (@pos + @heading*50).x, (@pos+@heading*50).y, @colors[:heading])
|
224
|
+
$lotu.draw_line(@pos.x, @pos.y, @colors[:target], @target.x, @target.y, @colors[:target]) if @target
|
203
225
|
end
|
204
226
|
|
205
227
|
# to_s utility methods
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Lotu
|
2
|
+
class TransformationSystem < System
|
3
|
+
|
4
|
+
def initialize(user, opts={})
|
5
|
+
super
|
6
|
+
user.extend(UserMethods)
|
7
|
+
@transformations = []
|
8
|
+
@tagged_for_deletion = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def transform(object, property, opts)
|
12
|
+
transformation = {
|
13
|
+
:object => object,
|
14
|
+
:property_getter => property,
|
15
|
+
:property_setter => "#{property}=",
|
16
|
+
:accum_time => 0,
|
17
|
+
:calc => 0,
|
18
|
+
:init => opts[:init],
|
19
|
+
:end => opts[:end],
|
20
|
+
:duration => opts[:duration] || 1,
|
21
|
+
:start_in => opts[:start_in] || 0,
|
22
|
+
:on_result => opts[:on_result],
|
23
|
+
:loop => opts[:loop]
|
24
|
+
}
|
25
|
+
@transformations << transformation
|
26
|
+
end
|
27
|
+
|
28
|
+
def update
|
29
|
+
@transformations.each do |t|
|
30
|
+
t[:accum_time] += dt
|
31
|
+
if t[:accum_time] > t[:start_in]
|
32
|
+
step = (t[:end] - t[:init])/t[:duration] * dt
|
33
|
+
t[:calc] += step
|
34
|
+
if step > 0
|
35
|
+
if t[:init] + t[:calc] > t[:end]
|
36
|
+
if t[:loop]
|
37
|
+
t[:calc] = 0
|
38
|
+
else
|
39
|
+
t[:calc] = t[:end] - t[:init]
|
40
|
+
tag_for_deletion(t)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
if t[:init] + t[:calc] < t[:end]
|
45
|
+
if t[:loop]
|
46
|
+
t[:calc] = 0
|
47
|
+
else
|
48
|
+
t[:calc] = t[:end] - t[:init]
|
49
|
+
tag_for_deletion(t)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
value = t[:init] + t[:calc]
|
54
|
+
value = value.send(t[:on_result]) if t[:on_result]
|
55
|
+
t[:object].send(t[:property_setter], value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
@tagged_for_deletion.each do |to_delete|
|
60
|
+
@transformations.delete(to_delete)
|
61
|
+
end.clear
|
62
|
+
end
|
63
|
+
|
64
|
+
def tag_for_deletion(transform)
|
65
|
+
@tagged_for_deletion << transform
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
["@transformations.length #{@transformations.length}",
|
70
|
+
"@tagged_for_deletion.length #{@tagged_for_deletion.length}"]
|
71
|
+
end
|
72
|
+
|
73
|
+
module UserMethods
|
74
|
+
def transform(object, property, opts)
|
75
|
+
@systems[TransformationSystem].transform(object, property, opts)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Image helpers
|
79
|
+
def transform_angle(opts)
|
80
|
+
transform(self, :angle, opts)
|
81
|
+
end
|
82
|
+
|
83
|
+
def transform_width(opts)
|
84
|
+
transform(self, :width, opts)
|
85
|
+
end
|
86
|
+
|
87
|
+
def transform_height(opts)
|
88
|
+
transform(self, :height, opts)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Color helpers
|
92
|
+
def transform_alpha(opts)
|
93
|
+
transform(@color, :alpha, opts.merge!(:on_result => :to_i))
|
94
|
+
end
|
95
|
+
|
96
|
+
def transform_red(opts)
|
97
|
+
transform(@color, :red, opts.merge!(:on_result => :to_i))
|
98
|
+
end
|
99
|
+
|
100
|
+
def transform_green(opts)
|
101
|
+
transform(@color, :green, opts.merge!(:on_result => :to_i))
|
102
|
+
end
|
103
|
+
|
104
|
+
def transform_blue(opts)
|
105
|
+
transform(@color, :blue, opts.merge!(:on_result => :to_i))
|
106
|
+
end
|
107
|
+
|
108
|
+
def transform_hue(opts)
|
109
|
+
transform(@color, :hue, opts)
|
110
|
+
end
|
111
|
+
|
112
|
+
def transform_saturation(opts)
|
113
|
+
transform(@color, :saturation, opts)
|
114
|
+
end
|
115
|
+
|
116
|
+
def transform_value(opts)
|
117
|
+
transform(@color, :value, opts)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
data/lib/lotu/text_box.rb
CHANGED
@@ -13,21 +13,32 @@ module Lotu
|
|
13
13
|
@watch_list = []
|
14
14
|
@size = opts[:size]
|
15
15
|
@attached_to = opts[:attach_to]
|
16
|
+
@hiding = false
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
-
|
19
|
+
def hide!
|
20
|
+
@hiding = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def show!
|
24
|
+
@hiding = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def toggle!
|
28
|
+
@hiding = !@hiding
|
20
29
|
end
|
21
30
|
|
22
31
|
def watch(subject, opts={})
|
23
32
|
@watch_list << [subject, opts]
|
24
33
|
end
|
34
|
+
alias :text :watch
|
25
35
|
|
26
36
|
def attach_to(actor)
|
27
37
|
@attached_to = actor
|
28
38
|
end
|
29
39
|
|
30
40
|
def update
|
41
|
+
return if @hiding
|
31
42
|
unless @attached_to.nil?
|
32
43
|
@x = @attached_to.x + @attached_to.image.width / 2
|
33
44
|
@y = @attached_to.y - @attached_to.image.height / 2
|
@@ -35,6 +46,7 @@ module Lotu
|
|
35
46
|
end
|
36
47
|
|
37
48
|
def draw
|
49
|
+
return if @hiding
|
38
50
|
pos_y = 0
|
39
51
|
@watch_list.each do |watched, opts|
|
40
52
|
my_size = opts[:size] || @size
|
data/lib/lotu.rb
CHANGED
@@ -5,4 +5,4 @@ require 'gosu'
|
|
5
5
|
%w{vector2d string}.each{|file| require "misc/#{file}"}
|
6
6
|
%w{system_user collidable controllable eventful}.each{|file| require "behaviors/#{file}"}
|
7
7
|
%w{game system actor cursor text_box}.each{|file| require file}
|
8
|
-
%w{animation_system input_system stalker_system fps_system collision_system steering_system}.each{|file| require "systems/#{file}"}
|
8
|
+
%w{transformation_system animation_system input_system stalker_system fps_system collision_system steering_system}.each{|file| require "systems/#{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.
|
8
|
+
s.version = "0.1.12"
|
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-
|
12
|
+
s.date = %q{2010-03-28}
|
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 = [
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"README.rdoc",
|
25
25
|
"Rakefile",
|
26
26
|
"VERSION",
|
27
|
-
"examples/hello_world/
|
27
|
+
"examples/hello_world/moving_portraits.rb",
|
28
28
|
"examples/media/animations/missile.png",
|
29
29
|
"examples/media/animations/missile.txt",
|
30
30
|
"examples/media/images/cohete-big.png",
|
@@ -36,8 +36,9 @@ Gem::Specification.new do |s|
|
|
36
36
|
"examples/media/images/lobo_tuerto.png",
|
37
37
|
"examples/media/images/missile-med.png",
|
38
38
|
"examples/media/images/silo.png",
|
39
|
-
"examples/
|
40
|
-
"examples/steering_behaviors/
|
39
|
+
"examples/screen_cursor/mouse_and_keyboard_cursors.rb",
|
40
|
+
"examples/steering_behaviors/pursuit_and_evade.rb",
|
41
|
+
"examples/steering_behaviors/pursuit_and_evade_multiple.rb",
|
41
42
|
"lib/lotu.rb",
|
42
43
|
"lib/lotu/actor.rb",
|
43
44
|
"lib/lotu/behaviors/collidable.rb",
|
@@ -55,6 +56,7 @@ Gem::Specification.new do |s|
|
|
55
56
|
"lib/lotu/systems/input_system.rb",
|
56
57
|
"lib/lotu/systems/stalker_system.rb",
|
57
58
|
"lib/lotu/systems/steering_system.rb",
|
59
|
+
"lib/lotu/systems/transformation_system.rb",
|
58
60
|
"lib/lotu/text_box.rb",
|
59
61
|
"lotu.gemspec",
|
60
62
|
"test/actor_test.rb"
|
@@ -66,9 +68,10 @@ Gem::Specification.new do |s|
|
|
66
68
|
s.summary = %q{A simple, agile Ruby game development framework.}
|
67
69
|
s.test_files = [
|
68
70
|
"test/actor_test.rb",
|
69
|
-
"examples/steering_behaviors/
|
70
|
-
"examples/
|
71
|
-
"examples/
|
71
|
+
"examples/steering_behaviors/pursuit_and_evade.rb",
|
72
|
+
"examples/steering_behaviors/pursuit_and_evade_multiple.rb",
|
73
|
+
"examples/hello_world/moving_portraits.rb",
|
74
|
+
"examples/screen_cursor/mouse_and_keyboard_cursors.rb"
|
72
75
|
]
|
73
76
|
|
74
77
|
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
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 12
|
9
|
+
version: 0.1.12
|
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
|
+
date: 2010-03-28 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -48,7 +48,7 @@ files:
|
|
48
48
|
- README.rdoc
|
49
49
|
- Rakefile
|
50
50
|
- VERSION
|
51
|
-
- examples/hello_world/
|
51
|
+
- examples/hello_world/moving_portraits.rb
|
52
52
|
- examples/media/animations/missile.png
|
53
53
|
- examples/media/animations/missile.txt
|
54
54
|
- examples/media/images/cohete-big.png
|
@@ -60,8 +60,9 @@ files:
|
|
60
60
|
- examples/media/images/lobo_tuerto.png
|
61
61
|
- examples/media/images/missile-med.png
|
62
62
|
- examples/media/images/silo.png
|
63
|
-
- examples/
|
64
|
-
- examples/steering_behaviors/
|
63
|
+
- examples/screen_cursor/mouse_and_keyboard_cursors.rb
|
64
|
+
- examples/steering_behaviors/pursuit_and_evade.rb
|
65
|
+
- examples/steering_behaviors/pursuit_and_evade_multiple.rb
|
65
66
|
- lib/lotu.rb
|
66
67
|
- lib/lotu/actor.rb
|
67
68
|
- lib/lotu/behaviors/collidable.rb
|
@@ -79,6 +80,7 @@ files:
|
|
79
80
|
- lib/lotu/systems/input_system.rb
|
80
81
|
- lib/lotu/systems/stalker_system.rb
|
81
82
|
- lib/lotu/systems/steering_system.rb
|
83
|
+
- lib/lotu/systems/transformation_system.rb
|
82
84
|
- lib/lotu/text_box.rb
|
83
85
|
- lotu.gemspec
|
84
86
|
- test/actor_test.rb
|
@@ -115,6 +117,7 @@ specification_version: 3
|
|
115
117
|
summary: A simple, agile Ruby game development framework.
|
116
118
|
test_files:
|
117
119
|
- test/actor_test.rb
|
118
|
-
- examples/steering_behaviors/
|
119
|
-
- examples/
|
120
|
-
- examples/
|
120
|
+
- examples/steering_behaviors/pursuit_and_evade.rb
|
121
|
+
- examples/steering_behaviors/pursuit_and_evade_multiple.rb
|
122
|
+
- examples/hello_world/moving_portraits.rb
|
123
|
+
- examples/screen_cursor/mouse_and_keyboard_cursors.rb
|
@@ -1,77 +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
|
-
|
5
|
-
include Gosu::Button
|
6
|
-
include Lotu
|
7
|
-
|
8
|
-
class MovingRuby < Actor
|
9
|
-
|
10
|
-
def initialize(opts={})
|
11
|
-
super
|
12
|
-
# Use the image which filename is CptnRuby Gem.png
|
13
|
-
set_image 'lobo_tuerto.png', :factor_x => 0.5, :factor_y => 0.5
|
14
|
-
end
|
15
|
-
|
16
|
-
# Let's define some basic movement methods
|
17
|
-
def move_right
|
18
|
-
@x += 1
|
19
|
-
end
|
20
|
-
|
21
|
-
def move_left
|
22
|
-
@x -= 1
|
23
|
-
end
|
24
|
-
|
25
|
-
def move_up
|
26
|
-
@y -= 1
|
27
|
-
end
|
28
|
-
|
29
|
-
def move_down
|
30
|
-
@y += 1
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
class Example < Game
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
# This will call the hooks:
|
39
|
-
# load_resources, setup_systems and setup_actors
|
40
|
-
# declared in the parent class
|
41
|
-
super
|
42
|
-
# When the Escape key is pressed, call the close method on class Example
|
43
|
-
set_keys(KbEscape => :close,
|
44
|
-
KbD => [:debug!, false])
|
45
|
-
end
|
46
|
-
|
47
|
-
def load_resources
|
48
|
-
# From this file,
|
49
|
-
with_path_from_file(__FILE__) do
|
50
|
-
# go back one dir and search inside media/
|
51
|
-
load_images '../media/images'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def setup_actors
|
56
|
-
# Create a ruby in the middle of the screen
|
57
|
-
@ruby = MovingRuby.new(:x => width/2, :y => height/2)
|
58
|
-
# Map keys to some methods
|
59
|
-
@ruby.set_keys(KbRight => :move_right,
|
60
|
-
KbLeft => :move_left,
|
61
|
-
KbUp => :move_up,
|
62
|
-
KbDown => :move_down)
|
63
|
-
@ruby2 = MovingRuby.new(:x => width/2, :y => height/2)
|
64
|
-
# Map keys to some methods
|
65
|
-
@ruby2.set_keys(KbRight => :move_left,
|
66
|
-
KbLeft => :move_right,
|
67
|
-
KbUp => :move_up,
|
68
|
-
KbDown => :move_down)
|
69
|
-
# Create a TextBox so we can display a message on screen
|
70
|
-
@info = TextBox.new
|
71
|
-
@info.text("Hello world!")
|
72
|
-
@info.text("Move around with arrow keys", :size => 16, :color => 0xff33ccff)
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
Example.new.show
|
@@ -1,92 +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
|
-
|
5
|
-
include Gosu::Button
|
6
|
-
include Lotu
|
7
|
-
|
8
|
-
class WarpingRuby < Actor
|
9
|
-
def initialize(opts={})
|
10
|
-
super
|
11
|
-
set_image 'lobo_tuerto.png', :factor_x => 0.3, :factor_y => 0.3
|
12
|
-
end
|
13
|
-
|
14
|
-
def warp(x, y)
|
15
|
-
@x, @y = x, y
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class Example < Game
|
20
|
-
def initialize
|
21
|
-
# This will call the hooks:
|
22
|
-
# load_resources, setup_systems and setup_actors
|
23
|
-
# declared in the parent class
|
24
|
-
super
|
25
|
-
# Custom setup methods for this class
|
26
|
-
setup_events
|
27
|
-
end
|
28
|
-
|
29
|
-
def load_resources
|
30
|
-
with_path_from_file(__FILE__) do
|
31
|
-
load_images '../media/images'
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def setup_systems
|
36
|
-
# It's important to call super here to setup the InputSystem
|
37
|
-
super
|
38
|
-
use(FpsSystem)
|
39
|
-
use(StalkerSystem, :stalk => [Actor, Cursor, TextBox, WarpingRuby, Object])
|
40
|
-
end
|
41
|
-
|
42
|
-
def setup_input
|
43
|
-
set_keys(KbEscape => :close,
|
44
|
-
KbD => [:debug!, false])
|
45
|
-
end
|
46
|
-
|
47
|
-
def setup_events
|
48
|
-
@cursor1.on(:click) do |x,y|
|
49
|
-
@ruby.warp(x,y)
|
50
|
-
end
|
51
|
-
@cursor2.on(:click) do |x,y|
|
52
|
-
@ruby.warp(x,y)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def setup_actors
|
57
|
-
@ruby = WarpingRuby.new(:x => width/2, :y => height/2)
|
58
|
-
@cursor1 = Cursor.new(:image => 'crosshair-1.png',
|
59
|
-
:keys => {MsLeft => [:click, false]},
|
60
|
-
:color => 0xff0099ff,
|
61
|
-
:width => 100,
|
62
|
-
:height => 100)
|
63
|
-
@cursor2 = Cursor.new(:image => 'crosshair-2.png',
|
64
|
-
:use_mouse => false,
|
65
|
-
:keys => {
|
66
|
-
KbSpace => [:click, false],
|
67
|
-
KbUp => :up,
|
68
|
-
KbDown => :down,
|
69
|
-
KbLeft => :left,
|
70
|
-
KbRight => :right},
|
71
|
-
:color => 0xff99ff00,
|
72
|
-
:factor_x => 0.5,
|
73
|
-
:factor_y => 0.5)
|
74
|
-
@cursor2.x = width*3/4
|
75
|
-
@cursor2.y = height/2
|
76
|
-
|
77
|
-
# Create a TextBox with default option :size => 15
|
78
|
-
@info = TextBox.new(:size => 15)
|
79
|
-
@info.watch(@systems[FpsSystem])
|
80
|
-
@info.watch(@systems[StalkerSystem], :color => 0xff3ffccf)
|
81
|
-
# We can change the size for a specific line of text
|
82
|
-
@info.watch("@cursor1 data:", :size => 20)
|
83
|
-
# Color too
|
84
|
-
@info.watch(@cursor1, :color => 0xff0099ff)
|
85
|
-
@info.watch("@cursor2 data:", :size => 20)
|
86
|
-
@info.watch(@cursor2, :color => 0xff99ff00)
|
87
|
-
@info.text("Move @cursor1 with mouse and @cursor2 with arrow keys (click with space!)")
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
Example.new.show
|
@@ -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
|
-
|
5
|
-
include Gosu::Button
|
6
|
-
include Lotu
|
7
|
-
|
8
|
-
class SteeringRuby < Actor
|
9
|
-
def initialize(opts={})
|
10
|
-
super
|
11
|
-
use(SteeringSystem, opts)
|
12
|
-
end
|
13
|
-
|
14
|
-
def warp(x, y)
|
15
|
-
@pos.x, @pos.y = x, y
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class Example < Game
|
20
|
-
def initialize
|
21
|
-
# This will call the hooks:
|
22
|
-
# load_resources, setup_systems and setup_actors
|
23
|
-
# declared in the parent class
|
24
|
-
super
|
25
|
-
# Custom setup methods for this class
|
26
|
-
setup_events
|
27
|
-
end
|
28
|
-
|
29
|
-
def load_resources
|
30
|
-
with_path_from_file(__FILE__) do
|
31
|
-
load_images '../media/images'
|
32
|
-
load_animations '../media/animations'
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def setup_input
|
37
|
-
set_keys(KbEscape => :close,
|
38
|
-
MsRight => :reset_ruby,
|
39
|
-
KbD => [:debug!, false])
|
40
|
-
end
|
41
|
-
|
42
|
-
def setup_systems
|
43
|
-
# It's important to call super here to setup the InputSystem
|
44
|
-
super
|
45
|
-
use(FpsSystem)
|
46
|
-
use(StalkerSystem, :stalk => [Actor, Vector2d, Object])
|
47
|
-
end
|
48
|
-
|
49
|
-
def setup_actors
|
50
|
-
@ruby = SteeringRuby.new(:mass => 0.3, :max_speed => 100, :max_turn_rate => 140)
|
51
|
-
@ruby.warp(width/2, height/2)
|
52
|
-
@ruby.activate(:evade)
|
53
|
-
@ruby.play_animation('missile.png')
|
54
|
-
|
55
|
-
@ruby2 = SteeringRuby.new
|
56
|
-
@ruby2.activate(:pursuit)
|
57
|
-
@ruby2.play_animation('missile.png', :factor_x => 0.5, :factor_y => 0.5, :fps => 60)
|
58
|
-
|
59
|
-
@cursor = Cursor.new(:image => 'crosshair-1.png',
|
60
|
-
:keys => {MsLeft => [:click, false]})
|
61
|
-
|
62
|
-
@window_info = TextBox.new(:size => 15)
|
63
|
-
@window_info.watch(@systems[FpsSystem])
|
64
|
-
@window_info.watch(@systems[StalkerSystem])
|
65
|
-
@window_info.watch(@cursor, :color => 0xffff0000)
|
66
|
-
@window_info.text("Click to start the simulation")
|
67
|
-
@window_info.text("One will pursuit while the other evades, right click to center evader on screen")
|
68
|
-
|
69
|
-
@ruby_info = TextBox.new(:attach_to => @ruby, :size => 14)
|
70
|
-
@ruby_info.watch(@ruby)
|
71
|
-
end
|
72
|
-
|
73
|
-
def setup_events
|
74
|
-
@cursor.on(:click) do |x,y|
|
75
|
-
@ruby.pursuer = @ruby2
|
76
|
-
@ruby2.evader = @ruby
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def reset_ruby
|
81
|
-
@ruby.pos.x = width/2
|
82
|
-
@ruby.pos.y = height/2
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
Example.new.show
|