ray 0.0.1 → 0.1.0.pre1

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 (188) hide show
  1. data/.gemtest +0 -0
  2. data/.yardopts +4 -0
  3. data/README.md +17 -21
  4. data/Rakefile +18 -139
  5. data/VERSION +1 -1
  6. data/ext/audio.cpp +723 -0
  7. data/ext/{color.c → color.cpp} +25 -13
  8. data/ext/drawable.cpp +91 -0
  9. data/ext/event.cpp +460 -0
  10. data/ext/extconf.rb +5 -104
  11. data/ext/font.cpp +190 -0
  12. data/ext/image.cpp +733 -0
  13. data/ext/input.cpp +74 -0
  14. data/ext/ray.cpp +168 -0
  15. data/ext/ray.hpp +356 -0
  16. data/ext/{rect.c → rect.cpp} +51 -37
  17. data/ext/shader.cpp +169 -0
  18. data/ext/shape.cpp +409 -0
  19. data/ext/sprite.cpp +306 -0
  20. data/ext/text.cpp +181 -0
  21. data/ext/vector.cpp +215 -0
  22. data/guide.md +619 -0
  23. data/lib/ray/audio.rb +0 -41
  24. data/lib/ray/color.rb +32 -10
  25. data/lib/ray/drawable.rb +16 -0
  26. data/lib/ray/dsl/event_listener.rb +25 -2
  27. data/lib/ray/dsl/event_runner.rb +33 -5
  28. data/lib/ray/dsl/event_translator.rb +66 -30
  29. data/lib/ray/dsl/handler.rb +3 -2
  30. data/lib/ray/dsl/matcher.rb +58 -14
  31. data/lib/ray/font.rb +38 -96
  32. data/lib/ray/font_set.rb +8 -8
  33. data/lib/ray/game.rb +87 -66
  34. data/lib/ray/helper.rb +105 -10
  35. data/lib/ray/image.rb +150 -24
  36. data/lib/ray/image_set.rb +3 -1
  37. data/lib/ray/input.rb +10 -0
  38. data/lib/ray/music_set.rb +5 -3
  39. data/lib/ray/ray.rb +21 -9
  40. data/lib/ray/rect.rb +48 -7
  41. data/lib/ray/rmagick.rb +41 -0
  42. data/lib/ray/scene.rb +99 -43
  43. data/lib/ray/scene_list.rb +67 -0
  44. data/lib/ray/shape.rb +132 -0
  45. data/lib/ray/sound_set.rb +4 -2
  46. data/lib/ray/sprite.rb +49 -111
  47. data/lib/ray/text.rb +101 -0
  48. data/lib/ray/text_helper.rb +37 -0
  49. data/lib/ray/turtle.rb +215 -0
  50. data/lib/ray/vector.rb +226 -0
  51. data/samples/audio/spacial.rb +44 -0
  52. data/samples/hello_world/hello.rb +9 -13
  53. data/samples/hello_world/hello_dsl.rb +8 -12
  54. data/samples/hello_world/text.rb +15 -0
  55. data/samples/opengl/binding.rb +38 -0
  56. data/samples/opengl/image.rb +32 -0
  57. data/samples/opengl/opengl.rb +34 -0
  58. data/samples/opengl/shader.rb +42 -0
  59. data/samples/pong/pong.rb +14 -10
  60. data/samples/run_scene.rb +53 -0
  61. data/samples/shaders/scene.rb +40 -0
  62. data/samples/shaders/shaders.rb +42 -0
  63. data/samples/shaders/shape.rb +34 -0
  64. data/samples/sokoban/sokoban.rb +18 -18
  65. data/samples/test/actual_scene.rb +41 -0
  66. data/samples/test/scene_riot.rb +39 -0
  67. data/samples/test/scene_spec.rb +32 -0
  68. data/samples/test/scene_test_unit.rb +25 -0
  69. data/samples/turtle/byzantium.rb +45 -0
  70. data/samples/turtle/hilbert.rb +48 -0
  71. data/samples/turtle/koch.rb +55 -0
  72. data/samples/turtle/mandala.rb +61 -0
  73. data/samples/turtle/tree.rb +57 -0
  74. data/test/audio_test.rb +69 -0
  75. data/test/color_test.rb +77 -0
  76. data/test/drawable_test.rb +19 -0
  77. data/test/dsl_test.rb +93 -0
  78. data/test/font_test.rb +57 -0
  79. data/test/helpers.rb +94 -0
  80. data/test/image_test.rb +82 -0
  81. data/test/ray_test.rb +25 -0
  82. data/test/rect_test.rb +121 -0
  83. data/{spec → test}/res/VeraMono.ttf +0 -0
  84. data/{spec → test}/res/aqua.bmp +0 -0
  85. data/{spec → test}/res/aqua.png +0 -0
  86. data/{spec → test}/res/aqua2.bmp +0 -0
  87. data/{spec → test}/res/not_a_jpeg.jpeg +0 -0
  88. data/{spec → test}/res/pop.wav +0 -0
  89. data/test/resource_set_test.rb +99 -0
  90. data/test/run_all.rb +7 -0
  91. data/test/shape_test.rb +101 -0
  92. data/test/sprite_test.rb +89 -0
  93. data/test/text_test.rb +78 -0
  94. data/test/turtle_test.rb +176 -0
  95. data/test/vector_test.rb +111 -0
  96. data/yard_ext.rb +0 -28
  97. metadata +95 -139
  98. data/.gitignore +0 -23
  99. data/.gitmodules +0 -3
  100. data/.rspec +0 -3
  101. data/ext/audio.c +0 -473
  102. data/ext/event.c +0 -557
  103. data/ext/font.c +0 -287
  104. data/ext/image.c +0 -933
  105. data/ext/joystick.c +0 -145
  106. data/ext/ray.c +0 -489
  107. data/ext/ray.h +0 -245
  108. data/ext/ray_osx.m +0 -161
  109. data/lib/ray/joystick.rb +0 -30
  110. data/psp/SDL_psp_main.c +0 -84
  111. data/psp/bigdecimal/README +0 -60
  112. data/psp/bigdecimal/bigdecimal.c +0 -4697
  113. data/psp/bigdecimal/bigdecimal.h +0 -216
  114. data/psp/bigdecimal/lib/bigdecimal/jacobian.rb +0 -85
  115. data/psp/bigdecimal/lib/bigdecimal/ludcmp.rb +0 -84
  116. data/psp/bigdecimal/lib/bigdecimal/math.rb +0 -235
  117. data/psp/bigdecimal/lib/bigdecimal/newton.rb +0 -77
  118. data/psp/bigdecimal/lib/bigdecimal/util.rb +0 -65
  119. data/psp/digest/bubblebabble/bubblebabble.c +0 -142
  120. data/psp/digest/defs.h +0 -20
  121. data/psp/digest/digest.c +0 -643
  122. data/psp/digest/digest.h +0 -32
  123. data/psp/digest/lib/digest.rb +0 -50
  124. data/psp/digest/lib/md5.rb +0 -27
  125. data/psp/digest/lib/sha1.rb +0 -27
  126. data/psp/digest/md5/md5.c +0 -420
  127. data/psp/digest/md5/md5.h +0 -80
  128. data/psp/digest/md5/md5init.c +0 -40
  129. data/psp/digest/rmd160/rmd160.c +0 -457
  130. data/psp/digest/rmd160/rmd160.h +0 -56
  131. data/psp/digest/rmd160/rmd160init.c +0 -40
  132. data/psp/digest/sha1/sha1.c +0 -269
  133. data/psp/digest/sha1/sha1.h +0 -39
  134. data/psp/digest/sha1/sha1init.c +0 -40
  135. data/psp/digest/sha2/lib/sha2.rb +0 -73
  136. data/psp/digest/sha2/sha2.c +0 -919
  137. data/psp/digest/sha2/sha2.h +0 -109
  138. data/psp/digest/sha2/sha2init.c +0 -52
  139. data/psp/enumerator/enumerator.c +0 -298
  140. data/psp/etc/etc.c +0 -559
  141. data/psp/ext.c +0 -289
  142. data/psp/fcntl/fcntl.c +0 -187
  143. data/psp/lib/rbconfig.rb +0 -178
  144. data/psp/nkf/lib/kconv.rb +0 -367
  145. data/psp/nkf/nkf-utf8/config.h +0 -88
  146. data/psp/nkf/nkf-utf8/nkf.c +0 -6040
  147. data/psp/nkf/nkf-utf8/utf8tbl.c +0 -8500
  148. data/psp/nkf/nkf-utf8/utf8tbl.h +0 -34
  149. data/psp/nkf/nkf.c +0 -654
  150. data/psp/socket/addrinfo.h +0 -173
  151. data/psp/socket/getaddrinfo.c +0 -676
  152. data/psp/socket/getnameinfo.c +0 -270
  153. data/psp/socket/pspsocket.c +0 -71
  154. data/psp/socket/pspsocket.h +0 -28
  155. data/psp/socket/socket.c +0 -4662
  156. data/psp/socket/sockport.h +0 -76
  157. data/psp/stringio/stringio.c +0 -1306
  158. data/psp/strscan/strscan.c +0 -1320
  159. data/psp/syck/bytecode.c +0 -1166
  160. data/psp/syck/emitter.c +0 -1242
  161. data/psp/syck/gram.c +0 -1894
  162. data/psp/syck/gram.h +0 -79
  163. data/psp/syck/handler.c +0 -174
  164. data/psp/syck/implicit.c +0 -2990
  165. data/psp/syck/node.c +0 -408
  166. data/psp/syck/rubyext.c +0 -2367
  167. data/psp/syck/syck.c +0 -504
  168. data/psp/syck/syck.h +0 -456
  169. data/psp/syck/token.c +0 -2725
  170. data/psp/syck/yaml2byte.c +0 -257
  171. data/psp/syck/yamlbyte.h +0 -170
  172. data/psp/thread/thread.c +0 -1175
  173. data/psp/zlib/zlib.c +0 -3547
  174. data/script.rb +0 -10
  175. data/spec/ray/audio_spec.rb +0 -146
  176. data/spec/ray/color_spec.rb +0 -57
  177. data/spec/ray/event_spec.rb +0 -80
  178. data/spec/ray/font_spec.rb +0 -93
  179. data/spec/ray/image_set_spec.rb +0 -48
  180. data/spec/ray/image_spec.rb +0 -162
  181. data/spec/ray/joystick_spec.rb +0 -21
  182. data/spec/ray/matcher_spec.rb +0 -50
  183. data/spec/ray/ray_spec.rb +0 -88
  184. data/spec/ray/rect_spec.rb +0 -154
  185. data/spec/ray/resource_set_spec.rb +0 -105
  186. data/spec/ray/sprite_spec.rb +0 -163
  187. data/spec/spec.opts +0 -4
  188. data/spec/spec_helper.rb +0 -8
@@ -0,0 +1,42 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
2
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
3
+
4
+ require 'ray'
5
+
6
+ Ray::Game.new("Shaders test") do
7
+ register do
8
+ add_hook :quit, method(:exit!)
9
+ end
10
+
11
+ scene :shader do
12
+ img = Ray::Image.new(:w => 100, :h => 100).fill(Ray::Color.green)
13
+ img.draw_line([0, 0], [100, 100], Ray::Color.black, 2)
14
+ img.draw_line([0, 100], [100, 0], Ray::Color.white, 2)
15
+ img.draw_filled_circle([50, 50], 10, Ray::Color.cyan)
16
+ img.update
17
+
18
+ shader = Ray::Shader.new StringIO.new(<<-SHADER)
19
+ uniform sampler2D texture;
20
+ uniform vec3 ratio;
21
+
22
+ void main() {
23
+ vec4 color = texture2D(texture, gl_TexCoord[0].xy);
24
+ float gray = dot(color.xyz, ratio);
25
+
26
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
27
+ }
28
+ SHADER
29
+
30
+ shader["texture"] = :current
31
+ shader["ratio"] = [0.299, 0.587, 0.114]
32
+
33
+ render do |win|
34
+ win.fill(Ray::Color.black)
35
+
36
+ img.draw(:on => win, :at => [0, 0], :shader => shader)
37
+ img.draw(:on => win, :at => [100, 100], :shader => nil)
38
+ end
39
+ end
40
+
41
+ push_scene :shader
42
+ end
@@ -0,0 +1,34 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
2
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
3
+
4
+ require 'ray'
5
+
6
+ Ray::Game.new("Shaders test") do
7
+ register do
8
+ add_hook :quit, method(:exit!)
9
+ end
10
+
11
+ scene :shader do
12
+ shape = Ray::Shape.rectangle([0, 0, 100, 100], Ray::Color.black)
13
+ shape.each do |point|
14
+ point.color = Ray::Color.new(rand(256), rand(256), rand(256))
15
+ end
16
+
17
+ shader = Ray::Shader.new StringIO.new(<<-SHADER)
18
+ uniform vec3 ratio;
19
+
20
+ void main() {
21
+ float gray = dot(gl_Color.xyz, ratio);
22
+ gl_FragColor = vec4(gray, gray, gray, 1.0);
23
+ }
24
+ SHADER
25
+
26
+ shader["ratio"] = [0.299, 0.587, 0.114]
27
+
28
+ render do |win|
29
+ shape.draw(:on => win, :shader => shader)
30
+ end
31
+ end
32
+
33
+ push_scene :shader
34
+ end
@@ -1,5 +1,5 @@
1
- $: << File.expand_path(File.dirname(__FILE__) + "/../../lib")
2
- $: << File.expand_path(File.dirname(__FILE__) + "/../../ext")
1
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
2
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
3
3
 
4
4
  require 'ray'
5
5
 
@@ -314,42 +314,42 @@ module Sokoban
314
314
  end
315
315
 
316
316
  def draw_man(win, x, y)
317
- x, y = pos_to_coord(x, y)
318
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.white)
317
+ draw_rect(win, x, y, Ray::Color.white)
319
318
  end
320
319
 
321
320
  def draw_crate(win, x, y)
322
- x, y = pos_to_coord(x, y)
323
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.gray)
321
+ draw_rect(win, x, y, Ray::Color.gray)
324
322
  end
325
323
 
326
324
  def draw_wall(win, x, y)
327
- x, y = pos_to_coord(x, y)
328
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.new(91, 59, 17))
325
+ draw_rect(win, x, y, Ray::Color.new(91, 59, 17))
329
326
  end
330
327
 
331
328
  def draw_storage(win, x, y)
332
- x, y = pos_to_coord(x, y)
333
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.yellow)
329
+ draw_rect(win, x, y, Ray::Color.yellow)
334
330
  end
335
331
 
336
332
  def draw_crate_on_storage(win, x, y)
337
- x, y = pos_to_coord(x, y)
338
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.green)
333
+ draw_rect(win, x, y, Ray::Color.green)
339
334
  end
340
335
 
341
336
  def draw_man_on_storage(win, x, y)
342
- x, y = pos_to_coord(x, y)
343
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.red)
337
+ draw_rect(win, x, y, Ray::Color.red)
344
338
  end
345
339
 
346
340
  def draw_empty_tile(win, x, y)
347
- x, y = pos_to_coord(x, y)
348
- win.draw_filled_rect([x, y, TILE_WIDTH, TILE_WIDTH], Ray::Color.black)
341
+ draw_rect(win, x, y, Ray::Color.black)
349
342
  end
350
343
 
351
- def pos_to_coord(x, y)
352
- [x * TILE_WIDTH, y * TILE_WIDTH]
344
+ def draw_rect(win, x, y, col)
345
+ rect = pos_to_rect(x, y)
346
+
347
+ win.draw_filled_rect(rect, col)
348
+ win.draw_rect(rect, Ray::Color.black)
349
+ end
350
+
351
+ def pos_to_rect(x, y)
352
+ [x * TILE_WIDTH, y * TILE_WIDTH, TILE_WIDTH, TILE_WIDTH]
353
353
  end
354
354
  end
355
355
 
@@ -0,0 +1,41 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
2
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
3
+
4
+ require 'ray'
5
+
6
+ class AwesomeScene < Ray::Scene
7
+ scene_name :awesome_scene
8
+
9
+ def setup
10
+ @cursor = Ray::Shape.rectangle [-10, -10, 20, 20], Ray::Color.red
11
+ end
12
+
13
+ def register
14
+ on :mouse_motion do |pos|
15
+ @cursor.pos = pos
16
+ end
17
+ end
18
+
19
+ def render(win)
20
+ @cursor.draw_on win
21
+ end
22
+
23
+ attr_reader :cursor
24
+ end
25
+
26
+ class AwesomeGame < Ray::Game
27
+ def initialize
28
+ super "Hello world!", :size => [600, 600]
29
+
30
+ AwesomeScene.bind(self)
31
+ push_scene :awesome_scene
32
+ end
33
+
34
+ def register
35
+ add_hook :quit, method(:exit!)
36
+ end
37
+ end
38
+
39
+ if __FILE__ == $0
40
+ AwesomeGame.new.run
41
+ end
@@ -0,0 +1,39 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'actual_scene'
3
+
4
+ require 'riot'
5
+ require 'riot/rr'
6
+
7
+ context AwesomeScene do
8
+ helper(:raise_event) { |*args| @game.raise_event(*args) }
9
+ helper(:run_event_loop) { @game.event_runner.run }
10
+
11
+ setup do
12
+ @game = AwesomeGame.new
13
+ @scene = @game.registred_scene(:awesome_scene)
14
+
15
+ @scene.register
16
+ @scene.setup
17
+
18
+ @scene
19
+ end
20
+
21
+ asserts("cursor position") { topic.cursor.pos }.equals Ray::Vector2[0, 0]
22
+
23
+ context "after moving the mouse" do
24
+ hookup do
25
+ raise_event :mouse_motion, Ray::Vector2[100, 100]
26
+ run_event_loop
27
+ end
28
+
29
+ asserts("cursor position") { topic.cursor.pos }.equals Ray::Vector2[100, 100]
30
+ end
31
+
32
+ asserts "draws its cursor" do
33
+ stub(topic.cursor).draw_on
34
+ topic.render Ray.screen
35
+
36
+ received(topic.cursor).draw_on(is_a(Ray::Image)).call
37
+ true
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'actual_scene'
3
+
4
+ describe AwesomeScene do
5
+ before :each do
6
+ @game = AwesomeGame.new
7
+ @scene = @game.registred_scene(:awesome_scene)
8
+
9
+ @scene.register
10
+ @scene.setup
11
+ end
12
+
13
+ it "has a cursor at (0, 0)" do
14
+ @scene.cursor.pos.should == [0, 0]
15
+ end
16
+
17
+ it "moves its cursor after the mouse moved" do
18
+ @game.raise_event :mouse_motion, Ray::Vector2[100, 100]
19
+ @game.event_runner.run
20
+
21
+ @scene.cursor.pos.should == [100, 100]
22
+ end
23
+
24
+ it "draws its cursor" do
25
+ @scene.cursor.should_receive(:draw_on)
26
+ @scene.render Ray.screen
27
+ end
28
+
29
+ after :each do
30
+ @scene.clean_up
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'actual_scene'
3
+
4
+ require 'test/unit'
5
+
6
+ class AwesomeSceneTest < Test::Unit::TestCase
7
+ def setup
8
+ @game = AwesomeGame.new
9
+ @scene = @game.registred_scene(:awesome_scene)
10
+
11
+ @scene.register
12
+ @scene.setup
13
+ end
14
+
15
+ def test_cursor_position
16
+ assert_equal @scene.cursor.pos, [0, 0]
17
+ end
18
+
19
+ def test_cursor_movement
20
+ @game.raise_event :mouse_motion, Ray::Vector2[100, 100]
21
+ @game.event_runner.run
22
+
23
+ assert_equal @scene.cursor.pos, [100, 100]
24
+ end
25
+ end
@@ -0,0 +1,45 @@
1
+ # Drawing code stolen from here:
2
+ # http://www.rubyquiz.com/quiz104.html
3
+
4
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
5
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
6
+
7
+ require 'ray'
8
+
9
+ class Ray::Turtle
10
+ def byzantium(r, n)
11
+ return if n < 1
12
+ forward r
13
+ right 135
14
+
15
+ 4.times do
16
+ pen_down
17
+ forward 2 * r * sin(PI / 4)
18
+
19
+ pen_up
20
+ byzantium(r / 2, n - 1)
21
+ right 90
22
+ end
23
+
24
+ left 135
25
+ backward r
26
+ end
27
+ end
28
+
29
+ Ray::Game.new("Turtle") do
30
+ register do
31
+ add_hook :quit, method(:exit!)
32
+ end
33
+
34
+ scene :byzantium do
35
+ render do |win|
36
+ win.fill(Ray::Color.black).turtle do
37
+ pen_up
38
+ center
39
+ byzantium(100, 4)
40
+ end
41
+ end
42
+ end
43
+
44
+ push_scene :byzantium
45
+ end
@@ -0,0 +1,48 @@
1
+ # Drawing code stolen from here:
2
+ # http://www.rubyquiz.com/quiz104.html
3
+
4
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
5
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
6
+
7
+ require 'ray'
8
+
9
+ class Ray::Turtle
10
+ def hilbert(s, n, k)
11
+ return if n < 1
12
+ left k * 90
13
+ hilbert(s, n - 1, -k)
14
+ forward s
15
+ right k * 90
16
+ hilbert(s, n - 1, k)
17
+ forward s
18
+ hilbert(s, n - 1, k)
19
+ right k * 90
20
+ forward s
21
+ hilbert(s, n - 1, -k)
22
+ left k * 90
23
+ end
24
+ end
25
+
26
+ Ray::Game.new("Turtle") do
27
+ register do
28
+ add_hook :quit, method(:exit!)
29
+ end
30
+
31
+ scene :hilbert do
32
+ render do |win|
33
+ win.fill(Ray::Color.black).turtle do
34
+ pen_up
35
+ left 90
36
+ backward 185
37
+ right 90
38
+ forward 185
39
+ left 90
40
+
41
+ pen_down
42
+ hilbert(12, 5, 1)
43
+ end
44
+ end
45
+ end
46
+
47
+ push_scene :hilbert
48
+ end
@@ -0,0 +1,55 @@
1
+ # Drawing code stolen from here:
2
+ # http://www.rubyquiz.com/quiz104.html
3
+
4
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
5
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
6
+
7
+ require 'ray'
8
+
9
+ class Ray::Turtle
10
+ def koch(s, n)
11
+ if n < 1
12
+ forward s
13
+ return
14
+ end
15
+
16
+ koch(s / 3, n - 1)
17
+ left 60
18
+ koch(s / 3, n - 1)
19
+ right 120
20
+ koch(s / 3, n - 1)
21
+ left 60
22
+ koch(s / 3, n - 1)
23
+ end
24
+
25
+ def snowflake(s, n)
26
+ 3.times do
27
+ koch(s, n)
28
+ right 120
29
+ end
30
+ end
31
+ end
32
+
33
+ Ray::Game.new("Turtle") do
34
+ register do
35
+ add_hook :quit, method(:exit!)
36
+ end
37
+
38
+ scene :koch do
39
+ render do |win|
40
+ win.fill(Ray::Color.black).turtle do
41
+ pen_up
42
+ center
43
+ backward 165
44
+ left 90
45
+ forward 95
46
+ right 90
47
+
48
+ pen_down
49
+ snowflake(350, 4)
50
+ end
51
+ end
52
+ end
53
+
54
+ push_scene :koch
55
+ end
@@ -0,0 +1,61 @@
1
+ # Drawing code stolen from here:
2
+ # http://www.rubyquiz.com/quiz104.html
3
+
4
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../lib")
5
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../../ext")
6
+
7
+ require 'ray'
8
+
9
+ class Ray::Turtle
10
+ def polygon(r, n)
11
+ poly = []
12
+ theta = 360 * (PI / 180) / n
13
+
14
+ n.times do |k|
15
+ angle = k * theta
16
+ poly << [img.w / 2 + r * sin(angle),
17
+ img.h / 2 + r * cos(angle)]
18
+ end
19
+
20
+ poly
21
+ end
22
+
23
+ def ray(from, to)
24
+ pen_down
25
+ go_to(*to)
26
+
27
+ pen_up
28
+ go_to(*from)
29
+ end
30
+
31
+ def fan(from, others)
32
+ others.each { |to| ray from, to }
33
+ end
34
+
35
+ def mandala(r, n)
36
+ poly = polygon(r, n)
37
+
38
+ until poly.empty?
39
+ v = poly.shift
40
+ go_to(*v)
41
+ fan v, poly
42
+ end
43
+ end
44
+ end
45
+
46
+ Ray::Game.new("Turtle") do
47
+ register do
48
+ add_hook :quit, method(:exit!)
49
+ end
50
+
51
+ scene :mandala do
52
+ render do |win|
53
+ win.fill(Ray::Color.black).turtle do
54
+ pen_up
55
+ mandala(180, 24)
56
+ end
57
+ end
58
+ end
59
+
60
+ push_scene :mandala
61
+ end