├── .gitignore
├── CREDITS.rdoc
├── LICENSE.txt
├── NEWS.rdoc
├── README.rdoc
├── ROADMAP.rdoc
├── Rakefile
├── doc
├── custom_sdl_load_paths.rdoc
├── getting_started.rdoc
├── keyboard_symbols.rdoc
├── macosx_install.rdoc
├── managing_framerate.rdoc
└── windows_install.rdoc
├── lib
├── rubygame.rb
└── rubygame
│ ├── audio.rb
│ ├── clock.rb
│ ├── color.rb
│ ├── color
│ ├── models
│ │ ├── base.rb
│ │ ├── hsl.rb
│ │ ├── hsv.rb
│ │ ├── rgb.rb
│ │ └── rgb255.rb
│ └── palettes
│ │ ├── css.rb
│ │ ├── palette.rb
│ │ └── x11.rb
│ ├── constants.rb
│ ├── deprecated_mixer.rb
│ ├── event.rb
│ ├── event_actions.rb
│ ├── event_handler.rb
│ ├── event_hook.rb
│ ├── event_triggers.rb
│ ├── events.rb
│ ├── events
│ ├── clock_events.rb
│ ├── joystick_events.rb
│ ├── keyboard_events.rb
│ ├── misc_events.rb
│ └── mouse_events.rb
│ ├── ftor.rb
│ ├── gfx.rb
│ ├── gl.rb
│ ├── hotspot.rb
│ ├── image.rb
│ ├── imagefont.rb
│ ├── joystick.rb
│ ├── keyconstants.rb
│ ├── main.rb
│ ├── mediabag.rb
│ ├── mixer.rb
│ ├── music.rb
│ ├── named_resource.rb
│ ├── new_rect.rb
│ ├── queue.rb
│ ├── rect.rb
│ ├── screen.rb
│ ├── sfont.rb
│ ├── shared.rb
│ ├── sound.rb
│ ├── sprite.rb
│ ├── surface.rb
│ ├── ttf.rb
│ └── vector2.rb
├── samples
├── FreeSans.ttf
├── GPL.txt
├── README
├── chimp.bmp
├── chimp.rb
├── demo_draw.rb
├── demo_imagefont.rb
├── demo_music.rb
├── demo_opengl.rb
├── demo_palette.rb
├── demo_rubygame.rb
├── demo_ttf.rb
├── demo_utf8.rb
├── fist.bmp
├── framerate.rb
├── image_viewer.rb
├── load_and_blit.rb
├── palettized.png
├── panda.png
├── punch.wav
├── ruby.png
├── rubygame.png
├── song.ogg
├── term16.png
└── whiff.wav
└── spec
├── audio_spec.rb
├── clock_spec.rb
├── color_spec.rb
├── event_actions_spec.rb
├── event_handler_spec.rb
├── event_hook_spec.rb
├── event_queue_spec.rb
├── event_triggers_spec.rb
├── ftor_spec.rb
├── has_event_handler_spec.rb
├── image.png
├── image_8bit.png
├── joystick_events_spec.rb
├── keyboard_events_spec.rb
├── misc_events_spec.rb
├── mouse_events_spec.rb
├── music_spec.rb
├── named_resource_spec.rb
├── rect_spec.rb
├── screen_spec.rb
├── short.ogg
├── sound_spec.rb
├── spec_helper.rb
├── surface_spec.rb
└── vector2_spec.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 |
3 | /pkg/
4 | /html/
5 | /ri/
6 | /coverage/
7 |
--------------------------------------------------------------------------------
/CREDITS.rdoc:
--------------------------------------------------------------------------------
1 | == Developers
2 |
3 | - John Croisant / jacius
4 | Email:: jacius at gmail.com
5 | Role:: Creator; primary developer
6 | Date:: 2004 - present
7 |
8 | == Past Developers
9 |
10 | - Ash Wilson / smashwilson
11 | Email:: smashwilson at gmail.com
12 | Role:: Assistant developer
13 | Date:: 2007 - 2008
14 |
15 | - Roger Ostrander / denor
16 | Email:: atiaxi at gmail.com
17 | Role:: Assistant developer
18 | Date:: 2007 - 2008
19 |
20 | - Rusterholz Stefan / apeiros
21 | Email:: apeiros at gmx.net
22 | Role:: Assistant developer
23 | Date:: 2007 - 2008
24 |
25 | - Bjorn De Meyer / beoran
26 | Email:: beoran at gmail.com
27 | Role:: Assistant developer
28 | Date:: Nov 2007 - 2008
29 |
30 | == Other Source Contributors
31 |
32 | - Randy Eckenrode
33 | Email:: randy.eckenrode at gmail.com
34 | Contribution:: Patch to improve Win32 compatibility (memory allocation,
35 | extconf.rb improvements, misc. other changes).
36 | Date:: received 2006-01-19; applied 2006-02-04 (r143).
37 |
38 | - Yun, Jonghyouk / ageldama
39 | Email:: ageldama at gmail.com
40 | Contribution:: Patch to add TTF#render_utf and TTF#render_unicode methods;
41 | UTF8 demo application.
42 | Date:: received 2007-03-04; applied 2007-04-13 (r235).
43 |
44 | - Johan Berntsson
45 | Email:: johan at microheaven.com
46 | Contribution:: Patch to add Mixer::Music class (music playback).
47 | Date:: 2007-04-27 (r304).
48 |
49 | - Daniel Neis Araujo / danielneis
50 | Email:: danielneis at gmail.com
51 | Contribution:: Patch to add Sprite#undraw (based on UpdateGroup#undraw).
52 | Date:: 2007-07-29 (r460).
53 |
54 | - ippa
55 | Email:: admin at rubylicio.us
56 | Contribution:: Patch to optimize Rect#collide_rect?
57 | Date:: 2007-11-21 (r595)
58 |
59 | - Michael Swiger / mokkan
60 | Email:: mokkan at users.sourceforge.net
61 | Contribution:: Patch to add Screen.icon=
62 | Date:: 2007-11-21 (r597)
63 |
64 | - Elio Cuevas Gómez / elcugo
65 | Email:: elcugo at gmail.com
66 | Contribution:: Patch to fix color conversion segfault on x86_64.
67 | Date:: 2008-07-31
68 |
69 | - Tyler Church
70 | Email:: tylertrain at yahoo.com
71 | Contribution:: Patch to add Rubygame.get_key_state
72 | (now Rubygame.pressed_keys)
73 | Date:: 2010-09-06
74 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | = Rubygame README
2 |
3 | == What is Rubygame?
4 |
5 | Rubygame is a cross-platform game-development library for Ruby,
6 | inspired by Pygame. Rubygame strives to empower game developers by
7 | providing them with powerful and flexible mid-to-high level tools.
8 | Instead of worrying about low-level technical details, you can focus
9 | your energy on more interesting things (like making a fun game).
10 |
11 | === Relevant Links
12 | 1. Rubygame: http://rubygame.org
13 | 2. Ruby: http://www.ruby-lang.org
14 | 3. Pygame: http://www.pygame.org
15 |
16 |
17 | == Requirements
18 |
19 | You will definitely need these software packages to use Rubygame:
20 |
21 | * Ruby >= 1.8.6
22 | * Or, JRuby >= 1.4
23 | * Ruby-SDL-FFI >= 0.4
24 | * SDL >= 1.2.7 (1.2.14 on MacOS X 10.6)
25 |
26 | It's highly recommended that you have these packages as well, or some
27 | cool features won't be available!
28 |
29 | * SDL_gfx >= 2.0.13
30 | * SDL_image >= 1.2.3
31 | * SDL_mixer >= 1.2.7
32 | * SDL_ttf >= 2.0.6
33 |
34 | For running the spec suite ('rake spec'), you will need:
35 |
36 | * RSpec >= 2.4
37 | * RCov >= 0.9 (only needed for 'rake rcov')
38 |
39 | == Install
40 |
41 | === Basic Install
42 |
43 | The simplest way to install is with RubyGems:
44 |
45 | $ sudo gem install rubygame
46 |
47 | Another way is to install directly from the source:
48 |
49 | $ sudo rake install
50 |
51 | Or generate and install a gem from the source:
52 |
53 | $ rake gem
54 | $ sudo gem install pkg/rubygame-*.gem
55 |
56 | === Generating documentation
57 |
58 | You can generate documentation for Rubygame's API by running:
59 |
60 | $ rake rdoc
61 |
62 | Documentation will be generated as HTML in the 'html' directory.
63 | Open 'html/index.html' in a web browser to get started.
64 |
65 |
66 | == Usage
67 |
68 | See the documentation (online at http://docs.rubygame.org, or
69 | generated locally with the 'rake rdoc' command).
70 |
71 | We also recommend that you take a peek at the demo applications in
72 | the 'samples' directory, especially image_viewer.rb,
73 | demo_rubygame.rb, and chimp.rb.
74 |
75 |
76 | == About the version number
77 |
78 | The version number of Rubygame has a strict meaning, to help you
79 | decide whether the new version might break your application. The
80 | version number has 3 parts: the major number, the minor number, and
81 | the patch number. For the example of Rubygame 2.6.0:
82 |
83 | 2 . 6 . 0
84 | MAJOR . MINOR . PATCH
85 |
86 | When a new release of Rubygame is made, one of the version numbers
87 | will go up, and the numbers that come after it will be reset to 0.
88 | Which number will go up depends on how much the Rubygame API changed:
89 |
90 | - *MAJOR*: API has changed, and old apps _must_ be updated.
91 | An example of this is when a class has been significantly changed,
92 | or a method has renamed/moved to another module and the old name is
93 | removed.
94 |
95 | - *MINOR*: API has changed, but old apps will still work.
96 | An example of this is when a new feature has been added, or a
97 | method has been renamed but the old name is still supported.
98 |
99 | - *PATCH*: API has not changed at all.
100 | An example of this is when a bug has been fixed, or existing code
101 | has been improved beneath the surface.
102 |
103 |
104 | == License
105 |
106 | Rubygame is distributed under the terms of the GNU Lesser GPL.
107 | See LICENSE for more details.
108 |
109 | Some of the sample files are distributed under licenses other than
110 | the GNU Lesser GPL. See 'samples/README' and 'samples/GPL' for more
111 | details.
112 |
113 |
114 | John Croisant (jacius at gmail.com)
115 |
--------------------------------------------------------------------------------
/ROADMAP.rdoc:
--------------------------------------------------------------------------------
1 | = ROADMAP
2 |
3 | This represents the direction Rubygame will be going in, but
4 | keep in mind that plans and details may change over time.
5 |
6 |
7 | == 2.X (_possible_ minor releases before 3.0)
8 |
9 | === Focus: Surface & Rect
10 |
11 | - Surface improvements
12 | - Make Surface instances copyable and marshalable
13 | - Support for palettes on 8-bit Surfaces
14 | - Export as OpenGL-ready 32bit pixel data.
15 | - To Fix: New Surfaces never have alpha channels
16 | - To Add: Surface#pixels= (set pixel data directly)
17 | - To Add: Surface.load_from_pixels (create from pixel data)
18 |
19 | - Optimize Rect for speed
20 |
21 |
22 | === Focus: Sprites
23 |
24 | - New sprite system
25 | - New Sprite, Scene, and Camera classes.
26 | - More powerful and simpler to use.
27 | - Integration with the Chipmunk physics library?
28 |
29 |
30 |
31 | == 3.0 (next major release)
32 |
33 | - Backwards compatibility is broken:
34 | - Deprecated classes / methods retired:
35 | - Rubygame::Mixer module.
36 | - Rubygame::Mixer::Sample class. Use Rubygame::Sound.
37 | - Rubygame::Mixer::Music class. Use Rubygame::Music.
38 | - Rubygame::Surface.load_image method. Use Rubygame::Surface.load.
39 | - Rubygame::Ftor class. An alternative class will be provided.
40 | - Rubygame::MediaBag class. Use Surface#[], Sound#[], and Music#[].
41 | - Surface#get_at
42 | - Sprites::Group#collide_group
43 |
44 | - Change Sprites::Group#collide_group to scrap the 'killa/killb' stuff,
45 | take a block instead.
46 |
47 |
48 |
49 | == Possible future developments
50 |
51 | - Switch from SDL_gfx to SPriG for graphics primitives.
52 | - SPriG provides more functionality and flexibility, and a more
53 | consistent interface.
54 | - How does speed compare?
55 | - Is it buggy?
56 |
57 | - Alternative back-ends:
58 | - OpenGL (faster rendering, better Mac support)
59 | - Allegro?
60 |
61 | - Polygon, circle, and other geometric primitives
62 | - Drawing, with styles?
63 | - OpenGL drawing?
64 | - Collision detection?
65 | - Physical shapes w/ Chipmunk?
66 | - Generate bounding Polygon from an image automatically?
67 |
68 | - Path (Curve?) (graphs/plots for tracing position and other uses)
69 | - Can find the position N units along the path.
70 | - Can draw a line showing the path.
71 | - LinearPath (connect the dots, linear interpolation)
72 | - BezierPath (chain of continuous cubic Bézier curves)
73 | - CodePath (calculated from a code block)
74 |
75 | - Effect (Action?)
76 | - "Attach" to an instance, does something over time.
77 | - E.g. moves a sprite from point A to point B over N seconds.
78 | - Many types of effects, easy to define custom ones.
79 | - Takes parameters: start/end time, others depending on effect.
80 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is the Rakefile for Rubygame. It's used for packaging,
3 | # installing, generating the documentation, and running specs.
4 | #
5 |
6 |
7 | # The version number for Rubygame.
8 | # If you update this, also update lib/rubygame/main.rb.
9 | RUBYGAME_VERSION = [2,6,4]
10 |
11 |
12 |
13 | require 'rubygems'
14 |
15 | require 'rake'
16 | require 'rake/gempackagetask'
17 | require 'rake/rdoctask'
18 |
19 | require "rbconfig"
20 | include Config
21 |
22 |
23 |
24 | #######
25 | # GEM #
26 | #######
27 |
28 | gem_spec = Gem::Specification.new do |s|
29 | s.name = "rubygame"
30 | s.version = RUBYGAME_VERSION.join(".")
31 | s.author = "John Croisant"
32 | s.email = "jacius@gmail.com"
33 | s.homepage = "http://rubygame.org/"
34 | s.summary = "Clean and powerful library for game programming"
35 | s.rubyforge_project = "rubygame"
36 |
37 | s.files = FileList.new do |fl|
38 | fl.include("{lib,samples,doc}/**/*")
39 | end
40 |
41 | s.require_paths = ["lib"]
42 |
43 | s.has_rdoc = true
44 | s.extra_rdoc_files = FileList.new do |fl|
45 | fl.include "doc/*.rdoc", "./*.rdoc", "LICENSE.txt"
46 | end
47 |
48 | s.required_ruby_version = ">= 1.8"
49 | s.add_dependency( "rake", ">=0.7.0" )
50 | s.add_dependency( "ruby-sdl-ffi", ">=0.4.0" )
51 | s.requirements = ["SDL >= 1.2.7",
52 | "SDL_gfx >= 2.0.10 (optional)",
53 | "SDL_image >= 1.2.3 (optional)",
54 | "SDL_mixer >= 1.2.7 (optional)",
55 | "SDL_ttf >= 2.0.6 (optional)"]
56 |
57 | end
58 |
59 |
60 | Rake::GemPackageTask.new(gem_spec) do |pkg|
61 | pkg.need_tar_bz2 = true
62 | end
63 |
64 |
65 |
66 | ########
67 | # RDOC #
68 | ########
69 |
70 | Rake::RDocTask.new do |rd|
71 | rd.main = "README.rdoc"
72 | rd.title = "Rubygame #{RUBYGAME_VERSION.join(".")} Docs"
73 | rd.rdoc_files.include("lib/rubygame/**/*.rb",
74 | "doc/*.rdoc",
75 | "./*.rdoc",
76 | "LICENSE.txt")
77 | end
78 |
79 | desc "Generate RI-formatted docs."
80 | task(:ri) do
81 | sh('rdoc --ri --threads=1 --force-update --output "./ri" ./lib')
82 | end
83 |
84 |
85 | ###########
86 | # VERBOSE #
87 | ###########
88 |
89 | desc "Run tasks more verbosely"
90 | task :verbose do
91 | ENV["SPEC_OPTS"] = "--format documentation #{ENV["SPEC_OPTS"]}"
92 | end
93 |
94 |
95 | #########
96 | # CLEAN #
97 | #########
98 |
99 | require 'rake/clean'
100 | task(:clean) { puts "Cleaning out temporary generated files" }
101 | task(:clobber) { puts "Cleaning out final generated files" }
102 |
103 | CLOBBER.include("ri")
104 |
105 |
106 | ###########
107 | # INSTALL #
108 | ###########
109 |
110 | task :install do |task|
111 | sitelibdir = (ENV["RUBYLIBDIR"] or CONFIG["sitelibdir"])
112 |
113 | puts "Installing to #{sitelibdir}"
114 |
115 | files = FileList.new do |fl|
116 | fl.include("lib/**/*.rb")
117 | end
118 |
119 | files.each do |f|
120 | dir = File.join(sitelibdir, File.dirname(f).sub('lib',''), "")
121 | mkdir_p dir
122 | cp f, dir
123 | end
124 | end
125 |
126 |
127 |
128 | #########
129 | # SPECS #
130 | #########
131 |
132 | begin
133 | require 'rspec/core/rake_task'
134 |
135 | rspec_opts = '-r spec/spec_helper.rb'
136 |
137 | desc "Run all specs"
138 | RSpec::Core::RakeTask.new do |t|
139 | ENV["RUBYGAME_NEWRECT"] = "true"
140 | t.pattern = 'spec/*_spec.rb'
141 | t.rspec_opts = rspec_opts
142 | end
143 |
144 |
145 | namespace :spec do
146 | desc "Run all specs"
147 | RSpec::Core::RakeTask.new(:all) do |t|
148 | ENV["RUBYGAME_NEWRECT"] = "true"
149 | t.pattern = 'spec/*_spec.rb'
150 | t.rspec_opts = rspec_opts
151 | end
152 |
153 | desc "Run spec/[name]_spec.rb (e.g. 'color')"
154 | task :name do
155 | puts( "This is just a stand-in spec.",
156 | "Run rake spec:[name] where [name] is e.g. 'color', 'music'." )
157 | end
158 |
159 | desc "Run specific examples from spec/[name]_spec.rb"
160 | task "name:\"example\"" do
161 | puts( "This is just a stand-in spec.",
162 | "Run rake spec:[name]:\"[example]\" where [name] is e.g."+
163 | "'color', and [example] is a pattern matching an example." )
164 | end
165 | end
166 |
167 |
168 | rule(/spec:.+/) do |t|
169 |
170 | # Matches e.g. 'spec:foo' and 'spec:foo:"Example pattern"'
171 | spec_regexp = /spec:([^:]+)(?::(.+))?/
172 |
173 | match = t.name.match(spec_regexp)
174 |
175 | unless match
176 | puts "Invalid spec task: #{t.name}"
177 | exit 1
178 | end
179 |
180 | name = match[1]
181 | example = match[2] # optional
182 |
183 | pattern = File.join('spec', '%s_spec.rb'%name)
184 | path = File.join( File.dirname(__FILE__), pattern )
185 |
186 | if File.exist? path
187 | RSpec::Core::RakeTask.new(name) do |t|
188 | t.pattern = pattern
189 | t.rspec_opts = rspec_opts
190 | if example
191 | t.rspec_opts += " -e #{example.inspect}"
192 | end
193 | end
194 |
195 | puts "\nRunning %s"%pattern
196 |
197 | Rake::Task[name].invoke
198 | else
199 | puts "File does not exist: %s"%pattern
200 | end
201 |
202 | end
203 |
204 |
205 | ########
206 | # RCOV #
207 | ########
208 |
209 | desc "Run all specs with rcov"
210 | RSpec::Core::RakeTask.new(:rcov) do |t|
211 | ENV["RUBYGAME_NEWRECT"] = "true"
212 | t.pattern = 'spec/*_spec.rb'
213 | t.rcov = true
214 | t.rspec_opts = rspec_opts
215 | end
216 |
217 |
218 | namespace :rcov do
219 | desc "Run all specs with rcov"
220 | RSpec::Core::RakeTask.new(:all) do |t|
221 | ENV["RUBYGAME_NEWRECT"] = "true"
222 | t.pattern = 'spec/*_spec.rb'
223 | t.rcov = true
224 | t.rspec_opts = rspec_opts
225 | end
226 |
227 | desc "Run spec/[name]_spec.rb (e.g. 'color') with rcov"
228 | task :name do
229 | puts( "This is just a stand-in spec.",
230 | "Run rake rcov:[name] where [name] is e.g. 'color', 'music'." )
231 | end
232 | end
233 |
234 |
235 | rule(/rcov:.+/) do |t|
236 | name = t.name.gsub("rcov:","")
237 |
238 | pattern = File.join('spec', '%s_spec.rb'%name)
239 | path = File.join( pattern )
240 |
241 | if File.exist? path
242 | RSpec::Core::RakeTask.new(name) do |t|
243 | t.pattern = pattern
244 | t.rcov = true
245 | t.rspec_opts = rspec_opts
246 | end
247 |
248 | puts "\nRunning %s"%pattern
249 |
250 | Rake::Task[name].invoke
251 | else
252 | puts "File does not exist: %s"%pattern
253 | end
254 |
255 | end
256 |
257 | rescue LoadError
258 |
259 | error = "ERROR: rspec >= 2.0 is not installed?"
260 |
261 | task :spec do
262 | puts error
263 | end
264 |
265 | rule( /spec:.*/ ) do
266 | puts error
267 | end
268 |
269 | task :rcov do
270 | puts error
271 | end
272 |
273 | rule( /rcov:.*/ ) do
274 | puts error
275 | end
276 |
277 | end
278 |
--------------------------------------------------------------------------------
/doc/custom_sdl_load_paths.rdoc:
--------------------------------------------------------------------------------
1 | = Custom SDL Load Paths
2 |
3 | In Rubygame 2.6 and later, you can tell Rubygame to look in custom
4 | locations to find the SDL libraries (e.g. DLL files). This is mostly
5 | intended for when you are packaging your application in a stand-alone
6 | package (e.g. with RubyScript2Exe), and want to distribute the SDL
7 | libraries with your application, so that users do not need to install
8 | SDL.
9 |
10 | == Setting Load Paths
11 |
12 | Setting custom load paths is easy: just set the SDL_PATHS constant
13 | to an Array of directories before you do `require "rubygame"`.
14 | Note: You really must set SDL_PATHS *before* loading Rubygame!
15 |
16 | Rubygame will look first in the paths in SDL_PATHS, in the order they
17 | are given in the array. If Rubygame can't find a SDL library in any of
18 | the SDL_PATHS directories, Rubygame will then search for the library
19 | in some common library paths for the current operating system (e.g.
20 | "C:\windows\system32\" on Windows, "/usr/lib/" on Linux, etc.).
21 |
22 | For example, if the SDL libraries are in "mygame/libs/", and your
23 | main script is "mygame/mygame.rb", you could do the following in
24 | "mygame/mygame.rb":
25 |
26 | main_dir = File.dirname(__FILE__)
27 | SDL_PATHS = [ File.join( main_dir, "libs" ) ]
28 |
29 | require "rubygame"
30 |
31 | # ... the rest of your code ...
32 |
33 | == Per-OS Load Paths
34 |
35 | If you prefer to split the libraries into a separate directory for
36 | each operating system, you can set SDL_PATHS to a Hash instead. For
37 | example:
38 |
39 | main_dir = File.dirname(__FILE__)
40 | SDL_PATHS = {
41 | /linux/ => File.join( main_dir, "libs", "linux" ),
42 | /bsd/ => File.join( main_dir, "libs", "bsd" ),
43 | /darwin/ => File.join( main_dir, "libs", "mac" ),
44 | /windows/ => File.join( main_dir, "libs", "windows" ),
45 | }
46 |
47 | require "rubygame"
48 |
49 | # ... the rest of your code ...
50 |
51 | Each key in the hash should be a Regexp that matches an OS name. As of
52 | this writing (October 2009), the list of recognized OS names is:
53 |
54 | * "darwin" (MacOS X)
55 | * "freebsd"
56 | * "linux"
57 | * "openbsd"
58 | * "solaris"
59 | * "windows"
60 |
61 | == Library File Names
62 |
63 | Rubygame has certain expectations about the names of library files for
64 | each operating system ("[NAME]" is replaced with e.g. "SDL"):
65 |
66 | 'Nix:: lib[NAME].so
67 | Mac:: lib[NAME].dylib or [NAME].framework/[NAME]
68 | Windows:: [NAME].dll
69 |
70 | The specific libraries used by Rubygame are:
71 |
72 | SDL:: libSDL.so; libSDL.dylib or SDL.framework/SDL; SDL.dll
73 | SDL_gfx:: libSDL_gfx.so; libSDL_gfx.dylib or SDL_gfx.framework/SDL_gfx; SDL_gfx.dll
74 | SDL_image:: libSDL_image.so; libSDL_image.dylib or SDL_image.framework/SDL_image; SDL_image.dll
75 | SDL_mixer:: libSDL_mixer.so; libSDL_mixer.dylib or SDL_mixer.framework/SDL_mixer; SDL_mixer.dll
76 | SDL_ttf:: libSDL_ttf.so; libSDL_ttf.dylib or SDL_ttf.framework/SDL_ttf; SDL_ttf.dll
77 |
78 | SDL is absolutely required. The others are optional, but strongly
79 | recommended, because they provide a lot of extra functionality.
80 |
--------------------------------------------------------------------------------
/doc/getting_started.rdoc:
--------------------------------------------------------------------------------
1 | = Getting Started with Rubygame
2 |
3 | This guide is also available on the Rubygame wiki:
4 |
5 | * http://rubygame.org/wiki/Getting_started
6 |
7 | == About Rubygame
8 |
9 | Rubygame is a cross-platform game-development library for Ruby,
10 | inspired by Pygame. Rubygame strives to empower game developers by
11 | providing them with powerful and flexible mid-to-high level tools.
12 | Instead of worrying about low-level technical details, you can focus
13 | your energy on more interesting things (like making a fun game).
14 |
15 | == Installing Rubygame
16 |
17 | Installation guides for Mac and Windows are available in the 'doc'
18 | directory:
19 |
20 | Mac:: {doc/macosx_install.rdoc}[link:doc/macosx_install.rdoc]
21 | Windows:: {doc/windows_install.rdoc}[link:doc/windows_install.rdoc]
22 |
23 | You can also find installation instructions for many operating systems
24 | online at the Rubygame wiki:
25 |
26 | * http://rubygame.org/wiki/Installation_Instructions
27 |
28 | == Guides and tutorials
29 |
30 | The Rubygame wiki has a list of guides and tutorials to help you get
31 | started using Rubygame:
32 |
33 | * http://rubygame.org/wiki/Guides_and_tutorials
34 |
35 | == Suggested order of reading
36 |
37 | To get acquainted with Rubygame, we recommend exploring the available classes
38 | and modules in this order.
39 |
40 | First, take a look at the most fundamental classes:
41 |
42 | Rubygame::Surface:: An image canvas that you can load from an image
43 | file, draw shapes on and "blit" (copy) to other
44 | Surfaces (or the Screen).
45 | Rubygame::Screen:: A special Surface that is displayed to the user.
46 | Everything drawn on the Screen appears in the
47 | application window on the user's desktop.
48 | Rubygame::Rect:: A rectangular area, used for choosing what parts
49 | of a Surface to copy from or to, among other uses.
50 |
51 | As a next step, read about the EventQueue, EventHandler, and the user
52 | input event classes. These allow you to handle keyboard, mouse, and
53 | joystick input from the user, among other things. By creating your own
54 | event classes, these systems can also be used to represent things
55 | occuring within your game, such as the player losing a life or the
56 | level being completed.
57 |
58 | Rubygame::EventQueue:: A special Array that caches events to be
59 | handled later.
60 | Rubygame::EventHandler:: A flexible hook-based system for performing
61 | actions when certain types of events occur.
62 | Rubygame::Events:: A module containing all the built-in event
63 | classes in Rubygame.
64 |
65 | Finally, you may be interested in these features:
66 |
67 | Rubygame::Sprites:: A simple and flexible game object framework.
68 | Rubygame::Sound:: Play sound effects to make your game more lively.
69 | Rubygame::Music:: Play music to enhance your game's mood.
70 | Rubygame::Clock:: Monitor and control framerate to lower CPU use.
71 | Rubygame::TTF:: Render text with TrueType fonts.
72 | Rubygame::SFont:: Render text with bitmap-based fonts.
73 | Rubygame::GL:: Enable OpenGL 2D & 3D graphics.
74 |
75 | There are several sample applications in the 'samples' directory
76 | packaged with Rubygame which can also help you get started.
77 |
--------------------------------------------------------------------------------
/doc/keyboard_symbols.rdoc:
--------------------------------------------------------------------------------
1 | This is a list of every possible key that a keyboard event can have in
2 | Rubygame. You can view this list in a nicer form at
3 | http://rubygame.org/wiki/Keyboard_Symbols .
4 |
5 | The names on the left represent constants in the Rubygame module, e.g.
6 | Rubygame::K_BACKSPACE. These were used in the legacy (before Rubygame
7 | 2.4) event classes: Rubygame::KeyDownEvent and Rubygame::KeyUpEvent.
8 |
9 | The legacy event classes are deprecated and will be removed in
10 | Rubygame 3.0, so you should not use them.
11 |
12 | The symbols on the right are used in the new event classes:
13 | Rubygame::Events::KeyPressed and Rubygame::Events::KeyReleased.
14 |
15 | K_BACKSPACE :backspace
16 | K_TAB :tab
17 | K_CLEAR :clear
18 | K_RETURN :return
19 | K_PAUSE :pause
20 | K_ESCAPE :escape
21 | K_SPACE :space
22 | K_EXCLAIM :exclamation_mark
23 | K_QUOTEDBL :double_quote
24 | K_HASH :hash
25 | K_DOLLAR :dollar
26 | K_AMPERSAND :ampersand
27 | K_QUOTE :quote
28 | K_LEFTPAREN :left_parenthesis
29 | K_RIGHTPAREN :right_parenthesis
30 | K_ASTERISK :asterisk
31 | K_PLUS :plus
32 | K_COMMA :comma
33 | K_MINUS :minus
34 | K_PERIOD :period
35 | K_SLASH :slash
36 | K_0 :number_0
37 | K_1 :number_1
38 | K_2 :number_2
39 | K_3 :number_3
40 | K_4 :number_4
41 | K_5 :number_5
42 | K_6 :number_6
43 | K_7 :number_7
44 | K_8 :number_8
45 | K_9 :number_9
46 | K_COLON :":" (will become :colon in Rubygame 3.0)
47 | K_SEMICOLON :semicolon
48 | K_LESS :less_than
49 | K_EQUALS :equals
50 | K_GREATER :greater_than
51 | K_QUESTION :question_mark
52 | K_AT :at
53 | K_LEFTBRACKET :left_bracket
54 | K_BACKSLASH :backslash
55 | K_RIGHTBRACKET :right_bracket
56 | K_CARET :caret
57 | K_UNDERSCORE :underscore
58 | K_BACKQUOTE :backquote
59 | K_A :a
60 | K_B :b
61 | K_C :c
62 | K_D :d
63 | K_E :e
64 | K_F :f
65 | K_G :g
66 | K_H :h
67 | K_I :i
68 | K_J :j
69 | K_K :k
70 | K_L :l
71 | K_M :m
72 | K_N :n
73 | K_O :o
74 | K_P :p
75 | K_Q :q
76 | K_R :r
77 | K_S :s
78 | K_T :t
79 | K_U :u
80 | K_V :v
81 | K_W :w
82 | K_X :x
83 | K_Y :y
84 | K_Z :z
85 | K_DELETE :delete
86 | K_WORLD_0 :world_0
87 | K_WORLD_1 :world_1
88 | K_WORLD_2 :world_2
89 | K_WORLD_3 :world_3
90 | K_WORLD_4 :world_4
91 | K_WORLD_5 :world_5
92 | K_WORLD_6 :world_6
93 | K_WORLD_7 :world_7
94 | K_WORLD_8 :world_8
95 | K_WORLD_9 :world_9
96 | K_WORLD_10 :world_10
97 | K_WORLD_11 :world_11
98 | K_WORLD_12 :world_12
99 | K_WORLD_13 :world_13
100 | K_WORLD_14 :world_14
101 | K_WORLD_15 :world_15
102 | K_WORLD_16 :world_16
103 | K_WORLD_17 :world_17
104 | K_WORLD_18 :world_18
105 | K_WORLD_19 :world_19
106 | K_WORLD_20 :world_20
107 | K_WORLD_21 :world_21
108 | K_WORLD_22 :world_22
109 | K_WORLD_23 :world_23
110 | K_WORLD_24 :world_24
111 | K_WORLD_25 :world_25
112 | K_WORLD_26 :world_26
113 | K_WORLD_27 :world_27
114 | K_WORLD_28 :world_28
115 | K_WORLD_29 :world_29
116 | K_WORLD_30 :world_30
117 | K_WORLD_31 :world_31
118 | K_WORLD_32 :world_32
119 | K_WORLD_33 :world_33
120 | K_WORLD_34 :world_34
121 | K_WORLD_35 :world_35
122 | K_WORLD_36 :world_36
123 | K_WORLD_37 :world_37
124 | K_WORLD_38 :world_38
125 | K_WORLD_39 :world_39
126 | K_WORLD_40 :world_40
127 | K_WORLD_41 :world_41
128 | K_WORLD_42 :world_42
129 | K_WORLD_43 :world_43
130 | K_WORLD_44 :world_44
131 | K_WORLD_45 :world_45
132 | K_WORLD_46 :world_46
133 | K_WORLD_47 :world_47
134 | K_WORLD_48 :world_48
135 | K_WORLD_49 :world_49
136 | K_WORLD_50 :world_50
137 | K_WORLD_51 :world_51
138 | K_WORLD_52 :world_52
139 | K_WORLD_53 :world_53
140 | K_WORLD_54 :world_54
141 | K_WORLD_55 :world_55
142 | K_WORLD_56 :world_56
143 | K_WORLD_57 :world_57
144 | K_WORLD_58 :world_58
145 | K_WORLD_59 :world_59
146 | K_WORLD_60 :world_60
147 | K_WORLD_61 :world_61
148 | K_WORLD_62 :world_62
149 | K_WORLD_63 :world_63
150 | K_WORLD_64 :world_64
151 | K_WORLD_65 :world_65
152 | K_WORLD_66 :world_66
153 | K_WORLD_67 :world_67
154 | K_WORLD_68 :world_68
155 | K_WORLD_69 :world_69
156 | K_WORLD_70 :world_70
157 | K_WORLD_71 :world_71
158 | K_WORLD_72 :world_72
159 | K_WORLD_73 :world_73
160 | K_WORLD_74 :world_74
161 | K_WORLD_75 :world_75
162 | K_WORLD_76 :world_76
163 | K_WORLD_77 :world_77
164 | K_WORLD_78 :world_78
165 | K_WORLD_79 :world_79
166 | K_WORLD_80 :world_80
167 | K_WORLD_81 :world_81
168 | K_WORLD_82 :world_82
169 | K_WORLD_83 :world_83
170 | K_WORLD_84 :world_84
171 | K_WORLD_85 :world_85
172 | K_WORLD_86 :world_86
173 | K_WORLD_87 :world_87
174 | K_WORLD_88 :world_88
175 | K_WORLD_89 :world_89
176 | K_WORLD_90 :world_90
177 | K_WORLD_91 :world_91
178 | K_WORLD_92 :world_92
179 | K_WORLD_93 :world_93
180 | K_WORLD_94 :world_94
181 | K_WORLD_95 :world_95
182 | K_KP0 :keypad_0
183 | K_KP1 :keypad_1
184 | K_KP2 :keypad_2
185 | K_KP3 :keypad_3
186 | K_KP4 :keypad_4
187 | K_KP5 :keypad_5
188 | K_KP6 :keypad_6
189 | K_KP7 :keypad_7
190 | K_KP8 :keypad_8
191 | K_KP9 :keypad_9
192 | K_KP_PERIOD :keypad_period
193 | K_KP_DIVIDE :keypad_divide
194 | K_KP_MULTIPLY :keypad_multiply
195 | K_KP_MINUS :keypad_minus
196 | K_KP_PLUS :keypad_plus
197 | K_KP_ENTER :keypad_enter
198 | K_KP_EQUALS :keypad_equals
199 | K_UP :up
200 | K_DOWN :down
201 | K_RIGHT :right
202 | K_LEFT :left
203 | K_INSERT :insert
204 | K_HOME :home
205 | K_END :end
206 | K_PAGEUP :page_up
207 | K_PAGEDOWN :page_down
208 | K_F1 :f1
209 | K_F2 :f2
210 | K_F3 :f3
211 | K_F4 :f4
212 | K_F5 :f5
213 | K_F6 :f6
214 | K_F7 :f7
215 | K_F8 :f8
216 | K_F9 :f9
217 | K_F10 :f10
218 | K_F11 :f11
219 | K_F12 :f12
220 | K_F13 :f13
221 | K_F14 :f14
222 | K_F15 :f15
223 | K_NUMLOCK :numlock
224 | K_CAPSLOCK :caps_lock
225 | K_SCROLLOCK :scroll_lock
226 | K_RSHIFT :right_shift
227 | K_LSHIFT :left_shift
228 | K_RCTRL :right_ctrl
229 | K_LCTRL :left_ctrl
230 | K_RALT :right_alt
231 | K_LALT :left_alt
232 | K_RMETA :right_meta
233 | K_LMETA :left_meta
234 | K_LSUPER :left_super
235 | K_RSUPER :right_super
236 | K_MODE :alt_gr
237 | K_HELP :help
238 | K_PRINT :print_screen
239 | K_SYSREQ :sys_req
240 | K_BREAK :break
241 | K_MENU :menu
242 | K_POWER :power
243 | K_EURO :euro
244 |
--------------------------------------------------------------------------------
/doc/macosx_install.rdoc:
--------------------------------------------------------------------------------
1 | Note: You can view the latest version of this guide online at the
2 | Rubygame wiki: http://rubygame.org/wiki/Mac_Installation_Guide
3 |
4 | == Installing Xcode
5 |
6 | Rubygame does not need to be compiled anymore (since version 2.6),
7 | but you will need to install the Xcode development tools in order
8 | to install the dependencies with Fink or Darwinports, as well as
9 | to compile rsdl.
10 |
11 | You can find Xcode on your Mac OS X installation disc. Or, you can
12 | download Xcode online. You must register for a (free) Mac developer
13 | account for this.
14 |
15 | * Mac OS X 10.5 (Leopard) and 10.6 (Snow Leopard):
16 | {Xcode 3.1}[https://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=20414]
17 |
18 | * Mac OS X 10.3 (Panther) and 10.4 (Tiger):
19 | {Xcode 2.5}[http://connect.apple.com/cgi-bin/WebObjects/MemberSite.woa/wa/getSoftware?bundleID=19907]
20 |
21 | == Installing dependencies...
22 |
23 | You have two options for installing the software libraries that
24 | Rubygame depends on: Fink or Darwinports. Which option you choose is
25 | just a matter of preference.
26 |
27 | === ...with {Fink}[http://www.finkproject.org/]
28 |
29 | 1. {Install Fink}[http://www.finkproject.org/download/index.php?phpLang=en]
30 | and update to the latest version.
31 | 2. Open a new terminal (can be found in /Applications/Utilities).
32 | 3. Install SDL:
33 |
34 | sudo apt-get install sdl
35 |
36 | 4. (Optional, but *highly* recommended:) Install the SDL companion
37 | libraries:
38 |
39 | sudo apt-get install sdl-gfx13 sdl-image sdl-mixer sdl-ttf
40 |
41 | Thanks to Matt Crinklaw for these instructions.
42 |
43 | === ...with {Darwinports}[http://darwinports.com/]
44 |
45 | 1. {Install Darwinports}[http://darwinports.com/download/] (you must
46 | register first).
47 | 2. Open a new terminal (can be found in /Applications/Utilities).
48 | 3. Install SDL:
49 |
50 | sudo port install libsdl
51 |
52 | 4. (Optional, but *highly* recommended:) Install the SDL companion
53 | libraries:
54 |
55 | sudo port install libsdl_gfx libsdl_image libsdl_mixer libsdl_ttf
56 |
57 | Thanks to Raffael Mancini (sepisultrum) for these instructions.
58 |
59 | == Installing rsdl
60 |
61 | In order to use Rubygame applications on Mac OS X, you must use a special wrapper for the Ruby interpreter, called rsdl.
62 |
63 | 1. {Get rsdl}[http://github.com/knu/rsdl].
64 | 2. From within the rsdl directory:
65 |
66 | ruby ./configure.rb
67 | make
68 | sudo cp rsdl /usr/local/bin/
69 |
70 | == Installing Rubygame
71 |
72 | The simplest way to install Rubygame is: gem install rubygame
73 |
74 | Or you can {download the source
75 | from Github}[http://github.com/jacius/rubygame/] and follow the installation instructions in README.
76 |
77 | == Running an application
78 |
79 | If all went well, you can now run Rubygame applications like so:
80 |
81 | rsdl a_rubygame_app.rb
82 |
83 | If you have any trouble installing Rubygame, please post in the
84 | {forums}[http://rubygame.org/forums/].
85 |
--------------------------------------------------------------------------------
/doc/windows_install.rdoc:
--------------------------------------------------------------------------------
1 | Note: You can view the latest version of this guide online at the
2 | Rubygame wiki: http://rubygame.org/wiki/Windows_Installation_Guide
3 |
4 | == Gather Dependencies
5 |
6 | * {Ruby}[http://www.ruby-lang.org/en/downloads/], the language itself.
7 | The easiest option here is the one-click installer. This will
8 | install Ruby and a number of useful libraries without any hassle.
9 |
10 | * {SDL}[http://www.libsdl.org/download-1.2.php].
11 | Download the Win32 binary package, e.g. "SDL-1.2.14-win32.zip".
12 |
13 | The rest are optional dependencies, but highly recommended. If you
14 | don't have them, you won't be able to use certain features of
15 | Rubygame.
16 |
17 | * {SDL_image}[http://www.libsdl.org/projects/SDL_image/].
18 | Grab the Win32 binary package, e.g. "SDL_image-1.2.8-win32.zip".
19 |
20 | * {SDL_mixer}[http://www.libsdl.org/projects/SDL_mixer/].
21 | Just like before, grab the Win32 binary package, e.g.
22 | "SDL_mixer-1.2.9-win32.zip".
23 |
24 | * {SDL_ttf}[http://www.libsdl.org/projects/SDL_ttf/].
25 | Again, get the Win32 binary package, e.g. "SDL_ttf-2.0.9-win32.zip".
26 |
27 | * {SDL_gfx}[http://www.ferzkopp.net/joomla/content/view/19/14/]
28 | ({compiled version}[http://download.rubygame.org/files/extras/]).
29 | Many thanks to a generous Rubygame user (bmatthew1) for providing a
30 | compiled Windows DLL for SDL_gfx!
31 |
32 | Once you have downloaded everything, unzip them and copy the *.dll
33 | files into the C:\windows\system32\
directory. This will
34 | allow the libraries to be detected and loaded by Rubygame.
35 |
36 | == Install Rubygame
37 |
38 | The simplest way to install Rubygame is: gem install rubygame
39 |
40 | Or you can {download the source from
41 | Github}[http://github.com/jacius/rubygame/] and follow the
42 | installation instructions in README.
43 |
44 | == Conclusion
45 |
46 | If all goes well, you have successfully installed Rubygame. Try to
47 | execute require 'rubygame'
in an irb session and run the
48 | provided samples to ensure that everything is acceptable.
49 |
50 | If you have any trouble installing Rubygame, please post in the
51 | {forums}[http://rubygame.org/forums/].
52 |
--------------------------------------------------------------------------------
/lib/rubygame.rb:
--------------------------------------------------------------------------------
1 | #--
2 | #
3 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
4 | # Copyright (C) 2004-2009 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 |
23 | module Rubygame
24 |
25 | # These features are safe to autoload when needed.
26 | autoload :Clock, "rubygame/clock"
27 | autoload :Color, "rubygame/color"
28 | autoload :GL, "rubygame/gl"
29 | autoload :ImageFont, "rubygame/imagefont"
30 | autoload :Joystick, "rubygame/joystick"
31 | autoload :NamedResource, "rubygame/named_resource"
32 | autoload :EventQueue, "rubygame/queue"
33 | autoload :Sprites, "rubygame/sprite"
34 | autoload :Vector2, "rubygame/vector2"
35 |
36 |
37 | # These ones must be required at startup.
38 | # Note: rubygame/screen is intentionally loaded late.
39 | require "rubygame/main"
40 | require "rubygame/shared"
41 | require "rubygame/constants"
42 | require "rubygame/event"
43 | require "rubygame/events"
44 | require "rubygame/event_handler"
45 | require "rubygame/surface"
46 |
47 |
48 | # If RUBYGAME_NEWRECT is set, load the new Rect class. Otherwise load
49 | # the old Rect class, for backwards compatibility. The old Rect class
50 | # will be removed in Rubygame 3.0.
51 | if /^(1|t|true|y|yes)$/i =~ ENV["RUBYGAME_NEWRECT"]
52 | require "rubygame/new_rect"
53 | else
54 | require "rubygame/rect"
55 | end
56 |
57 |
58 | # SDL_gfx is optional, rescue if it fails.
59 | begin
60 | require "rubygame/gfx"
61 | rescue LoadError => e
62 | puts( "Warning: Could not load SDL_gfx! " +
63 | "Continuing anyway, but some Surface methods will be missing.\n" +
64 | "Error message was: #{e.message.inspect}" )
65 | end
66 |
67 |
68 | # SDL_image is optional, rescue if it fails.
69 | begin
70 | require "rubygame/image"
71 | rescue LoadError => e
72 | puts( "Warning: Could not load SDL_image! " +
73 | "Continuing anyway, but image loading will be missing.\n" +
74 | "Error message was: #{e.message.inspect}" )
75 | end
76 |
77 |
78 | # SDL_mixer is optional, rescue if it fails.
79 | begin
80 | require "rubygame/mixer"
81 | rescue LoadError => e
82 | puts( "Warning: Could not load SDL_mixer! " +
83 | "Continuing anyway, but audio features will be missing.\n" +
84 | "Error message was: #{e.message.inspect}" )
85 | end
86 |
87 |
88 | # SDL_ttf is optional, rescue if it fails.
89 | begin
90 | require "rubygame/ttf"
91 | rescue LoadError => e
92 | puts( "Warning: Could not load SDL_ttf! " +
93 | "Continuing anyway, but the TTF class will be missing.\n" +
94 | "Error message was: #{e.message.inspect}" )
95 | end
96 |
97 |
98 | # Loaded late so Screen can undefine some inherited Surface methods.
99 | require "rubygame/screen"
100 |
101 |
102 | # Handle initialization automatically unless the RUBYGAME_NOINIT
103 | # environmental variable is set to something truthy.
104 | unless /^(1|t|true|y|yes)$/i =~ ENV["RUBYGAME_NOINIT"]
105 | Rubygame.init
106 | at_exit { Rubygame.quit }
107 | end
108 |
109 | end
110 |
--------------------------------------------------------------------------------
/lib/rubygame/audio.rb:
--------------------------------------------------------------------------------
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 | module Rubygame
23 |
24 | # call-seq:
25 | # open_audio( options={:buffer=>1024, :channels=>2, :frequency=>22050} )
26 | #
27 | # Initializes the audio device using the given settings.
28 | #
29 | # NOTE: Audio will be automatically opened when Rubygame::Sound or
30 | # Rubygame::Music are first used. You only need to open audio
31 | # manually if you want settings different from the default, or if
32 | # you are using the older, deprecated Music and Sample classes from
33 | # the Rubygame::Mixer module.
34 | #
35 | # If audio is already open, this method has no effect, and returns false.
36 | # If you want to change audio settings, you must #close_audio() and
37 | # then open it again.
38 | #
39 | # options:: A Hash of any of the following options. (Hash, optional)
40 | #
41 | # :frequency:: output sample rate in audio samples per second
42 | # (Hz). Affects the quality of the sound output, at
43 | # the expense of CPU usage. If omitted, the default
44 | # (22050) is used. The default is recommended for
45 | # most games.
46 | #
47 | # :channels:: output sound channels. Use 2 for stereo, 1 for mono.
48 | # If omitted, the default (2) is used.
49 | #
50 | # :buffer:: size of the sound buffer, in bytes. Must be a
51 | # power of 2 (e.g. 512, 1024, 2048). If omitted,
52 | # the default (1024) is used. If your game is
53 | # fast-paced, you may want to use a smaller value
54 | # to reduce audio delay, the time between when you
55 | # play a sound and when it is heard.
56 | #
57 | # Returns:: true if the audio was newly opened by this action, or
58 | # false if it was already open before this action.
59 | #
60 | # May raise:: SDLError, if initialization fails.
61 | # ArgumentError, if an invalid value is given for any option.
62 | #
63 | def self.open_audio( options={} )
64 | return false if audio_open?
65 |
66 | unless options.kind_of? Hash
67 | raise TypeError, "invalid options Hash: #{options.inspect}"
68 | end
69 |
70 | buff = (options[:buffer] or 1024)
71 | chan = (options[:channels] or 2)
72 | freq = (options[:frequency] or SDL::Mixer::DEFAULT_FREQUENCY)
73 |
74 | # In general, format should always be the default.
75 | frmt = SDL::Mixer::DEFAULT_FORMAT
76 |
77 |
78 | buff = if( buff <= 0 )
79 | raise ArgumentError, "buffer size must be positive (got #{buff})"
80 | elsif( buff & (buff - 1) != 0 )
81 | raise( ArgumentError, "buffer size must be a power of 2 "+
82 | "(e.g. 512, 1024) (got #{buff})" )
83 | else
84 | buff.to_i
85 | end
86 |
87 |
88 | chan = if( chan != 1 && chan != 2 )
89 | raise( ArgumentError,
90 | "channels must be 1 (mono) or 2 (stereo) (got #{chan})" )
91 | else
92 | chan.to_i
93 | end
94 |
95 |
96 | freq = if( freq <= 0 )
97 | raise ArgumentError, "frequency must be positive (got #{freq})"
98 | else
99 | freq.to_i
100 | end
101 |
102 | result = SDL::Mixer.OpenAudio(freq, frmt, chan, buff)
103 |
104 | if( result < 0 )
105 | raise Rubygame::SDLError, "Could not open audio: #{SDL.GetError()}"
106 | end
107 |
108 | return true
109 | end
110 |
111 |
112 |
113 | # Deinitializes and closes the audio device. If audio was not open,
114 | # this method does nothing, and returns false. See also #open_audio().
115 | #
116 | # NOTE: The audio will be automatically closed when the program
117 | # exits. You only need to close audio manually if you want to
118 | # call #open_audio with different settings.
119 | #
120 | # Returns:: true if the audio was open before this action.
121 | #
122 | def self.close_audio
123 | if audio_open?
124 | SDL::Mixer.CloseAudio()
125 | return true
126 | else
127 | return false
128 | end
129 | end
130 |
131 |
132 | def self.audio_open? # :nodoc:
133 | SDL::Mixer.QuerySpec(nil,nil,nil) > 0
134 | end
135 |
136 |
137 | # Returns the name of the audio driver that SDL is using.
138 | # This method opens the audio device if it is not open already.
139 | #
140 | # May raise an SDLError if the audio device could not be opened.
141 | #
142 | def self.audio_driver
143 | open_audio
144 | return SDL.AudioDriverName
145 | end
146 |
147 | end
148 |
--------------------------------------------------------------------------------
/lib/rubygame/color.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | require "rubygame/color/models/base"
22 | require "rubygame/color/models/rgb"
23 | require "rubygame/color/models/rgb255"
24 | require "rubygame/color/models/hsv"
25 | require "rubygame/color/models/hsl"
26 |
27 | require "rubygame/color/palettes/palette"
28 | require "rubygame/color/palettes/x11"
29 | require "rubygame/color/palettes/css"
30 |
31 |
32 | module Rubygame
33 |
34 | # The Color module contains classes related to colors.
35 | #
36 | # Available color representations:
37 | #
38 | # ColorRGB:: color class with red, green, and blue components.
39 | # ColorHSV:: color class with hue, saturation, and value components.
40 | # ColorHSL:: color class with hue, saturation, and luminosity components.
41 | #
42 | # The Palette class allows you to conveniently store and access a
43 | # collection of many different colors, with inheritance from
44 | # included Palettes.
45 | #
46 | # The available predefined palettes are:
47 | #
48 | # X11:: palette with the default X11 colors
49 | # CSS:: palette used with HTML and CSS, very similar to X11
50 | # GLOBAL:: special palette used for automatic lookup (see below)
51 | #
52 | # The GLOBAL palette is special; it is used for automatic color lookup
53 | # in functions like Surface#draw_circle and TTF#render.It includes the
54 | # CSS palette by default; you can include other palettes or define new
55 | # custom colors in GLOBAL to make them available for automatic lookup.
56 | #
57 | # For convenience, you can access the GLOBAL palette through the
58 | # #[] and #[]= methods:
59 | #
60 | # include Rubygame
61 | # player_color = Color[:red]
62 | # Color[:favorite] = Color[:azure]
63 | #
64 | module Color
65 |
66 | (GLOBAL = Palette.new()).include(CSS) # :nodoc:
67 |
68 | # Retrieve a color from the GLOBAL palette.
69 | # See Palette#[]
70 | def self.[]( name )
71 | GLOBAL[name]
72 | end
73 |
74 | # Store a color in the GLOBAL palette.
75 | # See Palette#[]=
76 | def self.[]=( name, color )
77 | GLOBAL[name] = color
78 | end
79 |
80 |
81 | # Same as Rubygame::Color::ColorRGB.new.
82 | def self.rgb( color )
83 | Rubygame::Color::ColorRGB.new( color )
84 | end
85 |
86 | # Same as Rubygame::Color::ColorRGB255.new.
87 | def self.rgb255( color )
88 | Rubygame::Color::ColorRGB255.new( color )
89 | end
90 |
91 | # Same as Rubygame::Color::ColorRGB255.hex.
92 | def self.hex( string )
93 | Rubygame::Color::ColorRGB255.hex( string )
94 | end
95 |
96 | # Same as Rubygame::Color::ColorHSV.new.
97 | def self.hsv( color )
98 | Rubygame::Color::ColorHSV.new( color )
99 | end
100 |
101 | # Same as Rubygame::Color::ColorHSL.new.
102 | def self.hsl( color )
103 | Rubygame::Color::ColorHSL.new( color )
104 | end
105 |
106 |
107 | # For use by Rubygame methods only:
108 |
109 | # Convert a color name (string or symbol), hex color string, Color
110 | # instance, or Array to a color array. Color names take precedence
111 | # over hex color strings.
112 | def self.convert_color( color ) # :nodoc:
113 | color =
114 | if color.kind_of?(String)
115 | begin
116 | Rubygame::Color[color].to_sdl_rgba_ary
117 | rescue IndexError => e
118 | # Match 3, 4, 6, or 8-digit hex color. "#" is required.
119 | if /\#([0-9a-f]{3}|[0-9a-f]{4}|
120 | [0-9a-f]{6}|[0-9a-f]{8})/ix =~ color
121 | Rubygame::Color::ColorRGB255.hex(color).to_sdl_rgba_ary
122 | else
123 | raise e
124 | end
125 | end
126 | elsif color.kind_of?(Symbol)
127 | Rubygame::Color[color].to_sdl_rgba_ary
128 | elsif color.respond_to? :to_sdl_rgba_ary
129 | color.to_sdl_rgba_ary
130 | elsif color.respond_to? :to_ary
131 | color.to_ary
132 | else
133 | raise TypeError, "unsupported type #{color.class} for color"
134 | end
135 |
136 | unless color.size.between?(3,4) and color.all?{|n| n.kind_of? Numeric}
137 | raise TypeError, "invalid color: #{color.inspect}"
138 | end
139 |
140 | return color
141 | end
142 |
143 | def self.make_sdl_rgba( color ) # :nodoc:
144 | @rgba_cache ||= {}
145 | @rgba_cache[color] ||=
146 | begin
147 | r,g,b,a = convert_color(color).collect!{ |c| c.to_i }[0,4]
148 | a ||= 255
149 | [r,g,b,a].freeze
150 | end
151 | end
152 |
153 |
154 | def self.remove_from_cache( color_name )
155 | @rgba_cache ||= {}
156 | @rgba_cache.delete( color_name )
157 | end
158 |
159 | end
160 | end
161 |
162 |
--------------------------------------------------------------------------------
/lib/rubygame/color/models/base.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | module Rubygame
21 | module Color
22 |
23 | # A mix-in module defining methods shared by all Color classes.
24 | module ColorBase
25 |
26 | # Class methods shared by all Color classes.
27 | module ClassMethods
28 |
29 | # Returns the class basename. E.g. the basename of
30 | # Rubygame::Color::ColorRGB is "ColorRGB".
31 | def basename
32 | n = name
33 | i = n.rindex(':')
34 | i ? n[i+1, n.length] : n
35 | end
36 |
37 | # Creates a new instance from an RGBA array of integers
38 | # ranging from 0 to 255.
39 | def new_from_sdl_rgba( rgba )
40 | new_from_rgba( rgba.collect { |i| i / 255.0 } )
41 | end
42 |
43 | end
44 |
45 | def self.included( other )
46 | class << other; include ClassMethods; end
47 | end
48 |
49 |
50 | # Override this in the class
51 | def to_ary # :nodoc:
52 | raise "Cannot convert #{self.class.basename} to array"
53 | end
54 | def to_a # :nodoc:
55 | to_ary
56 | end
57 |
58 |
59 | # Override this in the class
60 | def to_rgba_ary # :nodoc:
61 | raise "Cannot convert #{self.class.basename} to RGBA"
62 | end
63 |
64 | # Converts the color to an RGBA array of integers
65 | # ranging from 0 to 255, like SDL uses.
66 | def to_sdl_rgba_ary
67 | self.to_rgba_ary.collect { |i| clamp(i*255, 0, 255).round }
68 | end
69 |
70 |
71 | # Returns a new Rubygame::Color::ColorRGB matching this color.
72 | def to_rgb
73 | Rubygame::Color::ColorRGB.new(self)
74 | end
75 |
76 | # Returns a new Rubygame::Color::ColorRGB255 matching this color.
77 | # (Note: ColorRGB255 stores each component as an integer ranging
78 | # from 0 to 255, which may cause precision loss.)
79 | #
80 | def to_rgb255
81 | Rubygame::Color::ColorRGB255.new(self)
82 | end
83 |
84 | # Returns a new Rubygame::Color::ColorHSL matching this color.
85 | def to_hsl
86 | Rubygame::Color::ColorHSL.new(self)
87 | end
88 |
89 | # Returns a new Rubygame::Color::ColorHSV matching this color.
90 | def to_hsv
91 | Rubygame::Color::ColorHSV.new(self)
92 | end
93 |
94 |
95 | def to_s # :nodoc:
96 | "#<%s %s>"%[self.class.basename, to_ary.inspect]
97 | end
98 |
99 | def inspect # :nodoc:
100 | "#<%s:%#.x %s>"%[self.class.basename, object_id, to_ary.inspect]
101 | end
102 |
103 |
104 | def hash # :nodoc:
105 | ary = to_ary
106 | @hash ||= ((ary.at(0).hash << 4) +
107 | (ary.at(1).hash << 3) +
108 | (ary.at(2).hash << 2) +
109 | (ary.at(3).hash << 1) +
110 | self.class.hash)
111 | end
112 |
113 |
114 | # True if other has the same class and components
115 | def eql?( other )
116 | self.hash == other.hash
117 | end
118 |
119 | def ==( other )
120 | return true if eql?(other)
121 | c2 = begin
122 | self.class.new(other).to_rgba_ary
123 | rescue ArgumentError
124 | return false
125 | end
126 | c1 = to_rgba_ary
127 | return c1.enum_for(:each_index).all? { |i|
128 | (c1.at(i) - c2.at(i)).abs < Float::EPSILON*2
129 | }
130 | end
131 |
132 |
133 | # Perform color addition with another color of any type.
134 | # The alpha of the new color will be equal to the alpha
135 | # of the receiver.
136 | def +(other)
137 | wrap( simple_op(other) { |a,b| a + b } )
138 | end
139 |
140 | # Perform color subtraction with another color of any type.
141 | # The alpha of the new color will be equal to the alpha
142 | # of the receiver.
143 | def -(other)
144 | wrap( simple_op(other) { |a,b| a - b } )
145 | end
146 |
147 | # Perform color multiplication with another color of any type.
148 | # The alpha of the new color will be equal to the alpha
149 | # of the receiver.
150 | def *(other)
151 | wrap( simple_op(other) { |a,b| a * b } )
152 | end
153 |
154 | # Perform color division with another color of any type.
155 | # The alpha of the new color will be equal to the alpha
156 | # of the receiver.
157 | def /(other)
158 | wrap( simple_op(other) { |a,b| (a == 0) ? 0.0 : (a / b.to_f) } )
159 | end
160 |
161 | # Layer this color over another color.
162 | def over(other)
163 | c1, c2 = self.to_rgba_ary, other.to_rgba_ary
164 | a1, a2 = c1[3], c2[3]
165 |
166 | rgba = [0,1,2].collect do |i|
167 | clamp( a1*c1.at(i) + a2*c2.at(i)*(1-a1) )
168 | end
169 |
170 | rgba << ( a1 + a2*(1-a1) )
171 |
172 | wrap( rgba )
173 | end
174 |
175 | # Average this color with another color. (Linear weighted average)
176 | #
177 | # A weight of 0.0 means 0% of this color, 100% of the other.
178 | # A weight of 1.0 means 100% of this color, 0% of the other.
179 | # A weight of 0.5 means 50% of each color.
180 | #
181 | def average(other, weight=0.5)
182 | c1, c2 = self.to_rgba_ary, other.to_rgba_ary
183 |
184 | rgba = [0,1,2,3].collect do |i|
185 | clamp( c1.at(i)*weight + c2.at(i)*(1-weight) )
186 | end
187 |
188 | wrap( rgba )
189 | end
190 |
191 |
192 | private
193 |
194 | def wrap( rgba )
195 | self.class.new_from_rgba( rgba )
196 | end
197 |
198 | def simple_op(other, &block)
199 | c1, c2 = self.to_rgba_ary, other.to_rgba_ary
200 | a1, a2 = c1[3], c2[3]
201 |
202 | rgba = [0,1,2].collect do |i|
203 | clamp( block.call( a1*c1.at(i), a2*c2.at(i) ) )
204 | end
205 |
206 | rgba << a1
207 |
208 | return rgba
209 | end
210 |
211 | def clamp(v, min=0.0, max=1.0)
212 | v = min if v < min
213 | v = max if v > max
214 | return v
215 | end
216 | end
217 |
218 | end
219 | end
220 |
--------------------------------------------------------------------------------
/lib/rubygame/color/models/hsl.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | module Rubygame
23 | module Color
24 |
25 | # Represents color in the HSL (Hue, Saturation, Luminosity) color space.
26 | class ColorHSL
27 | include ColorBase
28 |
29 | attr_reader :h, :s, :l, :a
30 |
31 | # call-seq:
32 | # new( [h,s,l,a] ) -> ColorHSL
33 | # new( [h,s,l] ) -> ColorHSL
34 | # new( color ) -> ColorHSL
35 | #
36 | # Create a new instance from an Array or an existing color
37 | # (of any type). If the alpha (opacity) component is omitted
38 | # from the array, full opacity will be used.
39 | #
40 | # All color components range from 0.0 to 1.0.
41 | #
42 | def initialize( color )
43 | if color.kind_of?(Array) and color.size >= 3
44 | @h, @s, @l, @a = color.collect { |i| i.to_f }
45 | @a = 1.0 unless @a
46 | elsif color.instance_of?(self.class)
47 | @h, @s, @l, @a = color.to_ary
48 | elsif color.respond_to?(:to_rgba_ary)
49 | @h, @s, @l, @a = self.class.rgba_to_hsla( *color.to_rgba_ary )
50 | else
51 | raise ArgumentError, "Invalid color: #{color.inspect}"
52 | end
53 |
54 | hash
55 | end
56 |
57 | # Returns the color as an RGBA array of floats ranging from 0.0 to 1.0.
58 | def to_rgba_ary
59 | return self.class.hsla_to_rgba( @h, @s, @l, @a )
60 | end
61 |
62 | # Returns the color as an HSLA array of floats ranging from 0.0
63 | # to 1.0.
64 | def to_ary
65 | [@h, @s, @l, @a]
66 | end
67 |
68 |
69 | class << self
70 |
71 | # Creates a new instance from an RGBA array of floats ranging
72 | # from 0.0 to 1.0.
73 | def new_from_rgba( rgba )
74 | new( rgba_to_hsla(*rgba) )
75 | end
76 |
77 | # Convert the red, green, blue, and alpha to the
78 | # equivalent hue, saturation, luminosity, and alpha.
79 | def rgba_to_hsla( r, g, b, a ) # :nodoc:
80 | rgb_arr = [r, g, b]
81 | max = rgb_arr.max
82 | min = rgb_arr.min
83 |
84 | # Calculate lightness.
85 | l = (max + min) / 2.0
86 |
87 | # Calculate saturation.
88 | if l == 0.0 or max == min
89 | s = 0
90 | elsif 0 < l and l <= 0.5
91 | s = (max - min) / (max + min)
92 | else # l > 0.5
93 | s = (max - min) / (2 - (max + min))
94 | end
95 |
96 | # Calculate hue.
97 | if min == max
98 | h = 0
99 | # Undefined in this case, but set it to zero
100 | elsif max == r and g >= b
101 | h = (1.quo(6) * (g - b) / (max - min)) + 0
102 | elsif max == r and g < b
103 | h = (1.quo(6) * (g - b) / (max - min)) + 1.0
104 | elsif max == g
105 | h = (1.quo(6) * (b - r) / (max - min)) + 1.quo(3)
106 | elsif max == b
107 | h = (1.quo(6) * (r - g) / (max - min)) + 2.quo(3)
108 | else
109 | raise "Should never happen"
110 | end
111 |
112 | return [h,s,l,a]
113 | end
114 |
115 | # Convert the hue, saturation, luminosity, and alpha
116 | # to the equivalent red, green, blue, and alpha.
117 | def hsla_to_rgba( h, s, l, a ) # :nodoc:
118 | # If the color is achromatic, return already with the
119 | # lightness value for all components
120 | if s == 0.0
121 | return [l, l, l, a]
122 | end
123 |
124 | # Otherwise, we have to do the long, hard calculation
125 |
126 | # q helper value
127 | q = (l < 0.5) ? (l * (1.0 + s)) : (l + s - l * s)
128 |
129 | # p helper value
130 | p = (2.0 * l) - q
131 |
132 | r = calculate_component( p, q, h + 1.quo(3) )
133 | g = calculate_component( p, q, h )
134 | b = calculate_component( p, q, h - 1.quo(3) )
135 |
136 | return [r,g,b,a]
137 | end
138 |
139 | private
140 |
141 | # Perform some arcane math to calculate a color component.
142 | def calculate_component(p, q, tc) # :nodoc:
143 | tc %= 1.0
144 | if tc < 1.quo(6)
145 | p + (q - p) * tc * 6.0
146 | elsif tc < 0.5
147 | q
148 | elsif tc < 2.quo(3)
149 | p + (q - p) * (2.quo(3) - tc) * 6.0
150 | else
151 | p
152 | end
153 | end
154 |
155 | end
156 |
157 | end
158 | end
159 | end
160 |
--------------------------------------------------------------------------------
/lib/rubygame/color/models/hsv.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | module Rubygame
23 | module Color
24 |
25 | # Represents color in the HSV (Hue, Saturation, Value) color space.
26 | class ColorHSV
27 | include ColorBase
28 |
29 | attr_reader :h, :s, :v, :a
30 |
31 | # call-seq:
32 | # new( [h,s,v,a] ) -> ColorHSV
33 | # new( [h,s,v] ) -> ColorHSV
34 | # new( color ) -> ColorHSV
35 | #
36 | # Create a new instance from an Array or an existing color
37 | # (of any type). If the alpha (opacity) component is omitted
38 | # from the array, full opacity will be used.
39 | #
40 | # All color components range from 0.0 to 1.0.
41 | #
42 | def initialize( color )
43 | if color.kind_of?(Array) and color.size >= 3
44 | @h, @s, @v, @a = color.collect { |i| i.to_f }
45 | @a = 1.0 unless @a
46 | elsif color.instance_of?(self.class)
47 | @h, @s, @v, @a = color.to_ary
48 | elsif color.respond_to?(:to_rgba_ary)
49 | @h, @s, @v, @a = self.class.rgba_to_hsva( *color.to_rgba_ary )
50 | else
51 | raise ArgumentError, "Invalid color: #{color.inspect}"
52 | end
53 |
54 | hash
55 | end
56 |
57 | # Returns the color as an RGBA array of floats ranging from 0.0
58 | # to 1.0.
59 | def to_rgba_ary
60 | return self.class.hsva_to_rgba( @h, @s, @v, @a )
61 | end
62 |
63 | # Returns the color as an HSVA array of floats ranging from 0.0
64 | # to 1.0.
65 | def to_ary
66 | [@h, @s, @v, @a]
67 | end
68 |
69 |
70 | class << self
71 |
72 | # Creates a new instance from an RGBA array of floats ranging
73 | # from 0.0 to 1.0.
74 | def new_from_rgba( rgba )
75 | new( rgba_to_hsva(*rgba) )
76 | end
77 |
78 | # Convert the red, green, blue, and alpha to the
79 | # equivalent hue, saturation, value, and alpha.
80 | def rgba_to_hsva( r, g, b, a ) # :nodoc:
81 | rgb_arr = [r, g, b]
82 | max = rgb_arr.max
83 | min = rgb_arr.min
84 |
85 | # Calculate hue.
86 | if min == max
87 | h = 0
88 | # Undefined in this case, but set it to zero
89 | elsif max == r and g >= b
90 | h = (1.quo(6) * (g - b) / (max - min)) + 0
91 | elsif max == r and g < b
92 | h = (1.quo(6) * (g - b) / (max - min)) + 1.0
93 | elsif max == g
94 | h = (1.quo(6) * (b - r) / (max - min)) + 1.quo(3)
95 | elsif max == b
96 | h = (1.quo(6) * (r - g) / (max - min)) + 2.quo(3)
97 | else
98 | raise "Should never happen"
99 | end
100 |
101 | # Calulate value.
102 | v = max
103 |
104 | # Calculate saturation.
105 | if max == 0.0
106 | s = 0.0
107 | else
108 | s = 1.0 - (min / max)
109 | end
110 |
111 | return [h,s,v,a]
112 | end
113 |
114 | # Convert the hue, saturation, value, and alpha
115 | # to the equivalent red, green, blue, and alpha.
116 | def hsva_to_rgba( h, s, v, a ) # :nodoc:
117 | # Determine what part of the "color hexagon" the hue is in.
118 | hi = (h * 6).floor % 6
119 |
120 | # Fractional part
121 | f = (h * 6) - hi
122 |
123 | # Helper values
124 | p = v * (1.0 - s)
125 | q = v * (1.0 - (f * s))
126 | t = v * (1.0 - ((1.0 - f) * s))
127 |
128 | # Finally calculate the rgb values
129 | r, g, b = calculate_rgb(hi, v, p, t, q)
130 |
131 | return [r, g, b, a]
132 | end
133 |
134 | private
135 |
136 | def calculate_rgb(hi, v, p, t, q) # :nodoc:
137 | case hi
138 | when 0
139 | return v, t, p
140 | when 1
141 | return q, v, p
142 | when 2
143 | return p, v, t
144 | when 3
145 | return p, q, v
146 | when 4
147 | return t, p, v
148 | when 5
149 | return v, p, q
150 | end
151 | end
152 | end
153 | end
154 | end
155 | end
156 |
--------------------------------------------------------------------------------
/lib/rubygame/color/models/rgb.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | module Rubygame
23 | module Color
24 |
25 | # Represents color in the RGB (Red, Green, Blue) color space,
26 | # with each color component as a float from 0.0 to 1.0.
27 | #
28 | # See also ColorRGB255, where components are integers from 0 to 255.
29 | #
30 | class ColorRGB
31 | include ColorBase
32 |
33 | attr_reader :r, :g, :b, :a
34 |
35 | # call-seq:
36 | # new( [r,g,b,a] ) -> ColorRGB
37 | # new( [r,g,b] ) -> ColorRGB
38 | # new( color ) -> ColorRGB
39 | #
40 | # Create a new instance from an Array or an existing color
41 | # (of any type). If the alpha (opacity) component is omitted
42 | # from the array, full opacity will be used.
43 | #
44 | # All color components range from 0.0 to 1.0.
45 | #
46 | def initialize( color )
47 | if color.kind_of?(Array) and color.size >= 3
48 | @r, @g, @b, @a = color.collect { |i| i.to_f }
49 | @a = 1.0 unless @a
50 | elsif color.instance_of?(self.class)
51 | @r, @g, @b, @a = color.to_ary
52 | elsif color.respond_to?(:to_rgba_ary)
53 | @r, @g, @b, @a = color.to_rgba_ary
54 | else
55 | raise ArgumentError, "Invalid color: #{color.inspect}"
56 | end
57 |
58 | hash
59 | end
60 |
61 | # Creates a new instance from an RGBA array of floats ranging
62 | # from 0.0 to 1.0.
63 | def self.new_from_rgba( rgba )
64 | new( rgba )
65 | end
66 |
67 | # Returns the color as an RGBA array of floats ranging from 0.0
68 | # to 1.0.
69 | def to_rgba_ary
70 | return [@r, @g, @b, @a]
71 | end
72 |
73 | # Same as #to_rgba_ary
74 | def to_ary
75 | return [@r, @g, @b, @a]
76 | end
77 |
78 | end
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/lib/rubygame/color/models/rgb255.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 2010 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 | module Rubygame
23 | module Color
24 |
25 | # Represents color in the RGB (Red, Green, Blue) color space,
26 | # with each color component as an integer from 0 to 255.
27 | #
28 | # See also ColorRGB, where components are floats from 0.0 to 1.0.
29 | #
30 | class ColorRGB255
31 | include ColorBase
32 |
33 | attr_reader :r, :g, :b, :a
34 |
35 | # call-seq:
36 | # new( [r,g,b,a] ) -> ColorRGB
37 | # new( [r,g,b] ) -> ColorRGB
38 | # new( color ) -> ColorRGB
39 | #
40 | # Create a new instance from an Array or an existing color
41 | # (of any type). If the alpha (opacity) component is omitted
42 | # from the array, full opacity will be used.
43 | #
44 | # All color components range from 0 to 255.
45 | #
46 | def initialize( color )
47 | if color.kind_of?(Array) and color.size >= 3
48 | @r, @g, @b, @a = color.collect { |i| i.round }
49 | @a = 255 unless @a
50 | elsif color.instance_of?(self.class)
51 | @r, @g, @b, @a = color.to_ary
52 | elsif color.respond_to?(:to_rgba_ary)
53 | @r, @g, @b, @a = color.to_sdl_rgba_ary
54 | else
55 | raise ArgumentError, "Invalid color: #{color.inspect}"
56 | end
57 |
58 | hash
59 | end
60 |
61 | # Creates a new instance from an RGBA array of floats ranging
62 | # from 0.0 to 1.0.
63 | def self.new_from_rgba( rgba )
64 | new( rgba.collect { |i| (i * 255).round } )
65 | end
66 |
67 | # Creates a new instance from an RGBA array of integers
68 | # ranging from 0 to 255.
69 | def self.new_from_sdl_rgba( rgba )
70 | new( rgba )
71 | end
72 |
73 | # Creates a new instance from a string containing an HTML/CSS
74 | # color string, i.e. "#RGB", "#RGBA", "#RRGGBB", or "#RRGGBBAA".
75 | # The leading "#" is optional.
76 | #
77 | # Example:
78 | #
79 | # include Rubygame::Color
80 | #
81 | # # 4 ways of specifying the same color:
82 | #
83 | # # "#RGB"
84 | # ColorRGB255.hex("#248")
85 | # # => #
86 | #
87 | # # "#RGBA"
88 | # ColorRGB255.hex("#248f")
89 | # # => #
90 | #
91 | # # "#RRGGBB"
92 | # ColorRGB255.hex("#224488")
93 | # # => #
94 | #
95 | # # "#RRGGBBAA"
96 | # ColorRGB255.hex("#224488ff")
97 | # # => #
98 | #
99 | def self.hex( color_str )
100 | case color_str
101 | when /^#?([0-9a-f]{8}$)/i
102 | r = $1[0,2].hex
103 | g = $1[2,2].hex
104 | b = $1[4,2].hex
105 | a = $1[6,2].hex
106 | new( [r, g, b, a] )
107 | when /^#?([0-9a-f]{6}$)/i
108 | r = $1[0,2].hex
109 | g = $1[2,2].hex
110 | b = $1[4,2].hex
111 | a = 255
112 | new( [r, g, b, a] )
113 | when /^#?([0-9a-f]{4})$/i
114 | # As with HTML/CSS, each hexdigit is repeated.
115 | # So, "#1234" means "#11223344" (i.e. [17, 34, 51, 68]).
116 | r = ($1[0,1]*2).hex
117 | g = ($1[1,1]*2).hex
118 | b = ($1[2,1]*2).hex
119 | a = ($1[3,1]*2).hex
120 | new( [r, g, b, a] )
121 | when /^#?([0-9a-f]{3})$/i
122 | # As with HTML/CSS, each hexdigit is repeated.
123 | # So, "#123" means "#112233" (i.e. [17, 34, 51]).
124 | r = ($1[0,1]*2).hex
125 | g = ($1[1,1]*2).hex
126 | b = ($1[2,1]*2).hex
127 | a = 255
128 | new( [r, g, b, a] )
129 | else
130 | raise "Invalid hex color string #{color_str.inspect}."
131 | end
132 | end
133 |
134 | # Returns the color as an RGBA array of integers ranging from 0
135 | # to 255, as SDL wants.
136 | def to_sdl_rgba_ary
137 | [@r, @g, @b, @a]
138 | end
139 |
140 | # Returns the color as an RGBA array of floats ranging from 0.0
141 | # to 1.0.
142 | def to_rgba_ary
143 | [@r/255.0, @g/255.0, @b/255.0, @a/255.0]
144 | end
145 |
146 | # Same as #to_sdl_rgba_ary
147 | def to_ary
148 | [@r, @g, @b, @a]
149 | end
150 |
151 | # Returns the color as an 8-digit hex color string, in the form
152 | # "#RRGGBBAA". See also ColorRGB255.hex.
153 | #
154 | # Example:
155 | #
156 | # include Rubygame::Color
157 | #
158 | # color = ColorRGB255.hex("#124589ff")
159 | # # => #
160 | # color.to_hex
161 | # # => "#124589ff"
162 | #
163 | # ColorRGB255.hex("1234").to_hex
164 | # # => "#11223344"
165 | #
166 | def to_hex
167 | "#" + "%0.2x"%@r + "%0.2x"%@g + "%0.2x"%@b + "%0.2x"%@a
168 | end
169 |
170 | end
171 | end
172 | end
173 |
--------------------------------------------------------------------------------
/lib/rubygame/color/palettes/css.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | module Rubygame
23 | module Color
24 |
25 | # :enddoc:
26 |
27 | # The CSS module contains all the colors in the CSS/HTML palette
28 | # by symbol name, e.g. :alice_blue, :dark_olive_green, etc.
29 | #
30 | # NOTE: The CSS palette is identical to the X11 palette except for
31 | # four colors: gray, green, maroon, and purple.
32 | #
33 | # Differences between CSS and X11 derived from
34 | # http://en.wikipedia.org/wiki/X11_color_names
35 | # as accessed on 2007-12-17
36 | #
37 | CSS = Palette.new({
38 | :gray => ColorRGB.new( [0.50196, 0.50196, 0.50196] ),
39 | :green => ColorRGB.new( [0.00000, 0.50196, 0.00000] ),
40 | :maroon => ColorRGB.new( [0.50196, 0.00000, 0.00000] ),
41 | :purple => ColorRGB.new( [0.50196, 0.00000, 0.50196] )
42 | })
43 |
44 | CSS.include X11
45 |
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/lib/rubygame/color/palettes/palette.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 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 | class Rubygame::Color::Palette
21 |
22 | # Create a new Palette with the given name => color pairs.
23 | def initialize( colors = {} )
24 | @includes = []
25 |
26 | @colors = {}
27 | colors.each_pair do |name, color|
28 | @colors[sanitize_name(name)] = color
29 | end
30 | end
31 |
32 | # Retrieve a color by name from this palette.
33 | #
34 | # The name can be a Symbol or String. See #sanitize_name.
35 | #
36 | # If the color cannot be found in this palette, search
37 | # each of the #included palettes (recursively, depth-first,
38 | # to a maximum depth of 5 levels).
39 | #
40 | # If the color is not found in this palette or any included
41 | # palettes, raise IndexError.
42 | #
43 | def []( name )
44 | c = lookup( sanitize_name( name ) )
45 | raise IndexError, "unknown color #{name}" unless c
46 | return c
47 | end
48 |
49 | # Store a color by name in this palette. See #sanitize_name
50 | def []=( name, color )
51 | # Uncache colors with this name, to avoid using obsolete value.
52 | Rubygame::Color.remove_from_cache( name )
53 |
54 | name = sanitize_name( name )
55 | @colors[name] = color
56 | end
57 |
58 | # Include another palette in this one. If a color cannot be
59 | # found in this palette, the included palette(s) will be searched.
60 | # See also #uninclude.
61 | #
62 | # Has no effect if the palette is already included.
63 | def include( palette )
64 | @includes += [palette] unless @includes.include? palette
65 | end
66 |
67 | # Remove the other palette from this one, so that it won't be
68 | # searched for missing colors anymore. Has no effect if the
69 | # other palette hasn't been #included.
70 | def uninclude( palette )
71 | @includes -= [palette]
72 | end
73 |
74 | protected
75 |
76 | # Recursive color lookup
77 | def lookup( name, max_depth=5 ) # :nodoc:
78 | return nil if max_depth < 0
79 |
80 | color = @colors[name]
81 |
82 | unless color
83 | @includes.each { |palette|
84 | c = palette.lookup(name, max_depth-1)
85 | color = c if c
86 | }
87 | end
88 |
89 | return color
90 | end
91 |
92 | private
93 |
94 | # Takes either a Symbol or a String, and converts it to a
95 | # lowercase Symbol with spaces converted to underscores.
96 | #
97 | # E.g. "Alice Blue" and :ALICE_BLUE both become :alice_blue.
98 | #
99 | def sanitize_name( name )
100 | name.to_s.gsub(' ','_').downcase.intern
101 | end
102 |
103 | end
104 |
--------------------------------------------------------------------------------
/lib/rubygame/event_actions.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 2004-2008 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 | # This module contains all the event action classes that
22 | # come with Rubygame.
23 | #
24 | # An event action class is simply a class which can be
25 | # used as an action an EventHook. The action is used to
26 | # cause some effect when the EventHook matches an event.
27 | #
28 | # The only requirement for an event action is this:
29 | #
30 | # * It must have a #perform method which takes exactly two
31 | # arguments (the hook owner and an event). Return values
32 | # are ignored.
33 | #
34 | # You can make your own custom event action classes and
35 | # use them in an EventHook if they meet that requirement.
36 | #
37 | # Here is an overview of the event action classes that
38 | # come with Rubygame as of version 2.4:
39 | #
40 | # BlockAction:: Calls a custom code block, passing it the
41 | # hook owner and the event.
42 | #
43 | # MethodAction:: Calls one of the owner's methods, passing
44 | # it the event.
45 | #
46 | # MultiAction:: Holds multiple other actions and performs
47 | # each of them, in order.
48 | #
49 | module Rubygame::EventActions
50 |
51 |
52 | # BlockAction is an event action used with EventHook. BlockAction
53 | # takes a code block at initialization. When the action is performed,
54 | # it executes the block, passing in the EventHook#owner and the event
55 | # that is being handled as the two parameters to the block.
56 | #
57 | # Example:
58 | #
59 | # hit_by_missile = KindOfTrigger.new( MissileCollisionEvent )
60 | #
61 | # take_damage = BlockAction.new { |owner, event|
62 | # owner.health -= event.damage_amount
63 | # }
64 | #
65 | # hook = EventHook.new( :owner => player_ship,
66 | # :trigger => hit_by_missile,
67 | # :action => take_damage )
68 | #
69 | #
70 | # NOTE: It is also possible to pass a Proc or detached Method
71 | # as the block, using the standard Ruby syntax for that:
72 | #
73 | # # Using a pre-built Proc.
74 | #
75 | # my_proc = Proc.new { |owner, event| do_something() }
76 | #
77 | # BlockAction.new( &my_proc )
78 | #
79 | #
80 | # # Using a detached method.
81 | #
82 | # def a_method( owner, event )
83 | # do_something
84 | # end
85 | #
86 | # detached_method = method(:a_method)
87 | #
88 | # BlockAction.new( &detached_method )
89 | #
90 | #
91 | class BlockAction
92 |
93 | # Create a new BlockAction using the given code block.
94 | #
95 | # &block:: the code block to execute. Should take two parameters,
96 | # owner and event. (Proc, required)
97 | #
98 | # May raise:: ArgumentError, if no block is provided.
99 | #
100 | def initialize( &block )
101 | raise ArgumentError, "BlockAction needs a block" unless block_given?
102 | @block = block
103 | end
104 |
105 | # Execute the code block, passing in owner and event as the two
106 | # parameters to the block. This is automatically called by EventHook
107 | # when an event matches the trigger. You should usually not call it
108 | # in your own code.
109 | #
110 | # owner:: the owner of the EventHook, or nil if there is none.
111 | # (Object, required)
112 | # event:: the event that matched the trigger. (Object, required)
113 | #
114 | def perform( owner, event )
115 | @block.call( owner, event )
116 | end
117 | end
118 |
119 |
120 | # MethodAction is an event action used with EventHook.
121 | # MethodAction takes a symbol giving the name of a method. When
122 | # it is performed, it calls that method on the owner, passing
123 | # it the event that triggered the hook.
124 | #
125 | # Example:
126 | #
127 | # class Player
128 | # def aim_at( event )
129 | # self.crosshair_pos = event.pos
130 | # end
131 | # end
132 | #
133 | # player1 = Player.new
134 | #
135 | # EventHook.new( :owner => player1,
136 | # :trigger => MouseMoveTrigger.new(),
137 | # :action => MethodAction.new( :aim_at ) )
138 | #
139 | class MethodAction
140 |
141 | # Create a new MethodAction using the given method name.
142 | #
143 | # method_name:: the method to call when performing.
144 | # (Symbol, required)
145 | #
146 | def initialize( method_name )
147 | @method_name = method_name
148 | end
149 |
150 |
151 | # Call the method of the owner represented by @method_name,
152 | # passing in the event as the only argument.
153 | #
154 | # If that causes ArgumentError (e.g. because the method doesn't
155 | # take an argument), calls again without any arguments.
156 | #
157 | # If that also fails, this method re-raises the original error.
158 | #
159 | def perform( owner, event )
160 | owner.method(@method_name).call( event )
161 | rescue ArgumentError => s
162 | begin
163 | # Oops! Try again, without any argument.
164 | owner.method(@method_name).call()
165 | rescue ArgumentError
166 | # That didn't work either. Raise the original error.
167 | raise s
168 | end
169 | end
170 | end
171 |
172 |
173 |
174 | # MultiAction is an event action used with EventHook.
175 | # It takes zero or more actions (e.g. BlockAction or MethodAction
176 | # instances) at initialization.
177 | #
178 | # When MultiAction is performed, it performs all the given
179 | # actions, in the order they were given, passing in the owner
180 | # and event.
181 | #
182 | # As the name suggests, you can use MultiAction to cause
183 | # multiple actions to occur when an EventHook is triggered.
184 | #
185 | class MultiAction
186 |
187 | # Create a new MultiAction instance with the given sub-actions.
188 | #
189 | # *actions:: the actions to perform. (Action instances)
190 | #
191 | def initialize( *actions )
192 | @actions = actions
193 | end
194 |
195 | # Performs all the sub-actions, in the order they were given,
196 | # passing in the owner and event to each one.
197 | #
198 | def perform( owner, event )
199 | @actions.each { |action| action.perform( owner, event ) }
200 | end
201 | end
202 |
203 | end
204 |
--------------------------------------------------------------------------------
/lib/rubygame/event_hook.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 2004-2008 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 | require "rubygame/event_triggers"
22 | require "rubygame/event_actions"
23 |
24 |
25 | module Rubygame
26 |
27 | # The EventHook class provides the bare framework for event hooks
28 | # used by EventHandler. Each hook has a trigger, which controls what
29 | # types of events cause the hook to engage, and an action, which
30 | # controls what should happen when the hook engages.
31 | #
32 | # An instance of EventHook has these attributes:
33 | #
34 | # owner:: the object that this hook applies to. This value will
35 | # be provided to the action when the hook engages.
36 | #
37 | # trigger:: an instance of a trigger class, used to test every
38 | # event to check whether the hook should engage.
39 | # A valid trigger must have a #match? method which
40 | # accepts an event and returns either true or false.
41 | #
42 | # action:: an instance of an action class, which is performed
43 | # when the trigger matches an event. A valid action
44 | # must have a #perform method which accepts two values:
45 | # the hook's owner and the matching event.
46 | #
47 | # consumes:: if true, the event hook "eats" every event that it
48 | # matches, so that hooks that come after it will not
49 | # see the event. Has no effect on non-matching events.
50 | #
51 | # active:: if false, the event hook is disabled, and will not
52 | # match any event until it is set to true again. You can
53 | # use this to temporarily disable the hook.
54 | #
55 | class EventHook
56 | attr_accessor :owner, :trigger, :action, :consumes, :active
57 |
58 | # Create a new instance of EventHook. Description is a Hash with
59 | # the following keys. See the class documentation for EventHook for
60 | # more information about what these mean.
61 | #
62 | # :owner :: the hook's owner. (any object, required)
63 | # :trigger :: an event trigger which matches certain events.
64 | # (Object with +#match?(event)+, required)
65 | # :action :: an event action to do when an event matches.
66 | # (Object with +#perform(owner,event)+, required)
67 | # :consumes :: if true, the hook will "eat" matching so
68 | # later hooks won't see them. Default: false.
69 | # (true or false, optional)
70 | # :active :: if false, the hook will ignore all events.
71 | # Default: true. (true or false, optional)
72 | #
73 | # NOTE: None of the attributes are truly required to create a hook.
74 | # But, the hook will do nothing unless both @trigger and @action are
75 | # set. Setting @owner is also highly recommended, because some types
76 | # of actions use the owner, and may raise an error if it is nil.
77 | #
78 | # TIP: It's possible to set these attributes at any time using the
79 | # accessors. For example, You could change keyboard controls on the
80 | # fly, or temporarily deactivate a hook to stop it from engaging.
81 | #
82 | # Example:
83 | #
84 | # # Call player1.jump() when the space bar is pressed.
85 | # EventHook.new( :owner => player1,
86 | # :trigger => KeyPressTrigger.new(:space)
87 | # :action => MethodAction.new(:jump) )
88 | #
89 | def initialize( description={} )
90 | @owner = description[:owner]
91 | @trigger = description[:trigger]
92 | @action = description[:action]
93 | @consumes = (description[:consumes] or false)
94 | @active = (description[:active].nil? ? true : description[:active])
95 | end
96 |
97 | # Passes the event to @trigger's #match? method, and returns the
98 | # result. If there is no @trigger or if @active is false, returns
99 | # nil immediately.
100 | def match?( event )
101 | if (@trigger and @active)
102 | @trigger.match?( event )
103 | else
104 | false
105 | end
106 | end
107 |
108 | # Passes @owner and event to the @action's #perform method.
109 | def perform( event )
110 | @action.perform( owner, event ) if @action
111 | end
112 | end
113 |
114 | end
115 |
--------------------------------------------------------------------------------
/lib/rubygame/events/clock_events.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # This file is one part of:
3 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
4 | #
5 | # Copyright (C) 2009 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 | module Rubygame
24 |
25 | module Events
26 |
27 | # ClockTicked is an event returned by Clock#tick, if the Clock
28 | # has been configured with Clock#enable_tick_events.
29 | #
30 | # ClockTicked stores the time that has passed since the previous
31 | # tick. You can access that information with #seconds or
32 | # #milliseconds. This is useful to calculate how far a character
33 | # should move during the current frame, for example.
34 | #
35 | class ClockTicked
36 |
37 | # Create a new ClockTicked event.
38 | #
39 | # milliseconds:: The time since the last tick,
40 | # in milliseconds. (Numeric, required)
41 | #
42 | def initialize( milliseconds )
43 | @milliseconds = milliseconds
44 | end
45 |
46 | # Return the time since the last tick, in milliseconds.
47 | def milliseconds
48 | @milliseconds
49 | end
50 |
51 | # Return the time since the last tick, in seconds.
52 | def seconds
53 | @seconds or (@seconds = @milliseconds * 0.001)
54 | end
55 | end
56 |
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/lib/rubygame/events/keyboard_events.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # This file is one part of:
3 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
4 | #
5 | # Copyright (C) 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 | module Rubygame
24 |
25 | module Events
26 |
27 | #
28 | # KeyboardEvent is a mixin module included in the KeyPressed
29 | # and KeyReleased classes. It defines the #key and #modifiers
30 | # accessors.
31 | #
32 | module KeyboardEvent
33 | attr_reader :key, :modifiers
34 |
35 | #
36 | # Initialize the KeyboardEvent.
37 | #
38 | # key:: a key symbol for the key that was pressed or
39 | # released. (Symbol, required)
40 | #
41 | # modifiers:: an Array of key symbols for the modifier keys
42 | # that were active when the event occured.
43 | # (Array, optional)
44 | #
45 | def initialize( key, modifiers=[] )
46 |
47 | unless key.kind_of? Symbol
48 | raise ArgumentError, "key must be a :symbol"
49 | end
50 |
51 | @key = key
52 |
53 | @modifiers = modifiers.to_ary.dup
54 | @modifiers.freeze
55 |
56 | end
57 | end
58 |
59 |
60 | #
61 | # KeyPressed is an event class which occurs when a key
62 | # on the keyboard is pressed down.
63 | #
64 | # This class gains #key and #modifiers readers from
65 | # the KeyboardEvent mixin module.
66 | #
67 | # It also has #string, which is a UTF8 string containing
68 | # the text character that was generated by the keystroke;
69 | # if nothing was generated, #string will be the empty string,
70 | # "".
71 | #
72 | # The #string attribute is useful for for taking text input
73 | # (e.g. in a GUI). It supports UTF8 Unicode characters, and
74 | # works correctly on many different types of keyboards.
75 | #
76 | class KeyPressed
77 | include KeyboardEvent
78 |
79 | attr_reader :string
80 |
81 | #
82 | # Create a new KeyPressed instance.
83 | #
84 | # key:: a key symbol for the key that was pressed or
85 | # released. (Symbol, required)
86 | #
87 | # modifiers:: an Array of key symbols for the modifier keys
88 | # that were active when the event occured.
89 | # (Array, optional)
90 | #
91 | # string:: a String containing the text character that
92 | # was generated by the keystroke, or "" if
93 | # nothing was generated. (String, optional)
94 | #
95 | def initialize( key, modifiers=[], string="" )
96 | super( key, modifiers )
97 |
98 | @string = string.to_str.dup
99 | @string.freeze
100 |
101 | end
102 | end
103 |
104 |
105 | #
106 | # KeyReleased is an event class which occurs when a key
107 | # on the keyboard is released (no longer being pressed).
108 | #
109 | # This class gains #key and #modifiers readers from
110 | # the KeyboardEvent mixin module.
111 | #
112 | class KeyReleased
113 | include KeyboardEvent
114 |
115 | #
116 | # Create a new KeyReleased instance.
117 | #
118 | # key:: a key symbol for the key that was pressed or
119 | # released. (Symbol, required)
120 | #
121 | # modifiers:: an Array of key symbols for the modifier keys
122 | # that were active when the event occured.
123 | # (Array, optional)
124 | #
125 | def initialize( key, modifiers=[] )
126 | super
127 | end
128 |
129 | end
130 |
131 | end
132 | end
133 |
--------------------------------------------------------------------------------
/lib/rubygame/events/misc_events.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # This file is one part of:
3 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
4 | #
5 | # Copyright (C) 2008-2010 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 | module Rubygame
24 |
25 | module Events
26 |
27 | # FocusEvent is a mixin module that is included in the following
28 | # event classes:
29 | #
30 | # * InputFocusGained
31 | # * InputFocusLost
32 | # * MouseFocusGained
33 | # * MouseFocusLost
34 | # * WindowMinimized
35 | # * WindowUnminimized
36 | #
37 | # This module provides no functionality. It exists only to make it
38 | # easier to detect the above classes in a case statement, etc.
39 | #
40 | # Examples:
41 | #
42 | # include Rubygame::Events
43 | #
44 | # case event
45 | # when FocusEvent
46 | # # ...
47 | # end
48 | #
49 | # if event.is_a? FocusEvent
50 | # # ...
51 | # end
52 | #
53 | module FocusEvent; end
54 |
55 |
56 |
57 | # InputFocusEvent is a mixin module that is included in the
58 | # following event classes:
59 | #
60 | # * InputFocusGained
61 | # * InputFocusLost
62 | #
63 | # This module provides no functionality. It exists only to make it
64 | # easier to detect the above classes in a case statement, etc.
65 | #
66 | # Examples:
67 | #
68 | # include Rubygame::Events
69 | #
70 | # case event
71 | # when InputFocusEvent
72 | # # ...
73 | # end
74 | #
75 | # if event.is_a? InputFocusEvent
76 | # # ...
77 | # end
78 | #
79 | module InputFocusEvent
80 | include FocusEvent
81 | end
82 |
83 | # InputFocusGained is an event that occurs when
84 | # the Rubygame application gains input focus.
85 | #
86 | # Input focus means that the app will receive events from
87 | # input devices, such as the keyboard and joysticks.
88 | #
89 | # Usually, an application has input focus when it is the "active"
90 | # application (the one the user has clicked on or switched to most
91 | # recently).
92 | #
93 | class InputFocusGained
94 | include InputFocusEvent
95 | end
96 |
97 | # InputFocusLost is an event that occurs when
98 | # the Rubygame application loses input focus.
99 | #
100 | # See InputFocusGained for a description of "input focus".
101 | #
102 | class InputFocusLost
103 | include InputFocusEvent
104 | end
105 |
106 |
107 |
108 | # MouseFocusEvent is a mixin module that is included in the
109 | # following event classes:
110 | #
111 | # * MouseFocusGained
112 | # * MouseFocusLost
113 | #
114 | # This module provides no functionality. It exists only to make it
115 | # easier to detect the above classes in a case statement, etc.
116 | #
117 | # Examples:
118 | #
119 | # include Rubygame::Events
120 | #
121 | # case event
122 | # when MouseFocusEvent
123 | # # ...
124 | # end
125 | #
126 | # if event.is_a? MouseFocusEvent
127 | # # ...
128 | # end
129 | #
130 | module MouseFocusEvent
131 | include FocusEvent
132 | end
133 |
134 | # MouseFocusGained is an event that occurs when
135 | # the Rubygame application gains mouse focus.
136 | #
137 | # Mouse focus means that the mouse cursor is inside the
138 | # app window. When the app has mouse focus, it will receive
139 | # mouse events, particularly MouseMoved.
140 | #
141 | class MouseFocusGained
142 | include MouseFocusEvent
143 | end
144 |
145 | # MouseFocusLost is an event that occurs when
146 | # the Rubygame application loses mouse focus.
147 | #
148 | # See MouseFocusGained for a description of "mouse focus".
149 | #
150 | class MouseFocusLost
151 | include MouseFocusEvent
152 | end
153 |
154 |
155 |
156 | # MinimizeEvent is a mixin module that is included in the
157 | # following event classes:
158 | #
159 | # * WindowMinimized
160 | # * WindowUnminimized
161 | #
162 | # This module provides no functionality. It exists only to make it
163 | # easier to detect the above classes in a case statement, etc.
164 | #
165 | # Examples:
166 | #
167 | # include Rubygame::Events
168 | #
169 | # case event
170 | # when MinimizeEvent
171 | # # ...
172 | # end
173 | #
174 | # if event.is_a? MinimizeEvent
175 | # # ...
176 | # end
177 | #
178 | module MinimizeEvent
179 | include FocusEvent
180 | end
181 |
182 | # WindowMinimized is an event that occurs when
183 | # the Rubygame application window becomes minimized (also
184 | # called 'iconified').
185 | #
186 | class WindowMinimized
187 | include MinimizeEvent
188 | end
189 |
190 | # WindowUnminimized is an event that occurs when the
191 | # Rubygame application window is restored after it had been
192 | # minimized.
193 | #
194 | class WindowUnminimized
195 | include MinimizeEvent
196 | end
197 |
198 |
199 |
200 | # WindowExposed is an event that occurs in
201 | # certain situations when the Rubygame application
202 | # window is exposed after being covered by another
203 | # application.
204 | #
205 | # This event may not occur on all platforms, but
206 | # when it does occur, your app should refresh the
207 | # entire window via Screen#flip (or
208 | # Rubygame::GL.swap_buffers, if using OpenGL).
209 | #
210 | class WindowExposed; end
211 |
212 |
213 |
214 | # QuitRequested is an event that occurs when the
215 | # application receives a quit request, usually due to the
216 | # user clicking the "Close" button on the app window.
217 | #
218 | # Almost always, your application should respond to this
219 | # event by quitting or by displaying a "Quit/Cancel"
220 | # dialog. If you ignore this event, the user may become
221 | # frustrated that your app won't close properly!
222 | #
223 | class QuitRequested; end
224 |
225 |
226 |
227 | # WindowResized is an event that occurs when the
228 | # Rubygame application window is resized by the user.
229 | # This can only happen if the Screen mode was set with
230 | # the "resizable" flag.
231 | #
232 | # Your application should respond to this event by
233 | # setting the Screen mode again with the new #size and
234 | # redrawing.
235 | #
236 | # If you ignore this event, the "active" area of the
237 | # Screen will stay the same size, and the rest (if the
238 | # window was enlarged) will be black and won't receive
239 | # any changes (blits, drawing, etc.).
240 | #
241 | class WindowResized
242 | attr_reader :size
243 |
244 | def initialize( size )
245 |
246 | @size = size.to_ary.dup
247 | @size.freeze
248 |
249 | unless @size.length == 2
250 | raise ArgumentError, "size must have exactly 2 parts (got %s)"%@size.length
251 | end
252 |
253 | @size.each do |part|
254 | if part <= 0
255 | raise ArgumentError, "size must be positive (got %s)"%part
256 | end
257 | end
258 |
259 | end
260 | end
261 |
262 |
263 | end
264 | end
265 |
--------------------------------------------------------------------------------
/lib/rubygame/events/mouse_events.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # This file is one part of:
3 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
4 | #
5 | # Copyright (C) 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 | module Rubygame
24 |
25 | module Events
26 |
27 | #
28 | # MouseButtonEvent is a mixin module included in the MousePressed
29 | # and MouseReleased classes. It defines the #button and #pos
30 | # attribute readers.
31 | #
32 | module MouseButtonEvent
33 | attr_reader :button, :pos
34 |
35 | #
36 | # Initialize the MouseButtonEvent.
37 | #
38 | # button:: a symbol for the button that was pressed or
39 | # released. (Symbol, required)
40 | #
41 | # pos:: an Array for the position of the mouse cursor
42 | # when the event occured. [0,0] is the top-left
43 | # corner of the window (or the screen if running
44 | # full-screen). (Array, required)
45 | #
46 | def initialize( pos, button )
47 |
48 | unless button.kind_of? Symbol
49 | raise ArgumentError, "button must be a :symbol"
50 | end
51 |
52 | @button = button
53 |
54 | @pos = pos.to_ary.dup
55 | @pos.freeze
56 |
57 | end
58 | end
59 |
60 |
61 | #
62 | # MousePressed is an event class which occurs when a button
63 | # on the mouse is pressed down.
64 | #
65 | # This class gains #button and #pos attribute readers from
66 | # the MouseButtonEvent mixin module.
67 | #
68 | class MousePressed
69 | include MouseButtonEvent
70 |
71 | #
72 | # Create a new MousePressed instance.
73 | #
74 | # button:: a symbol for the button that was pressed or
75 | # released. (Symbol, required)
76 | #
77 | # pos:: an Array for the position of the mouse cursor
78 | # when the event occured. [0,0] is the top-left
79 | # corner of the window (or the screen if running
80 | # full-screen). (Array, required)
81 | #
82 | def initialize( pos, button )
83 | super
84 | end
85 | end
86 |
87 |
88 | #
89 | # MouseReleased is an event class which occurs when a button
90 | # on the mouse is released (no longer being pressed).
91 | #
92 | # This class gains #button and #pos attribute readers from
93 | # the MouseButtonEvent mixin module.
94 | #
95 | class MouseReleased
96 | include MouseButtonEvent
97 |
98 | #
99 | # Create a new MouseReleased instance.
100 | #
101 | # button:: a symbol for the button that was pressed or
102 | # released. (Symbol, required)
103 | #
104 | # pos:: an Array for the position of the mouse cursor
105 | # when the event occured. [0,0] is the top-left
106 | # corner of the window (or the screen if running
107 | # full-screen). (Array, required)
108 | #
109 | def initialize( pos, button )
110 | super
111 | end
112 | end
113 |
114 |
115 | #
116 | # MouseMoved is an event class which occurs when the mouse
117 | # cursor moves. It has attribute readers for #pos (new position),
118 | # #rel (change since the last MouseMoved event), and #buttons
119 | # (an Array of the mouse buttons that were held down while moving).
120 | #
121 | class MouseMoved
122 |
123 | attr_reader :pos, :rel, :buttons
124 |
125 | #
126 | # Create a new MouseReleased instance.
127 | #
128 | # pos:: an Array for the new position of the mouse cursor.
129 | # The point [0,0] is the top-left corner of the window
130 | # (or the screen if running full-screen).
131 | # (Array, required)
132 | #
133 | # rel:: an Array for the position change since the last
134 | # MouseMoved event, in pixels. (Array, required)
135 | #
136 | # buttons:: an Array of symbols for the mouse buttons that were
137 | # being held down while the mouse was moving. [] if
138 | # no buttons were being held. (Array, optional)
139 | #
140 | def initialize( pos, rel, buttons=[] )
141 |
142 | @pos = pos.to_ary.dup
143 | @pos.freeze
144 |
145 | @rel = rel.to_ary.dup
146 | @rel.freeze
147 |
148 | @buttons = buttons.to_ary.dup
149 | @buttons.freeze
150 |
151 | end
152 | end
153 |
154 | end
155 | end
156 |
--------------------------------------------------------------------------------
/lib/rubygame/gl.rb:
--------------------------------------------------------------------------------
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 | # The GL module provides an interface to SDL's OpenGL-related functions,
23 | # allowing a Rubygame application to create hardware-accelerated 3D graphics
24 | # with OpenGL.
25 | #
26 | # Please note that Rubygame itself does not provide an interface to OpenGL
27 | # functions -- only functions which allow Rubygame to work together with
28 | # OpenGL. You will need to use another library, for example
29 | # ruby-opengl[http://ruby-opengl.rubyforge.org/],
30 | # to actually create graphics with OpenGL.
31 | #
32 | # Users who wish to use Rubygame Surfaces as textures in OpenGL should
33 | # see also the Surface#pixels method.
34 | #
35 | module Rubygame::GL
36 |
37 |
38 | # Return the value of the the SDL/OpenGL attribute identified by +attrib+,
39 | # which should be one of the constants defined in the Rubygame::GL module.
40 | # See #set_attrib for a list of attribute constants.
41 | #
42 | # This method is useful after using #set_attrib and calling Screen#set_mode,
43 | # to make sure the attribute is the expected value.
44 | #
45 | def self.get_attrib( attrib )
46 | result = SDL.GL_GetAttribute(attrib)
47 | if( result.nil? )
48 | raise Rubygame::SDLError, "GL get attribute failed: #{SDL.GetError()}"
49 | end
50 | end
51 |
52 |
53 |
54 | # Set the SDL/OpenGL attribute +attrib+ to +value+. This should be called
55 | # *before* you call Screen#set_mode with the OPENGL flag. You may wish to
56 | # use #get_attrib after calling Screen#set_mode to confirm that the attribute
57 | # is set to the desired value.
58 | #
59 | # The full list of SDL/OpenGL attribute identifier constants (located under
60 | # the Rubygame::GL module) is as follows:
61 | #
62 | # RED_SIZE:: Size of framebuffer red component, in bits.
63 | # GREEN_SIZE:: Size of framebuffer green component, in bits.
64 | # BLUE_SIZE:: Size of framebuffer blue component, in bits.
65 | # ALPHA_SIZE:: Size of framebuffer alpha (opacity) component, in bits.
66 | # BUFFER_SIZE:: Size of framebuffer, in bits.
67 | # DOUBLEBUFFER:: Enable or disable double-buffering.
68 | # DEPTH_SIZE:: Size of depth buffer, in bits.
69 | # STENCIL_SIZE:: Size of stencil buffer, in bits.
70 | # ACCUM_RED_SIZE:: Size of accumulation buffer red component, in bits.
71 | # ACCUM_GREEN_SIZE:: Size of accumulation buffer green component, in bits.
72 | # ACCUM_BLUE_SIZE:: Size of accumulation buffer blue component, in bits.
73 | # ACCUM_ALPHA_SIZE:: Size of accumulation buffer alpha component, in bits.
74 | #
75 | def self.set_attrib( attrib, value )
76 | result = SDL.GL_SetAttribute( attrib, value )
77 | if( result == -1 )
78 | raise Rubygame::SDLError, "GL set attribute failed: #{SDL.GetError()}"
79 | end
80 | end
81 |
82 |
83 |
84 | # Swap the back and front buffers, for double-buffered OpenGL displays.
85 | # Should be safe to use (albeit with no effect) on single-buffered OpenGL
86 | # displays.
87 | #
88 | def self.swap_buffers
89 | SDL.GL_SwapBuffers()
90 | end
91 |
92 |
93 | RED_SIZE = SDL::GL_RED_SIZE
94 | GREEN_SIZE = SDL::GL_GREEN_SIZE
95 | BLUE_SIZE = SDL::GL_BLUE_SIZE
96 | ALPHA_SIZE = SDL::GL_ALPHA_SIZE
97 | BUFFER_SIZE = SDL::GL_BUFFER_SIZE
98 | DOUBLEBUFFER = SDL::GL_DOUBLEBUFFER
99 | DEPTH_SIZE = SDL::GL_DEPTH_SIZE
100 | STENCIL_SIZE = SDL::GL_STENCIL_SIZE
101 | ACCUM_RED_SIZE = SDL::GL_ACCUM_RED_SIZE
102 | ACCUM_GREEN_SIZE = SDL::GL_ACCUM_GREEN_SIZE
103 | ACCUM_BLUE_SIZE = SDL::GL_ACCUM_BLUE_SIZE
104 | ACCUM_ALPHA_SIZE = SDL::GL_ACCUM_ALPHA_SIZE
105 |
106 |
107 | end
108 |
--------------------------------------------------------------------------------
/lib/rubygame/image.rb:
--------------------------------------------------------------------------------
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 | require "ruby-sdl-ffi/image"
23 |
24 | Rubygame::VERSIONS[:sdl_image] = SDL::Image.Linked_Version().to_ary
25 |
26 |
27 | class Rubygame::Surface
28 |
29 | class << self
30 |
31 | # Searches each directory in Surface.autoload_dirs for a file with
32 | # the given filename. If it finds that file, loads it and returns
33 | # a Surface instance. If it doesn't find the file, returns nil.
34 | #
35 | # See Rubygame::NamedResource for more information about this
36 | # functionality.
37 | #
38 | def autoload( name )
39 | path = find_file( name )
40 |
41 | if( path )
42 | return load( path )
43 | else
44 | return nil
45 | end
46 | end
47 |
48 |
49 | # *IMPORTANT*: this method only exists if SDL_image is available!
50 | # Your code should check "defined?(Rubygame::Surface.load) != nil"
51 | # to see if you can use this method, or be prepared to rescue from
52 | # NoMethodError.
53 | #
54 | # Load an image file from the disk to a Surface. If the image has an alpha
55 | # channel (e.g. PNG with transparency), the Surface will as well. If the
56 | # image cannot be loaded (for example if the image format is unsupported),
57 | # will raise SDLError.
58 | #
59 | # This method takes this argument:
60 | # filename:: a string containing the relative or absolute path to the
61 | # image file. The file must have the proper file extension,
62 | # as it is used to determine image format.
63 | #
64 | # These formats may be supported, but some may not be available on a
65 | # particular system.
66 | # BMP:: "Windows Bitmap" format.
67 | # GIF:: "Graphics Interchange Format."
68 | # JPG:: "Independent JPEG Group" format.
69 | # LBM:: "Linear Bitmap" format (?)
70 | # PCX:: "PC Paintbrush" format
71 | # PNG:: "Portable Network Graphics" format.
72 | # PNM:: "Portable Any Map" format. (i.e., PPM, PGM, or PBM)
73 | # TGA:: "Truevision TARGA" format.
74 | # TIF:: "Tagged Image File Format"
75 | # XCF:: "eXperimental Computing Facility" (GIMP native format).
76 | # XPM:: "XPixMap" format.
77 | #
78 | def load( filename )
79 | surf = SDL::Image.Load( filename.to_s )
80 |
81 | if( surf.pointer.null? )
82 | raise( Rubygame::SDLError, "Couldn't load image \"%s\": %s"%\
83 | [filename, SDL.GetError()] )
84 | end
85 |
86 | return self.new(surf)
87 | end
88 |
89 |
90 | # Deprecated. Use Surface.load instead!
91 | def load_image( filename )
92 | Rubygame.deprecated( "Rubygame::Surface.load_image", "3.0" )
93 | load( filename )
94 | end
95 |
96 |
97 | # *IMPORTANT*: this method only exists if SDL_image is available!
98 | # Your code should check
99 | # "defined?(Rubygame::Surface.load_from_string) != nil" to see if
100 | # you can use this method, or be prepared to rescue from
101 | # NoMethodError.
102 | #
103 | # Load an image file from memory (in the form of the given data)
104 | # to a Surface. If the image has an alpha channel (e.g. PNG with
105 | # transparency), the Surface will as well. If the image cannot be
106 | # loaded (for example if the image format is unsupported), will
107 | # raise SDLError.
108 | #
109 | # This method takes these arguments:
110 | # data:: a string containing the data for the image, such as
111 | # IO::read would return.
112 | # type:: The type of file that the image is (i.e. 'TGA'). Case is
113 | # not important. If absent, the library will try to
114 | # automatically detect the type.
115 | #
116 | # See Surface.load for a list of possible supported file types.
117 | #
118 | def load_from_string( data, type=nil )
119 | size = data.respond_to?(:bytesize) ? data.bytesize : data.size
120 | bytes = FFI::MemoryPointer.new(:char, size)
121 | bytes.put_bytes(0, data, 0, size)
122 | rw = SDL.RWFromMem(bytes, size)
123 |
124 | surf = if type
125 | SDL::Image.LoadTyped_RW(rw, 1, type)
126 | else
127 | SDL::Image.Load_RW(rw, 1)
128 | end
129 |
130 | if surf.pointer.null?
131 | raise( Rubygame::SDLError,
132 | "Couldn't load image from string: #{SDL.GetError()}" )
133 | end
134 |
135 | new(surf)
136 | end
137 |
138 | end
139 |
140 | end
141 |
--------------------------------------------------------------------------------
/lib/rubygame/joystick.rb:
--------------------------------------------------------------------------------
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 | # The Joystick class interfaces with joysticks, gamepads, and other
23 | # similar hardware devices used to play games. Each joystick may
24 | # have zero or more #axes, #balls, #hats, and/or #buttons.
25 | #
26 | # After a Joystick object is successfully created, events for that
27 | # Joystick will begin appearing on the EventQueue when a button is
28 | # pressed or released, a control stick is moved, etc.
29 | #
30 | # You can use Joystick.activate_all to start receiving events for
31 | # all joysticks (equivalent to creating them all individually with
32 | # Joystick.new). You can use Joystick.deactivate_all to stop
33 | # receiving events for all joysticks.
34 | #
35 | # As of Rubygame 2.4, these are the current, "new-style" Joystick
36 | # event classes:
37 | #
38 | # * Events::JoystickAxisMoved
39 | # * Events::JoystickButtonPressed
40 | # * Events::JoystickButtonReleased
41 | # * Events::JoystickBallMoved
42 | # * Events::JoystickHatMoved
43 | #
44 | # These old Joystick-related events are deprecated and will be
45 | # removed in Rubygame 3.0:
46 | #
47 | # * JoyAxisEvent
48 | # * JoyBallEvent
49 | # * JoyHatEvent
50 | # * JoyDownEvent
51 | # * JoyUpEvent
52 | #
53 | # For more information about "new-style" events, see
54 | # EventQueue.enable_new_style_events.
55 | #
56 | class Rubygame::Joystick
57 |
58 |
59 | # Returns the total number of joysticks detected on the system.
60 | def self.num_joysticks
61 | SDL.NumJoysticks()
62 | end
63 |
64 |
65 | # Returns the name of Nth joystick on the system. The name is
66 | # implementation-dependent. See also #name.
67 | #
68 | def self.get_name( index )
69 | SDL.JoystickName( index )
70 | end
71 |
72 |
73 | # Activate all joysticks on the system, equivalent to calling
74 | # Joystick.new for every joystick available. This will allow
75 | # joystick-related events to be sent to the EventQueue for all
76 | # joysticks.
77 | #
78 | # Returns:: Array of zero or more Joysticks.
79 | # May raise:: SDLError, if the joystick system could not be
80 | # initialized.
81 | #
82 | def self.activate_all
83 | # Initialize if it isn't already.
84 | if( SDL.WasInit(SDL::INIT_JOYSTICK) == 0 )
85 | if( SDL.Init(SDL::INIT_JOYSTICK) != 0 )
86 | raise Rubygame::SDLError, "Could not initialize SDL joysticks."
87 | end
88 | end
89 |
90 | # Collect Joystick instances in an Array
91 | joysticks = []
92 |
93 | num_joysticks.times do |i|
94 | joysticks << new( i )
95 | end
96 |
97 | return joysticks
98 | end
99 |
100 |
101 | # Deactivate all joysticks on the system. This will stop all
102 | # joystick-related events from being sent to the EventQueue.
103 | #
104 | def self.deactivate_all
105 | # Return right away if it isn't active
106 | return if( SDL.WasInit(SDL::INIT_JOYSTICK) == 0 )
107 |
108 | num_joysticks.times do |i|
109 | joy = SDL.JoystickOpen(i)
110 | unless( joy.pointer.nil? )
111 | SDL.JoystickClose( joy )
112 | end
113 | end
114 |
115 | return nil
116 | end
117 |
118 |
119 | # Create and initialize an interface to the Nth joystick on the
120 | # system. Raises SDLError if the joystick could not be opened.
121 | #
122 | def initialize( index )
123 | @struct = SDL.JoystickOpen( index )
124 | if( @struct.pointer.null? )
125 | raise( Rubygame::SDLError, "Could not open joystick %d: %s"%
126 | [index, SDL.GetError()] )
127 | end
128 | end
129 |
130 |
131 | # Returns the index number of the Joystick, i.e. the identifier
132 | # number of the joystick that this interface controls. This is the
133 | # same number that was given to Joystick.new.
134 | #
135 | def index
136 | SDL.JoystickIndex( @struct )
137 | end
138 |
139 |
140 | # Returns a String containing the name of the Joystick. The name is
141 | # implementation-dependent. See also Joystick.get_name.
142 | #
143 | def name
144 | SDL.JoystickName( self.index )
145 | end
146 |
147 |
148 | # Returns the number of axes (singular: axis) featured on the
149 | # Joystick. Each control stick generally has two axes (X and Y),
150 | # although there are other types of controls which are represented
151 | # as one or more axes.
152 | #
153 | def axes
154 | SDL.JoystickNumAxes( @struct )
155 | end
156 |
157 |
158 | # Returns the number of trackballs featured on the Joystick. A
159 | # trackball is usually a small sphere which can be rotated in-place
160 | # in any direction, registering relative movement along two axes.
161 | #
162 | def balls
163 | SDL.JoystickNumBalls( @struct )
164 | end
165 |
166 |
167 | # Returns the number of hats featured on the Joystick. A hat is a
168 | # switch which can be pushed in one of several directions, or
169 | # centered.
170 | #
171 | def hats
172 | SDL.JoystickNumHats( @struct )
173 | end
174 |
175 |
176 | # Returns the number of buttons featured on the Joystick. A button
177 | # can be in one of two states: neutral, or pushed.
178 | #
179 | def buttons
180 | SDL.JoystickNumButtons( @struct )
181 | end
182 |
183 |
184 | end
185 |
--------------------------------------------------------------------------------
/lib/rubygame/main.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 2004-2010 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 | require "ruby-sdl-ffi/sdl"
23 |
24 |
25 | module Rubygame
26 |
27 | VERSIONS = {
28 | :rubygame => [2, 6, 4],
29 | :sdl => SDL.Linked_Version().to_ary
30 | }
31 |
32 |
33 | # Initialize Rubygame. This should be called soon after you
34 | # +require+ Rubygame, so that everything will work properly.
35 | #
36 | def self.init
37 | if( SDL.Init(SDL::INIT_EVERYTHING) == 0 )
38 | SDL.EnableUNICODE(1)
39 | else
40 | raise Rubygame::SDLError, "Could not initialize SDL: #{SDL.GetError()}"
41 | end
42 | end
43 |
44 |
45 | # Quit Rubygame. This should be used before your program terminates,
46 | # especially if you have been using a fullscreen Screen! (Otherwise,
47 | # the desktop resolution might not revert to its previous setting on
48 | # some platforms, and your users will be frustrated and confused!)
49 | #
50 | def self.quit
51 | SDL.Quit
52 | end
53 |
54 |
55 |
56 | # Indicates that an SDL function failed.
57 | class SDLError < RuntimeError
58 | end
59 |
60 |
61 |
62 | SWSURFACE = SDL::SWSURFACE
63 | HWSURFACE = SDL::HWSURFACE
64 | ASYNCBLIT = SDL::ASYNCBLIT
65 | ANYFORMAT = SDL::ANYFORMAT
66 | HWPALETTE = SDL::HWPALETTE
67 | HWACCEL = SDL::HWACCEL
68 | SRCCOLORKEY = SDL::SRCCOLORKEY
69 | RLEACCELOK = SDL::RLEACCELOK
70 | RLEACCEL = SDL::RLEACCEL
71 | SRCALPHA = SDL::SRCALPHA
72 | PREALLOC = SDL::PREALLOC
73 |
74 | DOUBLEBUF = SDL::DOUBLEBUF
75 | FULLSCREEN = SDL::FULLSCREEN
76 | OPENGL = SDL::OPENGL
77 | OPENGLBLIT = SDL::OPENGLBLIT
78 | RESIZABLE = SDL::RESIZABLE
79 | NOFRAME = SDL::NOFRAME
80 |
81 |
82 | end
83 |
--------------------------------------------------------------------------------
/lib/rubygame/mediabag.rb:
--------------------------------------------------------------------------------
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 | #--
23 | # MediaBag is DEPRECATED and will be removed in Rubygame 3.0!
24 | # Warn the user when this file is loaded.
25 | #++
26 | Rubygame.deprecated("Rubygame::MediaBag", "3.0")
27 |
28 |
29 | module Rubygame
30 |
31 | # *NOTE*: MediaBag is DEPRECATED and will be removed in Rubygame 3.0!
32 | # Use the NamedResource functionality of Music, Sound, and Surface instead.
33 | #
34 | # *NOTE*: you must require 'rubygame/mediabag' manually to gain access to
35 | # Rubygame::MediaBag. It is not imported with Rubygame by default!
36 | #
37 | # A Hash-like class which will load and retain media files (images and
38 | # sounds), so that the file can be loaded once, but used many times.
39 | #
40 | # The first time a file is requested with the #[] method,that file will be
41 | # loaded into memory. All subsequent requests for the same file will return
42 | # a reference to the already-loaded version. Ideally, objects should not
43 | # have to know whether or not the image has been loaded or not.
44 | class MediaBag
45 | @@image_ext = %W{bmp gif jpg lbm pcx png pnm ppm pgm pbm tga tif xcf xpm}
46 | @@sound_ext = %W{wav}
47 |
48 | def initialize()
49 | @media = Hash.new
50 | end
51 |
52 | # Return a reference to the stored value for key.
53 | # If there is no value for key, automatically attempt to load key
54 | # as a filename (guessing the file type based on its extension)
55 | #
56 | def [](key)
57 | @media[key] or load(key)
58 | rescue Rubygame::SDLError
59 | nil
60 | end
61 |
62 | # Load the file, but only if it has not been previously loaded.
63 | def load(filename)
64 | @media[filename] or store( filename, load_file(filename) )
65 | end
66 |
67 | # Store value as key, but only if there is no previous value.
68 | def store(key,value)
69 | @media[key] ||= value
70 | end
71 |
72 | # Forcibly (re)load the file, replacing the previous version in memory
73 | # (if any).
74 | def force_load(filename)
75 | force_store( filename, load_file(filename) )
76 | end
77 |
78 | # Forcibly store value as key, replacing the previous value (if any).
79 | def force_store(key,value)
80 | @media[key] = value
81 | end
82 |
83 | def load_file(filename)
84 | case File::extname(filename).downcase[1..-1]
85 | when *(@@image_ext)
86 | return load_image(filename)
87 | when *(@@sound_ext)
88 | return load_sound(filename)
89 | else
90 | raise(ArgumentError,"Unrecognized file extension `%s': %s"%
91 | [File::extname(filename), filename])
92 | end
93 | end
94 |
95 | def load_image(filename)
96 | return Rubygame::Surface.load_image(filename)
97 | end
98 |
99 | def load_sound(filename)
100 | return Rubygame::Mixer::Sample.load_audio(filename)
101 | end
102 | end
103 |
104 | end
105 |
--------------------------------------------------------------------------------
/lib/rubygame/mixer.rb:
--------------------------------------------------------------------------------
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 | require "ruby-sdl-ffi/mixer"
22 |
23 | Rubygame::VERSIONS[:sdl_mixer] = SDL::Mixer.Linked_Version.to_ary
24 |
25 | require "rubygame/audio"
26 | require "rubygame/sound"
27 | require "rubygame/music"
28 | require "rubygame/deprecated_mixer"
29 |
--------------------------------------------------------------------------------
/lib/rubygame/named_resource.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3 | # Copyright (C) 2004-2008 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 | module Rubygame
22 |
23 | # NamedResource is a mix-in module to implement a globally-available
24 | # resource table, a @name variable and accessors, and a system for
25 | # automatically loading resources when they are first needed.
26 | #
27 | # This module is used for Rubygame::Music, Rubygame::Sound, and
28 | # Rubygame::Surface. You can use it in your own classes this way:
29 | #
30 | # 1. Do 'include Rubygame::NamedResource' in your class definition.
31 | #
32 | # 2. Set MyClass.autoload_dirs to an Array of directories to look
33 | # for files when autoloading. Tip: use File.join to create
34 | # paths that work on any operating system.
35 | #
36 | # 3. Define #autoload to implement the behavior for your class,
37 | # or leave it as the default if you don't need autoloading.
38 | # See the docs for #autoload for more information.
39 | #
40 | # Here's an example of how you could use this for a class which
41 | # loads maps from a file:
42 | #
43 | # class Map
44 | # include Rubygame::NamedResource
45 | #
46 | # Map.autoload_dirs = [ File.join("maps","world_1"),
47 | # File.join("maps","custom") ]
48 | #
49 | # def autoload( name )
50 | # # Searches autoload_dirs for the file
51 | # path = find_file( name )
52 | #
53 | # if( path )
54 | # return load_map( path )
55 | # else
56 | # return nil
57 | # end
58 | # end
59 | #
60 | # def load_map( path )
61 | # # Your code to do the real loading, then return
62 | # # the created instance of Map class.
63 | # # ...
64 | # return map_instance
65 | # end
66 | # end
67 | #
68 | # Here's an example of how you could then use the Map class:
69 | #
70 | # map = Map["level_1.map"]
71 | #
72 | # if( map )
73 | # start_playing( map )
74 | # else
75 | # raise "Oops! The map file for Level 1 doesn't exist!"
76 | # end
77 | #
78 | module NamedResource
79 |
80 |
81 | # Adds class methods when the NamedResource module is included
82 | # in a class. (Here, we are assuming that the NamedResource
83 | # module was included in a class called MyClass.)
84 | module NamedResourceClassMethods
85 |
86 | # An Array of paths to check for files. See #find_file.
87 | attr_accessor :autoload_dirs
88 |
89 |
90 | # call-seq:
91 | # MyClass[ name ] -> instance or nil
92 | #
93 | # Retrieves an instance of the class from a per-class resource
94 | # table (Hash).
95 | #
96 | # If no object has been saved under the given name, invoke
97 | # #autoload to try to load a new instance, store it in the
98 | # Hash table under this name, and sets the instance's @name
99 | # to this name.
100 | #
101 | def []( name )
102 | result = @resources[name]
103 |
104 | if result.nil?
105 | result = autoload(name)
106 | if result
107 | self[name] = result
108 | result.name = name
109 | end
110 | end
111 |
112 | return result
113 | end
114 |
115 |
116 | # call-seq:
117 | # MyClass[ name ] = instance
118 | #
119 | # Stores an instance of the class in a per-class resource table
120 | # (Hash) for future access. If another object is already stored
121 | # with this name, the old record is lost.
122 | #
123 | # May raise: TypeError, if you try to store anything
124 | # that is not kind of this class.
125 | #
126 | def []=( name, value )
127 | if( value.kind_of? self )
128 | @resources[name] = value
129 | else
130 | raise TypeError, "#{self}#[]= can only store instances of #{self}"
131 | end
132 | end
133 |
134 | # call-seq:
135 | # MyClass.autoload( name ) -> instance or nil
136 | #
137 | # This method is invoked when a non-existing resource is
138 | # accessed with #[]. By default, this method simply returns
139 | # nil, effectively disabling autoloading.
140 | #
141 | # You should override this method in your class to provide
142 | # class-specific loading behavior, or leave it as the default if
143 | # you don't need autoloading. Your method should return either
144 | # an instance of the class, or nil.
145 | #
146 | # NOTE: The #find_file method is useful for getting the full
147 | # path to a file which matches the name. That's what it's there
148 | # for, so you should use it!
149 | #
150 | def autoload( name )
151 | nil
152 | end
153 |
154 |
155 | # call-seq:
156 | # MyClass.basename( path ) -> filename
157 | #
158 | # Returns the basename for the path (i.e. the
159 | # filename without the directory). Same as
160 | # File.basename
161 | #
162 | def basename( path )
163 | File.basename( path )
164 | end
165 |
166 |
167 | # call-seq:
168 | # MyClass.exist?( path ) -> true or false
169 | #
170 | # True if the given path points to a file
171 | # that exists, otherwise false. Same as
172 | # File.exist?
173 | #
174 | def exist?( path )
175 | File.exist?(path)
176 | end
177 |
178 |
179 | # call-seq:
180 | # MyClass.find_file( filename ) -> path or nil
181 | #
182 | # Checks every directory in @autoload_dirs for
183 | # a file with the given name, and returns the
184 | # path (directory and name) for the first match.
185 | #
186 | # If no directories have a file with that name,
187 | # return nil.
188 | #
189 | def find_file( filename )
190 | dir = @autoload_dirs.find { |dir|
191 | exist?( File.join(dir,filename) )
192 | }
193 |
194 | if dir
195 | return File.join(dir,filename)
196 | else
197 | return nil
198 | end
199 | end
200 |
201 | end
202 |
203 |
204 | # Sets up the class when this module is included.
205 | # Adds the class methods and defines class instance
206 | # variables.
207 | def self.included( object ) # :nodoc:
208 |
209 | class << object
210 | include NamedResourceClassMethods
211 | end
212 |
213 | object.instance_eval do
214 | @resources = Hash.new
215 | @autoload_dirs = []
216 | end
217 |
218 | end
219 |
220 |
221 | # Returns the instance's @name. See also #name=.
222 | def name
223 | @name
224 | end
225 |
226 | #
227 | # Sets the instance's @name to the given String, or nil to
228 | # unset the name. See also #name.
229 | #
230 | # NOTE: This does not automatically store the instance in the
231 | # class resource table by name. Use the #[]= class method to do
232 | # that.
233 | #
234 | # The string is dup'ed and frozen before being stored.
235 | #
236 | # May raise: TypeError, if new_name is not a String or nil.
237 | #
238 | def name=( new_name )
239 | if new_name.nil?
240 | return @name = nil
241 | end
242 |
243 | unless new_name.kind_of? String
244 | raise TypeError, "name must be a String (got #{new_name.class})"
245 | end
246 |
247 | @name = new_name.dup
248 | @name.freeze
249 | end
250 |
251 |
252 | end
253 |
254 | end
255 |
--------------------------------------------------------------------------------
/lib/rubygame/shared.rb:
--------------------------------------------------------------------------------
1 | #
2 | # Common / utility methods.
3 | #
4 | #--
5 | #
6 | # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
7 | # Copyright (C) 2009 John Croisant
8 | #
9 | # This library is free software; you can redistribute it and/or
10 | # modify it under the terms of the GNU Lesser General Public
11 | # License as published by the Free Software Foundation; either
12 | # version 2.1 of the License, or (at your option) any later version.
13 | #
14 | # This library is distributed in the hope that it will be useful,
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | # Lesser General Public License for more details.
18 | #
19 | # You should have received a copy of the GNU Lesser General Public
20 | # License along with this library; if not, write to the Free Software
21 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 | #
23 | #++
24 |
25 |
26 | module Rubygame
27 |
28 | class DeprecationError < RuntimeError # :nodoc:
29 | end
30 |
31 | # Warn about a deprecated Rubygame feature. The behavior of this
32 | # method is influenced by the value of ENV["RUBYGAME_DEPRECATED"]:
33 | #
34 | # (default):: Print a warning with Kernel.warn the first time each
35 | # deprecated feature is used. Note that Kernel.warn is
36 | # silent unless warnings are enabled (e.g. -W flag).
37 | #
38 | # "warn":: Print a warning on STDERR the first time each
39 | # deprecated feature is used.
40 | #
41 | # "warn!":: Print a warning on STDERR every time a deprecated
42 | # feature is used.
43 | #
44 | # "error":: Raise Rubygame::DeprecationError the first time each
45 | # deprecated feature is used.
46 | #
47 | # "error!":: Raise Rubygame::DeprecationError every time a
48 | # deprecated feature is used.
49 | #
50 | # "quiet":: Never warn when any deprecated feature is used.
51 | #
52 | def self.deprecated( feature, version=nil, info=nil) # :nodoc:
53 | @deprec_warned ||= {}
54 |
55 | config = ENV["RUBYGAME_DEPRECATED"]
56 | return if /^quiet$/i =~ config
57 |
58 | if( /^(error!|warn!)$/i =~ config || !@deprec_warned[feature] )
59 | message =
60 | "#{feature} is DEPRECATED and will be removed in " +
61 | (version ? "Rubygame #{version}" : "a future version of Rubygame") +
62 | "! " + (info || "Please see the docs for more information.")
63 |
64 | case config
65 | when /^error!?$/i
66 | raise Rubygame::DeprecationError.new(message)
67 | when /^warn!?$/i
68 | STDERR.puts 'warning: ' + message
69 | else
70 | Kernel.warn 'warning: ' + message
71 | end
72 |
73 | @deprec_warned[feature] = true
74 | end
75 |
76 | nil
77 | end
78 |
79 |
80 | # Initialize the SDL video system if necessary.
81 | def self.init_video_system # :nodoc:
82 | if( SDL::WasInit(SDL::INIT_VIDEO) == 0 )
83 | return SDL::Init(SDL::INIT_VIDEO)
84 | else
85 | return 0
86 | end
87 | end
88 |
89 |
90 | # Take nil, an integer, or an Array of integers. Returns an integer.
91 | def self.collapse_flags( flags ) # :nodoc:
92 | case flags
93 | when Array
94 | flags.inject(0){ |mem, flag| mem|flag }
95 | when Numeric
96 | flags
97 | when nil
98 | 0
99 | else
100 | raise( ArgumentError, "Wrong type for flags " +
101 | "(wanted integer, Array, or nil; got #{flags.class})." )
102 | end
103 | end
104 |
105 | end
106 |
--------------------------------------------------------------------------------
/samples/FreeSans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/FreeSans.ttf
--------------------------------------------------------------------------------
/samples/README:
--------------------------------------------------------------------------------
1 | Certain items in this directory are copyrighted works, but the nature
2 | of their media makes inclusion of copyright and licensing information
3 | impossible or inconvenient.
4 |
5 | Copyright and licensing information for those items is included herein
6 | for your convenience.
7 |
8 |
9 | "panda.png" copyright (C) 2004 John Croisant
10 | "ruby.png" copyright (C) 2006 John Croisant
11 | "rubygame.png" copyright (C) 2009 John Croisant
12 | "song.ogg" copyright (C) 1999 Bjorn De Meyer
13 | "term16.png" copyright (C) 2005 John Croisant
14 |
15 |
16 | "panda.png", "ruby.png", "rubygame.png", "song.ogg", and "term16.png"
17 | are licensed under the Creative Commons Attribution-ShareAlike 2.5 License.
18 |
19 | To view a copy of this license, visit
20 |
21 | http://creativecommons.org/licenses/by-sa/2.5/
22 |
23 | or send a letter to:
24 |
25 | Creative Commons,
26 | 543 Howard Street, 5th Floor,
27 | San Francisco, California, 94105, USA.
28 |
29 |
30 |
31 | "FreeSans.ttf" Copyleft 2002, 2003, 2005, 2008, 2009
32 | Free Software Foundation.
33 |
34 | "FreeSans.ttf" is licensed under the GNU General Public License.
35 |
36 | You should have received a copy of the GNU General Public License along with
37 | this program; if not, write to:
38 |
39 | Free Software Foundation, Inc.,
40 | 59 Temple Place, Suite 330,
41 | Boston, MA 02111-1307 USA
42 |
--------------------------------------------------------------------------------
/samples/chimp.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/chimp.bmp
--------------------------------------------------------------------------------
/samples/demo_draw.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # This program is released to the PUBLIC DOMAIN.
4 | # It is distributed in the hope that it will be useful,
5 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
6 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 |
8 | require "rubygame"
9 | include Rubygame
10 |
11 | $stdout.sync = true
12 |
13 | Rubygame.init()
14 |
15 |
16 | # SDL_gfx is required for drawing shapes and rotating/zooming Surfaces.
17 | $gfx_ok = (VERSIONS[:sdl_gfx] != nil)
18 |
19 | unless ( $gfx_ok )
20 | raise "You must have SDL_gfx support to run this demo!"
21 | end
22 |
23 |
24 |
25 | # Set up autoloading for Surfaces. Surfaces will be loaded automatically
26 | # the first time you use Surface["filename"]. Check out the docs for
27 | # Rubygame::NamedResource for more info about that.
28 | #
29 | Surface.autoload_dirs = [ File.dirname(__FILE__) ]
30 |
31 |
32 |
33 | screen = Screen.open([320,240])
34 | screen.title = "Drawing test"
35 |
36 |
37 |
38 | # Make the background surface. We'll draw on this, then blit (copy) it
39 | # onto the screen. We'll also use it as the background for "erasing"
40 | # the pandas from their old positions each frame.
41 | background = Surface.new( screen.size )
42 |
43 |
44 | # Filling with colors in a variety of ways.
45 | # See the Rubygame::Color module for more info.
46 | def fill_background( background )
47 | background.fill( Color::ColorRGB.new([0.1, 0.2, 0.35]) )
48 | background.fill( :black, [70,120,80,80] )
49 | background.fill( "dark red", [80,110,80,80] )
50 | end
51 |
52 |
53 | # Draw a bunch of shapes to try out the drawing methods
54 | def draw_some_shapes( background )
55 | # Create a new surface
56 | a = Surface.new([100,100])
57 |
58 | # Fill it with blue
59 | a.fill([70,70,255])
60 |
61 | # Fill a specific part of it with a different blue
62 | rect1 = Rect.new([3,3,94,94])
63 | a.fill([40,40,150],rect1)
64 |
65 | # Draw a black box with white almost at the edges
66 | a.draw_box_s( [30,30], [70,70], [0,0,0] )
67 | a.draw_box( [31,31], [69,69], [255,255,255] )
68 |
69 | # Draw a circle in the box
70 | a.draw_circle_s( [50,50], 10, [100,150,200] )
71 |
72 | # Two diagonal white lines, the right anti-aliased, the left not
73 | a.draw_line([31,69],[49,31],[255,255,255])
74 | a.draw_line_a([49,31],[69,69],[255,255,255])
75 |
76 | # Finally, blit (copy) this interesting surface onto
77 | # the background image
78 | a.blit(background,[50,50],[0,0,90,80])
79 | end
80 |
81 |
82 | # Draw a filled pentagon with a lighter border
83 | def draw_pentagon( background )
84 | points = [ [50,150], [100,140], [150,160], [120,180], [60,170] ]
85 | background.draw_polygon_s( points, [100,100,100] )
86 | background.draw_polygon_a( points, [200,200,200] )
87 | end
88 |
89 |
90 | # Draw a pepperoni pizza! (Use your imagination...)
91 | def draw_pizza( background )
92 | # Crust
93 | background.draw_arc_s( [250,200], 34, [210,150], [180,130,50])
94 |
95 | # Cheese -- similar to the crust, but different radius and color
96 | background.draw_arc_s( [250,200], 30, [210,150], [230,180,80])
97 |
98 | # Pepperonis
99 | background.draw_circle_s( [240,180], 4, :dark_red )
100 | background.draw_circle_s( [265,185], 4, :dark_red )
101 | background.draw_circle_s( [258,200], 4, :dark_red )
102 | background.draw_circle_s( [240,215], 4, :dark_red )
103 | background.draw_circle_s( [260,220], 4, :dark_red )
104 | end
105 |
106 |
107 | # _Try_ to draw an anti-aliased, solid ellipse, but it doesn't work
108 | # well. If you look closely at the white ellipse, you can see that it
109 | # isn't anti-aliased on the left and right side, and there are some
110 | # black specks on the top and bottom where the two ellipses don't
111 | # quite match.
112 | #
113 | # It sure would be nice if SDL_gfx had anti-aliased solid shapes...
114 | #
115 | def draw_antialiased_filled_ellipse( background )
116 | background.draw_ellipse_s([200,150],[30,25], :beige )
117 | background.draw_ellipse_a([200,150],[30,25], :beige )
118 | end
119 |
120 |
121 | # Render some text with SFont (image-based font)
122 | def render_sfont_text( background )
123 | require "rubygame/sfont"
124 | sfont = SFont.new( Surface["term16.png"] )
125 | result = sfont.render( "This is some SFont text!" )
126 | result.blit( background, [10,10] )
127 | end
128 |
129 |
130 | # Render some text with TTF (vector-based font)
131 | def render_ttf_text( background )
132 | TTF.setup()
133 | ttfont_path = File.join(File.dirname(__FILE__),"FreeSans.ttf")
134 | ttfont = TTF.new( ttfont_path, 20 )
135 |
136 | result = ttfont.render( "This is some TTF text!", true, [250,250,250] )
137 | result.blit( background, [20,200] )
138 | end
139 |
140 |
141 | # Create another surface to test transparency blitting
142 | def do_transparent_blit( background )
143 | b = Surface.new([200,50])
144 | b.fill([150,20,40])
145 | b.set_alpha(123)# approx. half transparent
146 | b.blit(background,[20,40])
147 | end
148 |
149 |
150 | # Call all those functions to draw on the background.
151 | # Try commenting some of these out or reordering them to
152 | # see what happens!
153 |
154 | fill_background( background )
155 | draw_some_shapes( background )
156 | draw_pentagon( background )
157 | draw_pizza( background )
158 | draw_antialiased_filled_ellipse( background )
159 | render_sfont_text( background )
160 | render_ttf_text( background )
161 | do_transparent_blit( background )
162 |
163 |
164 | # Now blit the background onto the screen and update the screen once.
165 | # During the loop, we'll use 'dirty rect' updating to refresh only the
166 | # parts of the screen that have changed.
167 | background.blit(screen,[0,0])
168 |
169 | screen.update()
170 |
171 |
172 |
173 | queue = EventQueue.new()
174 | queue.ignore = [ActiveEvent,MouseMotionEvent,MouseUpEvent,MouseDownEvent]
175 | queue.wait()
176 |
--------------------------------------------------------------------------------
/samples/demo_imagefont.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # encoding: utf-8
3 |
4 |
5 | require "rubygame"
6 | require "rubygame/imagefont"
7 |
8 | include Rubygame
9 |
10 |
11 | class App
12 | def initialize( filename, options={} )
13 | @filename = filename
14 | @basename = File.basename(filename)
15 |
16 | @font = ImageFont.new( Surface.load(@filename) )
17 |
18 | options = {
19 | :padding => 10,
20 | :message => default_message,
21 | :background => [50,50,50],
22 | }.merge(options)
23 |
24 | @message = options[:message]
25 | @padding = options[:padding]
26 | @background = options[:background]
27 |
28 | @screen = _make_screen()
29 | @queue = _make_queue()
30 | @clock = _make_clock()
31 |
32 | redraw()
33 | end
34 |
35 |
36 | def go
37 | catch(:app_quit) do
38 | loop do
39 | step
40 | end
41 | end
42 | end
43 |
44 |
45 | def step
46 | @screen.update()
47 |
48 | @queue.each do |event|
49 | case event
50 | when Events::QuitRequested
51 | quit()
52 | when Events::KeyPressed
53 | case event.key
54 | when :escape
55 | quit()
56 | else
57 | handle_keystroke(event)
58 | end
59 | end
60 | end
61 |
62 | @clock.tick()
63 | end
64 |
65 |
66 | def handle_keystroke(event)
67 | case event.key
68 | when :backspace
69 | self.message = @message[0..-2]
70 | when :return, :keypad_enter
71 | self.message += "\n"
72 | else
73 | unless event.string.empty?
74 | self.message += event.string
75 | end
76 | end
77 | end
78 |
79 |
80 | def redraw
81 | @screen.fill(@background)
82 | @font.render_to(@message, @screen, :offset => [@padding, @padding])
83 | @screen.update
84 | end
85 |
86 |
87 | def message
88 | @message.dup.freeze
89 | end
90 |
91 | def message=( new_message )
92 | # Increase the screen size to fit the new message, if necessary.
93 | new_size = _calculate_screen_size( new_message )
94 | new_size[0] = [new_size[0], @screen.width].max
95 | new_size[1] = [new_size[1], @screen.height].max
96 |
97 | unless new_size == @screen.size
98 | @screen = _make_screen( new_size )
99 | end
100 |
101 | @message = new_message
102 |
103 | redraw()
104 | end
105 |
106 |
107 | def default_message
108 | lines =
109 | ["Font: %s"%@basename,
110 | "",
111 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
112 | "The quick brown fox jumped over the lazy dog.",
113 | ""]
114 |
115 | # Necessary to use Array#each_slice with Ruby 1.8.6.
116 | require 'enumerator'
117 |
118 | # Add all the glyphs in the font, in rows of 32 glyphs.
119 | @font.glyphs.each_slice(32) { |slice|
120 | lines << slice.join('')
121 | }
122 |
123 | lines += ["", "Type on the keyboard to edit this text."]
124 |
125 | return lines.join("\n")
126 | end
127 |
128 |
129 | def quit
130 | throw :app_quit
131 | end
132 |
133 |
134 | private
135 |
136 |
137 | # Calculate how big the screen needs to be to fit the message.
138 | def _calculate_screen_size( message )
139 | w, h = @font.render_size(message)
140 |
141 | w += @padding * 2
142 | h += @padding * 2
143 |
144 | # Make sure it's not a super huge window.
145 | w = 1600 if w > 1600
146 | h = 1000 if h > 1000
147 |
148 | [w,h]
149 | end
150 |
151 |
152 | def _make_screen( size=:auto )
153 | size = _calculate_screen_size(@message) if size == :auto
154 | screen = Screen.new(size)
155 | screen.title = "ImageFont Test (%s)"%@basename
156 | return screen
157 | end
158 |
159 |
160 | def _make_queue
161 | Rubygame.enable_key_repeat
162 | return EventQueue.new { |q|
163 | q.enable_new_style_events
164 | }
165 | end
166 |
167 |
168 | def _make_clock
169 | return Clock.new { |c|
170 | c.calibrate
171 | c.enable_tick_events
172 | c.target_framerate = 30
173 | }
174 | end
175 |
176 | end
177 |
178 |
179 | if ARGV.length < 1
180 | font_name = "term16.png"
181 | puts < 3, :repeats => -1 );
37 | puts('ERROR: Music not fading in') unless mus.fading?(:in)
38 | sleep 3
39 |
40 | puts "Playing for 2 seconds."
41 | sleep 2
42 |
43 | puts "Lowering volume to half for 3 seconds."
44 | mus.volume = 0.5;
45 | puts "ERROR: Volume wasn't adjusted" unless mus.volume == 0.5
46 | sleep 3
47 |
48 | puts "Restoring volume to full."
49 | mus.volume = 1.0;
50 | sleep 2
51 |
52 | puts "Pausing for 1 seconds."
53 | mus.pause
54 | puts "ERROR: Music not paused." unless mus.paused?
55 | sleep 1
56 |
57 | puts "Resuming."
58 | mus.unpause
59 | puts "ERROR: Music not resumed" unless mus.playing?
60 |
61 | puts "Playing for 2 seconds."
62 | sleep 2
63 |
64 | puts "Fading out over 2 seconds."
65 | mus.fade_out(2);
66 | puts "ERROR: Music not fading out " unless mus.fading?(:out)
67 |
68 | while mus.playing? or mus.fading? == :out do Thread.pass end
69 | # Test playing of music to the end
70 |
71 | puts "ERROR: Music not ended" if mus.playing?
72 | end
73 |
74 | music_thread = Thread.new do test_music() end
75 | music_thread.join
76 | Rubygame.quit()
77 |
78 |
--------------------------------------------------------------------------------
/samples/demo_ttf.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # This program is PUBLIC DOMAIN.
4 | # It is distributed in the hope that it will be useful,
5 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
6 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 |
8 | require "rubygame"
9 | include Rubygame
10 | Rubygame.init()
11 |
12 | def test_noaa_nobg(font,screen,y)
13 | puts "No antialiasing, no background..."
14 | text = font.render("No AA, no BG",false,[200,200,200])
15 | text.blit(screen,[0,y])
16 | end
17 |
18 | def test_noaa_bg(font,screen,y)
19 | puts "No antialiasing, background..."
20 | text = font.render("No AA, BG",false,[200,200,200],[0,0,255])
21 | text.blit(screen,[0,y])
22 | end
23 |
24 | def test_aa_nobg(font,screen,y)
25 | puts "Antialiasing, no background..."
26 | text = font.render("AA, no BG",true,[200,200,200])
27 | text.blit(screen,[0,y])
28 | end
29 |
30 | def test_aa_bg(font,screen,y)
31 | puts "Antialiasing, background..."
32 | text = font.render("AA, BG",true,[200,200,200],[0,0,255])
33 | text.blit(screen,[0,y])
34 | end
35 |
36 | def test_bold_noaa(font,screen,y)
37 | puts "Bold, no antialiasing..."
38 | font.bold = true
39 | text = font.render("Bold, no AA",false,[200,200,200])
40 | text.blit(screen,[0,y])
41 | font.bold = false
42 | end
43 |
44 | def test_bold_aa(font,screen,y)
45 | puts "Bold, antialiasing..."
46 | font.bold = true
47 | text = font.render("Bold, AA",true,[200,200,200])
48 | text.blit(screen,[0,y])
49 | font.bold = false
50 | end
51 |
52 | def test_italic_noaa(font,screen,y)
53 | puts "Italic, no antialiasing..."
54 | font.italic = true
55 | text = font.render("Italic, no AA",false,[200,200,200])
56 | text.blit(screen,[0,y])
57 | font.italic = false
58 | end
59 |
60 | def test_italic_aa(font,screen,y)
61 | puts "Italic, antialiasing..."
62 | font.italic = true
63 | text = font.render("Italic, AA",true,[200,200,200])
64 | text.blit(screen,[0,y])
65 | font.italic = false
66 | end
67 |
68 | def test_underline_noaa(font,screen,y)
69 | puts "Underline, no antialiasing..."
70 | font.underline = true
71 | text = font.render("Underline, no AA",false,[200,200,200])
72 | text.blit(screen,[0,y])
73 | font.underline = false
74 | end
75 |
76 | def test_underline_aa(font,screen,y)
77 | puts "Underline, antialiasing..."
78 | font.underline = true
79 | text = font.render("Underline, AA",true,[200,200,200])
80 | text.blit(screen,[0,y])
81 | font.underline = false
82 | end
83 |
84 | def test_bi_noaa(font,screen,y)
85 | puts "Bold, Italic, no antialiasing..."
86 | font.bold = true
87 | font.italic = true
88 | text = font.render("B, I, no AA",false,[200,200,200])
89 | text.blit(screen,[0,y])
90 | font.bold = false
91 | font.italic = false
92 | end
93 |
94 | def test_bu_noaa(font,screen,y)
95 | puts "Bold, Underline, no antialiasing..."
96 | font.bold = true
97 | font.underline = true
98 | text = font.render("B, U, no AA",false,[200,200,200])
99 | text.blit(screen,[0,y])
100 | font.bold = false
101 | font.underline = false
102 | end
103 |
104 | def test_iu_noaa(font,screen,y)
105 | puts "Italic, Underline, no antialiasing..."
106 | font.italic = true
107 | font.underline = true
108 | text = font.render("I, U, no AA",false,[200,200,200])
109 | text.blit(screen,[0,y])
110 | font.italic = false
111 | font.underline = false
112 | end
113 |
114 | def test_bi_aa(font,screen,y)
115 | puts "Bold, Italic, antialiasing..."
116 | font.bold = true
117 | font.italic = true
118 | text = font.render("B, I, AA",true,[200,200,200])
119 | text.blit(screen,[0,y])
120 | font.bold = false
121 | font.italic = false
122 | end
123 |
124 | def test_bu_aa(font,screen,y)
125 | puts "Bold, Underline, antialiasing..."
126 | font.bold = true
127 | font.underline = true
128 | text = font.render("B, U, AA",true,[200,200,200])
129 | text.blit(screen,[0,y])
130 | font.bold = false
131 | font.underline = false
132 | end
133 |
134 | def test_iu_aa(font,screen,y)
135 | puts "Italic, Underline, antialiasing..."
136 | font.italic = true
137 | font.underline = true
138 | text = font.render("I, U, AA",true,[200,200,200])
139 | text.blit(screen,[0,y])
140 | font.italic = false
141 | font.underline = false
142 | end
143 |
144 | def main
145 | screen = Screen.open([300,300])
146 | queue = EventQueue.new()
147 | queue.ignore = SDL_EVENTS - [QuitEvent, KeyDownEvent]
148 |
149 |
150 | unless VERSIONS[:sdl_ttf]
151 | raise "TTF is not usable. Bailing out."
152 | end
153 | TTF.setup()
154 | font = TTF.new("FreeSans.ttf",30)
155 |
156 | skip = font.line_skip()
157 |
158 | screen.fill([30,70,30])
159 | y = -skip
160 | test_noaa_nobg(font,screen,y+=skip)
161 | test_noaa_bg(font,screen,y+=skip)
162 | test_aa_nobg(font,screen,y+=skip)
163 | test_aa_bg(font,screen,y+=skip)
164 | screen.update()
165 |
166 | queue.wait()
167 |
168 | screen.fill([30,70,30])
169 | y = -skip
170 | test_bold_noaa(font,screen,y+=skip)
171 | test_bold_aa(font,screen,y+=skip)
172 | test_italic_noaa(font,screen,y+=skip)
173 | test_italic_aa(font,screen,y+=skip)
174 | test_underline_noaa(font,screen,y+=skip)
175 | test_underline_aa(font,screen,y+=skip)
176 | screen.update()
177 |
178 | queue.wait()
179 |
180 | screen.fill([30,70,30])
181 | y = -skip
182 | test_bi_noaa(font,screen,y+=skip)
183 | test_bi_aa(font,screen,y+=skip)
184 | test_bu_noaa(font,screen,y+=skip)
185 | test_bu_aa(font,screen,y+=skip)
186 | test_iu_noaa(font,screen,y+=skip)
187 | test_iu_aa(font,screen,y+=skip)
188 | screen.update()
189 |
190 | queue.wait()
191 | end
192 |
193 | main()
194 |
195 | Rubygame.quit
196 |
--------------------------------------------------------------------------------
/samples/demo_utf8.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # Original script was contributed by ageldama (Yun, Jonghyouk)
4 |
5 | require 'encoding/character/utf-8'
6 | require 'rubygame'
7 |
8 | # Initialize Rubygame
9 | Rubygame.init
10 | screen = Rubygame::Screen.open([320,200])
11 | queue = Rubygame::EventQueue.new
12 |
13 | # Initialize fonts
14 |
15 | fontname = 'FreeSans.ttf'
16 | str = u'abc123하이~'
17 | if ARGV[0]
18 | if File.exist?(File.expand_path(ARGV[0]))
19 | fontname = File.expand_path(ARGV[0])
20 | str = ARGV[1..-1].join(" ")
21 | else
22 | str = ARGV[0..-1].join(" ")
23 | end
24 | else
25 | puts <= stop_time )
107 |
108 | # Tick the clock. Returns a ClockTicked instance
109 | # telling us how long this frame was.
110 | tick_event = clock.tick
111 |
112 | # Update the Mover.
113 | mover.update( tick_event )
114 |
115 | end
116 |
117 | end
118 |
119 |
120 | main_loop()
121 |
--------------------------------------------------------------------------------
/samples/image_viewer.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # A basic image viewer demo for Rubygame.
4 | #
5 | # Usage: Pass an image file to this script to display it. To quit,
6 | # press Q or Escape, right click, or close the window.
7 | #
8 | # Author: John Croisant
9 | # Date: 2009-10-18
10 | # License: You may use this code however you want. No warranty.
11 | #
12 |
13 |
14 | # Load Rubygame and include Rubygame and Rubygame::Events
15 | # in the current namespace, for convenience.
16 | #
17 | require "rubygame"
18 | include Rubygame
19 | include Rubygame::Events
20 |
21 |
22 | # Initialize Rubygame, and clean up when script exits.
23 | Rubygame.init
24 | at_exit { Rubygame.quit }
25 |
26 |
27 | # Decide which image file to load.
28 | this_dir = File.dirname( __FILE__ )
29 | file = File.expand_path( "rubygame.png", this_dir ) # default file
30 | if ARGV[0]
31 | file = File.expand_path( ARGV[0], this_dir )
32 | else
33 | puts "You can pass an script to this file to load it."
34 | end
35 |
36 |
37 | # Wrap this code in a "begin/rescue" block to recover from errors if
38 | # the image cannot be loaded.
39 | #
40 | begin
41 |
42 | # Load the image
43 | image = Surface.load( file )
44 |
45 | # Open a new Rubygame window to fit the image.
46 | screen = Screen.open( image.size )
47 | screen.title = File.basename(file)
48 |
49 | # Blit ("paste") the image onto the screen.
50 | image.blit( screen, [0,0] )
51 |
52 | rescue SDLError, NoMethodError
53 |
54 | # Oops, load failed.
55 | puts "#{File.basename($0)}: Could not load image: #{file}"
56 |
57 | # Open a new Rubygame window
58 | screen = Screen.open( [200,200] )
59 | screen.title = "Load Error"
60 |
61 | # Fill with white
62 | screen.fill( :white )
63 |
64 | # Thick red line from top left to bottom right.
65 | # Point [0,0] is the top left corner of the screen,
66 | # [200,200] is bottom right.
67 | #
68 | screen.draw_polygon_s( [[ -5, 5], [ 5, -5],
69 | [205, 195], [195, 205]], :red )
70 |
71 | # Now from top right to bottom left.
72 | screen.draw_polygon_s( [[195, -5], [205, 5],
73 | [ 5, 205], [ -5, 195]], :red )
74 |
75 | end
76 |
77 |
78 | # Set up an event handler to listen for events:
79 | #
80 | # - Q or Escape keys press
81 | # - Right mouse click inside the window
82 | # - Window close button press
83 | #
84 | # When any of these events occurs, the "exit_script" method is called.
85 | #
86 | class MyHandler
87 | include Rubygame::EventHandler::HasEventHandler
88 | end
89 |
90 | handler = MyHandler.new
91 | handler.make_magic_hooks( :q => :exit_script,
92 | :escape => :exit_script,
93 | :mouse_right => :exit_script,
94 | QuitRequested => :exit_script )
95 |
96 | def exit_script
97 | exit
98 | end
99 |
100 |
101 | # Repeat this code until the user quits.
102 | loop do
103 |
104 | # Fetch the user input events from SDL.
105 | events = Rubygame::Events.fetch_sdl_events
106 |
107 | # Pass each input to the event handler to check.
108 | events.each do |event|
109 | handler.handle( event )
110 | end
111 |
112 | # Refresh the screen
113 | screen.update
114 |
115 | # Pause for a while before checking for more events.
116 | sleep 0.1
117 |
118 | end
119 |
--------------------------------------------------------------------------------
/samples/load_and_blit.rb:
--------------------------------------------------------------------------------
1 | #/usr/bin/env ruby
2 |
3 | # A very basic sample application.
4 |
5 | require "rubygame"
6 | include Rubygame
7 |
8 | Rubygame.init
9 |
10 | screen = Screen.open([320,240])
11 |
12 | queue = EventQueue.new() {
13 | |q| q.ignore = [MouseMotionEvent, ActiveEvent]
14 | }
15 |
16 | image = Surface.load_image("panda.png")
17 | puts "Size is: [%s,%s]"%image.size
18 | image.blit(screen,[0,0])
19 |
20 | queue.wait() { screen.update() }
21 |
22 | Rubygame.quit
23 |
--------------------------------------------------------------------------------
/samples/palettized.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/palettized.png
--------------------------------------------------------------------------------
/samples/panda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/panda.png
--------------------------------------------------------------------------------
/samples/punch.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/punch.wav
--------------------------------------------------------------------------------
/samples/ruby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/ruby.png
--------------------------------------------------------------------------------
/samples/rubygame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/rubygame.png
--------------------------------------------------------------------------------
/samples/song.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/song.ogg
--------------------------------------------------------------------------------
/samples/term16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/term16.png
--------------------------------------------------------------------------------
/samples/whiff.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/samples/whiff.wav
--------------------------------------------------------------------------------
/spec/audio_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 |
5 |
6 |
7 | #########################
8 | ## ##
9 | ## GENERAL ##
10 | ## ##
11 | #########################
12 |
13 |
14 | describe "Opening audio for the first time" do
15 | after :each do
16 | Rubygame.close_audio
17 | end
18 |
19 | it "should return true" do
20 | Rubygame.open_audio.should be_true
21 | end
22 | end
23 |
24 |
25 | describe "Opening audio when it's already open" do
26 | before :each do
27 | Rubygame.open_audio
28 | end
29 |
30 | after :each do
31 | Rubygame.close_audio
32 | end
33 |
34 | it "should return false" do
35 | Rubygame.open_audio.should be_false
36 | end
37 | end
38 |
39 |
40 | describe "Opening audio that was opened then closed again" do
41 | before :each do
42 | Rubygame.open_audio
43 | Rubygame.close_audio
44 | end
45 |
46 | after :each do
47 | Rubygame.close_audio
48 | end
49 |
50 | it "should return true" do
51 | Rubygame.open_audio.should be_true
52 | end
53 | end
54 |
55 |
56 | describe "Opening audio with invalid argument" do
57 | after :each do
58 | Rubygame.close_audio
59 | end
60 |
61 | it "should raise TypeError" do
62 | lambda{ Rubygame.open_audio(:foo) }.should raise_error(TypeError)
63 | end
64 | end
65 |
66 |
67 | describe "Closing audio that was open" do
68 | before :each do
69 | Rubygame.open_audio
70 | end
71 |
72 | after :each do
73 | Rubygame.close_audio
74 | end
75 |
76 | it "should return true" do
77 | Rubygame.close_audio.should be_true
78 | end
79 | end
80 |
81 |
82 | describe "Closing audio that was not open" do
83 | before :each do
84 | end
85 |
86 | after :each do
87 | Rubygame.close_audio
88 | end
89 |
90 | it "should return false" do
91 | Rubygame.close_audio.should be_false
92 | end
93 | end
94 |
95 |
96 |
97 | #########################
98 | ## ##
99 | ## FREQUENCY ##
100 | ## ##
101 | #########################
102 |
103 |
104 | describe "Opening audio with a valid frequency" do
105 | after :each do
106 | Rubygame.close_audio
107 | end
108 |
109 | it "should not raise an error" do
110 | lambda{ Rubygame.open_audio(:frequency => 44100) }.should_not raise_error
111 | end
112 | end
113 |
114 |
115 | describe "Opening audio with a negative frequency" do
116 | after :each do
117 | Rubygame.close_audio
118 | end
119 |
120 | it "should raise ArgumentError" do
121 | lambda{ Rubygame.open_audio(:frequency => -1) }.should raise_error(ArgumentError)
122 | end
123 | end
124 |
125 |
126 | describe "Opening audio with a frequency of zero" do
127 | after :each do
128 | Rubygame.close_audio
129 | end
130 |
131 | it "should raise ArgumentError" do
132 | lambda{ Rubygame.open_audio(:frequency => 0) }.should raise_error(ArgumentError)
133 | end
134 | end
135 |
136 |
137 |
138 | #########################
139 | ## ##
140 | ## CHANNELS ##
141 | ## ##
142 | #########################
143 |
144 |
145 | describe "Opening audio with 1 channel (mono)" do
146 | after :each do
147 | Rubygame.close_audio
148 | end
149 |
150 | it "should not raise an error" do
151 | lambda{ Rubygame.open_audio(:channels => 1) }.should_not raise_error
152 | end
153 | end
154 |
155 |
156 | describe "Opening audio with 2 channels (stereo)" do
157 | after :each do
158 | Rubygame.close_audio
159 | end
160 |
161 | it "should not raise an error" do
162 | lambda{ Rubygame.open_audio(:channels => 2) }.should_not raise_error
163 | end
164 | end
165 |
166 |
167 | describe "Opening audio with a too-small number of channels" do
168 | after :each do
169 | Rubygame.close_audio
170 | end
171 |
172 | it "should raise ArgumentError" do
173 | lambda{ Rubygame.open_audio(:channels => 0) }.should raise_error(ArgumentError)
174 | end
175 | end
176 |
177 |
178 | describe "Opening audio with a too-large number of channels" do
179 | after :each do
180 | Rubygame.close_audio
181 | end
182 |
183 | it "should raise ArgumentError" do
184 | lambda{ Rubygame.open_audio(:channels => 3) }.should raise_error(ArgumentError)
185 | end
186 | end
187 |
188 |
189 |
190 | #########################
191 | ## ##
192 | ## FREQUENCY ##
193 | ## ##
194 | #########################
195 |
196 |
197 | describe "Opening audio with a valid buffer size" do
198 | after :each do
199 | Rubygame.close_audio
200 | end
201 |
202 | it "should not raise an error" do
203 | lambda{ Rubygame.open_audio(:buffer => 512) }.should_not raise_error
204 | end
205 | end
206 |
207 |
208 | describe "Opening audio with a non-power-of-two buffer size" do
209 | after :each do
210 | Rubygame.close_audio
211 | end
212 |
213 | it "should raise ArgumentError" do
214 | lambda{ Rubygame.open_audio(:buffer => 511) }.should raise_error(ArgumentError)
215 | end
216 | end
217 |
218 |
219 | describe "Opening audio with a negative buffer size" do
220 | after :each do
221 | Rubygame.close_audio
222 | end
223 |
224 | it "should raise ArgumentError" do
225 | lambda{ Rubygame.open_audio(:buffer => -1) }.should raise_error(ArgumentError)
226 | end
227 | end
228 |
229 |
230 | describe "Opening audio with a buffer of zero" do
231 | after :each do
232 | Rubygame.close_audio
233 | end
234 |
235 | it "should raise ArgumentError" do
236 | lambda{ Rubygame.open_audio(:buffer => 0) }.should raise_error(ArgumentError)
237 | end
238 | end
239 |
--------------------------------------------------------------------------------
/spec/clock_spec.rb:
--------------------------------------------------------------------------------
1 | # This is mostly for regression testing and bugfix confirmation at the moment.
2 |
3 |
4 | require 'rubygame'
5 | include Rubygame
6 | include Rubygame::Events
7 |
8 |
9 |
10 | describe Clock do
11 |
12 | before :each do
13 | @clock = Clock.new
14 | end
15 |
16 | after :each do
17 | Rubygame.quit
18 | end
19 |
20 |
21 | it "should have a granularity accessor" do
22 | lambda{@clock.granularity = 5}.should_not raise_error
23 | end
24 |
25 | it "should have a nice accessor" do
26 | lambda{@clock.nice = true}.should_not raise_error
27 | end
28 |
29 |
30 | describe "with target" do
31 |
32 | it "should pass frametime, granularity, and nice to Clock.delay" do
33 | @clock.target_frametime = 1
34 | @clock.granularity = 2
35 | @clock.nice = true
36 |
37 | Clock.should_receive(:delay).with(1,2,true).and_return(1)
38 | @clock.tick
39 | end
40 |
41 | end
42 |
43 |
44 | describe "with tick events" do
45 |
46 | before :each do
47 | @clock.enable_tick_events
48 | end
49 |
50 |
51 | it "should return ClockTicked events" do
52 | @clock.tick.should be_instance_of(ClockTicked)
53 | end
54 |
55 |
56 | it "should cache ClockTicked events" do
57 | Clock.stub!(:delay).and_return(10)
58 | # Make sure they are the same exact object
59 | @clock.tick.should equal(@clock.tick)
60 | end
61 |
62 | end
63 |
64 |
65 | describe "without tick events" do
66 |
67 | it "should return integer ticks" do
68 | @clock.tick.should be_instance_of(Fixnum)
69 | end
70 |
71 | end
72 |
73 | end
74 |
--------------------------------------------------------------------------------
/spec/event_actions_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame
5 | include Rubygame::EventActions
6 |
7 |
8 |
9 | shared_examples_for "an event action" do
10 |
11 | it "should have a #perform method" do
12 | @action.should respond_to(:perform)
13 | end
14 |
15 | it "should take 2 arguments to #perform" do
16 | @action.method(:perform).arity.should == 2
17 | end
18 |
19 | it "should raise error if #perform gets too few arguments" do
20 | lambda { @action.perform(1) }.should raise_error(ArgumentError)
21 | end
22 |
23 | it "should raise error if #perform gets too many arguments" do
24 | lambda { @action.perform(1,2,3) }.should raise_error(ArgumentError)
25 | end
26 |
27 | end
28 |
29 |
30 |
31 |
32 | describe BlockAction do
33 |
34 | before :each do
35 | @owner = mock("owner")
36 | @action = BlockAction.new { |owner,event| owner.foo(event) }
37 | end
38 |
39 | it_should_behave_like "an event action"
40 |
41 | it "should fail on creation if no block is given" do
42 | lambda { BlockAction.new }.should raise_error( ArgumentError )
43 | end
44 |
45 | it "#perform should execute the block" do
46 | @owner.should_receive( :foo ).with( :event )
47 | @action.perform( @owner, :event )
48 | end
49 |
50 | it "should yield 2 parameters (owner and event) to the block" do
51 | @action = BlockAction.new { |owner, event|
52 | owner.should == :owner
53 | event.should == :event
54 | }
55 | @action.perform( :owner, :event )
56 | end
57 |
58 | end
59 |
60 |
61 |
62 |
63 | describe MethodAction do
64 |
65 | before :each do
66 | @owner = mock("owner")
67 | @action = MethodAction.new( :foo )
68 | end
69 |
70 | it_should_behave_like "an event action"
71 |
72 | it "should call the owner's method with the event" do
73 | @owner.should_receive( :foo ).with( :event )
74 | @action.perform( @owner, :event )
75 | end
76 |
77 | describe "with a method that takes no arg" do
78 |
79 | it "should retry with no args" do
80 | @owner.should_receive( :foo ).with( :event ).ordered.and_raise( ArgumentError )
81 | @owner.should_receive( :foo ).with( no_args ).ordered
82 | @action.perform( @owner, :event )
83 | end
84 |
85 | end
86 |
87 | end
88 |
89 |
90 |
91 |
92 | describe MultiAction do
93 |
94 | before :each do
95 | @owner = mock("owner")
96 |
97 | action1 = MethodAction.new( :foo )
98 | action2 = BlockAction.new { |owner,event| owner.bar(event) }
99 | @action = MultiAction.new( action1, action2 )
100 | end
101 |
102 | it_should_behave_like "an event action"
103 |
104 | it "#perform should perform all included actions in order" do
105 | @owner.should_receive( :foo ).with( :event ).ordered
106 | @owner.should_receive( :bar ).with( :event ).ordered
107 | @action.perform( @owner, :event )
108 | end
109 |
110 | end
111 |
--------------------------------------------------------------------------------
/spec/event_hook_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame
5 |
6 |
7 |
8 | describe "EventHook" do
9 |
10 | ##############
11 | # ATTRIBUTES #
12 | ##############
13 |
14 | [:owner, :trigger, :action, :consumes, :active].each do |a|
15 |
16 | it "should have an accessor for @#{a}" do
17 | EventHook.new.should respond_to(a)
18 | EventHook.new.should respond_to("#{a}=".intern)
19 | end
20 |
21 | it "should accept :#{a} at creation" do
22 | e = EventHook.new(a => :value)
23 | e.send(a).should == :value
24 | end
25 |
26 | # Default values for attributes.
27 | # owner, trigger, and action default to nil.
28 | defaults = {:consumes => false, :active => true}
29 |
30 | it "@#{a} should be #{defaults[a].inspect} by default" do
31 | EventHook.new.send(a).should == defaults[a]
32 | end
33 |
34 | it "should allow setting @#{a} post-creation" do
35 | e = EventHook.new
36 | e.send("#{a}=".intern, :value)
37 | e.send(a).should == :value
38 | end
39 |
40 | end
41 |
42 |
43 | ############
44 | # MATCHING #
45 | ############
46 |
47 | it "should have a #match? method" do
48 | EventHook.new.should respond_to(:match?)
49 | end
50 |
51 | it "#match? should take one event" do
52 | lambda { EventHook.new.match?( ) }.should raise_error
53 | lambda { EventHook.new.match?( 1 ) }.should_not raise_error
54 | lambda { EventHook.new.match?( 1, 2 ) }.should raise_error
55 | end
56 |
57 | it "should ask the trigger to see if an event matches" do
58 | trigger = mock("trigger")
59 | trigger.should_receive(:match?).with(:event)
60 | EventHook.new(:trigger => trigger).match?(:event)
61 | end
62 |
63 | it "should match if the event matches the trigger" do
64 | trigger = mock("trigger", :match? => true)
65 | EventHook.new(:trigger => trigger).match?(:event).should be_true
66 | end
67 |
68 | it "should not match if the event does not match the trigger" do
69 | trigger = mock("trigger", :match? => false)
70 | EventHook.new(:trigger => trigger).match?(:event).should be_false
71 | end
72 |
73 | it "should not match if there is no trigger" do
74 | EventHook.new.match?(:event).should be_false
75 | end
76 |
77 | it "should not match if the hook is not active" do
78 | trigger = mock("trigger", :match? => true)
79 | e = EventHook.new(:trigger => trigger, :active => false)
80 | e.match?(:event).should be_false
81 | end
82 |
83 |
84 | ##############
85 | # PERFORMING #
86 | ##############
87 |
88 | it "should have a #perform method" do
89 | EventHook.new.should respond_to(:perform)
90 | end
91 |
92 | it "#perform should take one event" do
93 | lambda { EventHook.new.perform( ) }.should raise_error
94 | lambda { EventHook.new.perform( 1 ) }.should_not raise_error
95 | lambda { EventHook.new.perform( 1, 2 ) }.should raise_error
96 | end
97 |
98 | it "should call the action's #perform with the owner and event" do
99 | action = mock("action")
100 | action.should_receive(:perform).with(:owner, :event)
101 | EventHook.new(:action => action, :owner => :owner).perform(:event)
102 | end
103 |
104 | end
105 |
--------------------------------------------------------------------------------
/spec/event_queue_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame
5 |
6 |
7 |
8 | describe EventQueue do
9 |
10 | before :each do
11 | @queue = EventQueue.new
12 | end
13 |
14 |
15 |
16 | #############
17 | # AUTOFETCH #
18 | #############
19 |
20 | it "autofetch should be on by default" do
21 | @queue.autofetch.should be_true
22 | end
23 |
24 | it "should have autofetch read-write accessors" do
25 | @queue.should respond_to(:autofetch)
26 | @queue.should respond_to(:autofetch=)
27 | end
28 |
29 |
30 |
31 | ########
32 | # EACH #
33 | ########
34 |
35 | it "#each should yield each event in the queue in order" do
36 | collect = []
37 | @queue.push( [1,2,3] )
38 | @queue.each { |e| collect << e}
39 | collect.should == [1,2,3]
40 | end
41 |
42 | it "#each should flush the buffer afterwards" do
43 | @queue.push( [1,2,3] )
44 | @queue.each {}
45 | @queue.should be_empty
46 | end
47 |
48 | it "#each should fetch SDL events if autofetch is on" do
49 | @queue.autofetch = true
50 |
51 | @queue.should_receive(:fetch_sdl_events).and_return([:foo])
52 | @queue.each {}
53 | end
54 |
55 | it "#each should not fetch SDL events if autofetch is off" do
56 | @queue.autofetch = false
57 |
58 | @queue.should_not_receive(:fetch_sdl_events)
59 | @queue.each {}
60 | end
61 |
62 |
63 |
64 | #############
65 | # PEEK EACH #
66 | #############
67 |
68 | it "#peek_each should yield each event in the queue in order" do
69 | collect = []
70 | @queue.push( [1,2,3] )
71 | @queue.peek_each { |e| collect << e}
72 | collect.should == [1,2,3]
73 | end
74 |
75 | it "#peek_each should not flush the buffer afterwards" do
76 | @queue.push( [1,2,3] )
77 | @queue.peek_each {}
78 | @queue.should_not be_empty
79 | end
80 |
81 | it "#peek_each should fetch SDL events if autofetch is on" do
82 | @queue.autofetch = true
83 |
84 | @queue.should_receive(:fetch_sdl_events).and_return([:foo])
85 | @queue.peek_each {}
86 | end
87 |
88 | it "#peek_each should not fetch SDL events if autofetch is off" do
89 | @queue.autofetch = false
90 |
91 | @queue.should_not_receive(:fetch_sdl_events)
92 | @queue.peek_each {}
93 | end
94 |
95 |
96 |
97 | ####################
98 | # FETCH SDL EVENTS #
99 | ####################
100 |
101 | it "should fetch SDL events from the old place by default" do
102 | Rubygame.should_receive(:fetch_sdl_events).and_return([])
103 | @queue.fetch_sdl_events
104 | end
105 |
106 | it "should fetch SDL events from the new place if enabled" do
107 | Rubygame::Events.should_receive(:fetch_sdl_events).and_return([])
108 | @queue.enable_new_style_events
109 | @queue.fetch_sdl_events
110 | end
111 |
112 |
113 |
114 |
115 | ##########
116 | # IGNORE #
117 | ##########
118 |
119 | it "should provide @ignore read-write accessors" do
120 | @queue.should respond_to(:ignore)
121 | @queue.should respond_to(:ignore=)
122 | end
123 |
124 | it "should silently reject pushed objects whose class is ignored" do
125 | @queue.ignore << Fixnum
126 | @queue.push( :foo, 3, :baz )
127 | @queue.to_ary.should == [:foo, :baz]
128 | end
129 |
130 |
131 | ###############
132 | # PUSH / POST #
133 | ###############
134 |
135 | it "should accept pushes" do
136 | @queue.push( :foo )
137 | @queue.to_ary.should == [:foo]
138 | end
139 |
140 | it "should accept multiple pushes at once" do
141 | @queue.push( :foo, :bar, :baz )
142 | @queue.to_ary.should == [:foo, :bar, :baz]
143 | end
144 |
145 | it "should accept a pushed array" do
146 | @queue.push( [:foo, :bar] )
147 | @queue.to_ary.should == [:foo, :bar]
148 | end
149 |
150 | it "should accept posts" do
151 | @queue.post( :foo )
152 | @queue.to_ary.should == [:foo]
153 | end
154 |
155 | it "should accept multiple posts at once" do
156 | @queue.post( :foo, :bar, :baz )
157 | @queue.to_ary.should == [:foo, :bar, :baz]
158 | end
159 |
160 | it "should accept a posted array" do
161 | @queue.post( [:foo, :bar] )
162 | @queue.to_ary.should == [:foo, :bar]
163 | end
164 |
165 | it "should accept <<" do
166 | @queue << :foo
167 | @queue.to_ary.should == [:foo]
168 | end
169 |
170 | end
171 |
--------------------------------------------------------------------------------
/spec/ftor_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame/ftor'
4 | include Rubygame
5 |
6 |
7 |
8 | describe Ftor do
9 |
10 | describe ".new_from_to" do
11 | it "should accept two Ftors" do
12 | lambda {
13 | Ftor.new_from_to( Ftor.new(0,0), Ftor.new(2,0) )
14 | }.should_not raise_error
15 | end
16 |
17 | it "should accept two Arrays" do
18 | lambda {
19 | Ftor.new_from_to( [0,0], [2,0] )
20 | }.should_not raise_error
21 | end
22 |
23 | it "should create an Ftor connecting the points" do
24 | f = Ftor.new_from_to([2,-4],[10,3])
25 | f.x.should == 8
26 | f.y.should == 7
27 | end
28 | end
29 |
30 | end
31 |
--------------------------------------------------------------------------------
/spec/has_event_handler_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame
5 | include Rubygame::EventTriggers
6 | include Rubygame::EventActions
7 |
8 |
9 |
10 | HasEventHandler = Rubygame::EventHandler::HasEventHandler
11 |
12 | class HandledObject
13 | include HasEventHandler
14 | end
15 |
16 |
17 | describe HasEventHandler do
18 |
19 | before :each do
20 | @object = HandledObject.new
21 | @results = []
22 | end
23 |
24 | ###############
25 | # MAGIC HOOKS #
26 | ###############
27 |
28 | it "should have a #make_magic_hooks method" do
29 | @object.should respond_to(:make_magic_hooks)
30 | end
31 |
32 | describe "#make_magic_hooks" do
33 |
34 | it "should accept a hash" do
35 | lambda { @object.make_magic_hooks({}) }.should_not raise_error
36 | end
37 |
38 | it "should reject non-hashes" do
39 | lambda { @object.make_magic_hooks(EventHook.new) }.should raise_error
40 | lambda { @object.make_magic_hooks("string") }.should raise_error
41 | end
42 |
43 | it "should accept a valid hook hash" do
44 | lambda {
45 | @object.make_magic_hooks( { :up => :foo } )
46 | }.should_not raise_error
47 | end
48 |
49 | it "should accept a hook hash with multiple pairs" do
50 | lambda {
51 | @object.make_magic_hooks( { :up => :foo,
52 | :down => :bar,
53 | :mouse_left => :shoot } )
54 | }.should_not raise_error
55 | end
56 |
57 | it "should return an Array of EventHook instances" do
58 | hooks = @object.make_magic_hooks( { :up => :foo,
59 | :down => :bar,
60 | :mouse_left => :shoot } )
61 |
62 | hooks.should be_instance_of(Array)
63 | hooks.each { |hook| hook.should be_instance_of(EventHook) }
64 | end
65 |
66 | ############
67 | # TRIGGERS #
68 | ############
69 |
70 | it "should accept :mouse_* symbol triggers" do
71 | lambda {
72 | @object.make_magic_hooks( { :mouse_left => :foo } )
73 | @object.make_magic_hooks( { :mouse_right => :foo } )
74 | @object.make_magic_hooks( { :mouse_middle => :foo } )
75 | @object.make_magic_hooks( { :mouse_wheel_up => :foo } )
76 | @object.make_magic_hooks( { :mouse_wheel_down => :foo } )
77 | }.should_not raise_error
78 | end
79 |
80 | it "should turn :mouse_* symbols into MousePressTriggers" do
81 | hooks = @object.make_magic_hooks( {:mouse_left => :foo })
82 | hooks[0].trigger.should be_instance_of(MousePressTrigger)
83 | end
84 |
85 | it "should accept keyboard symbol triggers" do
86 | lambda {
87 | @object.make_magic_hooks( { :a => :foo } )
88 | @object.make_magic_hooks( { :up => :foo } )
89 | @object.make_magic_hooks( { :space => :foo } )
90 | @object.make_magic_hooks( { :number1 => :foo } )
91 | }.should_not raise_error
92 | end
93 |
94 | it "should turn keyboard symbols into KeyPressTriggers" do
95 | hooks = @object.make_magic_hooks( {:a => :foo })
96 | hooks[0].trigger.should be_instance_of(KeyPressTrigger)
97 | end
98 |
99 | it "should accept classes as triggers" do
100 | lambda {
101 | @object.make_magic_hooks( { Object => :foo } )
102 | @object.make_magic_hooks( { Events::MousePressed => :foo } )
103 | @object.make_magic_hooks( { Events::WindowResized => :foo } )
104 | }.should_not raise_error
105 | end
106 |
107 | it "should turn classes into InstanceOfTriggers" do
108 | hooks = @object.make_magic_hooks( {Object => :foo })
109 | hooks[0].trigger.should be_instance_of(InstanceOfTrigger)
110 | end
111 |
112 | it "should turn :tick into TickTrigger" do
113 | hooks = @object.make_magic_hooks( {:tick => :foo })
114 | hooks[0].trigger.should be_instance_of(TickTrigger)
115 | end
116 |
117 | it "should accept objects with #match? as triggers" do
118 | fake_trigger = Object.new
119 | class << fake_trigger; def match?; end; end
120 |
121 | lambda {
122 | @object.make_magic_hooks( { fake_trigger => :foo } )
123 | }.should_not raise_error
124 | end
125 |
126 | it "should use a dup of #match? triggers" do
127 | class FakeTrigger; def match?; end; end
128 | fake_trigger = FakeTrigger.new
129 |
130 | hooks = @object.make_magic_hooks( { fake_trigger => :foo } )
131 |
132 | hooks[0].trigger.should be_instance_of(FakeTrigger)
133 | hooks[0].trigger.should_not eql(fake_trigger)
134 | end
135 |
136 | it "should not accept invalid triggers" do
137 | lambda {
138 | @object.make_magic_hooks( { Object.new => :foo } )
139 | }.should raise_error(ArgumentError)
140 |
141 | lambda {
142 | @object.make_magic_hooks( { "string" => :foo } )
143 | }.should raise_error(ArgumentError)
144 |
145 | lambda {
146 | @object.make_magic_hooks( { 1 => :foo } )
147 | }.should raise_error(ArgumentError)
148 | end
149 |
150 |
151 | ###########
152 | # ACTIONS #
153 | ###########
154 |
155 | it "should accept method name symbol actions" do
156 | lambda {
157 | @object.make_magic_hooks( { :up => :foo } )
158 | }.should_not raise_error
159 | end
160 |
161 | it "should turn method names into MethodActions" do
162 | hooks = @object.make_magic_hooks( { :up => :foo } )
163 | hooks[0].action.should be_instance_of(MethodAction)
164 | end
165 |
166 | it "should accept Proc actions" do
167 | lambda {
168 | @object.make_magic_hooks( { :up => Proc.new { |o,e| :foo } } )
169 | }.should_not raise_error
170 | end
171 |
172 | it "should turn Procs into BlockActions" do
173 | hooks = @object.make_magic_hooks( { :up => Proc.new { |o,e| :foo } } )
174 | hooks[0].action.should be_instance_of(BlockAction)
175 | end
176 |
177 | it "should accept detached method actions" do
178 | lambda {
179 | @object.make_magic_hooks( { :up => Object.new.method(:to_s) } )
180 | }.should_not raise_error
181 | end
182 |
183 | it "should turn detached ethods into BlockActions" do
184 | hooks = @object.make_magic_hooks( { :up => Object.new.method(:to_s) } )
185 | hooks[0].action.should be_instance_of(BlockAction)
186 | end
187 |
188 | it "should accept objects with #perform as actions" do
189 | fake_action = Object.new
190 | class << fake_action; def perform; end; end
191 |
192 | lambda {
193 | @object.make_magic_hooks( { :up => fake_action } )
194 | }.should_not raise_error
195 | end
196 |
197 | it "should use a dup of #perform actions" do
198 | class FakeAction; def perform; end; end
199 | fake_action = FakeAction.new
200 |
201 | hooks = @object.make_magic_hooks( { :up => fake_action } )
202 |
203 | hooks[0].action.should be_instance_of(FakeAction)
204 | hooks[0].action.should_not eql(fake_action)
205 | end
206 |
207 | it "should not accept invalid actions" do
208 | lambda {
209 | @object.make_magic_hooks( { :up => Object.new } )
210 | }.should raise_error(ArgumentError)
211 |
212 | lambda {
213 | @object.make_magic_hooks( { :up => "string" } )
214 | }.should raise_error(ArgumentError)
215 |
216 | lambda {
217 | @object.make_magic_hooks( { :up => 1 } )
218 | }.should raise_error(ArgumentError)
219 | end
220 |
221 | end
222 |
223 |
224 | describe "#make_magic_hooks_for" do
225 |
226 | it "should use the given owner" do
227 | hooks = @object.make_magic_hooks_for( :owner, {:a => :foo } )
228 | hooks[0].owner.should == :owner
229 | end
230 |
231 | end
232 |
233 |
234 | # Regression test
235 | it "#handle should not eat NoMethodErrors" do
236 | @object.make_magic_hooks( :a => proc{ bad_method_call() } )
237 | lambda {
238 | @object.handle( Events::KeyPressed.new(:a) )
239 | }.should raise_error(NoMethodError)
240 | end
241 |
242 | end
243 |
--------------------------------------------------------------------------------
/spec/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/spec/image.png
--------------------------------------------------------------------------------
/spec/image_8bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/spec/image_8bit.png
--------------------------------------------------------------------------------
/spec/keyboard_events_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame::Events
5 |
6 |
7 |
8 | shared_examples_for "a keyboard event" do
9 |
10 | it "should have a key symbol" do
11 | @event.key.should == :a
12 | end
13 |
14 | it "should complain if key symbol is not a symbol" do
15 | lambda { @event.class.new( 4 ) }.should raise_error(ArgumentError)
16 | end
17 |
18 | it "should have an array of modifiers" do
19 | @event.modifiers.should == [:shift]
20 | end
21 |
22 | it "should complain if modifiers is not Array-like" do
23 | lambda { @event.class.new( :a, 4 ) }.should raise_error
24 | end
25 |
26 | it "modifiers should be frozen" do
27 | @event.modifiers.should be_frozen
28 | end
29 |
30 | it "should not freeze the original modifiers Array" do
31 | mods = [:shift]
32 | @event.class.new( :a, mods )
33 | mods.should_not be_frozen
34 | end
35 |
36 | end
37 |
38 |
39 |
40 | describe KeyPressed do
41 |
42 | before :each do
43 | @event = KeyPressed.new( :a, [:shift], "A" )
44 | end
45 |
46 | it_should_behave_like "a keyboard event"
47 |
48 | it "should have a string" do
49 | @event.string.should == "A"
50 | end
51 |
52 | it "should complain if string is not String-like" do
53 | lambda {@event.class.new( :a, [:shift], 4 )}.should raise_error
54 | end
55 |
56 | it "string should be frozen" do
57 | @event.string.should be_frozen
58 | end
59 |
60 | end
61 |
62 |
63 | describe KeyReleased do
64 |
65 | before :each do
66 | @event = KeyReleased.new( :a, [:shift] )
67 | end
68 |
69 | it_should_behave_like "a keyboard event"
70 |
71 | end
72 |
73 |
74 |
75 | describe "Rubygame.pressed_keys" do
76 |
77 | # Helper method to make an Array like would be returned from
78 | # SDL.GetKeyState. If you pass SDL::K_* constants to this method,
79 | # they will be marked as "pressed" in the array.
80 | #
81 | def mock_keys( *pressed )
82 | keys = Array.new(SDL::K_LAST, 0)
83 | pressed.each{ |key| keys[key] = 1 }
84 | keys
85 | end
86 |
87 | it "should query SDL.GetKeyState" do
88 | SDL.should_receive(:GetKeyState).and_return( mock_keys() )
89 | Rubygame.pressed_keys
90 | end
91 |
92 | it "should return an empty hash when no keys are pressed" do
93 | SDL.stub(:GetKeyState){ mock_keys() }
94 | Rubygame.pressed_keys.should == {}
95 | end
96 |
97 | it "should have a pair for every pressed key" do
98 | SDL.stub(:GetKeyState){ mock_keys( SDL::K_a, SDL::K_LCTRL ) }
99 | keys = Rubygame.pressed_keys
100 | keys.should have_key( :a )
101 | keys.should have_key( :left_ctrl )
102 | end
103 |
104 | it "should have a value of true for every pressed key" do
105 | SDL.stub(:GetKeyState){ mock_keys( SDL::K_a, SDL::K_LCTRL ) }
106 | keys = Rubygame.pressed_keys
107 | keys[:a].should be_true
108 | keys[:left_ctrl].should be_true
109 | end
110 |
111 | it "should have a falsey value for non-pressed keys" do
112 | SDL.stub(:GetKeyState){ mock_keys( SDL::K_a, SDL::K_LCTRL ) }
113 | keys = Rubygame.pressed_keys
114 | keys[:b].should satisfy{ |v| not v }
115 | keys[:left_shift].should satisfy{ |v| not v }
116 | end
117 |
118 | end
119 |
--------------------------------------------------------------------------------
/spec/misc_events_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame::Events
5 |
6 |
7 |
8 | shared_examples_for "a simple event" do
9 |
10 | it "should take zero arguments at creation" do
11 | lambda { @class.new }.should_not raise_error
12 | lambda { @class.new(:foo) }.should raise_error
13 | end
14 |
15 | end
16 |
17 |
18 |
19 | describe InputFocusGained do
20 | before :each do
21 | @class = InputFocusGained
22 | end
23 |
24 | it_should_behave_like "a simple event"
25 | end
26 |
27 | describe InputFocusLost do
28 | before :each do
29 | @class = InputFocusLost
30 | end
31 |
32 | it_should_behave_like "a simple event"
33 | end
34 |
35 |
36 |
37 | describe MouseFocusGained do
38 | before :each do
39 | @class = MouseFocusGained
40 | end
41 |
42 | it_should_behave_like "a simple event"
43 | end
44 |
45 | describe MouseFocusLost do
46 | before :each do
47 | @class = MouseFocusLost
48 | end
49 |
50 | it_should_behave_like "a simple event"
51 | end
52 |
53 |
54 |
55 | describe WindowMinimized do
56 | before :each do
57 | @class = WindowMinimized
58 | end
59 |
60 | it_should_behave_like "a simple event"
61 | end
62 |
63 | describe WindowUnminimized do
64 | before :each do
65 | @class = WindowUnminimized
66 | end
67 |
68 | it_should_behave_like "a simple event"
69 | end
70 |
71 |
72 |
73 | describe WindowExposed do
74 | before :each do
75 | @class = WindowExposed
76 | end
77 |
78 | it_should_behave_like "a simple event"
79 | end
80 |
81 |
82 |
83 | describe QuitRequested do
84 | before :each do
85 | @class = QuitRequested
86 | end
87 |
88 | it_should_behave_like "a simple event"
89 | end
90 |
91 |
92 |
93 |
94 | describe WindowResized do
95 |
96 | it "should have a size" do
97 | WindowResized.new([20,20]).should respond_to(:size)
98 | end
99 |
100 | it "should accept an [x,y] Array as size" do
101 | lambda { WindowResized.new([20,20]) }.should_not raise_error(ArgumentError)
102 | end
103 |
104 | it "should reject negative sizes" do
105 | lambda { WindowResized.new([-20, 20]) }.should raise_error(ArgumentError)
106 | lambda { WindowResized.new([ 20,-20]) }.should raise_error(ArgumentError)
107 | lambda { WindowResized.new([-20,-20]) }.should raise_error(ArgumentError)
108 | end
109 |
110 | it "should reject size zero" do
111 | lambda { WindowResized.new([ 0, 20]) }.should raise_error(ArgumentError)
112 | lambda { WindowResized.new([ 20, 0]) }.should raise_error(ArgumentError)
113 | lambda { WindowResized.new([ 0, 0]) }.should raise_error(ArgumentError)
114 | end
115 |
116 | it "should reject non-Array-like objects as size" do
117 | lambda { WindowResized.new( 20 ) }.should raise_error(NoMethodError)
118 | lambda { WindowResized.new( :foo ) }.should raise_error(NoMethodError)
119 | lambda { WindowResized.new( "blue" ) }.should raise_error(NoMethodError)
120 | end
121 |
122 | it "should reject sizes with wrong number of elements" do
123 | lambda { WindowResized.new([ ]) }.should raise_error(ArgumentError)
124 | lambda { WindowResized.new([ 20 ]) }.should raise_error(ArgumentError)
125 | lambda { WindowResized.new([ 20,20,20 ]) }.should raise_error(ArgumentError)
126 | end
127 |
128 | it "size should be read-only" do
129 | WindowResized.new([20,20]).should_not respond_to(:size=)
130 | end
131 |
132 | it "size should be frozen" do
133 | WindowResized.new([20,20]).size.should be_frozen
134 | end
135 |
136 | it "should not freeze the original Array passed as size" do
137 | a = [20,20]
138 | WindowResized.new(a)
139 | a.should_not be_frozen
140 | end
141 |
142 | end
143 |
--------------------------------------------------------------------------------
/spec/mouse_events_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame'
4 | include Rubygame::Events
5 |
6 |
7 |
8 | shared_examples_for "a mouse button event" do
9 |
10 | it "should have a button symbol" do
11 | @event.button.should == :mouse_left
12 | end
13 |
14 | it "should complain if button symbol is not a symbol" do
15 | lambda { @event.class.new(4) }.should raise_error(ArgumentError)
16 | end
17 |
18 | it "should complain if button symbol is omitted" do
19 | lambda { @event.class.new }.should raise_error(ArgumentError)
20 | end
21 |
22 | it "button symbol should be read-only" do
23 | @event.should_not respond_to(:button=)
24 | end
25 |
26 |
27 |
28 | it "should have a position" do
29 | @event.pos.should == [1,2]
30 | end
31 |
32 | it "should complain if position isn't Array-like" do
33 | lambda { @event.class.new(4,:mouse_left) }.should raise_error
34 | end
35 |
36 | it "should complain if position is omitted" do
37 | lambda { @event.class.new(:mouse_left) }.should raise_error(ArgumentError)
38 | end
39 |
40 | it "position should be read-only" do
41 | @event.should_not respond_to(:pos=)
42 | end
43 |
44 | it "position should be frozen" do
45 | @event.pos.should be_frozen
46 | end
47 |
48 | it "should not freeze the original position Array" do
49 | a = [0,0]
50 | @event.class.new(a, :mouse_left)
51 | a.should_not be_frozen
52 | end
53 |
54 | end
55 |
56 |
57 |
58 | describe MousePressed do
59 |
60 | before :each do
61 | @event = MousePressed.new( [1,2], :mouse_left )
62 | end
63 |
64 | it_should_behave_like "a mouse button event"
65 |
66 | end
67 |
68 |
69 |
70 | describe MouseReleased do
71 |
72 | before :each do
73 | @event = MouseReleased.new( [1,2], :mouse_left )
74 | end
75 |
76 | it_should_behave_like "a mouse button event"
77 |
78 | end
79 |
80 |
81 |
82 | describe MouseMoved do
83 |
84 | before :each do
85 | @event = MouseMoved.new( [1,2], [3,4], [:mouse_left] )
86 | end
87 |
88 | it "should have a position" do
89 | @event.pos.should == [1,2]
90 | end
91 |
92 | it "should complain if position is not Array-like" do
93 | lambda { @event.class.new( 4, [3,4] ) }.should raise_error
94 | end
95 |
96 | it "should complain if position is omitted" do
97 | lambda { @event.class.new() }.should raise_error(ArgumentError)
98 | end
99 |
100 | it "position should be frozen" do
101 | @event.pos.should be_frozen
102 | end
103 |
104 | it "should not freeze the original position Array" do
105 | a = [0,0]
106 | @event.class.new(a, [3,4])
107 | a.should_not be_frozen
108 | end
109 |
110 |
111 |
112 | it "should have a relative movement" do
113 | @event.rel.should == [3,4]
114 | end
115 |
116 | it "should complain if relative movement is not Array-like" do
117 | lambda { @event.class.new( [1,2], 4 ) }.should raise_error
118 | end
119 |
120 | it "should complain if relative movement is omitted" do
121 | lambda { @event.class.new( [1,2] ) }.should raise_error(ArgumentError)
122 | end
123 |
124 | it "relative movement should be frozen" do
125 | @event.rel.should be_frozen
126 | end
127 |
128 | it "should not freeze the original relative movement Array" do
129 | a = [0,0]
130 | @event.class.new([1,2], a)
131 | a.should_not be_frozen
132 | end
133 |
134 |
135 |
136 | it "should have an array of held buttons" do
137 | @event.buttons.should == [:mouse_left]
138 | end
139 |
140 | it "should complain if held buttons is not Array-like" do
141 | lambda { @event.class.new( [1,2], [3,4], 4 ) }.should raise_error
142 | end
143 |
144 | it "should have no held buttons if omitted" do
145 | @event = MouseMoved.new( [1,2], [3,4] )
146 | @event.buttons.should == []
147 | end
148 |
149 | it "buttons should be frozen" do
150 | @event.buttons.should be_frozen
151 | end
152 |
153 | it "should not freeze the original buttons Array" do
154 | a = [:mouse_left]
155 | @event.class.new([1,2], [3,4], a)
156 | a.should_not be_frozen
157 | end
158 |
159 | end
160 |
--------------------------------------------------------------------------------
/spec/named_resource_spec.rb:
--------------------------------------------------------------------------------
1 |
2 |
3 | require 'rubygame/named_resource'
4 | include Rubygame
5 |
6 | TEST_DIR = File.dirname(__FILE__)
7 |
8 |
9 |
10 | describe NamedResource do
11 |
12 |
13 | describe "instance names" do
14 | before :each do
15 | @class = Class.new {
16 | include NamedResource
17 |
18 | def initialize( name=nil )
19 | self.name = name
20 | end
21 |
22 | def to_s
23 | "#"
24 | end
25 | alias :inspect :to_s
26 | }
27 |
28 | @resource = @class.new( "my_name" )
29 | end
30 |
31 | it "should have a name" do
32 | @resource.name.should == "my_name"
33 | end
34 |
35 | it "name string should be frozen" do
36 | @resource.name.should be_frozen
37 | end
38 |
39 | it "should be able to set name" do
40 | @resource.name = "new_name"
41 | @resource.name.should == "new_name"
42 | end
43 |
44 | it "should reject non-string names" do
45 | lambda { @resource.name = ["foo"] }.should raise_error(TypeError)
46 | end
47 | end
48 |
49 |
50 | describe "resource table" do
51 |
52 | describe "general" do
53 | before :each do
54 | @class = Class.new {
55 | include NamedResource
56 |
57 | class << self
58 | attr_accessor :resources
59 | end
60 |
61 | def to_s
62 | "#"
63 | end
64 | alias :inspect :to_s
65 | }
66 |
67 | @instance = @class.new
68 | @class.resources["foo"] = @instance
69 | end
70 |
71 | it "should be able to get basename a name from a filename" do
72 | @class.basename("/foo/bar/baz.ext").should == "baz.ext"
73 | end
74 |
75 | it "should return object with registered name" do
76 | @class["foo"].should == @instance
77 | end
78 |
79 | it "should be able to register an object by name" do
80 | @class["bar"] = @instance
81 | @class["bar"].should == @instance
82 | end
83 |
84 | it "should only allow registering instances of that class" do
85 | lambda { @class["bar"] = 3 }.should raise_error(TypeError)
86 | end
87 | end
88 |
89 |
90 | describe "without autoload" do
91 | before :each do
92 | @class = Class.new {
93 | include NamedResource
94 |
95 | class << self
96 | attr_accessor :resources
97 | end
98 |
99 | def to_s
100 | "#"
101 | end
102 | alias :inspect :to_s
103 | }
104 | end
105 |
106 | it "should return nil for unregistered names" do
107 | @class["unassigned"].should be_nil
108 | end
109 | end
110 |
111 |
112 | describe "with autoload" do
113 | before :each do
114 | @class = Class.new {
115 | include NamedResource
116 |
117 | class << self
118 | attr_accessor :resources
119 |
120 | def autoload( name )
121 | instance = self.new
122 | return instance
123 | end
124 | end
125 |
126 | attr_accessor :name
127 |
128 | def to_s
129 | "#"
130 | end
131 | alias :inspect :to_s
132 | }
133 | end
134 |
135 | it "should autoload unregistered names" do
136 | instance = @class["bar"]
137 | instance.name.should == "bar"
138 | instance.should be_instance_of(@class)
139 | end
140 |
141 | it "should save autoloaded instances" do
142 | @class.resources["bar"].should be_nil
143 | instance = @class["bar"]
144 | @class.resources["bar"].should == instance
145 | end
146 |
147 | it "should set the name of autoloaded instances" do
148 | @class["bar"].name.should == "bar"
149 | end
150 | end
151 |
152 |
153 | describe "autoload paths" do
154 | before :each do
155 | @class = Class.new {
156 | include NamedResource
157 |
158 | class << self
159 | attr_accessor :resources
160 |
161 | def autoload( name )
162 | path = find_file( name )
163 | if path
164 | instance = self.new
165 | instance.path = path
166 | return instance
167 | end
168 | end
169 |
170 | # Fake check to see if file exists
171 | def exist?( path )
172 | if( path == File.join("foo","bar") or
173 | path == File.join("moo","bar") )
174 | true
175 | else
176 | false
177 | end
178 | end
179 | end
180 |
181 | attr_accessor :name, :path
182 |
183 | def to_s
184 | "#"
185 | end
186 | alias :inspect :to_s
187 | }
188 |
189 | @some_dirs = [ "hoo", "woo", "foo", "moo" ]
190 | end
191 |
192 | it "should have an accessor for @autoload_paths" do
193 | @class.autoload_dirs.should == []
194 | @class.autoload_dirs.push("foo")
195 | @class.autoload_dirs.should == ["foo"]
196 | end
197 |
198 | it "should use the first path which succeeds" do
199 | @class.autoload_dirs = @some_dirs
200 | @class["bar"].path.should == File.join("foo","bar")
201 | end
202 |
203 | it "should return nil if no path succeeds" do
204 | @class.autoload_dirs = @some_dirs
205 | @class["nothing"].should be_nil
206 | end
207 |
208 | end
209 |
210 | end
211 | end
212 |
--------------------------------------------------------------------------------
/spec/short.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jacius/rubygame/9d0d5dca83bb4427386cb1d70da3f8bdf26e9e19/spec/short.ogg
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 |
2 | # Prefer to load from ../lib before the system paths.
3 | $:.unshift File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
4 |
5 | ENV["RUBYGAME_DEPRECATED"] = "quiet"
6 |
--------------------------------------------------------------------------------