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/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 1000:
155
+ when 700:
160
156
  @environment.objects = []
161
157
  test_turn
162
158
  say "-" * 30
163
- when 1200:
159
+ when 900:
164
160
  @environment.objects = []
165
161
  test_approach
166
162
  say "-" * 30
167
- when 1400:
163
+ when 1100:
168
164
  @environment.objects = []
169
165
  test_flee
170
166
  say "-" * 30
171
- when 1600:
167
+ when 1300:
172
168
  @environment.objects = []
173
169
  test_eat
174
170
  say "-" * 30
175
- when 1800:
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 populate(environment, count = 50)
184
- @log.debug "Add #{count} creatures to #{environment}."
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
- environment.objects << Creature.new(
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
- populate(@environment)
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
- populate(@environment)
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.new(1, 1, 1),
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
- populate(@environment)
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
- populate(@environment)
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
- populate(@environment, 50)
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
- populate(@environment, 50)
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(360, creature.vector)
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
- populate(@environment)
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.new(0, 1, 0),
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