ruby-sfml 3.0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +101 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +245 -0
  5. data/ext/ruby-sfml/extconf.rb +69 -0
  6. data/lib/sfml/assets/fonts/DejaVuSans.LICENSE.txt +78 -0
  7. data/lib/sfml/assets/fonts/DejaVuSans.ttf +0 -0
  8. data/lib/sfml/assets.rb +121 -0
  9. data/lib/sfml/audio/listener.rb +55 -0
  10. data/lib/sfml/audio/music.rb +88 -0
  11. data/lib/sfml/audio/sound.rb +102 -0
  12. data/lib/sfml/audio/sound_buffer.rb +38 -0
  13. data/lib/sfml/audio/sound_buffer_recorder.rb +71 -0
  14. data/lib/sfml/audio/sound_recorder.rb +30 -0
  15. data/lib/sfml/c/audio.rb +106 -0
  16. data/lib/sfml/c/graphics.rb +425 -0
  17. data/lib/sfml/c/network.rb +79 -0
  18. data/lib/sfml/c/system.rb +43 -0
  19. data/lib/sfml/c/window.rb +186 -0
  20. data/lib/sfml/c.rb +72 -0
  21. data/lib/sfml/game.rb +101 -0
  22. data/lib/sfml/graphics/blend_mode.rb +108 -0
  23. data/lib/sfml/graphics/circle_shape.rb +67 -0
  24. data/lib/sfml/graphics/color.rb +89 -0
  25. data/lib/sfml/graphics/convex_shape.rb +82 -0
  26. data/lib/sfml/graphics/font.rb +67 -0
  27. data/lib/sfml/graphics/image.rb +125 -0
  28. data/lib/sfml/graphics/rectangle_shape.rb +62 -0
  29. data/lib/sfml/graphics/render_states.rb +56 -0
  30. data/lib/sfml/graphics/render_target.rb +146 -0
  31. data/lib/sfml/graphics/render_texture.rb +72 -0
  32. data/lib/sfml/graphics/render_window.rb +154 -0
  33. data/lib/sfml/graphics/shader.rb +132 -0
  34. data/lib/sfml/graphics/sprite.rb +75 -0
  35. data/lib/sfml/graphics/text.rb +144 -0
  36. data/lib/sfml/graphics/texture.rb +79 -0
  37. data/lib/sfml/graphics/transform.rb +150 -0
  38. data/lib/sfml/graphics/transformable.rb +74 -0
  39. data/lib/sfml/graphics/vertex.rb +53 -0
  40. data/lib/sfml/graphics/vertex_array.rb +114 -0
  41. data/lib/sfml/graphics/view.rb +126 -0
  42. data/lib/sfml/network/ip_address.rb +67 -0
  43. data/lib/sfml/network/tcp_listener.rb +61 -0
  44. data/lib/sfml/network/tcp_socket.rb +74 -0
  45. data/lib/sfml/network/udp_socket.rb +71 -0
  46. data/lib/sfml/system/clock.rb +44 -0
  47. data/lib/sfml/system/rect.rb +64 -0
  48. data/lib/sfml/system/time.rb +48 -0
  49. data/lib/sfml/system/vector2.rb +66 -0
  50. data/lib/sfml/system/vector3.rb +63 -0
  51. data/lib/sfml/version.rb +19 -0
  52. data/lib/sfml/window/clipboard.rb +38 -0
  53. data/lib/sfml/window/cursor.rb +68 -0
  54. data/lib/sfml/window/event.rb +133 -0
  55. data/lib/sfml/window/joystick.rb +90 -0
  56. data/lib/sfml/window/keyboard.rb +60 -0
  57. data/lib/sfml/window/mouse.rb +71 -0
  58. data/lib/sfml/window/video_mode.rb +37 -0
  59. data/lib/sfml/window/window.rb +149 -0
  60. data/lib/sfml.rb +98 -0
  61. data/ruby-sfml.gemspec +38 -0
  62. metadata +163 -0
@@ -0,0 +1,90 @@
1
+ module SFML
2
+ # Global gamepad / joystick state — peer to Keyboard and Mouse.
3
+ #
4
+ # if SFML::Joystick.connected?(0)
5
+ # x = SFML::Joystick.axis_position(0, :x) # -100.0 .. 100.0
6
+ # fire = SFML::Joystick.button_pressed?(0, 0)
7
+ # info = SFML::Joystick.identification(0)
8
+ # # => { name: "Xbox Controller", vendor_id: 0x045e, product_id: 0x028e }
9
+ # end
10
+ #
11
+ # SFML supports up to MAX_COUNT joysticks (0..MAX_COUNT-1). Axes are
12
+ # addressed by symbol (:x, :y, :z, :r, :u, :v, :pov_x, :pov_y) so callers
13
+ # don't have to remember the sfJoystickAxis enum order.
14
+ module Joystick
15
+ # Order matches sfJoystickAxis in CSFML/Window/Joystick.h.
16
+ AXES = %i[x y z r u v pov_x pov_y].freeze
17
+ AXIS_INDEX = AXES.each_with_index.to_h.freeze
18
+
19
+ # Friendly aliases — POV axes are also called "hat" or "dpad" in some
20
+ # gamepad APIs.
21
+ AXIS_ALIASES = {
22
+ hat_x: :pov_x, hat_y: :pov_y,
23
+ dpad_x: :pov_x, dpad_y: :pov_y,
24
+ }.freeze
25
+
26
+ MAX_COUNT = 8
27
+ MAX_BUTTON_COUNT = 32
28
+ MAX_AXIS_COUNT = AXES.length
29
+
30
+ module_function
31
+
32
+ def connected?(joystick)
33
+ C::Window.sfJoystick_isConnected(_id(joystick))
34
+ end
35
+
36
+ def button_count(joystick)
37
+ C::Window.sfJoystick_getButtonCount(_id(joystick))
38
+ end
39
+
40
+ def has_axis?(joystick, axis)
41
+ C::Window.sfJoystick_hasAxis(_id(joystick), _axis_code(axis))
42
+ end
43
+
44
+ # Axis value in the range [-100.0, 100.0]. Returns 0.0 for axes that
45
+ # don't exist on the device, so it's safe to call without first
46
+ # checking has_axis?.
47
+ def axis_position(joystick, axis)
48
+ C::Window.sfJoystick_getAxisPosition(_id(joystick), _axis_code(axis))
49
+ end
50
+
51
+ def button_pressed?(joystick, button)
52
+ C::Window.sfJoystick_isButtonPressed(_id(joystick), Integer(button))
53
+ end
54
+
55
+ # Returns a Hash {name:, vendor_id:, product_id:} describing the
56
+ # device, or nil if the joystick isn't connected.
57
+ def identification(joystick)
58
+ return nil unless connected?(joystick)
59
+ ident = C::Window.sfJoystick_getIdentification(_id(joystick))
60
+ name_ptr = ident[:name]
61
+ {
62
+ name: name_ptr.null? ? "" : name_ptr.read_string.force_encoding("UTF-8"),
63
+ vendor_id: ident[:vendor_id],
64
+ product_id: ident[:product_id],
65
+ }
66
+ end
67
+
68
+ # Refresh joystick state. SFML auto-updates as part of pollEvent, so
69
+ # most code never needs this. Call it explicitly only if you're
70
+ # polling joystick state without an active event loop.
71
+ def update
72
+ C::Window.sfJoystick_update
73
+ end
74
+
75
+ # @!visibility private
76
+ def _id(joystick)
77
+ n = Integer(joystick)
78
+ raise ArgumentError, "Joystick id must be in 0..#{MAX_COUNT - 1}, got #{n}" if n < 0 || n >= MAX_COUNT
79
+ n
80
+ end
81
+
82
+ # @!visibility private
83
+ def _axis_code(axis)
84
+ sym = AXIS_ALIASES.fetch(axis, axis)
85
+ AXIS_INDEX.fetch(sym) do
86
+ raise ArgumentError, "Unknown joystick axis: #{axis.inspect}. Expected: #{AXES.inspect}"
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,60 @@
1
+ module SFML
2
+ # Keyboard key code <-> symbol translation, plus Keyboard.key_pressed?(:esc).
3
+ #
4
+ # The KEY_CODES array order is load-bearing: it matches the sfKeyCode enum
5
+ # in CSFML/Window/Keyboard.h exactly. sfKeyUnknown is -1 and represented
6
+ # here by :unknown returned via #code_to_symbol.
7
+ module Keyboard
8
+ KEY_CODES = %i[
9
+ a b c d e f g h i j k l m n o p q r s t u v w x y z
10
+ num0 num1 num2 num3 num4 num5 num6 num7 num8 num9
11
+ escape
12
+ l_control l_shift l_alt l_system
13
+ r_control r_shift r_alt r_system
14
+ menu
15
+ l_bracket r_bracket
16
+ semicolon comma period apostrophe slash backslash grave equal hyphen
17
+ space enter backspace tab
18
+ page_up page_down end_key home insert delete
19
+ add subtract multiply divide
20
+ left right up down
21
+ numpad0 numpad1 numpad2 numpad3 numpad4
22
+ numpad5 numpad6 numpad7 numpad8 numpad9
23
+ f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15
24
+ pause
25
+ ].freeze
26
+
27
+ SYMBOL_TO_CODE = KEY_CODES.each_with_index.to_h.freeze
28
+
29
+ # Friendly aliases users might reach for naturally.
30
+ ALIASES = {
31
+ esc: :escape,
32
+ lctrl: :l_control,
33
+ rctrl: :r_control,
34
+ lshift: :l_shift,
35
+ rshift: :r_shift,
36
+ space_bar: :space,
37
+ return: :enter,
38
+ }.freeze
39
+
40
+ module_function
41
+
42
+ def code_to_symbol(code)
43
+ return :unknown if code < 0 || code >= KEY_CODES.length
44
+ KEY_CODES[code]
45
+ end
46
+
47
+ def symbol_to_code(symbol)
48
+ symbol = ALIASES.fetch(symbol, symbol)
49
+ SYMBOL_TO_CODE.fetch(symbol) do
50
+ raise ArgumentError, "Unknown key symbol: #{symbol.inspect}. " \
51
+ "See SFML::Keyboard::KEY_CODES."
52
+ end
53
+ end
54
+
55
+ # SFML::Keyboard.key_pressed?(:escape)
56
+ def key_pressed?(symbol)
57
+ C::Window.sfKeyboard_isKeyPressed(symbol_to_code(symbol))
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,71 @@
1
+ module SFML
2
+ # Global mouse state — peer to SFML::Keyboard. Use it for "is this
3
+ # button held right now?" and for current pointer coordinates outside
4
+ # of the event loop.
5
+ #
6
+ # SFML::Mouse.button_pressed?(:left) #=> true while LMB is held
7
+ # SFML::Mouse.position #=> Vector2 — desktop coords
8
+ # SFML::Mouse.position(window) #=> Vector2 — relative to window
9
+ # SFML::Mouse.set_position([400, 300], window)
10
+ #
11
+ # Buttons are addressed by symbol; the raw sfMouseButton enum order is
12
+ # exposed via BUTTONS for users who need it.
13
+ module Mouse
14
+ BUTTONS = %i[left right middle extra1 extra2].freeze
15
+ BUTTON_INDEX = BUTTONS.each_with_index.to_h.freeze
16
+
17
+ # Friendly aliases — SFML 2 used "X-button" terminology; some users
18
+ # still reach for it.
19
+ ALIASES = {
20
+ x1: :extra1,
21
+ x2: :extra2,
22
+ x_button1: :extra1,
23
+ x_button2: :extra2,
24
+ }.freeze
25
+
26
+ module_function
27
+
28
+ # Returns true if the named mouse button is currently held.
29
+ def button_pressed?(button)
30
+ C::Window.sfMouse_isButtonPressed(_code(button))
31
+ end
32
+
33
+ # Pointer position. With no argument, returns desktop-relative
34
+ # coordinates. With a RenderWindow, returns coordinates relative to
35
+ # that window's client area (top-left = 0, 0).
36
+ def position(window = nil)
37
+ vec = if window
38
+ C::Graphics.sfMouse_getPositionRenderWindow(window.handle)
39
+ else
40
+ C::Window.sfMouse_getPosition(nil)
41
+ end
42
+ Vector2.new(vec[:x], vec[:y])
43
+ end
44
+
45
+ # Move the OS pointer. Without `window`, the coordinates are desktop-
46
+ # relative. Useful for FPS-style mouse-look (warp the cursor back to
47
+ # screen centre each frame).
48
+ def set_position(point, window = nil)
49
+ px, py = point.is_a?(Vector2) ? [point.x, point.y] : point
50
+ vec = C::System::Vector2i.new
51
+ vec[:x] = Integer(px)
52
+ vec[:y] = Integer(py)
53
+
54
+ if window
55
+ C::Graphics.sfMouse_setPositionRenderWindow(vec, window.handle)
56
+ else
57
+ C::Window.sfMouse_setPosition(vec, nil)
58
+ end
59
+ end
60
+
61
+ # @!visibility private
62
+ def _code(button)
63
+ sym = ALIASES.fetch(button, button)
64
+ BUTTON_INDEX.fetch(sym) do
65
+ raise ArgumentError,
66
+ "Unknown mouse button: #{button.inspect}. " \
67
+ "Expected one of: #{BUTTONS.inspect}"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ module SFML
2
+ # Video mode = (width, height, bits-per-pixel). Used when creating windows.
3
+ #
4
+ # SFML::VideoMode.new(800, 600)
5
+ # SFML::VideoMode.desktop_mode
6
+ class VideoMode
7
+ attr_reader :width, :height, :bits_per_pixel
8
+
9
+ def initialize(width, height, bits_per_pixel = 32)
10
+ @width = Integer(width)
11
+ @height = Integer(height)
12
+ @bits_per_pixel = Integer(bits_per_pixel)
13
+ freeze
14
+ end
15
+
16
+ def self.desktop_mode
17
+ from_native(C::Window.sfVideoMode_getDesktopMode)
18
+ end
19
+
20
+ def size = Vector2.new(@width, @height)
21
+
22
+ def to_s = "#<SFML::VideoMode #{@width}x#{@height}@#{@bits_per_pixel}>"
23
+ alias inspect to_s
24
+
25
+ def self.from_native(struct) # :nodoc:
26
+ new(struct[:size][:x], struct[:size][:y], struct[:bits_per_pixel])
27
+ end
28
+
29
+ def to_native # :nodoc:
30
+ C::Window::VideoMode.new.tap do |m|
31
+ m[:size][:x] = @width
32
+ m[:size][:y] = @height
33
+ m[:bits_per_pixel] = @bits_per_pixel
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,149 @@
1
+ module SFML
2
+ # A bare window with input + an OpenGL context, **without** SFML's
3
+ # 2D batcher. Use this when you want raw OpenGL (or another
4
+ # rendering library) and just need SFML to manage the platform-level
5
+ # window and event loop. For 2D drawing with SFML's API, you want
6
+ # SFML::RenderWindow instead.
7
+ #
8
+ # win = SFML::Window.new(800, 600, "GL")
9
+ # while win.open?
10
+ # win.each_event do |event|
11
+ # case event
12
+ # in {type: :closed} then win.close
13
+ # in {type: :key_pressed, code: :escape} then win.close
14
+ # else
15
+ # end
16
+ # end
17
+ #
18
+ # # ... draw with raw OpenGL calls here ...
19
+ #
20
+ # win.display
21
+ # end
22
+ class Window
23
+ DEFAULT_STYLE = C::Window::Style::DEFAULT
24
+
25
+ def initialize(*args, **opts)
26
+ mode, title = parse_args(args)
27
+ style = opts.fetch(:style, DEFAULT_STYLE)
28
+ state = opts[:fullscreen] ? :fullscreen : :windowed
29
+
30
+ ptr = C::Window.sfWindow_create(
31
+ mode.to_native,
32
+ title.to_s,
33
+ style,
34
+ C::Window::State[state],
35
+ nil,
36
+ )
37
+ raise Error, "sfWindow_create returned NULL" if ptr.null?
38
+
39
+ @handle = FFI::AutoPointer.new(ptr, C::Window.method(:sfWindow_destroy))
40
+ @event_buffer = C::Window::Event.new
41
+
42
+ self.framerate_limit = opts[:framerate] if opts[:framerate]
43
+ self.vsync = opts[:vsync] unless opts[:vsync].nil?
44
+ end
45
+
46
+ def open?
47
+ C::Window.sfWindow_isOpen(@handle)
48
+ end
49
+
50
+ def close
51
+ C::Window.sfWindow_close(@handle)
52
+ self
53
+ end
54
+
55
+ def display
56
+ C::Window.sfWindow_display(@handle)
57
+ self
58
+ end
59
+
60
+ # Returns the next pending Event or nil. Same shape as RenderWindow#poll_event.
61
+ def poll_event
62
+ return nil unless C::Window.sfWindow_pollEvent(@handle, @event_buffer)
63
+ Event.from_native(@event_buffer)
64
+ end
65
+
66
+ def each_event
67
+ return enum_for(:each_event) unless block_given?
68
+ while (event = poll_event)
69
+ yield event
70
+ end
71
+ self
72
+ end
73
+
74
+ def title=(value)
75
+ C::Window.sfWindow_setTitle(@handle, value.to_s)
76
+ end
77
+
78
+ def size
79
+ v = C::Window.sfWindow_getSize(@handle)
80
+ Vector2.new(v[:x], v[:y])
81
+ end
82
+
83
+ def size=(value)
84
+ vec = value.is_a?(Vector2) ? value : Vector2.new(*value)
85
+ v = C::System::Vector2u.new
86
+ v[:x] = Integer(vec.x); v[:y] = Integer(vec.y)
87
+ C::Window.sfWindow_setSize(@handle, v)
88
+ end
89
+
90
+ def position
91
+ v = C::Window.sfWindow_getPosition(@handle)
92
+ Vector2.new(v[:x], v[:y])
93
+ end
94
+
95
+ def position=(value)
96
+ vec = value.is_a?(Vector2) ? value : Vector2.new(*value)
97
+ v = C::System::Vector2i.new
98
+ v[:x] = Integer(vec.x); v[:y] = Integer(vec.y)
99
+ C::Window.sfWindow_setPosition(@handle, v)
100
+ end
101
+
102
+ def visible=(value)
103
+ C::Window.sfWindow_setVisible(@handle, value ? true : false)
104
+ end
105
+
106
+ def framerate_limit=(value)
107
+ C::Window.sfWindow_setFramerateLimit(@handle, Integer(value))
108
+ end
109
+
110
+ def vsync=(enabled)
111
+ C::Window.sfWindow_setVerticalSyncEnabled(@handle, enabled ? true : false)
112
+ end
113
+
114
+ def key_repeat_enabled=(value)
115
+ C::Window.sfWindow_setKeyRepeatEnabled(@handle, value ? true : false)
116
+ end
117
+
118
+ def request_focus
119
+ C::Window.sfWindow_requestFocus(@handle)
120
+ end
121
+
122
+ def focused?
123
+ C::Window.sfWindow_hasFocus(@handle)
124
+ end
125
+
126
+ # Make this window's GL context current on the calling thread.
127
+ # Useful when juggling multiple windows / off-screen contexts.
128
+ def active=(value)
129
+ C::Window.sfWindow_setActive(@handle, value ? true : false)
130
+ end
131
+
132
+ attr_reader :handle # :nodoc:
133
+
134
+ private
135
+
136
+ def parse_args(args)
137
+ case args.length
138
+ when 2
139
+ [args[0], args[1]]
140
+ when 3
141
+ [VideoMode.new(args[0], args[1]), args[2]]
142
+ else
143
+ raise ArgumentError,
144
+ "Window.new takes either (video_mode, title) or " \
145
+ "(width, height, title), got #{args.length} positional arg(s)"
146
+ end
147
+ end
148
+ end
149
+ end
data/lib/sfml.rb ADDED
@@ -0,0 +1,98 @@
1
+ require "sfml/version"
2
+
3
+ module SFML
4
+ class Error < StandardError; end
5
+ class LoadError < Error; end
6
+ end
7
+
8
+ # Tame process-exit teardown so CSFML doesn't crash.
9
+ #
10
+ # Two things race during a normal Ruby exit:
11
+ #
12
+ # 1. ObjectSpace finalizers run in non-deterministic order. CSFML's
13
+ # GL-bound resources (RenderWindow's GL context, Font glyph atlases,
14
+ # View copies) freed in the wrong sequence segfault inside the
15
+ # SFML/GL stack. Setting autorelease = false on every live
16
+ # FFI::AutoPointer skips the destruction; the OS reclaims memory
17
+ # anyway, so this costs nothing.
18
+ #
19
+ # 2. SFML's audio thread is still pumping samples while Ruby starts to
20
+ # tear the interpreter down. If a `Sound` or `Music` is mid-loop,
21
+ # OpenAL is reading buffers we're about to free → segfault inside
22
+ # libopenal. Stopping every live source first quiets the audio
23
+ # thread before anything starts disappearing.
24
+ #
25
+ # Unreferenced objects still get cleaned up at runtime via the normal
26
+ # GC cycle; we only neuter the *teardown-time* pass.
27
+ at_exit do
28
+ # 1. Capture the desired exit status before we tamper with anything.
29
+ status =
30
+ if $!.is_a?(SystemExit) then $!.status
31
+ elsif $!.nil? then 0
32
+ else 1
33
+ end
34
+
35
+ # 2. Quiet the audio thread before anything else — OpenAL holds onto
36
+ # sample buffers and crashes if Ruby starts freeing them while
37
+ # a Sound/Music is mid-loop.
38
+ ObjectSpace.each_object(SFML::Sound) { |s| s.stop rescue nil } if defined?(SFML::Sound)
39
+ ObjectSpace.each_object(SFML::Music) { |m| m.stop rescue nil } if defined?(SFML::Music)
40
+
41
+ # 3. Bypass Ruby's natural finalizer pass entirely. Process memory is
42
+ # about to be reclaimed by the kernel anyway, and Ruby's
43
+ # non-deterministic destruction order races with CSFML's GL/audio
44
+ # internals — segfaulting inside libopenal/libGL is the typical
45
+ # failure mode. exit! kills the interpreter cleanly via _exit(2).
46
+ #
47
+ # Caveat: any user `at_exit` hook registered *before* `require "sfml"`
48
+ # won't run. Hooks registered after the require run first (LIFO),
49
+ # then our hook, so the common case is unaffected.
50
+ exit!(status)
51
+ end
52
+
53
+ require "sfml/c"
54
+ require "sfml/system/time"
55
+ require "sfml/system/clock"
56
+ require "sfml/system/vector2"
57
+ require "sfml/system/vector3"
58
+ require "sfml/system/rect"
59
+ require "sfml/window/keyboard"
60
+ require "sfml/window/mouse"
61
+ require "sfml/window/joystick"
62
+ require "sfml/window/cursor"
63
+ require "sfml/window/clipboard"
64
+ require "sfml/window/video_mode"
65
+ require "sfml/window/event"
66
+ require "sfml/window/window"
67
+ require "sfml/graphics/color"
68
+ require "sfml/graphics/transformable"
69
+ require "sfml/graphics/image"
70
+ require "sfml/graphics/texture"
71
+ require "sfml/graphics/sprite"
72
+ require "sfml/graphics/circle_shape"
73
+ require "sfml/graphics/rectangle_shape"
74
+ require "sfml/graphics/convex_shape"
75
+ require "sfml/graphics/vertex"
76
+ require "sfml/graphics/vertex_array"
77
+ require "sfml/graphics/font"
78
+ require "sfml/graphics/text"
79
+ require "sfml/graphics/view"
80
+ require "sfml/graphics/blend_mode"
81
+ require "sfml/graphics/shader"
82
+ require "sfml/graphics/transform"
83
+ require "sfml/graphics/render_states"
84
+ require "sfml/graphics/render_target"
85
+ require "sfml/graphics/render_window"
86
+ require "sfml/graphics/render_texture"
87
+ require "sfml/audio/sound_buffer"
88
+ require "sfml/audio/sound"
89
+ require "sfml/audio/music"
90
+ require "sfml/audio/listener"
91
+ require "sfml/audio/sound_recorder"
92
+ require "sfml/audio/sound_buffer_recorder"
93
+ require "sfml/network/ip_address"
94
+ require "sfml/network/tcp_socket"
95
+ require "sfml/network/tcp_listener"
96
+ require "sfml/network/udp_socket"
97
+ require "sfml/assets"
98
+ require "sfml/game"
data/ruby-sfml.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ require_relative "lib/sfml/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "ruby-sfml"
5
+ spec.version = SFML::VERSION
6
+ spec.authors = ["Mykhailo Melnyk"]
7
+ spec.email = ["m1kh41l.melnyk@gmail.com"]
8
+
9
+ spec.summary = "Modern Ruby bindings for SFML 3.x"
10
+ spec.description = "Idiomatic Ruby bindings for SFML 3 via CSFML and FFI. Build games and multimedia apps in Ruby."
11
+ spec.homepage = "https://github.com/sOM2H/ruby-sfml"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = ">= 3.2.0"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = spec.homepage
17
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
18
+ spec.metadata["documentation_uri"] = "https://www.rubydoc.info/gems/#{spec.name}"
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
20
+
21
+ spec.files = Dir[
22
+ "lib/**/*.rb",
23
+ "lib/sfml/assets/**/*",
24
+ "ext/**/*.rb",
25
+ "README.md",
26
+ "CHANGELOG.md",
27
+ "LICENSE.txt",
28
+ "ruby-sfml.gemspec"
29
+ ]
30
+ spec.require_paths = ["lib"]
31
+ spec.extensions = ["ext/ruby-sfml/extconf.rb"]
32
+
33
+ spec.add_dependency "ffi", "~> 1.16"
34
+
35
+ spec.add_development_dependency "rake", "~> 13.0"
36
+ spec.add_development_dependency "rspec", "~> 3.13"
37
+ spec.add_development_dependency "rdoc", "~> 7.0"
38
+ end