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,335 @@
|
|
|
1
|
+
# Platformer playground
|
|
2
|
+
# A tiny side-scrolling platformer scene built from Ruby 2D shapes.
|
|
3
|
+
#
|
|
4
|
+
# Use left/right (or the gamepad dpad) to run, space/up (or the south
|
|
5
|
+
# button) to jump, and press `r` to return to the start.
|
|
6
|
+
|
|
7
|
+
require 'ruby2d'
|
|
8
|
+
|
|
9
|
+
# === Tunables ===
|
|
10
|
+
|
|
11
|
+
WIDTH = 800 # window width in pixels
|
|
12
|
+
HEIGHT = 600 # window height in pixels
|
|
13
|
+
GROUND_Y = 540 # y of the ground strip in world space
|
|
14
|
+
WORLD_W = 1600 # total world width in pixels
|
|
15
|
+
GRAVITY = 1980 # downward acceleration (px/sec²)
|
|
16
|
+
RUN_ACCEL = 2520 # horizontal acceleration while pressing left/right (px/sec²)
|
|
17
|
+
FRICTION = 11.9 # horizontal decay rate when no input (per-sec; vx *= exp(-FRICTION * dt))
|
|
18
|
+
JUMP_V = -750 # initial jump velocity (px/sec, negative is up)
|
|
19
|
+
MAX_SPEED = 420 # horizontal speed cap (px/sec)
|
|
20
|
+
CAMERA_SMOOTHING = 7.67 # camera ease rate toward the player (per-sec)
|
|
21
|
+
GEM_BOB_AMP = 6 # how far gems bob up and down (px)
|
|
22
|
+
GEM_BOB_RATE = 2.6 # gem bob speed (rad/sec)
|
|
23
|
+
|
|
24
|
+
# Daytime sky and earthy world colors.
|
|
25
|
+
SKY_TOP = '#38a9f4' # sky at the top of the window
|
|
26
|
+
SKY_HORIZON = '#c4ecfe' # sky near the horizon
|
|
27
|
+
SUN_X = WIDTH - 120 # sun center x (screen space)
|
|
28
|
+
SUN_Y = 96 # sun center y (screen space)
|
|
29
|
+
HILL_FAR = '#a7ccd8' # hazy far hills
|
|
30
|
+
HILL_NEAR = '#8bbf86' # green near hills
|
|
31
|
+
CLOUD = [1.0, 1.0, 1.0, 0.9]
|
|
32
|
+
DIRT = '#7a5334' # ground fill
|
|
33
|
+
GRASS = '#4d9e3f' # grass band and platform caps
|
|
34
|
+
GRASS_CAP = '#86d95c' # bright grass highlight line
|
|
35
|
+
|
|
36
|
+
# === Window ===
|
|
37
|
+
|
|
38
|
+
set title: 'Ruby 2D ▸ Examples ▸ Platformer playground', width: WIDTH, height: HEIGHT, background: SKY_HORIZON
|
|
39
|
+
set close_on_esc: true
|
|
40
|
+
|
|
41
|
+
# === Game-object structs ===
|
|
42
|
+
|
|
43
|
+
Box = Struct.new(:x, :y, :width, :height)
|
|
44
|
+
|
|
45
|
+
def rects_overlap?(a, b)
|
|
46
|
+
a.x < b.x + b.width && a.x + a.width > b.x &&
|
|
47
|
+
a.y < b.y + b.height && a.y + a.height > b.y
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Build a red diamond gem at (x, y) — trapezoidal crown + triangular
|
|
51
|
+
# pavilion + lighter facet. Shared by the playfield gems and the HUD icon.
|
|
52
|
+
def build_gem(x, y, z: 0)
|
|
53
|
+
crown = Quad.new(
|
|
54
|
+
x1: x - 8, y1: y - 10,
|
|
55
|
+
x2: x + 8, y2: y - 10,
|
|
56
|
+
x3: x + 14, y3: y - 4,
|
|
57
|
+
x4: x - 14, y4: y - 4,
|
|
58
|
+
color: '#dc2626', z: z
|
|
59
|
+
)
|
|
60
|
+
pavilion = Triangle.new(
|
|
61
|
+
x1: x - 14, y1: y - 4,
|
|
62
|
+
x2: x + 14, y2: y - 4,
|
|
63
|
+
x3: x, y3: y + 10,
|
|
64
|
+
color: '#dc2626', z: z
|
|
65
|
+
)
|
|
66
|
+
facet = Triangle.new(
|
|
67
|
+
x1: x - 8, y1: y - 10,
|
|
68
|
+
x2: x, y2: y - 4,
|
|
69
|
+
x3: x - 14, y3: y - 4,
|
|
70
|
+
color: '#fca5a5', z: z
|
|
71
|
+
)
|
|
72
|
+
[crown, pavilion, facet]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Four overlapping white puffs make a soft cloud, returned as a list so the
|
|
76
|
+
# parallax loop can scroll each puff.
|
|
77
|
+
def cloud_puffs(cx, cy, s)
|
|
78
|
+
[
|
|
79
|
+
Circle.new(x: cx, y: cy, radius: 24 * s, color: CLOUD, z: -35),
|
|
80
|
+
Circle.new(x: cx - 26 * s, y: cy + 7 * s, radius: 17 * s, color: CLOUD, z: -35),
|
|
81
|
+
Circle.new(x: cx + 28 * s, y: cy + 5 * s, radius: 19 * s, color: CLOUD, z: -35),
|
|
82
|
+
Circle.new(x: cx + 2 * s, y: cy + 11 * s, radius: 20 * s, color: CLOUD, z: -35)
|
|
83
|
+
]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# === Backdrop ===
|
|
87
|
+
#
|
|
88
|
+
# A gradient sky and a soft sun sit still; clouds and two rows of rounded hills
|
|
89
|
+
# scroll at a fraction of the camera speed for a parallax sense of depth. Each
|
|
90
|
+
# scrolling piece is stored as `[shape, base_x, factor]`. Everything lives at
|
|
91
|
+
# negative z, behind the playfield.
|
|
92
|
+
|
|
93
|
+
Quad.new(x1: 0, y1: 0, x2: WIDTH, y2: 0, x3: WIDTH, y3: HEIGHT, x4: 0, y4: HEIGHT,
|
|
94
|
+
color: [SKY_TOP, SKY_TOP, SKY_HORIZON, SKY_HORIZON], z: -40)
|
|
95
|
+
|
|
96
|
+
Circle.new(x: SUN_X, y: SUN_Y, radius: 60, color: [1.0, 0.95, 0.7, 0.16], z: -39)
|
|
97
|
+
Circle.new(x: SUN_X, y: SUN_Y, radius: 40, color: [1.0, 0.96, 0.75, 0.26], z: -39)
|
|
98
|
+
Circle.new(x: SUN_X, y: SUN_Y, radius: 28, color: '#fff2b0', z: -39)
|
|
99
|
+
|
|
100
|
+
parallax = []
|
|
101
|
+
|
|
102
|
+
[[150, 90, 1.0], [430, 128, 0.7], [660, 72, 1.1], [980, 116, 0.85]].each do |cx, cy, s|
|
|
103
|
+
cloud_puffs(cx, cy, s).each { |c| parallax << [c, c.x, 0.1] }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Far hazy hills (slow), then nearer green hills (faster) — big circles whose
|
|
107
|
+
# rounded tops peek above the ground.
|
|
108
|
+
[120, 480, 900, 1360, 1650].each do |hx|
|
|
109
|
+
parallax << [Circle.new(x: hx, y: 560, radius: 160, color: HILL_FAR, z: -30), hx, 0.15]
|
|
110
|
+
end
|
|
111
|
+
[260, 700, 1120, 1520].each do |hx|
|
|
112
|
+
parallax << [Circle.new(x: hx, y: 650, radius: 210, color: HILL_NEAR, z: -20), hx, 0.3]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# === Level ===
|
|
116
|
+
|
|
117
|
+
level_data = [
|
|
118
|
+
[0, GROUND_Y, 1600, 60],
|
|
119
|
+
[150, 455, 160, 24],
|
|
120
|
+
[390, 390, 150, 24],
|
|
121
|
+
[660, 450, 180, 24],
|
|
122
|
+
[930, 350, 130, 24],
|
|
123
|
+
[1160, 430, 180, 24],
|
|
124
|
+
[1400, 300, 140, 24]
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
# The ground is a brown dirt rect with a grass band and a bright cap line on
|
|
128
|
+
# top; floating platforms are slate with a thin grass cap. `platforms[0]` is
|
|
129
|
+
# the ground and doubles as the collision floor.
|
|
130
|
+
platforms = level_data.map.with_index do |(x, y, w, h), i|
|
|
131
|
+
Rectangle.new(x: x, y: y, width: w, height: h, color: i.zero? ? DIRT : '#a8a29e')
|
|
132
|
+
end
|
|
133
|
+
grass_strip = Rectangle.new(x: 0, y: GROUND_Y, width: WORLD_W, height: 16, color: GRASS, z: 1)
|
|
134
|
+
grass_cap = Rectangle.new(x: 0, y: GROUND_Y, width: WORLD_W, height: 3, color: GRASS_CAP, z: 1)
|
|
135
|
+
platform_caps = level_data.drop(1).map do |x, y, w, _h|
|
|
136
|
+
Rectangle.new(x: x, y: y, width: w, height: 5, color: GRASS, z: 1)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Highest platform top at or below `from_y` under world x `x`, defaulting to
|
|
140
|
+
# the ground. Used to drop gem and player shadows onto the right surface.
|
|
141
|
+
surface_below = lambda do |x, from_y|
|
|
142
|
+
best = GROUND_Y
|
|
143
|
+
level_data.each do |px, py, pw, _ph|
|
|
144
|
+
best = [best, py].min if x >= px && x <= px + pw && py >= from_y - 1
|
|
145
|
+
end
|
|
146
|
+
best
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Red diamond gems — each stored as `[shape, world_x, world_y]` so the update
|
|
150
|
+
# loop can scroll and bob all parts together against the camera.
|
|
151
|
+
gem_data = [[220, 425], [460, 360], [1000, 320], [1465, 270]]
|
|
152
|
+
gems = gem_data.map do |x, y|
|
|
153
|
+
build_gem(x, y, z: 3).map { |s| [s, s.x, s.y] }
|
|
154
|
+
end
|
|
155
|
+
gem_collected = Array.new(gems.length, false)
|
|
156
|
+
|
|
157
|
+
# A soft shadow on the surface under each gem; it shrinks as the gem bobs up.
|
|
158
|
+
gem_shadow_y = gem_data.map { |gx, gy| surface_below.call(gx, gy) }
|
|
159
|
+
gem_shadows = gem_data.map.with_index do |(gx, _gy), i|
|
|
160
|
+
Ellipse.new(x: gx, y: gem_shadow_y[i], xradius: 12, yradius: 4,
|
|
161
|
+
color: 'black', opacity: 0.18, z: 2)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# === Mutable state ===
|
|
165
|
+
|
|
166
|
+
player = Rectangle.new(x: 60, y: GROUND_Y - 42, width: 28, height: 42, color: '#1e3a8a', z: 4)
|
|
167
|
+
player_shadow = Ellipse.new(x: 0, y: 0, xradius: 16, yradius: 5, color: 'black', opacity: 0.24, z: 2)
|
|
168
|
+
|
|
169
|
+
# HUD: a red gem icon followed by a "× N" counter, Mario-64 style. Reuses
|
|
170
|
+
# `build_gem` so the icon and the playfield gems stay in lockstep.
|
|
171
|
+
hud_cx, hud_cy = 30, 26
|
|
172
|
+
build_gem(hud_cx, hud_cy, z: 10)
|
|
173
|
+
label = Text.new('× 0', x: hud_cx + 20, y: hud_cy - 14, size: 22, color: '#0f172a', z: 10)
|
|
174
|
+
|
|
175
|
+
player_world_x = 60.0
|
|
176
|
+
player_world_y = GROUND_Y - 42.0
|
|
177
|
+
vx = 0.0
|
|
178
|
+
vy = 0.0
|
|
179
|
+
left = false
|
|
180
|
+
right = false
|
|
181
|
+
on_ground = false
|
|
182
|
+
camera_x = 0.0
|
|
183
|
+
collected = 0
|
|
184
|
+
anim = 0.0
|
|
185
|
+
|
|
186
|
+
reset = lambda do
|
|
187
|
+
player_world_x = 60.0
|
|
188
|
+
player_world_y = GROUND_Y - 42.0
|
|
189
|
+
vx = 0.0
|
|
190
|
+
vy = 0.0
|
|
191
|
+
collected = 0
|
|
192
|
+
gem_collected.fill(false)
|
|
193
|
+
gems.each { |parts| parts.each { |s, _, _| s.visible = true } }
|
|
194
|
+
gem_shadows.each { |s| s.visible = true }
|
|
195
|
+
label.content = '× 0'
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# === Input ===
|
|
199
|
+
|
|
200
|
+
on key_down: :left do
|
|
201
|
+
left = true
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
on key_down: :right do
|
|
205
|
+
right = true
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
on key_up: :left do
|
|
209
|
+
left = false
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
on key_up: :right do
|
|
213
|
+
right = false
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
on key_down: %i[space up], gamepad_button_down: :south do
|
|
217
|
+
if on_ground
|
|
218
|
+
vy = JUMP_V
|
|
219
|
+
on_ground = false
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
on key_down: :r do
|
|
224
|
+
reset.call
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# === Per-frame update ===
|
|
228
|
+
#
|
|
229
|
+
# Ruby 2D calls this block once per rendered frame and passes `dt` — wall-clock
|
|
230
|
+
# seconds since the previous update. All rates below are in per-second units
|
|
231
|
+
# (velocities in px/sec, accelerations in px/sec², drag as a per-second decay
|
|
232
|
+
# rate `vx *= Math.exp(-rate * dt)`), so feel is identical at any refresh rate.
|
|
233
|
+
|
|
234
|
+
update do |dt|
|
|
235
|
+
anim += dt
|
|
236
|
+
|
|
237
|
+
# Combine keyboard with the dpad held state across all connected pads,
|
|
238
|
+
# so either input runs the player and they don't fight each other.
|
|
239
|
+
go_left = left || gamepads.any? { |p| p.held?(:dpad_left) }
|
|
240
|
+
go_right = right || gamepads.any? { |p| p.held?(:dpad_right) }
|
|
241
|
+
|
|
242
|
+
vx -= RUN_ACCEL * dt if go_left
|
|
243
|
+
vx += RUN_ACCEL * dt if go_right
|
|
244
|
+
vx *= Math.exp(-FRICTION * dt) unless go_left || go_right
|
|
245
|
+
vx = vx.clamp(-MAX_SPEED, MAX_SPEED)
|
|
246
|
+
vy += GRAVITY * dt
|
|
247
|
+
|
|
248
|
+
player_world_x += vx * dt
|
|
249
|
+
player_box = Box.new(player_world_x, player_world_y, player.width, player.height)
|
|
250
|
+
level_data.each do |x, y, w, h|
|
|
251
|
+
p = Box.new(x, y, w, h)
|
|
252
|
+
next unless rects_overlap?(player_box, p)
|
|
253
|
+
|
|
254
|
+
if vx > 0
|
|
255
|
+
player_world_x = p.x - player.width
|
|
256
|
+
elsif vx < 0
|
|
257
|
+
player_world_x = p.x + p.width
|
|
258
|
+
end
|
|
259
|
+
vx = 0
|
|
260
|
+
player_box.x = player_world_x
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
player_world_y += vy * dt
|
|
264
|
+
player_box.x = player_world_x
|
|
265
|
+
player_box.y = player_world_y
|
|
266
|
+
on_ground = false
|
|
267
|
+
level_data.each do |x, y, w, h|
|
|
268
|
+
p = Box.new(x, y, w, h)
|
|
269
|
+
next unless rects_overlap?(player_box, p)
|
|
270
|
+
|
|
271
|
+
if vy > 0
|
|
272
|
+
player_world_y = p.y - player.height
|
|
273
|
+
on_ground = true
|
|
274
|
+
elsif vy < 0
|
|
275
|
+
player_world_y = p.y + p.height
|
|
276
|
+
end
|
|
277
|
+
vy = 0
|
|
278
|
+
player_box.y = player_world_y
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
if player_world_y > HEIGHT + 80
|
|
282
|
+
player_world_x = 60
|
|
283
|
+
player_world_y = GROUND_Y - 42
|
|
284
|
+
vx = 0
|
|
285
|
+
vy = 0
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
player_world_x = player_world_x.clamp(0, WORLD_W - player.width)
|
|
289
|
+
target_x = (player_world_x - WIDTH * 0.45).clamp(0, WORLD_W - WIDTH)
|
|
290
|
+
camera_x += (target_x - camera_x) * (1 - Math.exp(-CAMERA_SMOOTHING * dt))
|
|
291
|
+
|
|
292
|
+
# Parallax backdrop, then the ground, platforms, and their grass caps.
|
|
293
|
+
parallax.each { |s, bx, f| s.x = bx - camera_x * f }
|
|
294
|
+
platforms.each_with_index { |p, i| p.x = level_data[i][0] - camera_x }
|
|
295
|
+
platform_caps.each_with_index { |c, i| c.x = level_data[i + 1][0] - camera_x }
|
|
296
|
+
grass_strip.x = -camera_x
|
|
297
|
+
grass_cap.x = -camera_x
|
|
298
|
+
|
|
299
|
+
# Gems bob on a shared clock (each offset in phase); their shadows shrink as
|
|
300
|
+
# they rise.
|
|
301
|
+
gems.each_with_index do |parts, i|
|
|
302
|
+
bob = Math.sin(anim * GEM_BOB_RATE + i * 1.3) * GEM_BOB_AMP
|
|
303
|
+
parts.each { |s, wx, wy| s.x = wx - camera_x; s.y = wy + bob }
|
|
304
|
+
unless gem_collected[i]
|
|
305
|
+
sc = 1.0 + bob / 15.0
|
|
306
|
+
gem_shadows[i].x = gem_data[i][0] - camera_x
|
|
307
|
+
gem_shadows[i].xradius = 12 * sc
|
|
308
|
+
gem_shadows[i].yradius = 4 * sc
|
|
309
|
+
end
|
|
310
|
+
next if gem_collected[i]
|
|
311
|
+
|
|
312
|
+
if (gem_data[i][0] - player_world_x).abs < 28 && (gem_data[i][1] - player_world_y - 20).abs < 34
|
|
313
|
+
gem_collected[i] = true
|
|
314
|
+
parts.each { |s, _, _| s.visible = false }
|
|
315
|
+
gem_shadows[i].visible = false
|
|
316
|
+
collected += 1
|
|
317
|
+
label.content = "× #{collected}"
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Player drop shadow onto the surface below, shrinking and fading with height.
|
|
322
|
+
feet = player_world_y + player.height
|
|
323
|
+
surf = surface_below.call(player_world_x + player.width / 2.0, feet - 2)
|
|
324
|
+
scale = (1.0 - (surf - feet) / 260.0).clamp(0.25, 1.0)
|
|
325
|
+
player_shadow.x = player_world_x + player.width / 2.0 - camera_x
|
|
326
|
+
player_shadow.y = surf
|
|
327
|
+
player_shadow.xradius = 16 * scale
|
|
328
|
+
player_shadow.yradius = 5 * scale
|
|
329
|
+
player_shadow.opacity = 0.24 * scale
|
|
330
|
+
|
|
331
|
+
player.x = player_world_x - camera_x
|
|
332
|
+
player.y = player_world_y
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
show
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Ray casting maze
|
|
2
|
+
# A small pseudo-3D maze rendered from a 2D grid by ray casting.
|
|
3
|
+
#
|
|
4
|
+
# Use W/S to move and A/D to turn. The top-left mini map shows the player
|
|
5
|
+
# and viewing direction. Walls are found with DDA grid traversal: each ray
|
|
6
|
+
# hops from grid line to grid line (the only places a wall can begin)
|
|
7
|
+
# instead of marching in tiny steps, so a frame's ray casting stays cheap —
|
|
8
|
+
# around ten steps per ray. Everything on screen is a persistent shape
|
|
9
|
+
# created once and mutated in place each frame, which is far cheaper than
|
|
10
|
+
# redrawing from scratch — especially on the web build.
|
|
11
|
+
|
|
12
|
+
require 'ruby2d'
|
|
13
|
+
|
|
14
|
+
# === Tunables ===
|
|
15
|
+
|
|
16
|
+
WIDTH = 800 # window width in pixels
|
|
17
|
+
HEIGHT = 500 # window height in pixels
|
|
18
|
+
FOV = Math::PI / 3 # horizontal field of view (radians)
|
|
19
|
+
RAYS = 160 # number of rays cast across the view (column count)
|
|
20
|
+
MAX_DIST = 12.0 # maximum ray distance in grid units before giving up
|
|
21
|
+
TURN_RATE = 3.3 # turn speed in rad/sec
|
|
22
|
+
MOVE_SPEED = 3.6 # forward/back speed in grid units/sec
|
|
23
|
+
MAP_SCALE = 16 # mini-map pixels per grid cell
|
|
24
|
+
|
|
25
|
+
# === Window ===
|
|
26
|
+
|
|
27
|
+
set title: 'Ruby 2D ▸ Examples ▸ Ray casting maze', width: WIDTH, height: HEIGHT, background: '#0f172a'
|
|
28
|
+
set close_on_esc: true
|
|
29
|
+
|
|
30
|
+
# === Map ===
|
|
31
|
+
|
|
32
|
+
MAP = [
|
|
33
|
+
'##########',
|
|
34
|
+
'#........#',
|
|
35
|
+
'#..##....#',
|
|
36
|
+
'#.....#..#',
|
|
37
|
+
'#.##.....#',
|
|
38
|
+
'#....##..#',
|
|
39
|
+
'#........#',
|
|
40
|
+
'##########'
|
|
41
|
+
].map(&:chars)
|
|
42
|
+
|
|
43
|
+
# Wall lookup as booleans — the ray march tests cells thousands of times per
|
|
44
|
+
# frame, so precompute instead of comparing map characters in the hot loop.
|
|
45
|
+
SOLID = MAP.map { |row| row.map { |cell| cell == '#' } }
|
|
46
|
+
|
|
47
|
+
# === State ===
|
|
48
|
+
|
|
49
|
+
# Start tucked in the top-left corner facing diagonally into the maze, so the
|
|
50
|
+
# open space ahead reads as somewhere to go rather than a wall in your face.
|
|
51
|
+
px = 1.5
|
|
52
|
+
py = 1.5
|
|
53
|
+
angle = Math::PI / 4
|
|
54
|
+
keys = {}
|
|
55
|
+
|
|
56
|
+
wall_at = lambda do |x, y|
|
|
57
|
+
return true if x < 0 || y < 0 || y >= SOLID.length || x >= SOLID[0].length
|
|
58
|
+
|
|
59
|
+
SOLID[y][x]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# === Persistent shapes ===
|
|
63
|
+
# Created once in back-to-front order (equal z draws in creation order):
|
|
64
|
+
# sky and floor, then the wall columns over them, then the mini map on top.
|
|
65
|
+
|
|
66
|
+
Rectangle.new(x: 0, y: 0, width: WIDTH, height: HEIGHT / 2, color: '#1e293b')
|
|
67
|
+
Rectangle.new(x: 0, y: HEIGHT / 2, width: WIDTH, height: HEIGHT / 2, color: '#111827')
|
|
68
|
+
|
|
69
|
+
# One column per ray. The x position and width never change; each frame the
|
|
70
|
+
# update block reshapes y/height and dims the color by distance in place.
|
|
71
|
+
col_w = WIDTH / RAYS.to_f + 1
|
|
72
|
+
columns = Array.new(RAYS) do |i|
|
|
73
|
+
Rectangle.new(x: i * WIDTH / RAYS.to_f, y: HEIGHT / 2, width: col_w, height: 0,
|
|
74
|
+
color: [0.25, 0.55, 0.95, 1])
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The mini map never changes; only the player marker on it moves.
|
|
78
|
+
MAP.each_with_index do |row, y|
|
|
79
|
+
row.each_with_index do |cell, x|
|
|
80
|
+
Rectangle.new(x: 14 + x * MAP_SCALE, y: 14 + y * MAP_SCALE,
|
|
81
|
+
width: MAP_SCALE - 1, height: MAP_SCALE - 1,
|
|
82
|
+
color: cell == '#' ? '#e5e7eb' : '#334155')
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
player_dot = Circle.new(x: 0, y: 0, radius: 4, color: '#f97316')
|
|
87
|
+
player_dir = Line.new(x1: 0, y1: 0, x2: 0, y2: 0, stroke_width: 2, color: '#f97316')
|
|
88
|
+
|
|
89
|
+
# === Input ===
|
|
90
|
+
|
|
91
|
+
on :key_down do |event|
|
|
92
|
+
keys[event.key] = true
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
on :key_up do |event|
|
|
96
|
+
keys[event.key] = false
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# === Per-frame update ===
|
|
100
|
+
|
|
101
|
+
update do |dt|
|
|
102
|
+
angle -= TURN_RATE * dt if keys['a'] || keys['left']
|
|
103
|
+
angle += TURN_RATE * dt if keys['d'] || keys['right']
|
|
104
|
+
|
|
105
|
+
move = 0
|
|
106
|
+
move += MOVE_SPEED * dt if keys['w'] || keys['up']
|
|
107
|
+
move -= MOVE_SPEED * dt if keys['s'] || keys['down']
|
|
108
|
+
nx = px + Math.cos(angle) * move
|
|
109
|
+
ny = py + Math.sin(angle) * move
|
|
110
|
+
unless wall_at.call(nx.floor, py.floor)
|
|
111
|
+
px = nx
|
|
112
|
+
end
|
|
113
|
+
unless wall_at.call(px.floor, ny.floor)
|
|
114
|
+
py = ny
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Cast one ray per wall column and reshape the column to the hit
|
|
118
|
+
RAYS.times do |i|
|
|
119
|
+
ray_angle = angle - FOV / 2 + FOV * i / (RAYS - 1)
|
|
120
|
+
dx = Math.cos(ray_angle)
|
|
121
|
+
dy = Math.sin(ray_angle)
|
|
122
|
+
|
|
123
|
+
# DDA setup: `delta_x` is the distance along the ray between two vertical
|
|
124
|
+
# grid lines (`delta_y` between horizontals), and `side_x`/`side_y` are the
|
|
125
|
+
# ray distances from the player to the first of each. An axis-parallel ray
|
|
126
|
+
# never crosses one set of lines — a huge delta keeps it out of the race.
|
|
127
|
+
map_x = px.floor
|
|
128
|
+
map_y = py.floor
|
|
129
|
+
delta_x = dx.abs < 1e-12 ? 1e30 : 1.0 / dx.abs
|
|
130
|
+
delta_y = dy.abs < 1e-12 ? 1e30 : 1.0 / dy.abs
|
|
131
|
+
step_x = dx < 0 ? -1 : 1
|
|
132
|
+
step_y = dy < 0 ? -1 : 1
|
|
133
|
+
side_x = dx < 0 ? (px - map_x) * delta_x : (map_x + 1 - px) * delta_x
|
|
134
|
+
side_y = dy < 0 ? (py - map_y) * delta_y : (map_y + 1 - py) * delta_y
|
|
135
|
+
|
|
136
|
+
# Walk the grid: always advance to the nearer of the two upcoming grid
|
|
137
|
+
# lines, entering one new cell per step, until that cell is a wall. The
|
|
138
|
+
# hit distance is exact, unlike a fixed-step march.
|
|
139
|
+
dist = 0.0
|
|
140
|
+
until wall_at.call(map_x, map_y) || dist > MAX_DIST
|
|
141
|
+
if side_x < side_y
|
|
142
|
+
dist = side_x
|
|
143
|
+
side_x += delta_x
|
|
144
|
+
map_x += step_x
|
|
145
|
+
else
|
|
146
|
+
dist = side_y
|
|
147
|
+
side_y += delta_y
|
|
148
|
+
map_y += step_y
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
corrected = dist * Math.cos(ray_angle - angle)
|
|
153
|
+
wall_h = (HEIGHT * 0.85 / corrected).clamp(12, HEIGHT)
|
|
154
|
+
shade = (1.0 - corrected / MAX_DIST).clamp(0.12, 1.0)
|
|
155
|
+
|
|
156
|
+
# Mutate in place — no new shapes or colors per frame
|
|
157
|
+
column = columns[i]
|
|
158
|
+
column.y = HEIGHT / 2 - wall_h / 2
|
|
159
|
+
column.height = wall_h
|
|
160
|
+
color = column.color
|
|
161
|
+
color.r = 0.25 * shade
|
|
162
|
+
color.g = 0.55 * shade
|
|
163
|
+
color.b = 0.95 * shade
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Move the player marker on the mini map
|
|
167
|
+
player_dot.x = 14 + px * MAP_SCALE
|
|
168
|
+
player_dot.y = 14 + py * MAP_SCALE
|
|
169
|
+
player_dir.x1 = player_dot.x
|
|
170
|
+
player_dir.y1 = player_dot.y
|
|
171
|
+
player_dir.x2 = 14 + (px + Math.cos(angle) * 0.8) * MAP_SCALE
|
|
172
|
+
player_dir.y2 = 14 + (py + Math.sin(angle) * 0.8) * MAP_SCALE
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
show
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# 2D shadow casting
|
|
2
|
+
# A top-down flashlight paints a lit region behind sharp obstacle shadows.
|
|
3
|
+
#
|
|
4
|
+
# Light rays from the cursor are stopped by the rectangles, painting a
|
|
5
|
+
# brightly lit region surrounded by hard shadows. Move the mouse to sweep
|
|
6
|
+
# the light around. Press R to regenerate the scene.
|
|
7
|
+
|
|
8
|
+
require 'ruby2d'
|
|
9
|
+
|
|
10
|
+
# === Tunables ===
|
|
11
|
+
|
|
12
|
+
WIDTH = 800 # window width in pixels
|
|
13
|
+
HEIGHT = 600 # window height in pixels
|
|
14
|
+
NUM_OBSTACLES = 7 # rectangles scattered across the scene
|
|
15
|
+
OBS_MIN = 36 # smallest obstacle side, in pixels
|
|
16
|
+
OBS_MAX = 130 # largest obstacle side, in pixels
|
|
17
|
+
FALLOFF = 480 # distance over which the light fades to dark
|
|
18
|
+
ANGLE_EPS = 0.0003 # offset for the corner-peek rays (radians)
|
|
19
|
+
LIGHT_RGB = [1.0, 0.86, 0.45].freeze # warm flashlight tint
|
|
20
|
+
|
|
21
|
+
# === Window ===
|
|
22
|
+
|
|
23
|
+
set title: 'Ruby 2D ▸ Examples ▸ 2D shadow casting',
|
|
24
|
+
width: WIDTH, height: HEIGHT, background: '#08080d'
|
|
25
|
+
set close_on_esc: true
|
|
26
|
+
set render_mode: :on_demand
|
|
27
|
+
|
|
28
|
+
# === Helpers ===
|
|
29
|
+
|
|
30
|
+
# Ray (rx, ry) + t * (dx, dy) intersected with segment (s1)→(s2).
|
|
31
|
+
# Returns the ray parameter t (>= 0) of the closest hit, or nil. Since
|
|
32
|
+
# (dx, dy) is a unit vector, t is the hit distance in pixels.
|
|
33
|
+
def ray_segment_t(rx, ry, dx, dy, sx1, sy1, sx2, sy2)
|
|
34
|
+
ex = sx2 - sx1
|
|
35
|
+
ey = sy2 - sy1
|
|
36
|
+
denom = dx * ey - dy * ex
|
|
37
|
+
return nil if denom.abs < 1e-9
|
|
38
|
+
|
|
39
|
+
inv = 1.0 / denom
|
|
40
|
+
t = ((sx1 - rx) * ey - (sy1 - ry) * ex) * inv
|
|
41
|
+
u = ((sx1 - rx) * dy - (sy1 - ry) * dx) * inv
|
|
42
|
+
return nil if t < 0 || u < 0 || u > 1
|
|
43
|
+
|
|
44
|
+
t
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# === State ===
|
|
48
|
+
|
|
49
|
+
obstacles = []
|
|
50
|
+
segments = []
|
|
51
|
+
corners = []
|
|
52
|
+
light_x = WIDTH / 2.0
|
|
53
|
+
light_y = HEIGHT / 2.0
|
|
54
|
+
|
|
55
|
+
# === Reset ===
|
|
56
|
+
|
|
57
|
+
reset = lambda do
|
|
58
|
+
obstacles.clear
|
|
59
|
+
segments.clear
|
|
60
|
+
corners.clear
|
|
61
|
+
|
|
62
|
+
# The window border so every ray terminates somewhere.
|
|
63
|
+
segments.push([0, 0, WIDTH, 0],
|
|
64
|
+
[WIDTH, 0, WIDTH, HEIGHT],
|
|
65
|
+
[WIDTH, HEIGHT, 0, HEIGHT],
|
|
66
|
+
[0, HEIGHT, 0, 0])
|
|
67
|
+
corners.push([0, 0], [WIDTH, 0], [WIDTH, HEIGHT], [0, HEIGHT])
|
|
68
|
+
|
|
69
|
+
NUM_OBSTACLES.times do
|
|
70
|
+
w = OBS_MIN + rand(OBS_MAX - OBS_MIN)
|
|
71
|
+
h = OBS_MIN + rand(OBS_MAX - OBS_MIN)
|
|
72
|
+
x = 24 + rand(WIDTH - w - 48)
|
|
73
|
+
y = 24 + rand(HEIGHT - h - 48)
|
|
74
|
+
obstacles << [x, y, w, h]
|
|
75
|
+
segments.push([x, y, x + w, y ],
|
|
76
|
+
[x + w, y, x + w, y + h],
|
|
77
|
+
[x + w, y + h, x, y + h],
|
|
78
|
+
[x, y + h, x, y ])
|
|
79
|
+
corners.push([x, y], [x + w, y], [x + w, y + h], [x, y + h])
|
|
80
|
+
end
|
|
81
|
+
request_render
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
reset.call
|
|
85
|
+
|
|
86
|
+
# === Input ===
|
|
87
|
+
|
|
88
|
+
on :mouse_move do |event|
|
|
89
|
+
light_x = event.x
|
|
90
|
+
light_y = event.y
|
|
91
|
+
request_render
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
on key_down: :r do
|
|
95
|
+
reset.call
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# === Render ===
|
|
99
|
+
|
|
100
|
+
render do
|
|
101
|
+
# For every corner in the scene, cast three rays — one straight at
|
|
102
|
+
# the corner and one tiny offset on each side — so the second pair
|
|
103
|
+
# slips past and lands on whatever wall is hiding behind it. The
|
|
104
|
+
# difference between the two is exactly the shadow boundary.
|
|
105
|
+
hits = []
|
|
106
|
+
corners.each do |cx, cy|
|
|
107
|
+
base = Math.atan2(cy - light_y, cx - light_x)
|
|
108
|
+
[-ANGLE_EPS, 0.0, ANGLE_EPS].each do |off|
|
|
109
|
+
ang = base + off
|
|
110
|
+
dx = Math.cos(ang)
|
|
111
|
+
dy = Math.sin(ang)
|
|
112
|
+
best_t = nil
|
|
113
|
+
segments.each do |sx1, sy1, sx2, sy2|
|
|
114
|
+
t = ray_segment_t(light_x, light_y, dx, dy, sx1, sy1, sx2, sy2)
|
|
115
|
+
next if t.nil?
|
|
116
|
+
|
|
117
|
+
best_t = t if best_t.nil? || t < best_t
|
|
118
|
+
end
|
|
119
|
+
next if best_t.nil?
|
|
120
|
+
|
|
121
|
+
hits << [light_x + dx * best_t, light_y + dy * best_t, ang, best_t]
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
hits.sort_by! { |h| h[2] }
|
|
125
|
+
|
|
126
|
+
# Triangle fan from the light to each consecutive pair of hits. The
|
|
127
|
+
# per-vertex alpha (opaque at the source, transparent at FALLOFF)
|
|
128
|
+
# gives the radial falloff so far walls fade into shadow.
|
|
129
|
+
inner = [LIGHT_RGB[0], LIGHT_RGB[1], LIGHT_RGB[2], 0.92]
|
|
130
|
+
hits.each_with_index do |(hx, hy, _, t1), i|
|
|
131
|
+
nx, ny, _, t2 = hits[(i + 1) % hits.length]
|
|
132
|
+
a1 = (1.0 - t1 / FALLOFF).clamp(0.0, 0.92)
|
|
133
|
+
a2 = (1.0 - t2 / FALLOFF).clamp(0.0, 0.92)
|
|
134
|
+
Triangle.render(
|
|
135
|
+
x1: light_x, y1: light_y,
|
|
136
|
+
x2: hx, y2: hy,
|
|
137
|
+
x3: nx, y3: ny,
|
|
138
|
+
color: [inner,
|
|
139
|
+
[LIGHT_RGB[0], LIGHT_RGB[1], LIGHT_RGB[2], a1],
|
|
140
|
+
[LIGHT_RGB[0], LIGHT_RGB[1], LIGHT_RGB[2], a2]]
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
obstacles.each do |x, y, w, h|
|
|
145
|
+
Rectangle.render(x: x, y: y, width: w, height: h, color: '#1f2937')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
Circle.render(x: light_x, y: light_y, radius: 5, color: '#fef9c3')
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
show
|