ruby2d 0.12.1 → 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 (620) 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 -443
  285. data/assets/app.icns +0 -0
  286. data/assets/include/GL/glew.h +0 -26427
  287. data/assets/include/GLES2/gl2.h +0 -656
  288. data/assets/include/GLES2/gl2ext.h +0 -3949
  289. data/assets/include/GLES2/gl2ext_angle.h +0 -701
  290. data/assets/include/GLES2/gl2platform.h +0 -27
  291. data/assets/include/GLES3/gl3.h +0 -1192
  292. data/assets/include/GLES3/gl31.h +0 -1507
  293. data/assets/include/GLES3/gl32.h +0 -1808
  294. data/assets/include/GLES3/gl3platform.h +0 -27
  295. data/assets/include/KHR/khrplatform.h +0 -290
  296. data/assets/include/SDL2/SDL.h +0 -233
  297. data/assets/include/SDL2/SDL_assert.h +0 -326
  298. data/assets/include/SDL2/SDL_atomic.h +0 -415
  299. data/assets/include/SDL2/SDL_audio.h +0 -1500
  300. data/assets/include/SDL2/SDL_clipboard.h +0 -141
  301. data/assets/include/SDL2/SDL_config.h +0 -61
  302. data/assets/include/SDL2/SDL_config_android.h +0 -194
  303. data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
  304. data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
  305. data/assets/include/SDL2/SDL_config_macosx.h +0 -277
  306. data/assets/include/SDL2/SDL_config_minimal.h +0 -95
  307. data/assets/include/SDL2/SDL_config_ngage.h +0 -89
  308. data/assets/include/SDL2/SDL_config_os2.h +0 -207
  309. data/assets/include/SDL2/SDL_config_pandora.h +0 -141
  310. data/assets/include/SDL2/SDL_config_windows.h +0 -331
  311. data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
  312. data/assets/include/SDL2/SDL_config_winrt.h +0 -220
  313. data/assets/include/SDL2/SDL_config_xbox.h +0 -235
  314. data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
  315. data/assets/include/SDL2/SDL_endian.h +0 -348
  316. data/assets/include/SDL2/SDL_error.h +0 -163
  317. data/assets/include/SDL2/SDL_events.h +0 -1166
  318. data/assets/include/SDL2/SDL_filesystem.h +0 -149
  319. data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
  320. data/assets/include/SDL2/SDL_gesture.h +0 -117
  321. data/assets/include/SDL2/SDL_guid.h +0 -100
  322. data/assets/include/SDL2/SDL_haptic.h +0 -1341
  323. data/assets/include/SDL2/SDL_hidapi.h +0 -451
  324. data/assets/include/SDL2/SDL_hints.h +0 -2569
  325. data/assets/include/SDL2/SDL_image.h +0 -2173
  326. data/assets/include/SDL2/SDL_joystick.h +0 -1066
  327. data/assets/include/SDL2/SDL_keyboard.h +0 -353
  328. data/assets/include/SDL2/SDL_keycode.h +0 -358
  329. data/assets/include/SDL2/SDL_loadso.h +0 -115
  330. data/assets/include/SDL2/SDL_log.h +0 -404
  331. data/assets/include/SDL2/SDL_main.h +0 -275
  332. data/assets/include/SDL2/SDL_mixer.h +0 -2784
  333. data/assets/include/SDL2/SDL_mouse.h +0 -465
  334. data/assets/include/SDL2/SDL_mutex.h +0 -471
  335. data/assets/include/SDL2/SDL_name.h +0 -33
  336. data/assets/include/SDL2/SDL_pixels.h +0 -644
  337. data/assets/include/SDL2/SDL_platform.h +0 -261
  338. data/assets/include/SDL2/SDL_quit.h +0 -58
  339. data/assets/include/SDL2/SDL_rect.h +0 -376
  340. data/assets/include/SDL2/SDL_render.h +0 -1919
  341. data/assets/include/SDL2/SDL_revision.h +0 -6
  342. data/assets/include/SDL2/SDL_rwops.h +0 -841
  343. data/assets/include/SDL2/SDL_sensor.h +0 -322
  344. data/assets/include/SDL2/SDL_shape.h +0 -155
  345. data/assets/include/SDL2/SDL_stdinc.h +0 -830
  346. data/assets/include/SDL2/SDL_surface.h +0 -997
  347. data/assets/include/SDL2/SDL_system.h +0 -623
  348. data/assets/include/SDL2/SDL_syswm.h +0 -386
  349. data/assets/include/SDL2/SDL_test_images.h +0 -78
  350. data/assets/include/SDL2/SDL_test_random.h +0 -115
  351. data/assets/include/SDL2/SDL_thread.h +0 -464
  352. data/assets/include/SDL2/SDL_timer.h +0 -222
  353. data/assets/include/SDL2/SDL_touch.h +0 -150
  354. data/assets/include/SDL2/SDL_ttf.h +0 -2316
  355. data/assets/include/SDL2/SDL_types.h +0 -29
  356. data/assets/include/SDL2/SDL_version.h +0 -204
  357. data/assets/include/SDL2/SDL_video.h +0 -2150
  358. data/assets/include/SDL2/SDL_vulkan.h +0 -215
  359. data/assets/include/SDL2/begin_code.h +0 -187
  360. data/assets/include/mruby/boxing_no.h +0 -58
  361. data/assets/include/mruby/class.h +0 -108
  362. data/assets/include/mruby/error.h +0 -147
  363. data/assets/include/mruby/gc.h +0 -94
  364. data/assets/include/mruby/irep.h +0 -147
  365. data/assets/include/mruby/khash.h +0 -284
  366. data/assets/include/mruby/object.h +0 -43
  367. data/assets/include/mruby/presym/disable.h +0 -70
  368. data/assets/include/mruby/presym/enable.h +0 -37
  369. data/assets/include/mruby/presym.h +0 -40
  370. data/assets/include/mruby/proc.h +0 -211
  371. data/assets/include/mruby/throw.h +0 -66
  372. data/assets/macos/universal/bin/mrbc +0 -0
  373. data/assets/macos/universal/lib/libFLAC.a +0 -0
  374. data/assets/macos/universal/lib/libSDL2.a +0 -0
  375. data/assets/macos/universal/lib/libSDL2_image.a +0 -0
  376. data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
  377. data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
  378. data/assets/macos/universal/lib/libavif.a +0 -0
  379. data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
  380. data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
  381. data/assets/macos/universal/lib/libfreetype.a +0 -0
  382. data/assets/macos/universal/lib/libgraphite2.a +0 -0
  383. data/assets/macos/universal/lib/libharfbuzz.a +0 -0
  384. data/assets/macos/universal/lib/libhwy.a +0 -0
  385. data/assets/macos/universal/lib/libjpeg.a +0 -0
  386. data/assets/macos/universal/lib/libjxl.a +0 -0
  387. data/assets/macos/universal/lib/libmodplug.a +0 -0
  388. data/assets/macos/universal/lib/libmpg123.a +0 -0
  389. data/assets/macos/universal/lib/libmruby.a +0 -0
  390. data/assets/macos/universal/lib/libogg.a +0 -0
  391. data/assets/macos/universal/lib/libpng.a +0 -0
  392. data/assets/macos/universal/lib/libtiff.a +0 -0
  393. data/assets/macos/universal/lib/libvorbis.a +0 -0
  394. data/assets/macos/universal/lib/libvorbisfile.a +0 -0
  395. data/assets/macos/universal/lib/libwebp.a +0 -0
  396. data/assets/macos/universal/lib/libzstd.a +0 -0
  397. data/assets/test_media/README.md +0 -3
  398. data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
  399. data/assets/test_media/bitstream_vera/vera.ttf +0 -0
  400. data/assets/test_media/boom.png +0 -0
  401. data/assets/test_media/coin.png +0 -0
  402. data/assets/test_media/colors.png +0 -0
  403. data/assets/test_media/controller.png +0 -0
  404. data/assets/test_media/dial.wav +0 -0
  405. data/assets/test_media/hero.png +0 -0
  406. data/assets/test_media/image.bmp +0 -0
  407. data/assets/test_media/image.jpg +0 -0
  408. data/assets/test_media/image.png +0 -0
  409. data/assets/test_media/music.flac +0 -0
  410. data/assets/test_media/music.mp3 +0 -0
  411. data/assets/test_media/music.ogg +0 -0
  412. data/assets/test_media/music.wav +0 -0
  413. data/assets/test_media/originals/boom.pxm +0 -0
  414. data/assets/test_media/originals/coin.pxm +0 -0
  415. data/assets/test_media/originals/controller.sketch +0 -0
  416. data/assets/test_media/originals/hero.pxm +0 -0
  417. data/assets/test_media/originals/image.pxm +0 -0
  418. data/assets/test_media/originals/music.caf +0 -0
  419. data/assets/test_media/originals/texture_atlas.pxm +0 -0
  420. data/assets/test_media/rondo_alla_turka.ogg +0 -0
  421. data/assets/test_media/sound.flac +0 -0
  422. data/assets/test_media/sound.mp3 +0 -0
  423. data/assets/test_media/sound.ogg +0 -0
  424. data/assets/test_media/sound.wav +0 -0
  425. data/assets/test_media/sprite_sheet.png +0 -0
  426. data/assets/test_media/texture_atlas.png +0 -0
  427. data/assets/wasm/libmruby.a +0 -0
  428. data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
  429. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
  430. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
  431. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
  432. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
  433. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
  434. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
  435. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
  436. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
  437. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
  438. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
  439. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
  440. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
  441. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
  442. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
  443. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
  444. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
  445. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
  446. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
  447. data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
  448. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
  449. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
  450. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
  451. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
  452. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
  453. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
  454. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
  455. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
  456. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
  457. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
  458. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
  459. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
  460. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
  461. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
  462. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
  463. data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
  464. data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
  465. data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
  466. data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
  467. data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
  468. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
  469. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
  470. data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
  471. data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
  472. data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
  473. data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
  474. data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
  475. data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
  476. data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
  477. data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
  478. data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
  479. data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
  480. data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
  481. data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
  482. data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
  483. data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
  484. data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
  485. data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
  486. data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
  487. data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
  488. data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
  489. data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
  490. data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
  491. data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
  492. data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
  493. data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
  494. data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
  495. data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
  496. data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
  497. data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
  498. data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
  499. data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
  500. data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
  501. data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
  502. data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
  503. data/assets/xcode/ios/Info.plist +0 -43
  504. data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
  505. data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
  506. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  507. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  508. data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  509. data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
  510. data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
  511. data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
  512. data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
  513. data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
  514. data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
  515. data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
  516. data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
  517. data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
  518. data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
  519. data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
  520. data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
  521. data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
  522. data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
  523. data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
  524. data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
  525. data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
  526. data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
  527. data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
  528. data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
  529. data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
  530. data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
  531. data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
  532. data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
  533. data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
  534. data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
  535. data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
  536. data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
  537. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  538. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  539. data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  540. data/assets/xcode/ios/main.c +0 -1
  541. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  542. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
  543. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
  544. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  545. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
  546. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  547. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  548. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
  549. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
  550. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
  551. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
  552. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
  553. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
  554. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
  555. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
  556. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
  557. data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
  558. data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
  559. data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
  560. data/assets/xcode/tvos/Info.plist +0 -30
  561. data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
  562. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
  563. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
  564. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
  565. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
  566. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
  567. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
  568. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
  569. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
  570. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
  571. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
  572. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
  573. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
  574. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
  575. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
  576. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
  577. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
  578. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
  579. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
  580. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
  581. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
  582. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
  583. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
  584. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
  585. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
  586. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
  587. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
  588. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
  589. data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
  590. data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
  591. data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
  592. data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
  593. data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
  594. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  595. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  596. data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
  597. data/assets/xcode/tvos/main.c +0 -1
  598. data/ext/ruby2d/common.c +0 -185
  599. data/ext/ruby2d/controllers.c +0 -110
  600. data/ext/ruby2d/gl.c +0 -398
  601. data/ext/ruby2d/gl2.c +0 -86
  602. data/ext/ruby2d/gl3.c +0 -304
  603. data/ext/ruby2d/gles.c +0 -302
  604. data/ext/ruby2d/input.c +0 -48
  605. data/ext/ruby2d/music.c +0 -127
  606. data/ext/ruby2d/sound.c +0 -132
  607. data/lib/ruby2d/cli/console.rb +0 -65
  608. data/lib/ruby2d/cli/enable_console.rb +0 -7
  609. data/lib/ruby2d/cli/platform.rb +0 -17
  610. data/lib/ruby2d/music.rb +0 -77
  611. data/lib/ruby2d/pixel.rb +0 -18
  612. data/lib/ruby2d/pixmap.rb +0 -39
  613. data/lib/ruby2d/pixmap_atlas.rb +0 -56
  614. data/lib/ruby2d/sound.rb +0 -61
  615. data/lib/ruby2d/texture.rb +0 -38
  616. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
  617. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
  618. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
  619. /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
  620. /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
+ }