ruby2d 0.12.0 → 1.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 (619) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +7 -0
  3. data/README.md +141 -0
  4. data/USAGE.md +2435 -0
  5. data/assets/Rakefile +637 -0
  6. data/assets/build_support/CMakeLists.txt +94 -0
  7. data/assets/build_support/mruby/build_config.rb +34 -0
  8. data/assets/build_support/mruby/build_config_wasm.rb +30 -0
  9. data/assets/build_support/sdl_test.c +174 -0
  10. data/assets/deps.yaml +16 -0
  11. data/assets/platform/include/SDL3/SDL.h +91 -0
  12. data/assets/platform/include/SDL3/SDL_assert.h +705 -0
  13. data/assets/platform/include/SDL3/SDL_asyncio.h +550 -0
  14. data/assets/platform/include/SDL3/SDL_atomic.h +692 -0
  15. data/assets/platform/include/SDL3/SDL_audio.h +2370 -0
  16. data/assets/platform/include/SDL3/SDL_begin_code.h +553 -0
  17. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_bits.h +47 -27
  18. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_blendmode.h +59 -55
  19. data/assets/platform/include/SDL3/SDL_camera.h +535 -0
  20. data/assets/platform/include/SDL3/SDL_clipboard.h +331 -0
  21. data/assets/{include/SDL2/close_code.h → platform/include/SDL3/SDL_close_code.h} +9 -8
  22. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_copying.h +3 -1
  23. data/assets/platform/include/SDL3/SDL_cpuinfo.h +374 -0
  24. data/assets/platform/include/SDL3/SDL_dialog.h +343 -0
  25. data/assets/platform/include/SDL3/SDL_dlopennote.h +234 -0
  26. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_egl.h +11 -8
  27. data/assets/platform/include/SDL3/SDL_endian.h +645 -0
  28. data/assets/platform/include/SDL3/SDL_error.h +226 -0
  29. data/assets/platform/include/SDL3/SDL_events.h +1645 -0
  30. data/assets/platform/include/SDL3/SDL_filesystem.h +537 -0
  31. data/assets/platform/include/SDL3/SDL_gamepad.h +1656 -0
  32. data/assets/platform/include/SDL3/SDL_gpu.h +4608 -0
  33. data/assets/platform/include/SDL3/SDL_guid.h +106 -0
  34. data/assets/platform/include/SDL3/SDL_haptic.h +1461 -0
  35. data/assets/platform/include/SDL3/SDL_hidapi.h +571 -0
  36. data/assets/platform/include/SDL3/SDL_hints.h +5001 -0
  37. data/assets/platform/include/SDL3/SDL_init.h +507 -0
  38. data/assets/platform/include/SDL3/SDL_intrin.h +410 -0
  39. data/assets/platform/include/SDL3/SDL_iostream.h +1379 -0
  40. data/assets/platform/include/SDL3/SDL_joystick.h +1385 -0
  41. data/assets/platform/include/SDL3/SDL_keyboard.h +608 -0
  42. data/assets/platform/include/SDL3/SDL_keycode.h +347 -0
  43. data/assets/platform/include/SDL3/SDL_loadso.h +145 -0
  44. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_locale.h +40 -24
  45. data/assets/platform/include/SDL3/SDL_log.h +541 -0
  46. data/assets/platform/include/SDL3/SDL_main.h +704 -0
  47. data/assets/platform/include/SDL3/SDL_main_impl.h +151 -0
  48. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_messagebox.h +85 -48
  49. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_metal.h +29 -29
  50. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_misc.h +13 -12
  51. data/assets/platform/include/SDL3/SDL_mouse.h +813 -0
  52. data/assets/platform/include/SDL3/SDL_mutex.h +1117 -0
  53. data/assets/platform/include/SDL3/SDL_oldnames.h +1339 -0
  54. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl.h +1247 -278
  55. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl_glext.h +5 -1
  56. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles.h +6 -7
  57. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2.h +10 -11
  58. data/assets/platform/include/SDL3/SDL_pen.h +198 -0
  59. data/assets/platform/include/SDL3/SDL_pixels.h +1441 -0
  60. data/assets/{include/SDL2/SDL_test_log.h → platform/include/SDL3/SDL_platform.h} +25 -26
  61. data/assets/platform/include/SDL3/SDL_platform_defines.h +497 -0
  62. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_power.h +40 -20
  63. data/assets/platform/include/SDL3/SDL_process.h +441 -0
  64. data/assets/platform/include/SDL3/SDL_properties.h +572 -0
  65. data/assets/platform/include/SDL3/SDL_rect.h +528 -0
  66. data/assets/platform/include/SDL3/SDL_render.h +3028 -0
  67. data/assets/platform/include/SDL3/SDL_revision.h +59 -0
  68. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_scancode.h +59 -68
  69. data/assets/platform/include/SDL3/SDL_sensor.h +321 -0
  70. data/assets/platform/include/SDL3/SDL_stdinc.h +6186 -0
  71. data/assets/platform/include/SDL3/SDL_storage.h +686 -0
  72. data/assets/platform/include/SDL3/SDL_surface.h +1769 -0
  73. data/assets/platform/include/SDL3/SDL_system.h +840 -0
  74. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test.h +16 -22
  75. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_assert.h +27 -34
  76. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_common.h +109 -52
  77. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_compare.h +22 -14
  78. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_crc32.h +27 -30
  79. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_font.h +50 -49
  80. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_fuzzer.h +64 -79
  81. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_harness.h +47 -30
  82. data/assets/platform/include/SDL3/SDL_test_log.h +83 -0
  83. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_md5.h +21 -28
  84. data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_memory.h +19 -16
  85. data/assets/platform/include/SDL3/SDL_thread.h +602 -0
  86. data/assets/platform/include/SDL3/SDL_time.h +249 -0
  87. data/assets/platform/include/SDL3/SDL_timer.h +454 -0
  88. data/assets/platform/include/SDL3/SDL_touch.h +184 -0
  89. data/assets/platform/include/SDL3/SDL_tray.h +544 -0
  90. data/assets/platform/include/SDL3/SDL_version.h +198 -0
  91. data/assets/platform/include/SDL3/SDL_video.h +3497 -0
  92. data/assets/platform/include/SDL3/SDL_vulkan.h +287 -0
  93. data/assets/platform/include/SDL3_image/SDL_image.h +3328 -0
  94. data/assets/platform/include/SDL3_mixer/SDL_mixer.h +3369 -0
  95. data/assets/platform/include/SDL3_ttf/SDL_textengine.h +181 -0
  96. data/assets/platform/include/SDL3_ttf/SDL_ttf.h +2833 -0
  97. data/assets/{include → platform/include}/mrbconf.h +42 -31
  98. data/assets/{include → platform/include}/mruby/array.h +3 -4
  99. data/assets/{include → platform/include}/mruby/boxing_nan.h +10 -0
  100. data/assets/platform/include/mruby/boxing_no.h +59 -0
  101. data/assets/{include → platform/include}/mruby/boxing_word.h +72 -26
  102. data/assets/platform/include/mruby/class.h +157 -0
  103. data/assets/{include → platform/include}/mruby/common.h +30 -1
  104. data/assets/{include → platform/include}/mruby/compile.h +52 -74
  105. data/assets/{include → platform/include}/mruby/data.h +2 -2
  106. data/assets/{include → platform/include}/mruby/debug.h +12 -5
  107. data/assets/{include → platform/include}/mruby/dump.h +7 -9
  108. data/assets/{include → platform/include}/mruby/endian.h +1 -1
  109. data/assets/platform/include/mruby/error.h +173 -0
  110. data/assets/platform/include/mruby/gc.h +79 -0
  111. data/assets/{include → platform/include}/mruby/hash.h +1 -7
  112. data/assets/platform/include/mruby/internal.h +282 -0
  113. data/assets/platform/include/mruby/irep.h +143 -0
  114. data/assets/{include → platform/include}/mruby/istruct.h +1 -1
  115. data/assets/platform/include/mruby/khash.h +455 -0
  116. data/assets/platform/include/mruby/mempool.h +19 -0
  117. data/assets/{include → platform/include}/mruby/numeric.h +7 -10
  118. data/assets/platform/include/mruby/object.h +51 -0
  119. data/assets/{include → platform/include}/mruby/opcode.h +5 -5
  120. data/assets/{include → platform/include}/mruby/ops.h +19 -6
  121. data/assets/platform/include/mruby/presym/id.h +1447 -0
  122. data/assets/{include → platform/include}/mruby/presym/scanning.h +10 -7
  123. data/assets/platform/include/mruby/presym/table.h +2893 -0
  124. data/assets/platform/include/mruby/presym.h +65 -0
  125. data/assets/platform/include/mruby/proc.h +184 -0
  126. data/assets/{include → platform/include}/mruby/range.h +0 -2
  127. data/assets/{include → platform/include}/mruby/string.h +33 -53
  128. data/assets/platform/include/mruby/throw.h +81 -0
  129. data/assets/{include → platform/include}/mruby/value.h +64 -29
  130. data/assets/{include → platform/include}/mruby/variable.h +6 -23
  131. data/assets/{include → platform/include}/mruby/version.h +7 -7
  132. data/assets/{include → platform/include}/mruby.h +238 -116
  133. data/assets/platform/macos-arm64/bin/mrbc +0 -0
  134. data/assets/platform/macos-arm64/lib/libSDL3.a +0 -0
  135. data/assets/platform/macos-arm64/lib/libSDL3_image.a +0 -0
  136. data/assets/platform/macos-arm64/lib/libSDL3_mixer.a +0 -0
  137. data/assets/platform/macos-arm64/lib/libSDL3_ttf.a +0 -0
  138. data/assets/platform/macos-arm64/lib/libmruby.a +0 -0
  139. data/assets/platform/wasm/lib/libFLAC.a +0 -0
  140. data/assets/platform/wasm/lib/libSDL3.a +0 -0
  141. data/assets/platform/wasm/lib/libSDL3_image.a +0 -0
  142. data/assets/platform/wasm/lib/libSDL3_mixer.a +0 -0
  143. data/assets/platform/wasm/lib/libSDL3_ttf.a +0 -0
  144. data/assets/platform/wasm/lib/libfreetype.a +0 -0
  145. data/assets/platform/wasm/lib/libharfbuzz.a +0 -0
  146. data/assets/platform/wasm/lib/libmruby.a +0 -0
  147. data/assets/platform/wasm/lib/libogg.a +0 -0
  148. data/assets/platform/wasm/lib/libplutosvg.a +0 -0
  149. data/assets/platform/wasm/lib/libplutovg.a +0 -0
  150. data/assets/platform/wasm/lib/libpng.a +0 -0
  151. data/assets/platform/wasm/lib/libpng16.a +0 -0
  152. data/assets/platform/wasm/lib/libvorbis.a +0 -0
  153. data/assets/platform/wasm/lib/libvorbisfile.a +0 -0
  154. data/assets/platform/wasm/lib/libzlibstatic.a +0 -0
  155. data/assets/platform/windows-arm64-mingw-ucrt/bin/mrbc.exe +0 -0
  156. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3.a +0 -0
  157. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_image.a +0 -0
  158. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
  159. data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
  160. data/assets/platform/windows-arm64-mingw-ucrt/lib/libmruby.a +0 -0
  161. data/assets/platform/windows-x86_64-mingw-ucrt/bin/mrbc.exe +0 -0
  162. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3.a +0 -0
  163. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_image.a +0 -0
  164. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
  165. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
  166. data/assets/platform/windows-x86_64-mingw-ucrt/lib/libmruby.a +0 -0
  167. data/assets/resources/fonts/outfit/OFL.txt +93 -0
  168. data/assets/resources/fonts/outfit/outfit.ttf +0 -0
  169. data/assets/resources/fonts/roboto_mono/OFL.txt +91 -0
  170. data/assets/resources/fonts/roboto_mono/roboto_mono.ttf +0 -0
  171. data/assets/resources/icons/icon.icns +0 -0
  172. data/assets/resources/icons/icon.png +0 -0
  173. data/assets/resources/spritesheets/License.txt +28 -0
  174. data/assets/resources/spritesheets/spritesheet-backgrounds.png +0 -0
  175. data/assets/resources/spritesheets/spritesheet-backgrounds.xml +16 -0
  176. data/assets/resources/spritesheets/spritesheet-characters.png +0 -0
  177. data/assets/resources/spritesheets/spritesheet-characters.xml +47 -0
  178. data/assets/resources/spritesheets/spritesheet-enemies.png +0 -0
  179. data/assets/resources/spritesheets/spritesheet-enemies.xml +62 -0
  180. data/assets/resources/spritesheets/spritesheet-tiles.png +0 -0
  181. data/assets/resources/spritesheets/spritesheet-tiles.xml +316 -0
  182. data/assets/{wasm → resources/web}/template.html +1 -1
  183. data/assets/target.rb +131 -0
  184. data/bin/ruby2d +281 -82
  185. data/examples/astar.rb +269 -0
  186. data/examples/asteroids.rb +403 -0
  187. data/examples/bezier_editor.rb +96 -0
  188. data/examples/boids.rb +191 -0
  189. data/examples/bouncing_balls.rb +119 -0
  190. data/examples/breakout.rb +186 -0
  191. data/examples/constellations.rb +100 -0
  192. data/examples/dashboard.rb +133 -0
  193. data/examples/double_pendulum.rb +254 -0
  194. data/examples/falling_sand.rb +291 -0
  195. data/examples/fireworks.rb +110 -0
  196. data/examples/fluid_dynamics.rb +340 -0
  197. data/examples/fourier_epicycles.rb +142 -0
  198. data/examples/fractal_tree.rb +326 -0
  199. data/examples/game_of_life.rb +148 -0
  200. data/examples/gamepads.rb +333 -0
  201. data/examples/hill_driver.rb +613 -0
  202. data/examples/logo_animation.rb +251 -0
  203. data/examples/lorenz_attractor.rb +115 -0
  204. data/examples/mandelbrot.rb +207 -0
  205. data/examples/marching_squares.rb +200 -0
  206. data/examples/maze.rb +323 -0
  207. data/examples/nbody.rb +338 -0
  208. data/examples/outrun.rb +391 -0
  209. data/examples/pixel_paint.rb +313 -0
  210. data/examples/platformer.rb +335 -0
  211. data/examples/ray_casting_maze.rb +175 -0
  212. data/examples/shadow_casting.rb +151 -0
  213. data/examples/shape_recognizer.rb +908 -0
  214. data/examples/snake.rb +144 -0
  215. data/examples/sprite_sheets.rb +246 -0
  216. data/examples/swarm.rb +206 -0
  217. data/examples/tsp_annealing.rb +104 -0
  218. data/examples/ui_controls.rb +163 -0
  219. data/examples/wireframe_3d.rb +139 -0
  220. data/ext/ruby2d/audio.c +324 -0
  221. data/ext/ruby2d/canvas.c +1715 -494
  222. data/ext/ruby2d/ext.c +541 -0
  223. data/ext/ruby2d/extconf.rb +122 -145
  224. data/ext/ruby2d/font.c +566 -20
  225. data/ext/ruby2d/fps.c +92 -0
  226. data/ext/ruby2d/image.c +466 -41
  227. data/ext/ruby2d/ruby2d.c +374 -1890
  228. data/ext/ruby2d/ruby2d.h +840 -460
  229. data/ext/ruby2d/shapes.c +931 -101
  230. data/ext/ruby2d/text.c +586 -21
  231. data/ext/ruby2d/window.c +1693 -283
  232. data/lib/ruby2d/atlas_parser.rb +194 -0
  233. data/lib/ruby2d/audio.rb +73 -0
  234. data/lib/ruby2d/benchmark.rb +259 -0
  235. data/lib/ruby2d/bitmap_text.rb +155 -0
  236. data/lib/ruby2d/button.rb +402 -0
  237. data/lib/ruby2d/canvas.rb +703 -279
  238. data/lib/ruby2d/circle.rb +206 -29
  239. data/lib/ruby2d/cli/browser.rb +314 -0
  240. data/lib/ruby2d/cli/build.rb +471 -257
  241. data/lib/ruby2d/cli/colorize.rb +7 -5
  242. data/lib/ruby2d/cli/examples.rb +127 -0
  243. data/lib/ruby2d/cli/launch.rb +24 -39
  244. data/lib/ruby2d/cli/lib_files.rb +48 -0
  245. data/lib/ruby2d/cli/messages.rb +40 -0
  246. data/lib/ruby2d/cli/setup.rb +273 -0
  247. data/lib/ruby2d/cli/static_server.rb +160 -0
  248. data/lib/ruby2d/cli/usage.rb +255 -0
  249. data/lib/ruby2d/color.rb +191 -69
  250. data/lib/ruby2d/core.rb +37 -19
  251. data/lib/ruby2d/deps_help.rb +89 -0
  252. data/lib/ruby2d/dsl.rb +51 -12
  253. data/lib/ruby2d/ellipse.rb +228 -0
  254. data/lib/ruby2d/exceptions.rb +0 -2
  255. data/lib/ruby2d/font.rb +34 -74
  256. data/lib/ruby2d/gamepad.rb +323 -0
  257. data/lib/ruby2d/gem_paths.rb +19 -0
  258. data/lib/ruby2d/image.rb +155 -52
  259. data/lib/ruby2d/interactive.rb +103 -0
  260. data/lib/ruby2d/json_parser.rb +268 -0
  261. data/lib/ruby2d/line.rb +194 -85
  262. data/lib/ruby2d/mruby_compat.rb +12 -0
  263. data/lib/ruby2d/polygon.rb +297 -0
  264. data/lib/ruby2d/polyline.rb +368 -0
  265. data/lib/ruby2d/quad.rb +358 -94
  266. data/lib/ruby2d/rectangle.rb +77 -19
  267. data/lib/ruby2d/renderable.rb +411 -11
  268. data/lib/ruby2d/sprite.rb +471 -180
  269. data/lib/ruby2d/sprite_sheet.rb +64 -0
  270. data/lib/ruby2d/square.rb +29 -17
  271. data/lib/ruby2d/text.rb +196 -65
  272. data/lib/ruby2d/tileset.rb +139 -81
  273. data/lib/ruby2d/triangle.rb +324 -89
  274. data/lib/ruby2d/version.rb +1 -3
  275. data/lib/ruby2d/vertices.rb +62 -85
  276. data/lib/ruby2d/warnings.rb +29 -0
  277. data/lib/ruby2d/window/class_methods.rb +218 -0
  278. data/lib/ruby2d/window/gamepad_events.rb +141 -0
  279. data/lib/ruby2d/window/key_events.rb +74 -0
  280. data/lib/ruby2d/window/mouse_events.rb +171 -0
  281. data/lib/ruby2d/window/object_events.rb +168 -0
  282. data/lib/ruby2d/window.rb +632 -585
  283. data/lib/ruby2d.rb +14 -19
  284. metadata +275 -428
  285. data/assets/app.icns +0 -0
  286. data/assets/include/GLES2/gl2.h +0 -656
  287. data/assets/include/GLES2/gl2ext.h +0 -3949
  288. data/assets/include/GLES2/gl2ext_angle.h +0 -701
  289. data/assets/include/GLES2/gl2platform.h +0 -27
  290. data/assets/include/GLES3/gl3.h +0 -1192
  291. data/assets/include/GLES3/gl31.h +0 -1507
  292. data/assets/include/GLES3/gl32.h +0 -1808
  293. data/assets/include/GLES3/gl3platform.h +0 -27
  294. data/assets/include/KHR/khrplatform.h +0 -290
  295. data/assets/include/SDL2/SDL.h +0 -233
  296. data/assets/include/SDL2/SDL_assert.h +0 -326
  297. data/assets/include/SDL2/SDL_atomic.h +0 -415
  298. data/assets/include/SDL2/SDL_audio.h +0 -1500
  299. data/assets/include/SDL2/SDL_clipboard.h +0 -141
  300. data/assets/include/SDL2/SDL_config.h +0 -61
  301. data/assets/include/SDL2/SDL_config_android.h +0 -194
  302. data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
  303. data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
  304. data/assets/include/SDL2/SDL_config_macosx.h +0 -277
  305. data/assets/include/SDL2/SDL_config_minimal.h +0 -95
  306. data/assets/include/SDL2/SDL_config_ngage.h +0 -89
  307. data/assets/include/SDL2/SDL_config_os2.h +0 -207
  308. data/assets/include/SDL2/SDL_config_pandora.h +0 -141
  309. data/assets/include/SDL2/SDL_config_windows.h +0 -331
  310. data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
  311. data/assets/include/SDL2/SDL_config_winrt.h +0 -220
  312. data/assets/include/SDL2/SDL_config_xbox.h +0 -235
  313. data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
  314. data/assets/include/SDL2/SDL_endian.h +0 -348
  315. data/assets/include/SDL2/SDL_error.h +0 -163
  316. data/assets/include/SDL2/SDL_events.h +0 -1166
  317. data/assets/include/SDL2/SDL_filesystem.h +0 -149
  318. data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
  319. data/assets/include/SDL2/SDL_gesture.h +0 -117
  320. data/assets/include/SDL2/SDL_guid.h +0 -100
  321. data/assets/include/SDL2/SDL_haptic.h +0 -1341
  322. data/assets/include/SDL2/SDL_hidapi.h +0 -451
  323. data/assets/include/SDL2/SDL_hints.h +0 -2569
  324. data/assets/include/SDL2/SDL_image.h +0 -2173
  325. data/assets/include/SDL2/SDL_joystick.h +0 -1066
  326. data/assets/include/SDL2/SDL_keyboard.h +0 -353
  327. data/assets/include/SDL2/SDL_keycode.h +0 -358
  328. data/assets/include/SDL2/SDL_loadso.h +0 -115
  329. data/assets/include/SDL2/SDL_log.h +0 -404
  330. data/assets/include/SDL2/SDL_main.h +0 -275
  331. data/assets/include/SDL2/SDL_mixer.h +0 -2784
  332. data/assets/include/SDL2/SDL_mouse.h +0 -465
  333. data/assets/include/SDL2/SDL_mutex.h +0 -471
  334. data/assets/include/SDL2/SDL_name.h +0 -33
  335. data/assets/include/SDL2/SDL_pixels.h +0 -644
  336. data/assets/include/SDL2/SDL_platform.h +0 -261
  337. data/assets/include/SDL2/SDL_quit.h +0 -58
  338. data/assets/include/SDL2/SDL_rect.h +0 -376
  339. data/assets/include/SDL2/SDL_render.h +0 -1919
  340. data/assets/include/SDL2/SDL_revision.h +0 -6
  341. data/assets/include/SDL2/SDL_rwops.h +0 -841
  342. data/assets/include/SDL2/SDL_sensor.h +0 -322
  343. data/assets/include/SDL2/SDL_shape.h +0 -155
  344. data/assets/include/SDL2/SDL_stdinc.h +0 -830
  345. data/assets/include/SDL2/SDL_surface.h +0 -997
  346. data/assets/include/SDL2/SDL_system.h +0 -623
  347. data/assets/include/SDL2/SDL_syswm.h +0 -386
  348. data/assets/include/SDL2/SDL_test_images.h +0 -78
  349. data/assets/include/SDL2/SDL_test_random.h +0 -115
  350. data/assets/include/SDL2/SDL_thread.h +0 -464
  351. data/assets/include/SDL2/SDL_timer.h +0 -222
  352. data/assets/include/SDL2/SDL_touch.h +0 -150
  353. data/assets/include/SDL2/SDL_ttf.h +0 -2316
  354. data/assets/include/SDL2/SDL_types.h +0 -29
  355. data/assets/include/SDL2/SDL_version.h +0 -204
  356. data/assets/include/SDL2/SDL_video.h +0 -2150
  357. data/assets/include/SDL2/SDL_vulkan.h +0 -215
  358. data/assets/include/SDL2/begin_code.h +0 -187
  359. data/assets/include/mruby/boxing_no.h +0 -58
  360. data/assets/include/mruby/class.h +0 -108
  361. data/assets/include/mruby/error.h +0 -147
  362. data/assets/include/mruby/gc.h +0 -94
  363. data/assets/include/mruby/irep.h +0 -147
  364. data/assets/include/mruby/khash.h +0 -284
  365. data/assets/include/mruby/object.h +0 -43
  366. data/assets/include/mruby/presym/disable.h +0 -70
  367. data/assets/include/mruby/presym/enable.h +0 -37
  368. data/assets/include/mruby/presym.h +0 -40
  369. data/assets/include/mruby/proc.h +0 -211
  370. data/assets/include/mruby/throw.h +0 -66
  371. data/assets/macos/universal/bin/mrbc +0 -0
  372. data/assets/macos/universal/lib/libFLAC.a +0 -0
  373. data/assets/macos/universal/lib/libSDL2.a +0 -0
  374. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  375. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  376. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  377. data/assets/macos/universal/lib/libavif.a +0 -0
  378. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  379. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  380. data/assets/macos/universal/lib/libfreetype.a +0 -0
  381. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  382. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  383. data/assets/macos/universal/lib/libhwy.a +0 -0
  384. data/assets/macos/universal/lib/libjpeg.a +0 -0
  385. data/assets/macos/universal/lib/libjxl.a +0 -0
  386. data/assets/macos/universal/lib/libmodplug.a +0 -0
  387. data/assets/macos/universal/lib/libmpg123.a +0 -0
  388. data/assets/macos/universal/lib/libmruby.a +0 -0
  389. data/assets/macos/universal/lib/libogg.a +0 -0
  390. data/assets/macos/universal/lib/libpng.a +0 -0
  391. data/assets/macos/universal/lib/libtiff.a +0 -0
  392. data/assets/macos/universal/lib/libvorbis.a +0 -0
  393. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  394. data/assets/macos/universal/lib/libwebp.a +0 -0
  395. data/assets/macos/universal/lib/libzstd.a +0 -0
  396. data/assets/test_media/README.md +0 -3
  397. data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
  398. data/assets/test_media/bitstream_vera/vera.ttf +0 -0
  399. data/assets/test_media/boom.png +0 -0
  400. data/assets/test_media/coin.png +0 -0
  401. data/assets/test_media/colors.png +0 -0
  402. data/assets/test_media/controller.png +0 -0
  403. data/assets/test_media/dial.wav +0 -0
  404. data/assets/test_media/hero.png +0 -0
  405. data/assets/test_media/image.bmp +0 -0
  406. data/assets/test_media/image.jpg +0 -0
  407. data/assets/test_media/image.png +0 -0
  408. data/assets/test_media/music.flac +0 -0
  409. data/assets/test_media/music.mp3 +0 -0
  410. data/assets/test_media/music.ogg +0 -0
  411. data/assets/test_media/music.wav +0 -0
  412. data/assets/test_media/originals/boom.pxm +0 -0
  413. data/assets/test_media/originals/coin.pxm +0 -0
  414. data/assets/test_media/originals/controller.sketch +0 -0
  415. data/assets/test_media/originals/hero.pxm +0 -0
  416. data/assets/test_media/originals/image.pxm +0 -0
  417. data/assets/test_media/originals/music.caf +0 -0
  418. data/assets/test_media/originals/texture_atlas.pxm +0 -0
  419. data/assets/test_media/rondo_alla_turka.ogg +0 -0
  420. data/assets/test_media/sound.flac +0 -0
  421. data/assets/test_media/sound.mp3 +0 -0
  422. data/assets/test_media/sound.ogg +0 -0
  423. data/assets/test_media/sound.wav +0 -0
  424. data/assets/test_media/sprite_sheet.png +0 -0
  425. data/assets/test_media/texture_atlas.png +0 -0
  426. data/assets/wasm/libmruby.a +0 -0
  427. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  428. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  429. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  430. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  431. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  432. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  433. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  434. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  435. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  436. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
  437. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  438. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  439. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  440. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
  441. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  442. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  443. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
  444. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  445. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  446. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  447. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
  448. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  449. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  450. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
  451. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  452. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
  453. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  454. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  455. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
  456. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  457. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  458. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
  459. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
  460. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  461. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  462. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
  463. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  464. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  465. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  466. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  467. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  468. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  469. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  470. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  471. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  472. data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
  473. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  474. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  475. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  476. data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
  477. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  478. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  479. data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
  480. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  481. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  482. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  483. data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
  484. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  485. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  486. data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
  487. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  488. data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
  489. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  490. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  491. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
  492. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  493. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  494. data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
  495. data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
  496. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  497. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  498. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  499. data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
  500. data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
  501. data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
  502. data/assets/xcode/ios/Info.plist +0 -43
  503. data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
  504. data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
  505. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  506. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  507. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  508. data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
  509. data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
  510. data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
  511. data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
  512. data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
  513. data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
  514. data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
  515. data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
  516. data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
  517. data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
  518. data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
  519. data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
  520. data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
  521. data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
  522. data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
  523. data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
  524. data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
  525. data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
  526. data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
  527. data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
  528. data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
  529. data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
  530. data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
  531. data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
  532. data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
  533. data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
  534. data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
  535. data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
  536. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  537. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  538. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  539. data/assets/xcode/ios/main.c +0 -1
  540. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  541. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
  542. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
  543. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  544. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
  545. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  546. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  547. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  548. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
  549. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
  550. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  551. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
  552. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  553. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  554. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
  555. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
  556. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
  557. data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
  558. data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
  559. data/assets/xcode/tvos/Info.plist +0 -30
  560. data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
  561. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
  562. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  563. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  564. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  565. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
  566. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
  567. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
  568. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
  569. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
  570. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
  571. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
  572. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
  573. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
  574. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
  575. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
  576. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
  577. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
  578. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
  579. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
  580. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
  581. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
  582. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
  583. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
  584. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
  585. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
  586. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
  587. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
  588. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
  589. data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
  590. data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
  591. data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
  592. data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
  593. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  594. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  595. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  596. data/assets/xcode/tvos/main.c +0 -1
  597. data/ext/ruby2d/common.c +0 -185
  598. data/ext/ruby2d/controllers.c +0 -110
  599. data/ext/ruby2d/gl.c +0 -398
  600. data/ext/ruby2d/gl2.c +0 -86
  601. data/ext/ruby2d/gl3.c +0 -304
  602. data/ext/ruby2d/gles.c +0 -302
  603. data/ext/ruby2d/input.c +0 -48
  604. data/ext/ruby2d/music.c +0 -127
  605. data/ext/ruby2d/sound.c +0 -132
  606. data/lib/ruby2d/cli/console.rb +0 -65
  607. data/lib/ruby2d/cli/enable_console.rb +0 -7
  608. data/lib/ruby2d/cli/platform.rb +0 -17
  609. data/lib/ruby2d/music.rb +0 -77
  610. data/lib/ruby2d/pixel.rb +0 -18
  611. data/lib/ruby2d/pixmap.rb +0 -39
  612. data/lib/ruby2d/pixmap_atlas.rb +0 -56
  613. data/lib/ruby2d/sound.rb +0 -61
  614. data/lib/ruby2d/texture.rb +0 -38
  615. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
  616. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
  617. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
  618. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
  619. /data/assets/{include → platform/include}/mruby/re.h +0 -0
data/ext/ruby2d/shapes.c CHANGED
@@ -1,154 +1,984 @@
1
1
  // shapes.c
2
+ //
3
+ // Pure C primitives for shape rendering — no Ruby in this file. Ruby-callable
4
+ // wrappers live in ext.c and dispatch into these via Ruby2D::Ext class methods.
2
5
 
3
6
  #include "ruby2d.h"
4
7
 
5
8
 
6
9
  /*
7
- * Rotate a point around a given point
8
- * Params:
9
- * p The point to rotate
10
- * angle The angle in degrees
11
- * rx The x coordinate to rotate around
12
- * ry The y coordinate to rotate around
10
+ * Compute outer and inner outline points for a polyline or polygon stroke.
11
+ * See ruby2d.h for parameter documentation.
12
+ *
13
+ * Interior vertices (and all vertices in closed mode) use miter joins;
14
+ * endpoints in open mode get butt caps using the perpendicular of the single
15
+ * adjacent edge. Sharp miters are clamped to `miter_limit * half_width` so
16
+ * very acute corners don't shoot off into space (SVG's miterlimit behavior,
17
+ * though implemented here as a clamp rather than a bevel fallback).
13
18
  */
14
- R2D_GL_Point R2D_RotatePoint(R2D_GL_Point p, GLfloat angle, GLfloat rx, GLfloat ry) {
19
+ void R2D_ComputeStrokeOutline(const float *verts, int n, int closed,
20
+ float stroke_width, float miter_limit,
21
+ float *outer, float *inner) {
22
+
23
+ if (n < 2) return;
24
+
25
+ float hw = stroke_width / 2.0f;
26
+ float max_ml = miter_limit * hw;
27
+
28
+ for (int i = 0; i < n; i++) {
29
+ int is_endpoint = !closed && (i == 0 || i == n - 1);
30
+
31
+ if (is_endpoint) {
32
+ // Butt cap: perpendicular of the single adjacent edge
33
+ int other = (i == 0) ? 1 : n - 2;
34
+ float dx = verts[i*2] - verts[other*2];
35
+ float dy = verts[i*2+1] - verts[other*2+1];
36
+ if (i == 0) { dx = -dx; dy = -dy; }
37
+ float len = sqrtf(dx * dx + dy * dy);
38
+
39
+ if (len < 0.0001f) {
40
+ outer[i*2] = verts[i*2]; outer[i*2+1] = verts[i*2+1];
41
+ inner[i*2] = verts[i*2]; inner[i*2+1] = verts[i*2+1];
42
+ } else {
43
+ float nx = -dy / len, ny = dx / len;
44
+ outer[i*2] = verts[i*2] + nx * hw;
45
+ outer[i*2+1] = verts[i*2+1] + ny * hw;
46
+ inner[i*2] = verts[i*2] - nx * hw;
47
+ inner[i*2+1] = verts[i*2+1] - ny * hw;
48
+ }
49
+ continue;
50
+ }
51
+
52
+ // Interior (or any vertex in closed mode): compute miter
53
+ int prev = (i - 1 + n) % n;
54
+ int next = (i + 1) % n;
55
+
56
+ float d1x = verts[i*2] - verts[prev*2];
57
+ float d1y = verts[i*2+1] - verts[prev*2+1];
58
+ float d2x = verts[next*2] - verts[i*2];
59
+ float d2y = verts[next*2+1] - verts[i*2+1];
60
+
61
+ float len1 = sqrtf(d1x * d1x + d1y * d1y);
62
+ float len2 = sqrtf(d2x * d2x + d2y * d2y);
63
+
64
+ if (len1 < 0.0001f || len2 < 0.0001f) {
65
+ outer[i*2] = verts[i*2]; outer[i*2+1] = verts[i*2+1];
66
+ inner[i*2] = verts[i*2]; inner[i*2+1] = verts[i*2+1];
67
+ continue;
68
+ }
69
+
70
+ d1x /= len1; d1y /= len1;
71
+ d2x /= len2; d2y /= len2;
72
+
73
+ float n1x = -d1y, n1y = d1x;
74
+ float n2x = -d2y, n2y = d2x;
75
+
76
+ float mx = n1x + n2x;
77
+ float my = n1y + n2y;
78
+ float mlen = sqrtf(mx * mx + my * my);
79
+
80
+ if (mlen < 0.0001f) {
81
+ // 180° turn — degenerate; use the perpendicular of edge 1
82
+ outer[i*2] = verts[i*2] + n1x * hw;
83
+ outer[i*2+1] = verts[i*2+1] + n1y * hw;
84
+ inner[i*2] = verts[i*2] - n1x * hw;
85
+ inner[i*2+1] = verts[i*2+1] - n1y * hw;
86
+ continue;
87
+ }
88
+
89
+ mx /= mlen; my /= mlen;
90
+
91
+ float dot = mx * n1x + my * n1y;
92
+ if (fabsf(dot) < 0.0001f) dot = 0.0001f;
93
+ float ml = hw / dot;
94
+
95
+ // Clamp miter length for sharp corners
96
+ if (ml > max_ml) ml = max_ml;
97
+ else if (ml < -max_ml) ml = -max_ml;
98
+
99
+ outer[i*2] = verts[i*2] + mx * ml;
100
+ outer[i*2+1] = verts[i*2+1] + my * ml;
101
+ inner[i*2] = verts[i*2] - mx * ml;
102
+ inner[i*2+1] = verts[i*2+1] - my * ml;
103
+ }
104
+ }
15
105
 
16
- // Convert from degrees to radians
17
- angle = angle * M_PI / 180.0;
18
106
 
19
- // Get the sine and cosine of the angle
20
- GLfloat sa = sin(angle);
21
- GLfloat ca = cos(angle);
107
+ /*
108
+ * Stroke a polyline or closed polygon outline via SDL_RenderGeometry.
109
+ * See ruby2d.h for parameter documentation.
110
+ */
111
+ void R2D_StrokePath(const float *verts, int n, int closed,
112
+ float stroke_width, float miter_limit,
113
+ const float *colors) {
114
+
115
+ if (n < 2 || stroke_width <= 0.0f) return;
116
+
117
+ // 2n vertices (outer[0], inner[0], outer[1], inner[1], ...); 6 indices per
118
+ // edge, with n edges when closed and n-1 when open.
119
+ int num_vertices = n * 2;
120
+ int edges = closed ? n : n - 1;
121
+ int num_indices = edges * 6;
122
+
123
+ // Most stroked shapes are small (triangles, quads, short polylines), so serve
124
+ // the four scratch buffers from the stack and fall back to the heap only for
125
+ // large vertex counts. Avoids four malloc/free pairs per call on the
126
+ // per-frame stroke path.
127
+ float outer_stack[R2D_STROKE_STACK_N * 2];
128
+ float inner_stack[R2D_STROKE_STACK_N * 2];
129
+ SDL_Vertex vertices_stack[R2D_STROKE_STACK_N * 2];
130
+ int indices_stack[R2D_STROKE_STACK_N * 6];
131
+
132
+ float *outer, *inner;
133
+ SDL_Vertex *vertices;
134
+ int *indices;
135
+ bool heap = n > R2D_STROKE_STACK_N;
136
+
137
+ if (heap) {
138
+ outer = (float *)malloc(n * 2 * sizeof(float));
139
+ inner = (float *)malloc(n * 2 * sizeof(float));
140
+ vertices = (SDL_Vertex *)malloc(num_vertices * sizeof(SDL_Vertex));
141
+ indices = (int *)malloc(num_indices * sizeof(int));
142
+ if (!outer || !inner || !vertices || !indices) {
143
+ free(outer); free(inner); free(vertices); free(indices);
144
+ return;
145
+ }
146
+ } else {
147
+ outer = outer_stack;
148
+ inner = inner_stack;
149
+ vertices = vertices_stack;
150
+ indices = indices_stack;
151
+ }
22
152
 
23
- // Translate point to origin
24
- p.x -= rx;
25
- p.y -= ry;
153
+ R2D_ComputeStrokeOutline(verts, n, closed, stroke_width, miter_limit, outer, inner);
154
+
155
+ for (int i = 0; i < n; i++) {
156
+ float r = colors[i * 4];
157
+ float g = colors[i * 4 + 1];
158
+ float b = colors[i * 4 + 2];
159
+ float a = colors[i * 4 + 3];
160
+
161
+ vertices[i * 2].position.x = outer[i * 2];
162
+ vertices[i * 2].position.y = outer[i * 2 + 1];
163
+ vertices[i * 2].color.r = r;
164
+ vertices[i * 2].color.g = g;
165
+ vertices[i * 2].color.b = b;
166
+ vertices[i * 2].color.a = a;
167
+ vertices[i * 2].tex_coord.x = 0.0f;
168
+ vertices[i * 2].tex_coord.y = 0.0f;
169
+
170
+ vertices[i * 2 + 1].position.x = inner[i * 2];
171
+ vertices[i * 2 + 1].position.y = inner[i * 2 + 1];
172
+ vertices[i * 2 + 1].color.r = r;
173
+ vertices[i * 2 + 1].color.g = g;
174
+ vertices[i * 2 + 1].color.b = b;
175
+ vertices[i * 2 + 1].color.a = a;
176
+ vertices[i * 2 + 1].tex_coord.x = 0.0f;
177
+ vertices[i * 2 + 1].tex_coord.y = 0.0f;
178
+ }
26
179
 
27
- // Rotate point
28
- GLfloat xnew = p.x * ca - p.y * sa;
29
- GLfloat ynew = p.x * sa + p.y * ca;
180
+ for (int i = 0; i < edges; i++) {
181
+ int j = (i + 1) % n;
182
+ int oi = i * 2, ii = i * 2 + 1;
183
+ int oj = j * 2, ij = j * 2 + 1;
184
+
185
+ indices[i * 6] = oi;
186
+ indices[i * 6 + 1] = ii;
187
+ indices[i * 6 + 2] = ij;
188
+ indices[i * 6 + 3] = oi;
189
+ indices[i * 6 + 4] = ij;
190
+ indices[i * 6 + 5] = oj;
191
+ }
30
192
 
31
- // Translate point back
32
- p.x = xnew + rx;
33
- p.y = ynew + ry;
193
+ R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
194
+ vertices, num_vertices, indices, num_indices),
195
+ "SDL_RenderGeometry");
34
196
 
35
- return p;
197
+ if (heap) {
198
+ free(indices);
199
+ free(vertices);
200
+ free(outer);
201
+ free(inner);
202
+ }
36
203
  }
37
204
 
38
205
 
39
206
  /*
40
- * Get the point to be rotated around given a position in a rectangle
207
+ * Unit-circle lookup cache, keyed by sector count.
208
+ *
209
+ * The cos/sin of each sector angle depend only on the sector count — not on
210
+ * position, radius, or color — so they are identical every frame and across
211
+ * every circle/ellipse drawn with the same sector count. Build each table once
212
+ * on first use and reuse it, turning the per-vertex fill into a multiply-add
213
+ * with no trig. Rendering is single-threaded, so the file-static cache needs no
214
+ * locking; tables live for the process lifetime and slots for unused sector
215
+ * counts stay NULL.
41
216
  */
42
- R2D_GL_Point R2D_GetRectRotationPoint(int x, int y, int w, int h, int position) {
217
+ #define R2D_MAX_SECTORS 360
218
+ #define R2D_MIN_SECTORS 3
219
+ static float *unit_cos_table[R2D_MAX_SECTORS + 1];
220
+ static float *unit_sin_table[R2D_MAX_SECTORS + 1];
43
221
 
44
- R2D_GL_Point p;
222
+ /*
223
+ * Fetch the cached unit-circle cos/sin tables for `sectors` (in [3, 360]),
224
+ * building them on first use. On success points *cos_out / *sin_out at tables
225
+ * of `sectors` floats — cosf/sinf of i*(2*PI/sectors) for i in [0, sectors) —
226
+ * and returns true; on a bad sector count or allocation failure returns false
227
+ * so the caller computes the trig inline. The build expression matches the draw
228
+ * loops' former inline math exactly, so the geometry is bit-identical.
229
+ */
230
+ static bool R2D_UnitCircle(int sectors, const float **cos_out, const float **sin_out) {
231
+ if (sectors < 3 || sectors > R2D_MAX_SECTORS) return false;
232
+
233
+ if (!unit_cos_table[sectors]) {
234
+ float *cos_t = (float *)malloc(sectors * sizeof(float));
235
+ float *sin_t = (float *)malloc(sectors * sizeof(float));
236
+ if (!cos_t || !sin_t) { free(cos_t); free(sin_t); return false; }
237
+
238
+ float angle_step = (2.0f * M_PI) / sectors;
239
+ for (int i = 0; i < sectors; i++) {
240
+ float angle = i * angle_step;
241
+ cos_t[i] = cosf(angle);
242
+ sin_t[i] = sinf(angle);
243
+ }
244
+ unit_cos_table[sectors] = cos_t;
245
+ unit_sin_table[sectors] = sin_t;
246
+ }
45
247
 
46
- switch (position) {
47
- case R2D_CENTER:
48
- p.x = x + (w / 2.0);
49
- p.y = y + (h / 2.0);
50
- break;
51
- case R2D_TOP_LEFT:
52
- p.x = x;
53
- p.y = y;
54
- break;
55
- case R2D_TOP_RIGHT:
56
- p.x = x + w;
57
- p.y = y;
58
- break;
59
- case R2D_BOTTOM_LEFT:
60
- p.x = x;
61
- p.y = y + h;
62
- break;
63
- case R2D_BOTTOM_RIGHT:
64
- p.x = x + w;
65
- p.y = y + h;
66
- break;
248
+ *cos_out = unit_cos_table[sectors];
249
+ *sin_out = unit_sin_table[sectors];
250
+ return true;
251
+ }
252
+
253
+
254
+ /*
255
+ * Draw a filled ellipse via a triangle fan.
256
+ * See ruby2d.h for parameter documentation.
257
+ */
258
+ void R2D_DrawEllipse(float cx, float cy, float rx, float ry, float angle,
259
+ int sectors, float r, float g, float b, float a) {
260
+
261
+ if (sectors < R2D_MIN_SECTORS) sectors = R2D_MIN_SECTORS;
262
+ if (sectors > R2D_MAX_SECTORS) sectors = R2D_MAX_SECTORS;
263
+
264
+ // 1 center + one vertex per sector. The fan's last triangle wraps its index
265
+ // back to the first rim vertex (% sectors), so there's no duplicate rim point
266
+ // at angle 0 / 2π — matching R2D_StrokeEllipse.
267
+ int num_vertices = sectors + 1;
268
+ int num_indices = sectors * 3;
269
+
270
+ // Most ellipses use the default 30 sectors, so serve the vertex and index
271
+ // scratch from the stack and fall back to the heap only past the threshold.
272
+ // Avoids two malloc/free pairs per fill on the per-frame round-shape path.
273
+ SDL_Vertex vertices_stack[R2D_STROKE_STACK_N + 1];
274
+ int indices_stack[R2D_STROKE_STACK_N * 3];
275
+
276
+ SDL_Vertex *vertices;
277
+ int *indices;
278
+ bool heap = sectors > R2D_STROKE_STACK_N;
279
+
280
+ if (heap) {
281
+ vertices = (SDL_Vertex *)malloc(num_vertices * sizeof(SDL_Vertex));
282
+ indices = (int *)malloc(num_indices * sizeof(int));
283
+ if (!vertices || !indices) {
284
+ free(vertices); free(indices);
285
+ return;
286
+ }
287
+ } else {
288
+ vertices = vertices_stack;
289
+ indices = indices_stack;
290
+ }
291
+
292
+ // Center
293
+ vertices[0].position.x = cx;
294
+ vertices[0].position.y = cy;
295
+ vertices[0].color.r = r;
296
+ vertices[0].color.g = g;
297
+ vertices[0].color.b = b;
298
+ vertices[0].color.a = a;
299
+ vertices[0].tex_coord.x = 0.0f;
300
+ vertices[0].tex_coord.y = 0.0f;
301
+
302
+ // Unit-circle cos/sin come from the cached table (no per-vertex trig); only a
303
+ // table-build failure falls back to computing them inline.
304
+ const float *uc, *us;
305
+ bool cached = R2D_UnitCircle(sectors, &uc, &us);
306
+ float angle_step = cached ? 0.0f : (2.0f * M_PI) / sectors;
307
+ // Tilt the whole rim by `angle` (radians) so the ellipse can sit off-axis;
308
+ // when angle is 0 this is the identity, so skip the extra trig.
309
+ float rot_c = 1.0f, rot_s = 0.0f;
310
+ if (angle != 0.0f) { rot_c = cosf(angle); rot_s = sinf(angle); }
311
+ for (int i = 0; i < sectors; i++) {
312
+ float cv = cached ? uc[i] : cosf(i * angle_step);
313
+ float sv = cached ? us[i] : sinf(i * angle_step);
314
+ float ox = rx * cv, oy = ry * sv;
315
+ vertices[i + 1].position.x = cx + ox * rot_c - oy * rot_s;
316
+ vertices[i + 1].position.y = cy + ox * rot_s + oy * rot_c;
317
+ vertices[i + 1].color.r = r;
318
+ vertices[i + 1].color.g = g;
319
+ vertices[i + 1].color.b = b;
320
+ vertices[i + 1].color.a = a;
321
+ vertices[i + 1].tex_coord.x = 0.0f;
322
+ vertices[i + 1].tex_coord.y = 0.0f;
67
323
  }
68
324
 
69
- return p;
325
+ for (int i = 0; i < sectors; i++) {
326
+ indices[i * 3] = 0;
327
+ indices[i * 3 + 1] = i + 1;
328
+ indices[i * 3 + 2] = (i + 1) % sectors + 1;
329
+ }
330
+
331
+ R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
332
+ vertices, num_vertices, indices, num_indices),
333
+ "SDL_RenderGeometry");
334
+
335
+ if (heap) {
336
+ free(indices);
337
+ free(vertices);
338
+ }
339
+ }
340
+
341
+
342
+ /*
343
+ * Signed area (×2) of a polygon. Positive for CCW, negative for CW
344
+ * winding in screen coordinates (y-down). Used to normalize winding
345
+ * before ear clipping.
346
+ */
347
+ static float shapes_polygon_signed_area2(const float *verts, int n) {
348
+ float sum = 0.0f;
349
+ for (int i = 0; i < n; i++) {
350
+ int j = (i + 1) % n;
351
+ sum += verts[i * 2] * verts[j * 2 + 1] - verts[j * 2] * verts[i * 2 + 1];
352
+ }
353
+ return sum;
354
+ }
355
+
356
+
357
+ /*
358
+ * Triangle area sign helper (uses cross product). >0 is CCW, <0 is CW.
359
+ */
360
+ static float shapes_tri_cross(float ax, float ay, float bx, float by,
361
+ float cx, float cy) {
362
+ return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
70
363
  }
71
364
 
72
365
 
73
366
  /*
74
- * Draw a triangle
367
+ * Point-in-triangle test using barycentric sign comparisons.
368
+ * Returns 1 if (px, py) is strictly inside triangle (a, b, c) with the
369
+ * given winding (assumed CCW); points exactly on an edge are excluded.
75
370
  */
76
- void R2D_DrawTriangle(GLfloat x1, GLfloat y1,
77
- GLfloat r1, GLfloat g1, GLfloat b1, GLfloat a1,
78
- GLfloat x2, GLfloat y2,
79
- GLfloat r2, GLfloat g2, GLfloat b2, GLfloat a2,
80
- GLfloat x3, GLfloat y3,
81
- GLfloat r3, GLfloat g3, GLfloat b3, GLfloat a3) {
371
+ static int shapes_point_in_tri(float px, float py,
372
+ float ax, float ay,
373
+ float bx, float by,
374
+ float cx, float cy) {
375
+ float d1 = shapes_tri_cross(ax, ay, bx, by, px, py);
376
+ float d2 = shapes_tri_cross(bx, by, cx, cy, px, py);
377
+ float d3 = shapes_tri_cross(cx, cy, ax, ay, px, py);
378
+ // For CCW triangles, all three should be > 0 for strict interior.
379
+ return (d1 > 0.0f && d2 > 0.0f && d3 > 0.0f);
380
+ }
381
+
82
382
 
83
- R2D_GL_DrawTriangle(x1, y1, r1, g1, b1, a1,
84
- x2, y2, r2, g2, b2, a2,
85
- x3, y3, r3, g3, b3, a3);
383
+ /*
384
+ * Is the working polygon convex? (CCW winding assumed.) A blind triangle fan
385
+ * from poly[0] is only correct for a convex polygon — over a concave remainder
386
+ * it emits triangles that spill outside the outline. Used to guard the
387
+ * ear-clipping fan-tail fallback.
388
+ */
389
+ static bool shapes_remaining_is_convex(const float *verts, const int *poly, int remaining) {
390
+ for (int i = 0; i < remaining; i++) {
391
+ int a = poly[(i + remaining - 1) % remaining];
392
+ int b = poly[i];
393
+ int c = poly[(i + 1) % remaining];
394
+ float cross = shapes_tri_cross(verts[a * 2], verts[a * 2 + 1],
395
+ verts[b * 2], verts[b * 2 + 1],
396
+ verts[c * 2], verts[c * 2 + 1]);
397
+ if (cross < 0.0f) return false; // reflex corner — not convex
398
+ }
399
+ return true;
86
400
  }
87
401
 
88
402
 
89
403
  /*
90
- * Draw a quad, using two triangles
404
+ * Ear-clipping triangulation of a simple polygon.
405
+ * See ruby2d.h for parameter documentation.
91
406
  */
92
- void R2D_DrawQuad(GLfloat x1, GLfloat y1,
93
- GLfloat r1, GLfloat g1, GLfloat b1, GLfloat a1,
94
- GLfloat x2, GLfloat y2,
95
- GLfloat r2, GLfloat g2, GLfloat b2, GLfloat a2,
96
- GLfloat x3, GLfloat y3,
97
- GLfloat r3, GLfloat g3, GLfloat b3, GLfloat a3,
98
- GLfloat x4, GLfloat y4,
99
- GLfloat r4, GLfloat g4, GLfloat b4, GLfloat a4) {
407
+ int *R2D_TriangulatePolygon(const float *verts, int n, int *out_tri_count) {
408
+ if (out_tri_count) *out_tri_count = 0;
409
+ if (n < 3) return NULL;
410
+
411
+ int tri_count = n - 2;
412
+ int *indices = (int *)malloc(tri_count * 3 * sizeof(int));
413
+ if (!indices) return NULL;
414
+
415
+ // Fast path for triangles
416
+ if (n == 3) {
417
+ indices[0] = 0;
418
+ indices[1] = 1;
419
+ indices[2] = 2;
420
+ if (out_tri_count) *out_tri_count = 1;
421
+ return indices;
422
+ }
423
+
424
+ // Build a working list of original-vertex indices ordered CCW.
425
+ // If the input polygon is CW, reverse it so the rest of the algorithm
426
+ // can assume CCW (= "convex corner has positive cross product").
427
+ // poly is internal scratch (freed before return), so serve it from the stack
428
+ // for the common small-n case; only the largest polygons fall to the heap.
429
+ int poly_stack[R2D_STROKE_STACK_N];
430
+ bool poly_heap = n > R2D_STROKE_STACK_N;
431
+ int *poly = poly_heap ? (int *)malloc(n * sizeof(int)) : poly_stack;
432
+ if (!poly) { free(indices); return NULL; }
433
+
434
+ float area2 = shapes_polygon_signed_area2(verts, n);
435
+ if (area2 < 0.0f) {
436
+ // CW input — reverse so we work in CCW order. Output indices still
437
+ // refer to the caller's original vertex array.
438
+ for (int i = 0; i < n; i++) poly[i] = n - 1 - i;
439
+ } else {
440
+ for (int i = 0; i < n; i++) poly[i] = i;
441
+ }
442
+
443
+ int remaining = n;
444
+ int out = 0;
445
+ // Guard against pathological inputs (e.g. self-intersecting polygons
446
+ // where no ear can ever be found): cap total iterations.
447
+ int safety = 0;
448
+ int safety_limit = n * n + 4;
449
+
450
+ while (remaining > 3 && safety++ < safety_limit) {
451
+ int found_ear = 0;
452
+
453
+ for (int i = 0; i < remaining; i++) {
454
+ int i_prev = (i + remaining - 1) % remaining;
455
+ int i_next = (i + 1) % remaining;
456
+
457
+ int a = poly[i_prev];
458
+ int b = poly[i];
459
+ int c = poly[i_next];
460
+
461
+ float ax = verts[a * 2], ay = verts[a * 2 + 1];
462
+ float bx = verts[b * 2], by = verts[b * 2 + 1];
463
+ float cx = verts[c * 2], cy = verts[c * 2 + 1];
464
+
465
+ // Corner test (CCW => positive cross). Reject only reflex corners
466
+ // (cross < 0). A collinear corner (cross == 0) is clipped as a
467
+ // zero-area ear: it renders nothing but removes the vertex, keeping
468
+ // the algorithm progressing so polygons with collinear vertex runs
469
+ // don't stall into the fan-tail fallback.
470
+ float cross = shapes_tri_cross(ax, ay, bx, by, cx, cy);
471
+ if (cross < 0.0f) continue;
472
+
473
+ // Ear test: no other polygon vertex lies inside (a, b, c).
474
+ int contains = 0;
475
+ for (int k = 0; k < remaining; k++) {
476
+ if (k == i_prev || k == i || k == i_next) continue;
477
+ int v = poly[k];
478
+ float px = verts[v * 2], py = verts[v * 2 + 1];
479
+ if (shapes_point_in_tri(px, py, ax, ay, bx, by, cx, cy)) {
480
+ contains = 1;
481
+ break;
482
+ }
483
+ }
484
+ if (contains) continue;
485
+
486
+ // Emit the ear and remove vertex b from the working list.
487
+ indices[out++] = a;
488
+ indices[out++] = b;
489
+ indices[out++] = c;
490
+
491
+ for (int k = i; k < remaining - 1; k++) poly[k] = poly[k + 1];
492
+ remaining--;
493
+ found_ear = 1;
494
+ break;
495
+ }
100
496
 
101
- R2D_GL_DrawTriangle(x1, y1, r1, g1, b1, a1,
102
- x2, y2, r2, g2, b2, a2,
103
- x3, y3, r3, g3, b3, a3);
497
+ if (!found_ear) {
498
+ // Degenerate / self-intersecting input. Fall back to a fan over
499
+ // whatever remains so we still emit something defined.
500
+ break;
501
+ }
502
+ }
104
503
 
105
- R2D_GL_DrawTriangle(x3, y3, r3, g3, b3, a3,
106
- x4, y4, r4, g4, b4, a4,
107
- x1, y1, r1, g1, b1, a1);
108
- };
504
+ // Final triangle (or fan tail on fallback). A blind fan from poly[0] is only
505
+ // correct when the remainder is convex; over a concave remainder (genuinely
506
+ // degenerate / self-intersecting input, documented as unsupported) it would
507
+ // spill triangles outside the shape. In that case emit nothing for the
508
+ // remainder rather than render garbage — the unused slots pad to degenerate
509
+ // triangles below.
510
+ if (remaining == 3 || shapes_remaining_is_convex(verts, poly, remaining)) {
511
+ while (remaining >= 3 && out < tri_count * 3) {
512
+ indices[out++] = poly[0];
513
+ indices[out++] = poly[1];
514
+ indices[out++] = poly[2];
515
+ // Drop poly[1] to continue the fan if any remainder is left.
516
+ for (int k = 1; k < remaining - 1; k++) poly[k] = poly[k + 1];
517
+ remaining--;
518
+ }
519
+ }
520
+
521
+ if (poly_heap) free(poly);
522
+
523
+ // Real number of triangles emitted (before any degenerate padding below).
524
+ // Reporting this — not the theoretical n-2 — keeps callers from setting up
525
+ // the zero-area padding triangles when the input was degenerate.
526
+ int real_tri_count = out / 3;
527
+
528
+ // If the loop bailed early, pad unused slots with a degenerate triangle so
529
+ // the buffer stays well-formed even for a caller that ignores the count.
530
+ while (out < tri_count * 3) {
531
+ indices[out++] = 0;
532
+ indices[out++] = 0;
533
+ indices[out++] = 0;
534
+ }
535
+
536
+ if (out_tri_count) *out_tri_count = real_tri_count;
537
+ return indices;
538
+ }
109
539
 
110
540
 
111
541
  /*
112
- * Draw a line from a quad
542
+ * Draw a filled polygon. Triangulated via ear clipping so concave
543
+ * polygons fill correctly. See ruby2d.h for parameter documentation.
113
544
  */
114
- void R2D_DrawLine(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
115
- GLfloat width,
116
- GLfloat r1, GLfloat g1, GLfloat b1, GLfloat a1,
117
- GLfloat r2, GLfloat g2, GLfloat b2, GLfloat a2,
118
- GLfloat r3, GLfloat g3, GLfloat b3, GLfloat a3,
119
- GLfloat r4, GLfloat g4, GLfloat b4, GLfloat a4) {
545
+ void R2D_DrawPolygon(const float *verts, int n,
546
+ const float *per_vertex_colors,
547
+ float r, float g, float b, float a) {
548
+
549
+ if (n < 3) return;
550
+
551
+ int tri_count = 0;
552
+ int *indices = R2D_TriangulatePolygon(verts, n, &tri_count);
553
+ if (!indices || tri_count <= 0) { free(indices); return; }
554
+
555
+ // vertices is per-draw scratch; stack-serve it for small n to avoid a
556
+ // per-frame malloc/free. (indices stays heap — it is owned by this path and
557
+ // freed below after the draw.)
558
+ SDL_Vertex vertices_stack[R2D_STROKE_STACK_N];
559
+ bool heap = n > R2D_STROKE_STACK_N;
560
+ SDL_Vertex *vertices = heap ? (SDL_Vertex *)malloc(n * sizeof(SDL_Vertex)) : vertices_stack;
561
+ if (!vertices) { free(indices); return; }
562
+
563
+ for (int i = 0; i < n; i++) {
564
+ vertices[i].position.x = verts[i * 2];
565
+ vertices[i].position.y = verts[i * 2 + 1];
566
+ if (per_vertex_colors) {
567
+ vertices[i].color.r = per_vertex_colors[i * 4];
568
+ vertices[i].color.g = per_vertex_colors[i * 4 + 1];
569
+ vertices[i].color.b = per_vertex_colors[i * 4 + 2];
570
+ vertices[i].color.a = per_vertex_colors[i * 4 + 3];
571
+ } else {
572
+ vertices[i].color.r = r;
573
+ vertices[i].color.g = g;
574
+ vertices[i].color.b = b;
575
+ vertices[i].color.a = a;
576
+ }
577
+ vertices[i].tex_coord.x = 0.0f;
578
+ vertices[i].tex_coord.y = 0.0f;
579
+ }
120
580
 
121
- double length = sqrt(powf(x1 - x2, 2) + powf(y1 - y2, 2));
122
- double x = ((x2 - x1) / length) * width / 2;
123
- double y = ((y2 - y1) / length) * width / 2;
581
+ R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
582
+ vertices, n, indices, tri_count * 3),
583
+ "SDL_RenderGeometry");
124
584
 
125
- R2D_DrawQuad(
126
- x1 - y, y1 + x, r1, g1, b1, a1,
127
- x1 + y, y1 - x, r2, g2, b2, a2,
128
- x2 + y, y2 - x, r3, g3, b3, a3,
129
- x2 - y, y2 + x, r4, g4, b4, a4
130
- );
131
- };
585
+ free(indices);
586
+ if (heap) free(vertices);
587
+ }
132
588
 
133
589
 
134
590
  /*
135
- * Draw a circle from triangles
591
+ * Draw a dashed line from (x1,y1) to (x2,y2) as repeated thick quads.
592
+ * Each of the 4 input colors maps to a corner of the full line quad
593
+ * (c1=start+perp, c2=start-perp, c3=end-perp, c4=end+perp). Per-segment
594
+ * endpoint colors are linearly interpolated along the length.
595
+ * See ruby2d.h for parameter documentation.
136
596
  */
137
- void R2D_DrawCircle(GLfloat x, GLfloat y, GLfloat radius, int sectors,
138
- GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
597
+ void R2D_DrawDashedLine(float x1, float y1, float x2, float y2,
598
+ float stroke_width, float dash, float gap,
599
+ float r1, float g1, float b1, float a1,
600
+ float r2, float g2, float b2, float a2,
601
+ float r3, float g3, float b3, float a3,
602
+ float r4, float g4, float b4, float a4) {
603
+
604
+ if (stroke_width <= 0.0f || dash <= 0.0f) return;
605
+
606
+ float dx = x2 - x1;
607
+ float dy = y2 - y1;
608
+ float length = sqrtf(dx * dx + dy * dy);
609
+ if (length <= 0.0f) return;
610
+
611
+ float ux = dx / length;
612
+ float uy = dy / length;
613
+ float step = dash + (gap > 0.0f ? gap : 0.0f);
614
+
615
+ // Bound the work: a sub-pixel dash/gap on a long line would otherwise issue
616
+ // hundreds of thousands of draw calls and stall the frame. If the segment
617
+ // count blows past a ceiling, scale dash and gap up together (preserving
618
+ // their ratio) so the pattern still reads while the work stays bounded.
619
+ const int max_segments = 10000;
620
+ if (length / step > (float)max_segments) {
621
+ static bool warned = false;
622
+ if (!warned) {
623
+ R2D_Log(R2D_WARN, "Dashed line dash/gap too small; clamping segment count");
624
+ warned = true;
625
+ }
626
+ float f = (length / step) / (float)max_segments;
627
+ dash *= f;
628
+ gap *= f;
629
+ step = dash + (gap > 0.0f ? gap : 0.0f);
630
+ }
139
631
 
140
- double angle = 2 * M_PI / sectors;
632
+ // Perpendicular offset, scaled by half the stroke width. Every dash lies
633
+ // along the same line, so this is constant — compute it once instead of
634
+ // re-deriving it per dash inside R2D_DrawLine.
635
+ float half_width = stroke_width / 2.0f;
636
+ float px = -uy * half_width;
637
+ float py = ux * half_width;
638
+
639
+ // Batch every dash into one geometry submission: one quad (4 vertices,
640
+ // 6 indices) per dash. length / step is bounded by max_segments above, so
641
+ // this allocation is bounded; + 2 covers the partial trailing dash.
642
+ int max_dashes = (int)(length / step) + 2;
643
+ SDL_Vertex *vertices = (SDL_Vertex *)malloc((size_t)max_dashes * 4 * sizeof(SDL_Vertex));
644
+ int *indices = (int *)malloc((size_t)max_dashes * 6 * sizeof(int));
645
+ if (!vertices || !indices) {
646
+ free(vertices);
647
+ free(indices);
648
+ return;
649
+ }
650
+
651
+ int q = 0;
652
+ float pos = 0.0f;
653
+ while (pos < length) {
654
+ float end = pos + dash;
655
+ if (end > length) end = length;
656
+
657
+ float sx1 = x1 + ux * pos, sy1 = y1 + uy * pos;
658
+ float sx2 = x1 + ux * end, sy2 = y1 + uy * end;
659
+
660
+ float t1 = pos / length;
661
+ float t2 = end / length;
662
+
663
+ // Top edge: lerp c1 -> c4 along length
664
+ float sr1 = r1 + (r4 - r1) * t1, sg1 = g1 + (g4 - g1) * t1;
665
+ float sb1 = b1 + (b4 - b1) * t1, sa1 = a1 + (a4 - a1) * t1;
666
+ float er1 = r1 + (r4 - r1) * t2, eg1 = g1 + (g4 - g1) * t2;
667
+ float eb1 = b1 + (b4 - b1) * t2, ea1 = a1 + (a4 - a1) * t2;
668
+
669
+ // Bottom edge: lerp c2 -> c3 along length
670
+ float sr2 = r2 + (r3 - r2) * t1, sg2 = g2 + (g3 - g2) * t1;
671
+ float sb2 = b2 + (b3 - b2) * t1, sa2 = a2 + (a3 - a2) * t1;
672
+ float er2 = r2 + (r3 - r2) * t2, eg2 = g2 + (g3 - g2) * t2;
673
+ float eb2 = b2 + (b3 - b2) * t2, ea2 = a2 + (a3 - a2) * t2;
674
+
675
+ // Same four corners and winding as R2D_DrawLine, written straight into the
676
+ // batch: start + perp, start - perp, end - perp, end + perp.
677
+ int v = q * 4;
678
+ vertices[v + 0] = (SDL_Vertex){
679
+ .position = { sx1 + px, sy1 + py },
680
+ .color = { sr1, sg1, sb1, sa1 },
681
+ .tex_coord = { 0.0f, 0.0f }
682
+ };
683
+ vertices[v + 1] = (SDL_Vertex){
684
+ .position = { sx1 - px, sy1 - py },
685
+ .color = { sr2, sg2, sb2, sa2 },
686
+ .tex_coord = { 0.0f, 0.0f }
687
+ };
688
+ vertices[v + 2] = (SDL_Vertex){
689
+ .position = { sx2 - px, sy2 - py },
690
+ .color = { er2, eg2, eb2, ea2 },
691
+ .tex_coord = { 0.0f, 0.0f }
692
+ };
693
+ vertices[v + 3] = (SDL_Vertex){
694
+ .position = { sx2 + px, sy2 + py },
695
+ .color = { er1, eg1, eb1, ea1 },
696
+ .tex_coord = { 0.0f, 0.0f }
697
+ };
698
+
699
+ int ix = q * 6;
700
+ indices[ix + 0] = v + 0;
701
+ indices[ix + 1] = v + 1;
702
+ indices[ix + 2] = v + 2;
703
+ indices[ix + 3] = v + 0;
704
+ indices[ix + 4] = v + 2;
705
+ indices[ix + 5] = v + 3;
706
+
707
+ q++;
708
+ pos += step;
709
+ }
710
+
711
+ if (q > 0) {
712
+ R2D_CheckSDL(
713
+ SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, q * 4, indices, q * 6),
714
+ "SDL_RenderGeometry");
715
+ }
716
+
717
+ free(vertices);
718
+ free(indices);
719
+ }
720
+
721
+
722
+ /*
723
+ * Stroke an ellipse outline as a ring of triangles via SDL_RenderGeometry.
724
+ * Outer radius is (rx + sw/2, ry + sw/2), inner is (rx - sw/2, ry - sw/2),
725
+ * putting the stroke centered on the ellipse line.
726
+ */
727
+ void R2D_StrokeEllipse(float cx, float cy, float rx, float ry, float angle,
728
+ int sectors, float stroke_width,
729
+ float r, float g, float b, float a) {
730
+
731
+ if (stroke_width <= 0.0f) return;
732
+ if (sectors < R2D_MIN_SECTORS) sectors = R2D_MIN_SECTORS;
733
+ if (sectors > R2D_MAX_SECTORS) sectors = R2D_MAX_SECTORS;
734
+
735
+ float hw = stroke_width / 2.0f;
736
+ float orx = rx + hw, ory = ry + hw;
737
+ float irx = rx - hw, iry = ry - hw;
738
+ if (irx < 0.0f) irx = 0.0f;
739
+ if (iry < 0.0f) iry = 0.0f;
740
+
741
+ int num_vertices = sectors * 2;
742
+ int num_indices = sectors * 6;
743
+
744
+ // Default 30 sectors fits the stack; fall back to the heap only past the
745
+ // threshold. Avoids two malloc/free pairs per stroke on the per-frame path.
746
+ SDL_Vertex vertices_stack[R2D_STROKE_STACK_N * 2];
747
+ int indices_stack[R2D_STROKE_STACK_N * 6];
748
+
749
+ SDL_Vertex *vertices;
750
+ int *indices;
751
+ bool heap = sectors > R2D_STROKE_STACK_N;
752
+
753
+ if (heap) {
754
+ vertices = (SDL_Vertex *)malloc(num_vertices * sizeof(SDL_Vertex));
755
+ indices = (int *)malloc(num_indices * sizeof(int));
756
+ if (!vertices || !indices) {
757
+ free(vertices); free(indices);
758
+ return;
759
+ }
760
+ } else {
761
+ vertices = vertices_stack;
762
+ indices = indices_stack;
763
+ }
141
764
 
765
+ // Unit-circle cos/sin come from the cached table (no per-vertex trig); only a
766
+ // table-build failure falls back to computing them inline.
767
+ const float *uc, *us;
768
+ bool cached = R2D_UnitCircle(sectors, &uc, &us);
769
+ float angle_step = cached ? 0.0f : (2.0f * M_PI) / sectors;
770
+ // Tilt both rims by `angle` (radians); identity when angle is 0.
771
+ float rot_c = 1.0f, rot_s = 0.0f;
772
+ if (angle != 0.0f) { rot_c = cosf(angle); rot_s = sinf(angle); }
142
773
  for (int i = 0; i < sectors; i++) {
774
+ float ca = cached ? uc[i] : cosf(i * angle_step);
775
+ float sa = cached ? us[i] : sinf(i * angle_step);
776
+
777
+ float oox = orx * ca, ooy = ory * sa; // outer rim offset
778
+ float iox = irx * ca, ioy = iry * sa; // inner rim offset
779
+ vertices[i * 2].position.x = cx + oox * rot_c - ooy * rot_s;
780
+ vertices[i * 2].position.y = cy + oox * rot_s + ooy * rot_c;
781
+ vertices[i * 2].color.r = r;
782
+ vertices[i * 2].color.g = g;
783
+ vertices[i * 2].color.b = b;
784
+ vertices[i * 2].color.a = a;
785
+ vertices[i * 2].tex_coord.x = 0.0f;
786
+ vertices[i * 2].tex_coord.y = 0.0f;
787
+
788
+ vertices[i * 2 + 1].position.x = cx + iox * rot_c - ioy * rot_s;
789
+ vertices[i * 2 + 1].position.y = cy + iox * rot_s + ioy * rot_c;
790
+ vertices[i * 2 + 1].color.r = r;
791
+ vertices[i * 2 + 1].color.g = g;
792
+ vertices[i * 2 + 1].color.b = b;
793
+ vertices[i * 2 + 1].color.a = a;
794
+ vertices[i * 2 + 1].tex_coord.x = 0.0f;
795
+ vertices[i * 2 + 1].tex_coord.y = 0.0f;
796
+ }
143
797
 
144
- GLfloat x1 = x + radius * cos(i * angle);
145
- GLfloat y1 = y + radius * sin(i * angle);
798
+ for (int i = 0; i < sectors; i++) {
799
+ int j = (i + 1) % sectors;
800
+ int oi = i * 2, ii = i * 2 + 1;
801
+ int oj = j * 2, ij = j * 2 + 1;
802
+
803
+ indices[i * 6] = oi;
804
+ indices[i * 6 + 1] = ii;
805
+ indices[i * 6 + 2] = ij;
806
+ indices[i * 6 + 3] = oi;
807
+ indices[i * 6 + 4] = ij;
808
+ indices[i * 6 + 5] = oj;
809
+ }
146
810
 
147
- GLfloat x2 = x + radius * cos((i - 1) * angle);
148
- GLfloat y2 = y + radius * sin((i - 1) * angle);
811
+ R2D_CheckSDL(SDL_RenderGeometry(R2D_GetRenderer(), NULL,
812
+ vertices, num_vertices, indices, num_indices),
813
+ "SDL_RenderGeometry");
149
814
 
150
- R2D_GL_DrawTriangle( x, y, r, g, b, a,
151
- x1, y1, r, g, b, a,
152
- x2, y2, r, g, b, a);
815
+ if (heap) {
816
+ free(indices);
817
+ free(vertices);
153
818
  }
154
819
  }
820
+
821
+
822
+ /*
823
+ * Draws a filled triangle with per-vertex colors.
824
+ *
825
+ * Parameters:
826
+ * x, y - Vertex position coordinates
827
+ * r, g, b, a - Vertex color values (red, green, blue, alpha)
828
+ * The numbers specify the coordinates and color for each vertex of the triangle
829
+ *
830
+ * The triangle is rendered using the current SDL renderer, and colors are
831
+ * interpolated between vertices.
832
+ */
833
+ void R2D_DrawTriangle(float x1, float y1,
834
+ float r1, float g1, float b1, float a1,
835
+ float x2, float y2,
836
+ float r2, float g2, float b2, float a2,
837
+ float x3, float y3,
838
+ float r3, float g3, float b3, float a3) {
839
+
840
+ SDL_Vertex vertices[3] = {{
841
+ .position = { x1, y1 },
842
+ .color = { r1, g1, b1, a1 },
843
+ .tex_coord = { 0.0f, 0.0f }
844
+ }, {
845
+ .position = { x2, y2 },
846
+ .color = { r2, g2, b2, a2 },
847
+ .tex_coord = { 0.0f, 0.0f }
848
+ }, {
849
+ .position = { x3, y3 },
850
+ .color = { r3, g3, b3, a3 },
851
+ .tex_coord = { 0.0f, 0.0f }
852
+ }};
853
+
854
+ R2D_CheckSDL(
855
+ SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, 3, NULL, 0),
856
+ "SDL_RenderGeometry");
857
+ }
858
+
859
+
860
+ /*
861
+ * Draws a filled quad with per-vertex colors.
862
+ *
863
+ * Parameters:
864
+ * x, y - Vertex position coordinates for each of the 4 corners
865
+ * r, g, b, a - Vertex color values (red, green, blue, alpha) for each corner
866
+ *
867
+ * The quad is rendered as two triangles with interpolated colors.
868
+ */
869
+ void R2D_DrawQuad(float x1, float y1,
870
+ float r1, float g1, float b1, float a1,
871
+ float x2, float y2,
872
+ float r2, float g2, float b2, float a2,
873
+ float x3, float y3,
874
+ float r3, float g3, float b3, float a3,
875
+ float x4, float y4,
876
+ float r4, float g4, float b4, float a4) {
877
+
878
+ SDL_Vertex vertices[4] = {{
879
+ .position = { x1, y1 },
880
+ .color = { r1, g1, b1, a1 },
881
+ .tex_coord = { 0.0f, 0.0f }
882
+ }, {
883
+ .position = { x2, y2 },
884
+ .color = { r2, g2, b2, a2 },
885
+ .tex_coord = { 0.0f, 0.0f }
886
+ }, {
887
+ .position = { x3, y3 },
888
+ .color = { r3, g3, b3, a3 },
889
+ .tex_coord = { 0.0f, 0.0f }
890
+ }, {
891
+ .position = { x4, y4 },
892
+ .color = { r4, g4, b4, a4 },
893
+ .tex_coord = { 0.0f, 0.0f }
894
+ }};
895
+
896
+ // Indices for two triangles forming the quad
897
+ int indices[6] = { 0, 1, 2, 0, 2, 3 };
898
+
899
+ R2D_CheckSDL(
900
+ SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, 4, indices, 6),
901
+ "SDL_RenderGeometry");
902
+ }
903
+
904
+
905
+ /*
906
+ * Draws a line with specified width and per-vertex colors.
907
+ *
908
+ * Parameters:
909
+ * x1, y1 - Start point of the line
910
+ * x2, y2 - End point of the line
911
+ * width - Thickness of the line
912
+ * r, g, b, a - Color values for each of the 4 corners of the line quad
913
+ *
914
+ * The line is rendered as a quad perpendicular to the line direction.
915
+ */
916
+ void R2D_DrawLine(float x1, float y1, float x2, float y2,
917
+ float width,
918
+ float r1, float g1, float b1, float a1,
919
+ float r2, float g2, float b2, float a2,
920
+ float r3, float g3, float b3, float a3,
921
+ float r4, float g4, float b4, float a4) {
922
+
923
+ // Calculate the direction vector of the line
924
+ float dx = x2 - x1;
925
+ float dy = y2 - y1;
926
+
927
+ // Calculate the length of the line
928
+ float length = sqrtf(dx * dx + dy * dy);
929
+
930
+ // Avoid division by zero for zero-length lines and skip non-positive widths
931
+ // (a negative width would swap the quad sides and still fill a visible band)
932
+ if (length == 0.0f || width <= 0.0f) return;
933
+
934
+ // Calculate the perpendicular unit vector scaled by half width
935
+ float half_width = width / 2.0f;
936
+ float px = (-dy / length) * half_width;
937
+ float py = (dx / length) * half_width;
938
+
939
+ // Calculate the four corners of the line quad
940
+ SDL_Vertex vertices[4] = {{
941
+ .position = { x1 + px, y1 + py },
942
+ .color = { r1, g1, b1, a1 },
943
+ .tex_coord = { 0.0f, 0.0f }
944
+ }, {
945
+ .position = { x1 - px, y1 - py },
946
+ .color = { r2, g2, b2, a2 },
947
+ .tex_coord = { 0.0f, 0.0f }
948
+ }, {
949
+ .position = { x2 - px, y2 - py },
950
+ .color = { r3, g3, b3, a3 },
951
+ .tex_coord = { 0.0f, 0.0f }
952
+ }, {
953
+ .position = { x2 + px, y2 + py },
954
+ .color = { r4, g4, b4, a4 },
955
+ .tex_coord = { 0.0f, 0.0f }
956
+ }};
957
+
958
+ // Indices for two triangles forming the quad
959
+ int indices[6] = { 0, 1, 2, 0, 2, 3 };
960
+
961
+ R2D_CheckSDL(
962
+ SDL_RenderGeometry(R2D_GetRenderer(), NULL, vertices, 4, indices, 6),
963
+ "SDL_RenderGeometry");
964
+ }
965
+
966
+
967
+ /*
968
+ * Draws a filled circle with a solid color.
969
+ *
970
+ * Parameters:
971
+ * x, y - Center position of the circle
972
+ * radius - Radius of the circle
973
+ * sectors - Number of triangular sectors (higher = smoother circle)
974
+ * r, g, b, a - Color values for the circle
975
+ *
976
+ * The circle is rendered as a triangle fan from the center.
977
+ */
978
+ void R2D_DrawCircle(float x, float y, float radius, int sectors,
979
+ float r, float g, float b, float a) {
980
+
981
+ // A circle is an ellipse with equal radii. Delegating reuses the ellipse
982
+ // rasterizer's heap allocation and NULL checks instead of stack VLAs.
983
+ R2D_DrawEllipse(x, y, radius, radius, 0.0f, sectors, r, g, b, a);
984
+ }