rubygame 2.5.3 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CREDITS +6 -4
- data/NEWS +79 -0
- data/README +55 -72
- data/ROADMAP +20 -13
- data/doc/custom_sdl_load_paths.rdoc +79 -0
- data/doc/getting_started.rdoc +65 -36
- data/doc/keyboard_symbols.rdoc +243 -0
- data/doc/macosx_install.rdoc +49 -35
- data/doc/windows_install.rdoc +36 -108
- data/lib/rubygame.rb +62 -24
- data/lib/rubygame/audio.rb +147 -0
- data/lib/rubygame/clock.rb +164 -1
- data/lib/rubygame/color.rb +40 -7
- data/lib/rubygame/color/models/hsl.rb +1 -1
- data/lib/rubygame/color/models/hsv.rb +1 -1
- data/lib/rubygame/color/models/rgb.rb +1 -1
- data/lib/rubygame/color/palettes/css.rb +1 -3
- data/lib/rubygame/color/palettes/x11.rb +1 -2
- data/lib/rubygame/constants.rb +297 -0
- data/lib/rubygame/deprecated_mixer.rb +555 -0
- data/lib/rubygame/event.rb +122 -6
- data/lib/rubygame/event_handler.rb +3 -1
- data/lib/rubygame/event_hook.rb +6 -2
- data/lib/rubygame/event_triggers.rb +1 -1
- data/lib/rubygame/events.rb +416 -1
- data/lib/rubygame/ftor.rb +1 -7
- data/lib/rubygame/gfx.rb +583 -0
- data/lib/rubygame/gl.rb +107 -0
- data/lib/rubygame/image.rb +140 -0
- data/lib/rubygame/joystick.rb +184 -0
- data/lib/rubygame/main.rb +82 -0
- data/lib/rubygame/mediabag.rb +1 -1
- data/lib/rubygame/mixer.rb +30 -0
- data/lib/rubygame/music.rb +493 -0
- data/lib/rubygame/queue.rb +3 -1
- data/lib/rubygame/rect.rb +9 -9
- data/lib/rubygame/screen.rb +357 -0
- data/lib/rubygame/shared.rb +40 -4
- data/lib/rubygame/sound.rb +428 -0
- data/lib/rubygame/surface.rb +626 -0
- data/lib/rubygame/ttf.rb +311 -0
- data/samples/FreeSans.ttf +0 -0
- data/samples/README +6 -5
- data/samples/demo_draw.rb +1 -1
- data/samples/demo_gl.rb +3 -1
- data/samples/demo_gl_tex.rb +4 -2
- data/samples/demo_rubygame.rb +114 -105
- data/samples/demo_sfont.rb +1 -1
- data/samples/demo_ttf.rb +3 -1
- data/samples/demo_utf8.rb +1 -1
- data/samples/image_viewer.rb +118 -0
- data/samples/load_and_blit.rb +1 -1
- data/samples/rubygame.png +0 -0
- metadata +34 -40
- data/Rakefile +0 -537
- data/doc/extended_readme.rdoc +0 -49
- data/ext/body/rubygame_body.so +0 -0
- data/ext/rubygame/rubygame_clock.c +0 -301
- data/ext/rubygame/rubygame_clock.h +0 -32
- data/ext/rubygame/rubygame_event.c +0 -760
- data/ext/rubygame/rubygame_event.h +0 -48
- data/ext/rubygame/rubygame_event2.c +0 -661
- data/ext/rubygame/rubygame_event2.h +0 -29
- data/ext/rubygame/rubygame_gfx.c +0 -942
- data/ext/rubygame/rubygame_gfx.h +0 -101
- data/ext/rubygame/rubygame_gl.c +0 -154
- data/ext/rubygame/rubygame_gl.h +0 -32
- data/ext/rubygame/rubygame_image.c +0 -252
- data/ext/rubygame/rubygame_image.h +0 -41
- data/ext/rubygame/rubygame_joystick.c +0 -336
- data/ext/rubygame/rubygame_joystick.h +0 -41
- data/ext/rubygame/rubygame_main.c +0 -158
- data/ext/rubygame/rubygame_main.h +0 -36
- data/ext/rubygame/rubygame_mixer.c +0 -1024
- data/ext/rubygame/rubygame_mixer.h +0 -36
- data/ext/rubygame/rubygame_music.c +0 -1017
- data/ext/rubygame/rubygame_music.h +0 -29
- data/ext/rubygame/rubygame_screen.c +0 -572
- data/ext/rubygame/rubygame_screen.h +0 -45
- data/ext/rubygame/rubygame_shared.c +0 -269
- data/ext/rubygame/rubygame_shared.h +0 -69
- data/ext/rubygame/rubygame_sound.c +0 -863
- data/ext/rubygame/rubygame_sound.h +0 -29
- data/ext/rubygame/rubygame_surface.c +0 -1153
- data/ext/rubygame/rubygame_surface.h +0 -62
- data/ext/rubygame/rubygame_ttf.c +0 -599
- data/ext/rubygame/rubygame_ttf.h +0 -69
- data/samples/keys.rb +0 -52
@@ -0,0 +1,428 @@
|
|
1
|
+
#--
|
2
|
+
# Rubygame -- Ruby code and bindings to SDL to facilitate game creation
|
3
|
+
# Copyright (C) 2004-2009 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
|
+
# *IMPORTANT*: this class only exists if SDL_mixer is available!
|
23
|
+
# Your code should check "defined?(Rubygame::Sound) != nil" to see if
|
24
|
+
# you can use this class, or be prepared to rescue from NameError.
|
25
|
+
#
|
26
|
+
# Sound holds a sound effect, loaded from an audio file (see #load for
|
27
|
+
# supported formats).
|
28
|
+
#
|
29
|
+
# Sound can #play, #pause/#unpause, #stop, adjust #volume,
|
30
|
+
# and #fade_out (you can fade in by passing an option to #play).
|
31
|
+
#
|
32
|
+
# Sound can create duplicates (with #dup or #clone) in a memory-efficient
|
33
|
+
# way -- the new Sound instance refers back to the same audio data,
|
34
|
+
# so having 100 duplicates of a sound uses only slightly more memory
|
35
|
+
# than having the first sound. Duplicates can different volume levels,
|
36
|
+
# too!
|
37
|
+
#
|
38
|
+
# Sound includes the Rubygame::NamedResource mixin module, which
|
39
|
+
# can perform autoloading of sounds on demand, among other things.
|
40
|
+
#
|
41
|
+
class Rubygame::Sound
|
42
|
+
|
43
|
+
include Rubygame::NamedResource
|
44
|
+
|
45
|
+
class << self
|
46
|
+
|
47
|
+
# Searches each directory in Sound.autoload_dirs for a file with
|
48
|
+
# the given filename. If it finds that file, loads it and returns
|
49
|
+
# a Sound instance. If it doesn't find the file, returns nil.
|
50
|
+
#
|
51
|
+
# See Rubygame::NamedResource for more information about this
|
52
|
+
# functionality.
|
53
|
+
#
|
54
|
+
def autoload( filename )
|
55
|
+
path = find_file( filename )
|
56
|
+
|
57
|
+
if( path )
|
58
|
+
return load( path )
|
59
|
+
else
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Load the given audio file.
|
66
|
+
# Supported file formats are WAVE, MOD, MIDI, OGG, and MP3.
|
67
|
+
#
|
68
|
+
# filename:: Full or relative path to the file. (String, required)
|
69
|
+
#
|
70
|
+
# Returns:: The new Sound instance. (Sound)
|
71
|
+
# May raise:: SDLError, if the sound file could not be loaded.
|
72
|
+
#
|
73
|
+
def load( filename )
|
74
|
+
Rubygame.open_audio
|
75
|
+
|
76
|
+
sound = SDL::Mixer.LoadWAV( filename )
|
77
|
+
|
78
|
+
if( sound.pointer.null? )
|
79
|
+
raise( Rubygame::SDLError, "Could not load Sound file '%s': %s"%
|
80
|
+
[filename, SDL.GetError()] )
|
81
|
+
end
|
82
|
+
|
83
|
+
return new( sound )
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# call-seq:
|
90
|
+
# new
|
91
|
+
#
|
92
|
+
# **NOTE**: Don't use this method. Use Sound.load.
|
93
|
+
#
|
94
|
+
# Raises NotImplementedError.
|
95
|
+
#
|
96
|
+
def initialize( sound=nil )
|
97
|
+
if( sound.instance_of? SDL::Mixer::Chunk )
|
98
|
+
@struct = sound
|
99
|
+
@volume = 1
|
100
|
+
@channel = -1
|
101
|
+
else
|
102
|
+
raise( NotImplementedError, "Sound.new is not implemented. "+
|
103
|
+
"Use Sound.load to load a sound file." )
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
attr_reader :struct # :nodoc:
|
109
|
+
protected :struct
|
110
|
+
|
111
|
+
|
112
|
+
# call-seq:
|
113
|
+
# clone( other ) -> sound
|
114
|
+
# dup( other ) -> sound
|
115
|
+
#
|
116
|
+
# Create a copy of the given Sound instance. More efficient than
|
117
|
+
# using #load to load the sound file again.
|
118
|
+
#
|
119
|
+
# other:: An existing Sound instance. (Sound, required)
|
120
|
+
#
|
121
|
+
# Returns:: The new Sound instance. (Sound)
|
122
|
+
#
|
123
|
+
# **NOTE**: #clone and #dup do slightly different things; #clone
|
124
|
+
# will copy the 'frozen' state of the object, while #dup will create
|
125
|
+
# a fresh, un-frozen object.
|
126
|
+
#
|
127
|
+
def initialize_copy( other )
|
128
|
+
@struct = other.struct
|
129
|
+
@volume = other.volume
|
130
|
+
@channel = -1
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
# call-seq:
|
136
|
+
# play( options={:fade_in => 0, :repeats => 0, :stop_after => nil} )
|
137
|
+
#
|
138
|
+
# Play the Sound, optionally fading in, repeating a certain number
|
139
|
+
# of times (or forever), and/or stopping automatically after a certain time.
|
140
|
+
#
|
141
|
+
# See also #pause and #stop.
|
142
|
+
#
|
143
|
+
# options:: Hash of options, listed below. (Hash, required)
|
144
|
+
#
|
145
|
+
# :fade_in:: Fade in from silence over the given number of
|
146
|
+
# seconds. Default: 0. (Numeric, optional)
|
147
|
+
# :repeats:: Repeat the sound the given number of times, or
|
148
|
+
# forever (or until stopped) if -1. Default: 0.
|
149
|
+
# (Integer, optional)
|
150
|
+
# :stop_after:: Automatically stop playing after playing for the given
|
151
|
+
# number of seconds. Use nil to disable this behavior.
|
152
|
+
# (Numeric or nil, optional)
|
153
|
+
#
|
154
|
+
#
|
155
|
+
# Returns:: The receiver (self).
|
156
|
+
# May raise:: SDLError, if the audio device could not be opened, or
|
157
|
+
# if the sound file could not be played.
|
158
|
+
#
|
159
|
+
#
|
160
|
+
# **NOTE**: If the sound is already playing (or paused), it will be stopped
|
161
|
+
# and played again from the beginning.
|
162
|
+
#
|
163
|
+
# Example:
|
164
|
+
# # Fade in over 2 seconds, play 4 times (1 + 3 repeats),
|
165
|
+
# # but stop playing after 5 seconds.
|
166
|
+
# sound.play( :fade_in => 2, :repeats => 3, :stop_after => 5 );
|
167
|
+
#
|
168
|
+
def play( options={} )
|
169
|
+
|
170
|
+
fade_in = (options[:fade_in] or 0)
|
171
|
+
repeats = (options[:repeats] or 0)
|
172
|
+
stop_after = (options[:stop_after] or nil)
|
173
|
+
|
174
|
+
|
175
|
+
fade_in =
|
176
|
+
if( fade_in < 0 )
|
177
|
+
raise ArgumentError, ":fade_in cannot be negative (got %.2f)"%fade_in
|
178
|
+
elsif( fade_in < 0.05 )
|
179
|
+
# Work-around for a bug with SDL_mixer not working with small
|
180
|
+
# non-zero fade-ins
|
181
|
+
0
|
182
|
+
else
|
183
|
+
(fade_in * 1000).to_i
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
repeats =
|
188
|
+
if( repeats < -1 )
|
189
|
+
raise( ArgumentError,
|
190
|
+
":repeats cannot be negative, except -1 (got #{repeats})" )
|
191
|
+
else
|
192
|
+
repeats
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
stop_after =
|
197
|
+
if( stop_after.nil? )
|
198
|
+
-1
|
199
|
+
elsif( stop_after < 0 )
|
200
|
+
raise( ArgumentError,
|
201
|
+
":stop_after cannot be negative, (got %.2f)"%stop_after )
|
202
|
+
else
|
203
|
+
(stop_after * 1000).to_i
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
Rubygame.open_audio
|
209
|
+
|
210
|
+
|
211
|
+
# If it's already playing on a channel, stop it first.
|
212
|
+
if channel_active?
|
213
|
+
SDL::Mixer.HaltChannel( @channel )
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
# Find first available channel
|
218
|
+
@channel = SDL::Mixer.GroupAvailable(-1)
|
219
|
+
|
220
|
+
|
221
|
+
if @channel == -1
|
222
|
+
# No channels were available, so make one more than there are now.
|
223
|
+
# (Mix_AllocateChannels(-1) returns the current number of channels)
|
224
|
+
SDL::Mixer.AllocateChannels( SDL::Mixer.AllocateChannels(-1) + 1 )
|
225
|
+
|
226
|
+
# Try again
|
227
|
+
@channel = SDL::Mixer.GroupAvailable(-1)
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
# Set sound channel volume before we play
|
232
|
+
SDL::Mixer.Volume( @channel, (SDL::Mixer::MAX_VOLUME * @volume).to_i )
|
233
|
+
|
234
|
+
|
235
|
+
result =
|
236
|
+
if( fade_in <= 0 )
|
237
|
+
# Play sound without fading in
|
238
|
+
SDL::Mixer.PlayChannelTimed( @channel, @struct, repeats, stop_after )
|
239
|
+
else
|
240
|
+
# Play sound with fading in
|
241
|
+
SDL::Mixer.FadeInChannelTimed( @channel, @struct,
|
242
|
+
repeats, fade_in, stop_after )
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
if( result == -1 )
|
247
|
+
raise Rubygame::SDLError, "Could not play Sound: #{SDL.GetError()}"
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
return self
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
# True if the Sound is currently playing (not paused and not stopped).
|
257
|
+
# See also #paused? and #stopped?.
|
258
|
+
#
|
259
|
+
def playing?
|
260
|
+
channel_active? and
|
261
|
+
SDL::Mixer.Playing(@channel) == 1 and
|
262
|
+
SDL::Mixer.Paused(@channel) == 0
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
+
# Pause the Sound. Unlike #stop, it can be unpaused later to resume
|
268
|
+
# from where it was paused. See also #unpause and #paused?.
|
269
|
+
#
|
270
|
+
# Returns:: The receiver (self).
|
271
|
+
#
|
272
|
+
# **NOTE**: Does nothing if the sound is not currently playing.
|
273
|
+
#
|
274
|
+
def pause
|
275
|
+
if channel_active?
|
276
|
+
SDL::Mixer.Pause( @channel )
|
277
|
+
end
|
278
|
+
|
279
|
+
return self
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
# Unpause the Sound, if it is currently paused. Resumes from
|
284
|
+
# where it was paused. See also #pause and #paused?.
|
285
|
+
#
|
286
|
+
# Returns:: The receiver (self).
|
287
|
+
#
|
288
|
+
# **NOTE**: Does nothing if the sound is not currently paused.
|
289
|
+
#
|
290
|
+
def unpause
|
291
|
+
if channel_active?
|
292
|
+
SDL::Mixer.Resume( @channel )
|
293
|
+
end
|
294
|
+
|
295
|
+
return self
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
# True if the Sound is currently paused (not playing and not stopped).
|
300
|
+
# See also #playing? and #stopped?.
|
301
|
+
#
|
302
|
+
def paused?
|
303
|
+
channel_active? and
|
304
|
+
SDL::Mixer.Playing( @channel ) == 1 and
|
305
|
+
SDL::Mixer.Paused( @channel ) == 1
|
306
|
+
end
|
307
|
+
|
308
|
+
|
309
|
+
|
310
|
+
# Stop the Sound. Unlike #pause, the sound must be played again from
|
311
|
+
# the beginning, it cannot be resumed from it was stopped.
|
312
|
+
#
|
313
|
+
# Returns:: The receiver (self).
|
314
|
+
#
|
315
|
+
# **NOTE**: Does nothing if the sound is not currently playing or paused.
|
316
|
+
#
|
317
|
+
def stop
|
318
|
+
if channel_active?
|
319
|
+
SDL::Mixer.HaltChannel( @channel )
|
320
|
+
end
|
321
|
+
|
322
|
+
return self
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
# True if the Sound is currently stopped (not playing and not paused).
|
327
|
+
# See also #playing? and #paused?.
|
328
|
+
#
|
329
|
+
def stopped?
|
330
|
+
(not channel_active?) or (SDL::Mixer.Playing(@channel) == 0)
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
# Fade out to silence over the given number of seconds. Once the sound
|
336
|
+
# is silent, it is automatically stopped.
|
337
|
+
#
|
338
|
+
# Returns:: The receiver (self).
|
339
|
+
#
|
340
|
+
# **NOTE**: If the sound is currently paused, the fade will start,
|
341
|
+
# but you won't be able to hear it happening unless you #unpause during
|
342
|
+
# the fade.
|
343
|
+
#
|
344
|
+
# Does nothing if the sound is currently stopped.
|
345
|
+
#
|
346
|
+
def fade_out( fade_time )
|
347
|
+
if( fade_time < 0 )
|
348
|
+
raise ArgumentError, "fade time cannot be negative (got %.2f)"%fade_time
|
349
|
+
end
|
350
|
+
|
351
|
+
if channel_active?
|
352
|
+
SDL::Mixer.FadeOutChannel( @channel, (fade_time * 1000).to_i )
|
353
|
+
end
|
354
|
+
|
355
|
+
return self
|
356
|
+
end
|
357
|
+
|
358
|
+
|
359
|
+
# True if the Sound is currently fading in or out.
|
360
|
+
# See also #play and #fade_out.
|
361
|
+
#
|
362
|
+
# direction:: Check if it is fading :in, :out, or :either.
|
363
|
+
# (Symbol, required)
|
364
|
+
#
|
365
|
+
def fading?( direction=:either )
|
366
|
+
return false unless channel_active?
|
367
|
+
|
368
|
+
case direction
|
369
|
+
when :in
|
370
|
+
SDL::Mixer.FadingChannel( @channel ) == SDL::Mixer::FADING_IN
|
371
|
+
when :out
|
372
|
+
SDL::Mixer.FadingChannel( @channel ) == SDL::Mixer::FADING_OUT
|
373
|
+
else
|
374
|
+
SDL::Mixer.FadingChannel( @channel ) != SDL::Mixer::NO_FADING
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
|
380
|
+
# Return the volume level of the sound.
|
381
|
+
# 0.0 is totally silent, 1.0 is full volume.
|
382
|
+
#
|
383
|
+
# **NOTE**: Ignores fading in or out.
|
384
|
+
#
|
385
|
+
def volume
|
386
|
+
@volume
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
# Set the new #volume level of the sound.
|
391
|
+
# 0.0 is totally silent, 1.0 is full volume.
|
392
|
+
# The new volume will be clamped to this range if it is too small or
|
393
|
+
# too large.
|
394
|
+
#
|
395
|
+
# Volume cannot be set while the sound is fading in or out.
|
396
|
+
# Be sure to check #fading? or rescue from SDLError when
|
397
|
+
# using this method.
|
398
|
+
#
|
399
|
+
# May raise:: SDLError if the sound is fading in or out.
|
400
|
+
#
|
401
|
+
def volume=( new_vol )
|
402
|
+
# Clamp it to valid range
|
403
|
+
new_vol = if new_vol < 0.0; 0.0
|
404
|
+
elsif new_vol > 1.0; 1.0
|
405
|
+
else; new_vol
|
406
|
+
end
|
407
|
+
|
408
|
+
if channel_active?
|
409
|
+
if fading?
|
410
|
+
raise Rubygame::SDLError, "cannot set Sound volume while fading"
|
411
|
+
else
|
412
|
+
SDL::Mixer.Volume( @channel, (SDL::Mixer::MAX_VOLUME * new_vol).to_i )
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
@volume = new_vol
|
417
|
+
end
|
418
|
+
|
419
|
+
|
420
|
+
private
|
421
|
+
|
422
|
+
|
423
|
+
def channel_active?
|
424
|
+
(@channel != -1) and
|
425
|
+
(SDL::Mixer.GetChunk(@channel).pointer == @struct.pointer)
|
426
|
+
end
|
427
|
+
|
428
|
+
end
|
@@ -0,0 +1,626 @@
|
|
1
|
+
#--
|
2
|
+
# Rubygame -- Ruby code and bindings to SDL to facilitate game creation
|
3
|
+
# Copyright (C) 2004-2009 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
|
+
# Surface represents an image, a block of colored pixels arranged in a
|
23
|
+
# 2D grid. You can load image files to a new Surface with #load,
|
24
|
+
# or create an empty one with Surface.new and draw shapes on it with
|
25
|
+
# #draw_line, #draw_circle, and all the rest.
|
26
|
+
#
|
27
|
+
# One of the most important Surface concepts is #blit, copying image
|
28
|
+
# data from one Surface onto another. By blitting Surfaces onto the
|
29
|
+
# Screen (which is a special type of Surface) and then using
|
30
|
+
# Screen#update, you can make images appear for the player to see.
|
31
|
+
#
|
32
|
+
# As of Rubygame 2.3.0, Surface includes the Rubygame::NamedResource
|
33
|
+
# mixin module, which can perform autoloading of images on demand,
|
34
|
+
# among other things.
|
35
|
+
#
|
36
|
+
class Rubygame::Surface
|
37
|
+
|
38
|
+
include Rubygame::NamedResource
|
39
|
+
|
40
|
+
#--
|
41
|
+
#
|
42
|
+
# Image loading code is defined in image.rb
|
43
|
+
#
|
44
|
+
#++
|
45
|
+
|
46
|
+
|
47
|
+
attr_reader :struct # :nodoc:
|
48
|
+
protected :struct
|
49
|
+
|
50
|
+
|
51
|
+
# Create and initialize a new Surface object.
|
52
|
+
#
|
53
|
+
# A Surface is a grid of image data which you blit (i.e. copy) onto other
|
54
|
+
# Surfaces. Since the Rubygame display is also a Surface (see the Screen
|
55
|
+
# class), Surfaces can be blit to the screen; this is the most common way
|
56
|
+
# to display images on the screen.
|
57
|
+
#
|
58
|
+
# This method may raise SDLError if the SDL video subsystem could
|
59
|
+
# not be initialized for some reason.
|
60
|
+
#
|
61
|
+
# This function takes these arguments:
|
62
|
+
# size:: requested surface size; an array of the form [width, height].
|
63
|
+
# depth:: requested color depth (in bits per pixel). If depth is 0 (default),
|
64
|
+
# automatically choose a color depth: either the depth of the Screen
|
65
|
+
# mode (if one has been set), or the greatest color depth available
|
66
|
+
# on the system.
|
67
|
+
# flags:: an Array or Bitwise-OR'd list of zero or more of the following
|
68
|
+
# flags (located in the Rubygame module, e.g. Rubygame::SWSURFACE).
|
69
|
+
# This argument may be omitted, in which case the Surface
|
70
|
+
# will be a normal software surface (this is not necessarily a bad
|
71
|
+
# thing).
|
72
|
+
# SWSURFACE:: (default) request a software surface.
|
73
|
+
# HWSURFACE:: request a hardware-accelerated surface (using a
|
74
|
+
# graphics card), if available. Creates a software
|
75
|
+
# surface if hardware surfaces are not available.
|
76
|
+
# SRCCOLORKEY:: request a colorkeyed surface. #set_colorkey will
|
77
|
+
# also enable colorkey as needed. For a description
|
78
|
+
# of colorkeys, see #set_colorkey.
|
79
|
+
# SRCALPHA:: request an alpha channel. #set_alpha will
|
80
|
+
# also enable alpha. as needed. For a description
|
81
|
+
# of alpha, see #alpha.
|
82
|
+
#
|
83
|
+
def initialize( size, depth=0, flags=[] )
|
84
|
+
|
85
|
+
# Cheating a bit. First arg can be a SDL::Surface to wrap it.
|
86
|
+
#
|
87
|
+
if( size.kind_of? SDL::Surface )
|
88
|
+
surf = size
|
89
|
+
if( surf.pointer.null? )
|
90
|
+
raise Rubygame::SDLError, "Surface cannot wrap NULL Surface!"
|
91
|
+
else
|
92
|
+
@struct = surf
|
93
|
+
end
|
94
|
+
return
|
95
|
+
end
|
96
|
+
|
97
|
+
unless size.kind_of? Array
|
98
|
+
raise TypeError, "Surface size is not an Array: #{size.inspect}"
|
99
|
+
end
|
100
|
+
|
101
|
+
unless size.length == 2 and size.all?{ |n| n.kind_of? Numeric }
|
102
|
+
raise ArgumentError, "Invalid Surface size: #{size.inspect}"
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
pixformat = nil
|
107
|
+
|
108
|
+
vs = SDL.GetVideoSurface()
|
109
|
+
|
110
|
+
unless( vs.pointer.null? )
|
111
|
+
# Pixel format is retrieved from the video surface.
|
112
|
+
pixformat = vs.format
|
113
|
+
else
|
114
|
+
# We can only get the system color depth when the
|
115
|
+
# video system has been initialized.
|
116
|
+
if( Rubygame.init_video_system == 0 )
|
117
|
+
pixformat = SDL.GetVideoInfo().vfmt
|
118
|
+
else
|
119
|
+
raise(Rubygame::SDLError,
|
120
|
+
"Could not initialize SDL video subsystem.")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
rmask = pixformat.Rmask
|
125
|
+
gmask = pixformat.Gmask
|
126
|
+
bmask = pixformat.Bmask
|
127
|
+
amask = pixformat.Amask
|
128
|
+
|
129
|
+
if( depth <= 0 )
|
130
|
+
depth = pixformat.BitsPerPixel
|
131
|
+
end
|
132
|
+
|
133
|
+
w, h = size
|
134
|
+
|
135
|
+
flags = Rubygame.collapse_flags(flags)
|
136
|
+
|
137
|
+
@struct = SDL.CreateRGBSurface(flags, w, h, depth,
|
138
|
+
rmask, gmask, bmask, amask)
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
# Return the width (in pixels) of the surface.
|
144
|
+
#
|
145
|
+
def w
|
146
|
+
@struct.w
|
147
|
+
end
|
148
|
+
alias :width :w
|
149
|
+
|
150
|
+
|
151
|
+
# Return the height (in pixels) of the surface.
|
152
|
+
#
|
153
|
+
def h
|
154
|
+
@struct.h
|
155
|
+
end
|
156
|
+
alias :height :h
|
157
|
+
|
158
|
+
|
159
|
+
# call-seq:
|
160
|
+
# size -> [w,h]
|
161
|
+
#
|
162
|
+
# Return the surface's width and height (in pixels) in an Array.
|
163
|
+
#
|
164
|
+
def size
|
165
|
+
[@struct.w, @struct.h]
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
# Return the color depth (in bits per pixel) of the surface.
|
170
|
+
#
|
171
|
+
def depth
|
172
|
+
@struct.format.BitsPerPixel
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# Return any flags the surface was initialized with
|
177
|
+
# (as a bitwise OR'd integer).
|
178
|
+
#
|
179
|
+
def flags
|
180
|
+
@struct.flags
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
# call-seq:
|
185
|
+
# masks -> [r,g,b,a]
|
186
|
+
#
|
187
|
+
# Return the color masks [r,g,b,a] of the surface. Almost everyone can
|
188
|
+
# ignore this function. Color masks are used to separate an
|
189
|
+
# integer representation of a color into its seperate channels.
|
190
|
+
#
|
191
|
+
def masks
|
192
|
+
fmt = @struct.format
|
193
|
+
[fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask]
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
# Return the per-surface alpha (opacity; non-transparency) of the surface.
|
198
|
+
# It can range from 0 (full transparent) to 255 (full opaque).
|
199
|
+
#
|
200
|
+
def alpha
|
201
|
+
@struct.format.alpha
|
202
|
+
end
|
203
|
+
|
204
|
+
# Set the per-surface alpha (opacity; non-transparency) of the surface.
|
205
|
+
# You can do the same thing with #alpha= if you don't care about flags.
|
206
|
+
#
|
207
|
+
# This function takes these arguments:
|
208
|
+
# alpha:: requested opacity of the surface. Alpha must be from 0
|
209
|
+
# (fully transparent) to 255 (fully opaque).
|
210
|
+
# flags:: 0 or Rubygame::SRCALPHA (default). Most people will want the
|
211
|
+
# default, in which case this argument can be omitted. For advanced
|
212
|
+
# users: this flag affects the surface as described in the docs for
|
213
|
+
# the SDL C function, SDL_SetAlpha.
|
214
|
+
#
|
215
|
+
# Returns self.
|
216
|
+
#
|
217
|
+
def set_alpha( alpha, flags=Rubygame::SRCALPHA )
|
218
|
+
result = SDL.SetAlpha(@struct, flags, alpha.to_i)
|
219
|
+
raise Rubygame::SDLError, SDL.GetError() unless result == 0
|
220
|
+
return self
|
221
|
+
end
|
222
|
+
|
223
|
+
alias :alpha= :set_alpha
|
224
|
+
|
225
|
+
|
226
|
+
# call-seq:
|
227
|
+
# colorkey -> [r,g,b] or nil
|
228
|
+
#
|
229
|
+
# Return the colorkey of the surface in the form [r,g,b] (or +nil+ if there
|
230
|
+
# is no key). The colorkey of a surface is the exact color which will be
|
231
|
+
# ignored when the surface is blitted, effectively turning that color
|
232
|
+
# transparent. This is often used to make a blue (for example) background
|
233
|
+
# on an image seem transparent.
|
234
|
+
#
|
235
|
+
def colorkey
|
236
|
+
if( (@struct.flags & Rubygame::SRCCOLORKEY) == Rubygame::SRCCOLORKEY )
|
237
|
+
SDL::GetRGB(@struct.format.colorkey, @struct.format)
|
238
|
+
else
|
239
|
+
nil
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
# Set the colorkey of the surface. See Surface#colorkey for a description
|
245
|
+
# of colorkeys.
|
246
|
+
#
|
247
|
+
# This method takes these arguments:
|
248
|
+
# color:: color to use as the key, in the form [r,g,b]. Can be +nil+ to
|
249
|
+
# un-set the colorkey.
|
250
|
+
# flags:: 0 or Rubygame::SRCCOLORKEY (default) or
|
251
|
+
# Rubygame::SRCCOLORKEY|Rubygame::SDL_RLEACCEL. Most people will
|
252
|
+
# want the default, in which case this argument can be omitted. For
|
253
|
+
# advanced users: this flag affects the surface as described in the
|
254
|
+
# docs for the SDL C function, SDL_SetColorkey.
|
255
|
+
#
|
256
|
+
def set_colorkey( color, flags=Rubygame::SRCCOLORKEY )
|
257
|
+
if color.nil?
|
258
|
+
color, flags = 0, 0
|
259
|
+
else
|
260
|
+
color = _map_sdl_color( color )
|
261
|
+
end
|
262
|
+
|
263
|
+
result = SDL.SetColorKey(@struct, flags, color)
|
264
|
+
raise Rubygame::SDLError, SDL.GetError() unless result == 0
|
265
|
+
return self
|
266
|
+
end
|
267
|
+
|
268
|
+
alias :colorkey= :set_colorkey
|
269
|
+
|
270
|
+
|
271
|
+
# Blit (copy) all or part of the surface's image to another surface,
|
272
|
+
# at a given position. Returns a Rect representing the area of
|
273
|
+
# +target+ which was affected by the blit.
|
274
|
+
#
|
275
|
+
# This method takes these arguments:
|
276
|
+
# target:: the target Surface on which to paste the image.
|
277
|
+
# pos:: the coordinates of the top-left corner of the blit.
|
278
|
+
# Affects the area of +target+ the image data is /pasted/
|
279
|
+
# over. Can also be a Rect or an Array larger than 2, but
|
280
|
+
# width and height will be ignored.
|
281
|
+
# src_rect:: a Rect representing the area of the source surface to get data
|
282
|
+
# from. Affects where the image data is /copied/ from.
|
283
|
+
# Can also be an Array of no less than 4 values.
|
284
|
+
#
|
285
|
+
def blit( target, pos, src_rect=nil )
|
286
|
+
unless target.kind_of? Rubygame::Surface
|
287
|
+
raise TypeError, "blit target must be a Surface"
|
288
|
+
end
|
289
|
+
|
290
|
+
src_x, src_y, src_w, src_h =
|
291
|
+
case src_rect
|
292
|
+
when SDL::Rect
|
293
|
+
[src_rect.x, src_rect.y, src_rect.w, src_rect.h]
|
294
|
+
when Array
|
295
|
+
src_rect
|
296
|
+
when nil
|
297
|
+
[0, 0] + self.size
|
298
|
+
end
|
299
|
+
|
300
|
+
src_rect = SDL::Rect.new([src_x, src_y, src_w, src_h])
|
301
|
+
blit_x, blit_y = pos
|
302
|
+
blit_rect = SDL::Rect.new([blit_x, blit_y, src_w, src_h])
|
303
|
+
|
304
|
+
SDL.BlitSurface( @struct, src_rect, target.struct, blit_rect )
|
305
|
+
|
306
|
+
return Rubygame::Rect.new( blit_rect.to_ary )
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
# Fill all or part of a Surface with a color.
|
311
|
+
#
|
312
|
+
# This method takes these arguments:
|
313
|
+
# color:: color to fill with, in the form +[r,g,b]+ or +[r,g,b,a]+ (for
|
314
|
+
# partially transparent fills).
|
315
|
+
# rect:: a Rubygame::Rect representing the area of the surface to fill
|
316
|
+
# with color. Omit to fill the entire surface.
|
317
|
+
#
|
318
|
+
def fill( color, rect=nil )
|
319
|
+
unless rect.nil? or rect.kind_of? Array
|
320
|
+
raise TypeError, "invalid fill Rect: #{rect.inspect}"
|
321
|
+
end
|
322
|
+
|
323
|
+
color = _map_sdl_color( color )
|
324
|
+
rect = SDL::Rect.new( rect.to_ary ) unless rect.nil?
|
325
|
+
SDL.FillRect( @struct, rect, color )
|
326
|
+
return self
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
# Return a Rect with the same width and height as the Surface,
|
331
|
+
# with topleft = [0,0].
|
332
|
+
#
|
333
|
+
def make_rect()
|
334
|
+
return Rubygame::Rect.new( 0, 0, self.w, self.h )
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
# call-seq:
|
339
|
+
# get_at( [x,y] )
|
340
|
+
# get_at( x,y )
|
341
|
+
#
|
342
|
+
# Return the color [r,g,b,a] (0-255) of the pixel at [x,y].
|
343
|
+
# If the Surface does not have a per-pixel alpha channel (i.e. not
|
344
|
+
# 32-bit), alpha will always be 255. The Surface's overall alpha
|
345
|
+
# value (from #set_alpha) does not affect the returned alpha value.
|
346
|
+
#
|
347
|
+
# Raises IndexError if the coordinates are out of bounds.
|
348
|
+
#
|
349
|
+
def get_at( *args )
|
350
|
+
x,y = case args.length
|
351
|
+
when 1; args[0].to_ary.collect { |n| n.round }
|
352
|
+
when 2; [args[0].round, args[1].round]
|
353
|
+
else
|
354
|
+
raise( ArgumentError,
|
355
|
+
"wrong number of arguments (#{args.length} for 1)" )
|
356
|
+
end
|
357
|
+
|
358
|
+
if( x < 0 or x >= @struct.w or y < 0 or y >= @struct.h)
|
359
|
+
raise( IndexError, "point [%d,%d] is out of bounds for %dx%d Surface"%\
|
360
|
+
[x, y, @struct.w, @struct.h] )
|
361
|
+
end
|
362
|
+
|
363
|
+
SDL.LockSurface(@struct)
|
364
|
+
|
365
|
+
bpp = @struct.format.BytesPerPixel
|
366
|
+
ptr = @struct.pixels + (y * @struct.pitch + x * bpp)
|
367
|
+
|
368
|
+
pixel =
|
369
|
+
case bpp
|
370
|
+
when 1
|
371
|
+
ptr.get_uint8(0)
|
372
|
+
when 2
|
373
|
+
ptr.get_uint16(0)
|
374
|
+
when 3
|
375
|
+
if( FFI::Platform::BYTE_ORDER == FFI::Platform::BIG_ENDIAN )
|
376
|
+
(ptr.get_uint8(0) << 16)|(ptr.get_uint8(1) << 8)|ptr.get_uint8(2)
|
377
|
+
else
|
378
|
+
ptr.get_uint8(0)|(ptr.get_uint8(1) << 8)|(ptr.get_uint8(2) << 16)
|
379
|
+
end
|
380
|
+
when 4
|
381
|
+
ptr.get_uint32(0)
|
382
|
+
end
|
383
|
+
|
384
|
+
SDL.UnlockSurface(@struct)
|
385
|
+
|
386
|
+
return SDL::GetRGBA(pixel, @struct.format)
|
387
|
+
end
|
388
|
+
|
389
|
+
|
390
|
+
# call-seq:
|
391
|
+
# set_at( [x,y], color )
|
392
|
+
#
|
393
|
+
# Set the color of the pixel at [x,y]. If no alpha value is given,
|
394
|
+
# or if the Surface does not have a per-pixel alpha channel (i.e. not
|
395
|
+
# 32-bit), the pixel will be set at full opacity.
|
396
|
+
#
|
397
|
+
# color can be one of:
|
398
|
+
# * an Array, [r,g,b] or [r,g,b,a] with each component in 0-255.
|
399
|
+
# * an instance of Rubygame::ColorRGB, Rubygame::ColorHSV, etc.
|
400
|
+
# * the name of a color in Rubygame::Color, as a Symbol or String
|
401
|
+
#
|
402
|
+
# Raises IndexError if the coordinates are out of bounds.
|
403
|
+
#
|
404
|
+
def set_at( pos, color )
|
405
|
+
x,y = pos.to_ary.collect { |n| n.round }
|
406
|
+
|
407
|
+
if( x < 0 or x >= @struct.w or y < 0 or y >= @struct.h)
|
408
|
+
raise( IndexError, "point [%d,%d] is out of bounds for %dx%d Surface"%\
|
409
|
+
[x, y, @struct.w, @struct.h] )
|
410
|
+
end
|
411
|
+
|
412
|
+
color = _map_sdl_color( color )
|
413
|
+
|
414
|
+
SDL.LockSurface(@struct)
|
415
|
+
|
416
|
+
bpp = @struct.format.BytesPerPixel
|
417
|
+
ptr = @struct.pixels + (y * @struct.pitch + x * bpp)
|
418
|
+
|
419
|
+
case bpp
|
420
|
+
when 1
|
421
|
+
ptr.put_uint8(0, color)
|
422
|
+
when 2
|
423
|
+
ptr.put_uint16(0, color)
|
424
|
+
when 3
|
425
|
+
if( FFI::Platform::BYTE_ORDER == FFI::Platform::BIG_ENDIAN )
|
426
|
+
ptr.put_uint8(0, (color >> 16) & 0xff)
|
427
|
+
ptr.put_uint8(1, (color >> 8) & 0xff)
|
428
|
+
ptr.put_uint8(2, color & 0xff)
|
429
|
+
else
|
430
|
+
ptr.put_uint8(0, color & 0xff)
|
431
|
+
ptr.put_uint8(1, (color >> 8) & 0xff)
|
432
|
+
ptr.put_uint8(2, (color >> 16) & 0xff)
|
433
|
+
end
|
434
|
+
when 4
|
435
|
+
ptr.put_uint32(0, color)
|
436
|
+
end
|
437
|
+
|
438
|
+
SDL.UnlockSurface(@struct)
|
439
|
+
|
440
|
+
return
|
441
|
+
end
|
442
|
+
|
443
|
+
|
444
|
+
# Return a string of pixel data for the Surface. Most users will not
|
445
|
+
# need to use this method. If you want to convert a Surface into an
|
446
|
+
# OpenGL texture, pass the returned string to the TexImage2D method
|
447
|
+
# of the ruby-opengl library. (See samples/demo_gl_tex.rb for an
|
448
|
+
# example.)
|
449
|
+
#
|
450
|
+
# (Please note that the dimensions of OpenGL textures must be powers
|
451
|
+
# of 2 (e.g. 64x128, 512x512), so if you want to use a Surface as an
|
452
|
+
# OpenGL texture, the Surface's dimensions must also be powers of
|
453
|
+
# 2!)
|
454
|
+
#
|
455
|
+
def pixels
|
456
|
+
len = @struct.pitch * @struct.h
|
457
|
+
SDL.LockSurface(@struct)
|
458
|
+
pix = @struct.pixels.get_bytes(0, len)
|
459
|
+
SDL.UnlockSurface(@struct)
|
460
|
+
return pix
|
461
|
+
end
|
462
|
+
|
463
|
+
|
464
|
+
|
465
|
+
# Return the clipping area for this Surface. See also #clip=.
|
466
|
+
#
|
467
|
+
# The clipping area of a Surface is the only part which can be drawn
|
468
|
+
# upon by other Surface's #blits. By default, the clipping area is
|
469
|
+
# the entire area of the Surface.
|
470
|
+
#
|
471
|
+
def clip
|
472
|
+
Rubygame::Rect.new( SDL.GetClipRect(@struct).to_ary )
|
473
|
+
end
|
474
|
+
|
475
|
+
|
476
|
+
# Set the current clipping area of the Surface. See also #clip.
|
477
|
+
#
|
478
|
+
# The clipping area of a Surface is the only part which can be drawn
|
479
|
+
# upon by other Surface's #blits. The clipping area will be clipped
|
480
|
+
# to the edges of the surface so that the clipping area for a
|
481
|
+
# Surface can never fall outside the edges of the Surface.
|
482
|
+
#
|
483
|
+
# By default, the clipping area is the entire area of the Surface.
|
484
|
+
# You may set clip to +nil+, which will reset the clipping area to
|
485
|
+
# cover the entire Surface.
|
486
|
+
#
|
487
|
+
def clip=( newclip )
|
488
|
+
newclip = case newclip
|
489
|
+
when nil, SDL::Rect
|
490
|
+
newclip # no change
|
491
|
+
when Rubygame::Rect
|
492
|
+
newclip.to_sdl
|
493
|
+
when Array
|
494
|
+
Rubygame::Rect.new(newclip).to_sdl
|
495
|
+
end
|
496
|
+
|
497
|
+
SDL.SetClipRect(@struct, newclip)
|
498
|
+
return self
|
499
|
+
end
|
500
|
+
|
501
|
+
|
502
|
+
|
503
|
+
# Copies the Surface to a new Surface with the pixel format of
|
504
|
+
# another Surface, for fast blitting. May raise SDLError if a
|
505
|
+
# problem occurs.
|
506
|
+
#
|
507
|
+
# This method takes these arguments:
|
508
|
+
# other:: The Surface to match pixel format against. If +nil+, the
|
509
|
+
# display surface (i.e. Screen) is used, if available; if
|
510
|
+
# no display surface is available, raises SDLError.
|
511
|
+
# flags:: An array of flags to pass when the new Surface is created.
|
512
|
+
# See Surface#new.
|
513
|
+
#
|
514
|
+
def convert( other=nil, flags=nil )
|
515
|
+
|
516
|
+
if other.nil?
|
517
|
+
begin
|
518
|
+
other = Rubygame::ScreenFFI.get_surface
|
519
|
+
rescue Rubygame::SDLError
|
520
|
+
raise( Rubygame::SDLError, "Cannot convert Surface with no target " +
|
521
|
+
"given and no Screen made: #{SDL.GetError()}" )
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
flags = Rubygame.collapse_flags(flags)
|
526
|
+
|
527
|
+
newsurf =
|
528
|
+
if( Rubygame.init_video_system() == 0 )
|
529
|
+
SDL.ConvertSurface( @struct, other.struct.format, flags )
|
530
|
+
else
|
531
|
+
nil
|
532
|
+
end
|
533
|
+
|
534
|
+
if( newsurf.nil? or newsurf.pointer.null?)
|
535
|
+
raise( Rubygame::SDLError,
|
536
|
+
"Could not convert the Surface: #{SDL.GetError()}" )
|
537
|
+
end
|
538
|
+
|
539
|
+
# Wrap it
|
540
|
+
return self.class.new( newsurf )
|
541
|
+
end
|
542
|
+
|
543
|
+
|
544
|
+
|
545
|
+
# Copies the Surface to a new Surface with the pixel format of the
|
546
|
+
# display, suitable for fast blitting to the display surface (i.e.
|
547
|
+
# Screen). May raise SDLError if a problem occurs.
|
548
|
+
#
|
549
|
+
# If you want to take advantage of hardware colorkey or alpha blit
|
550
|
+
# acceleration, you should set the colorkey and alpha value before
|
551
|
+
# calling this function.
|
552
|
+
#
|
553
|
+
def to_display
|
554
|
+
newsurf =
|
555
|
+
if( Rubygame.init_video_system() == 0 )
|
556
|
+
SDL.DisplayFormat( @struct )
|
557
|
+
else
|
558
|
+
nil
|
559
|
+
end
|
560
|
+
|
561
|
+
if( newsurf.nil? or newsurf.pointer.null?)
|
562
|
+
raise( Rubygame::SDLError,
|
563
|
+
"Could not convert the Surface to display format: %s"%\
|
564
|
+
SDL.GetError() )
|
565
|
+
end
|
566
|
+
|
567
|
+
# Wrap it
|
568
|
+
return self.class.new( newsurf )
|
569
|
+
end
|
570
|
+
|
571
|
+
|
572
|
+
|
573
|
+
# Like #to_display except the Surface has an extra channel for alpha
|
574
|
+
# (i.e. opacity). May raise SDLError if a problem occurs.
|
575
|
+
#
|
576
|
+
# This function can be used to convert a colorkey to an alpha
|
577
|
+
# channel, if the SRCCOLORKEY flag is set on the surface. The
|
578
|
+
# generated surface will then be transparent (alpha=0) where the
|
579
|
+
# pixels match the colorkey, and opaque (alpha=255) elsewhere.
|
580
|
+
#
|
581
|
+
def to_display_alpha
|
582
|
+
newsurf =
|
583
|
+
if( Rubygame.init_video_system() == 0 )
|
584
|
+
SDL.DisplayFormatAlpha( @struct )
|
585
|
+
else
|
586
|
+
nil
|
587
|
+
end
|
588
|
+
|
589
|
+
if( newsurf.nil? or newsurf.pointer.null?)
|
590
|
+
raise( Rubygame::SDLError,
|
591
|
+
"Could not convert the Surface to display format "+
|
592
|
+
"with alpha channel: #{SDL.GetError()}" )
|
593
|
+
end
|
594
|
+
|
595
|
+
# Wrap it
|
596
|
+
return self.class.new( newsurf )
|
597
|
+
end
|
598
|
+
|
599
|
+
|
600
|
+
# Save the Surface as a Windows Bitmap (BMP) file with the given filename.
|
601
|
+
# May raise SDLError if a problem occurs.
|
602
|
+
#
|
603
|
+
def savebmp( filename )
|
604
|
+
result = SDL.SaveBMP( @struct, filename )
|
605
|
+
if(result != 0)
|
606
|
+
raise( Rubygame::SDLError, "Couldn't save surface to file %s: %s"%\
|
607
|
+
[filename, SDL.GetError()] )
|
608
|
+
end
|
609
|
+
nil
|
610
|
+
end
|
611
|
+
|
612
|
+
|
613
|
+
def to_s
|
614
|
+
"#<%s:%#.x>"%[self.class.name, self.object_id]
|
615
|
+
end
|
616
|
+
|
617
|
+
alias :inspect :to_s
|
618
|
+
|
619
|
+
|
620
|
+
private
|
621
|
+
|
622
|
+
def _map_sdl_color( color ) # :nodoc:
|
623
|
+
SDL.MapRGBA( @struct.format, *Rubygame::Color.make_sdl_rgba(color) )
|
624
|
+
end
|
625
|
+
|
626
|
+
end
|