chingu 0.7.0 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
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