diff --git a/BINDINGS.md b/BINDINGS.md index 6f96103c7..df53bb0ed 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -71,7 +71,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | | [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib | | [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** | -| [racket-raylib](https://github.com/eutro/racket-raylib) | 4.0 | [Racket](https://racket-lang.org) | MIT/Apache-2.0 | +| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 | | [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT | | [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT | | [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.5** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 | diff --git a/build.zig b/build.zig index d7d118003..b3da65984 100644 --- a/build.zig +++ b/build.zig @@ -192,7 +192,6 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. setDesktopPlatform(raylib, options.platform); }, .linux => { - if (options.platform == .drm) { if (options.opengl_version == .auto) { raylib.linkSystemLibrary("GLESv2"); @@ -209,34 +208,32 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. } else if (target.result.abi == .android) { //these are the only tag options per https://developer.android.com/ndk/guides/other_build_systems - const hostTuple = switch(builtin.target.os.tag) { - .linux => "linux-x86_64", + const hostTuple = switch (builtin.target.os.tag) { + .linux => "linux-x86_64", .windows => "windows-x86_64", - .macos => "darwin-x86_64", - else => { - @panic("unsupported host OS"); - } + .macos => "darwin-x86_64", + else => @panic("unsupported host OS"), }; const androidTriple = try target.result.linuxTriple(b.allocator); const androidNdkPathString: []const u8 = options.android_ndk; - if(androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set"); + if (androidNdkPathString.len < 1) @panic("no ndk path provided and ANDROID_NDK_HOME is not set"); const androidApiLevel: []const u8 = options.android_api_version; - const androidSysroot = try std.fs.path.join(b.allocator, &.{androidNdkPathString, "/toolchains/llvm/prebuilt/", hostTuple, "/sysroot"}); - const androidLibPath = try std.fs.path.join(b.allocator, &.{androidSysroot, "/usr/lib/", androidTriple}); - const androidApiSpecificPath = try std.fs.path.join(b.allocator, &.{androidLibPath, androidApiLevel}); - const androidIncludePath = try std.fs.path.join(b.allocator, &.{androidSysroot, "/usr/include"}); - const androidArchIncludePath = try std.fs.path.join(b.allocator, &.{androidIncludePath, androidTriple}); - const androidAsmPath = try std.fs.path.join(b.allocator, &.{androidIncludePath, "/asm-generic"}); - const androidGluePath = try std.fs.path.join(b.allocator, &.{androidNdkPathString, "/sources/android/native_app_glue/"}); + const androidSysroot = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/toolchains/llvm/prebuilt/", hostTuple, "/sysroot" }); + const androidLibPath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/lib/", androidTriple }); + const androidApiSpecificPath = try std.fs.path.join(b.allocator, &.{ androidLibPath, androidApiLevel }); + const androidIncludePath = try std.fs.path.join(b.allocator, &.{ androidSysroot, "/usr/include" }); + const androidArchIncludePath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, androidTriple }); + const androidAsmPath = try std.fs.path.join(b.allocator, &.{ androidIncludePath, "/asm-generic" }); + const androidGluePath = try std.fs.path.join(b.allocator, &.{ androidNdkPathString, "/sources/android/native_app_glue/" }); - raylib.addLibraryPath(.{ .cwd_relative = androidLibPath}); + raylib.addLibraryPath(.{ .cwd_relative = androidLibPath }); raylib.root_module.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath }); raylib.addSystemIncludePath(.{ .cwd_relative = androidIncludePath }); - raylib.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath}); - raylib.addSystemIncludePath( .{ .cwd_relative = androidAsmPath}); - raylib.addSystemIncludePath(.{ .cwd_relative = androidGluePath}); + raylib.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath }); + raylib.addSystemIncludePath(.{ .cwd_relative = androidAsmPath }); + raylib.addSystemIncludePath(.{ .cwd_relative = androidGluePath }); var libcData = std.ArrayList(u8).init(b.allocator); const writer = libcData.writer(); @@ -442,7 +439,7 @@ pub const PlatformBackend = enum { rgfw, sdl, drm, - android + android, }; pub fn build(b: *std.Build) !void { diff --git a/examples/Makefile b/examples/Makefile index 64442ad9e..548e869c2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -653,6 +653,7 @@ AUDIO = \ audio/audio_raw_stream \ audio/audio_sound_loading \ audio/audio_sound_multi \ + audio/audio_sound_positioning \ audio/audio_stream_effects OTHERS = \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 6b4fde75c..04fbe927a 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -535,6 +535,7 @@ AUDIO = \ audio/audio_raw_stream \ audio/audio_sound_loading \ audio/audio_sound_multi \ + audio/audio_sound_positioning \ audio/audio_stream_effects OTHERS = \ diff --git a/examples/README.md b/examples/README.md index a59bcd25e..9982c2001 100644 --- a/examples/README.md +++ b/examples/README.md @@ -216,6 +216,7 @@ Examples using raylib audio functionality, including sound/music loading and pla | 146 | [audio_mixed_processor](audio/audio_mixed_processor.c) | audio_mixed_processor | ⭐️⭐️⭐️⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) | | 147 | [audio_stream_effects](audio/audio_stream_effects.c) | audio_stream_effects | ⭐️⭐️⭐️⭐️ | 4.2 | 5.0 | [Ray](https://github.com/raysan5) | | 148 | [audio_sound_multi](audio/audio_sound_multi.c) | audio_sound_multi | ⭐️⭐️☆☆ | 4.6 | 4.6 | [Jeffery Myers](https://github.com/JeffM2501) | +| 149 | [audio_sound_positioning](audio/audio_sound_positioning.c) | audio_sound_positioning | ⭐️⭐️☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) | ### category: others @@ -223,11 +224,11 @@ Examples showing raylib misc functionality that does not fit in other categories | ## | example | image | difficulty
level | version
created | last version
updated | original
developer | |----|----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------| -| 149 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | 4.0 | [Ray](https://github.com/raysan5) | -| 150 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) | -| 151 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | -| 152 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) | -| 153 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | -| 154 | [raymath_vector_angle](others/raymath_vector_angle.c) | raymath_vector_angle | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) | +| 150 | [rlgl_standalone](others/rlgl_standalone.c) | rlgl_standalone | ⭐️⭐️⭐️⭐️ | 1.6 | 4.0 | [Ray](https://github.com/raysan5) | +| 151 | [rlgl_compute_shader](others/rlgl_compute_shader.c) | rlgl_compute_shader | ⭐️⭐️⭐️⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) | +| 152 | [easings_testbed](others/easings_testbed.c) | easings_testbed | ⭐️⭐️⭐️☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) | +| 153 | [raylib_opengl_interop](others/raylib_opengl_interop.c) | raylib_opengl_interop | ⭐️⭐️⭐️⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) | +| 154 | [embedded_files_loading](others/embedded_files_loading.c) | embedded_files_loading | ⭐️⭐️☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) | +| 155 | [raymath_vector_angle](others/raymath_vector_angle.c) | raymath_vector_angle | ⭐️⭐️☆☆ | 1.0 | 4.6 | [Ray](https://github.com/raysan5) | As always contributions are welcome, feel free to send new examples! Here is an [examples template](examples_template.c) to start with! diff --git a/examples/audio/audio_sound_positioning.c b/examples/audio/audio_sound_positioning.c new file mode 100644 index 000000000..4c78b66e3 --- /dev/null +++ b/examples/audio/audio_sound_positioning.c @@ -0,0 +1,115 @@ +/******************************************************************************************* +* +* raylib [audio] example - Playing spatialized 3D sound +* +* Example complexity rating: [★★☆☆] 2/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.5 +* +* Example contributed by Le Juez Victor (@Bigfoot71) and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2025 Le Juez Victor (@Bigfoot71) +* +********************************************************************************************/ + +#include +#include + +//------------------------------------------------------------------------------------ +// Sound positioning function +//------------------------------------------------------------------------------------ +static void SetSoundPosition(Camera listener, Sound sound, Vector3 position, float maxDist) +{ + // Calculate direction vector and distance between listener and sound source + Vector3 direction = Vector3Subtract(position, listener.position); + float distance = Vector3Length(direction); + + // Apply logarithmic distance attenuation and clamp between 0-1 + float attenuation = 1.0f / (1.0f + (distance / maxDist)); + attenuation = Clamp(attenuation, 0.0f, 1.0f); + + // Calculate normalized vectors for spatial positioning + Vector3 normalizedDirection = Vector3Normalize(direction); + Vector3 forward = Vector3Normalize(Vector3Subtract(listener.target, listener.position)); + Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, listener.up)); + + // Reduce volume for sounds behind the listener + float dotProduct = Vector3DotProduct(forward, normalizedDirection); + if (dotProduct < 0.0f) { + attenuation *= (1.0f + dotProduct * 0.5f); + } + + // Set stereo panning based on sound position relative to listener + float pan = 0.5f + 0.5f * Vector3DotProduct(normalizedDirection, right); + + // Apply final sound properties + SetSoundVolume(sound, attenuation); + SetSoundPan(sound, pan); +} + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(800, 600, "Quick Spatial Sound"); + InitAudioDevice(); + + SetTargetFPS(60); + DisableCursor(); + + Sound sound = LoadSound("resources/coin.wav"); + + Camera camera = { + .position = (Vector3) { 0, 5, 5 }, + .target = (Vector3) { 0, 0, 0 }, + .up = (Vector3) { 0, 1, 0 }, + .fovy = 60, + }; + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera, CAMERA_FREE); + + float th = GetTime(); + + Vector3 spherePos = { + .x = 5.0f * cosf(th), + .y = 0.0f, + .z = 5.0f * sinf(th) + }; + + SetSoundPosition(camera, sound, spherePos, 20.0f); + if (!IsSoundPlaying(sound)) PlaySound(sound); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + { + ClearBackground(BLACK); + + BeginMode3D(camera); + DrawGrid(10, 2); + DrawSphere(spherePos, 0.5f, RED); + EndMode3D(); + } + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadSound(sound); + CloseAudioDevice(); + CloseWindow(); +} diff --git a/examples/audio/audio_sound_positioning.png b/examples/audio/audio_sound_positioning.png new file mode 100644 index 000000000..3e7a8ffdd Binary files /dev/null and b/examples/audio/audio_sound_positioning.png differ diff --git a/src/rcore.c b/src/rcore.c index 65c37a23c..ea971b52f 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -1879,7 +1879,10 @@ void TakeScreenshot(const char *fileName) // Security check to (partially) avoid malicious code if (strchr(fileName, '\'') != NULL) { TRACELOG(LOG_WARNING, "SYSTEM: Provided fileName could be potentially malicious, avoid [\'] character"); return; } - Vector2 scale = GetWindowScaleDPI(); + // apply a scale if we are doing HIGHDPI auto-scaling + Vector2 scale = { 1,1 }; + if (IsWindowState(FLAG_WINDOW_HIGHDPI)) scale = GetWindowScaleDPI(); + unsigned char *imgData = rlReadScreenPixels((int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y)); Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };