ruby2d 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/ruby2d/gles.c CHANGED
@@ -202,40 +202,22 @@ void R2D_GLES_DrawTriangle(GLfloat x1, GLfloat y1,
202
202
 
203
203
 
204
204
  /*
205
- * Draw a texture
205
+ * Draw a texture (New method with vertices pre-calculated)
206
206
  */
207
- static void R2D_GLES_DrawTexture(int x, int y, int w, int h,
208
- GLfloat angle, GLfloat rx, GLfloat ry,
209
- GLfloat r, GLfloat g, GLfloat b, GLfloat a,
210
- GLfloat tx1, GLfloat ty1, GLfloat tx2, GLfloat ty2,
211
- GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4,
212
- GLuint texture_id) {
213
-
214
- R2D_GL_Point v1 = { .x = x, .y = y };
215
- R2D_GL_Point v2 = { .x = x + w, .y = y };
216
- R2D_GL_Point v3 = { .x = x + w, .y = y + h };
217
- R2D_GL_Point v4 = { .x = x, .y = y + h };
218
-
219
- // Rotate vertices
220
- if (angle != 0) {
221
- v1 = R2D_RotatePoint(v1, angle, rx, ry);
222
- v2 = R2D_RotatePoint(v2, angle, rx, ry);
223
- v3 = R2D_RotatePoint(v3, angle, rx, ry);
224
- v4 = R2D_RotatePoint(v4, angle, rx, ry);
225
- }
226
-
207
+ void R2D_GLES_DrawTexture(GLfloat coordinates[], GLfloat texture_coordinates[], GLfloat color[], int texture_id);
227
208
  GLfloat vertices[] =
228
209
  // x, y coords | x, y texture coords
229
- { v1.x, v1.y, 0.f, tx1, ty1,
230
- v2.x, v2.y, 0.f, tx2, ty2,
231
- v3.x, v3.y, 0.f, tx3, ty3,
232
- v4.x, v4.y, 0.f, tx4, ty4 };
210
+ {
211
+ coordinates[0], coordinates[1], 0.f, texture_coordinates[0], texture_coordinates[1],
212
+ coordinates[2], coordinates[3], 0.f, texture_coordinates[2], texture_coordinates[3],
213
+ coordinates[4], coordinates[5], 0.f, texture_coordinates[4], texture_coordinates[5],
214
+ coordinates[6], coordinates[7], 0.f, texture_coordinates[6], texture_coordinates[7] };
233
215
 
234
216
  GLfloat colors[] =
235
- { r, g, b, a,
236
- r, g, b, a,
237
- r, g, b, a,
238
- r, g, b, a };
217
+ { color[0], color[1], color[2], color[3],
218
+ color[0], color[1], color[2], color[3],
219
+ color[0], color[1], color[2], color[3],
220
+ color[0], color[1], color[2], color[3] };
239
221
 
240
222
  glUseProgram(texShaderProgram);
241
223
 
@@ -264,60 +246,4 @@ static void R2D_GLES_DrawTexture(int x, int y, int w, int h,
264
246
  }
265
247
 
266
248
 
267
- /*
268
- * Draw image
269
- */
270
- void R2D_GLES_DrawImage(R2D_Image *img) {
271
- R2D_GLES_DrawTexture(
272
- img->x, img->y, img->width, img->height,
273
- img->rotate, img->rx, img->ry,
274
- img->color.r, img->color.g, img->color.b, img->color.a,
275
- 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 1.f,
276
- img->texture_id
277
- );
278
- }
279
-
280
-
281
- /*
282
- * Draw sprite
283
- */
284
- void R2D_GLES_DrawSprite(R2D_Sprite *spr) {
285
- R2D_GLES_DrawTexture(
286
- spr->x, spr->y, spr->width, spr->height,
287
- spr->rotate, spr->rx, spr->ry,
288
- spr->color.r, spr->color.g, spr->color.b, spr->color.a,
289
- spr->tx1, spr->ty1, spr->tx2, spr->ty2, spr->tx3, spr->ty3, spr->tx4, spr->ty4,
290
- spr->img->texture_id
291
- );
292
- }
293
-
294
-
295
- /*
296
- * Draw a tile
297
- */
298
- void R2D_GLES_DrawTile(R2D_Image *img, int x, int y, int tw, int th, GLfloat tx1, GLfloat ty1, GLfloat tx2,
299
- GLfloat ty2, GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4) {
300
- R2D_GLES_DrawTexture(
301
- x, y, tw, th,
302
- img->rotate, img->rx, img->ry,
303
- img->color.r, img->color.g, img->color.b, img->color.a,
304
- tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4,
305
- img->texture_id
306
- );
307
- }
308
-
309
-
310
- /*
311
- * Draw text
312
- */
313
- void R2D_GLES_DrawText(R2D_Text *txt) {
314
- R2D_GLES_DrawTexture(
315
- txt->x, txt->y, txt->width, txt->height,
316
- txt->rotate, txt->rx, txt->ry,
317
- txt->color.r, txt->color.g, txt->color.b, txt->color.a,
318
- 0.f, 0.f, 1.f, 0.f, 1.f, 1.f, 0.f, 1.f,
319
- txt->texture_id
320
- );
321
- }
322
-
323
249
  #endif
data/ext/ruby2d/image.c CHANGED
@@ -3,75 +3,39 @@
3
3
  #include "ruby2d.h"
4
4
 
5
5
 
6
- /*
7
- * Create an image, given a file path
8
- */
9
- R2D_Image *R2D_CreateImage(const char *path) {
6
+ SDL_Surface *R2D_CreateImageSurface(const char *path) {
10
7
  R2D_Init();
11
8
 
12
9
  // Check if image file exists
13
10
  if (!R2D_FileExists(path)) {
14
- R2D_Error("R2D_CreateImage", "Image file `%s` not found", path);
15
- return NULL;
16
- }
17
-
18
- // Allocate the image structure
19
- R2D_Image *img = (R2D_Image *) malloc(sizeof(R2D_Image));
20
- if (!img) {
21
- R2D_Error("R2D_CreateImage", "Out of memory!");
11
+ R2D_Error("R2D_CreateImageSurface", "Image file `%s` not found", path);
22
12
  return NULL;
23
13
  }
24
14
 
25
15
  // Load image from file as SDL_Surface
26
- img->surface = IMG_Load(path);
27
- if (!img->surface) {
28
- R2D_Error("IMG_Load", IMG_GetError());
29
- free(img);
30
- return NULL;
31
- }
16
+ SDL_Surface *surface = IMG_Load(path);
32
17
 
33
- int bits_per_color = img->surface->format->Amask == 0 ?
34
- img->surface->format->BitsPerPixel / 3 :
35
- img->surface->format->BitsPerPixel / 4;
18
+ int bits_per_color = surface->format->Amask == 0 ?
19
+ surface->format->BitsPerPixel / 3 :
20
+ surface->format->BitsPerPixel / 4;
36
21
 
37
22
  if (bits_per_color < 8) {
38
23
  R2D_Log(R2D_WARN, "`%s` has less than 8 bits per color and will likely not render correctly", path, bits_per_color);
39
24
  }
40
25
 
41
- // Initialize values
42
- img->path = path;
43
- img->x = 0;
44
- img->y = 0;
45
- img->color.r = 1.f;
46
- img->color.g = 1.f;
47
- img->color.b = 1.f;
48
- img->color.a = 1.f;
49
- img->orig_width = img->surface->w;
50
- img->orig_height = img->surface->h;
51
- img->width = img->orig_width;
52
- img->height = img->orig_height;
53
- img->rotate = 0;
54
- img->rx = 0;
55
- img->ry = 0;
56
- img->texture_id = 0;
57
-
58
- // Detect image mode
59
- img->format = GL_RGB;
60
- if (img->surface->format->BytesPerPixel == 4) {
61
- img->format = GL_RGBA;
62
- }
63
-
64
- // Flip image bits if BGA
26
+ return surface;
27
+ }
65
28
 
66
- Uint32 r = img->surface->format->Rmask;
67
- Uint32 g = img->surface->format->Gmask;
68
- Uint32 a = img->surface->format->Amask;
29
+ void R2D_ImageConvertToRGB(SDL_Surface *surface) {
30
+ Uint32 r = surface->format->Rmask;
31
+ Uint32 g = surface->format->Gmask;
32
+ Uint32 a = surface->format->Amask;
69
33
 
70
34
  if (r&0xFF000000 || r&0xFF0000) {
71
- char *p = (char *)img->surface->pixels;
72
- int bpp = img->surface->format->BytesPerPixel;
73
- int w = img->surface->w;
74
- int h = img->surface->h;
35
+ char *p = (char *)surface->pixels;
36
+ int bpp = surface->format->BytesPerPixel;
37
+ int w = surface->w;
38
+ int h = surface->h;
75
39
  char tmp;
76
40
  for (int i = 0; i < bpp * w * h; i += bpp) {
77
41
  if (a&0xFF) {
@@ -91,48 +55,4 @@ R2D_Image *R2D_CreateImage(const char *path) {
91
55
  }
92
56
  }
93
57
  }
94
-
95
- return img;
96
- }
97
-
98
-
99
- /*
100
- * Rotate an image
101
- */
102
- void R2D_RotateImage(R2D_Image *img, GLfloat angle, int position) {
103
-
104
- R2D_GL_Point p = R2D_GetRectRotationPoint(
105
- img->x, img->y, img->width, img->height, position
106
- );
107
-
108
- img->rotate = angle;
109
- img->rx = p.x;
110
- img->ry = p.y;
111
- }
112
-
113
-
114
- /*
115
- * Draw an image
116
- */
117
- void R2D_DrawImage(R2D_Image *img) {
118
- if (!img) return;
119
-
120
- if (img->texture_id == 0) {
121
- R2D_GL_CreateTexture(&img->texture_id, img->format,
122
- img->orig_width, img->orig_height,
123
- img->surface->pixels, GL_NEAREST);
124
- SDL_FreeSurface(img->surface);
125
- }
126
-
127
- R2D_GL_DrawImage(img);
128
- }
129
-
130
-
131
- /*
132
- * Free an image
133
- */
134
- void R2D_FreeImage(R2D_Image *img) {
135
- if (!img) return;
136
- R2D_GL_FreeTexture(&img->texture_id);
137
- free(img);
138
58
  }
data/ext/ruby2d/ruby2d.c CHANGED
@@ -108,18 +108,6 @@ static R2D_Window *window;
108
108
 
109
109
  // Method signatures and structures for Ruby 2D classes
110
110
  #if MRUBY
111
- static void free_image(mrb_state *mrb, void *p_);
112
- static const struct mrb_data_type image_data_type = {
113
- "image", free_image
114
- };
115
- static void free_sprite(mrb_state *mrb, void *p_);
116
- static const struct mrb_data_type sprite_data_type = {
117
- "sprite", free_sprite
118
- };
119
- static void free_text(mrb_state *mrb, void *p_);
120
- static const struct mrb_data_type text_data_type = {
121
- "text", free_text
122
- };
123
111
  static void free_sound(mrb_state *mrb, void *p_);
124
112
  static const struct mrb_data_type sound_data_type = {
125
113
  "sound", free_sound
@@ -129,11 +117,10 @@ static R2D_Window *window;
129
117
  "music", free_music
130
118
  };
131
119
  #else
132
- static void free_image(R2D_Image *img);
133
- static void free_sprite(R2D_Sprite *spr);
134
- static void free_text(R2D_Text *txt);
135
120
  static void free_sound(R2D_Sound *snd);
136
121
  static void free_music(R2D_Music *mus);
122
+ static void free_font(TTF_Font *font);
123
+ static void free_surface(SDL_Surface *font);
137
124
  #endif
138
125
 
139
126
 
@@ -368,353 +355,190 @@ static R_VAL ruby2d_circle_ext_draw(R_VAL self, R_VAL a) {
368
355
 
369
356
 
370
357
  /*
371
- * Ruby2D::Image#ext_init
372
- * Initialize image structure data
373
- */
374
- #if MRUBY
375
- static R_VAL ruby2d_image_ext_init(mrb_state* mrb, R_VAL self) {
376
- mrb_value path;
377
- mrb_get_args(mrb, "o", &path);
378
- #else
379
- static R_VAL ruby2d_image_ext_init(R_VAL self, R_VAL path) {
380
- #endif
381
- R2D_Image *img = R2D_CreateImage(RSTRING_PTR(path));
382
- if (!img) return R_FALSE;
383
-
384
- // Get width and height from Ruby class. If set, use it, else choose the
385
- // native dimensions of the image.
386
- R_VAL w = r_iv_get(self, "@width");
387
- R_VAL h = r_iv_get(self, "@height");
388
- r_iv_set(self, "@width" , r_test(w) ? w : INT2NUM(img->width));
389
- r_iv_set(self, "@height", r_test(h) ? h : INT2NUM(img->height));
390
- r_iv_set(self, "@data", r_data_wrap_struct(image, img));
391
-
392
- return R_TRUE;
393
- }
394
-
395
-
396
- /*
397
- * Ruby2D::Image#self.ext_draw
358
+ * Ruby2D::Image#ext_load_image
359
+ * Create an SDL surface from an image path, return the surface, width, and height
398
360
  */
399
- #if MRUBY
400
- static R_VAL ruby2d_image_ext_draw(mrb_state* mrb, R_VAL self) {
401
- mrb_value a;
402
- mrb_get_args(mrb, "o", &a);
403
- #else
404
- static R_VAL ruby2d_image_ext_draw(R_VAL self, R_VAL a) {
405
- #endif
406
- // `a` is the array representing the image
361
+ static R_VAL ruby2d_image_ext_load_image(R_VAL self, R_VAL path) {
362
+ R2D_Init();
407
363
 
408
- R2D_Image *img;
409
- r_data_get_struct(r_ary_entry(a, 0), "@data", &image_data_type, R2D_Image, img);
364
+ VALUE result = rb_ary_new2(3);
410
365
 
411
- img->x = NUM2DBL(r_ary_entry(a, 1));
412
- img->y = NUM2DBL(r_ary_entry(a, 2));
366
+ SDL_Surface *surface = R2D_CreateImageSurface(RSTRING_PTR(path));
367
+ R2D_ImageConvertToRGB(surface);
413
368
 
414
- R_VAL w = r_ary_entry(a, 3);
415
- R_VAL h = r_ary_entry(a, 4);
416
- if (r_test(w)) img->width = NUM2INT(w);
417
- if (r_test(h)) img->height = NUM2INT(h);
369
+ rb_ary_push(result, r_data_wrap_struct(surface, surface));
370
+ rb_ary_push(result, INT2NUM(surface->w));
371
+ rb_ary_push(result, INT2NUM(surface->h));
418
372
 
419
- R2D_RotateImage(img, NUM2DBL(r_ary_entry(a, 5)), R2D_CENTER);
420
-
421
- img->color.r = NUM2DBL(r_ary_entry(a, 6));
422
- img->color.g = NUM2DBL(r_ary_entry(a, 7));
423
- img->color.b = NUM2DBL(r_ary_entry(a, 8));
424
- img->color.a = NUM2DBL(r_ary_entry(a, 9));
425
-
426
- R2D_DrawImage(img);
427
- return R_NIL;
373
+ return result;
428
374
  }
429
375
 
430
376
 
431
377
  /*
432
- * Free image structure attached to Ruby 2D `Image` class
378
+ * Ruby2D::Text#ext_load_text
433
379
  */
434
- #if MRUBY
435
- static void free_image(mrb_state *mrb, void *p_) {
436
- R2D_Image *img = (R2D_Image *)p_;
437
- #else
438
- static void free_image(R2D_Image *img) {
439
- #endif
440
- R2D_FreeImage(img);
441
- }
380
+ static R_VAL ruby2d_text_ext_load_text(R_VAL self, R_VAL font, R_VAL message) {
381
+ R2D_Init();
442
382
 
383
+ VALUE result = rb_ary_new2(3);
443
384
 
444
- /*
445
- * Ruby2D::Sprite#ext_init
446
- * Initialize sprite structure data
447
- */
448
- #if MRUBY
449
- static R_VAL ruby2d_sprite_ext_init(mrb_state* mrb, R_VAL self) {
450
- mrb_value path;
451
- mrb_get_args(mrb, "o", &path);
452
- #else
453
- static R_VAL ruby2d_sprite_ext_init(R_VAL self, R_VAL path) {
454
- #endif
455
- R2D_Sprite *spr = R2D_CreateSprite(RSTRING_PTR(path));
456
- if (!spr) return R_FALSE;
385
+ TTF_Font *ttf_font;
386
+ Data_Get_Struct(font, TTF_Font, ttf_font);
457
387
 
458
- r_iv_set(self, "@img_width" , INT2NUM(spr->width));
459
- r_iv_set(self, "@img_height", INT2NUM(spr->height));
460
- r_iv_set(self, "@data", r_data_wrap_struct(sprite, spr));
388
+ SDL_Surface *surface = R2D_TextCreateSurface(ttf_font, RSTRING_PTR(message));
389
+ if (!surface) {
390
+ return result;
391
+ }
461
392
 
462
- return R_TRUE;
463
- }
393
+ rb_ary_push(result, r_data_wrap_struct(surface, surface));
394
+ rb_ary_push(result, INT2NUM(surface->w));
395
+ rb_ary_push(result, INT2NUM(surface->h));
464
396
 
397
+ return result;
398
+ }
465
399
 
466
400
  /*
467
- * Ruby2D::Sprite#ext_draw
401
+ * Ruby2D::Texture#ext_create
468
402
  */
469
- #if MRUBY
470
- static R_VAL ruby2d_sprite_ext_draw(mrb_state* mrb, R_VAL self) {
471
- mrb_value a;
472
- mrb_get_args(mrb, "o", &a);
473
- #else
474
- static R_VAL ruby2d_sprite_ext_draw(R_VAL self, R_VAL a) {
475
- #endif
476
- // `a` is the array representing the sprite
477
-
478
- R2D_Sprite *spr;
479
- r_data_get_struct(r_ary_entry(a, 0), "@data", &sprite_data_type, R2D_Sprite, spr);
480
-
481
- spr->x = NUM2DBL(r_ary_entry(a, 1));
482
- spr->y = NUM2DBL(r_ary_entry(a, 2));
483
-
484
- R_VAL w = r_ary_entry(a, 3);
485
- if (r_test(w)) spr->width = NUM2DBL(w);
486
-
487
- R_VAL h = r_ary_entry(a, 4);
488
- if (r_test(h)) spr->height = NUM2DBL(h);
489
-
490
- R2D_RotateSprite(spr, NUM2DBL(r_ary_entry(a, 5)), R2D_CENTER);
491
-
492
- R2D_ClipSprite(
493
- spr,
494
- NUM2INT(r_ary_entry(a, 6)),
495
- NUM2INT(r_ary_entry(a, 7)),
496
- NUM2INT(r_ary_entry(a, 8)),
497
- NUM2INT(r_ary_entry(a, 9))
498
- );
499
-
500
- spr->color.r = NUM2DBL(r_ary_entry(a, 10));
501
- spr->color.g = NUM2DBL(r_ary_entry(a, 11));
502
- spr->color.b = NUM2DBL(r_ary_entry(a, 12));
503
- spr->color.a = NUM2DBL(r_ary_entry(a, 13));
504
-
505
- R2D_DrawSprite(spr);
506
- return R_NIL;
507
- }
403
+ static R_VAL ruby2d_texture_ext_create(R_VAL self, R_VAL rubySurface, R_VAL width, R_VAL height) {
404
+ GLuint texture_id = 0;
405
+ SDL_Surface *surface;
406
+ Data_Get_Struct(rubySurface, SDL_Surface, surface);
407
+
408
+ // Detect image mode
409
+ GLint format = GL_RGB;
410
+ if (surface->format->BytesPerPixel == 4) {
411
+ format = GL_RGBA;
412
+ }
508
413
 
414
+ R2D_GL_CreateTexture(&texture_id, format,
415
+ NUM2INT(width), NUM2INT(height),
416
+ surface->pixels, GL_NEAREST);
509
417
 
510
- /*
511
- * Free sprite structure attached to Ruby 2D `Sprite` class
512
- */
513
- #if MRUBY
514
- static void free_sprite(mrb_state *mrb, void *p_) {
515
- R2D_Sprite *spr = (R2D_Sprite *)p_;
516
- #else
517
- static void free_sprite(R2D_Sprite *spr) {
518
- #endif
519
- R2D_FreeSprite(spr);
418
+ return INT2NUM(texture_id);
520
419
  }
521
420
 
522
-
523
421
  /*
524
- * Ruby2D::Tileset#ext_init
525
- * Initialize tileset data
422
+ * Ruby2D::Texture#ext_delete
526
423
  */
527
- static R_VAL ruby2d_tileset_ext_init(R_VAL self, R_VAL path) {
528
- R2D_Image *img = R2D_CreateImage(RSTRING_PTR(path));
529
- if (!img) return R_FALSE;
530
-
531
- // Get width and height from Ruby class. If set, use it, else choose the
532
- // native dimensions of the image.
533
- R_VAL w = r_iv_get(self, "@width");
534
- R_VAL h = r_iv_get(self, "@height");
535
- r_iv_set(self, "@width" , r_test(w) ? w : INT2NUM(img->width));
536
- r_iv_set(self, "@height", r_test(h) ? h : INT2NUM(img->height));
537
- r_iv_set(self, "@data", r_data_wrap_struct(image, img));
538
-
539
- return R_TRUE;
540
- }
424
+ static R_VAL ruby2d_texture_ext_delete(R_VAL self, R_VAL rubyTexture_id) {
425
+ GLuint texture_id = NUM2INT(rubyTexture_id);
541
426
 
427
+ R2D_GL_FreeTexture(&texture_id);
542
428
 
543
- /*
544
- * Ruby2D::Tileset#ext_draw
545
- * Draws a single tile, will be called once per individual tile to draw
546
- */
547
- static R_VAL ruby2d_tileset_ext_draw(R_VAL self, R_VAL a) {
548
- // `a` is the array representing the tileset
549
-
550
- R2D_Image *img;
551
- r_data_get_struct(r_ary_entry(a, 0), "@data", &image_data_type, R2D_Image, img);
552
-
553
- int tw = NUM2INT(r_ary_entry(a, 1));
554
- int th = NUM2INT(r_ary_entry(a, 2));
555
- int padding = NUM2INT(r_ary_entry(a, 3));
556
- int spacing = NUM2INT(r_ary_entry(a, 4));
557
- int tx = NUM2INT(r_ary_entry(a, 5));
558
- int ty = NUM2INT(r_ary_entry(a, 6));
559
- int x = NUM2INT(r_ary_entry(a, 7));
560
- int y = NUM2INT(r_ary_entry(a, 8));
561
-
562
- R2D_DrawTile(img, tw, th, padding, spacing, tx, ty, x, y);
563
429
  return R_NIL;
564
430
  }
565
431
 
566
432
 
567
433
  /*
568
- * Ruby2D::Text#ext_init
569
- * Initialize text structure data
434
+ * Ruby2D::Sound#ext_init
435
+ * Initialize sound structure data
570
436
  */
571
437
  #if MRUBY
572
- static R_VAL ruby2d_text_ext_init(mrb_state* mrb, R_VAL self) {
438
+ static R_VAL ruby2d_sound_ext_init(mrb_state* mrb, R_VAL self) {
439
+ mrb_value path;
440
+ mrb_get_args(mrb, "o", &path);
573
441
  #else
574
- static R_VAL ruby2d_text_ext_init(R_VAL self) {
442
+ static R_VAL ruby2d_sound_ext_init(R_VAL self, R_VAL path) {
575
443
  #endif
576
- // Trim the font file string to its actual length on MRuby
577
- #if MRUBY
578
- mrb_value s = r_iv_get(self, "@font");
579
- mrb_str_resize(mrb, s, RSTRING_LEN(s));
580
- #endif
581
-
582
- R2D_Text *txt = R2D_CreateText(
583
- RSTRING_PTR(r_iv_get(self, "@font")),
584
- RSTRING_PTR(r_iv_get(self, "@text")),
585
- NUM2DBL(r_iv_get(self, "@size"))
586
- );
587
- if (!txt) return R_FALSE;
588
-
589
- r_iv_set(self, "@width", INT2NUM(txt->width));
590
- r_iv_set(self, "@height", INT2NUM(txt->height));
591
- r_iv_set(self, "@data", r_data_wrap_struct(text, txt));
592
-
444
+ R2D_Sound *snd = R2D_CreateSound(RSTRING_PTR(path));
445
+ if (!snd) return R_FALSE;
446
+ r_iv_set(self, "@data", r_data_wrap_struct(sound, snd));
593
447
  return R_TRUE;
594
448
  }
595
449
 
596
450
 
597
451
  /*
598
- * Ruby2D::Text#ext_set
452
+ * Ruby2D::Sound#ext_play
599
453
  */
600
454
  #if MRUBY
601
- static R_VAL ruby2d_text_ext_set(mrb_state* mrb, R_VAL self) {
602
- mrb_value text;
603
- mrb_get_args(mrb, "o", &text);
455
+ static R_VAL ruby2d_sound_ext_play(mrb_state* mrb, R_VAL self) {
604
456
  #else
605
- static R_VAL ruby2d_text_ext_set(R_VAL self, R_VAL text) {
457
+ static R_VAL ruby2d_sound_ext_play(R_VAL self) {
606
458
  #endif
607
- R2D_Text *txt;
608
- r_data_get_struct(self, "@data", &text_data_type, R2D_Text, txt);
609
-
610
- R2D_SetText(txt, RSTRING_PTR(text));
611
-
612
- r_iv_set(self, "@width", INT2NUM(txt->width));
613
- r_iv_set(self, "@height", INT2NUM(txt->height));
614
-
459
+ R2D_Sound *snd;
460
+ r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
461
+ R2D_PlaySound(snd);
615
462
  return R_NIL;
616
463
  }
617
464
 
618
465
 
619
466
  /*
620
- * Ruby2D::Text#self.ext_draw
467
+ * Ruby2D::Sound#ext_length
621
468
  */
622
- #if MRUBY
623
- static R_VAL ruby2d_text_ext_draw(mrb_state* mrb, R_VAL self) {
624
- mrb_value a;
625
- mrb_get_args(mrb, "o", &a);
626
- #else
627
- static R_VAL ruby2d_text_ext_draw(R_VAL self, R_VAL a) {
628
- #endif
629
- // `a` is the array representing the text
630
-
631
- R2D_Text *txt;
632
- r_data_get_struct(r_ary_entry(a, 0), "@data", &text_data_type, R2D_Text, txt);
633
-
634
- txt->x = NUM2DBL(r_ary_entry(a, 1));
635
- txt->y = NUM2DBL(r_ary_entry(a, 2));
636
-
637
- R2D_RotateText(txt, NUM2DBL(r_ary_entry(a, 3)), R2D_CENTER);
638
-
639
- txt->color.r = NUM2DBL(r_ary_entry(a, 4));
640
- txt->color.g = NUM2DBL(r_ary_entry(a, 5));
641
- txt->color.b = NUM2DBL(r_ary_entry(a, 6));
642
- txt->color.a = NUM2DBL(r_ary_entry(a, 7));
643
-
644
- R2D_DrawText(txt);
645
- return R_NIL;
469
+ static R_VAL ruby2d_sound_ext_length(R_VAL self) {
470
+ R2D_Sound *snd;
471
+ r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
472
+ return INT2NUM(R2D_GetSoundLength(snd));
646
473
  }
647
474
 
648
475
 
649
476
  /*
650
- * Free text structure attached to Ruby 2D `Text` class
477
+ * Free sound structure attached to Ruby 2D `Sound` class
651
478
  */
652
479
  #if MRUBY
653
- static void free_text(mrb_state *mrb, void *p_) {
654
- R2D_Text *txt = (R2D_Text *)p_;
480
+ static void free_sound(mrb_state *mrb, void *p_) {
481
+ R2D_Sound *snd = (R2D_Sound *)p_;
655
482
  #else
656
- static void free_text(R2D_Text *txt) {
483
+ static void free_sound(R2D_Sound *snd) {
657
484
  #endif
658
- R2D_FreeText(txt);
485
+ R2D_FreeSound(snd);
659
486
  }
660
487
 
661
-
662
488
  /*
663
- * Ruby2D::Sound#ext_init
664
- * Initialize sound structure data
489
+ * Ruby2D::Sound#ext_get_volume
665
490
  */
666
491
  #if MRUBY
667
- static R_VAL ruby2d_sound_ext_init(mrb_state* mrb, R_VAL self) {
668
- mrb_value path;
669
- mrb_get_args(mrb, "o", &path);
492
+ static R_VAL ruby2d_sound_ext_get_volume(mrb_state* mrb, R_VAL self) {
670
493
  #else
671
- static R_VAL ruby2d_sound_ext_init(R_VAL self, R_VAL path) {
494
+ static R_VAL ruby2d_sound_ext_get_volume(R_VAL self) {
672
495
  #endif
673
- R2D_Sound *snd = R2D_CreateSound(RSTRING_PTR(path));
674
- if (!snd) return R_FALSE;
675
- r_iv_set(self, "@data", r_data_wrap_struct(sound, snd));
676
- return R_TRUE;
496
+ R2D_Sound *snd;
497
+ r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
498
+ return INT2NUM(ceil(Mix_VolumeChunk(snd->data, -1) * (100.0 / MIX_MAX_VOLUME)));
677
499
  }
678
500
 
679
-
680
501
  /*
681
- * Ruby2D::Sound#ext_play
502
+ * Ruby2D::Music#ext_set_volume
682
503
  */
683
504
  #if MRUBY
684
- static R_VAL ruby2d_sound_ext_play(mrb_state* mrb, R_VAL self) {
505
+ static R_VAL ruby2d_sound_ext_set_volume(mrb_state* mrb, R_VAL self) {
506
+ mrb_value volume;
507
+ mrb_get_args(mrb, "o", &volume);
685
508
  #else
686
- static R_VAL ruby2d_sound_ext_play(R_VAL self) {
509
+ static R_VAL ruby2d_sound_ext_set_volume(R_VAL self, R_VAL volume) {
687
510
  #endif
688
511
  R2D_Sound *snd;
689
512
  r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
690
- R2D_PlaySound(snd);
513
+ Mix_VolumeChunk(snd->data, (NUM2INT(volume) / 100.0) * MIX_MAX_VOLUME);
691
514
  return R_NIL;
692
515
  }
693
516
 
694
-
695
517
  /*
696
- * Ruby2D::Sound#ext_length
518
+ * Ruby2D::Sound#ext_get_mix_volume
697
519
  */
698
- static R_VAL ruby2d_sound_ext_length(R_VAL self) {
699
- R2D_Sound *snd;
700
- r_data_get_struct(self, "@data", &sound_data_type, R2D_Sound, snd);
701
- return INT2NUM(R2D_GetSoundLength(snd));
520
+ #if MRUBY
521
+ static R_VAL ruby2d_sound_ext_get_mix_volume(mrb_state* mrb, R_VAL self) {
522
+ #else
523
+ static R_VAL ruby2d_sound_ext_get_mix_volume(R_VAL self) {
524
+ #endif
525
+ return INT2NUM(ceil(Mix_Volume(-1, -1) * (100.0 / MIX_MAX_VOLUME)));
702
526
  }
703
527
 
704
-
705
528
  /*
706
- * Free sound structure attached to Ruby 2D `Sound` class
529
+ * Ruby2D::Music#ext_set_mix_volume
707
530
  */
708
531
  #if MRUBY
709
- static void free_sound(mrb_state *mrb, void *p_) {
710
- R2D_Sound *snd = (R2D_Sound *)p_;
532
+ static R_VAL ruby2d_sound_ext_set_mix_volume(mrb_state* mrb, R_VAL self) {
533
+ mrb_value volume;
534
+ mrb_get_args(mrb, "o", &volume);
711
535
  #else
712
- static void free_sound(R2D_Sound *snd) {
536
+ static R_VAL ruby2d_sound_ext_set_mix_volume(R_VAL self, R_VAL volume) {
713
537
  #endif
714
- R2D_FreeSound(snd);
538
+ Mix_Volume(-1, (NUM2INT(volume) / 100.0) * MIX_MAX_VOLUME);
539
+ return R_NIL;
715
540
  }
716
541
 
717
-
718
542
  /*
719
543
  * Ruby2D::Music#ext_init
720
544
  * Initialize music structure data
@@ -838,6 +662,52 @@ static R_VAL ruby2d_music_ext_length(R_VAL self) {
838
662
  return INT2NUM(R2D_GetMusicLength(ms));
839
663
  }
840
664
 
665
+ /*
666
+ * Ruby2D::Font#ext_load
667
+ */
668
+ static R_VAL ruby2d_font_ext_load(R_VAL self, R_VAL path, R_VAL size, R_VAL style) {
669
+ R2D_Init();
670
+
671
+ TTF_Font *font = R2D_FontCreateTTFFont(RSTRING_PTR(path), NUM2INT(size), RSTRING_PTR(style));
672
+ if (!font) {
673
+ return R_NIL;
674
+ }
675
+
676
+ return r_data_wrap_struct(font, font);
677
+ }
678
+
679
+
680
+ /*
681
+ * Ruby2D::Texture#ext_draw
682
+ */
683
+ static R_VAL ruby2d_texture_ext_draw(R_VAL self, R_VAL ruby_coordinates, R_VAL ruby_texture_coordinates, R_VAL ruby_color, R_VAL texture_id) {
684
+ GLfloat coordinates[8];
685
+ GLfloat texture_coordinates[8];
686
+ GLfloat color[4];
687
+
688
+ for(int i = 0; i < 8; i++) { coordinates[i] = NUM2DBL(r_ary_entry(ruby_coordinates, i)); }
689
+ for(int i = 0; i < 8; i++) { texture_coordinates[i] = NUM2DBL(r_ary_entry(ruby_texture_coordinates, i)); }
690
+ for(int i = 0; i < 4; i++) { color[i] = NUM2DBL(r_ary_entry(ruby_color, i)); }
691
+
692
+ R2D_GL_DrawTexture(coordinates, texture_coordinates, color, NUM2INT(texture_id));
693
+
694
+ return R_NIL;
695
+ }
696
+
697
+ /*
698
+ * Free font structure stored in the Ruby 2D `Font` class
699
+ */
700
+ static void free_font(TTF_Font *font) {
701
+ TTF_CloseFont(font);
702
+ }
703
+
704
+ /*
705
+ * Free surface structure used within the Ruby 2D `Texture` class
706
+ */
707
+ static void free_surface(SDL_Surface *surface) {
708
+ SDL_FreeSurface(surface);
709
+ }
710
+
841
711
 
842
712
  /*
843
713
  * Free music structure attached to Ruby 2D `Music` class
@@ -1275,41 +1145,14 @@ void Init_ruby2d() {
1275
1145
  // Ruby2D::Image
1276
1146
  R_CLASS ruby2d_image_class = r_define_class(ruby2d_module, "Image");
1277
1147
 
1278
- // Ruby2D::Image#ext_init
1279
- r_define_method(ruby2d_image_class, "ext_init", ruby2d_image_ext_init, r_args_req(1));
1280
-
1281
- // Ruby2D::Image#self.ext_draw
1282
- r_define_class_method(ruby2d_image_class, "ext_draw", ruby2d_image_ext_draw, r_args_req(1));
1283
-
1284
- // Ruby2D::Sprite
1285
- R_CLASS ruby2d_sprite_class = r_define_class(ruby2d_module, "Sprite");
1286
-
1287
- // Ruby2D::Sprite#ext_init
1288
- r_define_method(ruby2d_sprite_class, "ext_init", ruby2d_sprite_ext_init, r_args_req(1));
1289
-
1290
- // Ruby2D::Sprite#self.ext_draw
1291
- r_define_class_method(ruby2d_sprite_class, "ext_draw", ruby2d_sprite_ext_draw, r_args_req(1));
1292
-
1293
- // Ruby2D::Tileset
1294
- R_CLASS ruby2d_tileset_class = r_define_class(ruby2d_module, "Tileset");
1295
-
1296
- // Ruby2D::Tileset#ext_init
1297
- r_define_method(ruby2d_tileset_class, "ext_init", ruby2d_tileset_ext_init, r_args_req(1));
1298
-
1299
- // Ruby2D::Tileset#self.ext_draw
1300
- r_define_class_method(ruby2d_tileset_class, "ext_draw", ruby2d_tileset_ext_draw, r_args_req(1));
1148
+ // Ruby2D::Image#ext_load_image
1149
+ r_define_class_method(ruby2d_image_class, "ext_load_image", ruby2d_image_ext_load_image, r_args_req(1));
1301
1150
 
1302
1151
  // Ruby2D::Text
1303
1152
  R_CLASS ruby2d_text_class = r_define_class(ruby2d_module, "Text");
1304
1153
 
1305
- // Ruby2D::Text#ext_init
1306
- r_define_method(ruby2d_text_class, "ext_init", ruby2d_text_ext_init, r_args_none);
1307
-
1308
- // Ruby2D::Text#ext_set
1309
- r_define_method(ruby2d_text_class, "ext_set", ruby2d_text_ext_set, r_args_req(1));
1310
-
1311
- // Ruby2D::Text#self.ext_draw
1312
- r_define_class_method(ruby2d_text_class, "ext_draw", ruby2d_text_ext_draw, r_args_req(1));
1154
+ // Ruby2D::Text#ext_load_text
1155
+ r_define_class_method(ruby2d_text_class, "ext_load_text", ruby2d_text_ext_load_text, r_args_req(2));
1313
1156
 
1314
1157
  // Ruby2D::Sound
1315
1158
  R_CLASS ruby2d_sound_class = r_define_class(ruby2d_module, "Sound");
@@ -1319,6 +1162,18 @@ void Init_ruby2d() {
1319
1162
 
1320
1163
  // Ruby2D::Sound#ext_play
1321
1164
  r_define_method(ruby2d_sound_class, "ext_play", ruby2d_sound_ext_play, r_args_none);
1165
+
1166
+ // Ruby2D::Sound#ext_get_volume
1167
+ r_define_method(ruby2d_sound_class, "ext_get_volume", ruby2d_sound_ext_get_volume, r_args_none);
1168
+
1169
+ // Ruby2D::Sound#ext_set_volume
1170
+ r_define_method(ruby2d_sound_class, "ext_set_volume", ruby2d_sound_ext_set_volume, r_args_req(1));
1171
+
1172
+ // Ruby2D::Sound#self.ext_get_mix_volume
1173
+ r_define_class_method(ruby2d_sound_class, "ext_get_mix_volume", ruby2d_sound_ext_get_mix_volume, r_args_none);
1174
+
1175
+ // Ruby2D::Sound#self.ext_set_mix_volume
1176
+ r_define_class_method(ruby2d_sound_class, "ext_set_mix_volume", ruby2d_sound_ext_set_mix_volume, r_args_req(1));
1322
1177
 
1323
1178
  // Ruby2D::Sound#ext_length
1324
1179
  r_define_method(ruby2d_sound_class, "ext_length", ruby2d_sound_ext_length, r_args_none);
@@ -1353,6 +1208,24 @@ void Init_ruby2d() {
1353
1208
  // Ruby2D::Music#ext_length
1354
1209
  r_define_method(ruby2d_music_class, "ext_length", ruby2d_music_ext_length, r_args_none);
1355
1210
 
1211
+ // Ruby2D::Font
1212
+ R_CLASS ruby2d_font_class = r_define_class(ruby2d_module, "Font");
1213
+
1214
+ // Ruby2D::Font#ext_load
1215
+ r_define_class_method(ruby2d_font_class, "ext_load", ruby2d_font_ext_load, r_args_req(3));
1216
+
1217
+ // Ruby2D::Texture
1218
+ R_CLASS ruby2d_texture_class = r_define_class(ruby2d_module, "Texture");
1219
+
1220
+ // Ruby2D::Texture#ext_draw
1221
+ r_define_method(ruby2d_texture_class, "ext_draw", ruby2d_texture_ext_draw, r_args_req(4));
1222
+
1223
+ // Ruby2D::Texture#ext_create
1224
+ r_define_method(ruby2d_texture_class, "ext_create", ruby2d_texture_ext_create, r_args_req(3));
1225
+
1226
+ // Ruby2D::Texture#ext_delete
1227
+ r_define_method(ruby2d_texture_class, "ext_delete", ruby2d_texture_ext_delete, r_args_req(1));
1228
+
1356
1229
  // Ruby2D::Window
1357
1230
  R_CLASS ruby2d_window_class = r_define_class(ruby2d_module, "Window");
1358
1231