chingu 0.7.0 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/History.txt +1 -1
  2. data/README.rdoc +110 -49
  3. data/benchmarks/game_objects_benchmark.rb +50 -0
  4. data/chingu.gemspec +24 -12
  5. data/examples/example10_traits_retrofy.rb +6 -4
  6. data/examples/example11_animation.rb +14 -23
  7. data/examples/example12_trait_timer.rb +1 -1
  8. data/examples/example13_high_scores.rb +1 -1
  9. data/examples/example14_bounding_box_circle.rb +6 -10
  10. data/examples/example15_trait_timer2.rb +1 -1
  11. data/examples/example16_online_high_scores.rb +1 -1
  12. data/examples/example17_gosu_tutorial.rb +4 -4
  13. data/examples/example18_animation_trait.rb +98 -0
  14. data/examples/example19_edit_viewport.rb +223 -0
  15. data/examples/example19_game_objects.yml +1591 -0
  16. data/examples/example20_trait_inheritence_test.rb +58 -0
  17. data/examples/example3_parallax.rb +1 -1
  18. data/examples/example4_gamestates.rb +1 -1
  19. data/examples/example7_gfx_helpers.rb +14 -9
  20. data/examples/example8_traits.rb +4 -4
  21. data/examples/example9_collision_detection.rb +1 -1
  22. data/examples/game1.rb +33 -38
  23. data/examples/game_of_life.rb +291 -0
  24. data/examples/media/droid_11x15.bmp +0 -0
  25. data/examples/media/droid_11x15.gal +0 -0
  26. data/examples/media/heli.bmp +0 -0
  27. data/examples/media/heli.gal +0 -0
  28. data/examples/media/star_25x25_default.png +0 -0
  29. data/examples/media/star_25x25_explode.gal +0 -0
  30. data/examples/media/star_25x25_explode.png +0 -0
  31. data/examples/media/stone_wall.bmp +0 -0
  32. data/lib/chingu.rb +1 -1
  33. data/lib/chingu/animation.rb +78 -9
  34. data/lib/chingu/basic_game_object.rb +16 -8
  35. data/lib/chingu/game_object.rb +36 -7
  36. data/lib/chingu/game_object_list.rb +20 -3
  37. data/lib/chingu/game_state.rb +8 -7
  38. data/lib/chingu/game_states/edit.rb +177 -90
  39. data/lib/chingu/helpers/class_inheritable_accessor.rb +12 -5
  40. data/lib/chingu/helpers/game_object.rb +45 -4
  41. data/lib/chingu/helpers/gfx.rb +150 -172
  42. data/lib/chingu/helpers/input_client.rb +7 -0
  43. data/lib/chingu/inflector.rb +16 -2
  44. data/lib/chingu/traits/animation.rb +84 -0
  45. data/lib/chingu/traits/bounding_box.rb +16 -3
  46. data/lib/chingu/traits/bounding_circle.rb +18 -4
  47. data/lib/chingu/traits/collision_detection.rb +10 -1
  48. data/lib/chingu/traits/velocity.rb +26 -3
  49. data/lib/chingu/traits/viewport.rb +10 -9
  50. data/lib/chingu/viewport.rb +103 -22
  51. data/lib/chingu/window.rb +8 -2
  52. metadata +46 -16
  53. data/examples/example18_viewport.rb +0 -173
  54. data/examples/media/city1.csv +0 -2
  55. data/examples/media/plane.csv +0 -2
  56. data/examples/media/saucer.csv +0 -4
  57. data/examples/media/stickfigure.bmp +0 -0
  58. data/examples/media/stickfigure.png +0 -0
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require File.join(File.dirname($0), "..", "lib", "chingu")
4
+ include Gosu
5
+ include Chingu
6
+
7
+ #
8
+ # This is more of a technical test to sort out the class inheritable accessor ..
9
+ # ..more then it's a fun-to-watch demo.
10
+ #
11
+ class Game < Chingu::Window
12
+ def initialize
13
+ super
14
+ self.input = { :escape => :exit }
15
+
16
+ star = SpinningStar.create(:x => 400, :y => 100)
17
+ star2 = MovingStar.create(:x => 10, :y => 200)
18
+
19
+ p star.class.superclass
20
+ p "=== Should only have collision detection"
21
+ p star.class
22
+ p star.class.trait_options
23
+ p "=== Should have collision detection and velocity"
24
+ p star2.class
25
+ p star2.class.trait_options
26
+ end
27
+ end
28
+
29
+
30
+ class Star < GameObject
31
+ trait :collision_detection
32
+
33
+ def initialize(options={})
34
+ super
35
+
36
+ @animation = Chingu::Animation.new(:file => "Star.png", :size => 25)
37
+ @image = @animation.next
38
+ end
39
+
40
+ end
41
+
42
+ class MovingStar < Star
43
+ trait :velocity
44
+
45
+ def initialize(options={})
46
+ super
47
+ self.velocity_x = 1
48
+ end
49
+ end
50
+
51
+ class SpinningStar < Star
52
+ def update
53
+ @image = @animation.next
54
+ end
55
+ end
56
+
57
+
58
+ Game.new.show
@@ -9,7 +9,7 @@ include Gosu
9
9
  #
10
10
  class Game < Chingu::Window
11
11
  def initialize
12
- super(600,200)
12
+ super(600,200)
13
13
  self.caption = "Chingu::Parallax example. Scroll with left/right arrows. Space for new parallax example!"
14
14
  switch_game_state(Wood)
15
15
  end
@@ -35,7 +35,7 @@ class Game < Chingu::Window
35
35
  push_game_state(Intro)
36
36
 
37
37
  # Yes you can do crazy things like this :)
38
- self.input = { :left_mouse_button => lambda{Chingu::Text.create(:text => "Woff!")}, :esc => :exit}
38
+ self.input = { :left_mouse_button => lambda{Chingu::Text.create(:text => "Woof!")}, :esc => :exit}
39
39
  end
40
40
  end
41
41
 
@@ -17,6 +17,7 @@ class Game < Chingu::Window
17
17
  push_game_state(FillRect)
18
18
  push_game_state(FillGradient)
19
19
  push_game_state(FillGradientRect)
20
+ push_game_state(FillGradientMultipleColors)
20
21
  push_game_state(Particles)
21
22
  end
22
23
 
@@ -25,24 +26,17 @@ class Game < Chingu::Window
25
26
  end
26
27
  end
27
28
 
28
-
29
29
  class Fill < Chingu::GameState
30
- def setup
31
- @white = Color.new(255,255,255,255)
32
- end
33
30
  def draw
34
31
  $window.caption = "fill (space to continue)"
35
- fill(@white)
32
+ fill(Color::RED)
36
33
  end
37
34
  end
38
35
 
39
36
  class FillRect < Chingu::GameState
40
- def setup
41
- @white = Color.new(255,255,255,255)
42
- end
43
37
  def draw
44
38
  $window.caption = "fill_rect (space to continue)"
45
- fill_rect([10,10,100,100], @white)
39
+ fill_rect([10,10,100,100], Color::WHITE)
46
40
  end
47
41
  end
48
42
 
@@ -58,6 +52,17 @@ class FillGradient < Chingu::GameState
58
52
  end
59
53
  end
60
54
 
55
+ class FillGradientMultipleColors < Chingu::GameState
56
+ def setup
57
+ @colors = [ 0xffff0000, 0xff00ff00, 0xff0000ff ].map { |c| Color.new(c) }
58
+ end
59
+
60
+ def draw
61
+ $window.caption = "fill_gradient with more than two colors (space to continue)"
62
+ fill_gradient(:colors => @colors, :orientation => :horizontal)
63
+ end
64
+ end
65
+
61
66
  class FillGradientRect < Chingu::GameState
62
67
  def setup
63
68
  @color1 = Color.new(0xFFFFEA02)
@@ -19,11 +19,10 @@ class Game < Chingu::Window
19
19
  end
20
20
 
21
21
  class Plasma < Chingu::GameObject
22
- has_traits :velocity
22
+ traits :velocity
23
23
  attr_accessor :fade_rate
24
24
 
25
- def initialize(options)
26
- super
25
+ def setup
27
26
  @image = Image["particle.png"]
28
27
  @mode = :additive
29
28
 
@@ -59,10 +58,11 @@ class Particles < Chingu::GameState
59
58
  # first optimization: 490 particles, 47 fps (350 @ 60)
60
59
  # optimized GameObject if/elsif: 490 particles, 50 fps
61
60
  #
62
- Plasma.create(:x => 0, :y => 0 + rand(5), :color => Color.new(0xFF86EFFF), :velocity_x => 10)
61
+ Plasma.create(:x => 0, :y => 0 + rand(5), :color => Color::RED.dup, :velocity_x => 10)
63
62
  Plasma.create(:x => 0, :y => 50 + rand(5), :color => Color.new(0xFF86EFFF), :velocity_x => 14)
64
63
  Plasma.create(:x => 0, :y => 100 + rand(5), :color => Color.new(0xFF86EFFF), :velocity_x => 7)
65
64
  Plasma.create(:x => 0, :y => 200 + rand(5), :color => Color.new(0xFF86EFFF), :velocity_x => 6)
65
+ #p pl.mode
66
66
 
67
67
  Plasma.all.each do |particle|
68
68
  #
@@ -19,7 +19,7 @@ class Game < Chingu::Window
19
19
  end
20
20
 
21
21
  class FireCube < Chingu::GameObject
22
- has_traits :velocity, :collision_detection
22
+ traits :velocity, :collision_detection
23
23
  attr_accessor :color, :radius
24
24
 
25
25
  def initialize(options)
@@ -3,25 +3,25 @@
3
3
  #
4
4
  # A "full" simple game in Chingu, using GameState, GameObject, Paralaxx, has_traits etc
5
5
  #
6
- # TODO: clean up code as Chingu moves along :). Comments.
6
+ # TODO: clean up code as Chingu moves along :). Comments. Get it working ;).
7
7
  #
8
8
  #
9
9
  require 'rubygems'
10
10
  require File.join(File.dirname($0), "..", "lib", "chingu")
11
-
12
11
  require 'texplay' # adds Image#get_pixel
13
- require 'opengl' # adds raw gl stuff so Image#retrofy works (in some setups this seems to be 'gl')
12
+ #require 'opengl' # adds raw gl stuff so Image#retrofy works (in some setups this seems to be 'gl')
14
13
 
15
14
  include Gosu
16
15
  include Chingu
17
16
 
18
17
  class Game < Chingu::Window
19
- attr_reader :factor
18
+ #attr_reader :factor
20
19
 
21
20
  def initialize
22
- super(1000,800,false)
21
+ super(1000,400,false)
23
22
  self.input = { :escape => :exit }
24
- @factor = 2
23
+ self.factor = 1
24
+ Gosu::enable_undocumented_retrofication
25
25
  switch_game_state(Level)
26
26
  end
27
27
  end
@@ -37,8 +37,12 @@ class Level < Chingu::GameState
37
37
  super
38
38
 
39
39
  @parallax = Parallax.create(:rotation_center => :top_left)
40
- @parallax << { :image => Image["city2.png"].retrofy, :damping => 2, :factor => $window.factor }
41
- @parallax << { :image => Image["city1.png"].retrofy, :damping => 1, :factor => $window.factor }
40
+ #@parallax = Parallax.create(:rotation_center => :center)
41
+ @parallax << { :image => "city2.png", :damping => 2}#, :factor => $window.factor }
42
+ @parallax << { :image => "city1.png", :damping => 1}#, :factor => $window.factor }
43
+ #@parallax.x = $window.width / 2
44
+ #@parallax.y = $window.height / 2
45
+
42
46
  @player = Player.create(:x => 30, :y => 10)
43
47
 
44
48
  @bg1 = Color.new(0xFFCE28FF)
@@ -72,7 +76,8 @@ class Level < Chingu::GameState
72
76
  #return false if pixel.nil?
73
77
  #return
74
78
 
75
- @parallax.layers.last.get_pixel(x/$window.factor, y/$window.factor)[3] != 0
79
+ @parallax.layers.last.get_pixel(x * $window.factor, y * $window.factor)[3] != 0
80
+ #@parallax.layers.last.get_pixel(x, y)[3] != 0
76
81
  rescue
77
82
  puts "Error in get_pixel(#{x}, #{y})"
78
83
  end
@@ -91,7 +96,7 @@ class Level < Chingu::GameState
91
96
  Bullet.all.select { |o| solid_pixel_at?(o.x, o.y)}.each { |o| o.die }
92
97
 
93
98
  # Collide player with terrain
94
- push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
99
+ #push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
95
100
 
96
101
  # Collide player with enemies and enemy bullets
97
102
  @player.each_bounding_circle_collision(Enemy) do |player, enemy|
@@ -106,7 +111,6 @@ class Level < Chingu::GameState
106
111
  end
107
112
  end
108
113
 
109
-
110
114
  @timer = @timer * 0.9999
111
115
  @total_ticks += 1
112
116
  if @total_ticks > @timer
@@ -130,14 +134,12 @@ end
130
134
  #
131
135
  class Player < GameObject
132
136
  has_traits :velocity, :collision_detection, :timer
133
- has_trait :bounding_circle, :scale => 0.50, :debug => true
134
-
137
+ has_trait :bounding_circle, :scale => 0.50, :debug => true
135
138
  attr_accessor :score
136
139
 
137
- def initialize(options = {})
138
- super
139
- @image = Image["plane.png"].retrofy
140
- self.factor = $window.factor
140
+ def setup
141
+ @image = Image["plane.png"]
142
+ #self.factor = $window.factor
141
143
 
142
144
  self.input = {
143
145
  :holding_left => :left,
@@ -150,7 +152,7 @@ class Player < GameObject
150
152
  @score = 0
151
153
  @cooling_down = false
152
154
  end
153
-
155
+
154
156
  def up
155
157
  self.velocity_y = -@max_velocity
156
158
  end
@@ -191,10 +193,9 @@ class Bullet < GameObject
191
193
  has_traits :timer, :collision_detection, :velocity
192
194
  attr_reader :status, :radius
193
195
 
194
- def initialize(options)
195
- super
196
- @image = Image["bullet.png"].retrofy
197
- self.factor = $window.factor
196
+ def setup
197
+ @image = Image["bullet.png"]
198
+ #self.factor = $window.factor
198
199
  self.velocity_x = 10
199
200
  @status = :default
200
201
  @radius = 3
@@ -217,9 +218,8 @@ end
217
218
  # ENEMY BULLET
218
219
  #
219
220
  class EnemyBullet < Bullet
220
- def initialize(options)
221
- super
222
- @image = Image["enemy_bullet.png"].retrofy
221
+ def setup
222
+ @image = Image["enemy_bullet.png"]
223
223
  self.velocity_x = -3
224
224
  end
225
225
  end
@@ -238,7 +238,7 @@ class Explosion < GameObject
238
238
  @image = @@image.dup if @image.nil?
239
239
 
240
240
  self.rotation_center = :center
241
- self.factor = options[:factor] ? options[:factor] : $window.factor
241
+ #self.factor = options[:factor] ? options[:factor] : $window.factor
242
242
  during(100) { self.alpha -= 30}.then { destroy }
243
243
  end
244
244
 
@@ -254,15 +254,15 @@ end
254
254
  class Shrapnel < GameObject
255
255
  has_traits :timer, :effect, :velocity
256
256
 
257
- def initialize(options)
258
- super
259
-
257
+ #def initialize(options)
258
+ # super
259
+ def setup
260
260
  self.rotation_rate = 1 + rand(10)
261
261
  self.velocity_x = 4 - rand(8)
262
262
  self.velocity_y = 4 - rand(10)
263
263
  self.acceleration_y = 0.2 # gravity = downards acceleration
264
264
  self.rotation_center = :center
265
- self.factor = $window.factor
265
+ #self.factor = $window.factor
266
266
  @status = :default
267
267
  end
268
268
 
@@ -292,16 +292,15 @@ class Enemy < GameObject
292
292
  has_traits :collision_detection, :timer
293
293
  attr_reader :radius
294
294
 
295
- def initialize(options)
296
- super
295
+ def setup
297
296
  @velocity = options[:velocity] || 2
298
297
  @health = options[:health] || 100
299
298
 
300
- @anim = Animation.new(:file => "media/saucer.png", :size => [32,13], :delay => 100).retrofy
299
+ @anim = Animation.new(:file => "media/saucer.png", :size => [32,13], :delay => 100)
301
300
  # @anim.retrofy
302
301
  @image = @anim.first
303
302
 
304
- self.factor = $window.factor
303
+ #self.factor = $window.factor
305
304
  @radius = 5
306
305
  @black = Color.new(0xFF000000)
307
306
  @status == :default
@@ -410,7 +409,3 @@ end
410
409
 
411
410
 
412
411
  Game.new.show
413
-
414
-
415
-
416
-
@@ -0,0 +1,291 @@
1
+ #
2
+ # Conway's game of life in Gosu/Chingu
3
+ # http://toastymofo.blogspot.com/2010/06/conways-game-of-life-in-ruby-gosu.html
4
+ #
5
+ # Developed by r.kachowski ( http://www.toastymofo.net/ )
6
+ # Additions by ippa ( http://ippa.se/gaming )
7
+ #
8
+ require 'chingu'
9
+ require 'gosu'
10
+
11
+ class Main < Chingu::Window
12
+ def initialize
13
+ super(640,480,false)
14
+ self.input={:esc=>:exit}
15
+ push_game_state(GameOfLife)
16
+ end
17
+ def draw
18
+ super
19
+ fill_rect([0,0,640,480], 0xffffffff, -2)
20
+ end
21
+ end
22
+
23
+ class GameOfLife < Chingu::GameState
24
+ CELL_SIZE = 4
25
+ @@tick =0
26
+ def initialize
27
+ super
28
+ @grid = generate_grid
29
+
30
+ self.input={ :left_mouse_button => :start_painting,
31
+ :released_left_mouse_button => :stop_painting,
32
+ :right_mouse_button => :start_erasing,
33
+ :releasedright_mouse_button => :stop_erasing,
34
+ :z => :reset,
35
+ :n => :update_grid,
36
+ :space => :toggle_running,
37
+ :left_arrow => :prev_pattern,
38
+ :right_arrow => :next_pattern
39
+ }
40
+
41
+ @pattern = :pixel
42
+ @pattern_nr = 0
43
+ @painting = false
44
+ @erasing = false
45
+ @running = false
46
+
47
+ @pattern_info = Chingu::Text.create(:x => 1, :y => 1, :size => 16, :color => Gosu::Color::BLACK)
48
+ update_pattern_info
49
+ end
50
+
51
+ def update_pattern_info
52
+ @pattern_info.text = "Current pattern: #{@pattern}. Change patterns with left/right arrow keys."
53
+ end
54
+
55
+ def prev_pattern
56
+ @pattern_nr -= 1
57
+ @pattern_nr = PATTERNS.keys.size-1 if @pattern_nr < 0
58
+ @pattern = PATTERNS.keys[@pattern_nr]
59
+ update_pattern_info
60
+ end
61
+
62
+ def next_pattern
63
+ @pattern_nr += 1
64
+ @pattern_nr = 0 if @pattern_nr >= PATTERNS.keys.size
65
+ @pattern = PATTERNS.keys[@pattern_nr]
66
+ update_pattern_info
67
+ end
68
+
69
+ def draw_pattern_at_mouse(pattern = :pixel, to_grid = false)
70
+ start_x = ($window.mouse_x/CELL_SIZE).floor
71
+ y = ($window.mouse_y/CELL_SIZE).floor - 1
72
+
73
+ PATTERNS[pattern].each_line do |line|
74
+ x = start_x
75
+ line.each_char do |char|
76
+ @grid[x][y] = true if char == "o" && to_grid
77
+ draw_cell(x, y) if char == "o"
78
+ x += 1
79
+ end
80
+
81
+ y += 1
82
+ end
83
+ end
84
+
85
+ def update
86
+ super
87
+
88
+ if @painting
89
+ draw_pattern_at_mouse(@pattern, true)
90
+ @painting = false if @running # Only put out pattern Once if game is running
91
+ else
92
+ draw_pattern_at_mouse(@pattern)
93
+ end
94
+
95
+ update_grid if @running
96
+
97
+ $window.caption = "Conway Generation #{@@tick}. Start/Stop with 'Space'. Run 1 generation with 'N'. Reset with 'Z'."
98
+ end
99
+
100
+ def draw
101
+ super
102
+ draw_grid
103
+ end
104
+
105
+ private
106
+
107
+ def generate_grid
108
+ width = $window.width/CELL_SIZE
109
+ height = $window.height/CELL_SIZE
110
+
111
+ grid = Array.new(width)
112
+ col = Array.new(height)
113
+ col.map!{false}
114
+ grid.map!{Array.new(col)}
115
+ grid
116
+ end
117
+
118
+ def draw_grid
119
+ @grid.each_with_index do |a,x|
120
+ a.each_with_index do |c,y|
121
+ if c === true
122
+ $window.fill_rect([x*CELL_SIZE,y*CELL_SIZE,CELL_SIZE,CELL_SIZE],0xff000000,0)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ def reset
129
+ @grid = generate_grid
130
+ @@tick = 0
131
+ @running = false
132
+ end
133
+
134
+ def update_grid
135
+ @new_grid = Marshal.load(Marshal.dump(@grid))
136
+
137
+ @grid.each_with_index do |a,x|
138
+ a.each_with_index do |c,y|
139
+ minus_x =x-1
140
+ minus_y = y-1
141
+ plus_x = x+1
142
+ plus_y = y+1
143
+ minus_x = @grid.length-1 if minus_x <0
144
+ minus_y = a.length-1 if minus_y <0
145
+ plus_y = 0 if plus_y >= a.length
146
+ plus_x = 0 if plus_x >= @grid.length
147
+
148
+ live_neighbours = 0
149
+
150
+ @grid[minus_x][y] == true ? live_neighbours+=1 : nil
151
+ @grid[plus_x][y] == true ? live_neighbours+=1 : nil
152
+ @grid[x][minus_y] == true ? live_neighbours+=1 : nil
153
+ @grid[x][plus_y] == true ? live_neighbours+=1 : nil
154
+ @grid[minus_x][plus_y] == true ? live_neighbours+=1 : nil
155
+ @grid[plus_x][minus_y] == true ? live_neighbours+=1 : nil
156
+ @grid[minus_x][minus_y] == true ? live_neighbours+=1 : nil
157
+ @grid[plus_x][plus_y] == true ? live_neighbours+=1 : nil
158
+
159
+ case live_neighbours
160
+ when 0..1 then @new_grid[x][y] = false
161
+ when 2 then @new_grid[x][y] = true if @new_grid[x][y] == true
162
+ when 3 then @new_grid[x][y] = true
163
+ when 4..8 then @new_grid[x][y] = false
164
+ end
165
+
166
+ end
167
+ end
168
+
169
+ @grid = @new_grid
170
+ @@tick+=1
171
+ end
172
+
173
+ def toggle_running
174
+ @running = !@running
175
+ end
176
+
177
+ def start_painting; @painting = true; end
178
+ def stop_painting; @painting = false; end
179
+ def start_erasing; @erasing = true; end
180
+ def stop_erasing; @erasing = false; end
181
+
182
+ def draw_cell(x, y, color = 0xaaff0000)
183
+ $window.fill_rect([x*CELL_SIZE,y*CELL_SIZE,CELL_SIZE,CELL_SIZE],0xaa0000ff,1)
184
+ end
185
+
186
+ end
187
+
188
+
189
+ PATTERNS = Hash.new
190
+
191
+ PATTERNS[:pixel] = %q{
192
+ o
193
+ }
194
+
195
+ #
196
+ # Spaceships
197
+ #
198
+ PATTERNS[:glider] = %q{
199
+ ---o
200
+ -o-o
201
+ --oo
202
+ }
203
+
204
+ PATTERNS[:lightweight_spaceship] = %q{
205
+ -oooo
206
+ o---o
207
+ ----o
208
+ o--o-
209
+ }
210
+
211
+ #
212
+ # Oscillators
213
+ #
214
+ PATTERNS[:blinker] = %q{
215
+ ooo
216
+ }
217
+
218
+ PATTERNS[:beacon] = %q{
219
+ -ooo
220
+ ooo-
221
+ }
222
+
223
+ PATTERNS[:toad] = %q{
224
+ oo--
225
+ o---
226
+ ---o
227
+ --oo
228
+ }
229
+
230
+ PATTERNS[:pulsar] = %q{
231
+ ---ooo---ooo--
232
+ --------------
233
+ -o----o-o----o
234
+ -o----o-o----o
235
+ -o----o-o----o
236
+ ---ooo---ooo--
237
+ --------------
238
+ ---ooo---ooo--
239
+ -o----o-o----o
240
+ -o----o-o----o
241
+ -o----o-o----o
242
+ --------------
243
+ ---ooo---ooo--
244
+ }
245
+
246
+ #
247
+ # Guns
248
+ #
249
+ PATTERNS[:gospel_glider_gun] = %q{
250
+ ------------------------o-----------
251
+ ----------------------o-o-----------
252
+ ------------oo------oo------------oo
253
+ -----------o---o----oo------------oo
254
+ oo--------o-----o---oo--------------
255
+ oo--------o---o-oo----o-o-----------
256
+ ----------o-----o-------o-----------
257
+ -----------o---o--------------------
258
+ ------------oo----------------------
259
+ }
260
+
261
+ PATTERNS[:block_laying_switch_engine] = %q{
262
+ ----------o-o--
263
+ oo-------o-----
264
+ oo--------o--o-
265
+ ------------ooo
266
+ }
267
+
268
+
269
+
270
+ #
271
+ # Long lived patterns
272
+ #
273
+ PATTERNS[:rpentomino] = %q{
274
+ --oo
275
+ -oo
276
+ --o
277
+ }
278
+
279
+ PATTERNS[:diehard] = %q{
280
+ oo---o-o
281
+ oo----o-
282
+ ------o-
283
+ }
284
+
285
+ PATTERNS[:acorn] = %q{
286
+ --o-----
287
+ ----o---
288
+ -oo--ooo
289
+ }
290
+
291
+ Main.new.show