zyps 0.7.5 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +674 -674
- data/README_windows.txt +3 -0
- data/bin/zyps +17 -12
- data/bin/zyps-175 +514 -0
- data/bin/zyps_demo +139 -72
- data/lib/zyps.rb +71 -3
- data/lib/zyps/actions.rb +98 -9
- data/lib/zyps/conditions.rb +22 -0
- data/test/test_zyps.rb +51 -0
- data/test/zyps/test_actions.rb +78 -17
- data/test/zyps/test_conditions.rb +12 -0
- metadata +58 -64
data/bin/zyps_demo
CHANGED
@@ -149,30 +149,35 @@ class Demo < Wx::App
|
|
149
149
|
test_behaviors_2
|
150
150
|
say "-" * 30
|
151
151
|
when 600:
|
152
|
-
@environment.objects = []
|
153
|
-
test_change_color
|
154
|
-
say "-" * 30
|
155
|
-
when 800:
|
156
152
|
@environment.objects = []
|
157
153
|
test_accelerate
|
158
154
|
say "-" * 30
|
159
|
-
when
|
155
|
+
when 700:
|
160
156
|
@environment.objects = []
|
161
157
|
test_turn
|
162
158
|
say "-" * 30
|
163
|
-
when
|
159
|
+
when 900:
|
164
160
|
@environment.objects = []
|
165
161
|
test_approach
|
166
162
|
say "-" * 30
|
167
|
-
when
|
163
|
+
when 1100:
|
168
164
|
@environment.objects = []
|
169
165
|
test_flee
|
170
166
|
say "-" * 30
|
171
|
-
when
|
167
|
+
when 1300:
|
172
168
|
@environment.objects = []
|
173
169
|
test_eat
|
174
170
|
say "-" * 30
|
175
|
-
when
|
171
|
+
when 1400:
|
172
|
+
@environment.objects = []
|
173
|
+
test_explode
|
174
|
+
say "-" * 30
|
175
|
+
when 1500:
|
176
|
+
@environment.objects = []
|
177
|
+
@environment.environmental_factors = []
|
178
|
+
test_shoot
|
179
|
+
say "-" * 30
|
180
|
+
when 1600:
|
176
181
|
finish
|
177
182
|
end
|
178
183
|
@update_count += 1
|
@@ -180,11 +185,12 @@ class Demo < Wx::App
|
|
180
185
|
|
181
186
|
|
182
187
|
#Populate an environment with the given number of creatures.
|
183
|
-
def
|
184
|
-
@log.debug "
|
188
|
+
def generate_creatures(count = 50)
|
189
|
+
@log.debug "Generating #{count} creatures."
|
190
|
+
objects = []
|
185
191
|
count.times do |i|
|
186
192
|
multiplier = i / count.to_f
|
187
|
-
|
193
|
+
objects << Creature.new(
|
188
194
|
:name => i,
|
189
195
|
:location => Location.new(multiplier * WIDTH, multiplier * HEIGHT),
|
190
196
|
:color => Color.new(multiplier, 1 - multiplier, multiplier / 2 + 0.5),
|
@@ -192,6 +198,7 @@ class Demo < Wx::App
|
|
192
198
|
:size => DEFAULT_OBJECT_SIZE
|
193
199
|
)
|
194
200
|
end
|
201
|
+
objects
|
195
202
|
end
|
196
203
|
|
197
204
|
|
@@ -240,7 +247,7 @@ class Demo < Wx::App
|
|
240
247
|
#Demonstrates environmental factors by adding gravity to the environment.
|
241
248
|
def test_environmental_factors
|
242
249
|
|
243
|
-
|
250
|
+
@environment.objects = generate_creatures
|
244
251
|
|
245
252
|
say("Without gravity, objects just travel on forever.")
|
246
253
|
|
@@ -262,7 +269,7 @@ class Demo < Wx::App
|
|
262
269
|
#Demonstrates creature behaviors.
|
263
270
|
def test_behaviors
|
264
271
|
|
265
|
-
|
272
|
+
@environment.objects = generate_creatures
|
266
273
|
|
267
274
|
say("Let's add a Behavior to our creatures.")
|
268
275
|
chase = Behavior.new
|
@@ -288,7 +295,7 @@ class Demo < Wx::App
|
|
288
295
|
@environment.objects << GameObject.new(
|
289
296
|
:name => "target",
|
290
297
|
:location => Location.new(WIDTH / 2, HEIGHT / 2),
|
291
|
-
:color => Color.
|
298
|
+
:color => Color.white,
|
292
299
|
:vector => Vector.new(30, 315),
|
293
300
|
:size => DEFAULT_OBJECT_SIZE * 2, #Size.
|
294
301
|
:tags => ["food"]
|
@@ -300,61 +307,11 @@ class Demo < Wx::App
|
|
300
307
|
end
|
301
308
|
|
302
309
|
|
303
|
-
#A Creature that changes the colors of other objects.
|
304
|
-
class Morpher < Creature
|
305
|
-
#Changes an object's color.
|
306
|
-
def initialize(*arguments)
|
307
|
-
super
|
308
|
-
morph = Behavior.new
|
309
|
-
#Shift the target's color to match the creature's.
|
310
|
-
morph.actions << BlendAction.new(self.color)
|
311
|
-
#Act only on nearby targets.
|
312
|
-
morph.conditions << ProximityCondition.new(50)
|
313
|
-
@behaviors << morph
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
#Demonstrates changing object colors.
|
318
|
-
def test_change_color
|
319
|
-
|
320
|
-
populate(@environment)
|
321
|
-
|
322
|
-
say("Creatures can influence any attribute of their target, such as its color.")
|
323
|
-
say("This demo includes a Morpher class, which is a type of Creature.")
|
324
|
-
say("Morphers are created with a single behavior, which shifts the color of any nearby target to match the Morpher's color.")
|
325
|
-
|
326
|
-
say("Let's place a red Morpher...")
|
327
|
-
@environment.objects << Morpher.new(
|
328
|
-
:location => Location.new(0, 100),
|
329
|
-
:color => Color.new(1, 0, 0),
|
330
|
-
:vector => Vector.new(100, 0),
|
331
|
-
:size => DEFAULT_OBJECT_SIZE
|
332
|
-
)
|
333
|
-
say("a green one...")
|
334
|
-
@environment.objects << Morpher.new(
|
335
|
-
:location => Location.new(0, 150),
|
336
|
-
:color => Color.new(0, 1, 0),
|
337
|
-
:vector => Vector.new(200, 0),
|
338
|
-
:size => DEFAULT_OBJECT_SIZE
|
339
|
-
)
|
340
|
-
say("and a blue one...")
|
341
|
-
@environment.objects << Morpher.new(
|
342
|
-
:location => Location.new(0, 200),
|
343
|
-
:color => Color.new(0, 0, 1),
|
344
|
-
:vector => Vector.new(300, 0),
|
345
|
-
:size => DEFAULT_OBJECT_SIZE
|
346
|
-
)
|
347
|
-
|
348
|
-
say("...and see what they do.")
|
349
|
-
|
350
|
-
end
|
351
|
-
|
352
|
-
|
353
310
|
#Demonstrates altering object speed.
|
354
311
|
def test_accelerate
|
355
312
|
|
356
313
|
say("Here are some Creatures, just plodding along.")
|
357
|
-
|
314
|
+
@environment.objects = generate_creatures
|
358
315
|
|
359
316
|
say("We're going to have them pick up the pace.")
|
360
317
|
say("We add a Behavior with an AccelerateAction to all the creatures.")
|
@@ -371,7 +328,7 @@ class Demo < Wx::App
|
|
371
328
|
#Demonstrates altering object vectors.
|
372
329
|
def test_turn
|
373
330
|
|
374
|
-
|
331
|
+
@environment.objects = generate_creatures
|
375
332
|
|
376
333
|
say("This time we'll use the TurnAction class.")
|
377
334
|
say("We tell each creature it should turn 90 degrees.")
|
@@ -387,7 +344,7 @@ class Demo < Wx::App
|
|
387
344
|
#Demonstrates adding vectors.
|
388
345
|
def test_approach
|
389
346
|
|
390
|
-
|
347
|
+
@environment.objects = generate_creatures
|
391
348
|
|
392
349
|
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.")
|
393
350
|
say("Our ApproachAction adds the vector the creature WANTS to follow to the vector it's ACTUALLY following.")
|
@@ -418,12 +375,12 @@ class Demo < Wx::App
|
|
418
375
|
#Demonstrates adding vectors.
|
419
376
|
def test_flee
|
420
377
|
|
421
|
-
|
378
|
+
@environment.objects = generate_creatures
|
422
379
|
|
423
380
|
say("A FleeAction is just like an ApproachAction, but we head in the OPPOSITE direction.")
|
424
381
|
@environment.objects.each do |creature|
|
425
382
|
flee = Behavior.new
|
426
|
-
flee.actions << FleeAction.new(
|
383
|
+
flee.actions << FleeAction.new(300)
|
427
384
|
flee.conditions << TagCondition.new("predator")
|
428
385
|
creature.behaviors << flee
|
429
386
|
end
|
@@ -442,13 +399,13 @@ class Demo < Wx::App
|
|
442
399
|
#Demonstrates keeping a reference to an Environment so a Creature can alter it.
|
443
400
|
def test_eat
|
444
401
|
|
445
|
-
|
402
|
+
@environment.objects = generate_creatures
|
446
403
|
|
447
404
|
say("Most games are all about destruction, but there hasn't been much so far.")
|
448
405
|
say("Let's create a creature that causes some havoc.")
|
449
406
|
predator = Creature.new(
|
450
407
|
:location => Location.new(0, 150),
|
451
|
-
:color => Color.
|
408
|
+
:color => Color.green,
|
452
409
|
:vector => Vector.new(200, 0),
|
453
410
|
:size => DEFAULT_OBJECT_SIZE * 5
|
454
411
|
)
|
@@ -473,6 +430,116 @@ class Demo < Wx::App
|
|
473
430
|
say("And - chomp!")
|
474
431
|
|
475
432
|
end
|
433
|
+
|
434
|
+
|
435
|
+
#Demonstrates ElapsedTimeCondition.
|
436
|
+
def test_explode
|
437
|
+
|
438
|
+
say("Let's have some fireworks.")
|
439
|
+
say("First we'll create 'stars' to load into the rocket.")
|
440
|
+
star = Creature.new(:color => Color.red)
|
441
|
+
say("A BlendAction will make them fade to black over time.")
|
442
|
+
star.behaviors << Behavior.new(:actions => [BlendAction.new(0.5, Color.black)])
|
443
|
+
say("An ExplodeAction copies prototype objects into the environment.")
|
444
|
+
action = ExplodeAction.new(@environment)
|
445
|
+
say("We'll make copies of our star with random vectors.")
|
446
|
+
say("We'll load these copies into our ExplodeAction.")
|
447
|
+
25.times do |i|
|
448
|
+
copy = star.copy
|
449
|
+
copy.vector = Vector.new(rand(50), rand(360))
|
450
|
+
action.prototypes << copy
|
451
|
+
end
|
452
|
+
|
453
|
+
say("It's just not smart to build fireworks without a fuse.")
|
454
|
+
say("An ElapsedTimeCondition should do nicely.")
|
455
|
+
condition = ElapsedTimeCondition.new
|
456
|
+
say("This will be a short fuse, though, say 2 seconds.")
|
457
|
+
condition.interval = 2
|
458
|
+
|
459
|
+
say("We set up a Behavior with the Action and Condition...")
|
460
|
+
explode = Behavior.new(:actions => [action], :conditions => [condition])
|
461
|
+
say("Add the behavior to rockets aimed at the sky...")
|
462
|
+
rocket = Creature.new(
|
463
|
+
:behaviors => [explode],
|
464
|
+
:vector => Vector.new(100, 260),
|
465
|
+
:location => Location.new(WIDTH / 2, HEIGHT),
|
466
|
+
:size => 50
|
467
|
+
)
|
468
|
+
rocket2 = rocket.copy
|
469
|
+
rocket2.vector = Vector.new(130, 275)
|
470
|
+
say("And light those suckers.")
|
471
|
+
@environment.objects << rocket << rocket2
|
472
|
+
@environment << Gravity.new(30)
|
473
|
+
|
474
|
+
end
|
475
|
+
|
476
|
+
|
477
|
+
#Demonstrates ShootAction.
|
478
|
+
def test_shoot
|
479
|
+
|
480
|
+
say("I'm a big fan of shoot-em-up games.")
|
481
|
+
say("The ability to make them easily is a major goal of Zyps.")
|
482
|
+
|
483
|
+
say("Every shooter needs someone to play it, so let's make a player.")
|
484
|
+
say("We give him a 'player' tag so enemies can target him.")
|
485
|
+
player = Creature.new(
|
486
|
+
:location => Location.new(WIDTH / 2, HEIGHT / 2),
|
487
|
+
:behaviors => [
|
488
|
+
Behavior.new(
|
489
|
+
:actions => [FleeAction.new(100)],
|
490
|
+
:conditions => [ProximityCondition.new(30)]
|
491
|
+
)
|
492
|
+
],
|
493
|
+
:size => DEFAULT_OBJECT_SIZE,
|
494
|
+
:vector => Vector.new(10, 0),
|
495
|
+
:tags => ['player']
|
496
|
+
)
|
497
|
+
|
498
|
+
say("Shooters need lots of bullets, of course.")
|
499
|
+
say("A bullet doesn't need to be smart, but it should destroy the player when he gets too close.")
|
500
|
+
bullet = Creature.new(
|
501
|
+
:behaviors => [
|
502
|
+
Behavior.new(
|
503
|
+
:actions => [DestroyAction.new(@environment)],
|
504
|
+
:conditions => [
|
505
|
+
ProximityCondition.new(7),
|
506
|
+
TagCondition.new('player')
|
507
|
+
]
|
508
|
+
)
|
509
|
+
],
|
510
|
+
:vector => Vector.new(100, 0)
|
511
|
+
)
|
512
|
+
|
513
|
+
say("We're going to fire groups of 3 bullets at once.")
|
514
|
+
bullets = [bullet, bullet.copy, bullet.copy]
|
515
|
+
say("There's no point firing all 3 at the same spot...")
|
516
|
+
say("We'll vary their angles a bit.")
|
517
|
+
bullets.first.vector.pitch -= 10
|
518
|
+
bullets.last.vector.pitch += 10
|
519
|
+
|
520
|
+
say("And lastly, we need an enemy to fire the bullets at the player.")
|
521
|
+
say("We'll give him a ShootAction, and assign it our group of bullets.")
|
522
|
+
say("The action copies the bullets into the Environment and aims them at its target.")
|
523
|
+
say("An ElapsedTimeCondition makes it fire every 0.5 seconds.")
|
524
|
+
enemy = Creature.new(
|
525
|
+
:vector => Vector.new(30, 45),
|
526
|
+
:behaviors => [
|
527
|
+
Behavior.new(
|
528
|
+
:actions => [ShootAction.new(@environment, [bullets])],
|
529
|
+
:conditions => [
|
530
|
+
ElapsedTimeCondition.new(0.5),
|
531
|
+
TagCondition.new('player'),
|
532
|
+
]
|
533
|
+
)
|
534
|
+
],
|
535
|
+
:color => Color.green,
|
536
|
+
:size => DEFAULT_OBJECT_SIZE
|
537
|
+
)
|
538
|
+
|
539
|
+
say("Game on!")
|
540
|
+
@environment.objects << player << enemy
|
541
|
+
|
542
|
+
end
|
476
543
|
|
477
544
|
|
478
545
|
#End the demos.
|
data/lib/zyps.rb
CHANGED
@@ -111,6 +111,19 @@ class Environment
|
|
111
111
|
|
112
112
|
end
|
113
113
|
|
114
|
+
#Overloads the << operator to put the new item into the correct list.
|
115
|
+
#This allows one to simply call env << <valid_object> instead of
|
116
|
+
#having to choose a specific list, such as objects or environmental factors.
|
117
|
+
def <<(item)
|
118
|
+
if(item.kind_of? Zyps::GameObject)
|
119
|
+
self.objects << item
|
120
|
+
elsif(item.kind_of? Zyps::EnvironmentalFactor)
|
121
|
+
self.environmental_factors << item
|
122
|
+
else
|
123
|
+
raise "Invalid item: #{item.class}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
114
127
|
end
|
115
128
|
|
116
129
|
|
@@ -164,7 +177,7 @@ class GameObject
|
|
164
177
|
copy.location = @location.copy
|
165
178
|
copy.tags = @tags.clone
|
166
179
|
copy.identifier = generate_identifier
|
167
|
-
copy.name = @name ? "Copy of " + @name : nil
|
180
|
+
copy.name = @name ? "Copy of " + @name.to_s : nil
|
168
181
|
copy
|
169
182
|
end
|
170
183
|
|
@@ -187,6 +200,21 @@ class GameObject
|
|
187
200
|
@identifier = value
|
188
201
|
end
|
189
202
|
|
203
|
+
#Overloads the << operator to put the new item into the correct
|
204
|
+
#list or assign it to the correct attribute.
|
205
|
+
#Assignment is done based on item's class or a parent class of item.
|
206
|
+
def <<(item)
|
207
|
+
if item.kind_of? Zyps::Location:
|
208
|
+
self.location = item
|
209
|
+
elsif item.kind_of? Zyps::Color:
|
210
|
+
self.color = item
|
211
|
+
elsif item.kind_of? Zyps::Vector:
|
212
|
+
self.vector = item
|
213
|
+
else
|
214
|
+
raise "Invalid item: #{item.class}"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
190
218
|
private
|
191
219
|
|
192
220
|
#Make a unique GameObject identifier.
|
@@ -236,6 +264,20 @@ class Creature < GameObject
|
|
236
264
|
behaviors.each {|behavior| behavior.perform(self, targets)}
|
237
265
|
end
|
238
266
|
|
267
|
+
#See GameObject#<<.
|
268
|
+
#Adds ability to stream in behaviors as well.
|
269
|
+
def <<(item)
|
270
|
+
begin
|
271
|
+
super
|
272
|
+
rescue
|
273
|
+
if(item.kind_of? Zyps::Behavior)
|
274
|
+
self.behaviors << item
|
275
|
+
else
|
276
|
+
raise "invalid item: #{item.class}"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
239
281
|
end
|
240
282
|
|
241
283
|
|
@@ -434,6 +476,19 @@ class Color
|
|
434
476
|
)
|
435
477
|
end
|
436
478
|
|
479
|
+
#Pre-defined color value.
|
480
|
+
def self.red; Color.new(1, 0, 0); end
|
481
|
+
def self.orange; Color.new(1, 0.63, 0); end
|
482
|
+
def self.yellow; Color.new(1, 1, 0); end
|
483
|
+
def self.green; Color.new(0, 1, 0); end
|
484
|
+
def self.blue; Color.new(0, 0, 1); end
|
485
|
+
def self.indigo; Color.new(0.4, 0, 1); end
|
486
|
+
def self.violet; Color.new(0.9, 0.5, 0.9); end
|
487
|
+
def self.white; Color.new(1, 1, 1); end
|
488
|
+
def self.black; Color.new(0, 0, 0); end
|
489
|
+
def self.grey; Color.new(0.5, 0.5, 0.5); end
|
490
|
+
|
491
|
+
|
437
492
|
end
|
438
493
|
|
439
494
|
|
@@ -451,6 +506,9 @@ class Location
|
|
451
506
|
#Make a deep copy.
|
452
507
|
def copy; self.clone; end
|
453
508
|
|
509
|
+
#True if x and y coordinates are the same.
|
510
|
+
def ==(other); self.x == other.x and self.y == other.y; end
|
511
|
+
|
454
512
|
end
|
455
513
|
|
456
514
|
|
@@ -478,7 +536,7 @@ class Vector
|
|
478
536
|
#Store as radians internally.
|
479
537
|
@pitch = Utility.to_radians(value)
|
480
538
|
end
|
481
|
-
|
539
|
+
|
482
540
|
#The X component.
|
483
541
|
def x; @speed.to_f * Math.cos(@pitch); end
|
484
542
|
def x=(value)
|
@@ -503,6 +561,9 @@ class Vector
|
|
503
561
|
Vector.new(new_length, new_angle)
|
504
562
|
end
|
505
563
|
|
564
|
+
#True if x and y coordinates are the same.
|
565
|
+
def ==(other); self.speed == other.speed and self.pitch == other.pitch; end
|
566
|
+
|
506
567
|
end
|
507
568
|
|
508
569
|
|
@@ -522,13 +583,20 @@ class Clock
|
|
522
583
|
time = Time.new.to_f
|
523
584
|
elapsed_time = time - @last_check_time
|
524
585
|
@last_check_time = time
|
525
|
-
elapsed_time
|
586
|
+
elapsed_time * @@speed
|
526
587
|
end
|
527
588
|
|
528
589
|
def reset_elapsed_time
|
529
590
|
@last_check_time = Time.new.to_f
|
530
591
|
end
|
531
592
|
|
593
|
+
#Speed at which all Clocks are operating.
|
594
|
+
@@speed = 1.0
|
595
|
+
def Clock.speed; @@speed; end
|
596
|
+
#Set speed at which all Clocks will operate.
|
597
|
+
#1 is real-time, 2 is double speed, 0 is paused.
|
598
|
+
def Clock.speed=(value); @@speed = value; end
|
599
|
+
|
532
600
|
end
|
533
601
|
|
534
602
|
|