rubygame 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CREDITS +50 -0
  2. data/Changelog +162 -0
  3. data/LICENSE +504 -0
  4. data/README +122 -0
  5. data/Rakefile +380 -0
  6. data/TODO +45 -0
  7. data/doc/extended_readme.rdoc +49 -0
  8. data/doc/getting_started.rdoc +47 -0
  9. data/doc/macosx_install.rdoc +74 -0
  10. data/doc/windows_install.rdoc +124 -0
  11. data/ext/rubygame/MANIFEST +25 -0
  12. data/ext/rubygame/rubygame_event.c +644 -0
  13. data/ext/rubygame/rubygame_event.h +48 -0
  14. data/ext/rubygame/rubygame_gfx.c +951 -0
  15. data/ext/rubygame/rubygame_gfx.h +102 -0
  16. data/ext/rubygame/rubygame_gl.c +154 -0
  17. data/ext/rubygame/rubygame_gl.h +32 -0
  18. data/ext/rubygame/rubygame_image.c +108 -0
  19. data/ext/rubygame/rubygame_image.h +41 -0
  20. data/ext/rubygame/rubygame_joystick.c +247 -0
  21. data/ext/rubygame/rubygame_joystick.h +41 -0
  22. data/ext/rubygame/rubygame_main.c +155 -0
  23. data/ext/rubygame/rubygame_main.h +33 -0
  24. data/ext/rubygame/rubygame_mixer.c +764 -0
  25. data/ext/rubygame/rubygame_mixer.h +62 -0
  26. data/ext/rubygame/rubygame_screen.c +420 -0
  27. data/ext/rubygame/rubygame_screen.h +41 -0
  28. data/ext/rubygame/rubygame_shared.c +152 -0
  29. data/ext/rubygame/rubygame_shared.h +54 -0
  30. data/ext/rubygame/rubygame_surface.c +1107 -0
  31. data/ext/rubygame/rubygame_surface.h +62 -0
  32. data/ext/rubygame/rubygame_time.c +183 -0
  33. data/ext/rubygame/rubygame_time.h +32 -0
  34. data/ext/rubygame/rubygame_ttf.c +600 -0
  35. data/ext/rubygame/rubygame_ttf.h +69 -0
  36. data/lib/rubygame.rb +40 -0
  37. data/lib/rubygame/MANIFEST +12 -0
  38. data/lib/rubygame/clock.rb +128 -0
  39. data/lib/rubygame/constants.rb +238 -0
  40. data/lib/rubygame/event.rb +313 -0
  41. data/lib/rubygame/ftor.rb +370 -0
  42. data/lib/rubygame/hotspot.rb +265 -0
  43. data/lib/rubygame/keyconstants.rb +237 -0
  44. data/lib/rubygame/mediabag.rb +94 -0
  45. data/lib/rubygame/queue.rb +288 -0
  46. data/lib/rubygame/rect.rb +614 -0
  47. data/lib/rubygame/sfont.rb +223 -0
  48. data/lib/rubygame/sprite.rb +477 -0
  49. data/samples/FreeSans.ttf +0 -0
  50. data/samples/GPL.txt +340 -0
  51. data/samples/README +40 -0
  52. data/samples/chimp.bmp +0 -0
  53. data/samples/chimp.rb +313 -0
  54. data/samples/demo_gl.rb +151 -0
  55. data/samples/demo_gl_tex.rb +197 -0
  56. data/samples/demo_music.rb +75 -0
  57. data/samples/demo_rubygame.rb +279 -0
  58. data/samples/demo_sfont.rb +52 -0
  59. data/samples/demo_ttf.rb +193 -0
  60. data/samples/demo_utf8.rb +53 -0
  61. data/samples/fist.bmp +0 -0
  62. data/samples/load_and_blit.rb +22 -0
  63. data/samples/panda.png +0 -0
  64. data/samples/punch.wav +0 -0
  65. data/samples/ruby.png +0 -0
  66. data/samples/term16.png +0 -0
  67. data/samples/whiff.wav +0 -0
  68. metadata +123 -0
@@ -0,0 +1,41 @@
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
+
22
+ #ifndef _RUBYGAME_JOYSTICK_H
23
+ #define _RUBYGAME_JOYSTICK_H
24
+
25
+ extern void Rubygame_Init_Joystick();
26
+
27
+ extern VALUE cJoy;
28
+
29
+ extern VALUE rbgm_joy_numjoysticks(VALUE);
30
+ extern VALUE rbgm_joy_getname(VALUE, VALUE);
31
+
32
+ extern VALUE rbgm_joystick_new(VALUE, VALUE);
33
+
34
+ extern VALUE rbgm_joystick_index(VALUE);
35
+ extern VALUE rbgm_joystick_name(VALUE);
36
+ extern VALUE rbgm_joystick_numaxes(VALUE);
37
+ extern VALUE rbgm_joystick_numballs(VALUE);
38
+ extern VALUE rbgm_joystick_numhats(VALUE);
39
+ extern VALUE rbgm_joystick_numbuttons(VALUE);
40
+
41
+ #endif
@@ -0,0 +1,155 @@
1
+ /*
2
+ *--
3
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
4
+ * Copyright (C) 2004-2007 John Croisant
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *++
20
+ */
21
+
22
+ #include "rubygame_shared.h"
23
+ #include "rubygame_main.h"
24
+ #include "rubygame_event.h"
25
+ #include "rubygame_gl.h"
26
+ #include "rubygame_joystick.h"
27
+ #include "rubygame_screen.h"
28
+ #include "rubygame_surface.h"
29
+ #include "rubygame_time.h"
30
+
31
+ VALUE rbgm_init(VALUE);
32
+ VALUE rbgm_quit(VALUE);
33
+ void Define_Rubygame_Constants();
34
+
35
+ /*
36
+ * call-seq:
37
+ * key_name(sym) -> string
38
+ *
39
+ * Given the sym of a key, returns a printable representation. This
40
+ * differs from key2str in that this will return a printable string
41
+ * for any key, even non-printable keys such as the arrow keys.
42
+ *
43
+ * This method may raise SDLError if the SDL video subsystem could
44
+ * not be initialized for some reason.
45
+ *
46
+ * Example:
47
+ * Rubygame.key_name( Rubygame::K_A ) # => "a"
48
+ * Rubygame.key_name( Rubygame::K_RETURN ) # => "return"
49
+ * Rubygame.key_name( Rubygame::K_LEFT ) # => "left"
50
+ */
51
+ VALUE rbgm_keyname(VALUE self, VALUE sym)
52
+ {
53
+ /* SDL_GetKeyName only works when video system has been initialized. */
54
+ if( init_video_system() == 0 )
55
+ {
56
+ SDLKey key = NUM2INT(sym);
57
+ char *result = SDL_GetKeyName(key);
58
+ return rb_str_new2(result);
59
+ }
60
+ else
61
+ {
62
+ rb_raise(eSDLError,"Could not initialize SDL video subsystem.");
63
+ return Qnil;
64
+ }
65
+ }
66
+
67
+
68
+ /*
69
+ * call-seq:
70
+ * init -> nil
71
+ *
72
+ * Initialize Rubygame. This should be called soon after you +require+
73
+ * Rubygame, so that everything will work properly.
74
+ */
75
+ VALUE rbgm_init(VALUE module)
76
+ {
77
+ if(SDL_Init(SDL_INIT_EVERYTHING)==0)
78
+ {
79
+ return Qnil;
80
+ }
81
+ else
82
+ {
83
+ rb_raise(eSDLError,"Could not initialize SDL.");
84
+ return Qnil; /* should never get here */
85
+ }
86
+ }
87
+
88
+ /*
89
+ * call-seq:
90
+ * quit -> nil
91
+ *
92
+ * Quit Rubygame. This should be used before your program terminates,
93
+ * especially if you have been using a fullscreen Screen! (Otherwise,
94
+ * the desktop resolution might not revert to its previous setting on
95
+ * some platforms, and your users will be frustrated and confused!)
96
+ */
97
+ VALUE rbgm_quit(VALUE module)
98
+ {
99
+ SDL_Quit();
100
+ return Qnil;
101
+ }
102
+
103
+
104
+ void Init_rubygame_core()
105
+ {
106
+ Init_rubygame_shared();
107
+
108
+ mRubygame = rb_define_module("Rubygame");
109
+
110
+ rb_define_module_function(mRubygame,"init",rbgm_init,0);
111
+ rb_define_module_function(mRubygame,"quit",rbgm_quit,0);
112
+ rb_define_singleton_method(mRubygame,"key_name",rbgm_keyname, 1);
113
+ cRect = rb_define_class_under(mRubygame,"Rect",rb_cArray);
114
+
115
+ rb_hash_aset(rb_ivar_get(mRubygame,rb_intern("VERSIONS")),
116
+ ID2SYM(rb_intern("rubygame")),
117
+ rb_ary_new3(3,
118
+ INT2NUM(RUBYGAME_MAJOR_VERSION),
119
+ INT2NUM(RUBYGAME_MINOR_VERSION),
120
+ INT2NUM(RUBYGAME_PATCHLEVEL)));
121
+ rb_hash_aset(rb_ivar_get(mRubygame,rb_intern("VERSIONS")),
122
+ ID2SYM(rb_intern("sdl")),
123
+ rb_ary_new3(3,
124
+ INT2NUM(SDL_MAJOR_VERSION),
125
+ INT2NUM(SDL_MINOR_VERSION),
126
+ INT2NUM(SDL_PATCHLEVEL)));
127
+
128
+ Rubygame_Init_Time();
129
+ Rubygame_Init_Surface();
130
+ Rubygame_Init_Screen();
131
+ Rubygame_Init_Event();
132
+ Rubygame_Init_Joystick();
133
+ Rubygame_Init_GL();
134
+
135
+ /* Flags for subsystem initialization */
136
+ rb_define_const(mRubygame,"INIT_TIMER",INT2NUM(SDL_INIT_TIMER));
137
+ rb_define_const(mRubygame,"INIT_AUDIO",INT2NUM(SDL_INIT_AUDIO));
138
+ rb_define_const(mRubygame,"INIT_VIDEO",INT2NUM(SDL_INIT_VIDEO));
139
+ rb_define_const(mRubygame,"INIT_CDROM",INT2NUM(SDL_INIT_CDROM));
140
+ rb_define_const(mRubygame,"INIT_JOYSTICK",INT2NUM(SDL_INIT_JOYSTICK));
141
+ rb_define_const(mRubygame,"INIT_NOPARACHUTE",INT2NUM(SDL_INIT_NOPARACHUTE));
142
+ rb_define_const(mRubygame,"INIT_EVENTTHREAD",UINT2NUM(SDL_INIT_EVENTTHREAD));
143
+ rb_define_const(mRubygame,"INIT_EVERYTHING",UINT2NUM(SDL_INIT_EVERYTHING));
144
+
145
+
146
+ /* Define fully opaque and full transparent (0 and 255) */
147
+ rb_define_const(mRubygame,"ALPHA_OPAQUE",UINT2NUM(SDL_ALPHA_OPAQUE));
148
+ rb_define_const(mRubygame,"ALPHA_TRANSPARENT",
149
+ UINT2NUM(SDL_ALPHA_TRANSPARENT));
150
+
151
+
152
+ /* Flags for palettes (?) */
153
+ rb_define_const(mRubygame,"LOGPAL",UINT2NUM(SDL_LOGPAL));
154
+ rb_define_const(mRubygame,"PHYSPAL",UINT2NUM(SDL_PHYSPAL));
155
+ }
@@ -0,0 +1,33 @@
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_H
22
+ #define _RUBYGAME_H
23
+
24
+ #define RUBYGAME_MAJOR_VERSION 2
25
+ #define RUBYGAME_MINOR_VERSION 0
26
+ #define RUBYGAME_PATCHLEVEL 1
27
+
28
+ extern VALUE rbgm_keyname(VALUE, VALUE);
29
+ extern VALUE rbgm_init(VALUE);
30
+ extern VALUE rbgm_quit(VALUE);
31
+ extern void Define_Rubygame_Constants();
32
+
33
+ #endif
@@ -0,0 +1,764 @@
1
+ /*
2
+ * Interface to SDL_mixer, for audio playback and mixing.
3
+ *--
4
+ * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
5
+ * Copyright (C) 2004-2007 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 "rubygame_shared.h"
24
+ #include "rubygame_mixer.h"
25
+
26
+ void Init_rubygame_mixer();
27
+ VALUE mMixer;
28
+
29
+ VALUE rbgm_mixer_openaudio(int, VALUE*, VALUE);
30
+ VALUE rbgm_mixer_closeaudio(VALUE);
31
+ VALUE rbgm_mixer_getmixchans();
32
+ VALUE rbgm_mixer_setmixchans(VALUE, VALUE);
33
+ VALUE rbgm_mixer_getdrivername(VALUE);
34
+
35
+ VALUE cSample;
36
+ VALUE rbgm_sample_new(VALUE, VALUE);
37
+ VALUE rbgm_mixchan_play( VALUE, VALUE, VALUE, VALUE );
38
+ VALUE rbgm_mixchan_stop( VALUE, VALUE );
39
+ VALUE rbgm_mixchan_pause( VALUE, VALUE );
40
+ VALUE rbgm_mixchan_resume( VALUE, VALUE );
41
+
42
+ VALUE cMusic;
43
+ VALUE rbgm_mixmusic_setcommand(VALUE, VALUE);
44
+ VALUE rbgm_mixmusic_new(VALUE, VALUE);
45
+
46
+ VALUE rbgm_mixmusic_play(int, VALUE*, VALUE);
47
+ VALUE rbgm_mixmusic_stop(VALUE);
48
+ VALUE rbgm_mixmusic_resume(VALUE);
49
+ VALUE rbgm_mixmusic_pause(VALUE);
50
+ VALUE rbgm_mixmusic_rewind(VALUE);
51
+ VALUE rbgm_mixmusic_jump(VALUE, VALUE);
52
+ VALUE rbgm_mixmusic_paused(VALUE);
53
+ VALUE rbgm_mixmusic_playing(VALUE);
54
+
55
+ VALUE rbgm_mixmusic_getvolume(VALUE);
56
+ VALUE rbgm_mixmusic_setvolume(VALUE, VALUE);
57
+ VALUE rbgm_mixmusic_fadein(int, VALUE*, VALUE);
58
+ VALUE rbgm_mixmusic_fadeout(VALUE, VALUE);
59
+ VALUE rbgm_mixmusic_fading(int, VALUE*, VALUE);
60
+
61
+
62
+ /* --
63
+ * SETUP AND INITIALIZATION
64
+ * ++
65
+ */
66
+
67
+ /* call-seq:
68
+ * open_audio( frequency=nil, format=nil, channels=nil, buffer=nil)
69
+ *
70
+ * Initializes the audio device. You must call this before using the other
71
+ * mixer functions. See also #close_audio().
72
+ *
73
+ * Returns nil. May raise an SDLError if initialization fails.
74
+ *
75
+ * This method takes these arguments:
76
+ *
77
+ * frequency:: output sample rate in audio samples per second (Hz).
78
+ * Affects the quality of the sound output, at the expense of
79
+ * CPU usage. If nil, the default (22050) is used. 22050 is
80
+ * recommended for most games. For reference, 44100 is CD quality.
81
+ * The larger the value, the more processing required.
82
+ *
83
+ * format:: output sample format. If nil, the default recommended system
84
+ * format is used. It's _highly_ recommended you leave this nil!
85
+ *
86
+ * But if you're feeling reckless, you can use one of these
87
+ * constants located in the Rubygame::Mixer module:
88
+ *
89
+ * AUDIO_U16SYS:: unsigned 16-bit samples.
90
+ * AUDIO_S16SYS:: signed 16-bit samples.
91
+ * AUDIO_U8:: unsigned 8-bit samples.
92
+ * AUDIO_S8:: signed 8-bit samples.
93
+ *
94
+ * channels:: output sound channels. Use 2 for stereo, 1 for mono.
95
+ * If nil, the default (2) is used.
96
+ * This option is not related to mixing channels.
97
+ *
98
+ * buffer:: size of the sound buffer, in bytes. If nil, the default (1024)
99
+ * is used. Larger values have more delay before playing a
100
+ * sound, but require less CPU usage (and have less skipping
101
+ * on slow systems).
102
+ *
103
+ */
104
+ VALUE rbgm_mixer_openaudio(int argc, VALUE *argv, VALUE module)
105
+ {
106
+ VALUE vfreq, vformat, vchannels, vbuffer;
107
+ int freq = MIX_DEFAULT_FREQUENCY;
108
+ Uint16 format = MIX_DEFAULT_FORMAT;
109
+ int channels = 2;
110
+ int buffer = 1024;
111
+
112
+ rb_scan_args(argc, argv, "04", &vfreq, &vformat, &vchannels, &vbuffer);
113
+
114
+ if( RTEST(vfreq) )
115
+ {
116
+ freq = NUM2INT(vfreq);
117
+ }
118
+
119
+ if( RTEST(vformat) )
120
+ {
121
+ format = NUM2UINT(vformat);
122
+ }
123
+
124
+ if( RTEST(vchannels) )
125
+ {
126
+ channels = NUM2INT(vchannels);
127
+ }
128
+
129
+ if( RTEST(vbuffer) )
130
+ {
131
+ buffer = NUM2INT(vbuffer);
132
+ }
133
+
134
+ if ( Mix_OpenAudio(freq, format, channels, buffer) < 0 )
135
+ {
136
+ rb_raise(eSDLError, "Error initializing SDL_mixer: %s", Mix_GetError());
137
+ }
138
+
139
+ return Qnil;
140
+ }
141
+
142
+ /* call-seq:
143
+ * close_audio()
144
+ *
145
+ * Close the audio device being used by the mixer. You should not use any
146
+ * mixer functions after this function, unless you use #open_audio() to
147
+ * re-open the audio device. See also #open_audio().
148
+ *
149
+ * Returns nil.
150
+ */
151
+ VALUE rbgm_mixer_closeaudio(VALUE module)
152
+ {
153
+ Mix_CloseAudio();
154
+ return Qnil;
155
+ }
156
+
157
+ /* call-seq:
158
+ * #mix_channels() -> integer
159
+ *
160
+ * Returns the number of mixing channels currently allocated.
161
+ * See also #mix_channels=().
162
+ */
163
+ VALUE rbgm_mixer_getmixchans(VALUE module)
164
+ {
165
+ int result;
166
+ result = Mix_AllocateChannels(-1);
167
+
168
+ return INT2NUM(result);
169
+ }
170
+
171
+ /* call-seq:
172
+ * #mix_channels = num_channels
173
+ *
174
+ * Set the number of mixer channels, allocating or deallocating channels as
175
+ * needed. This can be called many times, even during audio playback. If this
176
+ * call reduces the number of channels allocated, the excess channels will
177
+ * be stopped automatically. See also #mix_channels()
178
+ *
179
+ * Returns the number of mixing channels allocated.
180
+ *
181
+ * Note that 8 mixing channels are allocated when #open_audio() is called.
182
+ * This method only needs to be called if you want a different number (either
183
+ * greater or fewer) of mixing channels.
184
+ *
185
+ * This method takes this argument:
186
+ * num_channels:: desired number of mixing channels, an integer.
187
+ * Negative values will cause this method to behave as
188
+ * #mix_channels(), returning the number of channels currently
189
+ * allocated, without changing it.
190
+ */
191
+ VALUE rbgm_mixer_setmixchans(VALUE module, VALUE channelsv)
192
+ {
193
+ int desired;
194
+ int allocated;
195
+
196
+ desired = NUM2INT(channelsv);
197
+ allocated = Mix_AllocateChannels(desired);
198
+
199
+ return INT2NUM(allocated);
200
+ }
201
+
202
+ /* call-seq:
203
+ * driver_name -> string
204
+ *
205
+ * Returns the name of the audio driver that SDL is using.
206
+ *
207
+ * May raise an SDLError if initialization fails.
208
+ */
209
+
210
+ VALUE rbgm_mixer_getdrivername(VALUE module)
211
+ {
212
+ char driver_name[1024];
213
+ if(SDL_AudioDriverName(driver_name, sizeof(driver_name)) == NULL)
214
+ {
215
+ rb_raise(eSDLError, "Error fetrching audio driver name: %s", SDL_GetError());
216
+ }
217
+ return rb_str_new2(driver_name);
218
+ }
219
+
220
+
221
+
222
+ /* --
223
+ * SAMPLES
224
+ * ++
225
+ */
226
+
227
+ /* call-seq:
228
+ * load_audio( filename ) -> Sample
229
+ *
230
+ * Load an audio sample (a "chunk", to use SDL_mixer's term) from a file.
231
+ * Only WAV files are supported at this time.
232
+ *
233
+ * Raises SDLError if the sample could not be loaded.
234
+ */
235
+ VALUE rbgm_sample_new(VALUE class, VALUE filev)
236
+ {
237
+ VALUE self;
238
+ Mix_Chunk* sample;
239
+
240
+ sample = Mix_LoadWAV( StringValuePtr(filev) );
241
+
242
+ if( sample == NULL )
243
+ {
244
+ rb_raise(eSDLError, "Error loading audio Sample from file `%s': %s",
245
+ StringValuePtr(filev), Mix_GetError());
246
+ }
247
+ self = Data_Wrap_Struct( cSample, 0, Mix_FreeChunk, sample );
248
+
249
+ //rb_obj_call_init(self,argc,argv);
250
+
251
+ return self;
252
+ }
253
+
254
+ /* call-seq:
255
+ * play(sample, channel_num, repeats ) -> integer
256
+ *
257
+ * Play an audio Sample on a mixing channel, repeating a certain number
258
+ * of extra times. Returns the number of the channel that the sample
259
+ * is being played on.
260
+ *
261
+ * Raises SDLError if something goes wrong.
262
+ *
263
+ * This method takes these arguments:
264
+ * sample:: what Sample to play
265
+ * channel_num:: which mixing channel to play the sample on.
266
+ * Use -1 to play on the first unreserved channel.
267
+ * repeats:: how many extra times to repeat the sample.
268
+ * Can be -1 to repeat forever until it is stopped.
269
+ */
270
+ VALUE rbgm_mixchan_play( VALUE self, VALUE samplev, VALUE chanv, VALUE loopsv )
271
+ {
272
+ Mix_Chunk* sample;
273
+ int loops, channel, result;
274
+
275
+ channel = NUM2INT(chanv);
276
+ Data_Get_Struct( samplev, Mix_Chunk, sample );
277
+ loops = NUM2INT(loopsv);
278
+
279
+ result = Mix_PlayChannel(channel, sample, loops);
280
+
281
+ if ( result < 0 )
282
+ {
283
+ rb_raise(eSDLError, "Error playing sample on channel %d: %s",
284
+ channel, Mix_GetError());
285
+ }
286
+
287
+ return INT2NUM( result );
288
+ }
289
+
290
+ /* call-seq:
291
+ * stop( channel_num )
292
+ *
293
+ * Stop playback of a playing or paused mixing channel.
294
+ * Unlike #pause, playback cannot be resumed from the current point.
295
+ * See also #play.
296
+ */
297
+ VALUE rbgm_mixchan_stop( VALUE self, VALUE chanv )
298
+ {
299
+ Mix_HaltChannel(NUM2INT(chanv));
300
+ return Qnil;
301
+ }
302
+
303
+ /* call-seq:
304
+ * pause( channel_num )
305
+ *
306
+ * Pause playback of a currently-playing mixing channel.
307
+ * Playback can be resumed from the current point with #resume.
308
+ * See also #stop.
309
+ */
310
+ VALUE rbgm_mixchan_pause( VALUE self, VALUE chanv )
311
+ {
312
+ Mix_Pause(NUM2INT(chanv));
313
+ return Qnil;
314
+ }
315
+
316
+ /* call-seq:
317
+ * resume( channel_num )
318
+ *
319
+ * Resume playback of a paused mixing channel. The channel must have been
320
+ * paused (via the #pause method) for this to have any effect. Playback will
321
+ * resume from the point where the channel was paused.
322
+ *
323
+ */
324
+ VALUE rbgm_mixchan_resume( VALUE self, VALUE chanv )
325
+ {
326
+ Mix_Resume(NUM2INT(chanv));
327
+ return Qnil;
328
+ }
329
+
330
+
331
+ /* --
332
+ * MUSIC
333
+ * ++
334
+ */
335
+
336
+ /* call-seq:
337
+ * set_music_command(command) -> integer
338
+ *
339
+ * Sets the external command used to play music.
340
+ *
341
+ * Raises SDLError if something goes wrong.
342
+ *
343
+ * This method takes these arguments:
344
+ * command:: what command to use to play the music.
345
+ *
346
+ */
347
+ VALUE rbgm_mixmusic_setcommand(VALUE class, VALUE commandv)
348
+ {
349
+ int result;
350
+ result = Mix_SetMusicCMD(StringValuePtr(commandv));
351
+ if( result < 0 )
352
+ {
353
+ rb_raise(eSDLError, "Error setting music player commando to `%s': %s",
354
+ StringValuePtr(commandv), Mix_GetError());
355
+ }
356
+ return INT2NUM( result );
357
+ }
358
+
359
+ /* call-seq:
360
+ * load_audio( filename ) -> Music
361
+ *
362
+ * Load music from a file. Supports WAVE, MOD, MIDI, OGG, and MP3 formats.
363
+ *
364
+ * Raises SDLError if the music could not be loaded.
365
+ */
366
+ VALUE rbgm_mixmusic_new(VALUE class, VALUE filev)
367
+ {
368
+ VALUE self;
369
+ Mix_Music* music;
370
+
371
+ music = Mix_LoadMUS( StringValuePtr(filev) );
372
+
373
+ if( music == NULL )
374
+ {
375
+ rb_raise(eSDLError, "Error loading audio music from file `%s': %s",
376
+ StringValuePtr(filev), Mix_GetError());
377
+ }
378
+ self = Data_Wrap_Struct( cMusic, 0, Mix_FreeMusic, music );
379
+
380
+ //rb_obj_call_init(self,argc,argv);
381
+
382
+ return self;
383
+ }
384
+
385
+ /* call-seq:
386
+ * play( repeats = 0 ) -> self
387
+ *
388
+ * Play music, repeating a certain number of extra times. If
389
+ * any music was already playing, that music will be stopped
390
+ * first, and this music will start.
391
+ *
392
+ * Raises SDLError if something goes wrong.
393
+ *
394
+ * This method takes these arguments:
395
+ * repeats:: how many extra times to play the music.
396
+ * Can be -1 to repeat forever until it is stopped.
397
+ */
398
+ VALUE rbgm_mixmusic_play(int argc, VALUE *argv, VALUE self)
399
+ {
400
+ Mix_Music* music;
401
+ int reps, result;
402
+ VALUE repsv;
403
+
404
+ Data_Get_Struct( self, Mix_Music, music );
405
+
406
+ rb_scan_args(argc, argv, "01", &repsv);
407
+
408
+ if( RTEST(repsv) )
409
+ {
410
+ reps = NUM2INT(repsv);
411
+ }
412
+ else
413
+ {
414
+ reps = 0;
415
+ }
416
+
417
+ if( reps > -1 )
418
+ {
419
+ /* Adjust so repeats means the same as it does for Samples */
420
+ reps += 1;
421
+ }
422
+
423
+ result = Mix_PlayMusic(music, reps);
424
+
425
+ if ( result < 0 )
426
+ {
427
+ rb_raise(eSDLError, "Error playing music: %s",
428
+ Mix_GetError());
429
+ }
430
+
431
+ return self;
432
+ }
433
+
434
+ /* call-seq:
435
+ * stop() -> self
436
+ *
437
+ * Stop playback of music.
438
+ * See also #play
439
+ */
440
+ VALUE rbgm_mixmusic_stop(VALUE self)
441
+ {
442
+ Mix_HaltMusic();
443
+ return self;
444
+ }
445
+
446
+ /* call-seq:
447
+ * pause() -> self
448
+ *
449
+ * Pause playback of the playing music. You can later #resume
450
+ * playback from the point where you paused.
451
+ * Safe to use on already-paused music.
452
+ * See also #play_music.
453
+ */
454
+ VALUE rbgm_mixmusic_pause(VALUE self)
455
+ {
456
+ Mix_PauseMusic();
457
+ return self;
458
+ }
459
+
460
+ /* call-seq:
461
+ * resume() -> self
462
+ *
463
+ * Resume playback of paused music from the point it was paused.
464
+ * Safe to use on already-playing music.
465
+ * See also #play.
466
+ */
467
+ VALUE rbgm_mixmusic_resume(VALUE self)
468
+ {
469
+ Mix_ResumeMusic();
470
+ return self;
471
+ }
472
+
473
+ /* call-seq:
474
+ * rewind() -> self
475
+ *
476
+ * Rewind the music to the start. This is safe to use on stopped, paused, and playing music.
477
+ * Only works for MOD, OGG, MP3, and MIDI (but not WAV).
478
+ *
479
+ */
480
+ VALUE rbgm_mixmusic_rewind(VALUE self)
481
+ {
482
+ Mix_RewindMusic();
483
+ return self;
484
+ }
485
+
486
+ /* call-seq:
487
+ * jump( time ) -> self
488
+ *
489
+ * Jump to a certain time in the music.
490
+ * Only works when music is playing or paused (but not stopped).
491
+ * Only works for OGG and MP3 files.
492
+ *
493
+ * Raises SDLError if something goes wrong, or if the music type does not
494
+ * support setting the position.
495
+ *
496
+ * time:: Time to jump to, in seconds from the beginning.
497
+ *
498
+ */
499
+ VALUE rbgm_mixmusic_jump(VALUE self, VALUE vtime)
500
+ {
501
+ double time = NUM2DBL(vtime);
502
+
503
+ switch( Mix_GetMusicType(NULL) )
504
+ {
505
+ case MUS_OGG:
506
+ case MUS_MP3:
507
+ Mix_RewindMusic(); // Needed for MP3, and OK with OGG
508
+
509
+ int result = Mix_SetMusicPosition(time);
510
+ if( result < 0 )
511
+ {
512
+ rb_raise(eSDLError, "Error jumping to time in music: %s", Mix_GetError());
513
+ }
514
+
515
+ return self;
516
+
517
+ case MUS_NONE:
518
+ rb_raise(eSDLError, "Cannot jump when no music is playing.");
519
+
520
+ default:
521
+ rb_raise(eSDLError, "Music type does not support jumping.");
522
+ }
523
+ }
524
+
525
+ /* call-seq:
526
+ * playing? -> true or false
527
+ *
528
+ * Returns true if the music is currently playing.
529
+ *
530
+ */
531
+ VALUE rbgm_mixmusic_playing(VALUE self)
532
+ {
533
+ return Mix_PlayingMusic() ? Qtrue : Qfalse;
534
+ }
535
+
536
+ /* call-seq:
537
+ * paused? -> true or false
538
+ *
539
+ * Returns true if the music is currently paused.
540
+ *
541
+ */
542
+ VALUE rbgm_mixmusic_paused(VALUE self)
543
+ {
544
+ return Mix_PausedMusic() ? Qtrue : Qfalse;
545
+ }
546
+
547
+ /* call-seq:
548
+ * volume
549
+ *
550
+ * Returns the current volume level of the music.
551
+ * 0.0 is total silence, 1.0 is maximum volume.
552
+ */
553
+ VALUE rbgm_mixmusic_getvolume(VALUE self)
554
+ {
555
+ return rb_float_new( (double)(Mix_VolumeMusic(-1)) / MIX_MAX_VOLUME );
556
+ }
557
+
558
+ /* call-seq:
559
+ * volume = new_volume
560
+ *
561
+ * Sets the volume level of the music.
562
+ * 0.0 is total silence, 1.0 is maximum volume.
563
+ */
564
+ VALUE rbgm_mixmusic_setvolume(VALUE self, VALUE volumev)
565
+ {
566
+ double volume = NUM2DBL(volumev);
567
+ Mix_VolumeMusic( (int)(volume * MIX_MAX_VOLUME) );
568
+ return volumev;
569
+ }
570
+
571
+ /* call-seq:
572
+ * fade_in( fade_time, repeats=0, start=0 ) -> self
573
+ *
574
+ * Play the music, fading in and repeating a certain number of times.
575
+ * See also #play.
576
+ *
577
+ * Raises SDLError if something goes wrong.
578
+ *
579
+ * fade_time:: Time in seconds for the fade-in effect to complete.
580
+ * repeats:: Number of extra times to play through the music.
581
+ * -1 plays the music forever until it is stopped.
582
+ * Defaults to 0, play only once (no repeats).
583
+ * start:: Time to start from, in seconds since the beginning.
584
+ * Defaults to 0, the beginning of the song.
585
+ * Non-zero values only work for OGG and MP3; other
586
+ * music types will raise SDLError.
587
+ */
588
+ VALUE rbgm_mixmusic_fadein(int argc, VALUE *argv, VALUE self)
589
+ {
590
+ VALUE fadev, repsv, startv;
591
+ rb_scan_args(argc, argv, "12", &fadev, &repsv, &startv);
592
+
593
+ Mix_Music* music;
594
+ Data_Get_Struct( self, Mix_Music, music );
595
+
596
+ int fade, reps, result;
597
+ fade = (int)(NUM2DBL(fadev) * 1000); /* convert to milliseconds */
598
+
599
+ if( RTEST(repsv) )
600
+ {
601
+ reps = NUM2INT(repsv);
602
+ }
603
+ else
604
+ {
605
+ reps = 0;
606
+ }
607
+
608
+ if( reps > -1 )
609
+ {
610
+ /* Adjust so repeats means the same as it does for Samples */
611
+ reps += 1;
612
+ }
613
+
614
+ if( !RTEST(startv) || NUM2DBL(startv) == 0.0 )
615
+ {
616
+ result = Mix_FadeInMusic(music, reps, fade);
617
+ }
618
+ else
619
+ {
620
+ result = Mix_FadeInMusicPos(music, reps, fade, NUM2DBL(startv));
621
+ }
622
+
623
+ if( result < 0 )
624
+ {
625
+ rb_raise(eSDLError, "Error fading in music: %s", Mix_GetError());
626
+ }
627
+
628
+ return self;
629
+ }
630
+
631
+ /* call-seq:
632
+ * fade_out( fade_time ) -> self
633
+ *
634
+ * Gradually fade the music to silence over +fade_length+ seconds.
635
+ * After the fade is complete, the music will be automatically stopped.
636
+ *
637
+ * Raises SDLError if something goes wrong.
638
+ *
639
+ * fade_time:: Time until the music is totally silent, in seconds.
640
+ */
641
+ VALUE rbgm_mixmusic_fadeout(VALUE self, VALUE fadev)
642
+ {
643
+ int fade = (int)(NUM2DBL(fadev) * 1000);
644
+ int result = Mix_FadeOutMusic(fade);
645
+
646
+ if ( result < 0 )
647
+ {
648
+ rb_raise(eSDLError, "Error fading out music: %s", Mix_GetError());
649
+ }
650
+ return self;
651
+ }
652
+
653
+ /* call-seq:
654
+ * fading?( direction = nil ) -> true or false
655
+ *
656
+ * True if the music is fading in or out (or either). You can
657
+ * specify +direction+ as :in/:out to check only fading in/out;
658
+ * otherwise, it will return true if it's fading either way.
659
+ *
660
+ * direction:: :in, :out, or nil if you don't care which.
661
+ * Returns:: true if the music is fading in the given direction.
662
+ */
663
+ VALUE rbgm_mixmusic_fading(int argc, VALUE *argv, VALUE self)
664
+ {
665
+ VALUE dirv;
666
+ rb_scan_args(argc, argv, "01", &dirv);
667
+
668
+ if( dirv == make_symbol("in") )
669
+ {
670
+ return ( (Mix_FadingMusic() == MIX_FADING_IN) ? Qtrue : Qfalse );
671
+ }
672
+ else if( dirv == make_symbol("out") )
673
+ {
674
+ return ( (Mix_FadingMusic() == MIX_FADING_OUT) ? Qtrue : Qfalse );
675
+ }
676
+ else
677
+ {
678
+ return ( (Mix_FadingMusic() != MIX_NO_FADING) ? Qtrue : Qfalse );
679
+ }
680
+ }
681
+
682
+
683
+ void Init_rubygame_mixer()
684
+ {
685
+
686
+ #if 0
687
+ mRubygame = rb_define_module("Rubygame");
688
+ #endif
689
+
690
+ Init_rubygame_shared();
691
+
692
+ rb_hash_aset(rb_ivar_get(mRubygame,rb_intern("VERSIONS")),
693
+ ID2SYM(rb_intern("sdl_mixer")),
694
+ rb_ary_new3(3,
695
+ INT2NUM(SDL_MIXER_MAJOR_VERSION),
696
+ INT2NUM(SDL_MIXER_MINOR_VERSION),
697
+ INT2NUM(SDL_MIXER_PATCHLEVEL)));
698
+
699
+ /*
700
+ * The Mixer module provides access to the SDL_mixer library for audio
701
+ * playback and mixing. This module is still very basic, but it is
702
+ * good enough to load and play WAV files on multiple mix channels.
703
+ *
704
+ * See the Sample class for loading audio files.
705
+ * See the Music class for streaming music from a file.
706
+ */
707
+ mMixer = rb_define_module_under(mRubygame, "Mixer");
708
+
709
+ rb_define_const(mMixer,"AUDIO_U8", INT2NUM(AUDIO_U8));
710
+ rb_define_const(mMixer,"AUDIO_S8", INT2NUM(AUDIO_S8));
711
+ rb_define_const(mMixer,"AUDIO_U16SYS", INT2NUM(AUDIO_U16SYS));
712
+ rb_define_const(mMixer,"AUDIO_S16SYS", INT2NUM(AUDIO_S16SYS));
713
+
714
+ rb_define_module_function(mMixer,"open_audio",rbgm_mixer_openaudio, -1);
715
+ rb_define_module_function(mMixer,"close_audio",rbgm_mixer_closeaudio, 0);
716
+ rb_define_module_function(mMixer,"mix_channels",rbgm_mixer_getmixchans, 0);
717
+ rb_define_module_function(mMixer,"mix_channels=",rbgm_mixer_setmixchans, 1);
718
+ rb_define_module_function(mMixer,"driver_name", rbgm_mixer_getdrivername, 0);
719
+
720
+
721
+
722
+ /* Stores audio data to play with Mixer.play() */
723
+ cSample = rb_define_class_under(mMixer, "Sample", rb_cObject);
724
+ rb_define_singleton_method(cSample, "load_audio", rbgm_sample_new, 1);
725
+ rb_define_module_function(mMixer,"play", rbgm_mixchan_play, 3);
726
+ rb_define_module_function(mMixer,"stop", rbgm_mixchan_stop, 1);
727
+ rb_define_module_function(mMixer,"pause", rbgm_mixchan_pause, 1);
728
+ rb_define_module_function(mMixer,"resume", rbgm_mixchan_resume, 1);
729
+
730
+
731
+ /* The Music class is used for playing music from a file. It supports
732
+ * WAVE, MOD, MIDI, OGG, and MP3 files. There are two important differences
733
+ * between Music and Sample:
734
+ *
735
+ * 1. Music streams the music from disk, which means it can start faster and
736
+ * uses less memory than Sample, which loads the entire file into memory.
737
+ * This is especially important for music files, which are often several
738
+ * minutes long.
739
+ * 2. There can only be one Music instance playing at once, while there can
740
+ * be many Samples playing at once. If you play a second Music while one
741
+ * is already playing, the first one will be stopped. See #play.
742
+ */
743
+ cMusic = rb_define_class_under(mMixer, "Music", rb_cObject);
744
+ rb_define_singleton_method(cMusic, "load_audio", rbgm_mixmusic_new, 1);
745
+
746
+ //rb_define_singleton_method(cMusic, "set_command", rbgm_mixmusic_setcommand, 1);
747
+
748
+ rb_define_method(cMusic, "play", rbgm_mixmusic_play, -1);
749
+ rb_define_method(cMusic, "stop", rbgm_mixmusic_stop, 0);
750
+ rb_define_method(cMusic, "pause", rbgm_mixmusic_pause, 0);
751
+ rb_define_method(cMusic, "resume", rbgm_mixmusic_resume, 0);
752
+ rb_define_method(cMusic, "rewind", rbgm_mixmusic_rewind, 0);
753
+ rb_define_method(cMusic, "jump", rbgm_mixmusic_jump, 1);
754
+ rb_define_method(cMusic, "paused?", rbgm_mixmusic_paused, 0);
755
+ rb_define_method(cMusic, "playing?", rbgm_mixmusic_playing, 0);
756
+
757
+ rb_define_method(cMusic, "volume", rbgm_mixmusic_getvolume, 0);
758
+ rb_define_method(cMusic, "volume=", rbgm_mixmusic_setvolume, 1);
759
+ rb_define_method(cMusic, "fade_in", rbgm_mixmusic_fadein, -1);
760
+ rb_define_method(cMusic, "fade_out", rbgm_mixmusic_fadeout, 1);
761
+ rb_define_method(cMusic, "fading?", rbgm_mixmusic_fading, -1);
762
+ }
763
+
764
+