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
@@ -1,111 +1,12 @@
1
1
  require 'mkmf'
2
2
 
3
- def find_macosx_framework(name)
4
- paths = [
5
- "/opt/local/Library/Frameworks",
6
- "/Library/Frameworks",
7
- "/Network/Library/Frameworks",
8
- "/System/Library/Frameworks"
9
- ]
10
- paths.reverse!
3
+ $CFLAGS << " -Wextra -Wall -Wno-unused-parameter -Wno-long-long"
11
4
 
12
- paths.each do |dir|
13
- dir = File.join(dir, "#{name}.framework")
14
- next unless File.directory? dir
5
+ # Fix errors from missing.h when compiling as C++
6
+ have_func("ffs")
15
7
 
16
- return dir
17
- end
18
-
19
- nil
20
- end
21
-
22
- def have_framework(name)
23
- print "checking for framweork #{name}... "
24
- ret = find_macosx_framework(name)
25
-
26
- if ret
27
- puts "yes"
28
-
29
- $LDFLAGS << " -F#{File.dirname(ret)}"
30
- $LDFLAGS << " -framework #{name}"
31
- $CFLAGS << " -I#{File.join(ret, "Headers")}"
32
- $CFLAGS << " -DHAVE_#{name.upcase}"
33
- else
34
- puts "no"
35
- end
36
- ret
37
- end
38
-
39
- def have_sdl_ext(name, header)
40
- if res = have_framework(name)
41
- ending = header.upcase.tr('/', '_').gsub(/\.H$/, "_H")
42
- $CFLAGS << " -DHAVE_#{ending}"
43
-
44
- return res
45
- end
46
-
47
- if res = have_library(name)
48
- unless have_header(header) or have_header("SDL/#{header}")
49
- return false
50
- end
51
-
52
- return res
53
- end
54
- end
55
-
56
- $CFLAGS << " -pedantic -Wall -std=c99 -Wno-unused-parameter"
57
-
58
- unless RUBY_PLATFORM =~ /darwin/
59
- unless have_library("SDL", "SDL_Init")
60
- $stdder.puts "SDL not found"
61
- end
62
-
63
- unless (have_header("SDL/SDL.h") or have_header("SDL.h"))
64
- $stderr.puts "SDL.h not found."
65
- exit 1
66
- end
67
-
68
- unless have_library("SDLmain")
69
- $stderr.puts "SDL_main not found."
70
- exit 1
71
- end
72
-
73
- if have_library("SDL_image")
74
- have_header("SDL/SDL_image.h") or have_header("SDL_image.h")
75
- end
76
-
77
- if have_library("SDL_gfx")
78
- have_header("SDL/SDL_rotozoom.h") or have_header("SDL_rotozoom.h")
79
- end
80
-
81
- if have_library("SDL_ttf")
82
- have_header("SDL/SDL_ttf.h") or have_header("SDL_ttf.h")
83
- end
84
-
85
- if have_library("SDL_mixer")
86
- have_header("SDL/SDL_mixer.h") or have_header("SDL_mixer.h")
87
- end
88
-
89
- create_makefile("ray_ext")
90
-
91
- data = File.read("Makefile").gsub("ray_osx.o", "")
92
- open("Makefile", 'w') { |f| f.write(data) }
93
- else
94
- $CFLAGS << " #{ENV["CFLAGS"]}"
95
- $LDFLAGS << " #{ENV["LDFLAGS"]}"
96
-
97
- $CFLAGS << " -DRAY_USE_FRAMEWORK"
98
-
99
- unless have_framework("SDL") and have_framework("Cocoa") and
100
- have_framework("Foundation")
101
- $stderr.puts "missing frameworks"
102
- exit 1
103
- end
104
-
105
- have_sdl_ext("SDL_image", "SDL_image.h")
106
- have_sdl_ext("SDL_gfx", "SDL_rotozoom.h")
107
- have_sdl_ext("SDL_ttf", "SDL_ttf.h")
108
- have_sdl_ext("SDL_mixer", "SDL_mixer.h")
8
+ sfml_exts = %w(audio graphics window system)
109
9
 
10
+ if sfml_exts.all? { |ext| have_library("sfml-#{ext}") }
110
11
  create_makefile("ray_ext")
111
12
  end
@@ -0,0 +1,190 @@
1
+ #include "ray.hpp"
2
+
3
+ typedef struct {
4
+ unsigned long style;
5
+ int font_size;
6
+ } ray_font_style;
7
+
8
+ VALUE ray_cFont = Qnil;
9
+
10
+ void ray_free_font(ray_font *font) {
11
+ delete font;
12
+ }
13
+
14
+ VALUE ray_font2rb(const ray_font &font) {
15
+ ray_font *ptr = new ray_font(font);
16
+ return Data_Wrap_Struct(ray_cFont, 0, ray_free_font, ptr);
17
+ }
18
+
19
+ ray_font *ray_rb2font(VALUE object) {
20
+ if (!RAY_IS_A(object, ray_cFont)) {
21
+ rb_raise(rb_eTypeError, "Can't convert %s into Ray::Font",
22
+ RAY_OBJ_CLASSNAME(object));
23
+ }
24
+
25
+ ray_font *ptr = NULL;
26
+ Data_Get_Struct(object, ray_font, ptr);
27
+
28
+ return ptr;
29
+ }
30
+
31
+ VALUE ray_alloc_font(VALUE self) {
32
+ ray_font *ptr = new ray_font;
33
+ VALUE ret = Data_Wrap_Struct(self, 0, ray_free_font, ptr);
34
+
35
+ return ret;
36
+ }
37
+
38
+ /* @return [Ray::Font] The default font */
39
+ VALUE ray_font_default(VALUE self) {
40
+ return ray_font2rb(sf::Font::GetDefaultFont());
41
+ }
42
+
43
+ void ray_init_font_with_filename(VALUE self, VALUE filename) {
44
+ ray_font *font = NULL;
45
+ Data_Get_Struct(self, ray_font, font);
46
+
47
+ if (!font->LoadFromFile(StringValuePtr(filename))) {
48
+ rb_raise(rb_eRuntimeError, "Could not load the font");
49
+ }
50
+ }
51
+
52
+ void ray_init_font_with_io(VALUE self, VALUE io) {
53
+ ray_font *font = NULL;
54
+ Data_Get_Struct(self, ray_font, font);
55
+
56
+ VALUE string = rb_funcall2(io, RAY_METH("read"), 0, NULL);
57
+ char *content = StringValuePtr(string);
58
+
59
+ if (!font->LoadFromMemory(content, (int)RSTRING_LEN(string))) {
60
+ rb_raise(rb_eRuntimeError, "Could not load the font");
61
+ }
62
+ }
63
+
64
+ /*
65
+ Creates a new font.
66
+ @param [String, #read] arg Filename or IO object.
67
+ */
68
+ VALUE ray_init_font(VALUE self, VALUE arg) {
69
+ if (rb_respond_to(arg, RAY_METH("to_str")))
70
+ ray_init_font_with_filename(self, rb_String(arg));
71
+ else if (rb_respond_to(arg, RAY_METH("read")))
72
+ ray_init_font_with_io(self, arg);
73
+ else {
74
+ rb_raise(rb_eTypeError, "Can't convert %s into String",
75
+ RAY_OBJ_CLASSNAME(arg));
76
+ }
77
+
78
+ return Qnil;
79
+ }
80
+
81
+ ray_font_style ray_parse_font_style(VALUE opts) {
82
+ ray_font_style style;
83
+
84
+ VALUE font_size = rb_hash_aref(opts, RAY_SYM("size"));
85
+ if (!NIL_P(font_size))
86
+ style.font_size = NUM2INT(font_size);
87
+ else
88
+ rb_raise(rb_eArgError, "Character size not specified");
89
+
90
+ style.style = sf::Text::Regular;
91
+ VALUE font_style = Qnil;
92
+ if (!NIL_P(font_style = rb_hash_aref(opts, RAY_SYM("style"))))
93
+ style.style = NUM2INT(font_style);
94
+
95
+ return style;
96
+ }
97
+
98
+ /* @return [Integer] the recommended spacing between lines for this font */
99
+ VALUE ray_font_line_skip(VALUE self, VALUE size) {
100
+ ray_font *font = ray_rb2font(self);
101
+ return INT2FIX(font->GetLineSpacing(NUM2INT(size)));
102
+ }
103
+
104
+ VALUE ray_font_simple_size_of(VALUE self, VALUE str, VALUE opts) {
105
+ ray_font *font = ray_rb2font(self);
106
+ ray_font_style style = ray_parse_font_style(opts);
107
+
108
+ char *c_str = StringValuePtr(str);
109
+ sf::String string((uint32_t*)c_str);
110
+
111
+ sf::Text text(string, *font);
112
+ text.SetStyle(style.style);
113
+ text.SetCharacterSize(style.font_size);
114
+
115
+ ray_rect rect = RAY_RECT(text.GetRect());
116
+ return ray_vector2_to_rb(sf::Vector2f(rect.Width, rect.Height));
117
+ }
118
+
119
+ VALUE ray_font_simple_draw(VALUE self, VALUE str, VALUE hash) {
120
+ ray_font *font = ray_rb2font(self);
121
+ ray_font_style style = ray_parse_font_style(hash);
122
+
123
+ VALUE rb_color = rb_hash_aref(hash, RAY_SYM("color"));
124
+ ray_color c_color(255, 255, 255, 255);
125
+ if (!NIL_P(rb_color))
126
+ c_color = ray_rb2col(rb_color);
127
+
128
+ char *c_str = StringValuePtr(str);
129
+ sf::String string((uint32_t*)c_str);
130
+
131
+ sf::Text text(string, *font);
132
+ text.SetStyle(style.style);
133
+ text.SetCharacterSize(style.font_size);
134
+ text.SetColor(c_color);
135
+
136
+ ray_rect rect = RAY_RECT(text.GetRect());
137
+
138
+ ray_vector2 pos(0, 0);
139
+ VALUE rb_pos = rb_hash_aref(hash, RAY_SYM("at"));
140
+ if (NIL_P(rb_pos))
141
+ rb_pos = rb_hash_aref(hash, RAY_SYM("to"));
142
+ if (!NIL_P(rb_pos))
143
+ pos = ray_convert_to_vector2(rb_pos);
144
+
145
+ text.SetPosition(pos.x, pos.y);
146
+
147
+ VALUE on = rb_hash_aref(hash, RAY_SYM("on"));
148
+ if (NIL_P(on)) {
149
+ VALUE image_hash = rb_hash_new();
150
+ rb_hash_aset(image_hash, RAY_SYM("width"), INT2FIX(rect.Width));
151
+ rb_hash_aset(image_hash, RAY_SYM("height"), INT2FIX(rect.Height));
152
+
153
+ on = rb_funcall(ray_cImage, RAY_METH("new"), 1, image_hash);
154
+ }
155
+
156
+ ray_image *image = ray_rb2image(on);
157
+ image->draw(text);
158
+
159
+ return on;
160
+ }
161
+
162
+ /*
163
+ Doucment-class: Ray::Font
164
+
165
+ Class used to draw text.
166
+ It can render text on an image:
167
+ font.draw("Hello world!", :on => image, :at => [10, 20]) # => image
168
+ Or create a new image containing the text, to use it later (which is
169
+ potentially better than rendering the same string a great amount of
170
+ times):
171
+ font.draw("Hello world!") # => a new image
172
+ */
173
+
174
+ void Init_ray_font() {
175
+ ray_cFont = rb_define_class_under(ray_mRay, "Font", rb_cObject);
176
+ rb_define_alloc_func(ray_cFont, ray_alloc_font);
177
+ rb_define_method(ray_cFont, "initialize", ray_init_font, 1);
178
+
179
+ rb_define_singleton_method(ray_cFont, "default", ray_font_default, 0);
180
+
181
+ rb_define_method(ray_cFont, "line_skip", ray_font_line_skip, 1);
182
+ rb_define_method(ray_cFont, "simple_size_of", ray_font_simple_size_of, 2);
183
+
184
+ rb_define_method(ray_cFont, "simple_draw", ray_font_simple_draw, 2);
185
+
186
+ rb_define_const(ray_cFont, "STYLE_NORMAL", INT2FIX(sf::Text::Regular));
187
+ rb_define_const(ray_cFont, "STYLE_ITALIC", INT2FIX(sf::Text::Italic));
188
+ rb_define_const(ray_cFont, "STYLE_BOLD", INT2FIX(sf::Text::Bold));
189
+ rb_define_const(ray_cFont, "STYLE_UNDERLINE", INT2FIX(sf::Text::Underlined));
190
+ }
@@ -0,0 +1,733 @@
1
+ #include "ray.hpp"
2
+
3
+ VALUE ray_cImage = Qnil;
4
+
5
+ ray_image::ray_image(bool should_be_screen):
6
+ is_screen(should_be_screen),
7
+ pixel_modifier(NULL)
8
+ {}
9
+
10
+ ray_image::~ray_image() {
11
+ if (pixel_modifier) delete pixel_modifier;
12
+ }
13
+
14
+ bool ray_image::create_with_size(int w, int h) {
15
+ return render_image.Create(w, h);
16
+ }
17
+
18
+ bool ray_image::create_with_filename(const std::string &filename) {
19
+ sf::Image temp_image;
20
+ if (!temp_image.LoadFromFile(filename))
21
+ return false;
22
+
23
+ sf::Sprite temp_sprite(temp_image);
24
+
25
+ if (!create_with_size(temp_image.GetWidth(), temp_image.GetHeight()))
26
+ return false;
27
+
28
+ render_image.Draw(temp_sprite);
29
+ sprite.SetImage(render_image.GetImage());
30
+
31
+ update();
32
+
33
+ return true;
34
+ }
35
+
36
+ bool ray_image::create_with_io(VALUE io) {
37
+ VALUE string = rb_funcall2(io, RAY_METH("read"), 0, NULL);
38
+ char *content = StringValuePtr(string);
39
+
40
+ sf::Image temp_image;
41
+ if (!temp_image.LoadFromMemory(content, RSTRING_LEN(string)))
42
+ return false;
43
+
44
+ sf::Sprite temp_sprite(temp_image);
45
+
46
+ if (!create_with_size(temp_image.GetWidth(), temp_image.GetHeight()))
47
+ return false;
48
+
49
+ render_image.Draw(temp_sprite);
50
+ sprite.SetImage(render_image.GetImage());
51
+
52
+ update();
53
+
54
+ return true;
55
+ }
56
+
57
+ bool ray_image::create_with_image(ray_image &src) {
58
+ sf::Sprite &src_sprite = src.get_sprite();
59
+ sf::Vector2f size = src_sprite.GetSize();
60
+
61
+ if (!create_with_size(src.width(), src.height()))
62
+ return false;
63
+
64
+ draw_image(src, ray_rect(0, 0, src.width(), src.height()),
65
+ ray_vector2(0, 0),
66
+ 0.f, ray_vector2(1.f, 1.f));
67
+ update();
68
+
69
+ return true;
70
+ }
71
+
72
+ bool ray_image::save_as(const std::string &filename) const {
73
+ if (is_screen) {
74
+ sf::Image screen_copy;
75
+
76
+ if (!screen_copy.CopyScreen(ray_screen, sf::IntRect(0, 0, width(),
77
+ height()))) {
78
+ return false;
79
+ }
80
+
81
+ return screen_copy.SaveToFile(filename);
82
+ }
83
+ else {
84
+ return render_image.GetImage().SaveToFile(filename);
85
+ }
86
+ }
87
+
88
+ int ray_image::width() const { return target().GetWidth(); }
89
+ int ray_image::height() const { return target().GetHeight(); }
90
+
91
+ void ray_image::update() {
92
+ if (is_screen)
93
+ ray_screen.Display();
94
+ else
95
+ render_image.Display();
96
+ }
97
+
98
+ void ray_image::fill(sf::Color color) {
99
+ target().Clear(color);
100
+ }
101
+
102
+ void ray_image::draw(const sf::Drawable &drawable,
103
+ sf::Shader *shader) {
104
+ if (shader)
105
+ target().Draw(drawable, *shader);
106
+ else
107
+ target().Draw(drawable);
108
+ }
109
+
110
+ void ray_image::draw_image(ray_image &image,
111
+ const ray_rect &src_rect,
112
+ const ray_vector2 &dest_pos,
113
+ float angle, const ray_vector2 &zoom,
114
+ sf::Shader *shader,
115
+ const ray_color &color) {
116
+ sf::Image screen_copy;
117
+
118
+ if (image.is_screen) {
119
+ if (!screen_copy.CopyScreen(ray_screen, sf::IntRect(0, 0, image.width(),
120
+ image.height()))) {
121
+ return;
122
+ }
123
+
124
+ sprite = sf::Sprite(screen_copy);
125
+ }
126
+ else {
127
+ sprite = sf::Sprite(image.render_image.GetImage());
128
+ }
129
+
130
+ sprite.SetSubRect(RAY_INT_RECT(src_rect));
131
+
132
+ sprite.SetPosition(dest_pos);
133
+
134
+ sprite.SetScale(zoom);
135
+ sprite.SetRotation(angle);
136
+
137
+ sprite.SetColor(color);
138
+
139
+ if (!shader)
140
+ target().Draw(sprite);
141
+ else
142
+ target().Draw(sprite, *shader);
143
+ }
144
+
145
+ ray_color ray_image::at(int x, int y) const {
146
+ if (pixel_modifier)
147
+ return pixel_modifier->GetPixel(x, y);
148
+
149
+ if (is_screen) {
150
+ sf::Image img;
151
+ img.CopyScreen(ray_screen, sf::IntRect(x, y, 1, 1));
152
+ return img.GetPixel(0, 0);
153
+ }
154
+
155
+ return render_image.GetImage().GetPixel(x, y);
156
+ }
157
+
158
+ bool ray_image::set_at(int x, int y, const ray_color &color) {
159
+ if (!pixel_modifier) return false;
160
+
161
+ pixel_modifier->SetPixel(x, y, color);
162
+ return true;
163
+ }
164
+
165
+ const uint8_t *ray_image::pixels() const {
166
+ return render_image.GetImage().GetPixelsPtr();
167
+ }
168
+
169
+ ray_rect ray_image::clip() const {
170
+ sf::FloatRect rect = target().GetView().GetViewport();
171
+ return ray_rect(rect.Left * width(), rect.Top * height(),
172
+ rect.Width * width(), rect.Height * height());
173
+ }
174
+
175
+ void ray_image::set_clip(const ray_rect &other) {
176
+ sf::FloatRect rect(other.Left / (float)width(),
177
+ other.Top / (float)height(),
178
+ other.Width / (float)width(),
179
+ other.Height / (float)height());
180
+ sf::View view(target().GetDefaultView());
181
+ view.SetViewport(rect);
182
+
183
+ target().SetView(view);
184
+ }
185
+
186
+ bool ray_image::lock() {
187
+ if (pixel_modifier) return true;
188
+
189
+ if (is_screen) {
190
+ pixel_modifier = new sf::Image;
191
+
192
+ if (!pixel_modifier->CopyScreen(ray_screen,
193
+ sf::IntRect(0, 0, width(), height()))) {
194
+ delete pixel_modifier;
195
+ pixel_modifier = NULL;
196
+
197
+ return false;
198
+ }
199
+ }
200
+ else
201
+ pixel_modifier = new sf::Image(render_image.GetImage());
202
+
203
+ return true;
204
+ }
205
+
206
+ void ray_image::unlock() {
207
+ if (!pixel_modifier) return;
208
+
209
+ target().Clear(ray_color(0, 0, 0, 0));
210
+ sf::Sprite tmp_sprite(*pixel_modifier);
211
+ target().Draw(tmp_sprite);
212
+
213
+ delete pixel_modifier;
214
+ pixel_modifier = NULL;
215
+ }
216
+
217
+ void ray_image::activate() {
218
+ if (is_screen)
219
+ ray_screen.SetActive();
220
+ else
221
+ render_image.SetActive();
222
+ }
223
+
224
+ void ray_image::bind() {
225
+ render_image.GetImage().Bind();
226
+ }
227
+
228
+ bool ray_image::is_image() const {
229
+ return !is_screen;
230
+ }
231
+
232
+ const sf::Image &ray_image::image() const {
233
+ return render_image.GetImage();
234
+ }
235
+
236
+ bool ray_image::operator==(const ray_image &other) const {
237
+ return (&(target()) == &(other.target()));
238
+ }
239
+
240
+ sf::RenderTarget &ray_image::target() {
241
+ return is_screen ? (sf::RenderTarget&)ray_screen :
242
+ (sf::RenderTarget&)render_image;
243
+ }
244
+
245
+ const sf::RenderTarget &ray_image::target() const {
246
+ return is_screen ? (sf::RenderTarget&)ray_screen :
247
+ (sf::RenderTarget&)render_image;
248
+ }
249
+
250
+ ray_image *ray_rb2image(VALUE object) {
251
+ if (!RAY_IS_A(object, ray_cImage)) {
252
+ rb_raise(rb_eTypeError, "Can't convert %s into Ray::Image",
253
+ RAY_OBJ_CLASSNAME(object));
254
+ }
255
+
256
+ ray_image *ptr = NULL;
257
+ Data_Get_Struct(object, ray_image, ptr);
258
+
259
+ return ptr;
260
+ }
261
+
262
+ /*
263
+ @return [true, false] True if it is possible to draw on an image.
264
+ If this is false, many methods won't work as expected.
265
+ */
266
+ VALUE ray_image_available(VALUE self) {
267
+ return sf::RenderImage::IsAvailable() ? Qtrue : Qfalse;
268
+ }
269
+
270
+ void ray_init_image_with_hash(VALUE self, VALUE arg) {
271
+ VALUE width = rb_hash_aref(arg, RAY_SYM("width"));
272
+ if (NIL_P(width)) width = rb_hash_aref(arg, RAY_SYM("w"));
273
+
274
+ VALUE height = rb_hash_aref(arg, RAY_SYM("height"));
275
+ if (NIL_P(height)) height = rb_hash_aref(arg, RAY_SYM("h"));
276
+
277
+ ray_image *image = ray_rb2image(self);
278
+ bool res = image->create_with_size(NUM2INT(width), NUM2INT(height));
279
+
280
+ if (!res)
281
+ rb_raise(rb_eRuntimeError, "Could not create the image");
282
+ }
283
+
284
+ void ray_init_image_with_filename(VALUE self, VALUE filename) {
285
+ char *c_filename = StringValuePtr(filename);
286
+ ray_image *image = ray_rb2image(self);
287
+
288
+ if (!image->create_with_filename(c_filename))
289
+ rb_raise(rb_eRuntimeError, "Could not create the image");
290
+ }
291
+
292
+ void ray_init_image_with_io(VALUE self, VALUE io) {
293
+ ray_image *image = ray_rb2image(self);
294
+ if (!image->create_with_io(io))
295
+ rb_raise(rb_eRuntimeError, "Could not create the image");
296
+ }
297
+
298
+ /*
299
+ Creates a new image.
300
+
301
+ @overload initialize(hash)
302
+ @option hash [Integer] :width Width of the surface
303
+ @option hash [Integer] :height Height of the surface
304
+
305
+ @option hash [Integer] :w Alias for width
306
+ @option hash [Integer] :h Alias for height
307
+
308
+ @overload initialize(filename)
309
+ Loads the image from a file.
310
+ @param [String, #to_str] filename The name of the file to open
311
+
312
+ @overload initialize(io)
313
+ Loads the image friom an IO object.
314
+ @param [IO, #read] io Object the data will be loaded from.
315
+ */
316
+ VALUE ray_init_image(VALUE self, VALUE arg) {
317
+ if (RAY_IS_A(arg, rb_cHash))
318
+ ray_init_image_with_hash(self, arg);
319
+ else if (rb_respond_to(arg, RAY_METH("to_str")))
320
+ ray_init_image_with_filename(self, rb_String(arg));
321
+ else if (rb_respond_to(arg, RAY_METH("read")))
322
+ ray_init_image_with_io(self, arg);
323
+ else {
324
+ rb_raise(rb_eTypeError, "Can't convert %s into Hash",
325
+ RAY_OBJ_CLASSNAME(arg));
326
+ }
327
+
328
+ return Qnil;
329
+ }
330
+
331
+ VALUE ray_init_image_copy(VALUE self, VALUE obj) {
332
+ ray_image *img = ray_rb2image(self);
333
+ ray_image *src = ray_rb2image(obj);
334
+
335
+ if (!img->create_with_image(*src))
336
+ rb_raise(rb_eRuntimeError, "Could not create the image");
337
+
338
+ return self;
339
+ }
340
+
341
+ void ray_free_image(ray_image *ptr) {
342
+ delete ptr;
343
+ }
344
+
345
+ VALUE ray_alloc_image(VALUE self) {
346
+ ray_image *ptr = new ray_image(false);
347
+ VALUE ret = Data_Wrap_Struct(self, 0, ray_free_image, ptr);
348
+
349
+ return ret;
350
+ }
351
+
352
+ VALUE ray_create_screen() {
353
+ ray_image *ptr = new ray_image(true);
354
+ VALUE ret = Data_Wrap_Struct(ray_cImage, 0, ray_free_image, ptr);
355
+
356
+ return ret;
357
+ }
358
+
359
+ /*
360
+ @overload save_as(filename)
361
+ Saves the image in a file.
362
+ */
363
+ VALUE ray_image_save_as(VALUE self, VALUE filename) {
364
+ if (!ray_rb2image(self)->save_as(StringValuePtr(filename))) {
365
+ rb_raise(rb_eRuntimeError, "Couldn't save image to file");
366
+ }
367
+
368
+ return self;
369
+ }
370
+
371
+ /*
372
+ @overload fill(col)
373
+ Fills the image with a given color.
374
+ @param [Ray::Color] col The color used to fill the image.
375
+ */
376
+ VALUE ray_image_fill(VALUE self, VALUE col) {
377
+ rb_check_frozen(self);
378
+
379
+ ray_image *img = ray_rb2image(self);
380
+ img->fill(ray_rb2col(col));
381
+
382
+ return self;
383
+ }
384
+
385
+ /* Updates the image. */
386
+ VALUE ray_image_flip(VALUE self) {
387
+ rb_check_frozen(self);
388
+ ray_rb2image(self)->update();
389
+ return self;
390
+ }
391
+
392
+ /*
393
+ @overload blit(hash)
394
+ Blits the receiver on another image.
395
+
396
+ @option hash [Ray::Vector2, #to_vector2] :at Position where the receiver
397
+ should be drawn.
398
+ @option hash [Ray::Rect, Array] :rect Rects that will be copied.
399
+ If an array is given, it
400
+ passed to Ray::Rect.new.
401
+ If the size is (0, 0), it will
402
+ be reset to the image's size.
403
+ @option hash [Ray::Rect, Array] :from Alias for rect
404
+
405
+ @option hash [Ray::Image, required] :on The image on which the receiver should
406
+ be drawn.
407
+
408
+ @option hash [Ray::Image] :to Alias for on.
409
+
410
+ @option hash [Float] :angle Rotation in degrees.
411
+ @option hash [Ray::Vector2, Float] :zoom Zoom level. If a float is
412
+ specified, Vector2[zoom, zoom] will be used.
413
+
414
+ @option hash [Ray::Shader] :shader Shader to be used.
415
+
416
+ @option hash [Ray::Color] :color (Ray::Color.white) Color used, affecting
417
+ the whole image. Each pixel is multiplied by this color.
418
+ */
419
+ VALUE ray_image_blit(VALUE self, VALUE hash) {
420
+ ray_image *origin = ray_rb2image(self);
421
+
422
+ ray_rect from_rect;
423
+ ray_vector2 dest_pos;
424
+
425
+ VALUE pos = rb_hash_aref(hash, RAY_SYM("at"));
426
+ if (!NIL_P(pos))
427
+ dest_pos = ray_convert_to_vector2(pos);
428
+
429
+ VALUE rect = rb_hash_aref(hash, RAY_SYM("rect"));
430
+ if (NIL_P(rect)) rect = rb_hash_aref(hash, RAY_SYM("from"));
431
+
432
+ if (!NIL_P(rect))
433
+ from_rect = ray_convert_to_rect(rect);
434
+
435
+ VALUE surf = rb_hash_aref(hash, RAY_SYM("on"));
436
+ if (surf == Qnil) surf = rb_hash_aref(hash, RAY_SYM("to"));
437
+
438
+ rb_check_frozen(surf);
439
+
440
+ ray_image *target = ray_rb2image(surf);
441
+
442
+ VALUE rb_angle = Qnil, rb_zoom = Qnil;
443
+ float angle = 0.0f;
444
+ ray_vector2 zoom(1.0f, 1.0f);
445
+
446
+ if (!NIL_P(rb_angle = rb_hash_aref(hash, RAY_SYM("angle"))))
447
+ angle = (float)NUM2DBL(rb_angle);
448
+
449
+ if (!NIL_P(rb_zoom = rb_hash_aref(hash, RAY_SYM("zoom")))) {
450
+ if (RAY_IS_A(rb_zoom, rb_cFloat)) {
451
+ float zoom_val = (float)NUM2DBL(rb_zoom);
452
+ zoom = ray_vector2(zoom_val, zoom_val);
453
+ }
454
+ else
455
+ zoom = ray_convert_to_vector2(rb_zoom);
456
+ }
457
+
458
+ if (from_rect.Width == 0 && from_rect.Height == 0) {
459
+ from_rect.Width = origin->width();
460
+ from_rect.Height = origin->height();
461
+ }
462
+
463
+ VALUE rb_shader = rb_hash_aref(hash, RAY_SYM("shader"));
464
+ sf::Shader *shader = NULL;
465
+ if (!NIL_P(rb_shader))
466
+ shader = ray_rb2shader(rb_shader);
467
+
468
+ ray_color color(255, 255, 255);
469
+ VALUE rb_color = rb_hash_aref(hash, RAY_SYM("color"));
470
+ if (!NIL_P(rb_color))
471
+ color = ray_rb2col(rb_color);
472
+
473
+ target->draw_image(*origin, from_rect, dest_pos, angle, zoom,
474
+ shader, color);
475
+
476
+ return surf;
477
+ }
478
+
479
+ /* @return [Integer] Width of the surface */
480
+ VALUE ray_image_width(VALUE self) {
481
+ return INT2FIX(ray_rb2image(self)->width());
482
+ }
483
+
484
+ /* @return [Integer] Height of the surface */
485
+ VALUE ray_image_height(VALUE self) {
486
+ return INT2FIX(ray_rb2image(self)->height());
487
+ }
488
+
489
+ /*
490
+ @overload ==(obj)
491
+ @return [true, false] true if obj manipulates the same surface as the
492
+ receiver.
493
+ */
494
+ VALUE ray_image_is_equal(VALUE self, VALUE obj) {
495
+ if (!RAY_IS_A(obj, ray_cImage))
496
+ return Qfalse;
497
+
498
+ ray_image *first_img = ray_rb2image(self);
499
+ ray_image *sec_img = ray_rb2image(obj);
500
+
501
+ return (*first_img == *sec_img) ? Qtrue : Qfalse;
502
+ }
503
+
504
+
505
+ VALUE ray_image_ensure_unlock(VALUE self) {
506
+ rb_check_frozen(self);
507
+ ray_rb2image(self)->unlock();
508
+ return self;
509
+ }
510
+
511
+ /*
512
+ Locks the image (allow pixel-per-pixel modifications).
513
+ Don't forget to call unlock when you're done. You can also
514
+ pass a bock which will be called before the image gets unlocked
515
+ automatically.
516
+ */
517
+ VALUE ray_image_lock(VALUE self) {
518
+ rb_check_frozen(self);
519
+
520
+ ray_image *image = ray_rb2image(self);
521
+ if (!image->lock())
522
+ rb_raise(rb_eRuntimeError, "Couldn't lock the image");
523
+
524
+ if (rb_block_given_p())
525
+ rb_ensure(rb_yield, Qnil, ray_image_ensure_unlock, self);
526
+
527
+ return self;
528
+ }
529
+
530
+ /*
531
+ Unlocks the image. You must call this once you are done
532
+ modifying the image.
533
+ */
534
+ VALUE ray_image_unlock(VALUE self) {
535
+ return ray_image_ensure_unlock(self);
536
+ }
537
+
538
+ /*
539
+ @overload [](x, y)
540
+ @return [Ray::Color, nil] Pixel at (x, y). Nil if the point is outside the
541
+ image.
542
+ */
543
+ VALUE ray_image_at(VALUE self, VALUE rb_x, VALUE rb_y) {
544
+ ray_image *image = ray_rb2image(self);
545
+
546
+ int x = NUM2INT(rb_x);
547
+ int y = NUM2INT(rb_y);
548
+
549
+ /* (w, h) is not a valid point. Surfaces use 0-based indexing. */
550
+ if (x >= image->width() || y >= image->height())
551
+ return Qnil;
552
+
553
+ return ray_col2rb(image->at(x, y));
554
+ }
555
+
556
+ /*
557
+ @overload []=(x, y, color)
558
+ Sets the color of the point at (x, y)
559
+ @raise ArgumentError If (x, y) is outside the image.
560
+ @note Don't call this if the image isn't locked.
561
+ @example
562
+ img.lock { img[0, 0] = Ray::Color.red }
563
+ */
564
+ VALUE ray_image_set_at(VALUE self, VALUE rb_x, VALUE rb_y, VALUE rb_col) {
565
+ rb_check_frozen(self);
566
+
567
+ ray_image *image = ray_rb2image(self);
568
+
569
+ int x = NUM2INT(rb_x);
570
+ int y = NUM2INT(rb_y);
571
+
572
+ if (x >= image->width() || y >= image->height()) {
573
+ VALUE inspect = rb_inspect(self);
574
+ rb_raise(rb_eArgError, "(%d, %d) is outside %s",
575
+ x, y, StringValuePtr(inspect));
576
+ }
577
+
578
+ if (!image->set_at(x, y, ray_rb2col(rb_col)))
579
+ rb_raise(rb_eRuntimeError, "Trying to set pixel on a non locked image");
580
+
581
+ return rb_col;
582
+ }
583
+
584
+ VALUE ray_image_ensure_unclip(VALUE ary) {
585
+ ray_image *image = ray_rb2image(rb_ary_entry(ary, 0));
586
+ ray_rect rect = ray_rb2rect(rb_ary_entry(ary, 1));
587
+
588
+ image->set_clip(rect);
589
+ rb_gc_unregister_address(&ary);
590
+
591
+ return Qnil;
592
+ }
593
+
594
+ /*
595
+ @overload clip
596
+ @return [Ray::Rect] The current clipping rect
597
+
598
+ @overload clip(rect)
599
+ Changes the clipping rect (the rect which will be changed if something is
600
+ drawn on this image, the rest of the image being ignored.)
601
+
602
+ If a block is given, it is executed, and the old clipping rect is reset
603
+ afterwards.
604
+
605
+ @param [Ray::Rect, Array<Integer>] rect New clipping rect.
606
+ */
607
+ VALUE ray_image_clip(int argc, VALUE *argv, VALUE self) {
608
+ VALUE rb_rect = Qnil;
609
+ rb_scan_args(argc, argv, "01", &rb_rect);
610
+
611
+ ray_image *image = ray_rb2image(self);
612
+
613
+ ray_rect old_rect = image->clip();
614
+
615
+ if (NIL_P(rb_rect))
616
+ return ray_rect2rb(old_rect);
617
+
618
+ rb_check_frozen(self);
619
+
620
+ ray_rect rect = ray_convert_to_rect(rb_rect);
621
+ image->set_clip(rect);
622
+
623
+ if (rb_block_given_p()) {
624
+ VALUE ary = rb_ary_new();
625
+ rb_ary_push(ary, self);
626
+ rb_ary_push(ary, ray_rect2rb(old_rect));
627
+
628
+ rb_gc_register_address(&ary);
629
+
630
+ rb_ensure(rb_yield, Qnil, ray_image_ensure_unclip, ary);
631
+ }
632
+
633
+ return ray_rect2rb(rect);
634
+ }
635
+
636
+ /*
637
+ Binds the image to use it as an OpenGL texture.
638
+ */
639
+ VALUE ray_image_bind(VALUE self) {
640
+ ray_image *img = ray_rb2image(self);
641
+ if (!img->is_image())
642
+ rb_raise(rb_eRuntimeError, "Can't bind screen");
643
+
644
+ img->bind();
645
+ return self;
646
+ }
647
+
648
+ /* Activates the image to draw on it using OpenGL. */
649
+ VALUE ray_image_activate(VALUE self) {
650
+ rb_check_frozen(self);
651
+ ray_rb2image(self)->activate();
652
+
653
+ return self;
654
+ }
655
+
656
+ /*
657
+ @overload draw_shape(shape, shader = nil, color = Ray::Color.white)
658
+ Draws a shape on the image
659
+
660
+ @param [Ray::Shape] shape The shape to be drawn
661
+ @param [Ray::Shader] shader The shader to use with the shape
662
+ @param [Ray::Color] color The color used to multiply each pixel of the
663
+ shape.
664
+ */
665
+ VALUE ray_image_draw_shape(int argc, VALUE *argv, VALUE self) {
666
+ rb_check_frozen(self);
667
+
668
+ VALUE shape, shader, color;
669
+ rb_scan_args(argc, argv, "12", &shape, &shader, &color);
670
+
671
+ rb_check_frozen(self);
672
+
673
+ ray_image *image = ray_rb2image(self);
674
+
675
+ sf::Shape *c_shape = ray_rb2shape(shape);
676
+ sf::Shader *c_shader = NULL;
677
+ if (!NIL_P(shader)) c_shader = ray_rb2shader(shader);
678
+
679
+ ray_color c_color(sf::Color::White);
680
+ if (!NIL_P(color)) c_color = ray_rb2col(color);
681
+
682
+ c_shape->SetColor(c_color);
683
+
684
+ image->draw(*c_shape, c_shader);
685
+ return self;
686
+ }
687
+
688
+ /*
689
+ @overload draw_drawable(drawable)
690
+ Draws a drawable on the image
691
+ */
692
+ VALUE ray_image_draw_drawable(VALUE self, VALUE drawable) {
693
+ rb_check_frozen(self);
694
+
695
+ ray_drawable *c_drawable = ray_rb2drawable(drawable);
696
+ c_drawable->render(self);
697
+
698
+ return self;
699
+ }
700
+
701
+ void Init_ray_image() {
702
+ ray_cImage = rb_define_class_under(ray_mRay, "Image", rb_cObject);
703
+ rb_define_alloc_func(ray_cImage, ray_alloc_image);
704
+ rb_define_method(ray_cImage, "initialize", ray_init_image, 1);
705
+ rb_define_method(ray_cImage, "initialize_copy", ray_init_image_copy, 1);
706
+
707
+ rb_define_singleton_method(ray_cImage, "available?", ray_image_available, 0);
708
+
709
+ rb_define_method(ray_cImage, "save_as", ray_image_save_as, 1);
710
+
711
+ rb_define_method(ray_cImage, "fill", ray_image_fill, 1);
712
+ rb_define_method(ray_cImage, "flip", ray_image_flip, 0);
713
+
714
+ rb_define_method(ray_cImage, "blit", ray_image_blit, 1);
715
+
716
+ rb_define_method(ray_cImage, "width", ray_image_width, 0);
717
+ rb_define_method(ray_cImage, "height", ray_image_height, 0);
718
+
719
+ rb_define_method(ray_cImage, "==", ray_image_is_equal, 1);
720
+
721
+ rb_define_method(ray_cImage, "lock", ray_image_lock, 0);
722
+ rb_define_method(ray_cImage, "unlock", ray_image_unlock, 0);
723
+ rb_define_method(ray_cImage, "[]", ray_image_at, 2);
724
+ rb_define_method(ray_cImage, "[]=", ray_image_set_at, 3);
725
+
726
+ rb_define_method(ray_cImage, "clip", ray_image_clip, -1);
727
+
728
+ rb_define_method(ray_cImage, "bind", ray_image_bind, 0);
729
+ rb_define_method(ray_cImage, "activate", ray_image_activate, 0);
730
+
731
+ rb_define_method(ray_cImage, "draw_shape", ray_image_draw_shape, -1);
732
+ rb_define_method(ray_cImage, "draw_drawable", ray_image_draw_drawable, 1);
733
+ }