ruby2d 0.2.1 → 0.3.0
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.
- checksums.yaml +4 -4
- data/assets/README.md +1 -0
- data/assets/opal.js +19532 -0
- data/assets/simple2d.js +1180 -0
- data/assets/template.html +18 -0
- data/bin/ruby2d +161 -46
- data/ext/ruby2d/extconf.rb +17 -8
- data/ext/ruby2d/ruby2d-opal.rb +219 -0
- data/ext/ruby2d/ruby2d.c +665 -154
- data/lib/ruby2d.rb +7 -4
- data/lib/ruby2d/application.rb +14 -2
- data/lib/ruby2d/color.rb +56 -33
- data/lib/ruby2d/dsl.rb +21 -12
- data/lib/ruby2d/exceptions.rb +2 -3
- data/lib/ruby2d/image.rb +22 -9
- data/lib/ruby2d/music.rb +17 -0
- data/lib/ruby2d/quad.rb +24 -15
- data/lib/ruby2d/rectangle.rb +2 -5
- data/lib/ruby2d/sound.rb +6 -9
- data/lib/ruby2d/sprite.rb +91 -0
- data/lib/ruby2d/square.rb +2 -5
- data/lib/ruby2d/text.rb +19 -23
- data/lib/ruby2d/triangle.rb +29 -15
- data/lib/ruby2d/version.rb +1 -1
- data/lib/ruby2d/window.rb +121 -67
- metadata +27 -7
data/ext/ruby2d/ruby2d.c
CHANGED
@@ -1,104 +1,465 @@
|
|
1
|
-
|
1
|
+
// ruby2d.c – Native C extension for Ruby and MRuby
|
2
|
+
|
3
|
+
// Simple 2D includes
|
2
4
|
#include <simple2d.h>
|
3
5
|
|
6
|
+
// Ruby includes
|
7
|
+
#if MRUBY
|
8
|
+
#include <mruby.h>
|
9
|
+
#include <mruby/array.h>
|
10
|
+
#include <mruby/string.h>
|
11
|
+
#include <mruby/variable.h>
|
12
|
+
#include <mruby/numeric.h>
|
13
|
+
#include <mruby/data.h>
|
14
|
+
#include <mruby/irep.h>
|
15
|
+
#else
|
16
|
+
#include <ruby.h>
|
17
|
+
#endif
|
18
|
+
|
19
|
+
// Define Ruby type conversions in MRuby
|
20
|
+
#if MRUBY
|
21
|
+
// C to MRuby types
|
22
|
+
#define INT2FIX(val) (mrb_fixnum_value(val))
|
23
|
+
#define INT2NUM(val) (mrb_fixnum_value((mrb_int)(val)))
|
24
|
+
#define UINT2NUM(val) (INT2NUM((unsigned mrb_int)(val)))
|
25
|
+
#define LL2NUM(val) (INT2NUM(val))
|
26
|
+
#define ULL2NUM(val) (INT2NUM((unsigned __int64)(val)))
|
27
|
+
#define DBL2NUM(val) (mrb_float_value(mrb, (mrb_float)(val)))
|
28
|
+
// MRuby to C types
|
29
|
+
#define TO_PDT(val) ((mrb_type(val) == MRB_TT_FLOAT) ? mrb_float(val) : mrb_int(mrb, (val)))
|
30
|
+
#define FIX2INT(val) (mrb_fixnum(val))
|
31
|
+
#define NUM2INT(val) ((mrb_int)TO_PDT(val))
|
32
|
+
#define NUM2UINT(val) ((unsigned mrb_int)TO_PDT(val))
|
33
|
+
#define NUM2LONG(val) (mrb_int(mrb, (val)))
|
34
|
+
#define NUM2LL(val) ((__int64)(TO_PDT(val)))
|
35
|
+
#define NUM2ULL(val) ((unsigned __int64)(TO_PDT(val)))
|
36
|
+
#define NUM2DBL(val) (mrb_to_flo(mrb, (val)))
|
37
|
+
#define NUM2CHR(val) ((mrb_string_p(val) && (RSTRING_LEN(val)>=1)) ? RSTRING_PTR(val)[0] : (char)(NUM2INT(val) & 0xff))
|
38
|
+
// Memory management
|
39
|
+
#define ALLOC(type) ((type *)mrb_malloc(mrb, sizeof(type)))
|
40
|
+
#define ALLOC_N(type, n) ((type *)mrb_malloc(mrb, sizeof(type) * (n)))
|
41
|
+
#define ALLOCA_N(type, n) ((type *)alloca(sizeof(type) * (n)))
|
42
|
+
#define MEMCMP(p1, p2, type, n) (memcmp((p1), (p2), sizeof(type)*(n)))
|
43
|
+
#endif
|
44
|
+
|
45
|
+
// Define common types and API calls, mapping to both Ruby and MRuby APIs
|
46
|
+
#if MRUBY
|
47
|
+
// MRuby
|
48
|
+
#define R_VAL mrb_value
|
49
|
+
#define R_NIL (mrb_nil_value())
|
50
|
+
#define R_TRUE (mrb_true_value())
|
51
|
+
#define R_FALSE (mrb_false_value())
|
52
|
+
#define R_CLASS struct RClass *
|
53
|
+
#define r_iv_get(self, var) mrb_iv_get(mrb, self, mrb_intern_lit(mrb, var))
|
54
|
+
#define r_iv_set(self, var, val) mrb_iv_set(mrb, self, mrb_intern_lit(mrb, var), val)
|
55
|
+
#define r_funcall(self, method, num_args, ...) mrb_funcall(mrb, self, method, num_args, ##__VA_ARGS__)
|
56
|
+
#define r_str_new(str) mrb_str_new(mrb, str, strlen(str))
|
57
|
+
#define r_test(val) (mrb_test(val) == true)
|
58
|
+
#define r_ary_entry(ary, pos) mrb_ary_entry(ary, pos)
|
59
|
+
#define r_data_wrap_struct(name, data) mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &name##_data_type, data))
|
60
|
+
#define r_data_get_struct(self, var, mrb_type, rb_type, data) Data_Get_Struct(mrb, r_iv_get(self, var), mrb_type, data)
|
61
|
+
#define r_define_module(name) mrb_module_get(mrb, name)
|
62
|
+
#define r_define_class(module, name) mrb_class_get_under(mrb, module, name);
|
63
|
+
#define r_define_method(class, name, function, args) mrb_define_method(mrb, class, name, function, args)
|
64
|
+
#define r_args_none (MRB_ARGS_NONE())
|
65
|
+
#define r_args_req(n) MRB_ARGS_REQ(n)
|
66
|
+
#else
|
67
|
+
// Ruby
|
68
|
+
#define R_VAL VALUE
|
69
|
+
#define R_NIL Qnil
|
70
|
+
#define R_TRUE Qtrue
|
71
|
+
#define R_FALSE Qfalse
|
72
|
+
#define R_CLASS R_VAL
|
73
|
+
#define r_iv_get(self, var) rb_iv_get(self, var)
|
74
|
+
#define r_iv_set(self, var, val) rb_iv_set(self, var, val)
|
75
|
+
#define r_funcall(self, method, num_args, ...) rb_funcall(self, rb_intern(method), num_args, ##__VA_ARGS__)
|
76
|
+
#define r_str_new(str) rb_str_new2(str)
|
77
|
+
#define r_test(val) (val != Qfalse && val != Qnil)
|
78
|
+
#define r_ary_entry(ary, pos) rb_ary_entry(ary, pos)
|
79
|
+
#define r_data_wrap_struct(name, data) Data_Wrap_Struct(rb_cObject, NULL, (free_##name), data)
|
80
|
+
#define r_data_get_struct(self, var, mrb_type, rb_type, data) Data_Get_Struct(r_iv_get(self, var), rb_type, data)
|
81
|
+
#define r_define_module(name) rb_define_module(name)
|
82
|
+
#define r_define_class(module, name) rb_define_class_under(module, name, rb_cObject);
|
83
|
+
#define r_define_method(class, name, function, args) rb_define_method(class, name, function, args)
|
84
|
+
#define r_args_none 0
|
85
|
+
#define r_args_req(n) n
|
86
|
+
#endif
|
87
|
+
|
4
88
|
// @type_id values for rendering
|
5
|
-
#define
|
6
|
-
#define
|
7
|
-
#define
|
8
|
-
#define
|
89
|
+
#define R2D_TRIANGLE 1
|
90
|
+
#define R2D_QUAD 2
|
91
|
+
#define R2D_IMAGE 3
|
92
|
+
#define R2D_SPRITE 4
|
93
|
+
#define R2D_TEXT 5
|
94
|
+
|
95
|
+
// Create the MRuby context
|
96
|
+
#if MRUBY
|
97
|
+
static mrb_state *mrb;
|
98
|
+
#endif
|
9
99
|
|
10
100
|
// Ruby 2D window
|
11
|
-
|
101
|
+
static R_VAL ruby2d_window;
|
12
102
|
|
13
103
|
// Simple 2D window
|
14
|
-
S2D_Window *window;
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
static
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
struct
|
29
|
-
|
30
|
-
};
|
104
|
+
static S2D_Window *window;
|
105
|
+
|
106
|
+
|
107
|
+
// Method signatures and structures for Ruby 2D classes
|
108
|
+
#if MRUBY
|
109
|
+
static void free_image(mrb_state *mrb, void *p_);
|
110
|
+
static const struct mrb_data_type image_data_type = {
|
111
|
+
"image", free_image
|
112
|
+
};
|
113
|
+
static void free_sprite(mrb_state *mrb, void *p_);
|
114
|
+
static const struct mrb_data_type sprite_data_type = {
|
115
|
+
"sprite", free_sprite
|
116
|
+
};
|
117
|
+
static void free_text(mrb_state *mrb, void *p_);
|
118
|
+
static const struct mrb_data_type text_data_type = {
|
119
|
+
"text", free_text
|
120
|
+
};
|
121
|
+
static void free_sound(mrb_state *mrb, void *p_);
|
122
|
+
static const struct mrb_data_type sound_data_type = {
|
123
|
+
"sound", free_sound
|
124
|
+
};
|
125
|
+
static void free_music(mrb_state *mrb, void *p_);
|
126
|
+
static const struct mrb_data_type music_data_type = {
|
127
|
+
"music", free_music
|
128
|
+
};
|
129
|
+
#else
|
130
|
+
static void free_image(S2D_Image *img);
|
131
|
+
static void free_sprite(S2D_Sprite *spr);
|
132
|
+
static void free_text(S2D_Text *txt);
|
133
|
+
static void free_sound(S2D_Sound *snd);
|
134
|
+
static void free_music(S2D_Music *mus);
|
135
|
+
#endif
|
31
136
|
|
32
137
|
|
33
138
|
/*
|
34
|
-
* Function pointer to
|
139
|
+
* Function pointer to free the Simple 2D window
|
35
140
|
*/
|
36
|
-
static void
|
37
|
-
|
141
|
+
static void free_window() {
|
142
|
+
S2D_FreeWindow(window);
|
143
|
+
}
|
144
|
+
|
145
|
+
|
146
|
+
/*
|
147
|
+
* Ruby2D::Image#init
|
148
|
+
* Initialize image structure data
|
149
|
+
*/
|
150
|
+
#if MRUBY
|
151
|
+
static R_VAL ruby2d_image_init(mrb_state* mrb, R_VAL self) {
|
152
|
+
mrb_value path;
|
153
|
+
mrb_get_args(mrb, "o", &path);
|
154
|
+
#else
|
155
|
+
static R_VAL ruby2d_image_init(R_VAL self, R_VAL path) {
|
156
|
+
#endif
|
157
|
+
sprintf(S2D_msg, "Init image: %s", RSTRING_PTR(path));
|
158
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
159
|
+
S2D_Image *img = S2D_CreateImage(RSTRING_PTR(path));
|
160
|
+
r_iv_set(self, "@data", r_data_wrap_struct(image, img));
|
161
|
+
return R_NIL;
|
38
162
|
}
|
39
163
|
|
40
164
|
|
41
165
|
/*
|
42
166
|
* Free image structure attached to Ruby 2D `Image` class
|
43
167
|
*/
|
44
|
-
|
45
|
-
|
46
|
-
|
168
|
+
#if MRUBY
|
169
|
+
static void free_image(mrb_state *mrb, void *p_) {
|
170
|
+
S2D_Image *img = (S2D_Image *)p_;
|
171
|
+
#else
|
172
|
+
static void free_image(S2D_Image *img) {
|
173
|
+
#endif
|
174
|
+
sprintf(S2D_msg, "Free image: %i, %i", img->x, img->y);
|
175
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
176
|
+
S2D_FreeImage(img);
|
47
177
|
}
|
48
178
|
|
49
179
|
|
50
180
|
/*
|
51
|
-
*
|
181
|
+
* Ruby2D::Sprite#init
|
182
|
+
* Initialize sprite structure data
|
52
183
|
*/
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
184
|
+
#if MRUBY
|
185
|
+
static R_VAL ruby2d_sprite_init(mrb_state* mrb, R_VAL self) {
|
186
|
+
mrb_value path;
|
187
|
+
mrb_get_args(mrb, "o", &path);
|
188
|
+
#else
|
189
|
+
static R_VAL ruby2d_sprite_init(R_VAL self, R_VAL path) {
|
190
|
+
#endif
|
191
|
+
sprintf(S2D_msg, "Init sprite: %s", RSTRING_PTR(path));
|
192
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
193
|
+
S2D_Sprite *spr = S2D_CreateSprite(RSTRING_PTR(path));
|
194
|
+
r_iv_set(self, "@data", r_data_wrap_struct(sprite, spr));
|
195
|
+
return R_NIL;
|
57
196
|
}
|
58
197
|
|
59
198
|
|
60
199
|
/*
|
61
|
-
* Free
|
200
|
+
* Free sprite structure attached to Ruby 2D `Sprite` class
|
62
201
|
*/
|
63
|
-
|
64
|
-
|
65
|
-
|
202
|
+
#if MRUBY
|
203
|
+
static void free_sprite(mrb_state *mrb, void *p_) {
|
204
|
+
S2D_Sprite *spr = (S2D_Sprite *)p_;
|
205
|
+
#else
|
206
|
+
static void free_sprite(S2D_Sprite *spr) {
|
207
|
+
#endif
|
208
|
+
sprintf(S2D_msg, "Free sprite: %i, %i", spr->x, spr->y);
|
209
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
210
|
+
S2D_FreeSprite(spr);
|
66
211
|
}
|
67
212
|
|
68
213
|
|
69
214
|
/*
|
215
|
+
* Ruby2D::Text#init
|
70
216
|
* Initialize text structure data
|
71
217
|
*/
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
218
|
+
#if MRUBY
|
219
|
+
static R_VAL ruby2d_text_init(mrb_state* mrb, R_VAL self) {
|
220
|
+
#else
|
221
|
+
static R_VAL ruby2d_text_init(R_VAL self) {
|
222
|
+
#endif
|
223
|
+
sprintf(S2D_msg, "Init text: %s", RSTRING_PTR(r_iv_get(self, "@text")));
|
224
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
225
|
+
|
226
|
+
S2D_Text *txt = S2D_CreateText(
|
227
|
+
RSTRING_PTR(r_iv_get(self, "@font")),
|
228
|
+
RSTRING_PTR(r_iv_get(self, "@text")),
|
229
|
+
NUM2DBL(r_iv_get(self, "@size"))
|
230
|
+
);
|
231
|
+
|
232
|
+
r_iv_set(self, "@data", r_data_wrap_struct(text, txt));
|
233
|
+
return R_NIL;
|
234
|
+
}
|
235
|
+
|
236
|
+
|
237
|
+
/*
|
238
|
+
* Ruby2D::Text#text=
|
239
|
+
*/
|
240
|
+
#if MRUBY
|
241
|
+
static R_VAL ruby2d_text_equals(mrb_state* mrb, R_VAL self) {
|
242
|
+
mrb_value text;
|
243
|
+
mrb_get_args(mrb, "o", &text);
|
244
|
+
#else
|
245
|
+
static R_VAL ruby2d_text_equals(R_VAL self, R_VAL text) {
|
246
|
+
r_iv_set(self, "@text", text);
|
247
|
+
#endif
|
248
|
+
|
249
|
+
// If called before window is shown, return
|
250
|
+
if (!r_test(ruby2d_window)) return R_NIL;
|
251
|
+
|
252
|
+
S2D_Text *txt;
|
253
|
+
r_data_get_struct(self, "@data", &text_data_type, S2D_Text, txt);
|
254
|
+
|
255
|
+
S2D_SetText(txt, RSTRING_PTR(text));
|
256
|
+
return R_NIL;
|
257
|
+
}
|
258
|
+
|
259
|
+
|
260
|
+
/*
|
261
|
+
* Free text structure attached to Ruby 2D `Text` class
|
262
|
+
*/
|
263
|
+
#if MRUBY
|
264
|
+
static void free_text(mrb_state *mrb, void *p_) {
|
265
|
+
S2D_Text *txt = (S2D_Text *)p_;
|
266
|
+
#else
|
267
|
+
static void free_text(S2D_Text *txt) {
|
268
|
+
#endif
|
269
|
+
sprintf(S2D_msg, "Free text: %s", txt->msg);
|
270
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
271
|
+
S2D_FreeText(txt);
|
272
|
+
}
|
273
|
+
|
274
|
+
|
275
|
+
/*
|
276
|
+
* Ruby2D::Sound#init
|
277
|
+
* Initialize sound structure data
|
278
|
+
*/
|
279
|
+
#if MRUBY
|
280
|
+
static R_VAL ruby2d_sound_init(mrb_state* mrb, R_VAL self) {
|
281
|
+
mrb_value path;
|
282
|
+
mrb_get_args(mrb, "o", &path);
|
283
|
+
#else
|
284
|
+
static R_VAL ruby2d_sound_init(R_VAL self, R_VAL path) {
|
285
|
+
#endif
|
286
|
+
sprintf(S2D_msg, "Init sound: %s", RSTRING_PTR(path));
|
287
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
288
|
+
S2D_Sound *snd = S2D_CreateSound(RSTRING_PTR(path));
|
289
|
+
r_iv_set(self, "@data", r_data_wrap_struct(sound, snd));
|
290
|
+
return R_NIL;
|
291
|
+
}
|
292
|
+
|
293
|
+
|
294
|
+
/*
|
295
|
+
* Ruby2D::Sound#play
|
296
|
+
*/
|
297
|
+
#if MRUBY
|
298
|
+
static R_VAL ruby2d_sound_play(mrb_state* mrb, R_VAL self) {
|
299
|
+
#else
|
300
|
+
static R_VAL ruby2d_sound_play(R_VAL self) {
|
301
|
+
#endif
|
302
|
+
S2D_Sound *snd;
|
303
|
+
r_data_get_struct(self, "@data", &sound_data_type, S2D_Sound, snd);
|
304
|
+
S2D_PlaySound(snd);
|
305
|
+
return R_NIL;
|
306
|
+
}
|
307
|
+
|
308
|
+
|
309
|
+
/*
|
310
|
+
* Free sound structure attached to Ruby 2D `Sound` class
|
311
|
+
*/
|
312
|
+
#if MRUBY
|
313
|
+
static void free_sound(mrb_state *mrb, void *p_) {
|
314
|
+
S2D_Sound *snd = (S2D_Sound *)p_;
|
315
|
+
#else
|
316
|
+
static void free_sound(S2D_Sound *snd) {
|
317
|
+
#endif
|
318
|
+
sprintf(S2D_msg, "Free sound");
|
319
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
320
|
+
S2D_FreeSound(snd);
|
321
|
+
}
|
322
|
+
|
323
|
+
|
324
|
+
/*
|
325
|
+
* Ruby2D::Music#init
|
326
|
+
* Initialize music structure data
|
327
|
+
*/
|
328
|
+
#if MRUBY
|
329
|
+
static R_VAL ruby2d_music_init(mrb_state* mrb, R_VAL self) {
|
330
|
+
mrb_value path;
|
331
|
+
mrb_get_args(mrb, "o", &path);
|
332
|
+
#else
|
333
|
+
static R_VAL ruby2d_music_init(R_VAL self, R_VAL path) {
|
334
|
+
#endif
|
335
|
+
sprintf(S2D_msg, "Init music: %s", RSTRING_PTR(path));
|
336
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
337
|
+
S2D_Music *mus = S2D_CreateMusic(RSTRING_PTR(path));
|
338
|
+
r_iv_set(self, "@data", r_data_wrap_struct(music, mus));
|
339
|
+
return R_NIL;
|
340
|
+
}
|
341
|
+
|
342
|
+
|
343
|
+
/*
|
344
|
+
* Ruby2D::Music#play
|
345
|
+
*/
|
346
|
+
#if MRUBY
|
347
|
+
static R_VAL ruby2d_music_play(mrb_state* mrb, R_VAL self) {
|
348
|
+
#else
|
349
|
+
static R_VAL ruby2d_music_play(R_VAL self) {
|
350
|
+
#endif
|
351
|
+
S2D_Music *mus;
|
352
|
+
r_data_get_struct(self, "@data", &music_data_type, S2D_Music, mus);
|
353
|
+
S2D_PlayMusic(mus, r_test(r_iv_get(self, "@loop")));
|
354
|
+
return R_NIL;
|
355
|
+
}
|
356
|
+
|
357
|
+
|
358
|
+
/*
|
359
|
+
* Ruby2D::Music#pause
|
360
|
+
*/
|
361
|
+
#if MRUBY
|
362
|
+
static R_VAL ruby2d_music_pause(mrb_state* mrb, R_VAL self) {
|
363
|
+
#else
|
364
|
+
static R_VAL ruby2d_music_pause(R_VAL self) {
|
365
|
+
#endif
|
366
|
+
S2D_PauseMusic();
|
367
|
+
return R_NIL;
|
368
|
+
}
|
369
|
+
|
370
|
+
|
371
|
+
/*
|
372
|
+
* Ruby2D::Music#resume
|
373
|
+
*/
|
374
|
+
#if MRUBY
|
375
|
+
static R_VAL ruby2d_music_resume(mrb_state* mrb, R_VAL self) {
|
376
|
+
#else
|
377
|
+
static R_VAL ruby2d_music_resume(R_VAL self) {
|
378
|
+
#endif
|
379
|
+
S2D_ResumeMusic();
|
380
|
+
return R_NIL;
|
381
|
+
}
|
382
|
+
|
383
|
+
|
384
|
+
/*
|
385
|
+
* Ruby2D::Music#stop
|
386
|
+
*/
|
387
|
+
#if MRUBY
|
388
|
+
static R_VAL ruby2d_music_stop(mrb_state* mrb, R_VAL self) {
|
389
|
+
#else
|
390
|
+
static R_VAL ruby2d_music_stop(R_VAL self) {
|
391
|
+
#endif
|
392
|
+
S2D_StopMusic();
|
393
|
+
return R_NIL;
|
394
|
+
}
|
395
|
+
|
396
|
+
|
397
|
+
/*
|
398
|
+
* Ruby2D::Music#fadeout
|
399
|
+
*/
|
400
|
+
#if MRUBY
|
401
|
+
static R_VAL ruby2d_music_fadeout(mrb_state* mrb, R_VAL self) {
|
402
|
+
mrb_value ms;
|
403
|
+
mrb_get_args(mrb, "o", &ms);
|
404
|
+
#else
|
405
|
+
static R_VAL ruby2d_music_fadeout(R_VAL self, R_VAL ms) {
|
406
|
+
#endif
|
407
|
+
S2D_FadeOutMusic(NUM2INT(ms));
|
408
|
+
return R_NIL;
|
409
|
+
}
|
410
|
+
|
411
|
+
|
412
|
+
/*
|
413
|
+
* Free sound structure attached to Ruby 2D `Sound` class
|
414
|
+
*/
|
415
|
+
#if MRUBY
|
416
|
+
static void free_music(mrb_state *mrb, void *p_) {
|
417
|
+
S2D_Music *mus = (S2D_Music *)p_;
|
418
|
+
#else
|
419
|
+
static void free_music(S2D_Music *mus) {
|
420
|
+
#endif
|
421
|
+
sprintf(S2D_msg, "Free music");
|
422
|
+
S2D_Log(S2D_msg, S2D_INFO);
|
423
|
+
S2D_FreeMusic(mus);
|
76
424
|
}
|
77
425
|
|
78
426
|
|
79
427
|
/*
|
80
428
|
* Simple 2D `on_key` input callback function
|
81
429
|
*/
|
82
|
-
void on_key(const char *key) {
|
83
|
-
|
430
|
+
static void on_key(S2D_Event e, const char *key) {
|
431
|
+
switch (e) {
|
432
|
+
case S2D_KEYDOWN:
|
433
|
+
r_funcall(ruby2d_window, "key_down_callback", 1, r_str_new(key));
|
434
|
+
break;
|
435
|
+
|
436
|
+
case S2D_KEY:
|
437
|
+
r_funcall(ruby2d_window, "key_callback", 1, r_str_new(key));
|
438
|
+
break;
|
439
|
+
|
440
|
+
case S2D_KEYUP:
|
441
|
+
r_funcall(ruby2d_window, "key_up_callback", 1, r_str_new(key));
|
442
|
+
break;
|
443
|
+
}
|
84
444
|
}
|
85
445
|
|
86
446
|
|
87
447
|
/*
|
88
|
-
* Simple 2D `
|
448
|
+
* Simple 2D `on_mouse` input callback function
|
89
449
|
*/
|
90
|
-
void
|
91
|
-
|
450
|
+
void on_mouse(int x, int y) {
|
451
|
+
r_funcall(ruby2d_window, "mouse_callback", 3, r_str_new("any"), INT2NUM(x), INT2NUM(y));
|
92
452
|
}
|
93
453
|
|
94
454
|
|
95
455
|
/*
|
96
456
|
* Simple 2D `on_controller` input callback function
|
97
457
|
*/
|
98
|
-
void on_controller(bool is_axis, int axis, int val, bool is_btn, int btn) {
|
99
|
-
|
100
|
-
|
101
|
-
|
458
|
+
static void on_controller(int which, bool is_axis, int axis, int val, bool is_btn, int btn, bool pressed) {
|
459
|
+
r_funcall(ruby2d_window, "controller_callback", 7,
|
460
|
+
INT2NUM(which),
|
461
|
+
is_axis ? R_TRUE : R_FALSE, INT2NUM(axis), INT2NUM(val),
|
462
|
+
is_btn ? R_TRUE : R_FALSE, INT2NUM(btn), pressed ? R_TRUE : R_FALSE
|
102
463
|
);
|
103
464
|
}
|
104
465
|
|
@@ -106,137 +467,171 @@ void on_controller(bool is_axis, int axis, int val, bool is_btn, int btn) {
|
|
106
467
|
/*
|
107
468
|
* Simple 2D `update` callback function
|
108
469
|
*/
|
109
|
-
void update() {
|
470
|
+
static void update() {
|
110
471
|
|
111
472
|
// Set the cursor
|
112
|
-
|
113
|
-
|
473
|
+
r_iv_set(ruby2d_window, "@mouse_x", INT2NUM(window->mouse.x));
|
474
|
+
r_iv_set(ruby2d_window, "@mouse_y", INT2NUM(window->mouse.y));
|
475
|
+
|
476
|
+
// Store frames
|
477
|
+
r_iv_set(ruby2d_window, "@frames", DBL2NUM(window->frames));
|
114
478
|
|
115
479
|
// Store frame rate
|
116
|
-
|
480
|
+
r_iv_set(ruby2d_window, "@fps", DBL2NUM(window->fps));
|
117
481
|
|
118
482
|
// Call update proc, `window.update`
|
119
|
-
|
483
|
+
r_funcall(ruby2d_window, "update_callback", 0);
|
120
484
|
}
|
121
485
|
|
122
486
|
|
123
487
|
/*
|
124
488
|
* Simple 2D `render` callback function
|
125
489
|
*/
|
126
|
-
void render() {
|
490
|
+
static void render() {
|
491
|
+
|
492
|
+
// Set background color
|
493
|
+
R_VAL bc = r_iv_get(ruby2d_window, "@background");
|
494
|
+
window->background.r = NUM2DBL(r_iv_get(bc, "@r"));
|
495
|
+
window->background.g = NUM2DBL(r_iv_get(bc, "@g"));
|
496
|
+
window->background.b = NUM2DBL(r_iv_get(bc, "@b"));
|
497
|
+
window->background.a = NUM2DBL(r_iv_get(bc, "@a"));
|
127
498
|
|
128
499
|
// Read window objects
|
129
|
-
|
130
|
-
int num_objects = NUM2INT(
|
500
|
+
R_VAL objects = r_iv_get(ruby2d_window, "@objects");
|
501
|
+
int num_objects = NUM2INT(r_funcall(objects, "length", 0));
|
131
502
|
|
132
503
|
// Switch on each object type
|
133
504
|
for (int i = 0; i < num_objects; ++i) {
|
134
505
|
|
135
|
-
|
136
|
-
int type_id = NUM2INT(
|
506
|
+
R_VAL el = r_ary_entry(objects, i);
|
507
|
+
int type_id = NUM2INT(r_iv_get(el, "@type_id"));
|
137
508
|
|
138
509
|
// Switch on the object's type_id
|
139
510
|
switch(type_id) {
|
140
511
|
|
141
|
-
case
|
142
|
-
|
143
|
-
|
144
|
-
|
512
|
+
case R2D_TRIANGLE: {
|
513
|
+
R_VAL c1 = r_iv_get(el, "@c1");
|
514
|
+
R_VAL c2 = r_iv_get(el, "@c2");
|
515
|
+
R_VAL c3 = r_iv_get(el, "@c3");
|
145
516
|
|
146
517
|
S2D_DrawTriangle(
|
147
|
-
NUM2DBL(
|
148
|
-
NUM2DBL(
|
149
|
-
NUM2DBL(
|
150
|
-
NUM2DBL(
|
151
|
-
NUM2DBL(
|
152
|
-
NUM2DBL(
|
518
|
+
NUM2DBL(r_iv_get(el, "@x1")),
|
519
|
+
NUM2DBL(r_iv_get(el, "@y1")),
|
520
|
+
NUM2DBL(r_iv_get(c1, "@r")),
|
521
|
+
NUM2DBL(r_iv_get(c1, "@g")),
|
522
|
+
NUM2DBL(r_iv_get(c1, "@b")),
|
523
|
+
NUM2DBL(r_iv_get(c1, "@a")),
|
153
524
|
|
154
|
-
NUM2DBL(
|
155
|
-
NUM2DBL(
|
156
|
-
NUM2DBL(
|
157
|
-
NUM2DBL(
|
158
|
-
NUM2DBL(
|
159
|
-
NUM2DBL(
|
525
|
+
NUM2DBL(r_iv_get(el, "@x2")),
|
526
|
+
NUM2DBL(r_iv_get(el, "@y2")),
|
527
|
+
NUM2DBL(r_iv_get(c2, "@r")),
|
528
|
+
NUM2DBL(r_iv_get(c2, "@g")),
|
529
|
+
NUM2DBL(r_iv_get(c2, "@b")),
|
530
|
+
NUM2DBL(r_iv_get(c2, "@a")),
|
160
531
|
|
161
|
-
NUM2DBL(
|
162
|
-
NUM2DBL(
|
163
|
-
NUM2DBL(
|
164
|
-
NUM2DBL(
|
165
|
-
NUM2DBL(
|
166
|
-
NUM2DBL(
|
532
|
+
NUM2DBL(r_iv_get(el, "@x3")),
|
533
|
+
NUM2DBL(r_iv_get(el, "@y3")),
|
534
|
+
NUM2DBL(r_iv_get(c3, "@r")),
|
535
|
+
NUM2DBL(r_iv_get(c3, "@g")),
|
536
|
+
NUM2DBL(r_iv_get(c3, "@b")),
|
537
|
+
NUM2DBL(r_iv_get(c3, "@a"))
|
167
538
|
);
|
168
539
|
}
|
169
540
|
break;
|
170
541
|
|
171
|
-
case
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
542
|
+
case R2D_QUAD: {
|
543
|
+
R_VAL c1 = r_iv_get(el, "@c1");
|
544
|
+
R_VAL c2 = r_iv_get(el, "@c2");
|
545
|
+
R_VAL c3 = r_iv_get(el, "@c3");
|
546
|
+
R_VAL c4 = r_iv_get(el, "@c4");
|
176
547
|
|
177
548
|
S2D_DrawQuad(
|
178
|
-
NUM2DBL(
|
179
|
-
NUM2DBL(
|
180
|
-
NUM2DBL(
|
181
|
-
NUM2DBL(
|
182
|
-
NUM2DBL(
|
183
|
-
NUM2DBL(
|
184
|
-
|
185
|
-
NUM2DBL(
|
186
|
-
NUM2DBL(
|
187
|
-
NUM2DBL(
|
188
|
-
NUM2DBL(
|
189
|
-
NUM2DBL(
|
190
|
-
NUM2DBL(
|
191
|
-
|
192
|
-
NUM2DBL(
|
193
|
-
NUM2DBL(
|
194
|
-
NUM2DBL(
|
195
|
-
NUM2DBL(
|
196
|
-
NUM2DBL(
|
197
|
-
NUM2DBL(
|
198
|
-
|
199
|
-
NUM2DBL(
|
200
|
-
NUM2DBL(
|
201
|
-
NUM2DBL(
|
202
|
-
NUM2DBL(
|
203
|
-
NUM2DBL(
|
204
|
-
NUM2DBL(
|
549
|
+
NUM2DBL(r_iv_get(el, "@x1")),
|
550
|
+
NUM2DBL(r_iv_get(el, "@y1")),
|
551
|
+
NUM2DBL(r_iv_get(c1, "@r")),
|
552
|
+
NUM2DBL(r_iv_get(c1, "@g")),
|
553
|
+
NUM2DBL(r_iv_get(c1, "@b")),
|
554
|
+
NUM2DBL(r_iv_get(c1, "@a")),
|
555
|
+
|
556
|
+
NUM2DBL(r_iv_get(el, "@x2")),
|
557
|
+
NUM2DBL(r_iv_get(el, "@y2")),
|
558
|
+
NUM2DBL(r_iv_get(c2, "@r")),
|
559
|
+
NUM2DBL(r_iv_get(c2, "@g")),
|
560
|
+
NUM2DBL(r_iv_get(c2, "@b")),
|
561
|
+
NUM2DBL(r_iv_get(c2, "@a")),
|
562
|
+
|
563
|
+
NUM2DBL(r_iv_get(el, "@x3")),
|
564
|
+
NUM2DBL(r_iv_get(el, "@y3")),
|
565
|
+
NUM2DBL(r_iv_get(c3, "@r")),
|
566
|
+
NUM2DBL(r_iv_get(c3, "@g")),
|
567
|
+
NUM2DBL(r_iv_get(c3, "@b")),
|
568
|
+
NUM2DBL(r_iv_get(c3, "@a")),
|
569
|
+
|
570
|
+
NUM2DBL(r_iv_get(el, "@x4")),
|
571
|
+
NUM2DBL(r_iv_get(el, "@y4")),
|
572
|
+
NUM2DBL(r_iv_get(c4, "@r")),
|
573
|
+
NUM2DBL(r_iv_get(c4, "@g")),
|
574
|
+
NUM2DBL(r_iv_get(c4, "@b")),
|
575
|
+
NUM2DBL(r_iv_get(c4, "@a"))
|
205
576
|
);
|
206
577
|
}
|
207
578
|
break;
|
208
579
|
|
209
|
-
case
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
580
|
+
case R2D_IMAGE: {
|
581
|
+
S2D_Image *img;
|
582
|
+
r_data_get_struct(el, "@data", &image_data_type, S2D_Image, img);
|
583
|
+
|
584
|
+
img->x = NUM2DBL(r_iv_get(el, "@x"));
|
585
|
+
img->y = NUM2DBL(r_iv_get(el, "@y"));
|
586
|
+
|
587
|
+
R_VAL w = r_iv_get(el, "@width");
|
588
|
+
R_VAL h = r_iv_get(el, "@height");
|
589
|
+
if (r_test(w)) img->width = NUM2INT(w);
|
590
|
+
if (r_test(h)) img->height = NUM2INT(h);
|
591
|
+
|
592
|
+
R_VAL c = r_iv_get(el, "@color");
|
593
|
+
img->color.r = NUM2DBL(r_iv_get(c, "@r"));
|
594
|
+
img->color.g = NUM2DBL(r_iv_get(c, "@g"));
|
595
|
+
img->color.b = NUM2DBL(r_iv_get(c, "@b"));
|
596
|
+
img->color.a = NUM2DBL(r_iv_get(c, "@a"));
|
597
|
+
|
598
|
+
S2D_DrawImage(img);
|
599
|
+
}
|
600
|
+
break;
|
601
|
+
|
602
|
+
case R2D_SPRITE: {
|
603
|
+
S2D_Sprite *spr;
|
604
|
+
r_data_get_struct(el, "@data", &sprite_data_type, S2D_Sprite, spr);
|
214
605
|
|
215
|
-
|
216
|
-
|
606
|
+
spr->x = NUM2DBL(r_iv_get(el, "@x"));
|
607
|
+
spr->y = NUM2DBL(r_iv_get(el, "@y"));
|
217
608
|
|
218
|
-
|
219
|
-
|
220
|
-
|
609
|
+
S2D_ClipSprite(
|
610
|
+
spr,
|
611
|
+
NUM2INT(r_iv_get(el, "@clip_x")),
|
612
|
+
NUM2INT(r_iv_get(el, "@clip_y")),
|
613
|
+
NUM2INT(r_iv_get(el, "@clip_w")),
|
614
|
+
NUM2INT(r_iv_get(el, "@clip_h"))
|
615
|
+
);
|
616
|
+
|
617
|
+
S2D_DrawSprite(spr);
|
221
618
|
}
|
222
619
|
break;
|
223
620
|
|
224
|
-
case
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
);
|
231
|
-
rb_iv_set(el, "@data", data);
|
232
|
-
}
|
621
|
+
case R2D_TEXT: {
|
622
|
+
S2D_Text *txt;
|
623
|
+
r_data_get_struct(el, "@data", &text_data_type, S2D_Text, txt);
|
624
|
+
|
625
|
+
txt->x = NUM2DBL(r_iv_get(el, "@x"));
|
626
|
+
txt->y = NUM2DBL(r_iv_get(el, "@y"));
|
233
627
|
|
234
|
-
|
235
|
-
|
628
|
+
R_VAL c = r_iv_get(el, "@color");
|
629
|
+
txt->color.r = NUM2DBL(r_iv_get(c, "@r"));
|
630
|
+
txt->color.g = NUM2DBL(r_iv_get(c, "@g"));
|
631
|
+
txt->color.b = NUM2DBL(r_iv_get(c, "@b"));
|
632
|
+
txt->color.a = NUM2DBL(r_iv_get(c, "@a"));
|
236
633
|
|
237
|
-
|
238
|
-
data->txt->y = NUM2DBL(rb_iv_get(el, "@y"));
|
239
|
-
S2D_DrawText(data->txt);
|
634
|
+
S2D_DrawText(txt);
|
240
635
|
}
|
241
636
|
break;
|
242
637
|
}
|
@@ -247,43 +642,159 @@ void render() {
|
|
247
642
|
/*
|
248
643
|
* Ruby2D::Window#show
|
249
644
|
*/
|
250
|
-
|
251
|
-
|
645
|
+
#if MRUBY
|
646
|
+
static R_VAL ruby2d_show(mrb_state* mrb, R_VAL self) {
|
647
|
+
#else
|
648
|
+
static R_VAL ruby2d_show(R_VAL self) {
|
649
|
+
#endif
|
650
|
+
ruby2d_window = self;
|
252
651
|
|
253
|
-
|
254
|
-
|
255
|
-
|
652
|
+
if (r_test(r_iv_get(self, "@diagnostics"))) {
|
653
|
+
S2D_Diagnostics(true);
|
654
|
+
}
|
655
|
+
|
656
|
+
// Get window attributes
|
657
|
+
char *title = RSTRING_PTR(r_iv_get(self, "@title"));
|
658
|
+
int width = NUM2INT(r_iv_get(self, "@width"));
|
659
|
+
int height = NUM2INT(r_iv_get(self, "@height"));
|
256
660
|
int flags = 0;
|
257
661
|
|
662
|
+
// Get window flags
|
663
|
+
if (r_test(r_iv_get(self, "@resizable"))) {
|
664
|
+
flags = flags | S2D_RESIZABLE;
|
665
|
+
}
|
666
|
+
if (r_test(r_iv_get(self, "@borderless"))) {
|
667
|
+
flags = flags | S2D_BORDERLESS;
|
668
|
+
}
|
669
|
+
if (r_test(r_iv_get(self, "@fullscreen"))) {
|
670
|
+
flags = flags | S2D_FULLSCREEN;
|
671
|
+
}
|
672
|
+
if (r_test(r_iv_get(self, "@highdpi"))) {
|
673
|
+
flags = flags | S2D_HIGHDPI;
|
674
|
+
}
|
675
|
+
|
676
|
+
// Check viewport size and set
|
677
|
+
|
678
|
+
R_VAL vp_w = r_iv_get(self, "@viewport_width");
|
679
|
+
int viewport_width = r_test(vp_w) ? NUM2INT(vp_w) : width;
|
680
|
+
|
681
|
+
R_VAL vp_h = r_iv_get(self, "@viewport_height");
|
682
|
+
int viewport_height = r_test(vp_h) ? NUM2INT(vp_h) : height;
|
683
|
+
|
684
|
+
// Create and show window
|
685
|
+
|
258
686
|
window = S2D_CreateWindow(
|
259
687
|
title, width, height, update, render, flags
|
260
688
|
);
|
261
689
|
|
262
|
-
window->
|
263
|
-
window->
|
264
|
-
window->
|
690
|
+
window->viewport.width = viewport_width;
|
691
|
+
window->viewport.height = viewport_height;
|
692
|
+
window->on_key = on_key;
|
693
|
+
window->on_mouse = on_mouse;
|
694
|
+
window->on_controller = on_controller;
|
265
695
|
|
266
696
|
S2D_Show(window);
|
267
697
|
|
268
|
-
atexit(
|
269
|
-
return
|
698
|
+
atexit(free_window);
|
699
|
+
return R_NIL;
|
700
|
+
}
|
701
|
+
|
702
|
+
|
703
|
+
/*
|
704
|
+
* Ruby2D::Window#close
|
705
|
+
*/
|
706
|
+
static R_VAL ruby2d_close() {
|
707
|
+
S2D_Close(window);
|
708
|
+
return R_NIL;
|
270
709
|
}
|
271
710
|
|
272
711
|
|
712
|
+
#if MRUBY
|
713
|
+
/*
|
714
|
+
* MRuby entry point
|
715
|
+
*/
|
716
|
+
int main(void) {
|
717
|
+
// Open the MRuby environment
|
718
|
+
mrb = mrb_open();
|
719
|
+
if (!mrb) { /* handle error */ }
|
720
|
+
|
721
|
+
// Load the Ruby 2D library
|
722
|
+
mrb_load_irep(mrb, ruby2d_lib);
|
723
|
+
#else
|
273
724
|
/*
|
274
725
|
* Ruby C extension init
|
275
726
|
*/
|
276
727
|
void Init_ruby2d() {
|
728
|
+
#endif
|
277
729
|
|
278
730
|
// Ruby2D
|
279
|
-
ruby2d_module =
|
731
|
+
R_CLASS ruby2d_module = r_define_module("Ruby2D");
|
732
|
+
|
733
|
+
// Ruby2D::Image
|
734
|
+
R_CLASS ruby2d_image_class = r_define_class(ruby2d_module, "Image");
|
735
|
+
|
736
|
+
// Ruby2D::Image#init
|
737
|
+
r_define_method(ruby2d_image_class, "init", ruby2d_image_init, r_args_req(1));
|
738
|
+
|
739
|
+
// Ruby2D::Sprite
|
740
|
+
R_CLASS ruby2d_sprite_class = r_define_class(ruby2d_module, "Sprite");
|
741
|
+
|
742
|
+
// Ruby2D::Sprite#init
|
743
|
+
r_define_method(ruby2d_sprite_class, "init", ruby2d_sprite_init, r_args_req(1));
|
744
|
+
|
745
|
+
// Ruby2D::Text
|
746
|
+
R_CLASS ruby2d_text_class = r_define_class(ruby2d_module, "Text");
|
747
|
+
|
748
|
+
// Ruby2D::Text#init
|
749
|
+
r_define_method(ruby2d_text_class, "init", ruby2d_text_init, r_args_none);
|
750
|
+
|
751
|
+
// Ruby2D::Text#text=
|
752
|
+
r_define_method(ruby2d_text_class, "text=", ruby2d_text_equals, r_args_req(1));
|
753
|
+
|
754
|
+
// Ruby2D::Sound
|
755
|
+
R_CLASS ruby2d_sound_class = r_define_class(ruby2d_module, "Sound");
|
756
|
+
|
757
|
+
// Ruby2D::Sound#init
|
758
|
+
r_define_method(ruby2d_sound_class, "init", ruby2d_sound_init, r_args_req(1));
|
759
|
+
|
760
|
+
// Ruby2D::Sound#play
|
761
|
+
r_define_method(ruby2d_sound_class, "play", ruby2d_sound_play, r_args_none);
|
762
|
+
|
763
|
+
// Ruby2D::Music
|
764
|
+
R_CLASS ruby2d_music_class = r_define_class(ruby2d_module, "Music");
|
765
|
+
|
766
|
+
// Ruby2D::Music#init
|
767
|
+
r_define_method(ruby2d_music_class, "init", ruby2d_music_init, r_args_req(1));
|
768
|
+
|
769
|
+
// Ruby2D::Music#play
|
770
|
+
r_define_method(ruby2d_music_class, "play", ruby2d_music_play, r_args_none);
|
771
|
+
|
772
|
+
// Ruby2D::Music#pause
|
773
|
+
r_define_method(ruby2d_music_class, "pause", ruby2d_music_pause, r_args_none);
|
774
|
+
|
775
|
+
// Ruby2D::Music#resume
|
776
|
+
r_define_method(ruby2d_music_class, "resume", ruby2d_music_resume, r_args_none);
|
777
|
+
|
778
|
+
// Ruby2D::Music#stop
|
779
|
+
r_define_method(ruby2d_music_class, "stop", ruby2d_music_stop, r_args_none);
|
780
|
+
|
781
|
+
// Ruby2D::Music#fadeout
|
782
|
+
r_define_method(ruby2d_music_class, "fadeout", ruby2d_music_fadeout, r_args_req(1));
|
280
783
|
|
281
784
|
// Ruby2D::Window
|
282
|
-
|
785
|
+
R_CLASS ruby2d_window_class = r_define_class(ruby2d_module, "Window");
|
283
786
|
|
284
787
|
// Ruby2D::Window#show
|
285
|
-
|
788
|
+
r_define_method(ruby2d_window_class, "show", ruby2d_show, r_args_none);
|
789
|
+
|
790
|
+
// Ruby2D::Window#close
|
791
|
+
r_define_method(ruby2d_window_class, "close", ruby2d_close, r_args_none);
|
792
|
+
|
793
|
+
#if MRUBY
|
794
|
+
// Load the Ruby 2D app
|
795
|
+
mrb_load_irep(mrb, ruby2d_app);
|
286
796
|
|
287
|
-
//
|
288
|
-
|
797
|
+
// Close the MRuby environment
|
798
|
+
mrb_close(mrb);
|
799
|
+
#endif
|
289
800
|
}
|