rubygame 2.5.3 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/CREDITS +6 -4
  2. data/NEWS +79 -0
  3. data/README +55 -72
  4. data/ROADMAP +20 -13
  5. data/doc/custom_sdl_load_paths.rdoc +79 -0
  6. data/doc/getting_started.rdoc +65 -36
  7. data/doc/keyboard_symbols.rdoc +243 -0
  8. data/doc/macosx_install.rdoc +49 -35
  9. data/doc/windows_install.rdoc +36 -108
  10. data/lib/rubygame.rb +62 -24
  11. data/lib/rubygame/audio.rb +147 -0
  12. data/lib/rubygame/clock.rb +164 -1
  13. data/lib/rubygame/color.rb +40 -7
  14. data/lib/rubygame/color/models/hsl.rb +1 -1
  15. data/lib/rubygame/color/models/hsv.rb +1 -1
  16. data/lib/rubygame/color/models/rgb.rb +1 -1
  17. data/lib/rubygame/color/palettes/css.rb +1 -3
  18. data/lib/rubygame/color/palettes/x11.rb +1 -2
  19. data/lib/rubygame/constants.rb +297 -0
  20. data/lib/rubygame/deprecated_mixer.rb +555 -0
  21. data/lib/rubygame/event.rb +122 -6
  22. data/lib/rubygame/event_handler.rb +3 -1
  23. data/lib/rubygame/event_hook.rb +6 -2
  24. data/lib/rubygame/event_triggers.rb +1 -1
  25. data/lib/rubygame/events.rb +416 -1
  26. data/lib/rubygame/ftor.rb +1 -7
  27. data/lib/rubygame/gfx.rb +583 -0
  28. data/lib/rubygame/gl.rb +107 -0
  29. data/lib/rubygame/image.rb +140 -0
  30. data/lib/rubygame/joystick.rb +184 -0
  31. data/lib/rubygame/main.rb +82 -0
  32. data/lib/rubygame/mediabag.rb +1 -1
  33. data/lib/rubygame/mixer.rb +30 -0
  34. data/lib/rubygame/music.rb +493 -0
  35. data/lib/rubygame/queue.rb +3 -1
  36. data/lib/rubygame/rect.rb +9 -9
  37. data/lib/rubygame/screen.rb +357 -0
  38. data/lib/rubygame/shared.rb +40 -4
  39. data/lib/rubygame/sound.rb +428 -0
  40. data/lib/rubygame/surface.rb +626 -0
  41. data/lib/rubygame/ttf.rb +311 -0
  42. data/samples/FreeSans.ttf +0 -0
  43. data/samples/README +6 -5
  44. data/samples/demo_draw.rb +1 -1
  45. data/samples/demo_gl.rb +3 -1
  46. data/samples/demo_gl_tex.rb +4 -2
  47. data/samples/demo_rubygame.rb +114 -105
  48. data/samples/demo_sfont.rb +1 -1
  49. data/samples/demo_ttf.rb +3 -1
  50. data/samples/demo_utf8.rb +1 -1
  51. data/samples/image_viewer.rb +118 -0
  52. data/samples/load_and_blit.rb +1 -1
  53. data/samples/rubygame.png +0 -0
  54. metadata +34 -40
  55. data/Rakefile +0 -537
  56. data/doc/extended_readme.rdoc +0 -49
  57. data/ext/body/rubygame_body.so +0 -0
  58. data/ext/rubygame/rubygame_clock.c +0 -301
  59. data/ext/rubygame/rubygame_clock.h +0 -32
  60. data/ext/rubygame/rubygame_event.c +0 -760
  61. data/ext/rubygame/rubygame_event.h +0 -48
  62. data/ext/rubygame/rubygame_event2.c +0 -661
  63. data/ext/rubygame/rubygame_event2.h +0 -29
  64. data/ext/rubygame/rubygame_gfx.c +0 -942
  65. data/ext/rubygame/rubygame_gfx.h +0 -101
  66. data/ext/rubygame/rubygame_gl.c +0 -154
  67. data/ext/rubygame/rubygame_gl.h +0 -32
  68. data/ext/rubygame/rubygame_image.c +0 -252
  69. data/ext/rubygame/rubygame_image.h +0 -41
  70. data/ext/rubygame/rubygame_joystick.c +0 -336
  71. data/ext/rubygame/rubygame_joystick.h +0 -41
  72. data/ext/rubygame/rubygame_main.c +0 -158
  73. data/ext/rubygame/rubygame_main.h +0 -36
  74. data/ext/rubygame/rubygame_mixer.c +0 -1024
  75. data/ext/rubygame/rubygame_mixer.h +0 -36
  76. data/ext/rubygame/rubygame_music.c +0 -1017
  77. data/ext/rubygame/rubygame_music.h +0 -29
  78. data/ext/rubygame/rubygame_screen.c +0 -572
  79. data/ext/rubygame/rubygame_screen.h +0 -45
  80. data/ext/rubygame/rubygame_shared.c +0 -269
  81. data/ext/rubygame/rubygame_shared.h +0 -69
  82. data/ext/rubygame/rubygame_sound.c +0 -863
  83. data/ext/rubygame/rubygame_sound.h +0 -29
  84. data/ext/rubygame/rubygame_surface.c +0 -1153
  85. data/ext/rubygame/rubygame_surface.h +0 -62
  86. data/ext/rubygame/rubygame_ttf.c +0 -599
  87. data/ext/rubygame/rubygame_ttf.h +0 -69
  88. data/samples/keys.rb +0 -52
@@ -1,36 +0,0 @@
1
- /*
2
- * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
- * Copyright (C) 2004-2007 John Croisant
4
- *
5
- * This library is free software; you can redistribute it and/or
6
- * modify it under the terms of the GNU Lesser General Public
7
- * License as published by the Free Software Foundation; either
8
- * version 2.1 of the License, or (at your option) any later version.
9
- *
10
- * This library is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * Lesser General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU Lesser General Public
16
- * License along with this library; if not, write to the Free Software
17
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
- *
19
- */
20
-
21
- #ifndef _RUBYGAME_MIXER_H
22
- #define _RUBYGAME_MIXER_H
23
-
24
- #include "SDL_audio.h"
25
- #include "SDL_mixer.h"
26
-
27
- extern int audio_is_open();
28
- extern int ensure_open_audio();
29
-
30
- extern void Init_rubygame_mixer();
31
-
32
- extern VALUE mMixer;
33
- extern VALUE cSample;
34
- extern VALUE cOldMusic;
35
-
36
- #endif
@@ -1,1017 +0,0 @@
1
- /*
2
- * Interface to SDL_mixer music playback and mixing.
3
- *--
4
- * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
5
- * Copyright (C) 2004-2008 John Croisant
6
- *
7
- * This library is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU Lesser General Public
9
- * License as published by the Free Software Foundation; either
10
- * version 2.1 of the License, or (at your option) any later version.
11
- *
12
- * This library is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
- * Lesser General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU Lesser General Public
18
- * License along with this library; if not, write to the Free Software
19
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
- *++
21
- */
22
-
23
- #include "SDL_mixer.h"
24
- #include "rubygame_shared.h"
25
- #include "rubygame_mixer.h"
26
-
27
- VALUE cMusic;
28
-
29
-
30
- /*
31
- * A pointer to a Mix_Music, with a reference count.
32
- * Allows re-use of music data, then freeing memory when
33
- * there are no references to it.
34
- */
35
- typedef struct RG_WrapMusic {
36
- /* 'private' */
37
- Mix_Music *music;
38
- int ref_count;
39
- } RG_WrapMusic;
40
-
41
-
42
- /*
43
- * The struct that the Music class wraps. Stores a
44
- * pointer to a RG_WrapMusic and important attributes
45
- * of the Music like its volume.
46
- */
47
- typedef struct RG_Music {
48
- /* 'public' */
49
- float volume;
50
-
51
- /* 'private' */
52
- RG_WrapMusic *wrap;
53
- int repeats;
54
- } RG_Music;
55
-
56
-
57
-
58
-
59
- /* Allocate/initialize the memory for a RG_WrapMusic and return a pointer. */
60
- static RG_WrapMusic* _rg_wrapmusic_alloc()
61
- {
62
- RG_WrapMusic *wrap;
63
- wrap = ALLOC(RG_WrapMusic);
64
-
65
- wrap->music = NULL;
66
- wrap->ref_count = 0;
67
-
68
- return wrap;
69
- }
70
-
71
- /* Load a Mix_Music from a file and assign it to the RG_WrapMusic. */
72
- static int _rg_wrapmusic_load( RG_WrapMusic *wrap, char *file )
73
- {
74
- wrap->music = Mix_LoadMUS( file );
75
-
76
- if( !(wrap->music) )
77
- return -1;
78
- else
79
- return 0;
80
- }
81
-
82
- /* Make a copy of the other's Mix_Music data, and assign
83
- * it to the RG_WrapMusic.
84
- */
85
- static void _rg_wrapmusic_deepcopy( RG_WrapMusic *wrap, RG_WrapMusic *other )
86
- {
87
- wrap->music = other->music;
88
- }
89
-
90
-
91
- /* Free the memory used by the RG_WrapMusic */
92
- static void _rg_wrapmusic_free( RG_WrapMusic *wrap )
93
- {
94
- Mix_FreeMusic( wrap->music );
95
- wrap->music = NULL;
96
- free(wrap);
97
- }
98
-
99
-
100
-
101
-
102
- /* Associate a RG_WrapMusic with a RG_Music. Handles reference counts. */
103
- static inline void _rg_music_associate( RG_Music *music, RG_WrapMusic *wrap )
104
- {
105
- music->wrap = wrap;
106
- music->wrap->ref_count += 1;
107
- }
108
-
109
- /* Deassociate the RG_Music's WrapMusic. Handles reference counts. */
110
- static inline void _rg_music_deassociate( RG_Music *music )
111
- {
112
- music->wrap->ref_count -= 1;
113
- music->wrap = NULL;
114
- }
115
-
116
- /* Allocate/initialize the memory for a RG_Music and return a pointer. */
117
- static RG_Music* _rg_music_alloc()
118
- {
119
- RG_Music *music;
120
- music = ALLOC(RG_Music);
121
-
122
- music->wrap = NULL;
123
- music->volume = 1.f;
124
- music->repeats = 0;
125
-
126
- return music;
127
- }
128
-
129
-
130
- /*
131
- * Free the memory used by the RG_Music, and possibly the memory
132
- * used by the WrapMusic it refers to.
133
- */
134
- static void _rg_music_free( RG_Music *music )
135
- {
136
- RG_WrapMusic *wrap = music->wrap;
137
-
138
- _rg_music_deassociate( music );
139
-
140
- free(music);
141
-
142
- /* If the WrapMusic has no more referrers, free it too. */
143
- if( wrap->ref_count <= 0 )
144
- {
145
- _rg_wrapmusic_free( wrap );
146
- }
147
- }
148
-
149
-
150
- /* Load a new Music from a file. */
151
- static int _rg_music_load( RG_Music *music, char *file )
152
- {
153
- RG_WrapMusic *wrap = _rg_wrapmusic_alloc();
154
-
155
- int result = _rg_wrapmusic_load( wrap, file );
156
-
157
- _rg_music_associate( music, wrap );
158
-
159
- return result;
160
- }
161
-
162
-
163
- /*
164
- * Make a shallow copy of the given Music; the new Music points to
165
- * the same audio data in memory as the old one. Also copies
166
- * user-visible attributes (e.g. volume).
167
- */
168
- static void _rg_music_copy( RG_Music *music, RG_Music *other )
169
- {
170
- _rg_music_associate( music, other->wrap );
171
-
172
- music->volume = other->volume;
173
- }
174
-
175
-
176
- /* Make a new Music with a copy of the audio from an existing Music */
177
- static void _rg_music_deepcopy( RG_Music *music, RG_Music *other )
178
- {
179
- RG_WrapMusic *wrap = _rg_wrapmusic_alloc();
180
- _rg_wrapmusic_deepcopy( wrap, other->wrap );
181
-
182
- _rg_music_associate( music, wrap );
183
-
184
- music->volume = other->volume;
185
- }
186
-
187
-
188
- /*
189
- * Play the music, fading in, repeating, and starting at a time as specified.
190
- * fade_in and start_at are in milliseconds here!
191
- */
192
- static int _rg_music_play( RG_Music *music,
193
- int fade_in, int repeats, double start_at )
194
- {
195
-
196
- /* Open audio if it's not already. Return -1 if it failed. */
197
- if( ensure_open_audio() != 0 )
198
- {
199
- return -1;
200
- }
201
-
202
- /* Doing a little restart dance to please the SDL_mixer gods. */
203
- Mix_PlayMusic( music->wrap->music, 0 );
204
- Mix_HaltMusic();
205
-
206
- /* Set music channel volume before we play */
207
- Mix_VolumeMusic( (int)(MIX_MAX_VOLUME * music->volume) );
208
-
209
-
210
- if( fade_in <= 0 )
211
- {
212
- fade_in = 0;
213
- }
214
-
215
- if( start_at < 0 )
216
- {
217
- start_at = 0;
218
- }
219
-
220
- /* Remember repeats, for when we rewind or jump. */
221
- music->repeats = repeats;
222
-
223
- /* Play music as specified, and return whether it worked. */
224
- return Mix_FadeInMusicPos( music->wrap->music,
225
- repeats, fade_in, start_at );
226
-
227
- }
228
-
229
-
230
-
231
-
232
- /*
233
- * Return the Music which is currently set on the music channel (i.e.
234
- * was played most recently) or nil if no Music has ever been played.
235
- *
236
- * NOTE: The current Music could be playing, paused, or stopped. Use
237
- * #playing? or #stopped? if you want to know whether the current
238
- * music is still playing.
239
- */
240
- static VALUE rg_music_current( VALUE klass )
241
- {
242
- return rb_iv_get( cMusic, "@current_music" );
243
- }
244
-
245
-
246
- /* Set the currently-active Music to the given Music or nil.
247
- */
248
- static VALUE _rg_music_set_current( VALUE music )
249
- {
250
- return rb_iv_set( cMusic, "@current_music", music );
251
- }
252
-
253
-
254
- /* Check that the music is currently active on the music channel. */
255
- static int _rg_music_current_check( VALUE music )
256
- {
257
- return ( rg_music_current( cMusic ) == music );
258
- }
259
-
260
-
261
- /* Ruby allocation function. */
262
- static VALUE rg_music_alloc( VALUE klass )
263
- {
264
- RG_Music *music = _rg_music_alloc();
265
- return Data_Wrap_Struct(klass, 0, _rg_music_free, music);
266
- }
267
-
268
-
269
-
270
- /*
271
- * call-seq:
272
- * load( filename ) -> music
273
- *
274
- * Load the given audio file.
275
- * Supported file formats are WAVE, MOD, MIDI, OGG, and MP3.
276
- *
277
- * filename:: Full or relative path to the file. (String, required)
278
- *
279
- * Returns:: The new Music instance. (Music)
280
- * May raise:: SDLError, if the music file could not be loaded.
281
- *
282
- */
283
- static VALUE rg_music_load( VALUE klass, VALUE filename )
284
- {
285
- RG_Music *music;
286
-
287
- VALUE s = rg_music_alloc( cMusic );
288
-
289
- Data_Get_Struct( s, RG_Music, music );
290
-
291
- char *file = StringValuePtr( filename );
292
-
293
- int result = _rg_music_load( music, file );
294
-
295
- if( result == -1 )
296
- {
297
- rb_raise(eSDLError, "Could not load Music file '%s': %s",
298
- file, Mix_GetError());
299
- }
300
-
301
- return s;
302
- }
303
-
304
-
305
- /*
306
- * call-seq:
307
- * Music.autoload( filename ) -> Surface or nil
308
- *
309
- * Searches each directory in Music.autoload_dirs for a file with
310
- * the given filename. If it finds that file, loads it and returns
311
- * a Music instance. If it doesn't find the file, returns nil.
312
- *
313
- * See Rubygame::NamedResource for more information about this
314
- * functionality.
315
- *
316
- */
317
- VALUE rg_music_autoload( VALUE klass, VALUE namev )
318
- {
319
- VALUE pathv = rb_funcall( klass, rb_intern("find_file"), 1, namev );
320
-
321
- if( RTEST(pathv) )
322
- {
323
- return rg_music_load( klass, pathv );
324
- }
325
- else
326
- {
327
- return Qnil;
328
- }
329
- }
330
-
331
-
332
- /*
333
- * call-seq:
334
- * new
335
- *
336
- * **NOTE**: Don't use this method. Use Music.load.
337
- *
338
- * Raises NotImplementedError.
339
- *
340
- */
341
- static VALUE rg_music_new( int argc, VALUE *ARGV, VALUE self )
342
- {
343
- rb_raise(rb_eNotImpError, "Music.new is not implemented. Use Music.load to load a music file.");
344
- }
345
-
346
- /*
347
- * call-seq:
348
- * clone( other ) -> music
349
- * dup( other ) -> music
350
- *
351
- * Create a copy of the given Music instance. More efficient
352
- * than using #load to load the music file again.
353
- *
354
- * other:: An existing Music instance. (Music, required)
355
- *
356
- * Returns:: The new Music instance. (Music)
357
- *
358
- * **NOTE**: #clone and #dup do slightly different things; #clone will copy
359
- * the 'frozen' state of the object, while #dup will create a fresh, un-frozen
360
- * object.
361
- *
362
- */
363
- static VALUE rg_music_initialize_copy( VALUE self, VALUE other )
364
- {
365
- RG_Music *musicA, *musicB;
366
- Data_Get_Struct(self, RG_Music, musicA);
367
- Data_Get_Struct(other, RG_Music, musicB);
368
-
369
- _rg_music_copy( musicA, musicB );
370
-
371
- return self;
372
- }
373
-
374
-
375
-
376
-
377
- /*
378
- * call-seq:
379
- * play( options={:fade_in => 0, :repeats => 0, :start_at => 0} ) -> self
380
- *
381
- * Play the Music, optionally fading in, repeating a certain number
382
- * of times (or forever), and/or starting at a certain position in
383
- * the song.
384
- *
385
- * See also #pause and #stop.
386
- *
387
- * options:: Hash of options, listed below. (Hash, required)
388
- *
389
- * :fade_in:: Fade in from silence over the given number of
390
- * seconds. Default: 0. (Numeric, optional)
391
- * :repeats:: Repeat the music the given number of times, or
392
- * forever (or until stopped) if -1. Default: 0.
393
- * (Integer, optional)
394
- * :start_at:: Start playing the music at the given time in the
395
- * song, in seconds. Default: 0. (Numeric, optional)
396
- * **NOTE**: Non-zero start times only work for
397
- * OGG and MP3 formats! Please refer to #jump.
398
- *
399
- *
400
- * Returns:: The receiver (self).
401
- * May raise:: SDLError, if the music file could not be played, or
402
- * if you used :start_at with an unsupported format.
403
- *
404
- * **NOTE**: Only one music can be playing at once. If any music is
405
- * already playing (or paused), it will be stopped before playing the
406
- * new music.
407
- *
408
- * Example:
409
- * # Fade in over 2 seconds, play 4 times (1 + 3 repeats),
410
- * # starting at 60 seconds since the beginning of the song.
411
- * music.play( :fade_in => 2, :repeats => 3, :start_at => 60 );
412
- *
413
- */
414
- static VALUE rg_music_play( int argc, VALUE *argv, VALUE self )
415
- {
416
- RG_Music *music;
417
- Data_Get_Struct(self, RG_Music, music);
418
-
419
- VALUE options;
420
- rb_scan_args(argc, argv, "01", &options);
421
-
422
- int fade_in = 0;
423
- int repeats = 1;
424
- double start_at = 0;
425
-
426
- /* If we got some options */
427
- if( RTEST(options) )
428
- {
429
- /* Make sure options is a Hash table */
430
- if( TYPE(options) != T_HASH )
431
- {
432
- rb_raise(rb_eTypeError, "wrong argument type %s (expected Hash)",
433
- rb_obj_classname(options));
434
- }
435
-
436
- VALUE temp;
437
-
438
-
439
- temp = rb_hash_aref(options, make_symbol("fade_in"));
440
- if( RTEST(temp) )
441
- {
442
- fade_in = (int)(1000 * NUM2DBL( temp ));
443
-
444
- if( fade_in < 0 )
445
- {
446
- rb_raise(rb_eArgError, ":fade_in cannot be negative (got %.2f)",
447
- fade_in / 1000);
448
- }
449
- else if( fade_in < 50 )
450
- {
451
- /* Work-around for a bug with SDL_mixer not working with small non-zero fade-ins */
452
- fade_in = 0;
453
- }
454
- }
455
-
456
-
457
- temp = rb_hash_aref(options, make_symbol("repeats"));
458
- if( RTEST(temp) )
459
- {
460
- repeats = NUM2INT(temp);
461
-
462
- if( repeats > -1 )
463
- {
464
- /* Adjust so repeats means the same as it does for Sound */
465
- repeats += 1;
466
- }
467
-
468
- if( repeats < -1 )
469
- {
470
- rb_raise(rb_eArgError, ":repeats cannot be negative, except -1 (got %d)",
471
- repeats);
472
- }
473
- }
474
-
475
-
476
- temp = rb_hash_aref(options, make_symbol("start_at"));
477
- if( RTEST(temp) )
478
- {
479
- start_at = (double)(NUM2DBL( temp ));
480
-
481
- if( start_at < 0 )
482
- {
483
- rb_raise(rb_eArgError, ":start_at cannot be negative (got %.2f)",
484
- start_at);
485
- }
486
- }
487
-
488
- }
489
-
490
- int result = _rg_music_play( music, fade_in, repeats, start_at );
491
-
492
- if( result == -1 )
493
- {
494
- rb_raise(eSDLError, "Could not play Music: %s", Mix_GetError());
495
- }
496
-
497
- /* This music is now current. */
498
- _rg_music_set_current( self );
499
-
500
- return self;
501
- }
502
-
503
-
504
- /*
505
- * call-seq:
506
- * playing? -> true or false
507
- *
508
- * True if the Music is currently playing (not paused or stopped).
509
- * See also #paused? and #stopped?.
510
- *
511
- */
512
- static VALUE rg_music_playingp( VALUE self )
513
- {
514
- RG_Music *music;
515
- Data_Get_Struct(self, RG_Music, music);
516
-
517
- /* Check that the music is current. */
518
- if( _rg_music_current_check(self) )
519
- {
520
- /* Return true if music is playing, but not paused. */
521
- if( Mix_PlayingMusic() && !Mix_PausedMusic() )
522
- {
523
- return Qtrue;
524
- }
525
- else
526
- {
527
- return Qfalse;
528
- }
529
- }
530
- else
531
- {
532
- return Qfalse;
533
- }
534
- }
535
-
536
-
537
-
538
- /*
539
- * call-seq:
540
- * pause -> self
541
- *
542
- * Pause the Music. Unlike #stop, it can be unpaused later to resume
543
- * from where it was paused. See also #unpause and #paused?.
544
- *
545
- * Returns:: The receiver (self).
546
- *
547
- * **NOTE**: Does nothing if the music is not currently playing.
548
- *
549
- */
550
- static VALUE rg_music_pause( VALUE self )
551
- {
552
- RG_Music *music;
553
- Data_Get_Struct(self, RG_Music, music);
554
-
555
- /* Check that the music is current. */
556
- if( _rg_music_current_check(self) )
557
- {
558
- Mix_PauseMusic();
559
- }
560
-
561
- return self;
562
- }
563
-
564
-
565
- /*
566
- * call-seq:
567
- * unpause -> self
568
- *
569
- * Unpause the Music, if it is currently paused. Resumes from
570
- * where it was paused. See also #pause and #paused?.
571
- *
572
- * Returns:: The receiver (self).
573
- *
574
- * **NOTE**: Does nothing if the music is not currently paused.
575
- *
576
- */
577
- static VALUE rg_music_unpause( VALUE self )
578
- {
579
- RG_Music *music;
580
- Data_Get_Struct(self, RG_Music, music);
581
-
582
- /* Check that the music is current. */
583
- if( _rg_music_current_check(self) )
584
- {
585
- Mix_ResumeMusic();
586
- }
587
-
588
- return self;
589
- }
590
-
591
-
592
- /*
593
- * call-seq:
594
- * paused? -> true or false
595
- *
596
- * True if the Music is currently paused (not playing or stopped).
597
- * See also #playing? and #stopped?.
598
- *
599
- */
600
- static VALUE rg_music_pausedp( VALUE self )
601
- {
602
- RG_Music *music;
603
- Data_Get_Struct(self, RG_Music, music);
604
-
605
- /* Check that the music is current. */
606
- if( _rg_music_current_check(self) )
607
- {
608
- /* Return true if it's "playing" (not stopped), as well as paused. */
609
- if( Mix_PlayingMusic() && Mix_PausedMusic() )
610
- {
611
- return Qtrue;
612
- }
613
- else
614
- {
615
- return Qfalse;
616
- }
617
- }
618
- else
619
- {
620
- return Qfalse;
621
- }
622
- }
623
-
624
-
625
-
626
- /*
627
- * call-seq:
628
- * stop -> self
629
- *
630
- * Stop the Music. Unlike #pause, the music must be played again from
631
- * the beginning, it cannot be resumed from it was stopped.
632
- *
633
- * Returns:: The receiver (self).
634
- *
635
- * **NOTE**: Does nothing if the music is not currently playing or paused.
636
- *
637
- */
638
- static VALUE rg_music_stop( VALUE self )
639
- {
640
- RG_Music *music;
641
- Data_Get_Struct(self, RG_Music, music);
642
-
643
- /* Check that the music is current. */
644
- if( _rg_music_current_check(self) )
645
- {
646
- Mix_HaltMusic();
647
- }
648
-
649
- return self;
650
- }
651
-
652
-
653
- /*
654
- * call-seq:
655
- * stopped? -> true or false
656
- *
657
- * True if the Music is currently stopped (not playing or paused).
658
- * See also #playing? and #paused?.
659
- *
660
- */
661
- static VALUE rg_music_stoppedp( VALUE self )
662
- {
663
- RG_Music *music;
664
- Data_Get_Struct(self, RG_Music, music);
665
-
666
- /* Check that the music is current. */
667
- if( _rg_music_current_check(self) )
668
- {
669
- /* Return true if it's not playing. */
670
- if( !Mix_PlayingMusic() )
671
- {
672
- return Qtrue;
673
- }
674
- else
675
- {
676
- return Qfalse;
677
- }
678
- }
679
- else
680
- {
681
- return Qtrue;
682
- }
683
- }
684
-
685
-
686
- /*
687
- * call-seq:
688
- * fade_out( fade_time ) -> self
689
- *
690
- * Fade out to silence over the given number of seconds. Once the music
691
- * is silent, it is automatically stopped.
692
- *
693
- * Returns:: The receiver (self).
694
- *
695
- * **NOTE**: If the music is currently paused, the fade will start,
696
- * but you won't be able to hear it happening unless you #unpause during
697
- * the fade.
698
- *
699
- * Does nothing if the music is currently stopped.
700
- *
701
- */
702
- static VALUE rg_music_fadeout( VALUE self, VALUE fade_time )
703
- {
704
- RG_Music *music;
705
- Data_Get_Struct(self, RG_Music, music);
706
-
707
- int fade_ms = (int)(1000 * NUM2DBL(fade_time));
708
-
709
- if( fade_ms < 0 )
710
- {
711
- rb_raise(rb_eArgError, "fade_time cannot be negative (got %.2f)",
712
- fade_ms / 1000);
713
- }
714
-
715
- /* Check that the music is current */
716
- if( _rg_music_current_check(self) )
717
- {
718
- int result = Mix_FadeOutMusic( fade_ms );
719
-
720
- if ( result < 0 )
721
- {
722
- rb_raise(eSDLError, "Error fading out music: %s", Mix_GetError());
723
- }
724
-
725
- }
726
-
727
- return self;
728
- }
729
-
730
-
731
- /*
732
- * call-seq:
733
- * fading?( direction=:either ) -> true or false
734
- *
735
- * True if the Music is currently fading in or out.
736
- * See also #play and #fade_out.
737
- *
738
- * direction:: Check if it is fading :in, :out, or :either.
739
- * (Symbol, required)
740
- *
741
- */
742
- static VALUE rg_music_fadingp( int argc, VALUE *argv, VALUE self )
743
- {
744
- RG_Music *music;
745
- Data_Get_Struct(self, RG_Music, music);
746
-
747
- VALUE vdirection;
748
- rb_scan_args(argc, argv, "01", &vdirection);
749
-
750
- /* If the music is not current, return false right away. */
751
- if( !(_rg_music_current_check(self)) )
752
- {
753
- return Qfalse;
754
- }
755
-
756
- if( RTEST(vdirection) )
757
- {
758
- if( make_symbol("in") == vdirection )
759
- {
760
- return ( (Mix_FadingMusic() == MIX_FADING_IN) ? Qtrue : Qfalse );
761
- }
762
-
763
- else if( make_symbol("out") == vdirection )
764
- {
765
- return ( (Mix_FadingMusic() == MIX_FADING_OUT) ? Qtrue : Qfalse );
766
- }
767
-
768
- else if( make_symbol("either") == vdirection )
769
- {
770
- return ( (Mix_FadingMusic() != MIX_NO_FADING) ? Qtrue : Qfalse );
771
- }
772
- }
773
-
774
- /* default */
775
- return ( (Mix_FadingMusic() != MIX_NO_FADING) ? Qtrue : Qfalse );
776
- }
777
-
778
-
779
-
780
- /*
781
- * call-seq:
782
- * volume -> vol
783
- *
784
- * Return the volume level of the music.
785
- * 0.0 is totally silent, 1.0 is full volume.
786
- *
787
- * **NOTE**: Ignores fading in or out.
788
- *
789
- */
790
- static VALUE rg_music_getvolume( VALUE self )
791
- {
792
- RG_Music *music;
793
- Data_Get_Struct(self, RG_Music, music);
794
-
795
- return rb_float_new(music->volume);
796
- }
797
-
798
-
799
- /*
800
- * call-seq:
801
- * volume = new_vol
802
- *
803
- * Set the new #volume level of the music.
804
- * 0.0 is totally silent, 1.0 is full volume.
805
- *
806
- * Volume cannot be set while the music is fading in or out.
807
- * Be sure to check #fading? or rescue from SDLError when
808
- * using this method.
809
- *
810
- * May raise:: SDLError if the music is fading in or out.
811
- *
812
- */
813
- static VALUE rg_music_setvolume( VALUE self, VALUE volume )
814
- {
815
- RG_Music *music;
816
- Data_Get_Struct(self, RG_Music, music);
817
-
818
- /* If the music is current, we'll change the current volume. */
819
- if( _rg_music_current_check(self) )
820
- {
821
- /* But only if it's not fading right now. */
822
- if( Mix_FadingMusic() == MIX_NO_FADING )
823
- {
824
- music->volume = NUM2DBL(volume);
825
- Mix_VolumeMusic( (int)(MIX_MAX_VOLUME * music->volume) );
826
- }
827
- else
828
- {
829
- rb_raise(eSDLError, "cannot set Music volume while fading");
830
- }
831
- }
832
- else
833
- {
834
- /* Save it for later. */
835
- music->volume = NUM2DBL(volume);
836
- }
837
-
838
- return volume;
839
- }
840
-
841
-
842
- /*
843
- * call-seq:
844
- * rewind -> self
845
- *
846
- * Rewind the Music to the beginning. If the Music was paused, it
847
- * will still be paused after the rewind. Does nothing if the Music
848
- * is stopped.
849
- */
850
- static VALUE rg_music_rewind( VALUE self )
851
- {
852
- RG_Music *music;
853
- Data_Get_Struct(self, RG_Music, music);
854
-
855
- /* Check that the music is current. */
856
- if( _rg_music_current_check(self) )
857
- {
858
- /* Only do anything if it's not stopped */
859
- if( !rg_music_stoppedp(self) )
860
- {
861
- /* Remember whether it was paused. */
862
- int was_paused = Mix_PausedMusic();
863
-
864
- /*
865
- * Rather than using SDL_mixer's crippled Mix_RewindMusic,
866
- * which only works for a few file types, we'll just stop and
867
- * start the music again from the beginning.
868
- */
869
- Mix_HaltMusic();
870
- int result = Mix_PlayMusic(music->wrap->music, music->repeats);
871
-
872
- if( result == -1 )
873
- {
874
- rb_raise(eSDLError, "Could not rewind Music: %s", Mix_GetError());
875
- }
876
-
877
- /* Pause it again if it was paused before. */
878
- if( was_paused )
879
- {
880
- Mix_PauseMusic();
881
- }
882
- }
883
- }
884
-
885
- return self;
886
- }
887
-
888
-
889
- /*
890
- * call-seq:
891
- * jump_to( time ) -> self
892
- *
893
- * Jump to any time in the Music, in seconds since the beginning.
894
- * If the Music was paused, it will still be paused again after the
895
- * jump. Does nothing if the Music was stopped.
896
- *
897
- * **NOTE**: Only works for OGG and MP3 formats! Other formats (e.g.
898
- * WAV) will usually raise SDLError.
899
- *
900
- * time:: the time to jump to, in seconds since the beginning
901
- * of the song. (Numeric, required)
902
- *
903
- * May raise:: SDLError if something goes wrong, or if the music
904
- * type does not support jumping.
905
- *
906
- * **CAUTION**: This method may be unreliable (and could even crash!)
907
- * if you jump to a time after the end of the song. Unfortunately,
908
- * SDL_Mixer does not provide a way to find the song's length, so
909
- * Rubygame cannot warn you if you go off the end. Be careful!
910
- */
911
- static VALUE rg_music_jumpto( VALUE self, VALUE vtime )
912
- {
913
- RG_Music *music;
914
- Data_Get_Struct(self, RG_Music, music);
915
-
916
- /* Check that the music is current. */
917
- if( _rg_music_current_check(self) )
918
- {
919
- /* Only do anything if it's not stopped */
920
- if( !rg_music_stoppedp(self) )
921
- {
922
- /* Remember whether it was paused. */
923
- int was_paused = Mix_PausedMusic();
924
-
925
- double time = NUM2DBL(vtime); /* in seconds */
926
-
927
- if( time < 0 )
928
- {
929
- rb_raise(rb_eArgError, "jump_to time cannot be negative (got %d)", time);
930
- }
931
-
932
- int result = Mix_SetMusicPosition( time );
933
-
934
- if( result == -1 )
935
- {
936
- rb_raise(eSDLError, "Could not jump Music: %s", Mix_GetError());
937
- }
938
-
939
- /* Pause it again if it was paused before. */
940
- if( was_paused )
941
- {
942
- Mix_PauseMusic();
943
- }
944
- }
945
- }
946
-
947
- return self;
948
- }
949
-
950
-
951
-
952
- void Rubygame_Init_Music()
953
- {
954
- #if 0
955
- mRubygame = rb_define_module("Rubygame");
956
- #endif
957
-
958
- /*
959
- * **IMPORTANT**: Music is only available if Rubygame was compiled
960
- * with SDL_mixer support!
961
- *
962
- * Music holds a song, streamed from an audio file (see #load for
963
- * supported formats). There are two important differences between
964
- * the Music and Sound classes:
965
- *
966
- * 1. Only one Music can be playing. If you try to play
967
- * a second song, the first one will be stopped.
968
- *
969
- * 2. Music doesn't load the entire audio file, so it can begin
970
- * quickly and doesn't use much memory. This is good,
971
- * because songs are usually much longer than sound effects!
972
- *
973
- * Music can #play, #pause/#unpause, #stop, #rewind, #jump_to another
974
- * time, adjust #volume, and #fade_out (fade in by passing an option
975
- * to #play).
976
- *
977
- * Music includes the Rubygame::NamedResource mixin module, which
978
- * can perform autoloading of music on demand, among other things.
979
- *
980
- */
981
- cMusic = rb_define_class_under(mRubygame,"Music",rb_cObject);
982
-
983
- /* Include the Rubygame::NamedResource mixin module. */
984
- rg_include_named_resource(cMusic);
985
-
986
- rb_define_singleton_method( cMusic, "current_music", rg_music_current, 0 );
987
- rb_iv_set( cMusic, "@current_music", Qnil );
988
-
989
-
990
- rb_define_alloc_func( cMusic, rg_music_alloc );
991
-
992
- rb_define_singleton_method( cMusic, "new", rg_music_new, -1 );
993
- rb_define_singleton_method( cMusic, "load", rg_music_load, 1 );
994
-
995
- rb_define_singleton_method( cMusic, "autoload", rg_music_autoload, 1 );
996
-
997
- rb_define_method( cMusic, "initialize_copy", rg_music_initialize_copy, 1 );
998
-
999
- rb_define_method( cMusic, "play", rg_music_play, -1 );
1000
- rb_define_method( cMusic, "playing?", rg_music_playingp, 0 );
1001
-
1002
- rb_define_method( cMusic, "pause", rg_music_pause, 0 );
1003
- rb_define_method( cMusic, "unpause", rg_music_unpause, 0 );
1004
- rb_define_method( cMusic, "paused?", rg_music_pausedp, 0 );
1005
-
1006
- rb_define_method( cMusic, "stop", rg_music_stop, 0 );
1007
- rb_define_method( cMusic, "stopped?", rg_music_stoppedp, 0 );
1008
-
1009
- rb_define_method( cMusic, "fade_out", rg_music_fadeout, 1 );
1010
- rb_define_method( cMusic, "fading?", rg_music_fadingp, -1 );
1011
-
1012
- rb_define_method( cMusic, "volume", rg_music_getvolume, 0 );
1013
- rb_define_method( cMusic, "volume=", rg_music_setvolume, 1 );
1014
-
1015
- rb_define_method( cMusic, "rewind", rg_music_rewind, 0 );
1016
- rb_define_method( cMusic, "jump_to", rg_music_jumpto, 1 );
1017
- }