zyps 0.3.1 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/zyps +22 -346
- data/bin/zyps_demo +116 -188
- data/doc/classes/AccelerateAction.html +182 -0
- data/doc/classes/{Vector.src/M000006.html → AccelerateAction.src/M000009.html} +5 -5
- data/doc/classes/AccelerateAction.src/M000010.html +18 -0
- data/doc/classes/Action.html +118 -0
- data/doc/classes/AgeCondition.html +181 -0
- data/doc/classes/AgeCondition.src/M000039.html +18 -0
- data/doc/classes/AgeCondition.src/M000040.html +18 -0
- data/doc/classes/ApproachAction.html +189 -0
- data/doc/classes/ApproachAction.src/M000048.html +19 -0
- data/doc/classes/ApproachAction.src/M000049.html +38 -0
- data/doc/classes/Behavior.html +23 -26
- data/doc/classes/Behavior.src/{M000003.html → M000001.html} +1 -1
- data/doc/classes/Behavior.src/{M000004.html → M000002.html} +2 -2
- data/doc/classes/BlendAction.html +181 -0
- data/doc/classes/BlendAction.src/M000043.html +18 -0
- data/doc/classes/BlendAction.src/M000044.html +18 -0
- data/doc/classes/Clock.html +10 -10
- data/doc/classes/Clock.src/{M000026.html → M000041.html} +0 -0
- data/doc/classes/Clock.src/{M000027.html → M000042.html} +0 -0
- data/doc/classes/CollisionCondition.html +148 -0
- data/doc/classes/CollisionCondition.src/M000053.html +18 -0
- data/doc/classes/Color.html +36 -36
- data/doc/classes/Color.src/{M000015.html → M000022.html} +0 -0
- data/doc/classes/Color.src/{M000016.html → M000023.html} +0 -0
- data/doc/classes/Color.src/{M000017.html → M000024.html} +0 -0
- data/doc/classes/Color.src/{M000018.html → M000025.html} +0 -0
- data/doc/classes/Color.src/{M000019.html → M000026.html} +0 -0
- data/doc/classes/Color.src/{M000020.html → M000027.html} +3 -3
- data/doc/classes/Condition.html +118 -0
- data/doc/classes/Creature.html +28 -13
- data/doc/classes/Creature.src/{M000005.html → M000011.html} +4 -4
- data/doc/classes/{Responsive.src/M000030.html → Creature.src/M000012.html} +2 -2
- data/doc/classes/DestroyAction.html +181 -0
- data/doc/classes/DestroyAction.src/M000030.html +18 -0
- data/doc/classes/DestroyAction.src/M000031.html +18 -0
- data/doc/classes/EatAction.html +149 -0
- data/doc/classes/EatAction.src/M000045.html +21 -0
- data/doc/classes/Enclosure.html +206 -0
- data/doc/classes/Enclosure.src/M000005.html +18 -0
- data/doc/classes/Enclosure.src/M000006.html +31 -0
- data/doc/classes/Environment.html +11 -11
- data/doc/classes/Environment.src/{M000028.html → M000046.html} +1 -1
- data/doc/classes/Environment.src/{M000029.html → M000047.html} +0 -0
- data/doc/classes/EnvironmentalFactor.html +2 -51
- data/doc/classes/{Responsive.html → FaceAction.html} +21 -16
- data/doc/classes/FaceAction.src/M000052.html +18 -0
- data/doc/classes/FleeAction.html +189 -0
- data/doc/classes/FleeAction.src/M000054.html +19 -0
- data/doc/classes/FleeAction.src/M000055.html +38 -0
- data/doc/classes/GameObject.html +47 -21
- data/doc/classes/GameObject.src/{M000022.html → M000032.html} +3 -4
- data/doc/classes/GameObject.src/M000033.html +16 -0
- data/doc/classes/GameObject.src/{M000023.html → M000034.html} +1 -1
- data/doc/classes/GameObject.src/{M000024.html → M000035.html} +1 -1
- data/doc/classes/GameObject.src/{M000025.html → M000036.html} +1 -1
- data/doc/classes/Location.html +5 -5
- data/doc/classes/Location.src/{M000014.html → M000021.html} +1 -1
- data/doc/classes/ProximityCondition.html +182 -0
- data/doc/classes/ProximityCondition.src/M000037.html +18 -0
- data/doc/classes/ProximityCondition.src/M000038.html +18 -0
- data/doc/classes/TagAction.html +181 -0
- data/doc/classes/{EnvironmentalFactor.src/M000021.html → TagAction.src/M000028.html} +4 -4
- data/doc/classes/TagAction.src/M000029.html +18 -0
- data/doc/classes/TagCondition.html +181 -0
- data/doc/classes/TagCondition.src/M000007.html +18 -0
- data/doc/classes/TagCondition.src/M000008.html +18 -0
- data/doc/classes/TrailsView.html +13 -21
- data/doc/classes/TrailsView.src/{M000001.html → M000003.html} +3 -3
- data/doc/classes/TrailsView.src/{M000002.html → M000004.html} +4 -2
- data/doc/classes/TurnAction.html +182 -0
- data/doc/classes/TurnAction.src/M000050.html +19 -0
- data/doc/classes/TurnAction.src/M000051.html +18 -0
- data/doc/classes/Utility.html +48 -48
- data/doc/classes/Utility.src/{M000031.html → M000056.html} +0 -0
- data/doc/classes/Utility.src/{M000032.html → M000057.html} +0 -0
- data/doc/classes/Utility.src/{M000033.html → M000058.html} +0 -0
- data/doc/classes/Utility.src/{M000034.html → M000059.html} +0 -0
- data/doc/classes/Utility.src/{M000035.html → M000060.html} +0 -0
- data/doc/classes/Utility.src/{M000036.html → M000061.html} +0 -0
- data/doc/classes/Utility.src/M000062.html +21 -0
- data/doc/classes/Vector.html +41 -41
- data/doc/classes/Vector.src/M000013.html +5 -11
- data/doc/classes/Vector.src/{M000007.html → M000014.html} +0 -0
- data/doc/classes/Vector.src/{M000008.html → M000015.html} +0 -0
- data/doc/classes/Vector.src/{M000009.html → M000016.html} +0 -0
- data/doc/classes/Vector.src/{M000010.html → M000017.html} +0 -0
- data/doc/classes/Vector.src/{M000011.html → M000018.html} +0 -0
- data/doc/classes/Vector.src/{M000012.html → M000019.html} +0 -0
- data/doc/classes/Vector.src/M000020.html +25 -0
- data/doc/created.rid +1 -1
- data/doc/files/COPYING_LESSER_txt.html +1 -1
- data/doc/files/COPYING_txt.html +1 -1
- data/doc/files/README_txt.html +1 -1
- data/doc/files/lib/zyps/actions_rb.html +134 -0
- data/doc/files/lib/zyps/conditions_rb.html +134 -0
- data/doc/files/lib/zyps/environmental_factors_rb.html +134 -0
- data/doc/files/lib/zyps/views/trails_rb.html +1 -1
- data/doc/files/lib/zyps_rb.html +1 -1
- data/doc/fr_class_index.html +16 -1
- data/doc/fr_file_index.html +3 -0
- data/doc/fr_method_index.html +62 -37
- data/doc/index.html +2 -2
- data/lib/zyps.rb +46 -47
- data/lib/zyps/actions.rb +186 -0
- data/lib/zyps/conditions.rb +69 -0
- data/lib/zyps/environmental_factors.rb +55 -0
- data/lib/zyps/views/trails.rb +6 -6
- data/test/test_zyps.rb +159 -69
- data/test/zyps/test_actions.rb +183 -0
- data/test/zyps/test_conditions.rb +83 -0
- data/test/zyps/test_environmental_factors.rb +88 -0
- metadata +137 -75
- data/doc/classes/Utility.src/M000037.html +0 -22
data/bin/zyps
CHANGED
@@ -20,279 +20,20 @@
|
|
20
20
|
|
21
21
|
begin
|
22
22
|
require 'zyps'
|
23
|
+
require 'zyps/actions'
|
24
|
+
require 'zyps/conditions'
|
25
|
+
require 'zyps/environmental_factors'
|
23
26
|
require 'zyps/views/trails'
|
24
27
|
rescue LoadError
|
25
28
|
require 'rubygems'
|
26
29
|
require 'zyps'
|
30
|
+
require 'zyps/actions'
|
31
|
+
require 'zyps/conditions'
|
32
|
+
require 'zyps/environmental_factors'
|
27
33
|
require 'zyps/views/trails'
|
28
34
|
end
|
29
35
|
|
30
36
|
|
31
|
-
#Generates new creatures and places them in an environment.
|
32
|
-
class Generator
|
33
|
-
|
34
|
-
#Environment creatures will be spawned into.
|
35
|
-
attr_accessor :environment
|
36
|
-
#Boundary that all new objects must be inside.
|
37
|
-
attr_accessor :min_x, :min_y, :max_x, :max_y
|
38
|
-
#Array of tags to choose from when generating new one.
|
39
|
-
attr_accessor :tag_pool
|
40
|
-
#Array of colors to choose from when generating new one.
|
41
|
-
attr_accessor :color_pool
|
42
|
-
#The maximum speed a new creature should be going.
|
43
|
-
attr_accessor :max_speed
|
44
|
-
#The maximum number of behaviors a creature can have.
|
45
|
-
attr_accessor :max_behaviors
|
46
|
-
#The maximum number of conditions a Behavior can have.
|
47
|
-
attr_accessor :max_conditions
|
48
|
-
#The maximum number of actions a Behavior can have.
|
49
|
-
attr_accessor :max_actions
|
50
|
-
|
51
|
-
def initialize(environment, min_x, min_y, max_x, max_y)
|
52
|
-
@environment, @min_x, @min_y, @max_x, @max_y = environment, min_x, min_y, max_x, max_y
|
53
|
-
@tag_pool = %q{foo bar baz}
|
54
|
-
@color_pool = []
|
55
|
-
@max_behaviors = 2
|
56
|
-
@max_conditions = 2
|
57
|
-
@max_actions = 2
|
58
|
-
@max_speed = 100
|
59
|
-
end
|
60
|
-
|
61
|
-
#Create a creature.
|
62
|
-
def create_creature()
|
63
|
-
|
64
|
-
creature = Creature.new()
|
65
|
-
#Create a Color.
|
66
|
-
creature.color = create_color
|
67
|
-
#Create a Location.
|
68
|
-
creature.location = create_location
|
69
|
-
#Create a Vector.
|
70
|
-
creature.vector = create_vector()
|
71
|
-
#Create a random tag.
|
72
|
-
creature.tags << create_tag()
|
73
|
-
#Create a random number of behaviors.
|
74
|
-
generate_number(0, @max_behaviors).to_i.times {creature.behaviors << create_behavior()}
|
75
|
-
|
76
|
-
creature
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
#Create a random tag.
|
81
|
-
#Chooses from tag_pool.
|
82
|
-
def create_tag()
|
83
|
-
@tag_pool[generate_number(0, @tag_pool.length).to_i]
|
84
|
-
end
|
85
|
-
#Create a random Color.
|
86
|
-
#Chooses from color_pool, or creates a random one from scratch if color_pool is empty.
|
87
|
-
def create_color()
|
88
|
-
if (color_pool.length != 0) then
|
89
|
-
return @color_pool[generate_number(0, @color_pool.length).to_i]
|
90
|
-
else
|
91
|
-
return Color.new(generate_random_number(0, 1), generate_random_number(0, 1), generate_random_number(0, 1))
|
92
|
-
end
|
93
|
-
end
|
94
|
-
#Create a random Location.
|
95
|
-
def create_location()
|
96
|
-
Location.new(
|
97
|
-
generate_random_number(0, @max_x - @min_x) + @min_x,
|
98
|
-
generate_random_number(0, @max_y - @min_y) + @min_y
|
99
|
-
)
|
100
|
-
end
|
101
|
-
#Create a random Vector.
|
102
|
-
def create_vector()
|
103
|
-
Vector.new(generate_number(0, @max_speed), generate_number(0, 360))
|
104
|
-
end
|
105
|
-
#Create a random Behavior.
|
106
|
-
def create_behavior()
|
107
|
-
behavior = Behavior.new
|
108
|
-
action_count = generate_number(0, @max_actions).to_i
|
109
|
-
action_count.times do
|
110
|
-
behavior.actions << create_action()
|
111
|
-
end
|
112
|
-
#Only add conditions if there's an action.
|
113
|
-
if action_count > 0 then
|
114
|
-
#There should always be a proximity condition.
|
115
|
-
behavior.conditions << create_proximity_condition()
|
116
|
-
#Add some additional conditions.
|
117
|
-
generate_random_number(0, @max_conditions).to_i.times do
|
118
|
-
behavior.conditions << create_condition()
|
119
|
-
end
|
120
|
-
end
|
121
|
-
behavior
|
122
|
-
end
|
123
|
-
#Create a random condition.
|
124
|
-
def create_condition()
|
125
|
-
case generate_number(0, 2).to_i
|
126
|
-
when 0
|
127
|
-
return create_tag_condition()
|
128
|
-
when 1
|
129
|
-
return create_age_condition()
|
130
|
-
else
|
131
|
-
raise "Invalid condition"
|
132
|
-
end
|
133
|
-
end
|
134
|
-
#Create a condition that looks for a random tag.
|
135
|
-
def create_tag_condition()
|
136
|
-
tag = create_tag()
|
137
|
-
lambda {|creature, target| target.tags.include?(tag)}
|
138
|
-
end
|
139
|
-
#Create a condition that looks for a random age.
|
140
|
-
def create_age_condition()
|
141
|
-
age = generate_number(0, 60)
|
142
|
-
lambda {|creature, target| target.age > age}
|
143
|
-
end
|
144
|
-
#Create a condition that looks for a random proximity.
|
145
|
-
def create_proximity_condition()
|
146
|
-
proximity = generate_number(0, 100)
|
147
|
-
lambda do |creature, target|
|
148
|
-
Utility.find_distance(creature.location, target.location) < proximity
|
149
|
-
end
|
150
|
-
end
|
151
|
-
#Create a random action.
|
152
|
-
def create_action()
|
153
|
-
case generate_random_number(0, 9).to_i
|
154
|
-
when 0
|
155
|
-
return create_accelerate_action()
|
156
|
-
when 1
|
157
|
-
return create_approach_action()
|
158
|
-
when 2
|
159
|
-
return create_flee_action()
|
160
|
-
when 3
|
161
|
-
return create_blend_action()
|
162
|
-
when 4
|
163
|
-
return create_mate_action()
|
164
|
-
when 5
|
165
|
-
return create_spawn_action()
|
166
|
-
when 6
|
167
|
-
return create_turn_action()
|
168
|
-
when 7
|
169
|
-
return create_eat_action()
|
170
|
-
when 8
|
171
|
-
return create_tag_action()
|
172
|
-
else
|
173
|
-
raise "Invalid action"
|
174
|
-
end
|
175
|
-
end
|
176
|
-
#Create an action that accelerates at a random rate.
|
177
|
-
def create_accelerate_action()
|
178
|
-
clock = Clock.new()
|
179
|
-
rate = generate_number(0, 10)
|
180
|
-
lambda {|creature, target| creature.vector.speed += rate * clock.elapsed_time}
|
181
|
-
end
|
182
|
-
#Create an action that turns in a circle.
|
183
|
-
def create_turn_action()
|
184
|
-
clock = Clock.new()
|
185
|
-
rate = generate_number(0, 360)
|
186
|
-
lambda {|creature, target| creature.vector.pitch += rate * clock.elapsed_time}
|
187
|
-
end
|
188
|
-
#Create an action that approaches the target.
|
189
|
-
def create_approach_action()
|
190
|
-
heading = Vector.new
|
191
|
-
rate = generate_number(0, 20)
|
192
|
-
lambda do |creature, target|
|
193
|
-
#Find the difference between the current heading and the angle to the target.
|
194
|
-
turn_angle = Utility.find_angle(creature.location, target.location) - heading.pitch
|
195
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
196
|
-
if turn_angle > 180 then
|
197
|
-
turn_angle -= 360.0
|
198
|
-
elsif turn_angle < -180 then
|
199
|
-
turn_angle += 360.0
|
200
|
-
end
|
201
|
-
#If turn angle is greater than allowed turn speed, reduce it.
|
202
|
-
turn_angle = Utility.constrain_value(turn_angle, rate)
|
203
|
-
#Turn the appropriate amount.
|
204
|
-
heading.pitch += turn_angle
|
205
|
-
#Apply the heading to the creature's movement vector.
|
206
|
-
creature.vector += heading
|
207
|
-
end
|
208
|
-
end
|
209
|
-
#Create an action that flees from the target.
|
210
|
-
def create_flee_action()
|
211
|
-
heading = Vector.new
|
212
|
-
rate = generate_number(0, 20)
|
213
|
-
lambda do |creature, target|
|
214
|
-
#Find the difference between the current heading and the angle AWAY from the target.
|
215
|
-
turn_angle = Utility.find_angle(creature.location, target.location) - heading.pitch + 180
|
216
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
217
|
-
if turn_angle > 180 then
|
218
|
-
turn_angle -= 360.0
|
219
|
-
elsif turn_angle < -180 then
|
220
|
-
turn_angle += 360.0
|
221
|
-
end
|
222
|
-
#If turn angle is greater than allowed turn speed, reduce it.
|
223
|
-
turn_angle = Utility.constrain_value(turn_angle, rate)
|
224
|
-
#Turn the appropriate amount.
|
225
|
-
heading.pitch += turn_angle
|
226
|
-
#Apply the heading to the creature's movement vector.
|
227
|
-
creature.vector += heading
|
228
|
-
end
|
229
|
-
end
|
230
|
-
#Create an action that shifts the subject's color to match the target.
|
231
|
-
def create_blend_action()
|
232
|
-
lambda {|creature, target| creature.color += target.color}
|
233
|
-
end
|
234
|
-
#Create an action that mates with the target.
|
235
|
-
def create_mate_action()
|
236
|
-
#TODO
|
237
|
-
lambda {|creature, target| }
|
238
|
-
end
|
239
|
-
#Create an action that spawns a new creature.
|
240
|
-
def create_spawn_action()
|
241
|
-
#TODO
|
242
|
-
lambda {|creature, target| }
|
243
|
-
end
|
244
|
-
#Create an action that eats the target.
|
245
|
-
def create_eat_action()
|
246
|
-
lambda {|creature, target| @environment.objects.delete(target)}
|
247
|
-
end
|
248
|
-
#Create an action that applies a tag to the target.
|
249
|
-
def create_tag_action()
|
250
|
-
tag = create_tag()
|
251
|
-
lambda {|creature, target| target.tags << tag unless target.tags.include?(tag)}
|
252
|
-
end
|
253
|
-
#Generate a number between the given minimum and maximum, based on the current system time.
|
254
|
-
def generate_number(minimum, maximum)
|
255
|
-
(Time.new.to_f % (maximum - minimum)) + minimum
|
256
|
-
end
|
257
|
-
#Generate a random number between the given minimum and maximum.
|
258
|
-
def generate_random_number(minimum, maximum)
|
259
|
-
value = rand * (maximum - minimum) + minimum
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
#Keeps all objects within a set of walls.
|
266
|
-
class EncloseBehavior < Behavior
|
267
|
-
|
268
|
-
#Positions of walls.
|
269
|
-
attr_accessor :left, :top, :right, :bottom
|
270
|
-
|
271
|
-
def initialize
|
272
|
-
super
|
273
|
-
@left, @top, @right, @bottom = 0, 0, 0, 0
|
274
|
-
@actions << lambda do |boundary, object|
|
275
|
-
#If object is beyond a boundary, set its position equal to the boundary and reflect it.
|
276
|
-
if (object.location.x < @left) then
|
277
|
-
object.location.x = @left
|
278
|
-
object.vector.pitch = Utility.find_reflection_angle(90, object.vector.pitch)
|
279
|
-
elsif (object.location.x > @right) then
|
280
|
-
object.location.x = @right
|
281
|
-
object.vector.pitch = Utility.find_reflection_angle(270, object.vector.pitch)
|
282
|
-
end
|
283
|
-
if (object.location.y < @top) then
|
284
|
-
object.location.y = @top
|
285
|
-
object.vector.pitch = Utility.find_reflection_angle(0, object.vector.pitch)
|
286
|
-
elsif (object.location.y > @bottom) then
|
287
|
-
object.location.y = @bottom
|
288
|
-
object.vector.pitch = Utility.find_reflection_angle(180, object.vector.pitch)
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
end
|
294
|
-
|
295
|
-
|
296
37
|
|
297
38
|
class Application
|
298
39
|
|
@@ -334,15 +75,12 @@ class Application
|
|
334
75
|
|
335
76
|
|
336
77
|
#Keep all objects within a boundary.
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
@environment.environmental_factors <<
|
343
|
-
|
344
|
-
#Create a creature generator.
|
345
|
-
@generator = Generator.new(@environment, 0, 0, @width, @height)
|
78
|
+
enclosure = Enclosure.new
|
79
|
+
enclosure.left = 0
|
80
|
+
enclosure.bottom = 0
|
81
|
+
enclosure.top = @height
|
82
|
+
enclosure.right = @width
|
83
|
+
@environment.environmental_factors << enclosure
|
346
84
|
|
347
85
|
#Create thread to update environment.
|
348
86
|
thread = Thread.new do
|
@@ -350,9 +88,7 @@ class Application
|
|
350
88
|
begin
|
351
89
|
|
352
90
|
drawing_clock = Clock.new
|
353
|
-
birth_clock = Clock.new
|
354
91
|
time_per_frame = 1.0 / @fps
|
355
|
-
time_since_birth = 0
|
356
92
|
|
357
93
|
loop do
|
358
94
|
|
@@ -411,90 +147,30 @@ class Application
|
|
411
147
|
Utility.find_angle(@press_location, @release_location) #Move in direction of drag.
|
412
148
|
),
|
413
149
|
0,
|
150
|
+
1,
|
414
151
|
@tags_box.text.split(/,\s*/)
|
415
152
|
)
|
416
153
|
behavior = Behavior.new
|
417
154
|
condition_tags = @tag_condition_box.text
|
418
155
|
condition_tags.split(/,\s*/).each do |tag|
|
419
|
-
behavior.conditions <<
|
420
|
-
target.tags.include?(tag)
|
421
|
-
end
|
156
|
+
behavior.conditions << TagCondition.new(tag)
|
422
157
|
end
|
423
158
|
proximity = @proximity_condition_slider.value
|
424
|
-
if proximity > 0
|
425
|
-
behavior.conditions << lambda do |creature, target|
|
426
|
-
Utility.find_distance(creature.location, target.location) < proximity
|
427
|
-
end
|
428
|
-
end
|
159
|
+
behavior.conditions << ProximityCondition.new(proximity) if proximity > 0
|
429
160
|
age = @age_condition_slider.value
|
430
|
-
if age > 0
|
431
|
-
behavior.conditions << lambda do |creature, target|
|
432
|
-
target.age > age
|
433
|
-
end
|
434
|
-
end
|
161
|
+
behavior.conditions << AgeCondition.new(age) if age > 0
|
435
162
|
acceleration = @acceleration_slider.value
|
436
|
-
if acceleration != 0
|
437
|
-
behavior.actions << lambda do |creature, target|
|
438
|
-
creature.vector.speed += acceleration
|
439
|
-
creature.vector.speed = 0 if creature.vector.speed < 0
|
440
|
-
end
|
441
|
-
end
|
163
|
+
behavior.actions << AccelerateAction.new(acceleration) if acceleration != 0
|
442
164
|
turn = @turn_slider.value
|
443
|
-
if turn != 0
|
444
|
-
behavior.actions << lambda do |creature, target|
|
445
|
-
creature.vector.pitch += turn
|
446
|
-
end
|
447
|
-
end
|
165
|
+
behavior.actions << TurnAction.new(turn) if turn != 0
|
448
166
|
approach_angle = @approach_slider.value
|
449
|
-
if approach_angle > 0
|
450
|
-
heading = creature.vector.clone
|
451
|
-
behavior.actions << lambda do |creature, target|
|
452
|
-
#Find the difference between the current heading and the angle to the target.
|
453
|
-
turn_angle = Utility.find_angle(creature.location, target.location) - heading.pitch
|
454
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
455
|
-
if turn_angle > 180 then
|
456
|
-
turn_angle -= 360.0
|
457
|
-
elsif turn_angle < -180 then
|
458
|
-
turn_angle += 360.0
|
459
|
-
end
|
460
|
-
#If turn angle is greater than allowed turn speed, reduce it.
|
461
|
-
turn_angle = Utility.constrain_value(turn_angle, approach_angle)
|
462
|
-
#Turn the appropriate amount.
|
463
|
-
heading.pitch += turn_angle
|
464
|
-
#Apply the heading to the creature's movement vector.
|
465
|
-
creature.vector += heading
|
466
|
-
end
|
467
|
-
end
|
167
|
+
behavior.actions << ApproachAction.new(Vector.new(1, creature.vector.pitch), approach_angle) if approach_angle > 0
|
468
168
|
flee_angle = @flee_slider.value
|
469
|
-
if flee_angle > 0
|
470
|
-
|
471
|
-
behavior.actions << lambda do |creature, target|
|
472
|
-
#Find the difference between the current heading and the angle to the target.
|
473
|
-
turn_angle = Utility.find_angle(creature.location, target.location) - heading.pitch + 180
|
474
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
475
|
-
if turn_angle > 180 then
|
476
|
-
turn_angle -= 360.0
|
477
|
-
elsif turn_angle < -180 then
|
478
|
-
turn_angle += 360.0
|
479
|
-
end
|
480
|
-
#If turn angle is greater than allowed turn speed, reduce it.
|
481
|
-
turn_angle = Utility.constrain_value(turn_angle, flee_angle)
|
482
|
-
#Turn the appropriate amount.
|
483
|
-
heading.pitch += turn_angle
|
484
|
-
#Apply the heading to the creature's movement vector.
|
485
|
-
creature.vector += heading
|
486
|
-
end
|
487
|
-
end
|
488
|
-
if @eat_flag.active?
|
489
|
-
behavior.actions << lambda do |creature, target|
|
490
|
-
@environment.objects.delete(target)
|
491
|
-
end
|
492
|
-
end
|
169
|
+
behavior.actions << FleeAction.new(Vector.new(5, creature.vector.pitch), flee_angle) if flee_angle > 0
|
170
|
+
behavior.actions << EatAction.new(@environment) if @eat_flag.active?
|
493
171
|
apply_tags = @tag_action_box.text
|
494
172
|
apply_tags.split(/,\s*/).each do |tag|
|
495
|
-
behavior.
|
496
|
-
target.tags << tag unless target.tags.include?(tag)
|
497
|
-
end
|
173
|
+
behavior.actions << TagAction.new(tag)
|
498
174
|
end
|
499
175
|
creature.behaviors << behavior
|
500
176
|
@environment.objects << creature
|
data/bin/zyps_demo
CHANGED
@@ -20,10 +20,14 @@
|
|
20
20
|
|
21
21
|
begin
|
22
22
|
require 'zyps'
|
23
|
+
require 'zyps/actions'
|
24
|
+
require 'zyps/conditions'
|
23
25
|
require 'zyps/views/trails'
|
24
26
|
rescue LoadError
|
25
27
|
require 'rubygems'
|
26
28
|
require 'zyps'
|
29
|
+
require 'zyps/actions'
|
30
|
+
require 'zyps/conditions'
|
27
31
|
require 'zyps/views/trails'
|
28
32
|
end
|
29
33
|
|
@@ -38,6 +42,8 @@ class Demo
|
|
38
42
|
FRAME_COUNT = 80
|
39
43
|
#Number of frames per second.
|
40
44
|
FRAMES_PER_SECOND = 30
|
45
|
+
#Default size of game objects.
|
46
|
+
DEFAULT_OBJECT_SIZE = 78.5 #5 units in radius.
|
41
47
|
|
42
48
|
#Set up a window, a canvas, and an object environment, then run the given block.
|
43
49
|
def demo
|
@@ -102,10 +108,12 @@ class Demo
|
|
102
108
|
count.times do |i|
|
103
109
|
multiplier = i / count.to_f
|
104
110
|
environment.objects << Creature.new(
|
105
|
-
i,
|
111
|
+
i, #Name.
|
106
112
|
Location.new(multiplier * @view.width, multiplier * @view.height),
|
107
113
|
Color.new(multiplier, 1 - multiplier, multiplier / 2 + 0.5),
|
108
|
-
Vector.new(100 * multiplier, multiplier * 360)
|
114
|
+
Vector.new(100 * multiplier, multiplier * 360),
|
115
|
+
0, #Age.
|
116
|
+
DEFAULT_OBJECT_SIZE #Size.
|
109
117
|
)
|
110
118
|
end
|
111
119
|
end
|
@@ -125,7 +133,9 @@ class Demo
|
|
125
133
|
say("The things that populate an environment are called GameObjects. Each object has:")
|
126
134
|
object = GameObject.new
|
127
135
|
say("...a name")
|
128
|
-
object.name = "
|
136
|
+
object.name = "Huey"
|
137
|
+
say("...a size")
|
138
|
+
object.size = DEFAULT_OBJECT_SIZE
|
129
139
|
say("...a Location with x and y coordiates")
|
130
140
|
object.location = Location.new(@view.width/2, @view.height/2)
|
131
141
|
say("...a Color with red, green and blue components ranging from 0 to 1")
|
@@ -136,14 +146,28 @@ class Demo
|
|
136
146
|
say("Once your object is ready, add it to the environment.")
|
137
147
|
@environment.objects << object
|
138
148
|
|
139
|
-
say("
|
149
|
+
say("Add a view as an observer of an Environment, and it will draw the objects.")
|
140
150
|
say("Call an environment's interact() method to have the objects in it move around.")
|
141
|
-
say("Our demo's animate() method does
|
151
|
+
say("Our demo's animate() method does this for us.")
|
142
152
|
animate(FRAME_COUNT)
|
143
153
|
|
144
154
|
say("Let's add a couple more objects with different colors and vectors.")
|
145
|
-
@environment.objects << GameObject.new(
|
146
|
-
|
155
|
+
@environment.objects << GameObject.new(
|
156
|
+
"Duey", #Name.
|
157
|
+
Location.new(@view.width/2, @view.height/2),
|
158
|
+
Color.new(0, 1, 0),
|
159
|
+
Vector.new(20, 135),
|
160
|
+
0, #Age.
|
161
|
+
DEFAULT_OBJECT_SIZE * 2 #Size.
|
162
|
+
)
|
163
|
+
@environment.objects << GameObject.new(
|
164
|
+
"Louie", #Name.
|
165
|
+
Location.new(@view.width/2, @view.height/2),
|
166
|
+
Color.new(0, 0, 1),
|
167
|
+
Vector.new(30, 225),
|
168
|
+
0, #Age.
|
169
|
+
DEFAULT_OBJECT_SIZE * 3 #Size.
|
170
|
+
)
|
147
171
|
animate(FRAME_COUNT)
|
148
172
|
|
149
173
|
say("The viewing area can be resized at any time via its width and height attributes.")
|
@@ -151,16 +175,22 @@ class Demo
|
|
151
175
|
@view.height += 100
|
152
176
|
animate(FRAME_COUNT)
|
153
177
|
|
154
|
-
say("TrailsView lets you set the
|
155
|
-
@view.
|
156
|
-
@view.trail_length = 10
|
178
|
+
say("TrailsView lets you set the length of the trails as well.")
|
179
|
+
@view.trail_length = 50
|
157
180
|
animate(FRAME_COUNT)
|
158
181
|
|
159
182
|
end
|
160
|
-
|
183
|
+
|
161
184
|
end
|
162
185
|
|
163
186
|
|
187
|
+
class Gravity < EnvironmentalFactor
|
188
|
+
#Accelerate object toward the 'ground'.
|
189
|
+
def act(target)
|
190
|
+
target.vector.y += 9.8
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
164
194
|
#Demonstrates environmental factors by adding gravity to the environment.
|
165
195
|
def test_environmental_factors
|
166
196
|
|
@@ -172,26 +202,19 @@ class Demo
|
|
172
202
|
animate(FRAME_COUNT)
|
173
203
|
|
174
204
|
say("Let's add a new EnvironmentalFactor to simulate gravity.")
|
175
|
-
gravity =
|
205
|
+
gravity = Gravity.new
|
176
206
|
|
177
|
-
say("We
|
178
|
-
accelerate = Behavior.new
|
179
|
-
say("The behavior will have a single action: to accelerate objects toward the 'ground' at 9.8 meters/second.")
|
180
|
-
accelerate.actions << lambda {|gravity, target| target.vector.y += 9.8}
|
181
|
-
say("We add the behavior to the EnvironmentalFactor.")
|
182
|
-
gravity.behaviors << accelerate
|
183
|
-
say("Then we add the EnvironmentalFactor to the Environment.")
|
207
|
+
say("We add gravity to the Environment.")
|
184
208
|
@environment.environmental_factors << gravity
|
185
209
|
|
186
210
|
say("Everything immediately drops.")
|
187
211
|
animate(FRAME_COUNT)
|
188
212
|
|
189
213
|
end
|
190
|
-
|
214
|
+
|
191
215
|
end
|
192
216
|
|
193
217
|
|
194
|
-
|
195
218
|
#Demonstrates creature behaviors.
|
196
219
|
def test_behaviors
|
197
220
|
|
@@ -199,17 +222,17 @@ class Demo
|
|
199
222
|
|
200
223
|
thread = Thread.new do
|
201
224
|
|
202
|
-
say("Let's add a
|
225
|
+
say("Let's add a Behavior to our creatures.")
|
203
226
|
chase = Behavior.new
|
204
227
|
|
205
|
-
say("
|
206
|
-
|
207
|
-
|
208
|
-
creature.vector.pitch = angle_to_target
|
209
|
-
end
|
228
|
+
say("A Behavior has one or more Action objects that define an action to take on the current target.")
|
229
|
+
say("We'll add an Action that makes the creatures head straight toward their target.")
|
230
|
+
chase.actions << FaceAction.new
|
210
231
|
|
232
|
+
say("A Behavior also has one or more Condition objects.")
|
233
|
+
say("Unless every Condition is true, the action(s) won't be carried out.")
|
211
234
|
say("So that they don't target every creature on the screen, we'll add a condition to the behavior saying the target must have the label 'food'.")
|
212
|
-
chase.conditions <<
|
235
|
+
chase.conditions << TagCondition.new("food")
|
213
236
|
|
214
237
|
say("We'll apply this behavior to all creatures currently in the environment.")
|
215
238
|
@environment.objects.each {|creature| creature.behaviors << chase}
|
@@ -217,11 +240,12 @@ class Demo
|
|
217
240
|
|
218
241
|
say("Then we'll toss a piece of food (a GameObject with the label 'food') into the environment.")
|
219
242
|
@environment.objects << GameObject.new(
|
220
|
-
"target",
|
243
|
+
"target", #Name.
|
221
244
|
Location.new(@view.width / 2, @view.height / 2),
|
222
245
|
Color.new(1, 1, 1),
|
223
246
|
Vector.new(50, 315),
|
224
247
|
0, #Age.
|
248
|
+
DEFAULT_OBJECT_SIZE * 2, #Size.
|
225
249
|
["food"] #Tags.
|
226
250
|
)
|
227
251
|
|
@@ -235,17 +259,14 @@ class Demo
|
|
235
259
|
|
236
260
|
#A Creature that changes the colors of other objects.
|
237
261
|
class Morpher < Creature
|
262
|
+
#Changes an object's color.
|
238
263
|
def initialize(*arguments)
|
239
264
|
super
|
240
265
|
morph = Behavior.new
|
241
266
|
#Shift the target's color to match the creature's.
|
242
|
-
morph.actions <<
|
243
|
-
target.color.red += 0.1 if target.color.red < creature.color.red
|
244
|
-
target.color.green += 0.1 if target.color.green < creature.color.green
|
245
|
-
target.color.blue += 0.1 if target.color.blue < creature.color.blue
|
246
|
-
end
|
267
|
+
morph.actions << BlendAction.new(self.color)
|
247
268
|
#Act only on nearby targets.
|
248
|
-
morph.conditions <<
|
269
|
+
morph.conditions << ProximityCondition.new(50)
|
249
270
|
@behaviors << morph
|
250
271
|
end
|
251
272
|
end
|
@@ -260,15 +281,15 @@ class Demo
|
|
260
281
|
say("Morphers are created with a single behavior, which shifts the color of any nearby target to match the Morpher's color.")
|
261
282
|
|
262
283
|
say("Let's place a red Morpher...")
|
263
|
-
@environment.objects << Morpher.new(nil, Location.new(0, 100), Color.new(1, 0, 0), Vector.new(100, 0))
|
284
|
+
@environment.objects << Morpher.new(nil, Location.new(0, 100), Color.new(1, 0, 0), Vector.new(100, 0), 0, DEFAULT_OBJECT_SIZE)
|
264
285
|
say("a green one...")
|
265
|
-
@environment.objects << Morpher.new(nil, Location.new(0, 150), Color.new(0, 1, 0), Vector.new(200, 0))
|
286
|
+
@environment.objects << Morpher.new(nil, Location.new(0, 150), Color.new(0, 1, 0), Vector.new(200, 0), 0, DEFAULT_OBJECT_SIZE)
|
266
287
|
say("and a blue one...")
|
267
|
-
@environment.objects << Morpher.new(nil, Location.new(0, 200), Color.new(0, 0, 1), Vector.new(300, 0))
|
288
|
+
@environment.objects << Morpher.new(nil, Location.new(0, 200), Color.new(0, 0, 1), Vector.new(300, 0), 0, DEFAULT_OBJECT_SIZE)
|
268
289
|
|
269
290
|
say("And see what they do.")
|
270
291
|
thread = Thread.new {animate(FRAME_COUNT)}
|
271
|
-
|
292
|
+
|
272
293
|
end
|
273
294
|
|
274
295
|
|
@@ -280,30 +301,17 @@ class Demo
|
|
280
301
|
thread = Thread.new do
|
281
302
|
|
282
303
|
|
283
|
-
say("Many actions need to happen smoothly over time, such as accelerating at a given rate.")
|
284
|
-
|
285
304
|
say("Here are some Creatures, just plodding along.")
|
286
305
|
animate(FRAME_COUNT / 4)
|
287
306
|
say("We're going to have them pick up the pace.")
|
288
307
|
|
289
|
-
say("
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
say("It will multiply that time by a given rate, say 100 meters/second.")
|
295
|
-
say("Let's say it's been 0.1 seconds since this creature last accelerated.")
|
296
|
-
say("100 times 0.1 is 10.")
|
297
|
-
say("So we should add 10 meters/second to the creature's speed.")
|
298
|
-
accelerate = Behavior.new
|
299
|
-
accelerate.actions << lambda do |creature, target|
|
300
|
-
#Accelerate the appropriate amount for the elapsed time.
|
301
|
-
creature.vector.speed += 100 * clocks[creature].elapsed_time
|
308
|
+
say("We add a Behavior with an AccelerateAction to all the creatures, and specify they should increase their speed by 100 units/second...")
|
309
|
+
@environment.objects.each do |creature|
|
310
|
+
accelerate = Behavior.new
|
311
|
+
accelerate.actions << AccelerateAction.new(100)
|
312
|
+
creature.behaviors << accelerate
|
302
313
|
end
|
303
314
|
|
304
|
-
say("We add acceleration to all the creatures...")
|
305
|
-
@environment.objects.each {|creature| creature.behaviors << accelerate}
|
306
|
-
|
307
315
|
say("And watch them rocket away.")
|
308
316
|
animate(FRAME_COUNT)
|
309
317
|
|
@@ -319,24 +327,16 @@ class Demo
|
|
319
327
|
|
320
328
|
thread = Thread.new do
|
321
329
|
|
322
|
-
say("
|
330
|
+
say("This time we'll use the TurnAction class.")
|
323
331
|
animate(FRAME_COUNT / 2)
|
324
332
|
|
325
|
-
say("
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
say("We add the result to the Vector angle.")
|
331
|
-
turn = Behavior.new
|
332
|
-
turn.actions << lambda do |creature, target|
|
333
|
-
#Turn the appropriate amount for the elapsed time.
|
334
|
-
creature.vector.pitch += 100 * clocks[creature].elapsed_time
|
333
|
+
say("We tell each creature it should turn by 90 degrees/second...")
|
334
|
+
@environment.objects.each do |creature|
|
335
|
+
turn = Behavior.new
|
336
|
+
turn.actions << TurnAction.new(90)
|
337
|
+
creature.behaviors << turn
|
335
338
|
end
|
336
339
|
|
337
|
-
say("We add the behavior to each Creature...")
|
338
|
-
@environment.objects.each {|creature| creature.behaviors << turn}
|
339
|
-
|
340
340
|
say("And watch things spiral out of control.")
|
341
341
|
animate(FRAME_COUNT)
|
342
342
|
|
@@ -351,55 +351,25 @@ class Demo
|
|
351
351
|
populate(@environment, 50)
|
352
352
|
|
353
353
|
say("When your car skids on ice, you might steer in a different direction, but you're going to keep following your original vector for a while.")
|
354
|
-
say("
|
355
|
-
|
356
|
-
say("We
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
say("We create a Behavior which adds the Vector the creature WANTS to follow to the Vector it's ACTUALLY following.")
|
363
|
-
approach = Behavior.new
|
364
|
-
approach.actions << lambda do |creature, target|
|
365
|
-
|
366
|
-
#Find the difference between the current heading and the angle to the target.
|
367
|
-
turn_angle = Utility.find_angle(creature.location, target.location) - headings[creature].pitch
|
368
|
-
|
369
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
370
|
-
if turn_angle > 180 then
|
371
|
-
turn_angle -= 360.0
|
372
|
-
elsif turn_angle < -180 then
|
373
|
-
turn_angle += 360.0
|
374
|
-
end
|
375
|
-
|
376
|
-
#If turn angle is greater than allowed turn speed, reduce it.
|
377
|
-
turn_angle = Utility.constrain_value(turn_angle, max_turn_angle)
|
378
|
-
|
379
|
-
#Turn the appropriate amount.
|
380
|
-
headings[creature].pitch += turn_angle
|
381
|
-
|
382
|
-
#Apply the heading to the creature's movement vector.
|
383
|
-
creature.vector += headings[creature]
|
384
|
-
|
385
|
-
end
|
386
|
-
|
387
|
-
say("We add a condition that it should only target its prey.")
|
388
|
-
approach.conditions << lambda do |creature, target|
|
389
|
-
target.tags.include?('prey')
|
354
|
+
say("Our ApproachAction adds the vector the creature WANTS to follow to the vector it's ACTUALLY following.")
|
355
|
+
say("We add a behavior with an ApproachAction to all creatures...")
|
356
|
+
say("We also add a condition that it should only target food.")
|
357
|
+
@environment.objects.each do |creature|
|
358
|
+
approach = Behavior.new
|
359
|
+
approach.actions << ApproachAction.new(creature.vector)
|
360
|
+
approach.conditions << TagCondition.new("food")
|
361
|
+
creature.behaviors << approach
|
390
362
|
end
|
391
363
|
|
392
|
-
say("We add the behavior to all creatures...")
|
393
|
-
@environment.objects.each {|creature| creature.behaviors << approach}
|
394
|
-
|
395
364
|
say("Add a target...")
|
396
365
|
@environment.objects << Creature.new(
|
397
366
|
"target",
|
398
|
-
Location.new(@view.width / 2, @view.height /
|
367
|
+
Location.new(@view.width / 2, @view.height / 3),
|
399
368
|
Color.new(1, 1, 1),
|
400
369
|
Vector.new(3, 0),
|
401
370
|
0, #Age.
|
402
|
-
|
371
|
+
DEFAULT_OBJECT_SIZE, #Size.
|
372
|
+
["food"] #Tags.
|
403
373
|
)
|
404
374
|
|
405
375
|
say("And watch them all TRY to catch it.")
|
@@ -408,58 +378,27 @@ class Demo
|
|
408
378
|
end
|
409
379
|
|
410
380
|
|
411
|
-
|
381
|
+
|
382
|
+
#Demonstrates adding vectors.
|
412
383
|
def test_flee
|
413
384
|
|
414
|
-
populate(@environment,
|
415
|
-
|
416
|
-
say("Fleeing from something is just like approaching it, but we head in the OPPOSITE direction.")
|
417
|
-
say("Just get the angle toward the object, then add 180 degrees.")
|
418
|
-
|
419
|
-
#Keep a separate heading for each object.
|
420
|
-
headings = Hash.new {|h, k| h[k] = Vector.new(k.vector.speed, k.vector.pitch)}
|
421
|
-
|
422
|
-
#Create a behavior.
|
423
|
-
max_turn_angle = 20
|
424
|
-
flee = Behavior.new
|
425
|
-
flee.actions << lambda do |creature, target|
|
426
|
-
|
427
|
-
#Find the difference between the current heading and the angle AWAY from the target.
|
428
|
-
turn_angle = Utility.find_angle(creature.location, target.location) - headings[creature].pitch + 180
|
429
|
-
|
430
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
431
|
-
if turn_angle > 180 then
|
432
|
-
turn_angle -= 360.0
|
433
|
-
elsif turn_angle < -180 then
|
434
|
-
turn_angle += 360.0
|
435
|
-
end
|
436
|
-
|
437
|
-
#If turn angle is greater than allowed turn speed, reduce it.
|
438
|
-
turn_angle = Utility.constrain_value(turn_angle, max_turn_angle)
|
439
|
-
|
440
|
-
#Turn the appropriate amount for the elapsed time.
|
441
|
-
headings[creature].pitch += turn_angle
|
442
|
-
|
443
|
-
#Apply the heading to the creature's movement vector.
|
444
|
-
creature.vector += headings[creature]
|
445
|
-
|
446
|
-
end
|
385
|
+
populate(@environment, 50)
|
447
386
|
|
448
|
-
|
449
|
-
|
450
|
-
|
387
|
+
say("A FleeAction is just like an ApproachAction, but we head in the OPPOSITE direction.")
|
388
|
+
@environment.objects.each do |creature|
|
389
|
+
flee = Behavior.new
|
390
|
+
flee.actions << FleeAction.new(creature.vector)
|
391
|
+
flee.conditions << TagCondition.new("predator")
|
392
|
+
creature.behaviors << flee
|
451
393
|
end
|
452
394
|
|
453
|
-
#Add behavior to creatures.
|
454
|
-
@environment.objects.each {|creature| creature.behaviors << flee}
|
455
|
-
|
456
|
-
#Add a target.
|
457
395
|
@environment.objects << Creature.new(
|
458
|
-
"
|
396
|
+
"target",
|
459
397
|
Location.new(@view.width / 2, @view.height / 2),
|
460
398
|
Color.new(1, 1, 1),
|
461
399
|
Vector.new(3, 0),
|
462
400
|
0, #Age.
|
401
|
+
DEFAULT_OBJECT_SIZE, #Size.
|
463
402
|
["predator"] #Tags.
|
464
403
|
)
|
465
404
|
|
@@ -468,47 +407,32 @@ class Demo
|
|
468
407
|
end
|
469
408
|
|
470
409
|
|
471
|
-
|
472
|
-
class Destroy < Behavior
|
473
|
-
#Environment from which targets will be removed.
|
474
|
-
attr_accessor :environment
|
475
|
-
def initialize(actions = [], conditions = [], environment = Environment.new)
|
476
|
-
super(actions, conditions)
|
477
|
-
@environment = environment
|
478
|
-
#"Kill" target.
|
479
|
-
self.actions << lambda do |creature, target|
|
480
|
-
@environment.objects.delete(target)
|
481
|
-
end
|
482
|
-
#Act only if target is close.
|
483
|
-
self.conditions << lambda do |creature, target|
|
484
|
-
Utility.find_distance(creature.location, target.location) < 25
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
|
410
|
+
|
490
411
|
#Demonstrates keeping a reference to an Environment so a Creature can alter it.
|
491
|
-
def
|
412
|
+
def test_eat
|
492
413
|
|
493
414
|
populate(@environment)
|
494
415
|
|
495
416
|
say("Most games are all about destruction, but there hasn't been much so far.")
|
496
417
|
say("Let's create a creature that causes some havoc.")
|
497
|
-
|
498
|
-
|
499
|
-
say("
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
say("
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
418
|
+
predator = Creature.new(nil, Location.new(0, 150), Color.new(0, 1, 0), Vector.new(200, 0), 0, DEFAULT_OBJECT_SIZE * 2)
|
419
|
+
|
420
|
+
say("The EatAction eats targets by removing them from their environment.")
|
421
|
+
say("Creatures and their Actions normally know nothing about the Environment they belong to, so EatAction takes an Environment in its constructor.")
|
422
|
+
say("EatAction finds the target in Environment.objects and removes it.")
|
423
|
+
action = EatAction.new(@environment)
|
424
|
+
|
425
|
+
say("Create a behavior...")
|
426
|
+
behavior = Behavior.new
|
427
|
+
say("Add the action to the behavior...")
|
428
|
+
behavior.actions << action
|
429
|
+
say("Add a condition that they must collide first...")
|
430
|
+
behavior.conditions << CollisionCondition.new
|
431
|
+
say("Add the behavior to the creature...")
|
432
|
+
predator.behaviors << behavior
|
509
433
|
|
510
434
|
say("Drop the creature into the actual environment...")
|
511
|
-
@environment.objects <<
|
435
|
+
@environment.objects << predator
|
512
436
|
|
513
437
|
say("And - chomp!")
|
514
438
|
thread = Thread.new {animate(FRAME_COUNT)}
|
@@ -518,6 +442,7 @@ class Demo
|
|
518
442
|
|
519
443
|
#Run all the demos.
|
520
444
|
def main
|
445
|
+
say "This is a demonstration of the Zyps library."
|
521
446
|
say "After each demo, close the window to proceed."
|
522
447
|
say("-" * 30)
|
523
448
|
demo {test_render}
|
@@ -528,7 +453,10 @@ class Demo
|
|
528
453
|
demo {test_turn}
|
529
454
|
demo {test_approach}
|
530
455
|
demo {test_flee}
|
531
|
-
demo {
|
456
|
+
demo {test_eat}
|
457
|
+
say "To learn more about how the library works, you can read the source code in the 'bin/zyps_demo' file in the Zyps distribution."
|
458
|
+
say "And if you want to code your own Actions, Conditions, EnvironmentalFactors, or Views, see the distribution's 'lib' folder for examples."
|
459
|
+
say "Thanks for watching!"
|
532
460
|
end
|
533
461
|
|
534
462
|
|