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.
- checksums.yaml +4 -4
- data/LICENSE.md +7 -0
- data/README.md +141 -0
- data/USAGE.md +2435 -0
- data/assets/Rakefile +637 -0
- data/assets/build_support/CMakeLists.txt +94 -0
- data/assets/build_support/mruby/build_config.rb +34 -0
- data/assets/build_support/mruby/build_config_wasm.rb +30 -0
- data/assets/build_support/sdl_test.c +174 -0
- data/assets/deps.yaml +16 -0
- data/assets/platform/include/SDL3/SDL.h +91 -0
- data/assets/platform/include/SDL3/SDL_assert.h +705 -0
- data/assets/platform/include/SDL3/SDL_asyncio.h +550 -0
- data/assets/platform/include/SDL3/SDL_atomic.h +692 -0
- data/assets/platform/include/SDL3/SDL_audio.h +2370 -0
- data/assets/platform/include/SDL3/SDL_begin_code.h +553 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_bits.h +47 -27
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_blendmode.h +59 -55
- data/assets/platform/include/SDL3/SDL_camera.h +535 -0
- data/assets/platform/include/SDL3/SDL_clipboard.h +331 -0
- data/assets/{include/SDL2/close_code.h → platform/include/SDL3/SDL_close_code.h} +9 -8
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_copying.h +3 -1
- data/assets/platform/include/SDL3/SDL_cpuinfo.h +374 -0
- data/assets/platform/include/SDL3/SDL_dialog.h +343 -0
- data/assets/platform/include/SDL3/SDL_dlopennote.h +234 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_egl.h +11 -8
- data/assets/platform/include/SDL3/SDL_endian.h +645 -0
- data/assets/platform/include/SDL3/SDL_error.h +226 -0
- data/assets/platform/include/SDL3/SDL_events.h +1645 -0
- data/assets/platform/include/SDL3/SDL_filesystem.h +537 -0
- data/assets/platform/include/SDL3/SDL_gamepad.h +1656 -0
- data/assets/platform/include/SDL3/SDL_gpu.h +4608 -0
- data/assets/platform/include/SDL3/SDL_guid.h +106 -0
- data/assets/platform/include/SDL3/SDL_haptic.h +1461 -0
- data/assets/platform/include/SDL3/SDL_hidapi.h +571 -0
- data/assets/platform/include/SDL3/SDL_hints.h +5001 -0
- data/assets/platform/include/SDL3/SDL_init.h +507 -0
- data/assets/platform/include/SDL3/SDL_intrin.h +410 -0
- data/assets/platform/include/SDL3/SDL_iostream.h +1379 -0
- data/assets/platform/include/SDL3/SDL_joystick.h +1385 -0
- data/assets/platform/include/SDL3/SDL_keyboard.h +608 -0
- data/assets/platform/include/SDL3/SDL_keycode.h +347 -0
- data/assets/platform/include/SDL3/SDL_loadso.h +145 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_locale.h +40 -24
- data/assets/platform/include/SDL3/SDL_log.h +541 -0
- data/assets/platform/include/SDL3/SDL_main.h +704 -0
- data/assets/platform/include/SDL3/SDL_main_impl.h +151 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_messagebox.h +85 -48
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_metal.h +29 -29
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_misc.h +13 -12
- data/assets/platform/include/SDL3/SDL_mouse.h +813 -0
- data/assets/platform/include/SDL3/SDL_mutex.h +1117 -0
- data/assets/platform/include/SDL3/SDL_oldnames.h +1339 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl.h +1247 -278
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengl_glext.h +5 -1
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles.h +6 -7
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2.h +10 -11
- data/assets/platform/include/SDL3/SDL_pen.h +198 -0
- data/assets/platform/include/SDL3/SDL_pixels.h +1441 -0
- data/assets/{include/SDL2/SDL_test_log.h → platform/include/SDL3/SDL_platform.h} +25 -26
- data/assets/platform/include/SDL3/SDL_platform_defines.h +497 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_power.h +40 -20
- data/assets/platform/include/SDL3/SDL_process.h +441 -0
- data/assets/platform/include/SDL3/SDL_properties.h +572 -0
- data/assets/platform/include/SDL3/SDL_rect.h +528 -0
- data/assets/platform/include/SDL3/SDL_render.h +3028 -0
- data/assets/platform/include/SDL3/SDL_revision.h +59 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_scancode.h +59 -68
- data/assets/platform/include/SDL3/SDL_sensor.h +321 -0
- data/assets/platform/include/SDL3/SDL_stdinc.h +6186 -0
- data/assets/platform/include/SDL3/SDL_storage.h +686 -0
- data/assets/platform/include/SDL3/SDL_surface.h +1769 -0
- data/assets/platform/include/SDL3/SDL_system.h +840 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test.h +16 -22
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_assert.h +27 -34
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_common.h +109 -52
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_compare.h +22 -14
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_crc32.h +27 -30
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_font.h +50 -49
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_fuzzer.h +64 -79
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_harness.h +47 -30
- data/assets/platform/include/SDL3/SDL_test_log.h +83 -0
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_md5.h +21 -28
- data/assets/{include/SDL2 → platform/include/SDL3}/SDL_test_memory.h +19 -16
- data/assets/platform/include/SDL3/SDL_thread.h +602 -0
- data/assets/platform/include/SDL3/SDL_time.h +249 -0
- data/assets/platform/include/SDL3/SDL_timer.h +454 -0
- data/assets/platform/include/SDL3/SDL_touch.h +184 -0
- data/assets/platform/include/SDL3/SDL_tray.h +544 -0
- data/assets/platform/include/SDL3/SDL_version.h +198 -0
- data/assets/platform/include/SDL3/SDL_video.h +3497 -0
- data/assets/platform/include/SDL3/SDL_vulkan.h +287 -0
- data/assets/platform/include/SDL3_image/SDL_image.h +3328 -0
- data/assets/platform/include/SDL3_mixer/SDL_mixer.h +3369 -0
- data/assets/platform/include/SDL3_ttf/SDL_textengine.h +181 -0
- data/assets/platform/include/SDL3_ttf/SDL_ttf.h +2833 -0
- data/assets/{include → platform/include}/mrbconf.h +42 -31
- data/assets/{include → platform/include}/mruby/array.h +3 -4
- data/assets/{include → platform/include}/mruby/boxing_nan.h +10 -0
- data/assets/platform/include/mruby/boxing_no.h +59 -0
- data/assets/{include → platform/include}/mruby/boxing_word.h +72 -26
- data/assets/platform/include/mruby/class.h +157 -0
- data/assets/{include → platform/include}/mruby/common.h +30 -1
- data/assets/{include → platform/include}/mruby/compile.h +52 -74
- data/assets/{include → platform/include}/mruby/data.h +2 -2
- data/assets/{include → platform/include}/mruby/debug.h +12 -5
- data/assets/{include → platform/include}/mruby/dump.h +7 -9
- data/assets/{include → platform/include}/mruby/endian.h +1 -1
- data/assets/platform/include/mruby/error.h +173 -0
- data/assets/platform/include/mruby/gc.h +79 -0
- data/assets/{include → platform/include}/mruby/hash.h +1 -7
- data/assets/platform/include/mruby/internal.h +282 -0
- data/assets/platform/include/mruby/irep.h +143 -0
- data/assets/{include → platform/include}/mruby/istruct.h +1 -1
- data/assets/platform/include/mruby/khash.h +455 -0
- data/assets/platform/include/mruby/mempool.h +19 -0
- data/assets/{include → platform/include}/mruby/numeric.h +7 -10
- data/assets/platform/include/mruby/object.h +51 -0
- data/assets/{include → platform/include}/mruby/opcode.h +5 -5
- data/assets/{include → platform/include}/mruby/ops.h +19 -6
- data/assets/platform/include/mruby/presym/id.h +1447 -0
- data/assets/{include → platform/include}/mruby/presym/scanning.h +10 -7
- data/assets/platform/include/mruby/presym/table.h +2893 -0
- data/assets/platform/include/mruby/presym.h +65 -0
- data/assets/platform/include/mruby/proc.h +184 -0
- data/assets/{include → platform/include}/mruby/range.h +0 -2
- data/assets/{include → platform/include}/mruby/string.h +33 -53
- data/assets/platform/include/mruby/throw.h +81 -0
- data/assets/{include → platform/include}/mruby/value.h +64 -29
- data/assets/{include → platform/include}/mruby/variable.h +6 -23
- data/assets/{include → platform/include}/mruby/version.h +7 -7
- data/assets/{include → platform/include}/mruby.h +238 -116
- data/assets/platform/macos-arm64/bin/mrbc +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_image.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/macos-arm64/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/macos-arm64/lib/libmruby.a +0 -0
- data/assets/platform/wasm/lib/libFLAC.a +0 -0
- data/assets/platform/wasm/lib/libSDL3.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_image.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/wasm/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/wasm/lib/libfreetype.a +0 -0
- data/assets/platform/wasm/lib/libharfbuzz.a +0 -0
- data/assets/platform/wasm/lib/libmruby.a +0 -0
- data/assets/platform/wasm/lib/libogg.a +0 -0
- data/assets/platform/wasm/lib/libplutosvg.a +0 -0
- data/assets/platform/wasm/lib/libplutovg.a +0 -0
- data/assets/platform/wasm/lib/libpng.a +0 -0
- data/assets/platform/wasm/lib/libpng16.a +0 -0
- data/assets/platform/wasm/lib/libvorbis.a +0 -0
- data/assets/platform/wasm/lib/libvorbisfile.a +0 -0
- data/assets/platform/wasm/lib/libzlibstatic.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/bin/mrbc.exe +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_image.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/windows-arm64-mingw-ucrt/lib/libmruby.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/bin/mrbc.exe +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_image.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_mixer.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libSDL3_ttf.a +0 -0
- data/assets/platform/windows-x86_64-mingw-ucrt/lib/libmruby.a +0 -0
- data/assets/resources/fonts/outfit/OFL.txt +93 -0
- data/assets/resources/fonts/outfit/outfit.ttf +0 -0
- data/assets/resources/fonts/roboto_mono/OFL.txt +91 -0
- data/assets/resources/fonts/roboto_mono/roboto_mono.ttf +0 -0
- data/assets/resources/icons/icon.icns +0 -0
- data/assets/resources/icons/icon.png +0 -0
- data/assets/resources/spritesheets/License.txt +28 -0
- data/assets/resources/spritesheets/spritesheet-backgrounds.png +0 -0
- data/assets/resources/spritesheets/spritesheet-backgrounds.xml +16 -0
- data/assets/resources/spritesheets/spritesheet-characters.png +0 -0
- data/assets/resources/spritesheets/spritesheet-characters.xml +47 -0
- data/assets/resources/spritesheets/spritesheet-enemies.png +0 -0
- data/assets/resources/spritesheets/spritesheet-enemies.xml +62 -0
- data/assets/resources/spritesheets/spritesheet-tiles.png +0 -0
- data/assets/resources/spritesheets/spritesheet-tiles.xml +316 -0
- data/assets/{wasm → resources/web}/template.html +1 -1
- data/assets/target.rb +131 -0
- data/bin/ruby2d +281 -82
- data/examples/astar.rb +269 -0
- data/examples/asteroids.rb +403 -0
- data/examples/bezier_editor.rb +96 -0
- data/examples/boids.rb +191 -0
- data/examples/bouncing_balls.rb +119 -0
- data/examples/breakout.rb +186 -0
- data/examples/constellations.rb +100 -0
- data/examples/dashboard.rb +133 -0
- data/examples/double_pendulum.rb +254 -0
- data/examples/falling_sand.rb +291 -0
- data/examples/fireworks.rb +110 -0
- data/examples/fluid_dynamics.rb +340 -0
- data/examples/fourier_epicycles.rb +142 -0
- data/examples/fractal_tree.rb +326 -0
- data/examples/game_of_life.rb +148 -0
- data/examples/gamepads.rb +333 -0
- data/examples/hill_driver.rb +613 -0
- data/examples/logo_animation.rb +251 -0
- data/examples/lorenz_attractor.rb +115 -0
- data/examples/mandelbrot.rb +207 -0
- data/examples/marching_squares.rb +200 -0
- data/examples/maze.rb +323 -0
- data/examples/nbody.rb +338 -0
- data/examples/outrun.rb +391 -0
- data/examples/pixel_paint.rb +313 -0
- data/examples/platformer.rb +335 -0
- data/examples/ray_casting_maze.rb +175 -0
- data/examples/shadow_casting.rb +151 -0
- data/examples/shape_recognizer.rb +908 -0
- data/examples/snake.rb +144 -0
- data/examples/sprite_sheets.rb +246 -0
- data/examples/swarm.rb +206 -0
- data/examples/tsp_annealing.rb +104 -0
- data/examples/ui_controls.rb +163 -0
- data/examples/wireframe_3d.rb +139 -0
- data/ext/ruby2d/audio.c +324 -0
- data/ext/ruby2d/canvas.c +1715 -494
- data/ext/ruby2d/ext.c +541 -0
- data/ext/ruby2d/extconf.rb +122 -145
- data/ext/ruby2d/font.c +566 -20
- data/ext/ruby2d/fps.c +92 -0
- data/ext/ruby2d/image.c +466 -41
- data/ext/ruby2d/ruby2d.c +374 -1890
- data/ext/ruby2d/ruby2d.h +840 -460
- data/ext/ruby2d/shapes.c +931 -101
- data/ext/ruby2d/text.c +586 -21
- data/ext/ruby2d/window.c +1693 -283
- data/lib/ruby2d/atlas_parser.rb +194 -0
- data/lib/ruby2d/audio.rb +73 -0
- data/lib/ruby2d/benchmark.rb +259 -0
- data/lib/ruby2d/bitmap_text.rb +155 -0
- data/lib/ruby2d/button.rb +402 -0
- data/lib/ruby2d/canvas.rb +703 -279
- data/lib/ruby2d/circle.rb +206 -29
- data/lib/ruby2d/cli/browser.rb +314 -0
- data/lib/ruby2d/cli/build.rb +471 -257
- data/lib/ruby2d/cli/colorize.rb +7 -5
- data/lib/ruby2d/cli/examples.rb +127 -0
- data/lib/ruby2d/cli/launch.rb +24 -39
- data/lib/ruby2d/cli/lib_files.rb +48 -0
- data/lib/ruby2d/cli/messages.rb +40 -0
- data/lib/ruby2d/cli/setup.rb +273 -0
- data/lib/ruby2d/cli/static_server.rb +160 -0
- data/lib/ruby2d/cli/usage.rb +255 -0
- data/lib/ruby2d/color.rb +191 -69
- data/lib/ruby2d/core.rb +37 -19
- data/lib/ruby2d/deps_help.rb +89 -0
- data/lib/ruby2d/dsl.rb +51 -12
- data/lib/ruby2d/ellipse.rb +228 -0
- data/lib/ruby2d/exceptions.rb +0 -2
- data/lib/ruby2d/font.rb +34 -74
- data/lib/ruby2d/gamepad.rb +323 -0
- data/lib/ruby2d/gem_paths.rb +19 -0
- data/lib/ruby2d/image.rb +155 -52
- data/lib/ruby2d/interactive.rb +103 -0
- data/lib/ruby2d/json_parser.rb +268 -0
- data/lib/ruby2d/line.rb +194 -85
- data/lib/ruby2d/mruby_compat.rb +12 -0
- data/lib/ruby2d/polygon.rb +297 -0
- data/lib/ruby2d/polyline.rb +368 -0
- data/lib/ruby2d/quad.rb +358 -94
- data/lib/ruby2d/rectangle.rb +77 -19
- data/lib/ruby2d/renderable.rb +411 -11
- data/lib/ruby2d/sprite.rb +471 -180
- data/lib/ruby2d/sprite_sheet.rb +64 -0
- data/lib/ruby2d/square.rb +29 -17
- data/lib/ruby2d/text.rb +196 -65
- data/lib/ruby2d/tileset.rb +139 -81
- data/lib/ruby2d/triangle.rb +324 -89
- data/lib/ruby2d/version.rb +1 -3
- data/lib/ruby2d/vertices.rb +62 -85
- data/lib/ruby2d/warnings.rb +29 -0
- data/lib/ruby2d/window/class_methods.rb +218 -0
- data/lib/ruby2d/window/gamepad_events.rb +141 -0
- data/lib/ruby2d/window/key_events.rb +74 -0
- data/lib/ruby2d/window/mouse_events.rb +171 -0
- data/lib/ruby2d/window/object_events.rb +168 -0
- data/lib/ruby2d/window.rb +632 -585
- data/lib/ruby2d.rb +14 -19
- metadata +275 -443
- data/assets/app.icns +0 -0
- data/assets/include/GL/glew.h +0 -26427
- data/assets/include/GLES2/gl2.h +0 -656
- data/assets/include/GLES2/gl2ext.h +0 -3949
- data/assets/include/GLES2/gl2ext_angle.h +0 -701
- data/assets/include/GLES2/gl2platform.h +0 -27
- data/assets/include/GLES3/gl3.h +0 -1192
- data/assets/include/GLES3/gl31.h +0 -1507
- data/assets/include/GLES3/gl32.h +0 -1808
- data/assets/include/GLES3/gl3platform.h +0 -27
- data/assets/include/KHR/khrplatform.h +0 -290
- data/assets/include/SDL2/SDL.h +0 -233
- data/assets/include/SDL2/SDL_assert.h +0 -326
- data/assets/include/SDL2/SDL_atomic.h +0 -415
- data/assets/include/SDL2/SDL_audio.h +0 -1500
- data/assets/include/SDL2/SDL_clipboard.h +0 -141
- data/assets/include/SDL2/SDL_config.h +0 -61
- data/assets/include/SDL2/SDL_config_android.h +0 -194
- data/assets/include/SDL2/SDL_config_emscripten.h +0 -218
- data/assets/include/SDL2/SDL_config_iphoneos.h +0 -217
- data/assets/include/SDL2/SDL_config_macosx.h +0 -277
- data/assets/include/SDL2/SDL_config_minimal.h +0 -95
- data/assets/include/SDL2/SDL_config_ngage.h +0 -89
- data/assets/include/SDL2/SDL_config_os2.h +0 -207
- data/assets/include/SDL2/SDL_config_pandora.h +0 -141
- data/assets/include/SDL2/SDL_config_windows.h +0 -331
- data/assets/include/SDL2/SDL_config_wingdk.h +0 -253
- data/assets/include/SDL2/SDL_config_winrt.h +0 -220
- data/assets/include/SDL2/SDL_config_xbox.h +0 -235
- data/assets/include/SDL2/SDL_cpuinfo.h +0 -594
- data/assets/include/SDL2/SDL_endian.h +0 -348
- data/assets/include/SDL2/SDL_error.h +0 -163
- data/assets/include/SDL2/SDL_events.h +0 -1166
- data/assets/include/SDL2/SDL_filesystem.h +0 -149
- data/assets/include/SDL2/SDL_gamecontroller.h +0 -1074
- data/assets/include/SDL2/SDL_gesture.h +0 -117
- data/assets/include/SDL2/SDL_guid.h +0 -100
- data/assets/include/SDL2/SDL_haptic.h +0 -1341
- data/assets/include/SDL2/SDL_hidapi.h +0 -451
- data/assets/include/SDL2/SDL_hints.h +0 -2569
- data/assets/include/SDL2/SDL_image.h +0 -2173
- data/assets/include/SDL2/SDL_joystick.h +0 -1066
- data/assets/include/SDL2/SDL_keyboard.h +0 -353
- data/assets/include/SDL2/SDL_keycode.h +0 -358
- data/assets/include/SDL2/SDL_loadso.h +0 -115
- data/assets/include/SDL2/SDL_log.h +0 -404
- data/assets/include/SDL2/SDL_main.h +0 -275
- data/assets/include/SDL2/SDL_mixer.h +0 -2784
- data/assets/include/SDL2/SDL_mouse.h +0 -465
- data/assets/include/SDL2/SDL_mutex.h +0 -471
- data/assets/include/SDL2/SDL_name.h +0 -33
- data/assets/include/SDL2/SDL_pixels.h +0 -644
- data/assets/include/SDL2/SDL_platform.h +0 -261
- data/assets/include/SDL2/SDL_quit.h +0 -58
- data/assets/include/SDL2/SDL_rect.h +0 -376
- data/assets/include/SDL2/SDL_render.h +0 -1919
- data/assets/include/SDL2/SDL_revision.h +0 -6
- data/assets/include/SDL2/SDL_rwops.h +0 -841
- data/assets/include/SDL2/SDL_sensor.h +0 -322
- data/assets/include/SDL2/SDL_shape.h +0 -155
- data/assets/include/SDL2/SDL_stdinc.h +0 -830
- data/assets/include/SDL2/SDL_surface.h +0 -997
- data/assets/include/SDL2/SDL_system.h +0 -623
- data/assets/include/SDL2/SDL_syswm.h +0 -386
- data/assets/include/SDL2/SDL_test_images.h +0 -78
- data/assets/include/SDL2/SDL_test_random.h +0 -115
- data/assets/include/SDL2/SDL_thread.h +0 -464
- data/assets/include/SDL2/SDL_timer.h +0 -222
- data/assets/include/SDL2/SDL_touch.h +0 -150
- data/assets/include/SDL2/SDL_ttf.h +0 -2316
- data/assets/include/SDL2/SDL_types.h +0 -29
- data/assets/include/SDL2/SDL_version.h +0 -204
- data/assets/include/SDL2/SDL_video.h +0 -2150
- data/assets/include/SDL2/SDL_vulkan.h +0 -215
- data/assets/include/SDL2/begin_code.h +0 -187
- data/assets/include/mruby/boxing_no.h +0 -58
- data/assets/include/mruby/class.h +0 -108
- data/assets/include/mruby/error.h +0 -147
- data/assets/include/mruby/gc.h +0 -94
- data/assets/include/mruby/irep.h +0 -147
- data/assets/include/mruby/khash.h +0 -284
- data/assets/include/mruby/object.h +0 -43
- data/assets/include/mruby/presym/disable.h +0 -70
- data/assets/include/mruby/presym/enable.h +0 -37
- data/assets/include/mruby/presym.h +0 -40
- data/assets/include/mruby/proc.h +0 -211
- data/assets/include/mruby/throw.h +0 -66
- data/assets/macos/universal/bin/mrbc +0 -0
- data/assets/macos/universal/lib/libFLAC.a +0 -0
- data/assets/macos/universal/lib/libSDL2.a +0 -0
- data/assets/macos/universal/lib/libSDL2_image.a +0 -0
- data/assets/macos/universal/lib/libSDL2_mixer.a +0 -0
- data/assets/macos/universal/lib/libSDL2_ttf.a +0 -0
- data/assets/macos/universal/lib/libavif.a +0 -0
- data/assets/macos/universal/lib/libbrotlicommon-static.a +0 -0
- data/assets/macos/universal/lib/libbrotlidec-static.a +0 -0
- data/assets/macos/universal/lib/libfreetype.a +0 -0
- data/assets/macos/universal/lib/libgraphite2.a +0 -0
- data/assets/macos/universal/lib/libharfbuzz.a +0 -0
- data/assets/macos/universal/lib/libhwy.a +0 -0
- data/assets/macos/universal/lib/libjpeg.a +0 -0
- data/assets/macos/universal/lib/libjxl.a +0 -0
- data/assets/macos/universal/lib/libmodplug.a +0 -0
- data/assets/macos/universal/lib/libmpg123.a +0 -0
- data/assets/macos/universal/lib/libmruby.a +0 -0
- data/assets/macos/universal/lib/libogg.a +0 -0
- data/assets/macos/universal/lib/libpng.a +0 -0
- data/assets/macos/universal/lib/libtiff.a +0 -0
- data/assets/macos/universal/lib/libvorbis.a +0 -0
- data/assets/macos/universal/lib/libvorbisfile.a +0 -0
- data/assets/macos/universal/lib/libwebp.a +0 -0
- data/assets/macos/universal/lib/libzstd.a +0 -0
- data/assets/test_media/README.md +0 -3
- data/assets/test_media/bitstream_vera/COPYRIGHT.txt +0 -124
- data/assets/test_media/bitstream_vera/vera.ttf +0 -0
- data/assets/test_media/boom.png +0 -0
- data/assets/test_media/coin.png +0 -0
- data/assets/test_media/colors.png +0 -0
- data/assets/test_media/controller.png +0 -0
- data/assets/test_media/dial.wav +0 -0
- data/assets/test_media/hero.png +0 -0
- data/assets/test_media/image.bmp +0 -0
- data/assets/test_media/image.jpg +0 -0
- data/assets/test_media/image.png +0 -0
- data/assets/test_media/music.flac +0 -0
- data/assets/test_media/music.mp3 +0 -0
- data/assets/test_media/music.ogg +0 -0
- data/assets/test_media/music.wav +0 -0
- data/assets/test_media/originals/boom.pxm +0 -0
- data/assets/test_media/originals/coin.pxm +0 -0
- data/assets/test_media/originals/controller.sketch +0 -0
- data/assets/test_media/originals/hero.pxm +0 -0
- data/assets/test_media/originals/image.pxm +0 -0
- data/assets/test_media/originals/music.caf +0 -0
- data/assets/test_media/originals/texture_atlas.pxm +0 -0
- data/assets/test_media/rondo_alla_turka.ogg +0 -0
- data/assets/test_media/sound.flac +0 -0
- data/assets/test_media/sound.mp3 +0 -0
- data/assets/test_media/sound.ogg +0 -0
- data/assets/test_media/sound.wav +0 -0
- data/assets/test_media/sprite_sheet.png +0 -0
- data/assets/test_media/texture_atlas.png +0 -0
- data/assets/wasm/libmruby.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/bin/mrbc.exe +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libLerc.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_image.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libSDL2_ttf.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlicommon.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbrotlidec.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libbz2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libdeflate.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libfreetype.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libglew32.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libgraphite2.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libharfbuzz.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libhwy.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjbig.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjpeg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libjxl.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/liblzma.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libmruby.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libpng.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libssp.a +0 -1
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libtiff.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libwebp.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-ucrt-x86_64/lib/libzstd.a +0 -0
- data/assets/windows/mingw-w64-x86_64/bin/mrbc.exe +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libFLAC.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libLerc.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_image.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_mixer.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libSDL2_ttf.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbrotlicommon.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbrotlidec.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libbz2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libdeflate.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libfreetype.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libglew32.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libgraphite2.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libharfbuzz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libhwy.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjbig.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjpeg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libjxl.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/liblzma.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmodplug.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmpg123.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libmruby.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libogg.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopus.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libopusfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libpng.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libsndfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libssp.a +0 -1
- data/assets/windows/mingw-w64-x86_64/lib/libstdc++.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libtiff.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbis.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libvorbisfile.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libwebp.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libz.a +0 -0
- data/assets/windows/mingw-w64-x86_64/lib/libzstd.a +0 -0
- data/assets/xcode/ios/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -98
- data/assets/xcode/ios/Assets.xcassets/Contents.json +0 -6
- data/assets/xcode/ios/Base.lproj/LaunchScreen.storyboard +0 -27
- data/assets/xcode/ios/Info.plist +0 -43
- data/assets/xcode/ios/MRuby.framework/Headers/mrbconf.h +0 -143
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/array.h +0 -280
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/class.h +0 -97
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/common.h +0 -77
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/compile.h +0 -195
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/data.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/debug.h +0 -67
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/dump.h +0 -196
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/error.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/gc.h +0 -91
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/hash.h +0 -215
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/irep.h +0 -75
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/istruct.h +0 -47
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/khash.h +0 -274
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/numeric.h +0 -161
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/object.h +0 -44
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/opcode.h +0 -69
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/ops.h +0 -117
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/proc.h +0 -131
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/range.h +0 -49
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/re.h +0 -16
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/string.h +0 -444
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/throw.h +0 -55
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/value.h +0 -309
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/variable.h +0 -136
- data/assets/xcode/ios/MRuby.framework/Headers/mruby/version.h +0 -110
- data/assets/xcode/ios/MRuby.framework/Headers/mruby.h +0 -1282
- data/assets/xcode/ios/MRuby.framework/Info.plist +0 -20
- data/assets/xcode/ios/MRuby.framework/MRuby +0 -0
- data/assets/xcode/ios/MyApp.xcodeproj/project.pbxproj +0 -368
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/assets/xcode/ios/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
- data/assets/xcode/ios/main.c +0 -1
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json +0 -17
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json +0 -17
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json +0 -32
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json +0 -16
- data/assets/xcode/tvos/Assets.xcassets/Contents.json +0 -6
- data/assets/xcode/tvos/Assets.xcassets/LaunchImage.launchimage/Contents.json +0 -22
- data/assets/xcode/tvos/Info.plist +0 -30
- data/assets/xcode/tvos/MRuby.framework/Headers/mrbconf.h +0 -143
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/array.h +0 -280
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_nan.h +0 -102
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_no.h +0 -56
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/boxing_word.h +0 -144
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/class.h +0 -97
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/common.h +0 -77
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/compile.h +0 -195
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/data.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/debug.h +0 -67
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/dump.h +0 -196
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/error.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/gc.h +0 -91
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/hash.h +0 -215
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/irep.h +0 -75
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/istruct.h +0 -47
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/khash.h +0 -274
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/numeric.h +0 -161
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/object.h +0 -44
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/opcode.h +0 -69
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/ops.h +0 -117
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/proc.h +0 -131
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/range.h +0 -49
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/re.h +0 -16
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/string.h +0 -444
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/throw.h +0 -55
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/value.h +0 -309
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/variable.h +0 -136
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby/version.h +0 -110
- data/assets/xcode/tvos/MRuby.framework/Headers/mruby.h +0 -1282
- data/assets/xcode/tvos/MRuby.framework/Info.plist +0 -20
- data/assets/xcode/tvos/MRuby.framework/MRuby +0 -0
- data/assets/xcode/tvos/MyApp.xcodeproj/project.pbxproj +0 -350
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- data/assets/xcode/tvos/MyApp.xcodeproj/project.xcworkspace/xcshareddata/MyApp.xcscmblueprint +0 -30
- data/assets/xcode/tvos/main.c +0 -1
- data/ext/ruby2d/common.c +0 -185
- data/ext/ruby2d/controllers.c +0 -110
- data/ext/ruby2d/gl.c +0 -398
- data/ext/ruby2d/gl2.c +0 -86
- data/ext/ruby2d/gl3.c +0 -304
- data/ext/ruby2d/gles.c +0 -302
- data/ext/ruby2d/input.c +0 -48
- data/ext/ruby2d/music.c +0 -127
- data/ext/ruby2d/sound.c +0 -132
- data/lib/ruby2d/cli/console.rb +0 -65
- data/lib/ruby2d/cli/enable_console.rb +0 -7
- data/lib/ruby2d/cli/platform.rb +0 -17
- data/lib/ruby2d/music.rb +0 -77
- data/lib/ruby2d/pixel.rb +0 -18
- data/lib/ruby2d/pixmap.rb +0 -39
- data/lib/ruby2d/pixmap_atlas.rb +0 -56
- data/lib/ruby2d/sound.rb +0 -61
- data/lib/ruby2d/texture.rb +0 -38
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2ext.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_gl2platform.h +0 -0
- /data/assets/{include/SDL2 → platform/include/SDL3}/SDL_opengles2_khrplatform.h +0 -0
- /data/assets/{include → platform/include}/mruby/re.h +0 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# Asteroids
|
|
2
|
+
# A small clone of the classic, doubling as a tour of Ruby 2D fundamentals.
|
|
3
|
+
#
|
|
4
|
+
# Demonstrates the core building blocks:
|
|
5
|
+
# * `set` configures the window
|
|
6
|
+
# * `update do |dt| ... end` runs per-frame logic (no drawing); `dt` is
|
|
7
|
+
# wall-clock seconds since the last update so motion stays consistent
|
|
8
|
+
# across 60Hz, 120Hz, and slower frames alike
|
|
9
|
+
# * `render do ... end` does immediate-mode drawing
|
|
10
|
+
# * `on :key_down` / `on :key_up` capture input
|
|
11
|
+
# * Persistent shapes (`Text.new`) coexist with one-shot draws (`Circle.render`)
|
|
12
|
+
#
|
|
13
|
+
# Controls: rotate with left/right, thrust with up, fire with space,
|
|
14
|
+
# restart with r.
|
|
15
|
+
|
|
16
|
+
require 'ruby2d'
|
|
17
|
+
|
|
18
|
+
# === Tunables ===
|
|
19
|
+
|
|
20
|
+
WIDTH = 800 # window width in pixels
|
|
21
|
+
HEIGHT = 600 # window height in pixels
|
|
22
|
+
SHIP_R = 15 # ship radius (used for collision and drawing)
|
|
23
|
+
THRUST = 1152 # acceleration while thrusting (px/sec²)
|
|
24
|
+
HIT_PENALTY = 500 # score deducted when the ship is destroyed
|
|
25
|
+
|
|
26
|
+
# === Window ===
|
|
27
|
+
|
|
28
|
+
set title: 'Ruby 2D ▸ Examples ▸ Asteroids', width: WIDTH, height: HEIGHT, background: '#050816'
|
|
29
|
+
set close_on_esc: true
|
|
30
|
+
|
|
31
|
+
# === Game-object structs ===
|
|
32
|
+
#
|
|
33
|
+
# Plain values held in arrays and updated each frame. Sparks back both the
|
|
34
|
+
# ship's thrust trail and the victory fireworks; an optional `hue` lets
|
|
35
|
+
# fireworks override the default fire colors.
|
|
36
|
+
|
|
37
|
+
Asteroid = Struct.new(:x, :y, :vx, :vy, :radius, :points)
|
|
38
|
+
Bullet = Struct.new(:x, :y, :vx, :vy)
|
|
39
|
+
Spark = Struct.new(:x, :y, :vx, :vy, :life, :max_life, :hue)
|
|
40
|
+
|
|
41
|
+
# Build a jagged closed shape by sampling 10 angles around a circle and
|
|
42
|
+
# jittering each radius. Points are stored in the asteroid's local space
|
|
43
|
+
# and offset by `a.x, a.y` at draw time.
|
|
44
|
+
def make_asteroid(x = rand(WIDTH), y = rand(HEIGHT), radius = 42)
|
|
45
|
+
points = 10.times.map do |i|
|
|
46
|
+
angle = i / 10.0 * Math::PI * 2
|
|
47
|
+
r = radius * (0.72 + rand * 0.45)
|
|
48
|
+
[Math.cos(angle) * r, Math.sin(angle) * r]
|
|
49
|
+
end
|
|
50
|
+
Asteroid.new(x, y, rand(-156.0..156.0), rand(-156.0..156.0), radius, points)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# === Mutable state ===
|
|
54
|
+
#
|
|
55
|
+
# Plain locals; the `update` and `render` blocks below close over them.
|
|
56
|
+
# All time-bearing quantities are in wall-clock seconds.
|
|
57
|
+
|
|
58
|
+
ship_x = WIDTH / 2.0
|
|
59
|
+
ship_y = HEIGHT / 2.0
|
|
60
|
+
ship_vx = 0.0
|
|
61
|
+
ship_vy = 0.0
|
|
62
|
+
ship_angle = -Math::PI / 2 # facing up (-y)
|
|
63
|
+
left = false
|
|
64
|
+
right = false
|
|
65
|
+
thrust = false
|
|
66
|
+
firing = false
|
|
67
|
+
cooldown = 0 # seconds until the next bullet may fire
|
|
68
|
+
score = 0
|
|
69
|
+
bullets = []
|
|
70
|
+
asteroids = []
|
|
71
|
+
sparks = []
|
|
72
|
+
respawn_timer = 0 # > 0 (seconds) while the ship is dead
|
|
73
|
+
invuln_timer = 0 # > 0 (seconds) just after respawn; collisions ignored
|
|
74
|
+
firework_timer = 0 # seconds until the next victory firework
|
|
75
|
+
thrust_spark_accum = 0.0 # fractional carry for rate-based thrust emitter
|
|
76
|
+
|
|
77
|
+
# Pre-baked starfield: each entry is [x, y, radius, alpha].
|
|
78
|
+
stars = Array.new(70) { [rand(WIDTH), rand(HEIGHT), rand(0.4..1.3), 0.25 + rand * 0.55] }
|
|
79
|
+
|
|
80
|
+
# Firework palette as RGB triples; alpha is filled in at render time.
|
|
81
|
+
FIREWORK_HUES = [[1.0, 0.3, 0.4], [0.4, 0.7, 1.0], [0.5, 1.0, 0.5],
|
|
82
|
+
[1.0, 0.85, 0.3], [0.95, 0.55, 1.0], [0.4, 1.0, 0.95]]
|
|
83
|
+
|
|
84
|
+
# === HUD ===
|
|
85
|
+
|
|
86
|
+
score_text = Text.new('Score: 0', x: 16, y: 12, size: 18, color: '#e5e7eb')
|
|
87
|
+
|
|
88
|
+
# Cleared banner: hidden until the player wins. `x: :center` re-resolves at
|
|
89
|
+
# draw time against the live viewport, so the banner stays centered even if
|
|
90
|
+
# the window resizes.
|
|
91
|
+
cleared_title = Text.new('Asteroids Cleared!', x: :center, y: HEIGHT / 2 - 56,
|
|
92
|
+
size: 40, color: '#fde047', visible: false)
|
|
93
|
+
cleared_subtitle = Text.new('Press R to restart', x: :center, y: HEIGHT / 2 + 4,
|
|
94
|
+
size: 20, color: '#e5e7eb', visible: false)
|
|
95
|
+
|
|
96
|
+
# Captured as a lambda so it can rebuild state both at startup and on `r`.
|
|
97
|
+
reset = lambda do
|
|
98
|
+
ship_x = WIDTH / 2.0
|
|
99
|
+
ship_y = HEIGHT / 2.0
|
|
100
|
+
ship_vx = 0.0
|
|
101
|
+
ship_vy = 0.0
|
|
102
|
+
ship_angle = -Math::PI / 2
|
|
103
|
+
cooldown = 0
|
|
104
|
+
score = 0
|
|
105
|
+
respawn_timer = 0
|
|
106
|
+
invuln_timer = 1.5 # grace period at game start matches the post-death grace
|
|
107
|
+
firework_timer = 0
|
|
108
|
+
bullets.clear
|
|
109
|
+
sparks.clear
|
|
110
|
+
asteroids.replace(Array.new(6) { make_asteroid })
|
|
111
|
+
score_text.content = 'Score: 0'
|
|
112
|
+
cleared_title.hide
|
|
113
|
+
cleared_subtitle.hide
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
reset.call
|
|
117
|
+
|
|
118
|
+
# === Input ===
|
|
119
|
+
#
|
|
120
|
+
# Hold-to-repeat keys (left/right/up/space) flip booleans the update loop
|
|
121
|
+
# reads each frame. The fire `cooldown` paces space-held auto-fire.
|
|
122
|
+
|
|
123
|
+
on :key_down do |event|
|
|
124
|
+
case event.key
|
|
125
|
+
when 'left'
|
|
126
|
+
left = true
|
|
127
|
+
when 'right'
|
|
128
|
+
right = true
|
|
129
|
+
when 'up'
|
|
130
|
+
thrust = true
|
|
131
|
+
when 'space'
|
|
132
|
+
firing = true
|
|
133
|
+
when 'r'
|
|
134
|
+
reset.call
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
on :key_up do |event|
|
|
139
|
+
left = false if event.key? :left
|
|
140
|
+
right = false if event.key? :right
|
|
141
|
+
thrust = false if event.key? :up
|
|
142
|
+
firing = false if event.key? :space
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Gamepad: dpad left/right/up mirror the rotation and thrust keys; any button fires.
|
|
146
|
+
on :gamepad_button_down do |_pad, button|
|
|
147
|
+
case button
|
|
148
|
+
when :dpad_left then left = true
|
|
149
|
+
when :dpad_right then right = true
|
|
150
|
+
when :dpad_up then thrust = true
|
|
151
|
+
end
|
|
152
|
+
firing = true
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
on :gamepad_button_up do |pad, button|
|
|
156
|
+
case button
|
|
157
|
+
when :dpad_left then left = false
|
|
158
|
+
when :dpad_right then right = false
|
|
159
|
+
when :dpad_up then thrust = false
|
|
160
|
+
end
|
|
161
|
+
firing = false if pad.buttons_held.empty?
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# === Per-frame update ===
|
|
165
|
+
#
|
|
166
|
+
# Ruby 2D calls this block once per rendered frame and passes `dt` — wall-clock
|
|
167
|
+
# seconds since the previous update. All rates below are in per-second units
|
|
168
|
+
# (velocities in px/sec, accelerations in px/sec², drag as a per-second decay
|
|
169
|
+
# rate `vx *= Math.exp(-rate * dt)`), so feel is identical at any refresh rate.
|
|
170
|
+
|
|
171
|
+
update do |dt|
|
|
172
|
+
# Ship state machine: respawning, otherwise alive and being driven.
|
|
173
|
+
if respawn_timer.positive?
|
|
174
|
+
respawn_timer -= dt
|
|
175
|
+
if respawn_timer <= 0
|
|
176
|
+
respawn_timer = 0
|
|
177
|
+
ship_x = WIDTH / 2.0
|
|
178
|
+
ship_y = HEIGHT / 2.0
|
|
179
|
+
ship_vx = 0.0
|
|
180
|
+
ship_vy = 0.0
|
|
181
|
+
ship_angle = -Math::PI / 2
|
|
182
|
+
invuln_timer = 1.5 # 1.5s of grace, fading from translucent to solid
|
|
183
|
+
end
|
|
184
|
+
else
|
|
185
|
+
ship_angle -= 7.2 * dt if left # 7.2 rad/sec turn rate
|
|
186
|
+
ship_angle += 7.2 * dt if right
|
|
187
|
+
if thrust
|
|
188
|
+
ship_vx += Math.cos(ship_angle) * THRUST * dt
|
|
189
|
+
ship_vy += Math.sin(ship_angle) * THRUST * dt
|
|
190
|
+
end
|
|
191
|
+
drag = Math.exp(-0.964 * dt) # mild drag so the ship eventually slows
|
|
192
|
+
ship_vx *= drag
|
|
193
|
+
ship_vy *= drag
|
|
194
|
+
# Toroidal wrap: drift off one edge, reappear on the opposite side.
|
|
195
|
+
ship_x = (ship_x + ship_vx * dt) % WIDTH
|
|
196
|
+
ship_y = (ship_y + ship_vy * dt) % HEIGHT
|
|
197
|
+
cooldown -= dt if cooldown.positive?
|
|
198
|
+
|
|
199
|
+
# Auto-fire while space is held; `cooldown` paces it.
|
|
200
|
+
if firing && cooldown <= 0
|
|
201
|
+
bullets << Bullet.new(ship_x + Math.cos(ship_angle) * SHIP_R,
|
|
202
|
+
ship_y + Math.sin(ship_angle) * SHIP_R,
|
|
203
|
+
Math.cos(ship_angle) * 840 + ship_vx, # 840 px/sec muzzle speed
|
|
204
|
+
Math.sin(ship_angle) * 840 + ship_vy)
|
|
205
|
+
cooldown = 0.1 # seconds between auto-fire shots
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Spawn thrust sparks behind the ship while accelerating. Rate-based: ~240
|
|
209
|
+
# sparks/sec on average. The accumulator carries the fractional part so
|
|
210
|
+
# high refresh rates don't drop sparks and low ones don't pile them up.
|
|
211
|
+
if thrust
|
|
212
|
+
thrust_spark_accum += 240 * dt
|
|
213
|
+
count = thrust_spark_accum.to_i
|
|
214
|
+
thrust_spark_accum -= count
|
|
215
|
+
count.times do
|
|
216
|
+
back = ship_angle + Math::PI + (rand - 0.5) * 0.7
|
|
217
|
+
speed = 192 + rand * 216 # 192–408 px/sec
|
|
218
|
+
life = 0.12 + rand * 0.08 # 0.12–0.20 sec
|
|
219
|
+
sparks << Spark.new(ship_x - Math.cos(ship_angle) * SHIP_R * 0.45,
|
|
220
|
+
ship_y - Math.sin(ship_angle) * SHIP_R * 0.45,
|
|
221
|
+
Math.cos(back) * speed + ship_vx * 0.5,
|
|
222
|
+
Math.sin(back) * speed + ship_vy * 0.5,
|
|
223
|
+
life, life)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
invuln_timer -= dt if invuln_timer.positive?
|
|
228
|
+
invuln_timer = 0 if invuln_timer.negative?
|
|
229
|
+
|
|
230
|
+
# Particle update: drift, decay, prune dead ones.
|
|
231
|
+
spark_drag = Math.exp(-7.43 * dt)
|
|
232
|
+
sparks.each do |s|
|
|
233
|
+
s.x += s.vx * dt
|
|
234
|
+
s.y += s.vy * dt
|
|
235
|
+
s.vx *= spark_drag
|
|
236
|
+
s.vy *= spark_drag
|
|
237
|
+
s.life -= dt
|
|
238
|
+
end
|
|
239
|
+
sparks.reject! { |s| s.life <= 0 }
|
|
240
|
+
|
|
241
|
+
# Bullets fly straight and disappear when they leave the window.
|
|
242
|
+
bullets.each do |b|
|
|
243
|
+
b.x += b.vx * dt
|
|
244
|
+
b.y += b.vy * dt
|
|
245
|
+
end
|
|
246
|
+
bullets.reject! { |b| b.x < 0 || b.x > WIDTH || b.y < 0 || b.y > HEIGHT }
|
|
247
|
+
|
|
248
|
+
# Asteroids drift and wrap.
|
|
249
|
+
asteroids.each do |a|
|
|
250
|
+
a.x = (a.x + a.vx * dt) % WIDTH
|
|
251
|
+
a.y = (a.y + a.vy * dt) % HEIGHT
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Bullet vs. asteroid: simple circle test. `bullets.dup` lets us mutate
|
|
255
|
+
# the original array safely while iterating. A hit awards more for small
|
|
256
|
+
# asteroids and splits big ones into two smaller children at the same
|
|
257
|
+
# spot; asteroids below radius 20 don't split further.
|
|
258
|
+
bullets.dup.each do |b|
|
|
259
|
+
hit = asteroids.find do |a|
|
|
260
|
+
dx = b.x - a.x
|
|
261
|
+
dy = b.y - a.y
|
|
262
|
+
dx * dx + dy * dy < a.radius * a.radius
|
|
263
|
+
end
|
|
264
|
+
next unless hit
|
|
265
|
+
|
|
266
|
+
bullets.delete(b)
|
|
267
|
+
asteroids.delete(hit)
|
|
268
|
+
score += hit.radius < 25 ? 200 : 100
|
|
269
|
+
score_text.content = "Score: #{score}"
|
|
270
|
+
# Debris burst in the asteroid's slate color. Count and speed scale with
|
|
271
|
+
# size so big rocks pop harder than little chips.
|
|
272
|
+
burst = (hit.radius * 0.5).to_i + 8
|
|
273
|
+
burst.times do
|
|
274
|
+
angle = rand * Math::PI * 2
|
|
275
|
+
speed = 72 + rand * (144 + hit.radius * 7.2) # px/sec
|
|
276
|
+
life = 0.17 + rand * 0.17 # 0.17–0.33 sec
|
|
277
|
+
sparks << Spark.new(hit.x, hit.y,
|
|
278
|
+
Math.cos(angle) * speed, Math.sin(angle) * speed,
|
|
279
|
+
life, life, [0.75, 0.82, 0.9])
|
|
280
|
+
end
|
|
281
|
+
if hit.radius > 20
|
|
282
|
+
2.times { asteroids << make_asteroid(hit.x, hit.y, hit.radius * 0.58) }
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# Ship vs. asteroid. The `((d + size/2) % size) - size/2` trick gives the
|
|
287
|
+
# shortest distance across the toroidal screen, so an asteroid poking
|
|
288
|
+
# through one edge can still hit a ship hugging the opposite edge.
|
|
289
|
+
if respawn_timer.zero? && invuln_timer.zero?
|
|
290
|
+
ship_hit = asteroids.any? do |a|
|
|
291
|
+
dx = ((ship_x - a.x + WIDTH / 2) % WIDTH) - WIDTH / 2
|
|
292
|
+
dy = ((ship_y - a.y + HEIGHT / 2) % HEIGHT) - HEIGHT / 2
|
|
293
|
+
dx * dx + dy * dy < (a.radius + SHIP_R) ** 2
|
|
294
|
+
end
|
|
295
|
+
if ship_hit
|
|
296
|
+
# Burst a ring of sparks for the explosion.
|
|
297
|
+
25.times do
|
|
298
|
+
angle = rand * Math::PI * 2
|
|
299
|
+
speed = 96 + rand * 408 # px/sec
|
|
300
|
+
life = 0.25 + rand * 0.17 # 0.25–0.42 sec
|
|
301
|
+
sparks << Spark.new(ship_x, ship_y,
|
|
302
|
+
Math.cos(angle) * speed, Math.sin(angle) * speed,
|
|
303
|
+
life, life)
|
|
304
|
+
end
|
|
305
|
+
score = [score - HIT_PENALTY, 0].max
|
|
306
|
+
score_text.content = "Score: #{score}"
|
|
307
|
+
respawn_timer = 1.0 # 1 second dead before the ship reappears
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# All asteroids destroyed: show the cleared banner and keep launching
|
|
312
|
+
# colored fireworks at random spots.
|
|
313
|
+
if asteroids.empty? && respawn_timer.zero?
|
|
314
|
+
cleared_title.show
|
|
315
|
+
cleared_subtitle.show
|
|
316
|
+
firework_timer -= dt
|
|
317
|
+
if firework_timer <= 0
|
|
318
|
+
fx = 80 + rand(WIDTH - 160)
|
|
319
|
+
fy = 80 + rand((HEIGHT - 200))
|
|
320
|
+
hue = FIREWORK_HUES.sample
|
|
321
|
+
28.times do |i|
|
|
322
|
+
angle = i / 28.0 * Math::PI * 2 + (rand - 0.5) * 0.2
|
|
323
|
+
speed = 144 + rand * 312 # px/sec
|
|
324
|
+
life = 0.29 + rand * 0.21 # 0.29–0.50 sec
|
|
325
|
+
sparks << Spark.new(fx, fy, Math.cos(angle) * speed, Math.sin(angle) * speed,
|
|
326
|
+
life, life, hue)
|
|
327
|
+
end
|
|
328
|
+
firework_timer = 0.21 + rand * 0.17 # 0.21–0.38 sec between fireworks
|
|
329
|
+
end
|
|
330
|
+
else
|
|
331
|
+
cleared_title.hide
|
|
332
|
+
cleared_subtitle.hide
|
|
333
|
+
firework_timer = 0
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# === Render ===
|
|
338
|
+
#
|
|
339
|
+
# Draw order is back to front: stars, particles, ship, bullets, asteroids.
|
|
340
|
+
# `Foo.render(...)` is the immediate-mode form: cheap to call every frame
|
|
341
|
+
# and doesn't allocate a persistent object.
|
|
342
|
+
|
|
343
|
+
# The whole game draws behind the HUD (z: :background), so the score and the
|
|
344
|
+
# cleared banner always stay on top.
|
|
345
|
+
render z: :background do
|
|
346
|
+
# Background stars.
|
|
347
|
+
stars.each do |sx, sy, sr, sa|
|
|
348
|
+
Circle.render(x: sx, y: sy, radius: sr, color: [1.0, 1.0, 1.0, sa])
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
# Sparks fade with their remaining life. Fireworks keep their hue;
|
|
352
|
+
# thrust particles cool from yellow toward red as they age.
|
|
353
|
+
sparks.each do |s|
|
|
354
|
+
t = s.life.to_f / s.max_life
|
|
355
|
+
color = if s.hue
|
|
356
|
+
[s.hue[0], s.hue[1], s.hue[2], t]
|
|
357
|
+
else
|
|
358
|
+
[1.0, 0.35 + t * 0.55, 0.1 * t, t]
|
|
359
|
+
end
|
|
360
|
+
Circle.render(x: s.x, y: s.y, radius: 0.8 + t * 1.8, color: color)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# Ship: hidden while respawning; fades up from translucent to solid
|
|
364
|
+
# during the invulnerability window.
|
|
365
|
+
if respawn_timer.zero?
|
|
366
|
+
ship_alpha = invuln_timer.positive? ? 0.25 + 0.75 * (1.0 - invuln_timer / 1.5) : 1.0
|
|
367
|
+
# Local-space layout (nose at +x), rotated into world space:
|
|
368
|
+
# wx = ship_x + px*cos - py*sin
|
|
369
|
+
# wy = ship_y + px*sin + py*cos
|
|
370
|
+
ship_pts = [[SHIP_R, 0], [-SHIP_R * 0.8, -SHIP_R * 0.65], [-SHIP_R * 0.45, 0],
|
|
371
|
+
[-SHIP_R * 0.8, SHIP_R * 0.65]].map do |px, py|
|
|
372
|
+
c = Math.cos(ship_angle)
|
|
373
|
+
s = Math.sin(ship_angle)
|
|
374
|
+
[ship_x + px * c - py * s, ship_y + px * s + py * c]
|
|
375
|
+
end
|
|
376
|
+
if thrust
|
|
377
|
+
# Flame triangle behind the ship, flickering via random length offsets.
|
|
378
|
+
outer = 22 + rand * 14
|
|
379
|
+
inner = 8 + rand * 4
|
|
380
|
+
flame = [
|
|
381
|
+
ship_pts[2],
|
|
382
|
+
[ship_x - Math.cos(ship_angle) * outer, ship_y - Math.sin(ship_angle) * outer],
|
|
383
|
+
[ship_x - Math.cos(ship_angle) * inner, ship_y - Math.sin(ship_angle) * inner]
|
|
384
|
+
]
|
|
385
|
+
Triangle.render(x1: flame[0][0], y1: flame[0][1], x2: flame[1][0], y2: flame[1][1],
|
|
386
|
+
x3: flame[2][0], y3: flame[2][1],
|
|
387
|
+
color: ['#fde047', '#f97316', '#fbbf24'], opacity: ship_alpha)
|
|
388
|
+
end
|
|
389
|
+
Polyline.render(points: ship_pts, closed: true, stroke_width: 2,
|
|
390
|
+
color: '#e5e7eb', opacity: ship_alpha)
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
bullets.each do |b|
|
|
394
|
+
Circle.render(x: b.x, y: b.y, radius: 3, color: '#facc15')
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
asteroids.each do |a|
|
|
398
|
+
pts = a.points.map { |px, py| [a.x + px, a.y + py] }
|
|
399
|
+
Polyline.render(points: pts, closed: true, stroke_width: 2, color: '#94a3b8')
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
show
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Bezier curve editor
|
|
2
|
+
# Drag the four control points to reshape a cubic Bezier curve live.
|
|
3
|
+
#
|
|
4
|
+
# Handles and sample points update as you drag. Press `r` to restore
|
|
5
|
+
# the original curve.
|
|
6
|
+
|
|
7
|
+
require 'ruby2d'
|
|
8
|
+
|
|
9
|
+
# === Tunables ===
|
|
10
|
+
|
|
11
|
+
WIDTH = 800 # window width in pixels
|
|
12
|
+
HEIGHT = 600 # window height in pixels
|
|
13
|
+
CURVE_SAMPLES = 90 # number of line segments approximating the curve
|
|
14
|
+
GRAB_RADIUS = 18 # max pixel distance for picking up a control point
|
|
15
|
+
|
|
16
|
+
# === Window ===
|
|
17
|
+
|
|
18
|
+
set title: 'Ruby 2D ▸ Examples ▸ Bezier curve editor', width: WIDTH, height: HEIGHT, background: '#111827'
|
|
19
|
+
set close_on_esc: true
|
|
20
|
+
set render_mode: :on_demand
|
|
21
|
+
|
|
22
|
+
# === Setup ===
|
|
23
|
+
|
|
24
|
+
canvas = Canvas.new(width: WIDTH, height: HEIGHT, fill: [0.07, 0.10, 0.16, 1])
|
|
25
|
+
|
|
26
|
+
initial = [[90, 500], [230, 90], [560, 90], [710, 500]]
|
|
27
|
+
points = initial.map(&:dup)
|
|
28
|
+
handles = points.each_with_index.map do |(x, y), i|
|
|
29
|
+
Circle.new(x: x, y: y, radius: i.zero? || i == 3 ? 10 : 8,
|
|
30
|
+
color: i.zero? || i == 3 ? '#f97316' : '#38bdf8', z: 5)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
drag_index = nil
|
|
34
|
+
|
|
35
|
+
def bezier_point(points, t)
|
|
36
|
+
u = 1.0 - t
|
|
37
|
+
x = u ** 3 * points[0][0] + 3 * u * u * t * points[1][0] +
|
|
38
|
+
3 * u * t * t * points[2][0] + t ** 3 * points[3][0]
|
|
39
|
+
y = u ** 3 * points[0][1] + 3 * u * u * t * points[1][1] +
|
|
40
|
+
3 * u * t * t * points[2][1] + t ** 3 * points[3][1]
|
|
41
|
+
[x, y]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
redraw = lambda do
|
|
45
|
+
canvas.clear
|
|
46
|
+
canvas.draw_line(x1: points[0][0], y1: points[0][1], x2: points[1][0], y2: points[1][1],
|
|
47
|
+
stroke_width: 2, color: [0.55, 0.65, 0.8, 0.45])
|
|
48
|
+
canvas.draw_line(x1: points[2][0], y1: points[2][1], x2: points[3][0], y2: points[3][1],
|
|
49
|
+
stroke_width: 2, color: [0.55, 0.65, 0.8, 0.45])
|
|
50
|
+
|
|
51
|
+
prev = bezier_point(points, 0)
|
|
52
|
+
1.upto(CURVE_SAMPLES) do |i|
|
|
53
|
+
t = i / CURVE_SAMPLES.to_f
|
|
54
|
+
cur = bezier_point(points, t)
|
|
55
|
+
canvas.draw_line(x1: prev[0], y1: prev[1], x2: cur[0], y2: cur[1],
|
|
56
|
+
stroke_width: 4, color: [0.35, 0.9, 1.0, 0.95])
|
|
57
|
+
prev = cur
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
points.each_with_index do |(x, y), i|
|
|
61
|
+
handles[i].x = x
|
|
62
|
+
handles[i].y = y
|
|
63
|
+
end
|
|
64
|
+
request_render
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
redraw.call
|
|
68
|
+
|
|
69
|
+
# === Input ===
|
|
70
|
+
|
|
71
|
+
on :mouse_down do |event|
|
|
72
|
+
drag_index = points.each_index.find do |i|
|
|
73
|
+
dx = points[i][0] - event.x
|
|
74
|
+
dy = points[i][1] - event.y
|
|
75
|
+
dx * dx + dy * dy <= GRAB_RADIUS * GRAB_RADIUS
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
on :mouse_up do
|
|
80
|
+
drag_index = nil
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
on :mouse_move do |event|
|
|
84
|
+
next if drag_index.nil?
|
|
85
|
+
|
|
86
|
+
points[drag_index][0] = event.x.clamp(0, WIDTH)
|
|
87
|
+
points[drag_index][1] = event.y.clamp(0, HEIGHT)
|
|
88
|
+
redraw.call
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
on key_down: :r do
|
|
92
|
+
points.each_with_index { |p, i| p.replace(initial[i]) }
|
|
93
|
+
redraw.call
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
show
|
data/examples/boids.rb
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Boids
|
|
2
|
+
# A flocking simulation governed by separation, alignment, and cohesion.
|
|
3
|
+
#
|
|
4
|
+
# The flock self-organizes from local rules with no global plan. Move
|
|
5
|
+
# the cursor near the flock to scatter it; press `r` to randomize.
|
|
6
|
+
# Neighbor lookups go through a uniform spatial grid rather than
|
|
7
|
+
# comparing every pair, which is what keeps the flock cheap to run.
|
|
8
|
+
|
|
9
|
+
require 'ruby2d'
|
|
10
|
+
|
|
11
|
+
# === Tunables ===
|
|
12
|
+
|
|
13
|
+
WIDTH = 800 # window width in pixels
|
|
14
|
+
HEIGHT = 600 # window height in pixels
|
|
15
|
+
COUNT = 90 # number of boids in the flock
|
|
16
|
+
VIEW_RADIUS = 70 # how far a boid can see neighbors (pixels)
|
|
17
|
+
AVOID_RADIUS = 24 # personal-space radius for separation (pixels)
|
|
18
|
+
MAX_SPEED = 432 # cap on boid velocity (px/sec)
|
|
19
|
+
MIN_SPEED = 80 # boids cruise at least this fast (px/sec)
|
|
20
|
+
MAX_FORCE = 1152 # cap on per-update steering force (px/sec²)
|
|
21
|
+
ALIGNMENT = 4.2 # alignment blend rate toward neighbor heading (per sec)
|
|
22
|
+
COHESION = 1.2 # cohesion blend rate toward flock center (per sec)
|
|
23
|
+
SEPARATION = 10.8 # separation blend rate away from close neighbors (per sec)
|
|
24
|
+
MOUSE_REPULSION = 12960 # repulsion strength from the cursor (px/sec²)
|
|
25
|
+
CELL_W = 80 # spatial grid cell width in pixels (≥ VIEW_RADIUS)
|
|
26
|
+
CELL_H = 75 # spatial grid cell height in pixels (≥ VIEW_RADIUS)
|
|
27
|
+
|
|
28
|
+
GCOLS = WIDTH / CELL_W
|
|
29
|
+
GROWS = HEIGHT / CELL_H
|
|
30
|
+
NEIGHBORHOOD = [-1, 0, 1].freeze
|
|
31
|
+
|
|
32
|
+
# === Window ===
|
|
33
|
+
|
|
34
|
+
set title: 'Ruby 2D ▸ Examples ▸ Boids', width: WIDTH, height: HEIGHT, background: '#07111f'
|
|
35
|
+
set close_on_esc: true
|
|
36
|
+
|
|
37
|
+
# === Boid struct and helpers ===
|
|
38
|
+
|
|
39
|
+
Boid = Struct.new(:x, :y, :vx, :vy, :tri)
|
|
40
|
+
|
|
41
|
+
def make_boid
|
|
42
|
+
angle = rand * Math::PI * 2
|
|
43
|
+
Boid.new(
|
|
44
|
+
rand(WIDTH), rand(HEIGHT),
|
|
45
|
+
Math.cos(angle) * MAX_SPEED, Math.sin(angle) * MAX_SPEED,
|
|
46
|
+
Triangle.new(x1: 0, y1: -8, x2: -5, y2: 6, x3: 5, y3: 6, color: '#67e8f9')
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def limit(x, y, max)
|
|
51
|
+
mag = Math.sqrt(x * x + y * y)
|
|
52
|
+
return [x, y] if mag <= max || mag.zero?
|
|
53
|
+
|
|
54
|
+
[x / mag * max, y / mag * max]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def set_boid_triangle(boid)
|
|
58
|
+
angle = Math.atan2(boid.vy, boid.vx) + Math::PI / 2
|
|
59
|
+
pts = [[0, -10], [-6, 8], [6, 8]].map do |px, py|
|
|
60
|
+
c = Math.cos(angle)
|
|
61
|
+
s = Math.sin(angle)
|
|
62
|
+
[boid.x + px * c - py * s, boid.y + px * s + py * c]
|
|
63
|
+
end
|
|
64
|
+
boid.tri.x1, boid.tri.y1 = pts[0]
|
|
65
|
+
boid.tri.x2, boid.tri.y2 = pts[1]
|
|
66
|
+
boid.tri.x3, boid.tri.y3 = pts[2]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# === Mutable state ===
|
|
70
|
+
|
|
71
|
+
boids = Array.new(COUNT) { make_boid }
|
|
72
|
+
buckets = Array.new(GCOLS * GROWS) { [] }
|
|
73
|
+
mouse_x = -1000
|
|
74
|
+
mouse_y = -1000
|
|
75
|
+
|
|
76
|
+
# === Input ===
|
|
77
|
+
|
|
78
|
+
on :mouse_move do |event|
|
|
79
|
+
mouse_x = event.x
|
|
80
|
+
mouse_y = event.y
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
on key_down: :r do
|
|
84
|
+
boids.each do |b|
|
|
85
|
+
b.x = rand(WIDTH)
|
|
86
|
+
b.y = rand(HEIGHT)
|
|
87
|
+
angle = rand * Math::PI * 2
|
|
88
|
+
b.vx = Math.cos(angle) * MAX_SPEED
|
|
89
|
+
b.vy = Math.sin(angle) * MAX_SPEED
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# === Per-frame update ===
|
|
94
|
+
|
|
95
|
+
update do |dt|
|
|
96
|
+
# Bucket every boid by cell. Cells are at least VIEW_RADIUS across and
|
|
97
|
+
# divide the window exactly, so a boid's visible neighbors can only lie
|
|
98
|
+
# in the 3×3 block around its own cell — and the toroidal wrap lands on
|
|
99
|
+
# a cell boundary. `clear` keeps each bucket's backing array, so the
|
|
100
|
+
# refill reuses capacity instead of allocating one per frame.
|
|
101
|
+
buckets.each(&:clear)
|
|
102
|
+
boids.each do |b|
|
|
103
|
+
gx = (b.x / CELL_W).to_i.clamp(0, GCOLS - 1)
|
|
104
|
+
gy = (b.y / CELL_H).to_i.clamp(0, GROWS - 1)
|
|
105
|
+
buckets[gy * GCOLS + gx] << b
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
boids.each do |b|
|
|
109
|
+
sep_x = 0.0
|
|
110
|
+
sep_y = 0.0
|
|
111
|
+
ali_x = 0.0
|
|
112
|
+
ali_y = 0.0
|
|
113
|
+
coh_x = 0.0
|
|
114
|
+
coh_y = 0.0
|
|
115
|
+
neighbors = 0
|
|
116
|
+
|
|
117
|
+
cx = (b.x / CELL_W).to_i.clamp(0, GCOLS - 1)
|
|
118
|
+
cy = (b.y / CELL_H).to_i.clamp(0, GROWS - 1)
|
|
119
|
+
|
|
120
|
+
NEIGHBORHOOD.each do |oy|
|
|
121
|
+
row = ((cy + oy) % GROWS) * GCOLS
|
|
122
|
+
NEIGHBORHOOD.each do |ox|
|
|
123
|
+
buckets[row + ((cx + ox) % GCOLS)].each do |other|
|
|
124
|
+
next if other.equal?(b)
|
|
125
|
+
|
|
126
|
+
dx = other.x - b.x
|
|
127
|
+
dy = other.y - b.y
|
|
128
|
+
dx -= WIDTH if dx > WIDTH / 2
|
|
129
|
+
dx += WIDTH if dx < -WIDTH / 2
|
|
130
|
+
dy -= HEIGHT if dy > HEIGHT / 2
|
|
131
|
+
dy += HEIGHT if dy < -HEIGHT / 2
|
|
132
|
+
d2 = dx * dx + dy * dy
|
|
133
|
+
next if d2 > VIEW_RADIUS * VIEW_RADIUS
|
|
134
|
+
|
|
135
|
+
d = Math.sqrt(d2) + 0.001
|
|
136
|
+
neighbors += 1
|
|
137
|
+
ali_x += other.vx
|
|
138
|
+
ali_y += other.vy
|
|
139
|
+
coh_x += b.x + dx
|
|
140
|
+
coh_y += b.y + dy
|
|
141
|
+
if d < AVOID_RADIUS
|
|
142
|
+
sep_x -= dx / d
|
|
143
|
+
sep_y -= dy / d
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
ax = 0.0
|
|
150
|
+
ay = 0.0
|
|
151
|
+
if neighbors.positive?
|
|
152
|
+
ali_x, ali_y = limit(ali_x / neighbors, ali_y / neighbors, MAX_SPEED)
|
|
153
|
+
ax += (ali_x - b.vx) * ALIGNMENT
|
|
154
|
+
ay += (ali_y - b.vy) * ALIGNMENT
|
|
155
|
+
|
|
156
|
+
target_x = coh_x / neighbors
|
|
157
|
+
target_y = coh_y / neighbors
|
|
158
|
+
seek_x, seek_y = limit(target_x - b.x, target_y - b.y, MAX_SPEED)
|
|
159
|
+
ax += (seek_x - b.vx) * COHESION
|
|
160
|
+
ay += (seek_y - b.vy) * COHESION
|
|
161
|
+
|
|
162
|
+
sep_x, sep_y = limit(sep_x, sep_y, MAX_SPEED)
|
|
163
|
+
ax += sep_x * SEPARATION
|
|
164
|
+
ay += sep_y * SEPARATION
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
mdx = b.x - mouse_x
|
|
168
|
+
mdy = b.y - mouse_y
|
|
169
|
+
md2 = mdx * mdx + mdy * mdy
|
|
170
|
+
if md2 < 80 * 80
|
|
171
|
+
md = Math.sqrt(md2) + 0.001
|
|
172
|
+
ax += mdx / md * MOUSE_REPULSION
|
|
173
|
+
ay += mdy / md * MOUSE_REPULSION
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
ax, ay = limit(ax, ay, MAX_FORCE)
|
|
177
|
+
b.vx += ax * dt
|
|
178
|
+
b.vy += ay * dt
|
|
179
|
+
b.vx, b.vy = limit(b.vx, b.vy, MAX_SPEED)
|
|
180
|
+
speed = Math.sqrt(b.vx * b.vx + b.vy * b.vy)
|
|
181
|
+
if speed < MIN_SPEED && speed > 0.01
|
|
182
|
+
b.vx *= MIN_SPEED / speed
|
|
183
|
+
b.vy *= MIN_SPEED / speed
|
|
184
|
+
end
|
|
185
|
+
b.x = (b.x + b.vx * dt) % WIDTH
|
|
186
|
+
b.y = (b.y + b.vy * dt) % HEIGHT
|
|
187
|
+
set_boid_triangle(b)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
show
|