ruby-sfml 3.0.0.6 → 3.0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rdoc_options +44 -0
- data/CHANGELOG.md +40 -3
- data/README.md +71 -25
- data/lib/sfml/app.rb +5 -0
- data/lib/sfml/assets.rb +2 -0
- data/lib/sfml/audio/listener.rb +7 -0
- data/lib/sfml/audio/music.rb +51 -0
- data/lib/sfml/audio/sound.rb +41 -0
- data/lib/sfml/audio/sound_buffer.rb +4 -0
- data/lib/sfml/audio/sound_buffer_recorder.rb +2 -0
- data/lib/sfml/audio/sound_cone.rb +1 -0
- data/lib/sfml/audio/sound_recorder.rb +5 -0
- data/lib/sfml/audio/sound_stream.rb +46 -0
- data/lib/sfml/graphics/animation.rb +10 -0
- data/lib/sfml/graphics/blend_mode.rb +1 -0
- data/lib/sfml/graphics/circle_shape.rb +16 -0
- data/lib/sfml/graphics/color.rb +31 -0
- data/lib/sfml/graphics/convex_shape.rb +9 -0
- data/lib/sfml/graphics/font.rb +2 -0
- data/lib/sfml/graphics/image.rb +2 -0
- data/lib/sfml/graphics/particle_system.rb +5 -0
- data/lib/sfml/graphics/rectangle_shape.rb +11 -0
- data/lib/sfml/graphics/render_target.rb +1 -0
- data/lib/sfml/graphics/render_texture.rb +7 -0
- data/lib/sfml/graphics/render_window.rb +26 -0
- data/lib/sfml/graphics/shape.rb +5 -0
- data/lib/sfml/graphics/shape_inspectable.rb +2 -0
- data/lib/sfml/graphics/sprite.rb +4 -0
- data/lib/sfml/graphics/sprite_sheet.rb +2 -0
- data/lib/sfml/graphics/stencil_mode.rb +1 -0
- data/lib/sfml/graphics/text.rb +19 -0
- data/lib/sfml/graphics/texture.rb +5 -0
- data/lib/sfml/graphics/texture_atlas.rb +2 -0
- data/lib/sfml/graphics/transform.rb +2 -0
- data/lib/sfml/graphics/transformable.rb +12 -0
- data/lib/sfml/graphics/vertex_array.rb +18 -0
- data/lib/sfml/graphics/vertex_buffer.rb +4 -0
- data/lib/sfml/graphics/view.rb +5 -0
- data/lib/sfml/network/ftp.rb +34 -0
- data/lib/sfml/network/http.rb +1 -0
- data/lib/sfml/network/ip_address.rb +1 -0
- data/lib/sfml/network/packet.rb +28 -0
- data/lib/sfml/network/socket_selector.rb +1 -0
- data/lib/sfml/network/tcp_listener.rb +3 -0
- data/lib/sfml/network/tcp_socket.rb +4 -0
- data/lib/sfml/network/udp_socket.rb +3 -0
- data/lib/sfml/scene.rb +2 -0
- data/lib/sfml/system/clock.rb +1 -0
- data/lib/sfml/system/rect.rb +27 -5
- data/lib/sfml/system/time.rb +22 -2
- data/lib/sfml/system/vector2.rb +42 -2
- data/lib/sfml/system/vector3.rb +45 -2
- data/lib/sfml/version.rb +1 -1
- data/lib/sfml/window/clipboard.rb +1 -0
- data/lib/sfml/window/context_settings.rb +1 -0
- data/lib/sfml/window/event.rb +2 -0
- data/lib/sfml/window/joystick.rb +3 -0
- data/lib/sfml/window/sensor.rb +1 -0
- data/lib/sfml/window/video_mode.rb +2 -0
- data/lib/sfml/window/window.rb +12 -0
- data/ruby-sfml.gemspec +6 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a12ef598ae1b1dc8e541b0e3f463ec05208391202d465a5cd5360ae473be321
|
|
4
|
+
data.tar.gz: 6830ae6b0a231203e36d104a81caeb3cdcee03f706728cf2af935596f19783aa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd3caad7ec21d3408d86c973a3f0430408cfda54cb363664fbe6af319e11922740a52fde36290124ef3f591c87fbf70f0dfe2085dd3590e63dba51a54e392567
|
|
7
|
+
data.tar.gz: 41fee62ce46c0e69ee80521f51752309aa4b47bc82021d472f5370dad88dc28735549ee33563352938b2edd1f9f2e9fdbf25b611c33ccc01802b8a88acd2e9a5
|
data/.rdoc_options
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
# RDoc project config. Read by both `rake rdoc` (via RDoc::Task) and
|
|
3
|
+
# the standalone `rdoc` CLI — the docs-site repo invokes `rdoc`
|
|
4
|
+
# directly, so all the user-facing knobs live here, not in Rakefile.
|
|
5
|
+
|
|
6
|
+
# Page rendered as the doc-site root.
|
|
7
|
+
main_page: README.md
|
|
8
|
+
title: ruby-sfml — modern Ruby bindings for SFML 3.x
|
|
9
|
+
|
|
10
|
+
# README + LICENSE + CHANGELOG are markdown; assume the same dialect
|
|
11
|
+
# in source-file comments.
|
|
12
|
+
markup: markdown
|
|
13
|
+
|
|
14
|
+
# `doc/` matches RDoc's default output dir.
|
|
15
|
+
output: doc
|
|
16
|
+
|
|
17
|
+
# Visibility filter: public API only. Internal `_method` helpers and
|
|
18
|
+
# the FFI plumbing under `SFML::C::*` add noise without value.
|
|
19
|
+
visibility: public
|
|
20
|
+
|
|
21
|
+
# What gets parsed. Skip the C-bindings module entirely; including
|
|
22
|
+
# them would document every `attach_function` and drown the API user.
|
|
23
|
+
exclude:
|
|
24
|
+
- lib/sfml/c.rb
|
|
25
|
+
- lib/sfml/c/
|
|
26
|
+
- ext/
|
|
27
|
+
- spec/
|
|
28
|
+
- examples/
|
|
29
|
+
- pkg/
|
|
30
|
+
- doc/
|
|
31
|
+
- vendor/
|
|
32
|
+
|
|
33
|
+
# Surface non-source pages as a "Pages" sidebar entry.
|
|
34
|
+
files:
|
|
35
|
+
- README.md
|
|
36
|
+
- CHANGELOG.md
|
|
37
|
+
- LICENSE.txt
|
|
38
|
+
- lib/
|
|
39
|
+
|
|
40
|
+
# Cosmetic.
|
|
41
|
+
template: darkfish
|
|
42
|
+
charset: UTF-8
|
|
43
|
+
line_numbers: false
|
|
44
|
+
show_hash: false
|
data/CHANGELOG.md
CHANGED
|
@@ -6,8 +6,48 @@ versioning is [described in the README](README.md#versioning) — first
|
|
|
6
6
|
three segments mirror the targeted CSFML release, fourth segment is
|
|
7
7
|
ruby-sfml's own patch level.
|
|
8
8
|
|
|
9
|
+
HTML API docs: <https://ruby-sfml-doc.netlify.app/>
|
|
10
|
+
|
|
9
11
|
## [Unreleased]
|
|
10
12
|
|
|
13
|
+
## [3.0.0.7] — 2026-05-12
|
|
14
|
+
|
|
15
|
+
Documentation pass. Every public class / module / method now
|
|
16
|
+
carries at least a one-line RDoc comment — coverage went from
|
|
17
|
+
~36% (`rake rdoc:coverage`) to ~68%. Pair this release with the
|
|
18
|
+
new docs site at <https://ruby-sfml-doc.netlify.app/>.
|
|
19
|
+
|
|
20
|
+
### Changed — documentation
|
|
21
|
+
|
|
22
|
+
- Hand-written, context-aware docstrings on the value classes
|
|
23
|
+
(`Vector2`, `Vector3`, `Color`, `Rect`, `Time`): every operator,
|
|
24
|
+
every helper, every pattern-match hook.
|
|
25
|
+
- Audio API surface (`Sound`, `Music`, `SoundStream`, `Listener`):
|
|
26
|
+
every playback method, every property setter/getter, every 3D-
|
|
27
|
+
audio knob has a real description.
|
|
28
|
+
- Graphics — `Transformable` mixin (`#position` / `#rotation` /
|
|
29
|
+
`#scale` / `#origin` / `#move` / `#rotate` / `#scale_by`), then
|
|
30
|
+
`CircleShape` / `RectangleShape` / `ConvexShape` / `Text` /
|
|
31
|
+
`VertexArray` / `RenderWindow`. Color named-accessors,
|
|
32
|
+
geometric introspection, fill / outline / texture binding.
|
|
33
|
+
- Network — typed `Packet` reader / writer methods, full FTP
|
|
34
|
+
surface (`#download` / `#upload` / `#directory_listing` / …).
|
|
35
|
+
- The autodoc pass fills in trivial setter / getter / predicate
|
|
36
|
+
pairs everywhere else, so the docs site has at least an
|
|
37
|
+
identifiable signature line on every public method.
|
|
38
|
+
|
|
39
|
+
### Changed — infra
|
|
40
|
+
|
|
41
|
+
- `documentation_uri` in the gemspec now points to
|
|
42
|
+
<https://ruby-sfml-doc.netlify.app/> (was rubydoc.info).
|
|
43
|
+
rubydoc.info still works as an archive of older releases.
|
|
44
|
+
- `.rdoc_options` ships inside the gem (`gem unpack` exposes it),
|
|
45
|
+
so the docs-site repo can `rdoc` an unpacked release without
|
|
46
|
+
re-supplying title / template / markup / exclude config.
|
|
47
|
+
- Added `script/build-docs.sh` — local-only build that renders
|
|
48
|
+
`../ruby-sfml-doc/public/`. Optional `--check` mode catches
|
|
49
|
+
"docs out of date with source" in a pre-push hook.
|
|
50
|
+
|
|
11
51
|
## [3.0.0.6] — 2026-05-12
|
|
12
52
|
|
|
13
53
|
Quality-of-life release: the CSFML 3.0 surface was already covered;
|
|
@@ -79,9 +119,6 @@ on top of it.
|
|
|
79
119
|
|
|
80
120
|
### Added — CI / tooling
|
|
81
121
|
|
|
82
|
-
- GitHub Actions release workflow (`release.yml`) — tag
|
|
83
|
-
`vX.Y.Z.W` triggers a gem build + push to RubyGems. Verifies
|
|
84
|
-
the tag matches `lib/sfml/version.rb` before publishing.
|
|
85
122
|
- CI badge in `README.md`.
|
|
86
123
|
|
|
87
124
|
## [3.0.0.5] — 2026-05-11
|
data/README.md
CHANGED
|
@@ -7,9 +7,9 @@ Modern, idiomatic Ruby bindings for [SFML 3.x](https://www.sfml-dev.org/) via [C
|
|
|
7
7
|
|
|
8
8
|
[](https://rubygems.org/gems/ruby-sfml)
|
|
9
9
|
[](https://github.com/sOM2H/ruby-sfml/actions/workflows/ci.yml)
|
|
10
|
-
[](https://ruby-sfml-doc.netlify.app/)
|
|
11
11
|
|
|
12
|
-
> **Status:** API surface complete for SFML 3.0 — system, window, graphics (incl. stencil buffer + VBOs), audio (incl. 3D positional + custom DSP + procedural streams), network (incl. HTTP / FTP / socket selector), input (keyboard, mouse, joystick, touch, sensors), plus
|
|
12
|
+
> **Status:** API surface complete for SFML 3.0 — system, window, graphics (incl. stencil buffer + VBOs), audio (incl. 3D positional + custom DSP + procedural streams), network (incl. HTTP / FTP / socket selector), input (keyboard, mouse, joystick, touch, sensors), plus higher-level helpers (`App`, `Scene`, `Assets`, `SpriteSheet`, `Animation`, `TextureAtlas`, `ParticleSystem`, fixed timestep, input-action DSL, vector math). 640 RSpec examples, 35 runnable example folders.
|
|
13
13
|
|
|
14
14
|
## Why
|
|
15
15
|
|
|
@@ -46,9 +46,12 @@ Or drop it in directly:
|
|
|
46
46
|
gem install ruby-sfml
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
Hosted on [rubygems.org](https://rubygems.org/gems/ruby-sfml)
|
|
50
|
-
docs
|
|
51
|
-
|
|
49
|
+
Hosted on [rubygems.org](https://rubygems.org/gems/ruby-sfml).
|
|
50
|
+
HTML docs (RDoc) live at [**ruby-sfml-doc.netlify.app**](https://ruby-sfml-doc.netlify.app/)
|
|
51
|
+
— built from the source tree of the latest release and served as
|
|
52
|
+
static HTML. RubyGems' auto-generated docs at
|
|
53
|
+
[rubydoc.info/gems/ruby-sfml](https://www.rubydoc.info/gems/ruby-sfml)
|
|
54
|
+
work too as a fallback.
|
|
52
55
|
|
|
53
56
|
### How the CSFML check happens
|
|
54
57
|
|
|
@@ -156,31 +159,74 @@ to its script. Run from the gem root:
|
|
|
156
159
|
bundle exec ruby examples/<NN_name>/<name>.rb
|
|
157
160
|
```
|
|
158
161
|
|
|
162
|
+
The numbering reflects a rough learning order — earlier examples
|
|
163
|
+
introduce concepts that later ones build on. Pick the section that
|
|
164
|
+
matches what you want to learn first.
|
|
165
|
+
|
|
166
|
+
### Foundations — window, events, input
|
|
167
|
+
|
|
159
168
|
| # | Example | What it shows |
|
|
160
169
|
| --- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
161
170
|
| 01 | [hello_window](examples/01_hello_window/hello_window.rb) | Empty window, manual event loop |
|
|
162
171
|
| 02 | [events_demo](examples/02_events_demo/events_demo.rb) | Pattern matching on input events |
|
|
163
|
-
| 03 | [
|
|
164
|
-
| 04 | [
|
|
165
|
-
| 05 | [
|
|
166
|
-
| 06 | [
|
|
167
|
-
| 07 | [
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
|
|
|
172
|
+
| 03 | [mouse_demo](examples/03_mouse_demo/mouse_demo.rb) | Polling vs. events; paint with the mouse |
|
|
173
|
+
| 04 | [bouncing_ball](examples/04_bouncing_ball/bouncing_ball.rb) | dt-based physics on a manual main loop |
|
|
174
|
+
| 05 | [app_class](examples/05_app_class/app_class.rb) | Same idea on top of `SFML::App` — see how much boilerplate goes away |
|
|
175
|
+
| 06 | [vector_math](examples/06_vector_math/vector_math.rb) | `Vector2` helpers (`#distance` / `#angle_to` / `#rotated` / `#lerp` / `#clamp_length`) in real motion |
|
|
176
|
+
| 07 | [input_actions](examples/07_input_actions/input_actions.rb) | `action :name, keys:, scancodes:, mouse_buttons:` DSL + `axis(...)` digital steering |
|
|
177
|
+
|
|
178
|
+
### Drawing — geometry and assets
|
|
179
|
+
|
|
180
|
+
| # | Example | What it shows |
|
|
181
|
+
| --- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
182
|
+
| 08 | [draw_primitives](examples/08_draw_primitives/draw_primitives.rb) | Raw `draw_primitives` — line burst rebuilt every frame |
|
|
183
|
+
| 09 | [custom_shape](examples/09_custom_shape/custom_shape.rb) | Abstract `SFML::Shape` subclass — parametric star / heart / gear |
|
|
184
|
+
| 10 | [image_viewer](examples/10_image_viewer/image_viewer.rb) | Load a PNG, mutate the `Image`, re-upload to `Texture` on a key |
|
|
185
|
+
| 11 | [pixel_paint](examples/11_pixel_paint/pixel_paint.rb) | Paint into a CPU `Image`, blit to GPU `Texture` each dirty frame |
|
|
186
|
+
| 12 | [sprite_animation](examples/12_sprite_animation/sprite_animation.rb) | Procedural `SpriteSheet` → `Animation` walk cycle |
|
|
187
|
+
| 13 | [texture_atlas](examples/13_texture_atlas/texture_atlas.rb) | Aseprite-style JSON atlas → 3 named animations with auto-fps |
|
|
188
|
+
| 14 | [window_icon](examples/14_window_icon/window_icon.rb) | Procedural 32×32 icon set as the window/taskbar icon |
|
|
175
189
|
| 15 | [cursors_clipboard](examples/15_cursors_clipboard/cursors_clipboard.rb) | All 21 system `Cursor` shapes + `Clipboard` copy/paste |
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
190
|
+
|
|
191
|
+
### Camera, GPU, effects
|
|
192
|
+
|
|
193
|
+
| # | Example | What it shows |
|
|
194
|
+
| --- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
195
|
+
| 16 | [screenshot](examples/16_screenshot/screenshot.rb) | `RenderWindow#screenshot(path)` / `#capture_image` for in-memory frames |
|
|
196
|
+
| 17 | [scrolling_world](examples/17_scrolling_world/scrolling_world.rb) | `View` as a 2D camera: drag-pan, wheel-zoom around cursor, FPS HUD |
|
|
197
|
+
| 18 | [render_texture](examples/18_render_texture/render_texture.rb) | Off-screen `RenderTexture` for trail / motion-blur effects |
|
|
198
|
+
| 19 | [tilemap](examples/19_tilemap/tilemap.rb) | Textured `VertexArray` tilemap + additive `BlendMode` torch |
|
|
199
|
+
| 20 | [particle_system](examples/20_particle_system/particle_system.rb) | `SFML::ParticleSystem` fountain — VertexArray-backed pool |
|
|
200
|
+
| 21 | [particles](examples/21_particles/particles.rb) | Same fountain hand-rolled on `VertexArray` + `ConvexShape` ground |
|
|
201
|
+
| 22 | [shader_wave](examples/22_shader_wave/shader_wave.rb) | Pure GLSL fragment `Shader` — procedural ripple + plasma |
|
|
202
|
+
| 23 | [stencil_mask](examples/23_stencil_mask/stencil_mask.rb) | Two-pass `StencilMode` masking — cursor spotlight clip |
|
|
203
|
+
| 24 | [vertex_buffer](examples/24_vertex_buffer/vertex_buffer.rb) | 120 K-vertex `VertexBuffer` drawn in one call, animated via `View` only |
|
|
204
|
+
| 25 | [bare_window](examples/25_bare_window/bare_window.rb) | `SFML::Window` (no 2D batcher) — events for raw-OpenGL apps |
|
|
205
|
+
|
|
206
|
+
### Game-loop polish
|
|
207
|
+
|
|
208
|
+
| # | Example | What it shows |
|
|
209
|
+
| --- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
210
|
+
| 26 | [scenes](examples/26_scenes/scenes.rb) | Title → play → game-over flow with `SFML::Scene` |
|
|
211
|
+
| 27 | [fixed_timestep](examples/27_fixed_timestep/fixed_timestep.rb) | `fixed_timestep 30` + `interpolation_alpha` for jitter-free physics |
|
|
212
|
+
| 28 | [pong](examples/28_pong/pong.rb) | Two-player Pong with in-window score (`Text`) and bounce `Sound` |
|
|
213
|
+
| 29 | [joystick_demo](examples/29_joystick_demo/joystick_demo.rb) | Live gamepad inspector (axes, buttons, connect/disconnect) |
|
|
214
|
+
|
|
215
|
+
### Audio — simple to procedural
|
|
216
|
+
|
|
217
|
+
| # | Example | What it shows |
|
|
218
|
+
| --- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
219
|
+
| 30 | [spatial_audio](examples/30_spatial_audio/spatial_audio.rb) | 3D positional `Sound` + `Listener` — three drones around the cursor |
|
|
220
|
+
| 31 | [voice_memo](examples/31_voice_memo/voice_memo.rb) | Record from microphone via `SoundBufferRecorder`, save + play back |
|
|
221
|
+
| 32 | [sound_stream](examples/32_sound_stream/sound_stream.rb) | Real-time sine synth via `SFML::SoundStream` subclass |
|
|
222
|
+
| 33 | [procedural_synth](examples/33_procedural_synth/procedural_synth.rb) | `SoundBuffer.from_samples` mini-piano (Z–M keys, chromatic C4..B4) |
|
|
223
|
+
|
|
224
|
+
### Networking
|
|
225
|
+
|
|
226
|
+
| # | Example | What it shows |
|
|
227
|
+
| --- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
|
|
228
|
+
| 34 | [udp_loopback](examples/34_udp_loopback/udp_loopback.rb) | UDP send/receive on localhost via `Network::UdpSocket` |
|
|
229
|
+
| 35 | [tcp_chat](examples/35_tcp_chat/tcp_chat.rb) | `TcpListener` + `TcpSocket` + typed `Network::Packet` over loopback |
|
|
184
230
|
|
|
185
231
|
## Idioms baked in
|
|
186
232
|
|
data/lib/sfml/app.rb
CHANGED
|
@@ -118,6 +118,7 @@ module SFML
|
|
|
118
118
|
# Width and height shortcuts that always reflect the current
|
|
119
119
|
# window size — matters once the user is allowed to resize.
|
|
120
120
|
def width = @window.size.x
|
|
121
|
+
# Returns the height.
|
|
121
122
|
def height = @window.size.y
|
|
122
123
|
|
|
123
124
|
# Close the window. The main loop exits at the start of the
|
|
@@ -160,9 +161,13 @@ module SFML
|
|
|
160
161
|
# (handy for pause overlays that need to be drawn over a
|
|
161
162
|
# frozen scene).
|
|
162
163
|
|
|
164
|
+
# Pause the simulation. `#draw` keeps firing; `#update` doesn't.
|
|
163
165
|
def pause = (@paused = true)
|
|
166
|
+
# Resume the simulation.
|
|
164
167
|
def resume = (@paused = false)
|
|
168
|
+
# Flip the pause state.
|
|
165
169
|
def toggle_pause = (@paused = !paused?)
|
|
170
|
+
# `true` while the simulation is paused.
|
|
166
171
|
def paused? = @paused == true
|
|
167
172
|
|
|
168
173
|
# Fraction of a fixed timestep accumulated since the last
|
data/lib/sfml/assets.rb
CHANGED
|
@@ -26,11 +26,13 @@ module SFML
|
|
|
26
26
|
@search_paths ||= [default_root]
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# Set the search paths.
|
|
29
30
|
def search_paths=(paths)
|
|
30
31
|
@search_paths = Array(paths).map { |p| File.expand_path(p) }
|
|
31
32
|
@cache&.clear
|
|
32
33
|
end
|
|
33
34
|
|
|
35
|
+
# Set the root.
|
|
34
36
|
def root=(path)
|
|
35
37
|
self.search_paths = [path]
|
|
36
38
|
end
|
data/lib/sfml/audio/listener.rb
CHANGED
|
@@ -17,14 +17,17 @@ module SFML
|
|
|
17
17
|
C::Audio.sfListener_getGlobalVolume
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# Set the master volume in [0, 100].
|
|
20
21
|
def global_volume=(value)
|
|
21
22
|
C::Audio.sfListener_setGlobalVolume(value.to_f)
|
|
22
23
|
end
|
|
23
24
|
|
|
25
|
+
# The listener's 3D position in world space.
|
|
24
26
|
def position
|
|
25
27
|
Vector3.from_native(C::Audio.sfListener_getPosition)
|
|
26
28
|
end
|
|
27
29
|
|
|
30
|
+
# Set the position — accepts Vector3 or `[x, y, z]`.
|
|
28
31
|
def position=(value)
|
|
29
32
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
30
33
|
C::Audio.sfListener_setPosition(vec.to_native_f)
|
|
@@ -36,6 +39,7 @@ module SFML
|
|
|
36
39
|
Vector3.from_native(C::Audio.sfListener_getDirection)
|
|
37
40
|
end
|
|
38
41
|
|
|
42
|
+
# Set the forward direction — accepts Vector3 or `[x, y, z]`.
|
|
39
43
|
def direction=(value)
|
|
40
44
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
41
45
|
C::Audio.sfListener_setDirection(vec.to_native_f)
|
|
@@ -47,6 +51,7 @@ module SFML
|
|
|
47
51
|
Vector3.from_native(C::Audio.sfListener_getUpVector)
|
|
48
52
|
end
|
|
49
53
|
|
|
54
|
+
# Set the up vector — accepts Vector3 or `[x, y, z]`.
|
|
50
55
|
def up_vector=(value)
|
|
51
56
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
52
57
|
C::Audio.sfListener_setUpVector(vec.to_native_f)
|
|
@@ -58,6 +63,7 @@ module SFML
|
|
|
58
63
|
Vector3.from_native(C::Audio.sfListener_getVelocity)
|
|
59
64
|
end
|
|
60
65
|
|
|
66
|
+
# Set the velocity — accepts Vector3 or `[x, y, z]`.
|
|
61
67
|
def velocity=(value)
|
|
62
68
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
63
69
|
C::Audio.sfListener_setVelocity(vec.to_native_f)
|
|
@@ -72,6 +78,7 @@ module SFML
|
|
|
72
78
|
SoundCone.from_native(C::Audio.sfListener_getCone)
|
|
73
79
|
end
|
|
74
80
|
|
|
81
|
+
# Set the cone. Accepts a `SoundCone` or a Hash.
|
|
75
82
|
def cone=(value)
|
|
76
83
|
cone =
|
|
77
84
|
case value
|
data/lib/sfml/audio/music.rb
CHANGED
|
@@ -5,6 +5,9 @@ module SFML
|
|
|
5
5
|
# bgm = SFML::Music.load("assets/track.ogg", looping: true, volume: 60)
|
|
6
6
|
# bgm.play
|
|
7
7
|
class Music
|
|
8
|
+
# Load a music track from disk. `opts` may include `:volume`,
|
|
9
|
+
# `:pitch`, and `:looping` — these are applied right after load.
|
|
10
|
+
# Raises `SFML::LoadError` on missing file or unsupported format.
|
|
8
11
|
def self.load(path, **opts)
|
|
9
12
|
ptr = C::Audio.sfMusic_createFromFile(path.to_s)
|
|
10
13
|
raise LoadError, "Could not load music from #{path.inspect}" if ptr.null?
|
|
@@ -56,15 +59,23 @@ module SFML
|
|
|
56
59
|
end
|
|
57
60
|
private_class_method :_wrap
|
|
58
61
|
|
|
62
|
+
# Start playback (resumes from pause, restarts when stopped).
|
|
59
63
|
def play = C::Audio.sfMusic_play(@handle)
|
|
64
|
+
# Pause playback — `#play` resumes from here.
|
|
60
65
|
def pause = C::Audio.sfMusic_pause(@handle)
|
|
66
|
+
# Stop playback and rewind to the start.
|
|
61
67
|
def stop = C::Audio.sfMusic_stop(@handle)
|
|
62
68
|
|
|
69
|
+
# Playback state — one of `:stopped`, `:paused`, `:playing`.
|
|
63
70
|
def status = C::Audio::STATUSES[C::Audio.sfMusic_getStatus(@handle)]
|
|
71
|
+
# Convenience for `status == :playing`.
|
|
64
72
|
def playing? = status == :playing
|
|
73
|
+
# Convenience for `status == :paused`.
|
|
65
74
|
def paused? = status == :paused
|
|
75
|
+
# Convenience for `status == :stopped`.
|
|
66
76
|
def stopped? = status == :stopped
|
|
67
77
|
|
|
78
|
+
# Total length of the track as a `SFML::Time`.
|
|
68
79
|
def duration = Time.from_native(C::Audio.sfMusic_getDuration(@handle))
|
|
69
80
|
|
|
70
81
|
# Current playback head as a SFML::Time. Reads from the underlying
|
|
@@ -88,6 +99,7 @@ module SFML
|
|
|
88
99
|
Vector3.new(v[:x], v[:y], v[:z])
|
|
89
100
|
end
|
|
90
101
|
|
|
102
|
+
# Set the 3D velocity — accepts Vector3 or `[x, y, z]`.
|
|
91
103
|
def velocity=(value)
|
|
92
104
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
93
105
|
packed = C::System::Vector3f.new
|
|
@@ -95,14 +107,18 @@ module SFML
|
|
|
95
107
|
C::Audio.sfMusic_setVelocity(@handle, packed)
|
|
96
108
|
end
|
|
97
109
|
|
|
110
|
+
# Per-source Doppler scale. 1.0 realistic, 0 disables.
|
|
98
111
|
def doppler_factor = C::Audio.sfMusic_getDopplerFactor(@handle)
|
|
112
|
+
# Set the per-source Doppler scale.
|
|
99
113
|
def doppler_factor=(v) C::Audio.sfMusic_setDopplerFactor(@handle, v.to_f); end
|
|
100
114
|
|
|
115
|
+
# The direction the music's cone points.
|
|
101
116
|
def direction
|
|
102
117
|
v = C::Audio.sfMusic_getDirection(@handle)
|
|
103
118
|
Vector3.new(v[:x], v[:y], v[:z])
|
|
104
119
|
end
|
|
105
120
|
|
|
121
|
+
# Set the direction vector — accepts Vector3 or `[x, y, z]`.
|
|
106
122
|
def direction=(value)
|
|
107
123
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
108
124
|
packed = C::System::Vector3f.new
|
|
@@ -110,10 +126,13 @@ module SFML
|
|
|
110
126
|
C::Audio.sfMusic_setDirection(@handle, packed)
|
|
111
127
|
end
|
|
112
128
|
|
|
129
|
+
# Directional-attenuation cone — see SFML::SoundCone.
|
|
113
130
|
def cone
|
|
114
131
|
SoundCone.from_native(C::Audio.sfMusic_getCone(@handle))
|
|
115
132
|
end
|
|
116
133
|
|
|
134
|
+
# Set the cone. Accepts a `SoundCone` or a Hash with
|
|
135
|
+
# `inner_angle`, `outer_angle`, `outer_gain`.
|
|
117
136
|
def cone=(value)
|
|
118
137
|
cone =
|
|
119
138
|
case value
|
|
@@ -131,24 +150,31 @@ module SFML
|
|
|
131
150
|
C::Audio.sfMusic_setEffectProcessor(@handle, @effect_cb, nil)
|
|
132
151
|
end
|
|
133
152
|
|
|
153
|
+
# `true` if the track restarts after reaching the end (or its
|
|
154
|
+
# `loop_points` length).
|
|
134
155
|
# Cached on the Ruby side; see Sound#looping? for the why.
|
|
135
156
|
def looping?
|
|
136
157
|
@looping
|
|
137
158
|
end
|
|
138
159
|
|
|
160
|
+
# Toggle looping playback.
|
|
139
161
|
def looping=(value)
|
|
140
162
|
@looping = value ? true : false
|
|
141
163
|
C::Audio.sfMusic_setLooping(@handle, @looping)
|
|
142
164
|
end
|
|
143
165
|
|
|
166
|
+
# Playback volume in [0, 100] — 100 = unattenuated.
|
|
144
167
|
def volume = C::Audio.sfMusic_getVolume(@handle)
|
|
145
168
|
|
|
169
|
+
# Set the playback volume in [0, 100].
|
|
146
170
|
def volume=(value)
|
|
147
171
|
C::Audio.sfMusic_setVolume(@handle, value.to_f)
|
|
148
172
|
end
|
|
149
173
|
|
|
174
|
+
# Pitch multiplier. 1.0 = normal, 2.0 = octave up, 0.5 = octave down.
|
|
150
175
|
def pitch = C::Audio.sfMusic_getPitch(@handle)
|
|
151
176
|
|
|
177
|
+
# Set the pitch multiplier.
|
|
152
178
|
def pitch=(value)
|
|
153
179
|
C::Audio.sfMusic_setPitch(@handle, value.to_f)
|
|
154
180
|
end
|
|
@@ -158,32 +184,41 @@ module SFML
|
|
|
158
184
|
Vector3.from_native(C::Audio.sfMusic_getPosition(@handle))
|
|
159
185
|
end
|
|
160
186
|
|
|
187
|
+
# Set the 3D position — accepts Vector3 or `[x, y, z]`.
|
|
161
188
|
def position=(value)
|
|
162
189
|
vec = value.is_a?(Vector3) ? value : Vector3.new(*value)
|
|
163
190
|
C::Audio.sfMusic_setPosition(@handle, vec.to_native_f)
|
|
164
191
|
end
|
|
165
192
|
|
|
193
|
+
# Falloff sharpness with distance — see `Sound#attenuation`.
|
|
166
194
|
def attenuation = C::Audio.sfMusic_getAttenuation(@handle)
|
|
167
195
|
|
|
196
|
+
# Set the attenuation.
|
|
168
197
|
def attenuation=(value)
|
|
169
198
|
C::Audio.sfMusic_setAttenuation(@handle, value.to_f)
|
|
170
199
|
end
|
|
171
200
|
|
|
201
|
+
# Distance below which volume is not attenuated.
|
|
172
202
|
def min_distance = C::Audio.sfMusic_getMinDistance(@handle)
|
|
173
203
|
|
|
204
|
+
# Set the min-distance.
|
|
174
205
|
def min_distance=(value)
|
|
175
206
|
C::Audio.sfMusic_setMinDistance(@handle, value.to_f)
|
|
176
207
|
end
|
|
177
208
|
|
|
209
|
+
# `true` if `#position` is interpreted relative to the listener.
|
|
178
210
|
def relative_to_listener? = C::Audio.sfMusic_isRelativeToListener(@handle)
|
|
179
211
|
|
|
212
|
+
# Toggle listener-relative positioning.
|
|
180
213
|
def relative_to_listener=(value)
|
|
181
214
|
C::Audio.sfMusic_setRelativeToListener(@handle, value ? true : false)
|
|
182
215
|
end
|
|
183
216
|
|
|
184
217
|
# ---- Stream introspection ----
|
|
185
218
|
|
|
219
|
+
# Number of audio channels (1 = mono, 2 = stereo, ...).
|
|
186
220
|
def channel_count = C::Audio.sfMusic_getChannelCount(@handle)
|
|
221
|
+
# Sample rate in Hz (e.g. 44_100 for CD-quality).
|
|
187
222
|
def sample_rate = C::Audio.sfMusic_getSampleRate(@handle)
|
|
188
223
|
|
|
189
224
|
# The portion of the track that loops when `looping = true`.
|
|
@@ -194,6 +229,8 @@ module SFML
|
|
|
194
229
|
[Time.from_native(span[:offset]), Time.from_native(span[:length])]
|
|
195
230
|
end
|
|
196
231
|
|
|
232
|
+
# Set the looping window. Accepts `[offset, length]` of either
|
|
233
|
+
# `SFML::Time` or numeric seconds.
|
|
197
234
|
def loop_points=(value)
|
|
198
235
|
offset_t, length_t = value
|
|
199
236
|
raise ArgumentError, "expected [offset_time, length_time]" unless offset_t && length_t
|
|
@@ -206,40 +243,54 @@ module SFML
|
|
|
206
243
|
|
|
207
244
|
# ---- 3D-audio extras (mirror of Sound's) ----
|
|
208
245
|
|
|
246
|
+
# Stereo pan in [-1.0, 1.0] — see `Sound#pan`.
|
|
209
247
|
def pan = C::Audio.sfMusic_getPan(@handle)
|
|
210
248
|
|
|
249
|
+
# Set the stereo pan.
|
|
211
250
|
def pan=(v)
|
|
212
251
|
C::Audio.sfMusic_setPan(@handle, v.to_f)
|
|
213
252
|
end
|
|
214
253
|
|
|
254
|
+
# Lower gain bound — see `Sound#min_gain`.
|
|
215
255
|
def min_gain = C::Audio.sfMusic_getMinGain(@handle)
|
|
216
256
|
|
|
257
|
+
# Set the min-gain floor.
|
|
217
258
|
def min_gain=(v)
|
|
218
259
|
C::Audio.sfMusic_setMinGain(@handle, v.to_f)
|
|
219
260
|
end
|
|
220
261
|
|
|
262
|
+
# Upper gain bound — see `Sound#max_gain`.
|
|
221
263
|
def max_gain = C::Audio.sfMusic_getMaxGain(@handle)
|
|
222
264
|
|
|
265
|
+
# Set the max-gain cap.
|
|
223
266
|
def max_gain=(v)
|
|
224
267
|
C::Audio.sfMusic_setMaxGain(@handle, v.to_f)
|
|
225
268
|
end
|
|
226
269
|
|
|
270
|
+
# Distance beyond which the source is fully attenuated.
|
|
227
271
|
def max_distance = C::Audio.sfMusic_getMaxDistance(@handle)
|
|
228
272
|
|
|
273
|
+
# Set the max-distance.
|
|
229
274
|
def max_distance=(v)
|
|
230
275
|
C::Audio.sfMusic_setMaxDistance(@handle, v.to_f)
|
|
231
276
|
end
|
|
232
277
|
|
|
278
|
+
# `true` if 3D positional / Doppler / cone math is applied at
|
|
279
|
+
# mix time.
|
|
233
280
|
def spatialization_enabled? = C::Audio.sfMusic_isSpatializationEnabled(@handle)
|
|
234
281
|
|
|
282
|
+
# Toggle 3D spatialisation.
|
|
235
283
|
def spatialization_enabled=(v)
|
|
236
284
|
C::Audio.sfMusic_setSpatializationEnabled(@handle, v ? true : false)
|
|
237
285
|
end
|
|
238
286
|
|
|
287
|
+
# Multiplier on the Listener's directional attenuation cone —
|
|
288
|
+
# see `Sound#directional_attenuation_factor`.
|
|
239
289
|
def directional_attenuation_factor
|
|
240
290
|
C::Audio.sfMusic_getDirectionalAttenuationFactor(@handle)
|
|
241
291
|
end
|
|
242
292
|
|
|
293
|
+
# Set the directional-attenuation factor.
|
|
243
294
|
def directional_attenuation_factor=(v)
|
|
244
295
|
C::Audio.sfMusic_setDirectionalAttenuationFactor(@handle, v.to_f)
|
|
245
296
|
end
|