rgame 0.1.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 (161) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +26 -0
  3. data/README.md +406 -0
  4. data/docs/api/README.md +167 -0
  5. data/docs/api/app.md +192 -0
  6. data/docs/api/assets.md +426 -0
  7. data/docs/api/audio.md +208 -0
  8. data/docs/api/components.md +321 -0
  9. data/docs/api/drawing.md +330 -0
  10. data/docs/api/game.md +99 -0
  11. data/docs/api/images.md +118 -0
  12. data/docs/api/input.md +179 -0
  13. data/docs/api/internals.md +110 -0
  14. data/docs/api/scene_graph.md +159 -0
  15. data/docs/api/signals.md +142 -0
  16. data/docs/api/systems.md +98 -0
  17. data/docs/api/text.md +116 -0
  18. data/docs/api/toolbox.md +240 -0
  19. data/docs/api/values.md +101 -0
  20. data/ext/README.md +225 -0
  21. data/ext/rgame_core/app/app.c +721 -0
  22. data/ext/rgame_core/app/app_gl.h +64 -0
  23. data/ext/rgame_core/app/frame_loop.c +42 -0
  24. data/ext/rgame_core/app/frame_loop.h +54 -0
  25. data/ext/rgame_core/audio/audio.c +466 -0
  26. data/ext/rgame_core/audio/audio_internal.h +45 -0
  27. data/ext/rgame_core/audio/vorbis_decoder.c +282 -0
  28. data/ext/rgame_core/audio/vorbis_decoder.h +45 -0
  29. data/ext/rgame_core/example.rb +188 -0
  30. data/ext/rgame_core/extconf.rb +167 -0
  31. data/ext/rgame_core/graphics/backend.c +52 -0
  32. data/ext/rgame_core/graphics/backend.h +64 -0
  33. data/ext/rgame_core/graphics/canvas.c +247 -0
  34. data/ext/rgame_core/graphics/canvas.h +143 -0
  35. data/ext/rgame_core/graphics/clip.c +87 -0
  36. data/ext/rgame_core/graphics/clip.h +89 -0
  37. data/ext/rgame_core/graphics/draw_queue.c +216 -0
  38. data/ext/rgame_core/graphics/draw_queue.h +174 -0
  39. data/ext/rgame_core/graphics/gl_backend.c +122 -0
  40. data/ext/rgame_core/graphics/gl_backend.h +43 -0
  41. data/ext/rgame_core/graphics/image.c +304 -0
  42. data/ext/rgame_core/graphics/image_internal.h +30 -0
  43. data/ext/rgame_core/graphics/primitives.c +189 -0
  44. data/ext/rgame_core/graphics/primitives.h +111 -0
  45. data/ext/rgame_core/graphics/recording.c +119 -0
  46. data/ext/rgame_core/graphics/recording.h +88 -0
  47. data/ext/rgame_core/graphics/texture.c +181 -0
  48. data/ext/rgame_core/graphics/texture.h +165 -0
  49. data/ext/rgame_core/graphics/transform.c +128 -0
  50. data/ext/rgame_core/graphics/transform.h +106 -0
  51. data/ext/rgame_core/include/rgame/core.h +577 -0
  52. data/ext/rgame_core/input/device_slots.c +103 -0
  53. data/ext/rgame_core/input/device_slots.h +93 -0
  54. data/ext/rgame_core/input/gamepad.c +145 -0
  55. data/ext/rgame_core/input/gamepad.h +63 -0
  56. data/ext/rgame_core/input/input.c +109 -0
  57. data/ext/rgame_core/input/input.h +99 -0
  58. data/ext/rgame_core/ruby/audio_ext.c +321 -0
  59. data/ext/rgame_core/ruby/core_ext.c +513 -0
  60. data/ext/rgame_core/ruby/core_ext.h +51 -0
  61. data/ext/rgame_core/ruby/font_ext.c +168 -0
  62. data/ext/rgame_core/ruby/image_ext.c +230 -0
  63. data/ext/rgame_core/ruby/recording_ext.c +186 -0
  64. data/ext/rgame_core/ruby/renderer_ext.c +376 -0
  65. data/ext/rgame_core/text/atlas.c +59 -0
  66. data/ext/rgame_core/text/atlas.h +85 -0
  67. data/ext/rgame_core/text/font.c +281 -0
  68. data/ext/rgame_core/text/font.h +139 -0
  69. data/ext/rgame_core/text/font_atlas.c +385 -0
  70. data/ext/rgame_core/text/font_internal.h +47 -0
  71. data/ext/rgame_core/text/glyph_cache.c +142 -0
  72. data/ext/rgame_core/text/glyph_cache.h +89 -0
  73. data/ext/rgame_core/vendor/README.md +159 -0
  74. data/ext/rgame_core/vendor/miniaudio.h +95864 -0
  75. data/ext/rgame_core/vendor/miniaudio_impl.c +62 -0
  76. data/ext/rgame_core/vendor/stb_image.h +7988 -0
  77. data/ext/rgame_core/vendor/stb_image_impl.c +31 -0
  78. data/ext/rgame_core/vendor/stb_truetype.h +5079 -0
  79. data/ext/rgame_core/vendor/stb_truetype_impl.c +23 -0
  80. data/ext/rgame_core/vendor/stb_vorbis.c +5584 -0
  81. data/ext/rgame_core/vendor/stb_vorbis_impl.c +29 -0
  82. data/ext/rgame_util/color.c +19 -0
  83. data/ext/rgame_util/color.h +60 -0
  84. data/ext/rgame_util/color_ext.c +156 -0
  85. data/ext/rgame_util/extconf.rb +27 -0
  86. data/ext/rgame_util/tensor.c +186 -0
  87. data/ext/rgame_util/util_ext.c +27 -0
  88. data/ext/rgame_util/util_ext.h +16 -0
  89. data/lib/rgame/boot.rb +13 -0
  90. data/lib/rgame/core/app.rb +82 -0
  91. data/lib/rgame/core/asset_manager.rb +224 -0
  92. data/lib/rgame/core/audio.rb +124 -0
  93. data/lib/rgame/core/font.rb +49 -0
  94. data/lib/rgame/core/gamepad.rb +55 -0
  95. data/lib/rgame/core/image.rb +55 -0
  96. data/lib/rgame/core/input.rb +77 -0
  97. data/lib/rgame/core/nine_slice.rb +163 -0
  98. data/lib/rgame/core/recording.rb +52 -0
  99. data/lib/rgame/core/renderer.rb +363 -0
  100. data/lib/rgame/core/sprite_sheet.rb +108 -0
  101. data/lib/rgame/core/tile_map_renderer.rb +160 -0
  102. data/lib/rgame/core/ui_atlas.rb +86 -0
  103. data/lib/rgame/core.rb +24 -0
  104. data/lib/rgame/engine/actor.rb +53 -0
  105. data/lib/rgame/engine/animation_set.rb +49 -0
  106. data/lib/rgame/engine/animator.rb +44 -0
  107. data/lib/rgame/engine/audio_bus.rb +24 -0
  108. data/lib/rgame/engine/audio_director.rb +29 -0
  109. data/lib/rgame/engine/body.rb +49 -0
  110. data/lib/rgame/engine/cached_label.rb +33 -0
  111. data/lib/rgame/engine/camera.rb +33 -0
  112. data/lib/rgame/engine/camera_view.rb +28 -0
  113. data/lib/rgame/engine/circle_collider.rb +32 -0
  114. data/lib/rgame/engine/collision_box.rb +34 -0
  115. data/lib/rgame/engine/collision_system.rb +44 -0
  116. data/lib/rgame/engine/component.rb +30 -0
  117. data/lib/rgame/engine/components/action_trigger.rb +41 -0
  118. data/lib/rgame/engine/components/animated_sprite.rb +63 -0
  119. data/lib/rgame/engine/components/character_body.rb +70 -0
  120. data/lib/rgame/engine/components/circle_collider.rb +44 -0
  121. data/lib/rgame/engine/components/collision_world.rb +103 -0
  122. data/lib/rgame/engine/components/despawn_offscreen.rb +26 -0
  123. data/lib/rgame/engine/components/path_follow.rb +84 -0
  124. data/lib/rgame/engine/components/player_controller.rb +24 -0
  125. data/lib/rgame/engine/components/pool.rb +53 -0
  126. data/lib/rgame/engine/components/screen_wrap.rb +27 -0
  127. data/lib/rgame/engine/components/sprite.rb +31 -0
  128. data/lib/rgame/engine/components/targeting.rb +54 -0
  129. data/lib/rgame/engine/components/thrust_controller.rb +65 -0
  130. data/lib/rgame/engine/components/tile_world.rb +68 -0
  131. data/lib/rgame/engine/components/timer.rb +75 -0
  132. data/lib/rgame/engine/components/velocity.rb +27 -0
  133. data/lib/rgame/engine/components/wander_controller.rb +60 -0
  134. data/lib/rgame/engine/debug_overlay.rb +106 -0
  135. data/lib/rgame/engine/i18n.rb +97 -0
  136. data/lib/rgame/engine/input/action_mapper.rb +46 -0
  137. data/lib/rgame/engine/input/actions.rb +41 -0
  138. data/lib/rgame/engine/input/player_controller.rb +14 -0
  139. data/lib/rgame/engine/matrix.rb +32 -0
  140. data/lib/rgame/engine/node2d.rb +271 -0
  141. data/lib/rgame/engine/path.rb +78 -0
  142. data/lib/rgame/engine/pool.rb +51 -0
  143. data/lib/rgame/engine/resettable.rb +67 -0
  144. data/lib/rgame/engine/scene/scene_stack.rb +65 -0
  145. data/lib/rgame/engine/signal.rb +75 -0
  146. data/lib/rgame/engine/spatial_hash.rb +71 -0
  147. data/lib/rgame/engine/tile_collision.rb +78 -0
  148. data/lib/rgame/engine/tile_map.rb +149 -0
  149. data/lib/rgame/engine/tileset.rb +101 -0
  150. data/lib/rgame/engine/timer.rb +51 -0
  151. data/lib/rgame/engine.rb +68 -0
  152. data/lib/rgame/fonts/LiberationSans-Regular.ttf +0 -0
  153. data/lib/rgame/fonts/OFL.txt +102 -0
  154. data/lib/rgame/game.rb +129 -0
  155. data/lib/rgame/util/color.rb +27 -0
  156. data/lib/rgame/util/controls.rb +107 -0
  157. data/lib/rgame/util/tensor.rb +12 -0
  158. data/lib/rgame/util.rb +8 -0
  159. data/lib/rgame/version.rb +12 -0
  160. data/lib/rgame.rb +20 -0
  161. metadata +215 -0
data/lib/rgame/game.rb ADDED
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'boot'
4
+ require_relative 'core'
5
+ require_relative 'engine'
6
+
7
+ module RGame
8
+ # The entry point of a game, and the one class that knows both halves.
9
+ #
10
+ # class HelloScene < RGame::Engine::Node2D
11
+ # def on_draw(renderer) = renderer.text('Hello world!', 250, 200)
12
+ # end
13
+ #
14
+ # RGame::Game.new(root: HelloScene.new, caption: 'Hello').start
15
+ #
16
+ # A complete game is a root node plus that. `Game` assembles the pieces
17
+ # around it — the window and its loop, the renderer, the asset manager, the
18
+ # sound device, the input mapper, the debug overlay — and drives the root
19
+ # node once per tick.
20
+ #
21
+ # ## Why this class is allowed to name both layers
22
+ #
23
+ # `RGame::Engine` holds game concepts and may not name `RGame::Core`;
24
+ # `RGame::Core` owns handles and may not know Engine exists. Two RuboCop cops
25
+ # say so. Something still has to introduce them, and **this is that
26
+ # something** — see CLAUDE.md, "The rule points both ways". Keeping the
27
+ # introduction to one file is what makes the rule checkable everywhere else,
28
+ # so wiring belongs here and only here.
29
+ #
30
+ # The tile-map loader is the clearest case. Parsing a `.tmx` is Engine's job
31
+ # and drawing one is Core's, and neither may call the other, so `Game`
32
+ # installs the loader that joins them.
33
+ #
34
+ # ## The loop
35
+ #
36
+ # `Game` is an `App`, so it inherits the fixed-timestep loop rather than
37
+ # running one. Its hooks do three things: sample input once per frame, drive
38
+ # the root once per tick, and draw. Nothing here counts steps or measures
39
+ # time — `frame_loop.c` does that, and `update` is called once per whole tick.
40
+ class Game < RGame::Core::App
41
+ Controls = RGame::Util::Controls
42
+
43
+ WIDTH = 640
44
+ HEIGHT = 480
45
+
46
+ attr_reader :root, :renderer, :action_mapper
47
+
48
+ def initialize(root:, width: WIDTH, height: HEIGHT, caption: 'RGame',
49
+ media_root: 'media', action_map: {})
50
+ super(width: width, height: height, caption: caption, media_root: media_root)
51
+
52
+ @root = root
53
+ @renderer = RGame::Core::Renderer.new(self)
54
+ @input = RGame::Core::Input.new(self)
55
+ @action_mapper = RGame::Engine::ActionMapper.new(action_map)
56
+ @overlay = RGame::Engine::DebugOverlay.new # always wired up; F1 reveals it
57
+ @dirty = true # draw the first frame
58
+
59
+ install_asset_loaders
60
+ end
61
+
62
+ # Brings the tree live and runs until the window closes.
63
+ #
64
+ # The root gets this object as its `context`, which is how a node deep in
65
+ # the tree reaches the asset manager (`node.root.context.assets`) without
66
+ # anything being threaded through its constructor.
67
+ def start
68
+ @root.context = self
69
+ @root.enter_tree # components attach, then on_add
70
+ run
71
+ end
72
+
73
+ # One fixed simulation tick. `dt` is always the engine's fixed step, so the
74
+ # tree never sees variable frame time.
75
+ #
76
+ # **Input is polled here, per tick, not in `frame_begin` per frame.** That
77
+ # is not where it started, and the reason is edge detection: `pressed?` is
78
+ # "held now, not held at the previous poll", so whatever polls decides what
79
+ # a press *is*. `frame_begin` runs once per rendered frame, and a loop that
80
+ # renders faster than it simulates runs it many times between two ticks —
81
+ # each one shifting the previous state, so the press is consumed by a poll
82
+ # no tick ever reads. Menus stop responding, and only on fast machines.
83
+ #
84
+ # Polling per tick costs nothing extra and loses nothing: the C layer
85
+ # snapshots the keyboard once per frame, so several ticks inside one frame
86
+ # read identical state, and the edge lands on the first of them — one press,
87
+ # one `pressed?`, which is what a caller means.
88
+ def update(dt)
89
+ @root.control(@action_mapper.poll(@input))
90
+ @root.update(dt)
91
+ @root.sweep_freed # flush queue_free'd nodes outside the update traversal
92
+ @dirty = true
93
+ end
94
+
95
+ # Only the simulation advancing makes the frame stale. While the overlay is
96
+ # up, redraw anyway, so its numbers stay live even when nothing is moving.
97
+ def needs_redraw? = @dirty || @overlay.visible?
98
+
99
+ def draw
100
+ @root.draw(@renderer)
101
+ @overlay.draw(@renderer, width, height, fps) # last, so it layers on top
102
+ @dirty = false
103
+ end
104
+
105
+ def button_down(id)
106
+ close if id == Controls::KEY_ESCAPE
107
+ @overlay.toggle if id == Controls::KEY_F1
108
+ end
109
+
110
+ private
111
+
112
+ # Teaches the asset manager the types Core cannot build for itself.
113
+ #
114
+ # `:tilemap` is the only one so far, and it is the reason this method
115
+ # exists: `RGame::Engine::TileMap` reads the `.tmx`, `Image#tiles` slices the
116
+ # tileset through the cache — so two maps sharing a tileset share one
117
+ # upload — and `Core::TileMapRenderer` draws the result. Three objects, and
118
+ # neither of the outer two may name the other.
119
+ def install_asset_loaders
120
+ game = self
121
+ assets.add_loader(:tilemap) do |path|
122
+ map, image_path = RGame::Engine::TileMap.load(path)
123
+ tiles = game.assets.image(image_path)
124
+ .tiles(map.tileset.tile_width, map.tileset.tile_height)
125
+ RGame::Core::TileMapRenderer.new(map, tiles)
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RGame::Util::Color is implemented in C — see ext/rgame_util/color_ext.c for
4
+ # the Ruby binding and ext/rgame_util/color.c for the packing arithmetic.
5
+ #
6
+ # Color = RGame::Util::Color
7
+ # Color.new(255, 128, 0) # r, g, b, a defaults to 255
8
+ # Color.rgba(255, 128, 0, 200) # the same thing, named
9
+ # Color.from_packed(0xFF8000FF) # 0xRRGGBBAA
10
+ # Color::WHITE # also BLACK and TRANSPARENT
11
+ #
12
+ # c.r; c.g; c.b; c.a # => Integer, 0..255
13
+ # c.packed # => Integer, 0xRRGGBBAA
14
+ #
15
+ # Instances are frozen and compare by value, so a Color works as a Hash key and
16
+ # can be shared without anyone tinting it out from under its other holders.
17
+ #
18
+ # Every draw call accepts a colour as nil (white), [r, g, b], [r, g, b, a] or a
19
+ # Color; `Color.coerce` is the single place that conversion happens.
20
+ #
21
+ # A colour is a *value* — no window, no GPU handle — so it lives in Util rather
22
+ # than Core. That is what lets the engine layer hold one as an attribute; see
23
+ # CLAUDE.md, "Value objects go in Util; only handle-owners go in Core".
24
+ #
25
+ # It loads from lib/rgame/util_ext.so, which `make ext-util` copies out of
26
+ # ext/rgame_util/.
27
+ require 'rgame/util_ext'
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RGame
4
+ module Util
5
+ # The vocabulary of physical inputs: which integer means "the left arrow
6
+ # key", "the A button", "the left stick's X axis", "player 2's controller".
7
+ #
8
+ # These are values — plain integers with no window, GPU or OS handle behind
9
+ # them — so they live in Util rather than Core. That is what lets the engine
10
+ # layer and a game's own configuration name a physical input without
11
+ # touching RGame::Core, which they may not do:
12
+ #
13
+ # bindings = Controls::DEFAULT_KEYBOARD.merge(fire: Controls::KEY_J)
14
+ # RGame::Core::Input.new(app, bindings: bindings)
15
+ #
16
+ # The same numbers exist as `#define`s in
17
+ # ext/rgame_core/include/rgame/core.h, because the C engine and the
18
+ # standalone binary need them too and cannot see Ruby. Two definitions means
19
+ # a drift risk, so it is checked: the C side is tied to SDL's own scancodes
20
+ # by _Static_assert at compile time, and spec/rgame/util/controls_spec.rb
21
+ # parses that header and compares every value here against it.
22
+ module Controls
23
+ # --- Keyboard. Values are SDL scancodes. ---
24
+ KEY_RETURN = 40
25
+ KEY_ESCAPE = 41
26
+ KEY_SPACE = 44
27
+ KEY_F1 = 58
28
+ KEY_RIGHT = 79
29
+ KEY_LEFT = 80
30
+ KEY_DOWN = 81
31
+ KEY_UP = 82
32
+
33
+ # --- Gamepad buttons. The gamepad range plus SDL's controller button. ---
34
+ PAD_A = 4096
35
+ PAD_B = 4097
36
+ PAD_X = 4098
37
+ PAD_Y = 4099
38
+ PAD_BACK = 4100
39
+ PAD_GUIDE = 4101
40
+ PAD_START = 4102
41
+ PAD_LEFT_STICK = 4103
42
+ PAD_RIGHT_STICK = 4104
43
+ PAD_LEFT_SHOULDER = 4105
44
+ PAD_RIGHT_SHOULDER = 4106
45
+ PAD_DPAD_UP = 4107
46
+ PAD_DPAD_DOWN = 4108
47
+ PAD_DPAD_LEFT = 4109
48
+ PAD_DPAD_RIGHT = 4110
49
+
50
+ # --- Analog axes. Their own small space: they are float-valued and read
51
+ # through a different call, so folding them into the button space would
52
+ # only invite asking for an axis as if it were a button. ---
53
+ AXIS_LEFT_X = 0
54
+ AXIS_LEFT_Y = 1
55
+ AXIS_RIGHT_X = 2
56
+ AXIS_RIGHT_Y = 3
57
+ AXIS_TRIGGER_LEFT = 4
58
+ AXIS_TRIGGER_RIGHT = 5
59
+
60
+ # --- Devices. The keyboard is 0 so single-player code can leave it out;
61
+ # gamepads follow, one per player slot. ---
62
+ KEYBOARD = 0
63
+ GAMEPAD_FIRST = 1
64
+ MAX_GAMEPADS = 4
65
+
66
+ # The device id for a player slot: gamepad(0) is the first controller.
67
+ def self.gamepad(slot) = GAMEPAD_FIRST + slot
68
+
69
+ # --- Default bindings ---
70
+ #
71
+ # Symbolic action => physical input. Games override these to rebind; they
72
+ # are values, so a config screen can build its own table from the
73
+ # constants above and hand it to the input layer.
74
+ #
75
+ # Two button tables rather than one, because the same action is a
76
+ # different physical input per device class: :fire is the space bar on a
77
+ # keyboard and the A button on a pad.
78
+ DEFAULT_KEYBOARD = {
79
+ left: KEY_LEFT,
80
+ right: KEY_RIGHT,
81
+ up: KEY_UP,
82
+ down: KEY_DOWN,
83
+ confirm: KEY_RETURN,
84
+ fire: KEY_SPACE
85
+ }.freeze
86
+
87
+ DEFAULT_PAD = {
88
+ left: PAD_DPAD_LEFT,
89
+ right: PAD_DPAD_RIGHT,
90
+ up: PAD_DPAD_UP,
91
+ down: PAD_DPAD_DOWN,
92
+ confirm: PAD_A,
93
+ fire: PAD_A
94
+ }.freeze
95
+
96
+ # Analog axes exist only on pads, so there is one table.
97
+ DEFAULT_AXES = {
98
+ move_x: AXIS_LEFT_X,
99
+ move_y: AXIS_LEFT_Y,
100
+ aim_x: AXIS_RIGHT_X,
101
+ aim_y: AXIS_RIGHT_Y,
102
+ trigger_left: AXIS_TRIGGER_LEFT,
103
+ trigger_right: AXIS_TRIGGER_RIGHT
104
+ }.freeze
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RGame::Util::Tensor is implemented in C — see ext/rgame_util/tensor.c. It used
4
+ # to be a pure-Ruby class here; the public API (RGame::Util::Tensor.new(width,
5
+ # height, depth, initial: nil), #[], #[]=, #width/#height/#depth) is unchanged,
6
+ # only the backing implementation moved to C for speed and a compact flat-array
7
+ # layout.
8
+ #
9
+ # The compiled extension is a separate .so from the SDL/GL engine, so requiring
10
+ # Tensor pulls in no graphics libraries. It loads from lib/rgame/util_ext.so,
11
+ # which the build (`make ext-util`) copies out of ext/rgame_util/.
12
+ require 'rgame/util_ext'
data/lib/rgame/util.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # RGame::Util — everything that does NOT depend on SDL, OpenGL, or anything
4
+ # built on them. Backed by the graphics-free extension in ext/rgame_util/.
5
+ # Its counterpart is RGame::Core (see lib/rgame/core.rb).
6
+ require_relative 'util/color'
7
+ require_relative 'util/controls'
8
+ require_relative 'util/tensor'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The gem's version, and deliberately nothing else.
4
+ #
5
+ # rgame.gemspec loads this file directly to fill in `spec.version`, which
6
+ # happens before either extension is compiled — so this file must never require
7
+ # anything that reaches for `rgame/util_ext` or `rgame/core_ext`. Reopening the
8
+ # module here is enough; the extensions define `RGame` too, and doing so twice
9
+ # is harmless.
10
+ module RGame
11
+ VERSION = '0.1.0'
12
+ end
data/lib/rgame.rb ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Entry point for `require "rgame"`: everything that runs without a window.
4
+ #
5
+ # require 'rgame' # RGame::Util + RGame::Engine — no graphics libraries
6
+ # require 'rgame/core' # adds the window, the GPU and the sound device
7
+ # require 'rgame/game' # all of it, wired together
8
+ #
9
+ # Each line is a strict superset of the one above, and the split is the point.
10
+ # **This one loads no SDL and no OpenGL** — `RGame::Util` is a graphics-free
11
+ # extension and `RGame::Engine` is pure Ruby — so game logic and the specs that
12
+ # cover it run with no display present. `spec/rgame/no_graphics_spec.rb` holds
13
+ # that up rather than leaving it to good intentions.
14
+ #
15
+ # Nothing is forced through this file. `rgame/util`, `rgame/engine` and
16
+ # `rgame/core` are separately requirable, which is how the Core spec suite loads
17
+ # exactly one layer and gets a `NameError` if it reaches for another.
18
+ require_relative 'rgame/version'
19
+ require_relative 'rgame/util'
20
+ require_relative 'rgame/engine'
metadata ADDED
@@ -0,0 +1,215 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rgame
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Paul Süßenbach
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: |
13
+ rgame is a 2D game engine written in C on top of SDL2 and OpenGL and exposed
14
+ to Ruby as C extensions. It opens a window, runs a fixed-timestep main loop,
15
+ reads keyboard and controllers, loads PNGs onto the GPU and draws shapes and
16
+ sprites through a z-sorted batching renderer.
17
+
18
+ Everything Ruby-visible lives under the RGame module, split in two by what it
19
+ depends on. RGame::Core owns the window, the GPU and the OS handles;
20
+ RGame::Util holds the shareable value types and links no graphics libraries
21
+ at all, so `require "rgame"` gives you the pure half with no SDL or OpenGL in
22
+ the process and pure-logic code stays testable with no display.
23
+ email:
24
+ - 2452696+psuessenb@users.noreply.github.com
25
+ executables: []
26
+ extensions:
27
+ - ext/rgame_core/extconf.rb
28
+ - ext/rgame_util/extconf.rb
29
+ extra_rdoc_files: []
30
+ files:
31
+ - LICENSE
32
+ - README.md
33
+ - docs/api/README.md
34
+ - docs/api/app.md
35
+ - docs/api/assets.md
36
+ - docs/api/audio.md
37
+ - docs/api/components.md
38
+ - docs/api/drawing.md
39
+ - docs/api/game.md
40
+ - docs/api/images.md
41
+ - docs/api/input.md
42
+ - docs/api/internals.md
43
+ - docs/api/scene_graph.md
44
+ - docs/api/signals.md
45
+ - docs/api/systems.md
46
+ - docs/api/text.md
47
+ - docs/api/toolbox.md
48
+ - docs/api/values.md
49
+ - ext/README.md
50
+ - ext/rgame_core/app/app.c
51
+ - ext/rgame_core/app/app_gl.h
52
+ - ext/rgame_core/app/frame_loop.c
53
+ - ext/rgame_core/app/frame_loop.h
54
+ - ext/rgame_core/audio/audio.c
55
+ - ext/rgame_core/audio/audio_internal.h
56
+ - ext/rgame_core/audio/vorbis_decoder.c
57
+ - ext/rgame_core/audio/vorbis_decoder.h
58
+ - ext/rgame_core/example.rb
59
+ - ext/rgame_core/extconf.rb
60
+ - ext/rgame_core/graphics/backend.c
61
+ - ext/rgame_core/graphics/backend.h
62
+ - ext/rgame_core/graphics/canvas.c
63
+ - ext/rgame_core/graphics/canvas.h
64
+ - ext/rgame_core/graphics/clip.c
65
+ - ext/rgame_core/graphics/clip.h
66
+ - ext/rgame_core/graphics/draw_queue.c
67
+ - ext/rgame_core/graphics/draw_queue.h
68
+ - ext/rgame_core/graphics/gl_backend.c
69
+ - ext/rgame_core/graphics/gl_backend.h
70
+ - ext/rgame_core/graphics/image.c
71
+ - ext/rgame_core/graphics/image_internal.h
72
+ - ext/rgame_core/graphics/primitives.c
73
+ - ext/rgame_core/graphics/primitives.h
74
+ - ext/rgame_core/graphics/recording.c
75
+ - ext/rgame_core/graphics/recording.h
76
+ - ext/rgame_core/graphics/texture.c
77
+ - ext/rgame_core/graphics/texture.h
78
+ - ext/rgame_core/graphics/transform.c
79
+ - ext/rgame_core/graphics/transform.h
80
+ - ext/rgame_core/include/rgame/core.h
81
+ - ext/rgame_core/input/device_slots.c
82
+ - ext/rgame_core/input/device_slots.h
83
+ - ext/rgame_core/input/gamepad.c
84
+ - ext/rgame_core/input/gamepad.h
85
+ - ext/rgame_core/input/input.c
86
+ - ext/rgame_core/input/input.h
87
+ - ext/rgame_core/ruby/audio_ext.c
88
+ - ext/rgame_core/ruby/core_ext.c
89
+ - ext/rgame_core/ruby/core_ext.h
90
+ - ext/rgame_core/ruby/font_ext.c
91
+ - ext/rgame_core/ruby/image_ext.c
92
+ - ext/rgame_core/ruby/recording_ext.c
93
+ - ext/rgame_core/ruby/renderer_ext.c
94
+ - ext/rgame_core/text/atlas.c
95
+ - ext/rgame_core/text/atlas.h
96
+ - ext/rgame_core/text/font.c
97
+ - ext/rgame_core/text/font.h
98
+ - ext/rgame_core/text/font_atlas.c
99
+ - ext/rgame_core/text/font_internal.h
100
+ - ext/rgame_core/text/glyph_cache.c
101
+ - ext/rgame_core/text/glyph_cache.h
102
+ - ext/rgame_core/vendor/README.md
103
+ - ext/rgame_core/vendor/miniaudio.h
104
+ - ext/rgame_core/vendor/miniaudio_impl.c
105
+ - ext/rgame_core/vendor/stb_image.h
106
+ - ext/rgame_core/vendor/stb_image_impl.c
107
+ - ext/rgame_core/vendor/stb_truetype.h
108
+ - ext/rgame_core/vendor/stb_truetype_impl.c
109
+ - ext/rgame_core/vendor/stb_vorbis.c
110
+ - ext/rgame_core/vendor/stb_vorbis_impl.c
111
+ - ext/rgame_util/color.c
112
+ - ext/rgame_util/color.h
113
+ - ext/rgame_util/color_ext.c
114
+ - ext/rgame_util/extconf.rb
115
+ - ext/rgame_util/tensor.c
116
+ - ext/rgame_util/util_ext.c
117
+ - ext/rgame_util/util_ext.h
118
+ - lib/rgame.rb
119
+ - lib/rgame/boot.rb
120
+ - lib/rgame/core.rb
121
+ - lib/rgame/core/app.rb
122
+ - lib/rgame/core/asset_manager.rb
123
+ - lib/rgame/core/audio.rb
124
+ - lib/rgame/core/font.rb
125
+ - lib/rgame/core/gamepad.rb
126
+ - lib/rgame/core/image.rb
127
+ - lib/rgame/core/input.rb
128
+ - lib/rgame/core/nine_slice.rb
129
+ - lib/rgame/core/recording.rb
130
+ - lib/rgame/core/renderer.rb
131
+ - lib/rgame/core/sprite_sheet.rb
132
+ - lib/rgame/core/tile_map_renderer.rb
133
+ - lib/rgame/core/ui_atlas.rb
134
+ - lib/rgame/engine.rb
135
+ - lib/rgame/engine/actor.rb
136
+ - lib/rgame/engine/animation_set.rb
137
+ - lib/rgame/engine/animator.rb
138
+ - lib/rgame/engine/audio_bus.rb
139
+ - lib/rgame/engine/audio_director.rb
140
+ - lib/rgame/engine/body.rb
141
+ - lib/rgame/engine/cached_label.rb
142
+ - lib/rgame/engine/camera.rb
143
+ - lib/rgame/engine/camera_view.rb
144
+ - lib/rgame/engine/circle_collider.rb
145
+ - lib/rgame/engine/collision_box.rb
146
+ - lib/rgame/engine/collision_system.rb
147
+ - lib/rgame/engine/component.rb
148
+ - lib/rgame/engine/components/action_trigger.rb
149
+ - lib/rgame/engine/components/animated_sprite.rb
150
+ - lib/rgame/engine/components/character_body.rb
151
+ - lib/rgame/engine/components/circle_collider.rb
152
+ - lib/rgame/engine/components/collision_world.rb
153
+ - lib/rgame/engine/components/despawn_offscreen.rb
154
+ - lib/rgame/engine/components/path_follow.rb
155
+ - lib/rgame/engine/components/player_controller.rb
156
+ - lib/rgame/engine/components/pool.rb
157
+ - lib/rgame/engine/components/screen_wrap.rb
158
+ - lib/rgame/engine/components/sprite.rb
159
+ - lib/rgame/engine/components/targeting.rb
160
+ - lib/rgame/engine/components/thrust_controller.rb
161
+ - lib/rgame/engine/components/tile_world.rb
162
+ - lib/rgame/engine/components/timer.rb
163
+ - lib/rgame/engine/components/velocity.rb
164
+ - lib/rgame/engine/components/wander_controller.rb
165
+ - lib/rgame/engine/debug_overlay.rb
166
+ - lib/rgame/engine/i18n.rb
167
+ - lib/rgame/engine/input/action_mapper.rb
168
+ - lib/rgame/engine/input/actions.rb
169
+ - lib/rgame/engine/input/player_controller.rb
170
+ - lib/rgame/engine/matrix.rb
171
+ - lib/rgame/engine/node2d.rb
172
+ - lib/rgame/engine/path.rb
173
+ - lib/rgame/engine/pool.rb
174
+ - lib/rgame/engine/resettable.rb
175
+ - lib/rgame/engine/scene/scene_stack.rb
176
+ - lib/rgame/engine/signal.rb
177
+ - lib/rgame/engine/spatial_hash.rb
178
+ - lib/rgame/engine/tile_collision.rb
179
+ - lib/rgame/engine/tile_map.rb
180
+ - lib/rgame/engine/tileset.rb
181
+ - lib/rgame/engine/timer.rb
182
+ - lib/rgame/fonts/LiberationSans-Regular.ttf
183
+ - lib/rgame/fonts/OFL.txt
184
+ - lib/rgame/game.rb
185
+ - lib/rgame/util.rb
186
+ - lib/rgame/util/color.rb
187
+ - lib/rgame/util/controls.rb
188
+ - lib/rgame/util/tensor.rb
189
+ - lib/rgame/version.rb
190
+ homepage: https://github.com/psuessenb/rgame
191
+ licenses:
192
+ - MIT
193
+ metadata:
194
+ source_code_uri: https://github.com/psuessenb/rgame
195
+ bug_tracker_uri: https://github.com/psuessenb/rgame/issues
196
+ documentation_uri: https://github.com/psuessenb/rgame/blob/main/docs/api/README.md
197
+ rubygems_mfa_required: 'true'
198
+ rdoc_options: []
199
+ require_paths:
200
+ - lib
201
+ required_ruby_version: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ version: '4.0'
206
+ required_rubygems_version: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
211
+ requirements: []
212
+ rubygems_version: 4.0.10
213
+ specification_version: 4
214
+ summary: A 2D game engine in C on SDL2 and OpenGL, exposed to Ruby.
215
+ test_files: []