Init zig project with raylib bindings
@ -0,0 +1,16 @@
|
||||
Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
|
||||
|
||||
This software is provided "as-is", without any express or implied warranty. In no event
|
||||
will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
wrote the original software. If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
@ -0,0 +1,790 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const emsdk = struct {
|
||||
const zemscripten = @import("zemscripten");
|
||||
|
||||
pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath {
|
||||
return raylib_dep.path("src/shell.html");
|
||||
}
|
||||
|
||||
pub const FlagsOptions = struct {
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
asyncify: bool = true,
|
||||
};
|
||||
|
||||
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: FlagsOptions) zemscripten.EmccFlags {
|
||||
var emcc_flags = zemscripten.emccDefaultFlags(allocator, .{
|
||||
.optimize = options.optimize,
|
||||
.fsanitize = true,
|
||||
});
|
||||
|
||||
if (options.asyncify)
|
||||
emcc_flags.put("-sASYNCIFY", {}) catch unreachable;
|
||||
|
||||
return emcc_flags;
|
||||
}
|
||||
|
||||
pub const SettingsOptions = struct {
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
es3: bool = false,
|
||||
glfw3: bool = true,
|
||||
memory_growth: bool = false,
|
||||
total_memory: u32 = 134217728,
|
||||
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc,
|
||||
};
|
||||
|
||||
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: SettingsOptions) zemscripten.EmccSettings {
|
||||
var emcc_settings = zemscripten.emccDefaultSettings(allocator, .{
|
||||
.optimize = options.optimize,
|
||||
.emsdk_allocator = options.emsdk_allocator,
|
||||
});
|
||||
|
||||
if (options.es3) {
|
||||
emcc_settings.put("FULL_ES3", "1") catch unreachable;
|
||||
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable;
|
||||
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable;
|
||||
}
|
||||
if (options.glfw3) {
|
||||
emcc_settings.put("USE_GLFW", "3") catch unreachable;
|
||||
}
|
||||
|
||||
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable;
|
||||
|
||||
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable;
|
||||
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable;
|
||||
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable;
|
||||
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
|
||||
|
||||
if (options.memory_growth)
|
||||
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
|
||||
|
||||
return emcc_settings;
|
||||
}
|
||||
|
||||
pub fn emccStep(b: *std.Build, raylib: *std.Build.Step.Compile, wasm: *std.Build.Step.Compile, options: zemscripten.StepOptions) *std.Build.Step {
|
||||
const activate_emsdk_step = zemscripten.activateEmsdkStep(b);
|
||||
|
||||
const emsdk_dep = b.dependency("emsdk", .{});
|
||||
raylib.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
|
||||
wasm.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
|
||||
|
||||
const emcc_step = zemscripten.emccStep(b, wasm, options);
|
||||
emcc_step.dependOn(activate_emsdk_step);
|
||||
|
||||
return emcc_step;
|
||||
}
|
||||
|
||||
pub fn emrunStep(
|
||||
b: *std.Build,
|
||||
html_path: []const u8,
|
||||
extra_args: []const []const u8,
|
||||
) *std.Build.Step {
|
||||
return zemscripten.emrunStep(b, html_path, extra_args);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool) void {
|
||||
if (opengl) mod.linkSystemLibrary("opengl32", .{});
|
||||
mod.linkSystemLibrary("winmm", .{});
|
||||
mod.linkSystemLibrary("gdi32", .{});
|
||||
if (shcore) mod.linkSystemLibrary("shcore", .{});
|
||||
}
|
||||
|
||||
fn findWaylandScanner(b: *std.Build) void {
|
||||
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
|
||||
std.log.err(
|
||||
\\ `wayland-scanner` may not be installed on the system.
|
||||
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
|
||||
, .{});
|
||||
@panic("`wayland-scanner` not found");
|
||||
};
|
||||
}
|
||||
|
||||
pub fn linkLinux(mod: *std.Build.Module, comptime display_backend: LinuxDisplayBackend) void {
|
||||
if (display_backend == .None) {
|
||||
mod.linkSystemLibrary("GL", .{});
|
||||
}
|
||||
|
||||
if (display_backend == .X11) {
|
||||
mod.linkSystemLibrary("X11", .{});
|
||||
mod.linkSystemLibrary("Xrandr", .{});
|
||||
mod.linkSystemLibrary("Xinerama", .{});
|
||||
mod.linkSystemLibrary("Xi", .{});
|
||||
mod.linkSystemLibrary("Xcursor", .{});
|
||||
}
|
||||
|
||||
if (display_backend == .Wayland) {
|
||||
mod.linkSystemLibrary("wayland-client", .{});
|
||||
mod.linkSystemLibrary("wayland-cursor", .{});
|
||||
mod.linkSystemLibrary("wayland-egl", .{});
|
||||
mod.linkSystemLibrary("xkbcommon", .{});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
|
||||
mod.linkSystemLibrary("GL", .{});
|
||||
}
|
||||
|
||||
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void {
|
||||
// Include xcode_frameworks for cross compilation
|
||||
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
|
||||
mod.addSystemFrameworkPath(dep.path("Frameworks"));
|
||||
mod.addSystemIncludePath(dep.path("include"));
|
||||
mod.addLibraryPath(dep.path("lib"));
|
||||
}
|
||||
|
||||
mod.linkFramework("Foundation", .{});
|
||||
mod.linkFramework("CoreServices", .{});
|
||||
mod.linkFramework("CoreGraphics", .{});
|
||||
mod.linkFramework("AppKit", .{});
|
||||
mod.linkFramework("IOKit", .{});
|
||||
}
|
||||
|
||||
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
|
||||
const raylib_mod = b.createModule(.{
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
.link_libc = true,
|
||||
});
|
||||
|
||||
const raylib = b.addLibrary(.{
|
||||
.name = "raylib",
|
||||
.linkage = options.linkage,
|
||||
.root_module = raylib_mod,
|
||||
});
|
||||
|
||||
raylib_mod.addCMacro("_GNU_SOURCE", "");
|
||||
raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L");
|
||||
|
||||
var arena: std.heap.ArenaAllocator = .init(b.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
var raylib_flags_arr: std.array_list.Managed([]const u8) = .init(arena.allocator());
|
||||
var c_source_files: std.array_list.Managed([]const u8) = .init(arena.allocator());
|
||||
|
||||
try c_source_files.append("src/rcore.c");
|
||||
|
||||
if (target.result.os.tag == .emscripten) {
|
||||
try raylib_flags_arr.append("-std=gnu99");
|
||||
} else {
|
||||
try raylib_flags_arr.append("-std=c99");
|
||||
}
|
||||
|
||||
if (options.linkage == .dynamic) {
|
||||
raylib_mod.pic = true;
|
||||
raylib_mod.addCMacro("BUILD_LIBTYPE_SHARED", "");
|
||||
}
|
||||
|
||||
if (options.config.len > 0) {
|
||||
// Splits a space-separated list of config flags into multiple flags
|
||||
//
|
||||
// Note: This means certain flags like `-x c++` won't be processed properly.
|
||||
// `-xc++` or similar should be used when possible
|
||||
var config_iter = std.mem.tokenizeScalar(u8, options.config, ' ');
|
||||
|
||||
// Apply config flags supplied by the user
|
||||
while (config_iter.next()) |config_flag| {
|
||||
try raylib_flags_arr.append(config_flag);
|
||||
}
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("SUPPORT_MODULE_RSHAPES", &.{@as(u8, @intFromBool(options.rshapes)) + 0x30});
|
||||
if (options.rshapes) {
|
||||
try c_source_files.append("src/rshapes.c");
|
||||
}
|
||||
raylib_mod.addCMacro("SUPPORT_MODULE_RTEXTURES", &.{@as(u8, @intFromBool(options.rtextures)) + 0x30});
|
||||
if (options.rtextures) {
|
||||
try c_source_files.append("src/rtextures.c");
|
||||
}
|
||||
raylib_mod.addCMacro("SUPPORT_MODULE_RTEXT", &.{@as(u8, @intFromBool(options.rtext)) + 0x30});
|
||||
if (options.rtext) {
|
||||
try c_source_files.append("src/rtext.c");
|
||||
}
|
||||
raylib_mod.addCMacro("SUPPORT_MODULE_RMODELS", &.{@as(u8, @intFromBool(options.rmodels)) + 0x30});
|
||||
if (options.rmodels) {
|
||||
try c_source_files.append("src/rmodels.c");
|
||||
}
|
||||
raylib_mod.addCMacro("SUPPORT_MODULE_RAUDIO", &.{@as(u8, @intFromBool(options.raudio)) + 0x30});
|
||||
if (options.raudio) {
|
||||
try c_source_files.append("src/raudio.c");
|
||||
}
|
||||
|
||||
raylib_mod.addIncludePath(b.path("src/platforms"));
|
||||
switch (options.platform) {
|
||||
.glfw => {
|
||||
var opengl_version: OpenglVersion = options.opengl_version;
|
||||
if (opengl_version == .gl_soft) {
|
||||
@panic("The opengl version is not supported by this platform");
|
||||
}
|
||||
|
||||
raylib_mod.addIncludePath(b.path("src/external/glfw/include"));
|
||||
|
||||
if (target.result.os.tag != .emscripten) {
|
||||
if (opengl_version == .auto) {
|
||||
opengl_version = OpenglVersion.gl_3_3;
|
||||
}
|
||||
raylib_mod.addCMacro("PLATFORM_DESKTOP_GLFW", "");
|
||||
try c_source_files.append("src/rglfw.c");
|
||||
}
|
||||
|
||||
switch (target.result.os.tag) {
|
||||
.windows => linkWindows(raylib_mod, true, false),
|
||||
.linux => {
|
||||
if (target.result.abi.isAndroid()) {
|
||||
@panic("Target is not supported with this platform");
|
||||
}
|
||||
|
||||
linkLinux(raylib_mod, .None);
|
||||
|
||||
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
||||
raylib_mod.addCMacro("_GLFW_X11", "");
|
||||
linkLinux(raylib_mod, .X11);
|
||||
}
|
||||
|
||||
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
|
||||
findWaylandScanner(b);
|
||||
|
||||
raylib_mod.addCMacro("_GLFW_WAYLAND", "");
|
||||
linkLinux(raylib_mod, .Wayland);
|
||||
try waylandGenerate(b, raylib, "src/external/glfw/deps/wayland/", false);
|
||||
}
|
||||
},
|
||||
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
|
||||
.macos => {
|
||||
// On macos rglfw.c include Objective-C files.
|
||||
_ = c_source_files.pop();
|
||||
try raylib_flags_arr.append("-ObjC");
|
||||
raylib_mod.addCSourceFile(.{
|
||||
.file = b.path("src/rglfw.c"),
|
||||
.flags = raylib_flags_arr.items,
|
||||
});
|
||||
_ = raylib_flags_arr.pop();
|
||||
|
||||
linkMacOS(b, raylib_mod);
|
||||
},
|
||||
.emscripten => {
|
||||
switch (opengl_version) {
|
||||
.auto => opengl_version = OpenglVersion.gles_2,
|
||||
.gles_2, .gles_3, .gl_soft => {},
|
||||
else => @panic("opengl version not supported"),
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_WEB", "");
|
||||
|
||||
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
|
||||
raylib.step.dependOn(activate_emsdk_step);
|
||||
},
|
||||
else => @panic("Target is not supported with this platform"),
|
||||
}
|
||||
raylib_mod.addCMacro(opengl_version.toCMacroStr(), "");
|
||||
},
|
||||
.rgfw => {
|
||||
var opengl_version: OpenglVersion = options.opengl_version;
|
||||
|
||||
if (target.result.os.tag != .emscripten) {
|
||||
if (opengl_version == .auto) {
|
||||
opengl_version = OpenglVersion.gl_3_3;
|
||||
}
|
||||
raylib_mod.addCMacro("PLATFORM_DESKTOP_RGFW", "");
|
||||
}
|
||||
|
||||
switch (target.result.os.tag) {
|
||||
.windows => linkWindows(raylib_mod, true, false),
|
||||
.linux => {
|
||||
if (target.result.abi.isAndroid()) {
|
||||
@panic("Target is not supported with this platform");
|
||||
}
|
||||
|
||||
linkLinux(raylib_mod, .None);
|
||||
|
||||
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
||||
raylib_mod.addCMacro("RGFW_X11", "");
|
||||
raylib_mod.addCMacro("RGFW_UNIX", "");
|
||||
|
||||
linkLinux(raylib_mod, .X11);
|
||||
}
|
||||
|
||||
if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) {
|
||||
findWaylandScanner(b);
|
||||
|
||||
if (options.linux_display_backend != .Both) {
|
||||
raylib_mod.addCMacro("RGFW_NO_X11", "");
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("RGFW_WAYLAND", "");
|
||||
raylib_mod.addCMacro("EGLAPIENTRY", "");
|
||||
|
||||
linkLinux(raylib_mod, .Wayland);
|
||||
|
||||
try waylandGenerate(b, raylib, "src/external/RGFW/deps/wayland/", true);
|
||||
}
|
||||
},
|
||||
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
|
||||
.macos => linkMacOS(b, raylib_mod),
|
||||
.emscripten => {
|
||||
switch (opengl_version) {
|
||||
.auto => opengl_version = OpenglVersion.gles_2,
|
||||
.gles_2, .gles_3, .gl_soft => {},
|
||||
else => @panic("opengl version not supported"),
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
|
||||
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
|
||||
raylib.step.dependOn(activate_emsdk_step);
|
||||
},
|
||||
else => @panic("Target is not supported with this platform"),
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro(opengl_version.toCMacroStr(), "");
|
||||
},
|
||||
.sdl, .sdl2, .sdl3 => {
|
||||
if (options.opengl_version == .auto) {
|
||||
raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), "");
|
||||
} else {
|
||||
raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), "");
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_DESKTOP_SDL", "");
|
||||
|
||||
if (options.platform == .sdl2) {
|
||||
raylib_mod.addCMacro("USING_SDL2_PACKAGE", "");
|
||||
}
|
||||
if (options.platform == .sdl3) {
|
||||
raylib_mod.addCMacro("USING_SDL3_PACKAGE", "");
|
||||
}
|
||||
},
|
||||
.memory => {
|
||||
if (options.opengl_version != .auto and options.opengl_version != .gl_soft) {
|
||||
@panic("The opengl version is not supported by this platform");
|
||||
}
|
||||
raylib_mod.addCMacro(OpenglVersion.gl_soft.toCMacroStr(), "");
|
||||
raylib_mod.addCMacro("PLATFORM_MEMORY", "");
|
||||
},
|
||||
.win32 => {
|
||||
if (target.result.os.tag != .windows) {
|
||||
@panic("Target is not supported with this platform");
|
||||
}
|
||||
|
||||
if (options.opengl_version == .auto) {
|
||||
raylib_mod.addCMacro(OpenglVersion.gl_3_3.toCMacroStr(), "");
|
||||
} else {
|
||||
raylib_mod.addCMacro(options.opengl_version.toCMacroStr(), "");
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_DESKTOP_WIN32", "");
|
||||
|
||||
linkWindows(raylib_mod, options.opengl_version != .gl_soft, true);
|
||||
},
|
||||
.drm => {
|
||||
if (target.result.os.tag != .linux) {
|
||||
@panic("Target is not supported with this platform");
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_DRM", "");
|
||||
raylib_mod.addCMacro("EGL_NO_X11", "");
|
||||
raylib_mod.addCMacro("DEFAULT_BATCH_BUFFER_ELEMENT", "");
|
||||
|
||||
try raylib_flags_arr.append("-Werror=implicit-function-declaration");
|
||||
|
||||
raylib_mod.linkSystemLibrary("libdrm", .{ .use_pkg_config = .force });
|
||||
raylib_mod.linkSystemLibrary("drm", .{});
|
||||
raylib_mod.linkSystemLibrary("gbm", .{});
|
||||
|
||||
switch (options.opengl_version) {
|
||||
.auto, .gles_2 => {
|
||||
raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), "");
|
||||
raylib_mod.linkSystemLibrary("GLESv2", .{});
|
||||
raylib_mod.linkSystemLibrary("EGL", .{});
|
||||
},
|
||||
.gl_soft => {},
|
||||
else => @panic("The opengl version is not supported by this platform"),
|
||||
}
|
||||
},
|
||||
.android => {
|
||||
if (!target.result.abi.isAndroid()) {
|
||||
@panic("Target is not supported with this platform");
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_ANDROID", "");
|
||||
|
||||
raylib_mod.linkSystemLibrary("EGL", .{});
|
||||
switch (options.opengl_version) {
|
||||
.auto, .gles_2 => {
|
||||
raylib_mod.addCMacro(OpenglVersion.gles_2.toCMacroStr(), "");
|
||||
raylib_mod.linkSystemLibrary("GLESv2", .{});
|
||||
},
|
||||
else => @panic("The opengl version is not supported by this platform"),
|
||||
}
|
||||
|
||||
//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",
|
||||
.windows => "windows-x86_64",
|
||||
.macos => "darwin-x86_64",
|
||||
else => @panic("unsupported host OS"),
|
||||
};
|
||||
|
||||
const androidTriple = switch (target.result.cpu.arch) {
|
||||
.x86 => "i686-linux-android",
|
||||
.x86_64 => "x86_64-linux-android",
|
||||
.arm => "arm-linux-androideabi",
|
||||
.aarch64 => "aarch64-linux-android",
|
||||
.riscv64 => "riscv64-linux-android",
|
||||
else => error.InvalidAndroidTarget,
|
||||
} catch @panic("invalid android target!");
|
||||
const androidNdkPathString: []const u8 = options.android_ndk;
|
||||
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/" });
|
||||
|
||||
raylib_mod.addLibraryPath(.{ .cwd_relative = androidLibPath });
|
||||
raylib_mod.addLibraryPath(.{ .cwd_relative = androidApiSpecificPath });
|
||||
raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidIncludePath });
|
||||
raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidArchIncludePath });
|
||||
raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidAsmPath });
|
||||
raylib_mod.addSystemIncludePath(.{ .cwd_relative = androidGluePath });
|
||||
|
||||
const libc_data = try std.fmt.allocPrint(b.allocator,
|
||||
\\include_dir={0s}/sysroot/usr/include
|
||||
\\sys_include_dir={0s}/sysroot/usr/include/aarch64-linux-android
|
||||
\\crt_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24
|
||||
\\static_lib_dir={0s}/sysroot/usr/lib/aarch64-linux-android/24
|
||||
\\msvc_lib_dir=
|
||||
\\kernel32_lib_dir=
|
||||
\\gcc_dir=
|
||||
\\
|
||||
, .{androidNdkPathString});
|
||||
const write_step = b.addWriteFiles();
|
||||
const libcFile = write_step.add("android-libc.txt", libc_data);
|
||||
raylib.setLibCFile(libcFile);
|
||||
},
|
||||
}
|
||||
|
||||
raylib_mod.addCSourceFiles(.{
|
||||
.files = c_source_files.items,
|
||||
.flags = raylib_flags_arr.items,
|
||||
});
|
||||
|
||||
return raylib;
|
||||
}
|
||||
|
||||
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void {
|
||||
if (b.lazyDependency("raygui", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
})) |raygui_dep| {
|
||||
var gen_step = b.addWriteFiles();
|
||||
raylib.step.dependOn(&gen_step.step);
|
||||
|
||||
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
|
||||
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
|
||||
raylib.root_module.addIncludePath(raygui_dep.path("src"));
|
||||
raylib.root_module.addIncludePath(b.path("src"));
|
||||
|
||||
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
|
||||
|
||||
const c = b.addTranslateC(.{
|
||||
.root_source_file = raygui_dep.path("src/raygui.h"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
c.addIncludePath(b.path("src"));
|
||||
const c_mod = c.createModule();
|
||||
c_mod.linkLibrary(raylib);
|
||||
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
|
||||
}
|
||||
}
|
||||
|
||||
pub const Options = struct {
|
||||
raudio: bool = true,
|
||||
rmodels: bool = true,
|
||||
rshapes: bool = true,
|
||||
rtext: bool = true,
|
||||
rtextures: bool = true,
|
||||
raygui: bool = false,
|
||||
platform: PlatformBackend = .glfw,
|
||||
linkage: std.builtin.LinkMode = .static,
|
||||
linux_display_backend: LinuxDisplayBackend = .X11,
|
||||
opengl_version: OpenglVersion = .auto,
|
||||
android_ndk: []const u8 = "",
|
||||
android_api_version: []const u8 = "35",
|
||||
/// config should be a list of space-separated cflags, eg, "-DSUPPORT_CUSTOM_FRAME_CONTROL"
|
||||
config: []const u8 = &.{},
|
||||
|
||||
const defaults = Options{};
|
||||
|
||||
pub fn getOptions(b: *std.Build) Options {
|
||||
return .{
|
||||
.platform = b.option(PlatformBackend, "platform", "Choose the platform backend for desktop target") orelse defaults.platform,
|
||||
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
|
||||
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
|
||||
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
|
||||
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
|
||||
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
|
||||
.raygui = b.option(bool, "raygui", "Include raygui") orelse defaults.raygui,
|
||||
.linkage = b.option(std.builtin.LinkMode, "linkage", "Compile as shared or static library") orelse defaults.linkage,
|
||||
.linux_display_backend = b.option(LinuxDisplayBackend, "linux_display_backend", "Linux display backend to use") orelse defaults.linux_display_backend,
|
||||
.opengl_version = b.option(OpenglVersion, "opengl_version", "OpenGL version to use") orelse defaults.opengl_version,
|
||||
.config = b.option([]const u8, "config", "Compile with custom define macros overriding config.h") orelse &.{},
|
||||
.android_ndk = b.option([]const u8, "android_ndk", "specify path to android ndk") orelse b.graph.environ_map.get("ANDROID_NDK_HOME") orelse "",
|
||||
.android_api_version = b.option([]const u8, "android_api_version", "specify target android API level") orelse defaults.android_api_version,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const OpenglVersion = enum {
|
||||
auto,
|
||||
gl_soft,
|
||||
gl_1_1,
|
||||
gl_2_1,
|
||||
gl_3_3,
|
||||
gl_4_3,
|
||||
gles_2,
|
||||
gles_3,
|
||||
|
||||
pub fn toCMacroStr(self: @This()) []const u8 {
|
||||
switch (self) {
|
||||
.auto => @panic("OpenglVersion.auto cannot be turned into a C macro string"),
|
||||
.gl_soft => return "GRAPHICS_API_OPENGL_SOFTWARE",
|
||||
.gl_1_1 => return "GRAPHICS_API_OPENGL_11",
|
||||
.gl_2_1 => return "GRAPHICS_API_OPENGL_21",
|
||||
.gl_3_3 => return "GRAPHICS_API_OPENGL_33",
|
||||
.gl_4_3 => return "GRAPHICS_API_OPENGL_43",
|
||||
.gles_2 => return "GRAPHICS_API_OPENGL_ES2",
|
||||
.gles_3 => return "GRAPHICS_API_OPENGL_ES3",
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const LinuxDisplayBackend = enum {
|
||||
None,
|
||||
X11,
|
||||
Wayland,
|
||||
Both,
|
||||
};
|
||||
|
||||
pub const PlatformBackend = enum {
|
||||
glfw,
|
||||
rgfw,
|
||||
sdl,
|
||||
sdl2,
|
||||
sdl3,
|
||||
memory,
|
||||
win32,
|
||||
drm,
|
||||
android,
|
||||
};
|
||||
|
||||
fn translateCMod(
|
||||
comptime header: []const u8,
|
||||
b: *std.Build,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
raylib: *std.Build.Step.Compile,
|
||||
) void {
|
||||
const c = b.addTranslateC(.{
|
||||
.root_source_file = b.path("src/" ++ header ++ ".h"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
const c_mod = c.createModule();
|
||||
c_mod.linkLibrary(raylib);
|
||||
b.modules.put(b.graph.arena, header, c_mod) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const options: Options = .getOptions(b);
|
||||
|
||||
const lib = try compileRaylib(b, target, optimize, options);
|
||||
|
||||
lib.installHeader(b.path("src/raylib.h"), "raylib.h");
|
||||
lib.installHeader(b.path("src/rcamera.h"), "rcamera.h");
|
||||
lib.installHeader(b.path("src/raymath.h"), "raymath.h");
|
||||
lib.installHeader(b.path("src/rlgl.h"), "rlgl.h");
|
||||
|
||||
b.installArtifact(lib);
|
||||
|
||||
translateCMod("raylib", b, target, optimize, lib);
|
||||
translateCMod("rcamera", b, target, optimize, lib);
|
||||
translateCMod("raymath", b, target, optimize, lib);
|
||||
translateCMod("rlgl", b, target, optimize, lib);
|
||||
|
||||
if (options.raygui) {
|
||||
addRaygui(b, target, optimize, lib);
|
||||
}
|
||||
|
||||
const examples = b.step("examples", "build/install all examples");
|
||||
examples.dependOn(try addExamples("core", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("audio", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("models", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("shaders", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("shapes", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("text", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("textures", b, target, optimize, lib, options.platform));
|
||||
examples.dependOn(try addExamples("others", b, target, optimize, lib, options.platform));
|
||||
}
|
||||
|
||||
fn addExamples(
|
||||
comptime module: []const u8,
|
||||
b: *std.Build,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
raylib: *std.Build.Step.Compile,
|
||||
platform: PlatformBackend,
|
||||
) !*std.Build.Step {
|
||||
const all = b.step(module, "All " ++ module ++ " examples");
|
||||
const module_subpath = b.pathJoin(&.{ "examples", module });
|
||||
|
||||
var dir = try b.build_root.handle.openDir(b.graph.io, module_subpath, .{ .iterate = true });
|
||||
defer dir.close(b.graph.io);
|
||||
|
||||
var iter = dir.iterate();
|
||||
while (try iter.next(b.graph.io)) |entry| {
|
||||
if (entry.kind != .file) continue;
|
||||
|
||||
const filetype = std.fs.path.extension(entry.name);
|
||||
if (!std.mem.eql(u8, filetype, ".c")) continue;
|
||||
|
||||
const filename = std.fs.path.stem(entry.name);
|
||||
const path = b.pathJoin(&.{ module_subpath, entry.name });
|
||||
|
||||
const exe_mod = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
exe_mod.addCSourceFile(.{ .file = b.path(path) });
|
||||
exe_mod.linkLibrary(raylib);
|
||||
|
||||
if (platform == .sdl) {
|
||||
exe_mod.linkSystemLibrary("SDL2", .{});
|
||||
exe_mod.linkSystemLibrary("SDL3", .{});
|
||||
}
|
||||
if (platform == .sdl2) {
|
||||
exe_mod.linkSystemLibrary("SDL2", .{});
|
||||
}
|
||||
if (platform == .sdl3) {
|
||||
exe_mod.linkSystemLibrary("SDL3", .{});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, filename, "rlgl_standalone")) {
|
||||
if (platform != .glfw) continue;
|
||||
exe_mod.addIncludePath(b.path("src"));
|
||||
exe_mod.addIncludePath(b.path("src/external/glfw/include"));
|
||||
}
|
||||
if (std.mem.eql(u8, filename, "raylib_opengl_interop")) {
|
||||
if (platform == .drm) continue;
|
||||
if (target.result.os.tag == .macos) continue;
|
||||
exe_mod.addIncludePath(b.path("src/external"));
|
||||
}
|
||||
|
||||
const run_step = b.step(filename, filename);
|
||||
|
||||
// web exports are completely separate
|
||||
if (target.query.os_tag == .emscripten) {
|
||||
exe_mod.addCMacro("PLATFORM_WEB", "");
|
||||
|
||||
const wasm = b.addLibrary(.{
|
||||
.name = filename,
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
|
||||
const install_dir: std.Build.InstallDir = .{ .custom = b.fmt("web/{s}/{s}", .{ module, filename }) };
|
||||
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
|
||||
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
|
||||
|
||||
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{
|
||||
.optimize = optimize,
|
||||
.flags = emcc_flags,
|
||||
.settings = emcc_settings,
|
||||
.shell_file_path = b.path("src/shell.html"),
|
||||
.install_dir = install_dir,
|
||||
});
|
||||
b.getInstallStep().dependOn(emcc_step);
|
||||
|
||||
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
|
||||
const emrun_step = emsdk.emrunStep(
|
||||
b,
|
||||
b.getInstallPath(install_dir, html_filename),
|
||||
&.{},
|
||||
);
|
||||
|
||||
emrun_step.dependOn(emcc_step);
|
||||
run_step.dependOn(emrun_step);
|
||||
all.dependOn(emcc_step);
|
||||
} else {
|
||||
exe_mod.addCMacro("PLATFORM_DESKTOP", "");
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = filename,
|
||||
.root_module = exe_mod,
|
||||
.use_lld = target.result.os.tag == .windows,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) });
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.cwd = b.path(module_subpath);
|
||||
run_cmd.step.dependOn(&install_cmd.step);
|
||||
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
all.dependOn(&install_cmd.step);
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
fn waylandGenerate(
|
||||
b: *std.Build,
|
||||
raylib: *std.Build.Step.Compile,
|
||||
comptime waylandDir: []const u8,
|
||||
comptime source: bool,
|
||||
) !void {
|
||||
const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true });
|
||||
defer dir.close(b.graph.io);
|
||||
|
||||
var iter = dir.iterate();
|
||||
while (try iter.next(b.graph.io)) |entry| {
|
||||
if (entry.kind != .file) continue;
|
||||
const protocolDir = b.pathJoin(&.{ waylandDir, entry.name });
|
||||
|
||||
const filename = std.fs.path.stem(entry.name);
|
||||
|
||||
const clientHeader = b.fmt("{s}-client-protocol.h", .{filename});
|
||||
const client_step = b.addSystemCommand(&.{ "wayland-scanner", "client-header" });
|
||||
client_step.addFileArg(b.path(protocolDir));
|
||||
raylib.root_module.addIncludePath(client_step.addOutputFileArg(clientHeader).dirname());
|
||||
raylib.step.dependOn(&client_step.step);
|
||||
|
||||
if (comptime source) {
|
||||
const privateCode = b.fmt("{s}-client-protocol-code.c", .{filename});
|
||||
const private_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
|
||||
private_step.addFileArg(b.path(protocolDir));
|
||||
raylib.root_module.addCSourceFile(.{
|
||||
.file = private_step.addOutputFileArg(privateCode),
|
||||
.flags = &.{ "-std=c99", "-O2" },
|
||||
});
|
||||
raylib.step.dependOn(&private_step.step);
|
||||
} else {
|
||||
const privateCodeHeader = b.fmt("{s}-client-protocol-code.h", .{filename});
|
||||
const private_head_step = b.addSystemCommand(&.{ "wayland-scanner", "private-code" });
|
||||
private_head_step.addFileArg(b.path(protocolDir));
|
||||
raylib.root_module.addIncludePath(private_head_step.addOutputFileArg(privateCodeHeader).dirname());
|
||||
raylib.step.dependOn(&private_head_step.step);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
.{
|
||||
.name = .raylib,
|
||||
.version = "6.0.0",
|
||||
.minimum_zig_version = "0.16.0",
|
||||
|
||||
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
|
||||
|
||||
.dependencies = .{
|
||||
.xcode_frameworks = .{
|
||||
.url = "https://pkg.machengine.org/xcode-frameworks/8a1cfb373587ea4c9bb1468b7c986462d8d4e10e.tar.gz",
|
||||
.hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ",
|
||||
.lazy = true,
|
||||
},
|
||||
.raygui = .{
|
||||
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
|
||||
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
|
||||
.lazy = true,
|
||||
},
|
||||
.emsdk = .{
|
||||
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
|
||||
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
|
||||
},
|
||||
.zemscripten = .{
|
||||
.url = "git+https://github.com/zig-gamedev/zemscripten#3fa4b778852226c7346bdcc3c1486e875a9a6d02",
|
||||
.hash = "zemscripten-0.2.0-dev-sRlDqApRAACspTbAZnuNKWIzfWzSYgYkb2nWAXZ-tqqt",
|
||||
},
|
||||
},
|
||||
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
"src",
|
||||
"examples",
|
||||
"LICENSE",
|
||||
},
|
||||
}
|
||||
@ -0,0 +1,211 @@
|
||||
# Setup the project and settings
|
||||
project(examples)
|
||||
|
||||
# Directories that contain examples
|
||||
set(example_dirs
|
||||
audio
|
||||
core
|
||||
models
|
||||
others
|
||||
shaders
|
||||
shapes
|
||||
text
|
||||
textures
|
||||
)
|
||||
|
||||
# Next few lines will check for existence of symbols or header files
|
||||
# They are needed for the physac example and threads examples
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=199309L)
|
||||
include(CheckSymbolExists)
|
||||
check_symbol_exists(CLOCK_MONOTONIC time.h HAVE_CLOCK_MONOTONIC)
|
||||
check_symbol_exists(QueryPerformanceCounter windows.h HAVE_QPC)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS)
|
||||
|
||||
if (HAVE_QPC OR HAVE_CLOCK_MONOTONIC)
|
||||
set(example_dirs ${example_dirs} physac)
|
||||
endif ()
|
||||
|
||||
include(CheckIncludeFile)
|
||||
CHECK_INCLUDE_FILE("stdatomic.h" HAVE_STDATOMIC_H)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads)
|
||||
if (CMAKE_USE_PTHREADS_INIT AND HAVE_STDATOMIC_H)
|
||||
add_if_flag_compiles("-std=c11" CMAKE_C_FLAGS)
|
||||
if (THREADS_HAVE_PTHREAD_ARG)
|
||||
add_if_flag_compiles("-pthread" CMAKE_C_FLAGS)
|
||||
endif ()
|
||||
if (CMAKE_THREAD_LIBS_INIT)
|
||||
link_libraries("${CMAKE_THREAD_LIBS_INIT}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (APPLE AND NOT CMAKE_SYSTEM STRLESS "Darwin-18.0.0")
|
||||
add_definitions(-DGL_SILENCE_DEPRECATION)
|
||||
MESSAGE(AUTHOR_WARNING "OpenGL is deprecated starting with macOS 10.14 (Mojave)!")
|
||||
endif ()
|
||||
|
||||
# Collect all source files and resource files
|
||||
# into a CMake variable
|
||||
set(example_sources)
|
||||
set(example_resources)
|
||||
foreach (example_dir ${example_dirs})
|
||||
# Get the .c files
|
||||
file(GLOB sources ${example_dir}/*.c)
|
||||
list(APPEND example_sources ${sources})
|
||||
|
||||
# Any any resources
|
||||
file(GLOB resources ${example_dir}/resources/*)
|
||||
list(APPEND example_resources ${resources})
|
||||
endforeach ()
|
||||
|
||||
if(NOT CMAKE_USE_PTHREADS_INIT OR NOT HAVE_STDATOMIC_H)
|
||||
# Items requiring pthreads
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_loading_thread.c)
|
||||
endif ()
|
||||
|
||||
if (${PLATFORM} MATCHES "Android")
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/standard_lighting.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_3d_picking.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_vr_simulator.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_3d_camera_free.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_3d_camera_first_person.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_world_screen.c)
|
||||
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_mesh_picking.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_cubicmap.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_skybox.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_mesh_picking.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_mesh_generation.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_heightmap.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_billboard.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_rlgl_solar_system.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_rlgl_full_solar_system.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_solar_system.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_obj_viewer.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_animation.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_first_person_maze.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/models/models_magicavoxel_loading.c)
|
||||
|
||||
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_custom_uniform.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_model_shader.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_view_depth.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_postprocessing.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_raymarching.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_palette_switch.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_basic_lighting.c)
|
||||
|
||||
elseif (${PLATFORM} MATCHES "Web")
|
||||
set(example_sources) # clear example_sources
|
||||
list(APPEND example_sources others/web_basic_window.c)
|
||||
list(APPEND example_sources core/core_input_gestures_testbed.c)
|
||||
|
||||
elseif ("${PLATFORM}" STREQUAL "DRM")
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
||||
|
||||
elseif ("${PLATFORM}" MATCHES "Memory")
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
||||
|
||||
elseif ("${OPENGL_VERSION}" STREQUAL "Software")
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
|
||||
|
||||
elseif (NOT SUPPORT_GESTURES_SYSTEM)
|
||||
# Items requiring gestures system
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_mouse_painting.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_basic_screen_manager.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_input_gestures_web.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/core/core_input_gestures.c)
|
||||
|
||||
endif ()
|
||||
|
||||
# The rlgl_standalone example only targets desktop, without shared libraries.
|
||||
if (BUILD_SHARED_LIBS OR NOT ${PLATFORM} MATCHES "Desktop")
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
|
||||
endif()
|
||||
|
||||
# The audio examples fail to link if raylib is built without raudio
|
||||
if (NOT SUPPORT_MODULE_RAUDIO)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_mixed_processor.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_module_playing.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_music_stream.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_raw_stream.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_sound_loading.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_sound_multi.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio/audio_stream_effects.c)
|
||||
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/embedded_files_loading.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_sprite_button.c)
|
||||
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_sprite_explosion.c)
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE SYSTEM others/external/include)
|
||||
|
||||
if (NOT TARGET raylib)
|
||||
find_package(raylib 2.0 REQUIRED)
|
||||
endif ()
|
||||
|
||||
# Do each example
|
||||
foreach (example_source ${example_sources})
|
||||
# Create the basename for the example
|
||||
get_filename_component(example_name ${example_source} NAME)
|
||||
string(REPLACE ".c" "" example_name ${example_name})
|
||||
|
||||
# Setup the example
|
||||
add_executable(${example_name} ${example_source})
|
||||
|
||||
target_link_libraries(${example_name} raylib)
|
||||
if (NOT WIN32)
|
||||
target_link_libraries(${example_name} m)
|
||||
endif()
|
||||
|
||||
string(REGEX MATCH ".*/.*/" resources_dir ${example_source})
|
||||
string(APPEND resources_dir "resources")
|
||||
|
||||
if (${PLATFORM} MATCHES "Web")
|
||||
target_compile_options(${example_name} PRIVATE -Os)
|
||||
target_link_options(${example_name} PRIVATE
|
||||
-sALLOW_MEMORY_GROWTH=1
|
||||
-sEXPORTED_RUNTIME_METHODS=[requestFullscreen]
|
||||
-sUSE_GLFW=3
|
||||
--shell-file "${CMAKE_SOURCE_DIR}/src/shell.html"
|
||||
)
|
||||
set_target_properties(${example_name} PROPERTIES SUFFIX ".html")
|
||||
|
||||
if (EXISTS ${resources_dir})
|
||||
# The local resources path needs to be mapped to /resources virtual path
|
||||
string(APPEND resources_dir "@resources")
|
||||
set_target_properties(${example_name} PROPERTIES LINK_FLAGS "--preload-file ${resources_dir}")
|
||||
endif ()
|
||||
|
||||
if(${GRAPHICS} MATCHES "GRAPHICS_API_OPENGL_ES3")
|
||||
target_link_options(${example_name} PUBLIC "-sMIN_WEBGL_VERSION=2")
|
||||
target_link_options(${example_name} PUBLIC "-sMAX_WEBGL_VERSION=2")
|
||||
endif()
|
||||
|
||||
# Checks if OSX and links appropriate frameworks (Only required on MacOS)
|
||||
if (APPLE)
|
||||
target_link_libraries(${example_name} "-framework IOKit")
|
||||
target_link_libraries(${example_name} "-framework Cocoa")
|
||||
target_link_libraries(${example_name} "-framework OpenGL")
|
||||
endif()
|
||||
|
||||
elseif (${PLATFORM} MATCHES "RGFW")
|
||||
if (APPLE)
|
||||
target_link_libraries(${example_name} "-framework IOKit")
|
||||
target_link_libraries(${example_name} "-framework Cocoa")
|
||||
target_link_libraries(${example_name} "-framework OpenGL")
|
||||
elseif (WIN32)
|
||||
target_link_libraries(${example_name} "-lgdi32")
|
||||
target_link_libraries(${example_name} "-lwinmm")
|
||||
elseif (UNIX)
|
||||
target_link_libraries(${example_name} "-lX11")
|
||||
target_link_libraries(${example_name} "-lXrandr")
|
||||
endif()
|
||||
endif ()
|
||||
endforeach ()
|
||||
|
||||
# Copy all of the resource files to the destination
|
||||
file(COPY ${example_resources} DESTINATION "resources/")
|
||||
@ -0,0 +1,808 @@
|
||||
#**************************************************************************************************
|
||||
#
|
||||
# raylib makefile for multiple platforms
|
||||
#
|
||||
# This file supports building raylib examples for the following platforms:
|
||||
#
|
||||
# > PLATFORM_DESKTOP
|
||||
# - Defaults to PLATFORM_DESKTOP_GLFW
|
||||
# > PLATFORM_DESKTOP_GFLW (GLFW backend):
|
||||
# - Windows (Win32, Win64)
|
||||
# - Linux (X11/Wayland desktop mode)
|
||||
# - macOS/OSX (x64, arm64)
|
||||
# - FreeBSD, OpenBSD, NetBSD, DragonFly (X11 desktop)
|
||||
# > PLATFORM_DESKTOP_SDL (SDL backend):
|
||||
# - Windows (Win32, Win64)
|
||||
# - Linux (X11/Wayland desktop mode)
|
||||
# - Others (not tested)
|
||||
# > PLATFORM_DESKTOP_RGFW (RGFW backend):
|
||||
# - Windows (Win32, Win64)
|
||||
# - Linux (X11 desktop mode)
|
||||
# - macOS/OSX (x64, arm64 (not tested))
|
||||
# - Others (not tested)
|
||||
# > PLATFORM_WEB_RGFW:
|
||||
# - HTML5 (WebAssembly)
|
||||
# > PLATFORM_WEB:
|
||||
# - HTML5 (WebAssembly)
|
||||
# > PLATFORM_DRM:
|
||||
# - Raspberry Pi 0-5 (DRM/KMS)
|
||||
# - Linux DRM subsystem (KMS mode)
|
||||
# > PLATFORM_ANDROID:
|
||||
# - Android (ARM, ARM64)
|
||||
#
|
||||
# Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
|
||||
#
|
||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||
# will the authors be held liable for any damages arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
# applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
# wrote the original software. If you use this software in a product, an acknowledgment
|
||||
# in the product documentation would be appreciated but is not required.
|
||||
#
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
# as being the original software.
|
||||
#
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
#
|
||||
#**************************************************************************************************
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
# Define required environment variables
|
||||
#------------------------------------------------------------------------------------------------
|
||||
# Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB, PLATFORM_WEB_RGFW
|
||||
PLATFORM ?= PLATFORM_DESKTOP
|
||||
|
||||
ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW))
|
||||
TARGET_PLATFORM := $(PLATFORM)
|
||||
override PLATFORM = PLATFORM_DESKTOP
|
||||
else
|
||||
ifeq ($(PLATFORM), PLATFORM_DESKTOP)
|
||||
TARGET_PLATFORM = PLATFORM_DESKTOP_GLFW
|
||||
else
|
||||
TARGET_PLATFORM = $(PLATFORM)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Define required raylib variables
|
||||
PROJECT_NAME ?= raylib_examples
|
||||
RAYLIB_VERSION ?= 6.0.0
|
||||
RAYLIB_PATH ?= ..
|
||||
|
||||
# Define raylib source code path
|
||||
RAYLIB_SRC_PATH ?= ../src
|
||||
|
||||
# Locations of raylib.h and libraylib.a/libraylib.so
|
||||
# NOTE: Those variables are only used for PLATFORM_OS: LINUX, BSD
|
||||
DESTDIR ?= /usr/local
|
||||
RAYLIB_INCLUDE_PATH ?= $(DESTDIR)/include
|
||||
RAYLIB_LIB_PATH ?= $(DESTDIR)/lib
|
||||
|
||||
# Library type compilation: STATIC (.a) or SHARED (.so/.dll)
|
||||
RAYLIB_LIBTYPE ?= STATIC
|
||||
|
||||
# Build mode for project: DEBUG or RELEASE
|
||||
BUILD_MODE ?= RELEASE
|
||||
|
||||
# Use external GLFW library instead of rglfw module
|
||||
USE_EXTERNAL_GLFW ?= FALSE
|
||||
|
||||
# Enable support for X11 by default on Linux when using GLFW
|
||||
# NOTE: Wayland is disabled by default, only enable if you are sure
|
||||
GLFW_LINUX_ENABLE_WAYLAND ?= FALSE
|
||||
GLFW_LINUX_ENABLE_X11 ?= TRUE
|
||||
|
||||
# Enable support for X11 by default on Linux when using RGFW
|
||||
# NOTE: Wayland is disabled by default, only enable if you are sure
|
||||
RGFW_LINUX_ENABLE_WAYLAND ?= FALSE
|
||||
RGFW_LINUX_ENABLE_X11 ?= TRUE
|
||||
|
||||
# PLATFORM_DESKTOP_SDL: It requires SDL library to be provided externally
|
||||
# WARNING: Library is not included in raylib, it MUST be configured by users
|
||||
SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include
|
||||
SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib
|
||||
SDL_LIBRARIES ?= -lSDL2 -lSDL2main
|
||||
|
||||
# Use Wayland display server protocol on Linux desktop (by default it uses X11 windowing system)
|
||||
# NOTE: This variable is only used for PLATFORM_OS: LINUX
|
||||
USE_WAYLAND_DISPLAY ?= FALSE
|
||||
|
||||
# PLATFORM_WEB: Default properties
|
||||
BUILD_WEB_ASYNCIFY ?= TRUE
|
||||
BUILD_WEB_SHELL ?= $(RAYLIB_PATH)/src/minshell.html
|
||||
BUILD_WEB_HEAP_SIZE ?= 134217728
|
||||
BUILD_WEB_RESOURCES ?= TRUE
|
||||
BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources
|
||||
# Use WebGL2 backend (OpenGL 3.0)
|
||||
# WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3
|
||||
BUILD_WEB_WEBGL2 ?= FALSE
|
||||
|
||||
# Determine PLATFORM_OS when required
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# No uname.exe on MinGW!, but OS=Windows_NT on Windows!
|
||||
# ifeq ($(UNAME),Msys) -> Windows
|
||||
ifeq ($(OS),Windows_NT)
|
||||
PLATFORM_OS = WINDOWS
|
||||
else
|
||||
UNAMEOS = $(shell uname)
|
||||
ifeq ($(UNAMEOS),Linux)
|
||||
PLATFORM_OS = LINUX
|
||||
endif
|
||||
ifeq ($(UNAMEOS),FreeBSD)
|
||||
PLATFORM_OS = BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),OpenBSD)
|
||||
PLATFORM_OS = BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),NetBSD)
|
||||
PLATFORM_OS = BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),DragonFly)
|
||||
PLATFORM_OS = BSD
|
||||
endif
|
||||
ifeq ($(UNAMEOS),Darwin)
|
||||
PLATFORM_OS = OSX
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
UNAMEOS = $(shell uname)
|
||||
ifeq ($(UNAMEOS),Linux)
|
||||
PLATFORM_OS = LINUX
|
||||
endif
|
||||
endif
|
||||
|
||||
# Default path for raylib on Raspberry Pi
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
RAYLIB_PATH ?= /home/pi/raylib
|
||||
endif
|
||||
|
||||
# Define raylib release directory for compiled library
|
||||
RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src
|
||||
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
# Emscripten required variables
|
||||
EMSDK_PATH ?= C:/raylib/emsdk
|
||||
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
|
||||
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
|
||||
PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
|
||||
NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
|
||||
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Define default C compiler: CC
|
||||
#------------------------------------------------------------------------------------------------
|
||||
CC = gcc
|
||||
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
# OSX default compiler
|
||||
CC = clang
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
# FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
|
||||
CC = clang
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# HTML5 emscripten compiler
|
||||
# WARNING: To compile to HTML5, code must be redesigned
|
||||
# to use emscripten.h and emscripten_set_main_loop()
|
||||
CC = emcc
|
||||
endif
|
||||
|
||||
# Define default make program: MAKE
|
||||
#------------------------------------------------------------------------------------------------
|
||||
MAKE ?= make
|
||||
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
MAKE = mingw32-make
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
MAKE = mingw32-make
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
MAKE = mingw32-make
|
||||
else
|
||||
EMMAKE := $(shell command -v emmake)
|
||||
ifneq (, $(EMMAKE))
|
||||
MAKE = $(EMMAKE) make
|
||||
else
|
||||
MAKE = mingw32-make
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Define compiler flags: CFLAGS
|
||||
#------------------------------------------------------------------------------------------------
|
||||
# -O1 defines optimization level
|
||||
# -g include debug information on compilation
|
||||
# -s strip unnecessary data from build
|
||||
# -Wall turns on most, but not all, compiler warnings
|
||||
# -std=c99 defines C language mode (standard C from 1999 revision)
|
||||
# -std=gnu99 defines C language mode (GNU C from 1999 revision)
|
||||
# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
|
||||
# -Wno-unused-value ignore unused return values of some functions (i.e. fread())
|
||||
# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
|
||||
CFLAGS = -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wno-unused-result
|
||||
|
||||
ifeq ($(BUILD_MODE),DEBUG)
|
||||
CFLAGS += -g -D_DEBUG
|
||||
else
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
ifeq ($(BUILD_WEB_ASYNCIFY),TRUE)
|
||||
CFLAGS += -O3
|
||||
else
|
||||
CFLAGS += -Os
|
||||
endif
|
||||
else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
endif
|
||||
|
||||
# Additional flags for compiler (if desired)
|
||||
# -Wextra enables some extra warning flags that are not enabled by -Wall
|
||||
# -Wmissing-prototypes warn if a global function is defined without a previous prototype declaration
|
||||
# -Wstrict-prototypes warn if a function is declared or defined without specifying the argument types
|
||||
# -Werror=implicit-function-declaration catch function calls without prior declaration
|
||||
#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
ifeq ($(RAYLIB_LIBTYPE),STATIC)
|
||||
CFLAGS += -D_DEFAULT_SOURCE
|
||||
endif
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
# Explicitly enable runtime link to libraylib.so
|
||||
CFLAGS += -Wl,-rpath,$(RAYLIB_RELEASE_PATH)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
CFLAGS += -std=gnu99 -DEGL_NO_X11
|
||||
endif
|
||||
|
||||
# Define include paths for required headers: INCLUDE_PATHS
|
||||
# NOTE: Some external/extras libraries could be required (stb, easings...)
|
||||
#------------------------------------------------------------------------------------------------
|
||||
INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external $(EXTRA_INCLUDE_PATHS)
|
||||
|
||||
# Define additional directories containing required header files
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) -I/usr/pkg/include -I/usr/X11R7/include
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
|
||||
INCLUDE_PATHS += -I$(SDL_INCLUDE_PATH)
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH)
|
||||
INCLUDE_PATHS += -I/usr/include/libdrm
|
||||
endif
|
||||
|
||||
# Define library paths containing required libs: LDFLAGS
|
||||
#------------------------------------------------------------------------------------------------
|
||||
LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH)
|
||||
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
# NOTE: The resource .rc file contains windows executable icon and properties
|
||||
LDFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data
|
||||
# -Wl,--subsystem,windows hides the console window
|
||||
ifeq ($(BUILD_MODE), RELEASE)
|
||||
LDFLAGS += -Wl,--subsystem,windows
|
||||
endif
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
LDFLAGS += -L$(RAYLIB_LIB_PATH)
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
LDFLAGS += -Lsrc -L$(RAYLIB_LIB_PATH)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
# NOTE: The resource .rc file contains windows executable icon and properties
|
||||
LDFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data
|
||||
# -Wl,--subsystem,windows hides the console window
|
||||
ifeq ($(BUILD_MODE), RELEASE)
|
||||
LDFLAGS += -Wl,--subsystem,windows
|
||||
endif
|
||||
endif
|
||||
LDFLAGS += -L$(SDL_LIBRARY_PATH)
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# -Os # size optimization
|
||||
# -O2 # optimization level 2, if used, also set --memory-init-file 0
|
||||
# -sUSE_GLFW=3 # Use glfw3 library (context/input management)
|
||||
# -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
|
||||
# -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB)
|
||||
# -sUSE_PTHREADS=1 # multithreading support
|
||||
# -sWASM=0 # disable Web Assembly, emitted by default
|
||||
# -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
|
||||
# -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data
|
||||
# -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
|
||||
# -sMINIFY_HTML=0 # minify generated html from shell.html
|
||||
# --profiling # include information for code profiling
|
||||
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
||||
# --preload-file resources # specify a resources folder for data compilation
|
||||
# --source-map-base # allow debugging in browser with source map
|
||||
# --shell-file shell.html # define a custom shell .html and output extension
|
||||
LDFLAGS += -sTOTAL_MEMORY=$(BUILD_WEB_HEAP_SIZE) -sFORCE_FILESYSTEM=1 -sEXPORTED_RUNTIME_METHODS=ccall -sMINIFY_HTML=0
|
||||
|
||||
# Using GLFW3 library (instead of RGFW)
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_WEB)
|
||||
LDFLAGS += -sUSE_GLFW=3
|
||||
endif
|
||||
|
||||
# Build using asyncify
|
||||
ifeq ($(BUILD_WEB_ASYNCIFY),TRUE)
|
||||
LDFLAGS += -sASYNCIFY
|
||||
endif
|
||||
|
||||
# NOTE: Flags required for WebGL 2.0 (OpenGL ES 3.0)
|
||||
# WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3
|
||||
ifeq ($(BUILD_WEB_WEBGL2),TRUE)
|
||||
LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2
|
||||
endif
|
||||
|
||||
# Add resources building if required
|
||||
ifeq ($(BUILD_WEB_RESOURCES),TRUE)
|
||||
LDFLAGS += --preload-file $(BUILD_WEB_RESOURCES_PATH)
|
||||
endif
|
||||
|
||||
# Add debug mode flags if required
|
||||
ifeq ($(BUILD_MODE),DEBUG)
|
||||
LDFLAGS += -sASSERTIONS=1 --profiling
|
||||
endif
|
||||
|
||||
# Define a custom shell .html and output extension
|
||||
LDFLAGS += --shell-file $(BUILD_WEB_SHELL)
|
||||
EXT = .html
|
||||
|
||||
# NOTE: Simple raylib examples are compiled to be interpreter with asyncify, that way,
|
||||
# we can compile same code for ALL platforms with no change required, but, working on bigger
|
||||
# projects, code needs to be refactored to avoid a blocking while() loop, moving Update and Draw
|
||||
# logic to a self contained function: UpdateDrawFrame(), check core_basic_window_web.c for reference.
|
||||
|
||||
endif
|
||||
|
||||
# Define libraries required on linking: LDLIBS
|
||||
# NOTE: To link libraries (lib<name>.so or lib<name>.a), use -l<name>
|
||||
#------------------------------------------------------------------------------------------------
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
# Libraries for Windows desktop compilation
|
||||
# NOTE: WinMM library required to set high-res timer resolution
|
||||
LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
# Libraries for Debian GNU/Linux desktop compiling
|
||||
# NOTE: Required packages: libegl1-mesa-dev
|
||||
LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
|
||||
|
||||
# On Wayland, additional libraries requires
|
||||
ifeq ($(GLFW_LINUX_ENABLE_WAYLAND),TRUE)
|
||||
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
|
||||
endif
|
||||
|
||||
ifeq ($(GLFW_LINUX_ENABLE_X11),TRUE)
|
||||
# On X11, additional libraries required
|
||||
LDLIBS += -lX11
|
||||
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
|
||||
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
|
||||
endif
|
||||
# Explicit link to libc
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
LDLIBS += -lc
|
||||
endif
|
||||
|
||||
# NOTE: On ARM 32bit arch, miniaudio requires atomics library
|
||||
LDLIBS += -latomic
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
# Libraries for OSX 10.9 desktop compiling
|
||||
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
|
||||
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
|
||||
# NOTE: Required packages: mesa-libs
|
||||
LDFLAGS += -L/usr/X11R7/lib -Wl,-R/usr/X11R7/lib
|
||||
LDLIBS = -lraylib -lGL -lm -lpthread
|
||||
|
||||
# On XWindow requires also below libraries
|
||||
LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
|
||||
endif
|
||||
ifeq ($(USE_EXTERNAL_GLFW),TRUE)
|
||||
# NOTE: It could require additional packages installed: libglfw3-dev
|
||||
LDLIBS += -lglfw
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
# Libraries for Windows desktop compilation
|
||||
LDLIBS = -lraylib $(SDL_LIBRARIES) -lopengl32 -lgdi32
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
# Libraries for Debian GNU/Linux desktop compiling
|
||||
# NOTE: Required packages: libegl1-mesa-dev
|
||||
LDLIBS = -lraylib $(SDL_LIBRARIES) -lGL -lm -lpthread -ldl -lrt
|
||||
|
||||
# On X11, addition libraries required
|
||||
LDLIBS += -lX11
|
||||
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
|
||||
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
|
||||
|
||||
# On Wayland, additional libraries requires
|
||||
ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
|
||||
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
|
||||
endif
|
||||
|
||||
# Explicit link to libc
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
LDLIBS += -lc
|
||||
endif
|
||||
|
||||
# NOTE: On ARM 32bit arch, miniaudio requires atomics library
|
||||
LDLIBS += -latomic
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
# Libraries for Windows desktop compilation
|
||||
LDFLAGS += -L..\src
|
||||
LDLIBS = -lraylib -lgdi32 -lwinmm -lopengl32
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
# Libraries for Debian GNU/Linux desktop compipling
|
||||
# NOTE: Required packages: libegl1-mesa-dev
|
||||
LDFLAGS += -L../src
|
||||
LDLIBS = -lraylib -lm
|
||||
|
||||
ifeq ($(RGFW_LINUX_ENABLE_X11),TRUE)
|
||||
LDLIBS += -lGL -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lpthread -ldl -lrt
|
||||
endif
|
||||
|
||||
ifeq ($(RGFW_LINUX_ENABLE_WAYLAND),TRUE)
|
||||
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
|
||||
endif
|
||||
|
||||
# Explicit link to libc
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
LDLIBS += -lc
|
||||
endif
|
||||
|
||||
# NOTE: On ARM 32bit arch, miniaudio requires atomics library
|
||||
LDLIBS += -latomic
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
# Libraries for Debian GNU/Linux desktop compiling
|
||||
# NOTE: Required packages: libegl1-mesa-dev
|
||||
LDFLAGS += -L../src
|
||||
LDLIBS = -lraylib -lm
|
||||
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
# Libraries for DRM compiling
|
||||
# NOTE: Required packages: libasound2-dev (ALSA)
|
||||
LDLIBS = -lraylib -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl -latomic
|
||||
# TODO: Examples compilation does not define GRAPHICS, is it required?
|
||||
#ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_ES2)
|
||||
# LDLIBS += -lGLESv2 -lEGL
|
||||
#endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
|
||||
# Libraries for Windows desktop compilation
|
||||
LDFLAGS += -L..\src
|
||||
LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore
|
||||
ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_SOFTWARE)
|
||||
LDLIBS += -lopengl32
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# Libraries for web (HTML5) compiling
|
||||
LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.web.a
|
||||
endif
|
||||
|
||||
CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
# Define source code object files required
|
||||
#------------------------------------------------------------------------------------------------
|
||||
#EXAMPLES_LIST_START
|
||||
CORE = \
|
||||
core/core_2d_camera \
|
||||
core/core_2d_camera_mouse_zoom \
|
||||
core/core_2d_camera_platformer \
|
||||
core/core_2d_camera_split_screen \
|
||||
core/core_3d_camera_first_person \
|
||||
core/core_3d_camera_fps \
|
||||
core/core_3d_camera_free \
|
||||
core/core_3d_camera_mode \
|
||||
core/core_3d_camera_split_screen \
|
||||
core/core_3d_picking \
|
||||
core/core_automation_events \
|
||||
core/core_basic_screen_manager \
|
||||
core/core_basic_window \
|
||||
core/core_clipboard_text \
|
||||
core/core_compute_hash \
|
||||
core/core_custom_frame_control \
|
||||
core/core_custom_logging \
|
||||
core/core_delta_time \
|
||||
core/core_directory_files \
|
||||
core/core_drop_files \
|
||||
core/core_highdpi_demo \
|
||||
core/core_highdpi_testbed \
|
||||
core/core_input_actions \
|
||||
core/core_input_gamepad \
|
||||
core/core_input_gestures \
|
||||
core/core_input_gestures_testbed \
|
||||
core/core_input_keys \
|
||||
core/core_input_mouse \
|
||||
core/core_input_mouse_wheel \
|
||||
core/core_input_multitouch \
|
||||
core/core_input_virtual_controls \
|
||||
core/core_keyboard_testbed \
|
||||
core/core_monitor_detector \
|
||||
core/core_random_sequence \
|
||||
core/core_random_values \
|
||||
core/core_render_texture \
|
||||
core/core_scissor_test \
|
||||
core/core_screen_recording \
|
||||
core/core_smooth_pixelperfect \
|
||||
core/core_storage_values \
|
||||
core/core_text_file_loading \
|
||||
core/core_undo_redo \
|
||||
core/core_viewport_scaling \
|
||||
core/core_vr_simulator \
|
||||
core/core_window_flags \
|
||||
core/core_window_letterbox \
|
||||
core/core_window_should_close \
|
||||
core/core_window_web \
|
||||
core/core_world_screen
|
||||
|
||||
SHAPES = \
|
||||
shapes/shapes_ball_physics \
|
||||
shapes/shapes_basic_shapes \
|
||||
shapes/shapes_bouncing_ball \
|
||||
shapes/shapes_bullet_hell \
|
||||
shapes/shapes_circle_sector_drawing \
|
||||
shapes/shapes_clock_of_clocks \
|
||||
shapes/shapes_collision_area \
|
||||
shapes/shapes_colors_palette \
|
||||
shapes/shapes_dashed_line \
|
||||
shapes/shapes_digital_clock \
|
||||
shapes/shapes_double_pendulum \
|
||||
shapes/shapes_easings_ball \
|
||||
shapes/shapes_easings_box \
|
||||
shapes/shapes_easings_rectangles \
|
||||
shapes/shapes_easings_testbed \
|
||||
shapes/shapes_following_eyes \
|
||||
shapes/shapes_hilbert_curve \
|
||||
shapes/shapes_kaleidoscope \
|
||||
shapes/shapes_lines_bezier \
|
||||
shapes/shapes_lines_drawing \
|
||||
shapes/shapes_logo_raylib \
|
||||
shapes/shapes_logo_raylib_anim \
|
||||
shapes/shapes_math_angle_rotation \
|
||||
shapes/shapes_math_sine_cosine \
|
||||
shapes/shapes_mouse_trail \
|
||||
shapes/shapes_penrose_tile \
|
||||
shapes/shapes_pie_chart \
|
||||
shapes/shapes_rectangle_advanced \
|
||||
shapes/shapes_rectangle_scaling \
|
||||
shapes/shapes_recursive_tree \
|
||||
shapes/shapes_ring_drawing \
|
||||
shapes/shapes_rlgl_color_wheel \
|
||||
shapes/shapes_rlgl_triangle \
|
||||
shapes/shapes_rounded_rectangle_drawing \
|
||||
shapes/shapes_simple_particles \
|
||||
shapes/shapes_splines_drawing \
|
||||
shapes/shapes_starfield_effect \
|
||||
shapes/shapes_top_down_lights \
|
||||
shapes/shapes_triangle_strip \
|
||||
shapes/shapes_vector_angle
|
||||
|
||||
TEXTURES = \
|
||||
textures/textures_background_scrolling \
|
||||
textures/textures_blend_modes \
|
||||
textures/textures_bunnymark \
|
||||
textures/textures_cellular_automata \
|
||||
textures/textures_clipboard_image \
|
||||
textures/textures_fog_of_war \
|
||||
textures/textures_framebuffer_rendering \
|
||||
textures/textures_gif_player \
|
||||
textures/textures_image_channel \
|
||||
textures/textures_image_drawing \
|
||||
textures/textures_image_generation \
|
||||
textures/textures_image_kernel \
|
||||
textures/textures_image_loading \
|
||||
textures/textures_image_processing \
|
||||
textures/textures_image_rotate \
|
||||
textures/textures_image_text \
|
||||
textures/textures_logo_raylib \
|
||||
textures/textures_magnifying_glass \
|
||||
textures/textures_mouse_painting \
|
||||
textures/textures_npatch_drawing \
|
||||
textures/textures_particles_blending \
|
||||
textures/textures_polygon_drawing \
|
||||
textures/textures_raw_data \
|
||||
textures/textures_screen_buffer \
|
||||
textures/textures_sprite_animation \
|
||||
textures/textures_sprite_button \
|
||||
textures/textures_sprite_explosion \
|
||||
textures/textures_sprite_stacking \
|
||||
textures/textures_srcrec_dstrec \
|
||||
textures/textures_textured_curve \
|
||||
textures/textures_tiled_drawing \
|
||||
textures/textures_to_image
|
||||
|
||||
TEXT = \
|
||||
text/text_3d_drawing \
|
||||
text/text_codepoints_loading \
|
||||
text/text_font_filters \
|
||||
text/text_font_loading \
|
||||
text/text_font_sdf \
|
||||
text/text_font_spritefont \
|
||||
text/text_format_text \
|
||||
text/text_inline_styling \
|
||||
text/text_input_box \
|
||||
text/text_rectangle_bounds \
|
||||
text/text_sprite_fonts \
|
||||
text/text_strings_management \
|
||||
text/text_unicode_emojis \
|
||||
text/text_unicode_ranges \
|
||||
text/text_words_alignment \
|
||||
text/text_writing_anim
|
||||
|
||||
MODELS = \
|
||||
models/models_animation_blend_custom \
|
||||
models/models_animation_blending \
|
||||
models/models_animation_gpu_skinning \
|
||||
models/models_animation_timing \
|
||||
models/models_basic_voxel \
|
||||
models/models_billboard_rendering \
|
||||
models/models_bone_socket \
|
||||
models/models_box_collisions \
|
||||
models/models_cubicmap_rendering \
|
||||
models/models_decals \
|
||||
models/models_directional_billboard \
|
||||
models/models_first_person_maze \
|
||||
models/models_geometric_shapes \
|
||||
models/models_heightmap_rendering \
|
||||
models/models_loading \
|
||||
models/models_loading_gltf \
|
||||
models/models_loading_iqm \
|
||||
models/models_loading_m3d \
|
||||
models/models_loading_vox \
|
||||
models/models_mesh_generation \
|
||||
models/models_mesh_picking \
|
||||
models/models_orthographic_projection \
|
||||
models/models_point_rendering \
|
||||
models/models_rlgl_solar_system \
|
||||
models/models_rotating_cube \
|
||||
models/models_skybox_rendering \
|
||||
models/models_tesseract_view \
|
||||
models/models_textured_cube \
|
||||
models/models_waving_cubes \
|
||||
models/models_yaw_pitch_roll
|
||||
|
||||
SHADERS = \
|
||||
shaders/shaders_ascii_rendering \
|
||||
shaders/shaders_basic_lighting \
|
||||
shaders/shaders_basic_pbr \
|
||||
shaders/shaders_cel_shading \
|
||||
shaders/shaders_color_correction \
|
||||
shaders/shaders_custom_uniform \
|
||||
shaders/shaders_deferred_rendering \
|
||||
shaders/shaders_depth_rendering \
|
||||
shaders/shaders_depth_writing \
|
||||
shaders/shaders_eratosthenes_sieve \
|
||||
shaders/shaders_fog_rendering \
|
||||
shaders/shaders_game_of_life \
|
||||
shaders/shaders_hot_reloading \
|
||||
shaders/shaders_hybrid_rendering \
|
||||
shaders/shaders_julia_set \
|
||||
shaders/shaders_lightmap_rendering \
|
||||
shaders/shaders_mandelbrot_set \
|
||||
shaders/shaders_mesh_instancing \
|
||||
shaders/shaders_model_shader \
|
||||
shaders/shaders_multi_sample2d \
|
||||
shaders/shaders_normalmap_rendering \
|
||||
shaders/shaders_palette_switch \
|
||||
shaders/shaders_postprocessing \
|
||||
shaders/shaders_raymarching_rendering \
|
||||
shaders/shaders_rlgl_compute \
|
||||
shaders/shaders_rounded_rectangle \
|
||||
shaders/shaders_shadowmap_rendering \
|
||||
shaders/shaders_shapes_textures \
|
||||
shaders/shaders_simple_mask \
|
||||
shaders/shaders_spotlight_rendering \
|
||||
shaders/shaders_texture_outline \
|
||||
shaders/shaders_texture_rendering \
|
||||
shaders/shaders_texture_tiling \
|
||||
shaders/shaders_texture_waves \
|
||||
shaders/shaders_vertex_displacement
|
||||
|
||||
AUDIO = \
|
||||
audio/audio_mixed_processor \
|
||||
audio/audio_module_playing \
|
||||
audio/audio_music_stream \
|
||||
audio/audio_raw_stream \
|
||||
audio/audio_sound_loading \
|
||||
audio/audio_sound_multi \
|
||||
audio/audio_sound_positioning \
|
||||
audio/audio_spectrum_visualizer \
|
||||
audio/audio_stream_callback \
|
||||
audio/audio_stream_effects
|
||||
#EXAMPLES_LIST_END
|
||||
|
||||
# Define processes to execute
|
||||
#------------------------------------------------------------------------------------------------
|
||||
# Default target entry
|
||||
all: $(CORE) $(SHAPES) $(TEXT) $(TEXTURES) $(MODELS) $(SHADERS) $(AUDIO)
|
||||
|
||||
core: $(CORE)
|
||||
shapes: $(SHAPES)
|
||||
textures: $(TEXTURES)
|
||||
text: $(TEXT)
|
||||
models: $(MODELS)
|
||||
shaders: $(SHADERS)
|
||||
audio: $(AUDIO)
|
||||
|
||||
# Generic compilation pattern
|
||||
# NOTE: Examples must be ready for Android compilation!
|
||||
%: %.c
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
|
||||
$(MAKE) -f Makefile.Android PROJECT_NAME=$@ PROJECT_SOURCE_FILES=$<
|
||||
else ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
$(MAKE) -f Makefile.Web $@
|
||||
else
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -D$(TARGET_PLATFORM)
|
||||
endif
|
||||
|
||||
# Clean everything
|
||||
clean:
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
del *.o *.exe /s
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
find . -type f -perm -ugo+x -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
find . -type f -executable -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
find . -type f -perm +ugo+x -delete
|
||||
rm -f *.o
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
find . -type f -executable -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
del *.wasm *.html *.js *.data
|
||||
else
|
||||
rm -f */*.wasm */*.html */*.js */*.data
|
||||
endif
|
||||
endif
|
||||
@echo Cleaning done
|
||||
@ -0,0 +1,412 @@
|
||||
#**************************************************************************************************
|
||||
#
|
||||
# raylib makefile for Android project (APK building)
|
||||
#
|
||||
# Copyright (c) 2017-2026 Ramon Santamaria (@raysan5)
|
||||
#
|
||||
# This software is provided "as-is", without any express or implied warranty. In no event
|
||||
# will the authors be held liable for any damages arising from the use of this software.
|
||||
#
|
||||
# Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
# applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
#
|
||||
# 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
# wrote the original software. If you use this software in a product, an acknowledgment
|
||||
# in the product documentation would be appreciated but is not required.
|
||||
#
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
# as being the original software.
|
||||
#
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
#
|
||||
#**************************************************************************************************
|
||||
|
||||
# Define required raylib variables
|
||||
PLATFORM ?= PLATFORM_ANDROID
|
||||
RAYLIB_PATH ?= ..\..
|
||||
|
||||
# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version
|
||||
# Starting in 2019 using ARM64 is mandatory for published apps,
|
||||
# Starting on August 2020, minimum required target API is Android 10 (API level 29)
|
||||
ANDROID_ARCH ?= ARM64
|
||||
ANDROID_API_VERSION = 29
|
||||
|
||||
# Android required path variables
|
||||
# NOTE: Starting with Android NDK r21, no more toolchain generation is required, NDK is the toolchain on itself
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ANDROID_NDK = C:/android-ndk
|
||||
ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/windows-x86_64
|
||||
else
|
||||
ANDROID_NDK ?= /usr/lib/android/ndk
|
||||
ANDROID_TOOLCHAIN = $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64
|
||||
endif
|
||||
|
||||
ifeq ($(ANDROID_ARCH),ARM)
|
||||
ANDROID_ARCH_NAME = armeabi-v7a
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),ARM64)
|
||||
ANDROID_ARCH_NAME = arm64-v8a
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),x86)
|
||||
ANDROID_ARCH_NAME = x86
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),x86_64)
|
||||
ANDROID_ARCH_NAME = x86_64
|
||||
endif
|
||||
|
||||
# Required path variables
|
||||
# NOTE: JAVA_HOME must be set to JDK (using OpenJDK 13)
|
||||
JAVA_HOME ?= C:/open-jdk
|
||||
ANDROID_HOME ?= C:/android-sdk
|
||||
ANDROID_BUILD_TOOLS ?= $(ANDROID_HOME)/build-tools/29.0.3
|
||||
ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools
|
||||
|
||||
# Android project configuration variables
|
||||
PROJECT_NAME ?= raylib_game
|
||||
PROJECT_LIBRARY_NAME ?= main
|
||||
PROJECT_BUILD_ID ?= android
|
||||
PROJECT_BUILD_PATH ?= $(PROJECT_BUILD_ID).$(PROJECT_NAME)
|
||||
PROJECT_RESOURCES_PATH ?= resources
|
||||
PROJECT_SOURCE_FILES ?= raylib_game.c
|
||||
NATIVE_APP_GLUE_PATH = $(ANDROID_NDK)/sources/android/native_app_glue
|
||||
|
||||
# Some source files are placed in directories, when compiling to some
|
||||
# output directory other than source, that directory must pre-exist.
|
||||
# Here we get a list of required folders that need to be created on
|
||||
# code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors.
|
||||
PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES)))
|
||||
|
||||
# Android app configuration variables
|
||||
APP_LABEL_NAME ?= rGame
|
||||
APP_COMPANY_NAME ?= raylib
|
||||
APP_PRODUCT_NAME ?= rgame
|
||||
APP_VERSION_CODE ?= 1
|
||||
APP_VERSION_NAME ?= 1.0
|
||||
APP_ICON_LDPI ?= $(RAYLIB_PATH)/logo/raylib_36x36.png
|
||||
APP_ICON_MDPI ?= $(RAYLIB_PATH)/logo/raylib_48x48.png
|
||||
APP_ICON_HDPI ?= $(RAYLIB_PATH)/logo/raylib_72x72.png
|
||||
APP_SCREEN_ORIENTATION ?= landscape
|
||||
APP_KEYSTORE_PASS ?= raylib
|
||||
|
||||
# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
|
||||
RAYLIB_LIBTYPE ?= STATIC
|
||||
|
||||
# Library path for libraylib.a/libraylib.so
|
||||
RAYLIB_LIB_PATH = $(RAYLIB_PATH)/src
|
||||
|
||||
# Define copy command depending on OS
|
||||
ifeq ($(OS),Windows_NT)
|
||||
COPY_COMMAND ?= copy /Y
|
||||
else
|
||||
COPY_COMMAND ?= cp -f
|
||||
endif
|
||||
|
||||
# Shared libs must be added to APK if required
|
||||
# NOTE: Generated NativeLoader.java automatically load those libraries
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so
|
||||
endif
|
||||
|
||||
# Compiler and archiver
|
||||
ifeq ($(ANDROID_ARCH),ARM)
|
||||
CC = $(ANDROID_TOOLCHAIN)/bin/armv7a-linux-androideabi$(ANDROID_API_VERSION)-clang
|
||||
AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),ARM64)
|
||||
CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android$(ANDROID_API_VERSION)-clang
|
||||
AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),x86)
|
||||
CC = $(ANDROID_TOOLCHAIN)/bin/i686-linux-android$(ANDROID_API_VERSION)-clang
|
||||
AR = $(ANDROID_TOOLCHAIN)/bin/i686-linux-android-ar
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),x86_64)
|
||||
CC = $(ANDROID_TOOLCHAIN)/bin/x86_64-linux-android$(ANDROID_API_VERSION)-clang
|
||||
AR = $(ANDROID_TOOLCHAIN)/bin/x86_64-linux-android-ar
|
||||
endif
|
||||
|
||||
# Compiler flags for arquitecture
|
||||
ifeq ($(ANDROID_ARCH),ARM)
|
||||
CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
|
||||
endif
|
||||
ifeq ($(ANDROID_ARCH),ARM64)
|
||||
CFLAGS = -std=c99 -mfix-cortex-a53-835769
|
||||
endif
|
||||
# Compilation functions attributes options
|
||||
CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC
|
||||
# Compiler options for the linker
|
||||
CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes
|
||||
# Preprocessor macro definitions
|
||||
CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION)
|
||||
|
||||
# Paths containing required header files
|
||||
INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(NATIVE_APP_GLUE_PATH)
|
||||
|
||||
# Linker options
|
||||
LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a
|
||||
LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings
|
||||
# Force linking of library module to define symbol
|
||||
LDFLAGS += -u ANativeActivity_onCreate
|
||||
# Library paths containing required libs
|
||||
LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib
|
||||
|
||||
# Define any libraries to link into executable
|
||||
# if you want to link libraries (libname.so or libname.a), use the -lname
|
||||
LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl
|
||||
|
||||
# Generate target objects list from PROJECT_SOURCE_FILES
|
||||
OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES))
|
||||
|
||||
# Android APK building process... some steps required...
|
||||
# NOTE: typing 'make' will invoke the default target entry called 'all'
|
||||
# TODO: Use apksigner for APK signing, jarsigner is not recommended
|
||||
all: create_temp_project_dirs \
|
||||
copy_project_required_libs \
|
||||
copy_project_resources \
|
||||
generate_loader_script \
|
||||
generate_android_manifest \
|
||||
generate_apk_keystore \
|
||||
config_project_package \
|
||||
compile_project_code \
|
||||
compile_project_class \
|
||||
compile_project_class_dex \
|
||||
create_project_apk_package \
|
||||
sign_project_apk_package \
|
||||
zipalign_project_apk_package
|
||||
|
||||
# WARNING: About build signing process:
|
||||
# - If using apksigner, zipalign must be used before the APK file has been signed.
|
||||
# - If using jarsigner (not recommended), zipalign must be used after the APK file has been signed.
|
||||
# REF: https://developer.android.com/tools/zipalign
|
||||
# REF: https://developer.android.com/tools/apksigner
|
||||
|
||||
# Create required temp directories for APK building
|
||||
create_temp_project_dirs:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH)
|
||||
if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj
|
||||
if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj\src
|
||||
if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src
|
||||
if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com
|
||||
if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)
|
||||
if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME)
|
||||
if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib
|
||||
if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)
|
||||
if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin
|
||||
if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res
|
||||
if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi
|
||||
if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi
|
||||
if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi
|
||||
if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values
|
||||
if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets
|
||||
if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH)
|
||||
if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens
|
||||
else
|
||||
mkdir -p $(PROJECT_BUILD_PATH)
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/obj
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/obj/src
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/src
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/src/com
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/lib
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/bin
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/res
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/res/drawable-ldpi
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/res/drawable-mdpi
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/res/drawable-hdpi
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/res/values
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/assets
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/assets/$(PROJECT_RESOURCES_PATH)
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/obj/screens
|
||||
endif
|
||||
$(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir)))
|
||||
|
||||
define create_dir
|
||||
mkdir -p $(PROJECT_BUILD_PATH)/obj/$(1)
|
||||
endef
|
||||
|
||||
# Copy required shared libs for integration into APK
|
||||
# NOTE: If using shared libs they are loaded by generated NativeLoader.java
|
||||
copy_project_required_libs:
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
$(COPY_COMMAND) $(RAYLIB_LIB_PATH)/libraylib.so $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/libraylib.so
|
||||
endif
|
||||
ifeq ($(RAYLIB_LIBTYPE),STATIC)
|
||||
$(COPY_COMMAND) $(RAYLIB_LIB_PATH)/libraylib.a $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/libraylib.a
|
||||
endif
|
||||
|
||||
# Copy project required resources: strings.xml, icon.png, assets
|
||||
# NOTE: Required strings.xml is generated and game resources are copied to assets folder
|
||||
copy_project_resources:
|
||||
$(COPY_COMMAND) $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)/res/drawable-ldpi/icon.png
|
||||
$(COPY_COMMAND) $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)/res/drawable-mdpi/icon.png
|
||||
$(COPY_COMMAND) $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)/res/drawable-hdpi/icon.png
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@echo ^<?xml version="1.0" encoding="utf-8"^?^> > $(PROJECT_BUILD_PATH)/res/values/strings.xml
|
||||
@echo ^<resources^>^<string name="app_name"^>$(APP_LABEL_NAME)^</string^>^</resources^> >> $(PROJECT_BUILD_PATH)/res/values/strings.xml
|
||||
if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F
|
||||
else
|
||||
@echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" > $(PROJECT_BUILD_PATH)/res/values/strings.xml
|
||||
@echo "<resources><string name=\"app_name\">$(APP_LABEL_NAME)</string></resources>" >> $(PROJECT_BUILD_PATH)/res/values/strings.xml
|
||||
@[ -d "$(PROJECT_RESOURCES_PATH)" ] || cp -rf $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)/assets/$(PROJECT_RESOURCES_PATH)
|
||||
endif
|
||||
|
||||
# Generate NativeLoader.java to load required shared libraries
|
||||
# NOTE: Probably not the bet way to generate this file... but it works.
|
||||
generate_loader_script:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
@echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
endif
|
||||
@echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
else
|
||||
@echo "package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME);" > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo "" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo "public class NativeLoader extends android.app.NativeActivity {" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo " static {" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
ifeq ($(RAYLIB_LIBTYPE),SHARED)
|
||||
@echo " System.loadLibrary(\"raylib\");" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
endif
|
||||
@echo " System.loadLibrary(\"$(PROJECT_LIBRARY_NAME)\");" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo " }" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
@echo "}" >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
endif
|
||||
|
||||
# Generate AndroidManifest.xml with all the required options
|
||||
# NOTE: Probably not the bet way to generate this file... but it works.
|
||||
generate_android_manifest:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
@echo ^<?xml version="1.0" encoding="utf-8"^?^> > $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<manifest xmlns:android="http://schemas.android.com/apk/res/android" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<uses-sdk android:minSdkVersion="$(ANDROID_API_VERSION)" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<uses-feature android:glEsVersion="0x00020000" android:required="true" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<application android:allowBackup="false" android:label="@string/app_name" android:icon="@drawable/icon" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<activity android:name="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME).NativeLoader" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<meta-data android:name="android.app.lib_name" android:value="$(PROJECT_LIBRARY_NAME)" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<intent-filter^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<action android:name="android.intent.action.MAIN" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^<category android:name="android.intent.category.LAUNCHER" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^</intent-filter^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^</activity^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^</application^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo ^</manifest^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
else
|
||||
@echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" > $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " package=\"com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)\" " >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " android:versionCode=\"$(APP_VERSION_CODE)\" android:versionName=\"$(APP_VERSION_NAME)\" >" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <uses-sdk android:minSdkVersion=\"$(ANDROID_API_VERSION)\" />" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <uses-feature android:glEsVersion=\"0x00020000\" android:required=\"true\" />" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <application android:allowBackup=\"false\" android:label=\"@string/app_name\" android:icon=\"@drawable/icon\" >" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <activity android:name=\"com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME).NativeLoader\"" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\"" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " android:configChanges=\"orientation|keyboardHidden|screenSize\"" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " android:screenOrientation=\"$(APP_SCREEN_ORIENTATION)\" android:launchMode=\"singleTask\"" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " android:clearTaskOnLaunch=\"true\">" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <meta-data android:name=\"android.app.lib_name\" android:value=\"$(PROJECT_LIBRARY_NAME)\" />" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <intent-filter>" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <action android:name=\"android.intent.action.MAIN\" />" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " <category android:name=\"android.intent.category.LAUNCHER\" />" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " </intent-filter>" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " </activity>" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo " </application>" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
@echo "</manifest>" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
|
||||
endif
|
||||
|
||||
# Generate storekey for APK signing: $(PROJECT_NAME).keystore
|
||||
# NOTE: Configure here your Distinguished Names (-dname) if required!
|
||||
generate_apk_keystore:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 10000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA
|
||||
else
|
||||
@[ -f "$(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore" ] || $(JAVA_HOME)/bin/keytool -genkeypair -validity 10000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA
|
||||
endif
|
||||
|
||||
# Config project package and resource using AndroidManifest.xml and res/values/strings.xml
|
||||
# NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java
|
||||
config_project_package:
|
||||
$(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar
|
||||
|
||||
# Compile native_app_glue code as static library: obj/libnative_app_glue.a
|
||||
compile_native_app_glue:
|
||||
$(CC) -c $(NATIVE_APP_GLUE_PATH)/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS)
|
||||
$(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o
|
||||
|
||||
# Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so
|
||||
compile_project_code: $(OBJS)
|
||||
$(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
# Compile all .c files required into object (.o) files
|
||||
# NOTE: Those files will be linked into a shared library
|
||||
$(PROJECT_BUILD_PATH)/obj/%.o:%.c
|
||||
$(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot
|
||||
|
||||
# Compile project .java code into .class (Java bytecode)
|
||||
compile_project_class:
|
||||
$(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -d $(PROJECT_BUILD_PATH)/obj $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
|
||||
|
||||
# Compile .class files into Dalvik executable bytecode (.dex)
|
||||
# NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT)
|
||||
compile_project_class_dex:
|
||||
$(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj
|
||||
|
||||
# Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk
|
||||
# NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so
|
||||
# NOTE: Use -A resources to define additional directory in which to find raw asset files
|
||||
create_project_apk_package:
|
||||
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin
|
||||
cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS)
|
||||
|
||||
# Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk
|
||||
sign_project_apk_package:
|
||||
$(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key
|
||||
|
||||
# Create zip-aligned APK package: $(PROJECT_NAME).apk
|
||||
zipalign_project_apk_package:
|
||||
$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk
|
||||
|
||||
# Install $(PROJECT_NAME).apk to default emulator/device
|
||||
# NOTE: Use -e (emulator) or -d (device) parameters if required
|
||||
install:
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb install $(PROJECT_NAME).apk
|
||||
|
||||
# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64)
|
||||
check_device_abi:
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi
|
||||
|
||||
# Monitorize output log coming from device, only raylib tag
|
||||
logcat:
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb logcat -c
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S
|
||||
|
||||
# Install and monitorize $(PROJECT_NAME).apk to default emulator/device
|
||||
deploy:
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb install $(PROJECT_NAME).apk
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb logcat -c
|
||||
$(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S
|
||||
|
||||
#$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W
|
||||
|
||||
# Clean everything
|
||||
clean:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
del $(PROJECT_BUILD_PATH)\* /f /s /q
|
||||
rmdir $(PROJECT_BUILD_PATH) /s /q
|
||||
else
|
||||
rm -r $(PROJECT_BUILD_PATH)
|
||||
endif
|
||||
@echo Cleaning done
|
||||
@ -0,0 +1,284 @@
|
||||
## Building the Examples
|
||||
|
||||
The examples assume you have already built the `raylib` library in `../src`.
|
||||
|
||||
### With GNU make
|
||||
|
||||
- `make` builds all examples
|
||||
- `make [module]` builds all examples for a particular module (e.g `make core`)
|
||||
- `make [module]/[name]` builds one examples for a particular module (e.g `make core/core_basic_window`)
|
||||
|
||||
### With Zig
|
||||
|
||||
The [Zig](https://ziglang.org/) toolchain can compile `C` and `C++` in addition to `Zig`.
|
||||
You may find it easier to use than other toolchains, especially when it comes to cross-compiling.
|
||||
|
||||
- `zig build` to compile all examples
|
||||
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
|
||||
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
|
||||
|
||||
## EXAMPLES COLLECTION [TOTAL: 212]
|
||||
|
||||
### category: core [49]
|
||||
|
||||
Examples using raylib [core](../src/rcore.c) module platform functionality: window creation, inputs, drawing modes and system functionality.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [core_basic_window](core/core_basic_window.c) | <img src="core/core_basic_window.png" alt="core_basic_window" width="80"> | ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_delta_time](core/core_delta_time.c) | <img src="core/core_delta_time.png" alt="core_delta_time" width="80"> | ⭐☆☆☆ | 5.5 | 6.0 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [core_input_keys](core/core_input_keys.c) | <img src="core/core_input_keys.png" alt="core_input_keys" width="80"> | ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_input_mouse](core/core_input_mouse.c) | <img src="core/core_input_mouse.png" alt="core_input_mouse" width="80"> | ⭐☆☆☆ | 1.0 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_input_mouse_wheel](core/core_input_mouse_wheel.c) | <img src="core/core_input_mouse_wheel.png" alt="core_input_mouse_wheel" width="80"> | ⭐☆☆☆ | 1.1 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_input_gamepad](core/core_input_gamepad.c) | <img src="core/core_input_gamepad.png" alt="core_input_gamepad" width="80"> | ⭐☆☆☆ | 1.1 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_input_multitouch](core/core_input_multitouch.c) | <img src="core/core_input_multitouch.png" alt="core_input_multitouch" width="80"> | ⭐☆☆☆ | 2.1 | 2.5 | [Berni](https://github.com/Berni8k) |
|
||||
| [core_input_gestures](core/core_input_gestures.c) | <img src="core/core_input_gestures.png" alt="core_input_gestures" width="80"> | ⭐⭐☆☆ | 1.4 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_input_gestures_testbed](core/core_input_gestures_testbed.c) | <img src="core/core_input_gestures_testbed.png" alt="core_input_gestures_testbed" width="80"> | ⭐⭐⭐☆ | 5.0 | 6.0 | [ubkp](https://github.com/ubkp) |
|
||||
| [core_input_virtual_controls](core/core_input_virtual_controls.c) | <img src="core/core_input_virtual_controls.png" alt="core_input_virtual_controls" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [GreenSnakeLinux](https://github.com/GreenSnakeLinux) |
|
||||
| [core_2d_camera](core/core_2d_camera.c) | <img src="core/core_2d_camera.png" alt="core_2d_camera" width="80"> | ⭐⭐☆☆ | 1.5 | 3.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_2d_camera_mouse_zoom](core/core_2d_camera_mouse_zoom.c) | <img src="core/core_2d_camera_mouse_zoom.png" alt="core_2d_camera_mouse_zoom" width="80"> | ⭐⭐☆☆ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||
| [core_2d_camera_platformer](core/core_2d_camera_platformer.c) | <img src="core/core_2d_camera_platformer.png" alt="core_2d_camera_platformer" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.0 | [arvyy](https://github.com/arvyy) |
|
||||
| [core_2d_camera_split_screen](core/core_2d_camera_split_screen.c) | <img src="core/core_2d_camera_split_screen.png" alt="core_2d_camera_split_screen" width="80"> | ⭐⭐⭐⭐️ | 4.5 | 4.5 | [Gabriel dos Santos Sanches](https://github.com/gabrielssanches) |
|
||||
| [core_3d_camera_mode](core/core_3d_camera_mode.c) | <img src="core/core_3d_camera_mode.png" alt="core_3d_camera_mode" width="80"> | ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_3d_camera_free](core/core_3d_camera_free.c) | <img src="core/core_3d_camera_free.png" alt="core_3d_camera_free" width="80"> | ⭐☆☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_3d_camera_first_person](core/core_3d_camera_first_person.c) | <img src="core/core_3d_camera_first_person.png" alt="core_3d_camera_first_person" width="80"> | ⭐⭐☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_3d_camera_split_screen](core/core_3d_camera_split_screen.c) | <img src="core/core_3d_camera_split_screen.png" alt="core_3d_camera_split_screen" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||
| [core_3d_camera_fps](core/core_3d_camera_fps.c) | <img src="core/core_3d_camera_fps.png" alt="core_3d_camera_fps" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
|
||||
| [core_3d_picking](core/core_3d_picking.c) | <img src="core/core_3d_picking.png" alt="core_3d_picking" width="80"> | ⭐⭐☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_world_screen](core/core_world_screen.c) | <img src="core/core_world_screen.png" alt="core_world_screen" width="80"> | ⭐⭐☆☆ | 1.3 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_window_flags](core/core_window_flags.c) | <img src="core/core_window_flags.png" alt="core_window_flags" width="80"> | ⭐⭐⭐☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_window_letterbox](core/core_window_letterbox.c) | <img src="core/core_window_letterbox.png" alt="core_window_letterbox" width="80"> | ⭐⭐☆☆ | 2.5 | 4.0 | [Anata](https://github.com/anatagawa) |
|
||||
| [core_window_should_close](core/core_window_should_close.c) | <img src="core/core_window_should_close.png" alt="core_window_should_close" width="80"> | ⭐☆☆☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_monitor_detector](core/core_monitor_detector.c) | <img src="core/core_monitor_detector.png" alt="core_monitor_detector" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) |
|
||||
| [core_custom_logging](core/core_custom_logging.c) | <img src="core/core_custom_logging.png" alt="core_custom_logging" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) |
|
||||
| [core_drop_files](core/core_drop_files.c) | <img src="core/core_drop_files.png" alt="core_drop_files" width="80"> | ⭐⭐☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_random_values](core/core_random_values.c) | <img src="core/core_random_values.png" alt="core_random_values" width="80"> | ⭐☆☆☆ | 1.1 | 1.1 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_storage_values](core/core_storage_values.c) | <img src="core/core_storage_values.png" alt="core_storage_values" width="80"> | ⭐⭐☆☆ | 1.4 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_vr_simulator](core/core_vr_simulator.c) | <img src="core/core_vr_simulator.png" alt="core_vr_simulator" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_scissor_test](core/core_scissor_test.c) | <img src="core/core_scissor_test.png" alt="core_scissor_test" width="80"> | ⭐☆☆☆ | 2.5 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
|
||||
| [core_basic_screen_manager](core/core_basic_screen_manager.c) | <img src="core/core_basic_screen_manager.png" alt="core_basic_screen_manager" width="80"> | ⭐☆☆☆ | 4.0 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_custom_frame_control](core/core_custom_frame_control.c) | <img src="core/core_custom_frame_control.png" alt="core_custom_frame_control" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) |
|
||||
| [core_random_sequence](core/core_random_sequence.c) | <img src="core/core_random_sequence.png" alt="core_random_sequence" width="80"> | ⭐☆☆☆ | 5.0 | 5.0 | [Dalton Overmyer](https://github.com/REDl3east) |
|
||||
| [core_automation_events](core/core_automation_events.c) | <img src="core/core_automation_events.png" alt="core_automation_events" width="80"> | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_highdpi_demo](core/core_highdpi_demo.c) | <img src="core/core_highdpi_demo.png" alt="core_highdpi_demo" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
|
||||
| [core_render_texture](core/core_render_texture.c) | <img src="core/core_render_texture.png" alt="core_render_texture" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_viewport_scaling](core/core_viewport_scaling.c) | <img src="core/core_viewport_scaling.png" alt="core_viewport_scaling" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
|
||||
| [core_input_actions](core/core_input_actions.c) | <img src="core/core_input_actions.png" alt="core_input_actions" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) |
|
||||
| [core_directory_files](core/core_directory_files.c) | <img src="core/core_directory_files.png" alt="core_directory_files" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
|
||||
| [core_highdpi_testbed](core/core_highdpi_testbed.c) | <img src="core/core_highdpi_testbed.png" alt="core_highdpi_testbed" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_screen_recording](core/core_screen_recording.c) | <img src="core/core_screen_recording.png" alt="core_screen_recording" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_clipboard_text](core/core_clipboard_text.c) | <img src="core/core_clipboard_text.png" alt="core_clipboard_text" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Ananth S](https://github.com/Ananth1839) |
|
||||
| [core_text_file_loading](core/core_text_file_loading.c) | <img src="core/core_text_file_loading.png" alt="core_text_file_loading" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) |
|
||||
| [core_compute_hash](core/core_compute_hash.c) | <img src="core/core_compute_hash.png" alt="core_compute_hash" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_keyboard_testbed](core/core_keyboard_testbed.c) | <img src="core/core_keyboard_testbed.png" alt="core_keyboard_testbed" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_window_web](core/core_window_web.c) | <img src="core/core_window_web.png" alt="core_window_web" width="80"> | ⭐☆☆☆ | 1.3 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
|
||||
### category: shapes [40]
|
||||
|
||||
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [shapes_basic_shapes](shapes/shapes_basic_shapes.c) | <img src="shapes/shapes_basic_shapes.png" alt="shapes_basic_shapes" width="80"> | ⭐☆☆☆ | 1.0 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) | <img src="shapes/shapes_bouncing_ball.png" alt="shapes_bouncing_ball" width="80"> | ⭐☆☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_bullet_hell](shapes/shapes_bullet_hell.c) | <img src="shapes/shapes_bullet_hell.png" alt="shapes_bullet_hell" width="80"> | ⭐☆☆☆ | 5.6 | 5.6 | [Zero](https://github.com/zerohorsepower) |
|
||||
| [shapes_colors_palette](shapes/shapes_colors_palette.c) | <img src="shapes/shapes_colors_palette.png" alt="shapes_colors_palette" width="80"> | ⭐⭐☆☆ | 1.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_logo_raylib](shapes/shapes_logo_raylib.c) | <img src="shapes/shapes_logo_raylib.png" alt="shapes_logo_raylib" width="80"> | ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) | <img src="shapes/shapes_logo_raylib_anim.png" alt="shapes_logo_raylib_anim" width="80"> | ⭐⭐☆☆ | 2.5 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_rectangle_scaling](shapes/shapes_rectangle_scaling.c) | <img src="shapes/shapes_rectangle_scaling.png" alt="shapes_rectangle_scaling" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [shapes_lines_bezier](shapes/shapes_lines_bezier.c) | <img src="shapes/shapes_lines_bezier.png" alt="shapes_lines_bezier" width="80"> | ⭐☆☆☆ | 1.7 | 1.7 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_collision_area](shapes/shapes_collision_area.c) | <img src="shapes/shapes_collision_area.png" alt="shapes_collision_area" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_following_eyes](shapes/shapes_following_eyes.c) | <img src="shapes/shapes_following_eyes.png" alt="shapes_following_eyes" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_easings_ball](shapes/shapes_easings_ball.c) | <img src="shapes/shapes_easings_ball.png" alt="shapes_easings_ball" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_easings_box](shapes/shapes_easings_box.c) | <img src="shapes/shapes_easings_box.png" alt="shapes_easings_box" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_easings_rectangles](shapes/shapes_easings_rectangles.c) | <img src="shapes/shapes_easings_rectangles.png" alt="shapes_easings_rectangles" width="80"> | ⭐⭐⭐☆ | 2.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_recursive_tree](shapes/shapes_recursive_tree.c) | <img src="shapes/shapes_recursive_tree.png" alt="shapes_recursive_tree" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
|
||||
| [shapes_ring_drawing](shapes/shapes_ring_drawing.c) | <img src="shapes/shapes_ring_drawing.png" alt="shapes_ring_drawing" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [shapes_circle_sector_drawing](shapes/shapes_circle_sector_drawing.c) | <img src="shapes/shapes_circle_sector_drawing.png" alt="shapes_circle_sector_drawing" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [shapes_rounded_rectangle_drawing](shapes/shapes_rounded_rectangle_drawing.c) | <img src="shapes/shapes_rounded_rectangle_drawing.png" alt="shapes_rounded_rectangle_drawing" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | <img src="shapes/shapes_top_down_lights.png" alt="shapes_top_down_lights" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||
| [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | <img src="shapes/shapes_rectangle_advanced.png" alt="shapes_rectangle_advanced" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) |
|
||||
| [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | <img src="shapes/shapes_splines_drawing.png" alt="shapes_splines_drawing" width="80"> | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_digital_clock](shapes/shapes_digital_clock.c) | <img src="shapes/shapes_digital_clock.png" alt="shapes_digital_clock" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
|
||||
| [shapes_double_pendulum](shapes/shapes_double_pendulum.c) | <img src="shapes/shapes_double_pendulum.png" alt="shapes_double_pendulum" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) |
|
||||
| [shapes_dashed_line](shapes/shapes_dashed_line.c) | <img src="shapes/shapes_dashed_line.png" alt="shapes_dashed_line" width="80"> | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) |
|
||||
| [shapes_triangle_strip](shapes/shapes_triangle_strip.c) | <img src="shapes/shapes_triangle_strip.png" alt="shapes_triangle_strip" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
|
||||
| [shapes_vector_angle](shapes/shapes_vector_angle.c) | <img src="shapes/shapes_vector_angle.png" alt="shapes_vector_angle" width="80"> | ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shapes_pie_chart](shapes/shapes_pie_chart.c) | <img src="shapes/shapes_pie_chart.png" alt="shapes_pie_chart" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) |
|
||||
| [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | <img src="shapes/shapes_kaleidoscope.png" alt="shapes_kaleidoscope" width="80"> | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
|
||||
| [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | <img src="shapes/shapes_clock_of_clocks.png" alt="shapes_clock_of_clocks" width="80"> | ⭐⭐☆☆ | 5.5 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
|
||||
| [shapes_math_sine_cosine](shapes/shapes_math_sine_cosine.c) | <img src="shapes/shapes_math_sine_cosine.png" alt="shapes_math_sine_cosine" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
|
||||
| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | <img src="shapes/shapes_mouse_trail.png" alt="shapes_mouse_trail" width="80"> | ⭐☆☆☆ | 5.6 | 6.0 | [Balamurugan R](https://github.com/Bala050814) |
|
||||
| [shapes_simple_particles](shapes/shapes_simple_particles.c) | <img src="shapes/shapes_simple_particles.png" alt="shapes_simple_particles" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | <img src="shapes/shapes_starfield_effect.png" alt="shapes_starfield_effect" width="80"> | ⭐⭐☆☆ | 5.5 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
|
||||
| [shapes_lines_drawing](shapes/shapes_lines_drawing.c) | <img src="shapes/shapes_lines_drawing.png" alt="shapes_lines_drawing" width="80"> | ⭐☆☆☆ | 6.0 | 5.6 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) | <img src="shapes/shapes_math_angle_rotation.png" alt="shapes_math_angle_rotation" width="80"> | ⭐☆☆☆ | 6.0 | 5.6 | [Kris](https://github.com/krispy-snacc) |
|
||||
| [shapes_rlgl_color_wheel](shapes/shapes_rlgl_color_wheel.c) | <img src="shapes/shapes_rlgl_color_wheel.png" alt="shapes_rlgl_color_wheel" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [shapes_rlgl_triangle](shapes/shapes_rlgl_triangle.c) | <img src="shapes/shapes_rlgl_triangle.png" alt="shapes_rlgl_triangle" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [shapes_ball_physics](shapes/shapes_ball_physics.c) | <img src="shapes/shapes_ball_physics.png" alt="shapes_ball_physics" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
|
||||
| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) | <img src="shapes/shapes_penrose_tile.png" alt="shapes_penrose_tile" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
|
||||
| [shapes_hilbert_curve](shapes/shapes_hilbert_curve.c) | <img src="shapes/shapes_hilbert_curve.png" alt="shapes_hilbert_curve" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
|
||||
| [shapes_easings_testbed](shapes/shapes_easings_testbed.c) | <img src="shapes/shapes_easings_testbed.png" alt="shapes_easings_testbed" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Juan Miguel López](https://github.com/flashback-fx) |
|
||||
|
||||
### category: textures [32]
|
||||
|
||||
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [textures_clipboard_image](textures/textures_clipboard_image.c) | <img src="textures/textures_clipboard_image.png" alt="textures_clipboard_image" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Maicon Santana](https://github.com/maiconpintoabreu) |
|
||||
| [textures_magnifying_glass](textures/textures_magnifying_glass.c) | <img src="textures/textures_magnifying_glass.png" alt="textures_magnifying_glass" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Luke Vaughan](https://github.com/badram) |
|
||||
| [textures_logo_raylib](textures/textures_logo_raylib.c) | <img src="textures/textures_logo_raylib.png" alt="textures_logo_raylib" width="80"> | ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_srcrec_dstrec](textures/textures_srcrec_dstrec.c) | <img src="textures/textures_srcrec_dstrec.png" alt="textures_srcrec_dstrec" width="80"> | ⭐⭐⭐☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_image_drawing](textures/textures_image_drawing.c) | <img src="textures/textures_image_drawing.png" alt="textures_image_drawing" width="80"> | ⭐⭐☆☆ | 1.4 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_image_generation](textures/textures_image_generation.c) | <img src="textures/textures_image_generation.png" alt="textures_image_generation" width="80"> | ⭐⭐☆☆ | 1.8 | 1.8 | [Wilhem Barbier](https://github.com/nounoursheureux) |
|
||||
| [textures_image_loading](textures/textures_image_loading.c) | <img src="textures/textures_image_loading.png" alt="textures_image_loading" width="80"> | ⭐☆☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_image_processing](textures/textures_image_processing.c) | <img src="textures/textures_image_processing.png" alt="textures_image_processing" width="80"> | ⭐⭐⭐☆ | 1.4 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_image_text](textures/textures_image_text.c) | <img src="textures/textures_image_text.png" alt="textures_image_text" width="80"> | ⭐⭐☆☆ | 1.8 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_to_image](textures/textures_to_image.c) | <img src="textures/textures_to_image.png" alt="textures_to_image" width="80"> | ⭐☆☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_raw_data](textures/textures_raw_data.c) | <img src="textures/textures_raw_data.png" alt="textures_raw_data" width="80"> | ⭐⭐⭐☆ | 1.3 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_particles_blending](textures/textures_particles_blending.c) | <img src="textures/textures_particles_blending.png" alt="textures_particles_blending" width="80"> | ⭐☆☆☆ | 1.7 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_npatch_drawing](textures/textures_npatch_drawing.c) | <img src="textures/textures_npatch_drawing.png" alt="textures_npatch_drawing" width="80"> | ⭐⭐⭐☆ | 2.0 | 2.5 | [Jorge A. Gomes](https://github.com/overdev) |
|
||||
| [textures_background_scrolling](textures/textures_background_scrolling.c) | <img src="textures/textures_background_scrolling.png" alt="textures_background_scrolling" width="80"> | ⭐☆☆☆ | 2.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_sprite_animation](textures/textures_sprite_animation.c) | <img src="textures/textures_sprite_animation.png" alt="textures_sprite_animation" width="80"> | ⭐⭐☆☆ | 1.3 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_sprite_button](textures/textures_sprite_button.c) | <img src="textures/textures_sprite_button.png" alt="textures_sprite_button" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_sprite_explosion](textures/textures_sprite_explosion.c) | <img src="textures/textures_sprite_explosion.png" alt="textures_sprite_explosion" width="80"> | ⭐⭐☆☆ | 2.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_bunnymark](textures/textures_bunnymark.c) | <img src="textures/textures_bunnymark.png" alt="textures_bunnymark" width="80"> | ⭐⭐⭐☆ | 1.6 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
|
||||
| [textures_blend_modes](textures/textures_blend_modes.c) | <img src="textures/textures_blend_modes.png" alt="textures_blend_modes" width="80"> | ⭐☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) |
|
||||
| [textures_tiled_drawing](textures/textures_tiled_drawing.c) | <img src="textures/textures_tiled_drawing.png" alt="textures_tiled_drawing" width="80"> | ⭐⭐⭐☆ | 3.0 | 4.2 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [textures_polygon_drawing](textures/textures_polygon_drawing.c) | <img src="textures/textures_polygon_drawing.png" alt="textures_polygon_drawing" width="80"> | ⭐☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
|
||||
| [textures_fog_of_war](textures/textures_fog_of_war.c) | <img src="textures/textures_fog_of_war.png" alt="textures_fog_of_war" width="80"> | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_gif_player](textures/textures_gif_player.c) | <img src="textures/textures_gif_player.png" alt="textures_gif_player" width="80"> | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_image_kernel](textures/textures_image_kernel.c) | <img src="textures/textures_image_kernel.png" alt="textures_image_kernel" width="80"> | ⭐⭐⭐⭐️ | 1.3 | 1.3 | [Karim Salem](https://github.com/kimo-s) |
|
||||
| [textures_image_channel](textures/textures_image_channel.c) | <img src="textures/textures_image_channel.png" alt="textures_image_channel" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Bruno Cabral](https://github.com/brccabral) |
|
||||
| [textures_image_rotate](textures/textures_image_rotate.c) | <img src="textures/textures_image_rotate.png" alt="textures_image_rotate" width="80"> | ⭐⭐☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_screen_buffer](textures/textures_screen_buffer.c) | <img src="textures/textures_screen_buffer.png" alt="textures_screen_buffer" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
|
||||
| [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||
| [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [textures_cellular_automata](textures/textures_cellular_automata.c) | <img src="textures/textures_cellular_automata.png" alt="textures_cellular_automata" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [textures_framebuffer_rendering](textures/textures_framebuffer_rendering.c) | <img src="textures/textures_framebuffer_rendering.png" alt="textures_framebuffer_rendering" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jack Boakes](https://github.com/jackboakes) |
|
||||
|
||||
### category: text [16]
|
||||
|
||||
Examples using raylib text functionality, including sprite fonts loading/generation and text drawing, provided by raylib [text](../src/rtext.c) module.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [text_sprite_fonts](text/text_sprite_fonts.c) | <img src="text/text_sprite_fonts.png" alt="text_sprite_fonts" width="80"> | ⭐☆☆☆ | 1.7 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_font_spritefont](text/text_font_spritefont.c) | <img src="text/text_font_spritefont.png" alt="text_font_spritefont" width="80"> | ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_font_filters](text/text_font_filters.c) | <img src="text/text_font_filters.png" alt="text_font_filters" width="80"> | ⭐⭐☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_font_loading](text/text_font_loading.c) | <img src="text/text_font_loading.png" alt="text_font_loading" width="80"> | ⭐☆☆☆ | 1.4 | 3.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_font_sdf](text/text_font_sdf.c) | <img src="text/text_font_sdf.png" alt="text_font_sdf" width="80"> | ⭐⭐⭐☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_format_text](text/text_format_text.c) | <img src="text/text_format_text.png" alt="text_format_text" width="80"> | ⭐☆☆☆ | 1.1 | 3.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_input_box](text/text_input_box.c) | <img src="text/text_input_box.png" alt="text_input_box" width="80"> | ⭐⭐☆☆ | 1.7 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_writing_anim](text/text_writing_anim.c) | <img src="text/text_writing_anim.png" alt="text_writing_anim" width="80"> | ⭐⭐☆☆ | 1.4 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_rectangle_bounds](text/text_rectangle_bounds.c) | <img src="text/text_rectangle_bounds.png" alt="text_rectangle_bounds" width="80"> | ⭐⭐⭐⭐️ | 2.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [text_unicode_emojis](text/text_unicode_emojis.c) | <img src="text/text_unicode_emojis.png" alt="text_unicode_emojis" width="80"> | ⭐⭐⭐⭐️ | 2.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [text_unicode_ranges](text/text_unicode_ranges.c) | <img src="text/text_unicode_ranges.png" alt="text_unicode_ranges" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Vadim Gunko](https://github.com/GuvaCode) |
|
||||
| [text_3d_drawing](text/text_3d_drawing.c) | <img src="text/text_3d_drawing.png" alt="text_3d_drawing" width="80"> | ⭐⭐⭐⭐️ | 3.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [text_codepoints_loading](text/text_codepoints_loading.c) | <img src="text/text_codepoints_loading.png" alt="text_codepoints_loading" width="80"> | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [text_inline_styling](text/text_inline_styling.c) | <img src="text/text_inline_styling.png" alt="text_inline_styling" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Wagner Barongello](https://github.com/SultansOfCode) |
|
||||
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
|
||||
| [text_strings_management](text/text_strings_management.c) | <img src="text/text_strings_management.png" alt="text_strings_management" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
|
||||
|
||||
### category: models [30]
|
||||
|
||||
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [models_loading_iqm](models/models_loading_iqm.c) | <img src="models/models_loading_iqm.png" alt="models_loading_iqm" width="80"> | ⭐⭐☆☆ | 2.5 | 3.5 | [Culacant](https://github.com/culacant) |
|
||||
| [models_billboard_rendering](models/models_billboard_rendering.c) | <img src="models/models_billboard_rendering.png" alt="models_billboard_rendering" width="80"> | ⭐⭐⭐☆ | 1.3 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_box_collisions](models/models_box_collisions.c) | <img src="models/models_box_collisions.png" alt="models_box_collisions" width="80"> | ⭐☆☆☆ | 1.3 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_cubicmap_rendering](models/models_cubicmap_rendering.c) | <img src="models/models_cubicmap_rendering.png" alt="models_cubicmap_rendering" width="80"> | ⭐⭐☆☆ | 1.8 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_first_person_maze](models/models_first_person_maze.c) | <img src="models/models_first_person_maze.png" alt="models_first_person_maze" width="80"> | ⭐⭐☆☆ | 2.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_geometric_shapes](models/models_geometric_shapes.c) | <img src="models/models_geometric_shapes.png" alt="models_geometric_shapes" width="80"> | ⭐☆☆☆ | 1.0 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_mesh_generation](models/models_mesh_generation.c) | <img src="models/models_mesh_generation.png" alt="models_mesh_generation" width="80"> | ⭐⭐☆☆ | 1.8 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_mesh_picking](models/models_mesh_picking.c) | <img src="models/models_mesh_picking.png" alt="models_mesh_picking" width="80"> | ⭐⭐⭐☆ | 1.7 | 4.0 | [Joel Davis](https://github.com/joeld42) |
|
||||
| [models_loading](models/models_loading.c) | <img src="models/models_loading.png" alt="models_loading" width="80"> | ⭐☆☆☆ | 2.0 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_loading_gltf](models/models_loading_gltf.c) | <img src="models/models_loading_gltf.png" alt="models_loading_gltf" width="80"> | ⭐☆☆☆ | 3.7 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_loading_vox](models/models_loading_vox.c) | <img src="models/models_loading_vox.png" alt="models_loading_vox" width="80"> | ⭐☆☆☆ | 4.0 | 4.0 | [Johann Nadalutti](https://github.com/procfxgen) |
|
||||
| [models_loading_m3d](models/models_loading_m3d.c) | <img src="models/models_loading_m3d.png" alt="models_loading_m3d" width="80"> | ⭐⭐☆☆ | 4.5 | 4.5 | [bzt](https://github.com/bztsrc) |
|
||||
| [models_orthographic_projection](models/models_orthographic_projection.c) | <img src="models/models_orthographic_projection.png" alt="models_orthographic_projection" width="80"> | ⭐☆☆☆ | 2.0 | 3.7 | [Max Danielsson](https://github.com/autious) |
|
||||
| [models_point_rendering](models/models_point_rendering.c) | <img src="models/models_point_rendering.png" alt="models_point_rendering" width="80"> | ⭐⭐⭐☆ | 5.0 | 5.0 | [Reese Gallagher](https://github.com/satchelfrost) |
|
||||
| [models_rlgl_solar_system](models/models_rlgl_solar_system.c) | <img src="models/models_rlgl_solar_system.png" alt="models_rlgl_solar_system" width="80"> | ⭐⭐⭐⭐️ | 2.5 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_yaw_pitch_roll](models/models_yaw_pitch_roll.c) | <img src="models/models_yaw_pitch_roll.png" alt="models_yaw_pitch_roll" width="80"> | ⭐⭐☆☆ | 1.8 | 4.0 | [Berni](https://github.com/Berni8k) |
|
||||
| [models_waving_cubes](models/models_waving_cubes.c) | <img src="models/models_waving_cubes.png" alt="models_waving_cubes" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.7 | [Codecat](https://github.com/codecat) |
|
||||
| [models_heightmap_rendering](models/models_heightmap_rendering.c) | <img src="models/models_heightmap_rendering.png" alt="models_heightmap_rendering" width="80"> | ⭐☆☆☆ | 1.8 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_skybox_rendering](models/models_skybox_rendering.c) | <img src="models/models_skybox_rendering.png" alt="models_skybox_rendering" width="80"> | ⭐⭐☆☆ | 1.8 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_textured_cube](models/models_textured_cube.c) | <img src="models/models_textured_cube.png" alt="models_textured_cube" width="80"> | ⭐⭐☆☆ | 4.5 | 4.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_animation_gpu_skinning](models/models_animation_gpu_skinning.c) | <img src="models/models_animation_gpu_skinning.png" alt="models_animation_gpu_skinning" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Daniel Holden](https://github.com/orangeduck) |
|
||||
| [models_bone_socket](models/models_bone_socket.c) | <img src="models/models_bone_socket.png" alt="models_bone_socket" width="80"> | ⭐⭐⭐⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) |
|
||||
| [models_tesseract_view](models/models_tesseract_view.c) | <img src="models/models_tesseract_view.png" alt="models_tesseract_view" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Timothy van der Valk](https://github.com/arceryz) |
|
||||
| [models_basic_voxel](models/models_basic_voxel.c) | <img src="models/models_basic_voxel.png" alt="models_basic_voxel" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) |
|
||||
| [models_rotating_cube](models/models_rotating_cube.c) | <img src="models/models_rotating_cube.png" alt="models_rotating_cube" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Jopestpe](https://github.com/jopestpe) |
|
||||
| [models_decals](models/models_decals.c) | <img src="models/models_decals.png" alt="models_decals" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
|
||||
| [models_directional_billboard](models/models_directional_billboard.c) | <img src="models/models_directional_billboard.png" alt="models_directional_billboard" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [models_animation_blend_custom](models/models_animation_blend_custom.c) | <img src="models/models_animation_blend_custom.png" alt="models_animation_blend_custom" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [dmitrii-brand](https://github.com/dmitrii-brand) |
|
||||
| [models_animation_blending](models/models_animation_blending.c) | <img src="models/models_animation_blending.png" alt="models_animation_blending" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
|
||||
| [models_animation_timing](models/models_animation_timing.c) | <img src="models/models_animation_timing.png" alt="models_animation_timing" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
|
||||
### category: shaders [35]
|
||||
|
||||
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.h) module.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [shaders_ascii_rendering](shaders/shaders_ascii_rendering.c) | <img src="shaders/shaders_ascii_rendering.png" alt="shaders_ascii_rendering" width="80"> | ⭐⭐☆☆ | 5.5 | 6.0 | [Maicon Santana](https://github.com/maiconpintoabreu) |
|
||||
| [shaders_basic_lighting](shaders/shaders_basic_lighting.c) | <img src="shaders/shaders_basic_lighting.png" alt="shaders_basic_lighting" width="80"> | ⭐⭐⭐⭐️ | 3.0 | 4.2 | [Chris Camacho](https://github.com/chriscamacho) |
|
||||
| [shaders_model_shader](shaders/shaders_model_shader.c) | <img src="shaders/shaders_model_shader.png" alt="shaders_model_shader" width="80"> | ⭐⭐☆☆ | 1.3 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_shapes_textures](shaders/shaders_shapes_textures.c) | <img src="shaders/shaders_shapes_textures.png" alt="shaders_shapes_textures" width="80"> | ⭐⭐☆☆ | 1.7 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_custom_uniform](shaders/shaders_custom_uniform.c) | <img src="shaders/shaders_custom_uniform.png" alt="shaders_custom_uniform" width="80"> | ⭐⭐☆☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_postprocessing](shaders/shaders_postprocessing.c) | <img src="shaders/shaders_postprocessing.png" alt="shaders_postprocessing" width="80"> | ⭐⭐⭐☆ | 1.3 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_palette_switch](shaders/shaders_palette_switch.c) | <img src="shaders/shaders_palette_switch.png" alt="shaders_palette_switch" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.7 | [Marco Lizza](https://github.com/MarcoLizza) |
|
||||
| [shaders_raymarching_rendering](shaders/shaders_raymarching_rendering.c) | <img src="shaders/shaders_raymarching_rendering.png" alt="shaders_raymarching_rendering" width="80"> | ⭐⭐⭐⭐️ | 2.0 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_texture_rendering](shaders/shaders_texture_rendering.c) | <img src="shaders/shaders_texture_rendering.png" alt="shaders_texture_rendering" width="80"> | ⭐⭐☆☆ | 2.0 | 3.7 | [Michał Ciesielski](https://github.com/ciessielski) |
|
||||
| [shaders_texture_outline](shaders/shaders_texture_outline.c) | <img src="shaders/shaders_texture_outline.png" alt="shaders_texture_outline" width="80"> | ⭐⭐⭐☆ | 4.0 | 4.0 | [Serenity Skiff](https://github.com/GoldenThumbs) |
|
||||
| [shaders_texture_waves](shaders/shaders_texture_waves.c) | <img src="shaders/shaders_texture_waves.png" alt="shaders_texture_waves" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) |
|
||||
| [shaders_julia_set](shaders/shaders_julia_set.c) | <img src="shaders/shaders_julia_set.png" alt="shaders_julia_set" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [Josh Colclough](https://github.com/joshcol9232) |
|
||||
| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | <img src="shaders/shaders_mandelbrot_set.png" alt="shaders_mandelbrot_set" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [shaders_color_correction](shaders/shaders_color_correction.c) | <img src="shaders/shaders_color_correction.png" alt="shaders_color_correction" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [shaders_eratosthenes_sieve](shaders/shaders_eratosthenes_sieve.c) | <img src="shaders/shaders_eratosthenes_sieve.png" alt="shaders_eratosthenes_sieve" width="80"> | ⭐⭐⭐☆ | 2.5 | 4.0 | [ProfJski](https://github.com/ProfJski) |
|
||||
| [shaders_fog_rendering](shaders/shaders_fog_rendering.c) | <img src="shaders/shaders_fog_rendering.png" alt="shaders_fog_rendering" width="80"> | ⭐⭐⭐☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
|
||||
| [shaders_simple_mask](shaders/shaders_simple_mask.c) | <img src="shaders/shaders_simple_mask.png" alt="shaders_simple_mask" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
|
||||
| [shaders_hot_reloading](shaders/shaders_hot_reloading.c) | <img src="shaders/shaders_hot_reloading.png" alt="shaders_hot_reloading" width="80"> | ⭐⭐⭐☆ | 3.0 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_mesh_instancing](shaders/shaders_mesh_instancing.c) | <img src="shaders/shaders_mesh_instancing.png" alt="shaders_mesh_instancing" width="80"> | ⭐⭐⭐⭐️ | 3.7 | 4.2 | [seanpringle](https://github.com/seanpringle) |
|
||||
| [shaders_multi_sample2d](shaders/shaders_multi_sample2d.c) | <img src="shaders/shaders_multi_sample2d.png" alt="shaders_multi_sample2d" width="80"> | ⭐⭐☆☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [shaders_normalmap_rendering](shaders/shaders_normalmap_rendering.c) | <img src="shaders/shaders_normalmap_rendering.png" alt="shaders_normalmap_rendering" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [Jeremy Montgomery](https://github.com/Sir_Irk) |
|
||||
| [shaders_spotlight_rendering](shaders/shaders_spotlight_rendering.c) | <img src="shaders/shaders_spotlight_rendering.png" alt="shaders_spotlight_rendering" width="80"> | ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
|
||||
| [shaders_deferred_rendering](shaders/shaders_deferred_rendering.c) | <img src="shaders/shaders_deferred_rendering.png" alt="shaders_deferred_rendering" width="80"> | ⭐⭐⭐⭐️ | 4.5 | 4.5 | [Justin Andreas Lacoste](https://github.com/27justin) |
|
||||
| [shaders_hybrid_rendering](shaders/shaders_hybrid_rendering.c) | <img src="shaders/shaders_hybrid_rendering.png" alt="shaders_hybrid_rendering" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
|
||||
| [shaders_texture_tiling](shaders/shaders_texture_tiling.c) | <img src="shaders/shaders_texture_tiling.png" alt="shaders_texture_tiling" width="80"> | ⭐⭐☆☆ | 4.5 | 4.5 | [Luis Almeida](https://github.com/luis605) |
|
||||
| [shaders_shadowmap_rendering](shaders/shaders_shadowmap_rendering.c) | <img src="shaders/shaders_shadowmap_rendering.png" alt="shaders_shadowmap_rendering" width="80"> | ⭐⭐⭐⭐️ | 5.0 | 5.0 | [TheManTheMythTheGameDev](https://github.com/TheManTheMythTheGameDev) |
|
||||
| [shaders_vertex_displacement](shaders/shaders_vertex_displacement.c) | <img src="shaders/shaders_vertex_displacement.png" alt="shaders_vertex_displacement" width="80"> | ⭐⭐⭐☆ | 5.0 | 4.5 | [Alex ZH](https://github.com/ZzzhHe) |
|
||||
| [shaders_depth_writing](shaders/shaders_depth_writing.c) | <img src="shaders/shaders_depth_writing.png" alt="shaders_depth_writing" width="80"> | ⭐⭐☆☆ | 4.2 | 4.2 | [Buğra Alptekin Sarı](https://github.com/BugraAlptekinSari) |
|
||||
| [shaders_basic_pbr](shaders/shaders_basic_pbr.c) | <img src="shaders/shaders_basic_pbr.png" alt="shaders_basic_pbr" width="80"> | ⭐⭐⭐⭐️ | 5.0 | 5.5 | [Afan OLOVCIC](https://github.com/_DevDad) |
|
||||
| [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | <img src="shaders/shaders_lightmap_rendering.png" alt="shaders_lightmap_rendering" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) |
|
||||
| [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
|
||||
| [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | <img src="shaders/shaders_depth_rendering.png" alt="shaders_depth_rendering" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Luís Almeida](https://github.com/luis605) |
|
||||
| [shaders_game_of_life](shaders/shaders_game_of_life.c) | <img src="shaders/shaders_game_of_life.png" alt="shaders_game_of_life" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [shaders_rlgl_compute](shaders/shaders_rlgl_compute.c) | <img src="shaders/shaders_rlgl_compute.png" alt="shaders_rlgl_compute" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
|
||||
| [shaders_cel_shading](shaders/shaders_cel_shading.c) | <img src="shaders/shaders_cel_shading.png" alt="shaders_cel_shading" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Gleb A](https://github.com/ggrizzly) |
|
||||
|
||||
### category: audio [10]
|
||||
|
||||
Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib.
|
||||
|
||||
| example | image | difficulty<br>level | version<br>created | last version<br>updated | original<br>developer |
|
||||
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
|
||||
| [audio_module_playing](audio/audio_module_playing.c) | <img src="audio/audio_module_playing.png" alt="audio_module_playing" width="80"> | ⭐☆☆☆ | 1.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [audio_music_stream](audio/audio_music_stream.c) | <img src="audio/audio_music_stream.png" alt="audio_music_stream" width="80"> | ⭐☆☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [audio_raw_stream](audio/audio_raw_stream.c) | <img src="audio/audio_raw_stream.png" alt="audio_raw_stream" width="80"> | ⭐⭐⭐☆ | 1.6 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [audio_sound_loading](audio/audio_sound_loading.c) | <img src="audio/audio_sound_loading.png" alt="audio_sound_loading" width="80"> | ⭐☆☆☆ | 1.1 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [audio_mixed_processor](audio/audio_mixed_processor.c) | <img src="audio/audio_mixed_processor.png" alt="audio_mixed_processor" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
|
||||
| [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
|
||||
| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [IANN](https://github.com/meisei4) |
|
||||
| [audio_stream_callback](audio/audio_stream_callback.c) | <img src="audio/audio_stream_callback.png" alt="audio_stream_callback" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Dan Hoang](https://github.com/dan-hoang) |
|
||||
|
||||
Some example missing? As always, contributions are welcome, feel free to send new examples!
|
||||
Here is an [examples template](examples_template.c) with instructions to start with!
|
||||
@ -0,0 +1,238 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - amp envelope
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Arbinda Rizki Muhammad (@arbipink) 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) 2026 Arbinda Rizki Muhammad (@arbipink)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#include <math.h> // Required for: sinf()
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
#define SAMPLE_RATE 44100
|
||||
|
||||
// Wave state
|
||||
typedef enum {
|
||||
IDLE,
|
||||
ATTACK,
|
||||
DECAY,
|
||||
SUSTAIN,
|
||||
RELEASE
|
||||
} ADSRState;
|
||||
|
||||
// Grouping all ADSR parameters and state into a struct
|
||||
typedef struct {
|
||||
float attackTime;
|
||||
float decayTime;
|
||||
float sustainLevel;
|
||||
float releaseTime;
|
||||
float currentValue;
|
||||
ADSRState state;
|
||||
} Envelope;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime);
|
||||
static void UpdateEnvelope(Envelope *env);
|
||||
static void DrawADSRGraph(Envelope *env, Rectangle bounds);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - amp envelope");
|
||||
|
||||
InitAudioDevice();
|
||||
|
||||
// Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE
|
||||
SetAudioStreamBufferSizeDefault(BUFFER_SIZE);
|
||||
float buffer[BUFFER_SIZE] = { 0 };
|
||||
|
||||
// Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono)
|
||||
AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1);
|
||||
|
||||
// Init Phase
|
||||
float audioTime = 0.0f;
|
||||
|
||||
// Initialize the struct
|
||||
Envelope env = {
|
||||
.attackTime = 1.0f,
|
||||
.decayTime = 1.0f,
|
||||
.sustainLevel = 0.5f,
|
||||
.releaseTime = 1.0f,
|
||||
.currentValue = 0.0f,
|
||||
.state = IDLE
|
||||
};
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK;
|
||||
|
||||
if (IsKeyReleased(KEY_SPACE) && (env.state != IDLE)) env.state = RELEASE;
|
||||
|
||||
if (IsAudioStreamProcessed(stream))
|
||||
{
|
||||
if ((env.state != IDLE) || (env.currentValue > 0.0f))
|
||||
{
|
||||
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||
{
|
||||
UpdateEnvelope(&env);
|
||||
FillAudioBuffer(i, buffer, env.currentValue, &audioTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear buffer if silent to avoid looping noise
|
||||
for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0;
|
||||
audioTime = 0.0f;
|
||||
}
|
||||
|
||||
UpdateAudioStream(stream, buffer, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
if (!IsAudioStreamPlaying(stream)) PlayAudioStream(stream);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
GuiSliderBar((Rectangle){ 100, 60, 400, 30 }, "Attack (s)", TextFormat("%2.2fs", env.attackTime), &env.attackTime, 0.1f, 3.0f);
|
||||
GuiSliderBar((Rectangle){ 100, 100, 400, 30 }, "Decay (s)", TextFormat("%2.2fs", env.decayTime), &env.decayTime, 0.1f, 3.0f);
|
||||
GuiSliderBar((Rectangle){ 100, 140, 400, 30 }, "Sustain", TextFormat("%2.2f", env.sustainLevel), &env.sustainLevel, 0.0f, 1.0f);
|
||||
GuiSliderBar((Rectangle){ 100, 180, 400, 30 }, "Release (s)", TextFormat("%2.2fs", env.releaseTime), &env.releaseTime, 0.1f, 3.0f);
|
||||
|
||||
DrawADSRGraph(&env, (Rectangle){ 100, 250, 400, 100 });
|
||||
|
||||
DrawCircleV((Vector2){ 520, 350 - (env.currentValue * 100) }, 5, MAROON);
|
||||
DrawText(TextFormat("Current Gain: %2.2f", env.currentValue), 535, 345 - (env.currentValue * 100), 10, MAROON);
|
||||
|
||||
DrawText("Press SPACE to PLAY the sound!", 200, 400, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadAudioStream(stream);
|
||||
CloseAudioDevice();
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime)
|
||||
{
|
||||
int frequency = 440;
|
||||
buffer[i] = envelopeValue*sinf(2.0f*PI*frequency*(*audioTime));
|
||||
*audioTime += (1.0f/SAMPLE_RATE);
|
||||
}
|
||||
|
||||
static void UpdateEnvelope(Envelope *env)
|
||||
{
|
||||
// Calculate the time delta for ONE sample (1/44100)
|
||||
float sampleTime = 1.0f/SAMPLE_RATE;
|
||||
|
||||
switch(env->state)
|
||||
{
|
||||
case ATTACK:
|
||||
{
|
||||
env->currentValue += (1.0f/env->attackTime)*sampleTime;
|
||||
if (env->currentValue >= 1.0f)
|
||||
{
|
||||
env->currentValue = 1.0f;
|
||||
env->state = DECAY;
|
||||
}
|
||||
|
||||
} break;
|
||||
case DECAY:
|
||||
{
|
||||
env->currentValue -= ((1.0f - env->sustainLevel)/env->decayTime)*sampleTime;
|
||||
if (env->currentValue <= env->sustainLevel)
|
||||
{
|
||||
env->currentValue = env->sustainLevel;
|
||||
env->state = SUSTAIN;
|
||||
}
|
||||
|
||||
} break;
|
||||
case SUSTAIN:
|
||||
{
|
||||
env->currentValue = env->sustainLevel;
|
||||
|
||||
} break;
|
||||
case RELEASE:
|
||||
{
|
||||
env->currentValue -= (env->sustainLevel/env->releaseTime)*sampleTime;
|
||||
if (env->currentValue <= 0.001f) // Use a small threshold to avoid infinite tail
|
||||
{
|
||||
env->currentValue = 0.0f;
|
||||
env->state = IDLE;
|
||||
}
|
||||
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawADSRGraph(Envelope *env, Rectangle bounds)
|
||||
{
|
||||
DrawRectangleRec(bounds, Fade(LIGHTGRAY, 0.3f));
|
||||
DrawRectangleLinesEx(bounds, 1, GRAY);
|
||||
|
||||
// Fixed visual width for sustain stage since it's an amplitude not a time value
|
||||
float sustainWidth = 1.0f;
|
||||
|
||||
// Total time to visualize (sum of A, D, R + a padding for Sustain)
|
||||
float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime;
|
||||
|
||||
float scaleX = bounds.width/totalTime;
|
||||
float scaleY = bounds.height;
|
||||
|
||||
Vector2 start = { bounds.x, bounds.y + bounds.height };
|
||||
Vector2 peak = { start.x + (env->attackTime*scaleX), bounds.y };
|
||||
Vector2 sustain = { peak.x + (env->decayTime*scaleX), bounds.y + (1.0f - env->sustainLevel)*scaleY };
|
||||
Vector2 rel = { sustain.x + (sustainWidth*scaleX), sustain.y };
|
||||
Vector2 end = { rel.x + (env->releaseTime*scaleX), bounds.y + bounds.height };
|
||||
|
||||
DrawLineV(start, peak, SKYBLUE);
|
||||
DrawLineV(peak, sustain, BLUE);
|
||||
DrawLineV(sustain, rel, DARKBLUE);
|
||||
DrawLineV(rel, end, ORANGE);
|
||||
|
||||
DrawText("ADSR Visualizer", bounds.x, bounds.y - 20, 10, DARKGRAY);
|
||||
}
|
||||
|
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,125 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - mixed processor
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
* Example contributed by hkc (@hatkidchan) 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) 2023-2025 hkc (@hatkidchan)
|
||||
*
|
||||
********************************************************************************************/
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
static float exponent = 1.0f; // Audio exponentiation value
|
||||
static float averageVolume[400] = { 0.0f }; // Average volume history
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Audio processing function
|
||||
//------------------------------------------------------------------------------------
|
||||
void ProcessAudio(void *buffer, unsigned int frames)
|
||||
{
|
||||
float *samples = (float *)buffer; // Samples internally stored as <float>s
|
||||
float average = 0.0f; // Temporary average volume
|
||||
|
||||
for (unsigned int frame = 0; frame < frames; frame++)
|
||||
{
|
||||
float *left = &samples[frame*2 + 0], *right = &samples[frame*2 + 1];
|
||||
|
||||
*left = powf(fabsf(*left), exponent)*( (*left < 0.0f)? -1.0f : 1.0f );
|
||||
*right = powf(fabsf(*right), exponent)*( (*right < 0.0f)? -1.0f : 1.0f );
|
||||
|
||||
average += fabsf(*left)/frames; // accumulating average volume
|
||||
average += fabsf(*right)/frames;
|
||||
}
|
||||
|
||||
// Moving history to the left
|
||||
for (int i = 0; i < 399; i++) averageVolume[i] = averageVolume[i + 1];
|
||||
|
||||
averageVolume[399] = average; // Adding last average value
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - mixed processor");
|
||||
|
||||
InitAudioDevice(); // Initialize audio device
|
||||
|
||||
AttachAudioMixedProcessor(ProcessAudio);
|
||||
|
||||
Music music = LoadMusicStream("resources/country.mp3");
|
||||
Sound sound = LoadSound("resources/coin.wav");
|
||||
|
||||
PlayMusicStream(music);
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateMusicStream(music); // Update music buffer with new stream data
|
||||
|
||||
// Modify processing variables
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_LEFT)) exponent -= 0.05f;
|
||||
if (IsKeyPressed(KEY_RIGHT)) exponent += 0.05f;
|
||||
|
||||
if (exponent <= 0.5f) exponent = 0.5f;
|
||||
if (exponent >= 3.0f) exponent = 3.0f;
|
||||
|
||||
if (IsKeyPressed(KEY_SPACE)) PlaySound(sound);
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY);
|
||||
|
||||
DrawText(TextFormat("EXPONENT = %.2f", exponent), 215, 180, 20, LIGHTGRAY);
|
||||
|
||||
DrawRectangle(199, 199, 402, 34, LIGHTGRAY);
|
||||
for (int i = 0; i < 400; i++)
|
||||
{
|
||||
DrawLine(201 + i, 232 - (int)(averageVolume[i]*32), 201 + i, 232, MAROON);
|
||||
}
|
||||
DrawRectangleLines(199, 199, 402, 34, GRAY);
|
||||
|
||||
DrawText("PRESS SPACE TO PLAY OTHER SOUND", 200, 250, 20, LIGHTGRAY);
|
||||
DrawText("USE LEFT AND RIGHT ARROWS TO ALTER DISTORTION", 140, 280, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
|
||||
DetachAudioMixedProcessor(ProcessAudio); // Disconnect audio processor
|
||||
|
||||
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
@ -0,0 +1,162 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - module playing
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.5, last time updated with raylib 3.5
|
||||
*
|
||||
* 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) 2016-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define MAX_CIRCLES 64
|
||||
|
||||
typedef struct {
|
||||
Vector2 position;
|
||||
float radius;
|
||||
float alpha;
|
||||
float speed;
|
||||
Color color;
|
||||
} CircleWave;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT); // NOTE: Try to enable MSAA 4X
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - module playing");
|
||||
|
||||
InitAudioDevice(); // Initialize audio device
|
||||
|
||||
Color colors[14] = { ORANGE, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK,
|
||||
YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE };
|
||||
|
||||
// Creates some circles for visual effect
|
||||
CircleWave circles[MAX_CIRCLES] = { 0 };
|
||||
|
||||
for (int i = MAX_CIRCLES - 1; i >= 0; i--)
|
||||
{
|
||||
circles[i].alpha = 0.0f;
|
||||
circles[i].radius = (float)GetRandomValue(10, 40);
|
||||
circles[i].position.x = (float)GetRandomValue((int)circles[i].radius, (int)(screenWidth - circles[i].radius));
|
||||
circles[i].position.y = (float)GetRandomValue((int)circles[i].radius, (int)(screenHeight - circles[i].radius));
|
||||
circles[i].speed = (float)GetRandomValue(1, 100)/2000.0f;
|
||||
circles[i].color = colors[GetRandomValue(0, 13)];
|
||||
}
|
||||
|
||||
Music music = LoadMusicStream("resources/mini1111.xm");
|
||||
music.looping = false;
|
||||
float pitch = 1.0f;
|
||||
|
||||
PlayMusicStream(music);
|
||||
|
||||
float timePlayed = 0.0f;
|
||||
bool pause = false;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateMusicStream(music); // Update music buffer with new stream data
|
||||
|
||||
// Restart music playing (stop and play)
|
||||
if (IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
StopMusicStream(music);
|
||||
PlayMusicStream(music);
|
||||
pause = false;
|
||||
}
|
||||
|
||||
// Pause/Resume music playing
|
||||
if (IsKeyPressed(KEY_P))
|
||||
{
|
||||
pause = !pause;
|
||||
|
||||
if (pause) PauseMusicStream(music);
|
||||
else ResumeMusicStream(music);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_DOWN)) pitch -= 0.01f;
|
||||
else if (IsKeyDown(KEY_UP)) pitch += 0.01f;
|
||||
|
||||
SetMusicPitch(music, pitch);
|
||||
|
||||
// Get timePlayed scaled to bar dimensions
|
||||
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*(screenWidth - 40);
|
||||
|
||||
// Color circles animation
|
||||
for (int i = MAX_CIRCLES - 1; (i >= 0) && !pause; i--)
|
||||
{
|
||||
circles[i].alpha += circles[i].speed;
|
||||
circles[i].radius += circles[i].speed*10.0f;
|
||||
|
||||
if (circles[i].alpha > 1.0f) circles[i].speed *= -1;
|
||||
|
||||
if (circles[i].alpha <= 0.0f)
|
||||
{
|
||||
circles[i].alpha = 0.0f;
|
||||
circles[i].radius = (float)GetRandomValue(10, 40);
|
||||
circles[i].position.x = (float)GetRandomValue((int)circles[i].radius, (int)(screenWidth - circles[i].radius));
|
||||
circles[i].position.y = (float)GetRandomValue((int)circles[i].radius, (int)(screenHeight - circles[i].radius));
|
||||
circles[i].color = colors[GetRandomValue(0, 13)];
|
||||
circles[i].speed = (float)GetRandomValue(1, 100)/2000.0f;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
for (int i = MAX_CIRCLES - 1; i >= 0; i--)
|
||||
{
|
||||
DrawCircleV(circles[i].position, circles[i].radius, Fade(circles[i].color, circles[i].alpha));
|
||||
}
|
||||
|
||||
// Draw time bar
|
||||
DrawRectangle(20, screenHeight - 20 - 12, screenWidth - 40, 12, LIGHTGRAY);
|
||||
DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON);
|
||||
DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, GRAY);
|
||||
|
||||
// Draw help instructions
|
||||
DrawRectangle(20, 20, 425, 145, WHITE);
|
||||
DrawRectangleLines(20, 20, 425, 145, GRAY);
|
||||
DrawText("PRESS SPACE TO RESTART MUSIC", 40, 40, 20, BLACK);
|
||||
DrawText("PRESS P TO PAUSE/RESUME", 40, 70, 20, BLACK);
|
||||
DrawText("PRESS UP/DOWN TO CHANGE SPEED", 40, 100, 20, BLACK);
|
||||
DrawText(TextFormat("SPEED: %f", pitch), 40, 130, 20, MAROON);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
|
||||
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 44 KiB |
@ -0,0 +1,144 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - music stream
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.2
|
||||
*
|
||||
* 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - music stream");
|
||||
|
||||
InitAudioDevice(); // Initialize audio device
|
||||
|
||||
Music music = LoadMusicStream("resources/country.mp3");
|
||||
|
||||
PlayMusicStream(music);
|
||||
|
||||
float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f]
|
||||
bool pause = false; // Music playing paused
|
||||
|
||||
float pan = 0.0f; // Default audio pan center [-1.0f..1.0f]
|
||||
SetMusicPan(music, pan);
|
||||
|
||||
float volume = 0.8f; // Default audio volume [0.0f..1.0f]
|
||||
SetMusicVolume(music, volume);
|
||||
|
||||
SetTargetFPS(30); // Set our game to run at 30 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateMusicStream(music); // Update music buffer with new stream data
|
||||
|
||||
// Restart music playing (stop and play)
|
||||
if (IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
StopMusicStream(music);
|
||||
PlayMusicStream(music);
|
||||
}
|
||||
|
||||
// Pause/Resume music playing
|
||||
if (IsKeyPressed(KEY_P))
|
||||
{
|
||||
pause = !pause;
|
||||
|
||||
if (pause) PauseMusicStream(music);
|
||||
else ResumeMusicStream(music);
|
||||
}
|
||||
|
||||
// Set audio pan
|
||||
if (IsKeyDown(KEY_LEFT))
|
||||
{
|
||||
pan -= 0.05f;
|
||||
if (pan < -1.0f) pan = -1.0f;
|
||||
SetMusicPan(music, pan);
|
||||
}
|
||||
else if (IsKeyDown(KEY_RIGHT))
|
||||
{
|
||||
pan += 0.05f;
|
||||
if (pan > 1.0f) pan = 1.0f;
|
||||
SetMusicPan(music, pan);
|
||||
}
|
||||
|
||||
// Set audio volume
|
||||
if (IsKeyDown(KEY_DOWN))
|
||||
{
|
||||
volume -= 0.05f;
|
||||
if (volume < 0.0f) volume = 0.0f;
|
||||
SetMusicVolume(music, volume);
|
||||
}
|
||||
else if (IsKeyDown(KEY_UP))
|
||||
{
|
||||
volume += 0.05f;
|
||||
if (volume > 1.0f) volume = 1.0f;
|
||||
SetMusicVolume(music, volume);
|
||||
}
|
||||
|
||||
// Get normalized time played for current music stream
|
||||
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music);
|
||||
|
||||
if (timePlayed > 1.0f) timePlayed = 1.0f; // Make sure time played is no longer than music
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY);
|
||||
|
||||
DrawText("LEFT-RIGHT for PAN CONTROL", 320, 74, 10, DARKBLUE);
|
||||
DrawRectangle(300, 100, 200, 12, LIGHTGRAY);
|
||||
DrawRectangleLines(300, 100, 200, 12, GRAY);
|
||||
DrawRectangle((int)(300 + (pan + 1.0f)/2.0f*200 - 5), 92, 10, 28, DARKGRAY);
|
||||
|
||||
DrawRectangle(200, 200, 400, 12, LIGHTGRAY);
|
||||
DrawRectangle(200, 200, (int)(timePlayed*400.0f), 12, MAROON);
|
||||
DrawRectangleLines(200, 200, 400, 12, GRAY);
|
||||
|
||||
DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY);
|
||||
DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY);
|
||||
|
||||
DrawText("UP-DOWN for VOLUME CONTROL", 320, 334, 10, DARKGREEN);
|
||||
DrawRectangle(300, 360, 200, 12, LIGHTGRAY);
|
||||
DrawRectangleLines(300, 360, 200, 12, GRAY);
|
||||
DrawRectangle((int)(300 + volume*200 - 5), 352, 10, 28, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
|
||||
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,146 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - raw stream
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 1.6, last time updated with raylib 6.0
|
||||
*
|
||||
* Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox)
|
||||
*
|
||||
* 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) 2015-2026 Ramon Santamaria (@raysan5) and James Hofmann (@triplefox)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
#define SAMPLE_RATE 44100
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw stream");
|
||||
|
||||
InitAudioDevice();
|
||||
|
||||
// Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE
|
||||
SetAudioStreamBufferSizeDefault(BUFFER_SIZE);
|
||||
float buffer[BUFFER_SIZE] = {};
|
||||
|
||||
// Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono)
|
||||
AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1);
|
||||
float pan = 0.0f;
|
||||
SetAudioStreamPan(stream, pan);
|
||||
PlayAudioStream(stream);
|
||||
|
||||
int sineFrequency = 440;
|
||||
int newSineFrequency = 440;
|
||||
int sineIndex = 0;
|
||||
double sineStartTime = 0.0;
|
||||
|
||||
SetTargetFPS(30);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
if (IsKeyDown(KEY_UP))
|
||||
{
|
||||
newSineFrequency += 10;
|
||||
if (newSineFrequency > 12500) newSineFrequency = 12500;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_DOWN))
|
||||
{
|
||||
newSineFrequency -= 10;
|
||||
if (newSineFrequency < 20) newSineFrequency = 20;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_LEFT))
|
||||
{
|
||||
pan -= 0.01f;
|
||||
if (pan < -1.0f) pan = -1.0f;
|
||||
SetAudioStreamPan(stream, pan);
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_RIGHT))
|
||||
{
|
||||
pan += 0.01f;
|
||||
if (pan > 1.0f) pan = 1.0f;
|
||||
SetAudioStreamPan(stream, pan);
|
||||
}
|
||||
|
||||
if (IsAudioStreamProcessed(stream))
|
||||
{
|
||||
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||
{
|
||||
int wavelength = SAMPLE_RATE/sineFrequency;
|
||||
buffer[i] = sin(2*PI*sineIndex/wavelength);
|
||||
sineIndex++;
|
||||
|
||||
if (sineIndex >= wavelength)
|
||||
{
|
||||
sineFrequency = newSineFrequency;
|
||||
sineIndex = 0;
|
||||
sineStartTime = GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAudioStream(stream, buffer, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText(TextFormat("sine frequency: %i", sineFrequency), screenWidth - 220, 10, 20, RED);
|
||||
DrawText(TextFormat("pan: %.2f", pan), screenWidth - 220, 30, 20, RED);
|
||||
DrawText("Up/down to change frequency", 10, 10, 20, DARKGRAY);
|
||||
DrawText("Left/right to pan", 10, 30, 20, DARKGRAY);
|
||||
|
||||
int windowStart = (GetTime() - sineStartTime)*SAMPLE_RATE;
|
||||
int windowSize = 0.1f*SAMPLE_RATE;
|
||||
int wavelength = SAMPLE_RATE/sineFrequency;
|
||||
|
||||
// Draw a sine wave with the same frequency as the one being sent to the audio stream
|
||||
for (int i = 0; i < screenWidth; i++)
|
||||
{
|
||||
int t0 = windowStart + i*windowSize/screenWidth;
|
||||
int t1 = windowStart + (i + 1)*windowSize/screenWidth;
|
||||
Vector2 startPos = { i, 250 + 50*sin(2*PI*t0/wavelength) };
|
||||
Vector2 endPos = { i + 1, 250 + 50*sin(2*PI*t1/wavelength) };
|
||||
DrawLineV(startPos, endPos, RED);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadAudioStream(stream); // Close raw audio stream and delete buffers from RAM
|
||||
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,71 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - sound loading
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.1, last time updated with raylib 3.5
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - sound loading");
|
||||
|
||||
InitAudioDevice(); // Initialize audio device
|
||||
|
||||
Sound fxWav = LoadSound("resources/sound.wav"); // Load WAV audio file
|
||||
Sound fxOgg = LoadSound("resources/target.ogg"); // Load OGG audio file
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_SPACE)) PlaySound(fxWav); // Play WAV sound
|
||||
if (IsKeyPressed(KEY_ENTER)) PlaySound(fxOgg); // Play OGG sound
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Press SPACE to PLAY the WAV sound!", 200, 180, 20, LIGHTGRAY);
|
||||
DrawText("Press ENTER to PLAY the OGG sound!", 200, 220, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadSound(fxWav); // Unload sound data
|
||||
UnloadSound(fxOgg); // Unload sound data
|
||||
|
||||
CloseAudioDevice(); // Close audio device
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,91 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - sound multi
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example contributed by Jeffery Myers (@JeffM2501) 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) 2023-2025 Jeffery Myers (@JeffM2501)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define MAX_SOUNDS 10
|
||||
Sound soundArray[MAX_SOUNDS] = { 0 };
|
||||
int currentSound;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - sound multi");
|
||||
|
||||
InitAudioDevice(); // Initialize audio device
|
||||
|
||||
// Load audio file into the first slot as the 'source' sound,
|
||||
// this sound owns the sample data
|
||||
soundArray[0] = LoadSound("resources/sound.wav");
|
||||
|
||||
// Load an alias of the sound into slots 1-9. These do not own the sound data, but can be played
|
||||
for (int i = 1; i < MAX_SOUNDS; i++) soundArray[i] = LoadSoundAlias(soundArray[0]);
|
||||
|
||||
currentSound = 0; // Set the sound list to the start
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
PlaySound(soundArray[currentSound]); // Play the next open sound slot
|
||||
currentSound++; // Increment the sound slot
|
||||
|
||||
// If the sound slot is out of bounds, go back to 0
|
||||
if (currentSound >= MAX_SOUNDS) currentSound = 0;
|
||||
|
||||
// NOTE: Another approach would be to look at the list for the first sound
|
||||
// that is not playing and use that slot
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Press SPACE to PLAY a WAV sound!", 200, 180, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
for (int i = 1; i < MAX_SOUNDS; i++) UnloadSoundAlias(soundArray[i]); // Unload sound aliases
|
||||
UnloadSound(soundArray[0]); // Unload source sound data
|
||||
|
||||
CloseAudioDevice(); // Close audio device
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,131 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - sound positioning
|
||||
*
|
||||
* 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 "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void SetSoundPosition(Camera listener, Sound sound, Vector3 position, float maxDist);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - sound positioning");
|
||||
|
||||
InitAudioDevice();
|
||||
|
||||
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,
|
||||
.projection = CAMERA_PERSPECTIVE
|
||||
};
|
||||
|
||||
DisableCursor();
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera, CAMERA_FREE);
|
||||
|
||||
float th = (float)GetTime();
|
||||
|
||||
Vector3 spherePos = {
|
||||
.x = 5.0f*cosf(th),
|
||||
.y = 0.0f,
|
||||
.z = 5.0f*sinf(th)
|
||||
};
|
||||
|
||||
SetSoundPosition(camera, sound, spherePos, 1.0f);
|
||||
|
||||
if (!IsSoundPlaying(sound)) PlaySound(sound);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawGrid(10, 2);
|
||||
DrawSphere(spherePos, 0.5f, RED);
|
||||
EndMode3D();
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadSound(sound);
|
||||
CloseAudioDevice(); // Close audio device
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
// Set sound 3d position
|
||||
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(listener.up, forward));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,285 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - spectrum visualizer
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Inspired by Inigo Quilez's https://www.shadertoy.com/
|
||||
* Resources/specification: https://gist.github.com/soulthreads/2efe50da4be1fb5f7ab60ff14ca434b8
|
||||
*
|
||||
* Example created by created by IANN (@meisei4) 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 IANN (@meisei4)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#define GLSL_VERSION 330
|
||||
#else // PLATFORM_ANDROID, PLATFORM_WEB
|
||||
#define GLSL_VERSION 100
|
||||
#endif
|
||||
|
||||
#define MONO 1
|
||||
#define SAMPLE_RATE 44100
|
||||
#define SAMPLE_RATE_F 44100.0f
|
||||
#define FFT_WINDOW_SIZE 1024
|
||||
#define BUFFER_SIZE 512
|
||||
#define PER_SAMPLE_BIT_DEPTH 16
|
||||
#define AUDIO_STREAM_RING_BUFFER_SIZE (FFT_WINDOW_SIZE*2)
|
||||
#define EFFECTIVE_SAMPLE_RATE (SAMPLE_RATE_F*0.5f)
|
||||
#define WINDOW_TIME ((double)FFT_WINDOW_SIZE/(double)EFFECTIVE_SAMPLE_RATE)
|
||||
#define FFT_HISTORICAL_SMOOTHING_DUR 2.0f
|
||||
#define MIN_DECIBELS (-100.0f) // https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/minDecibels
|
||||
#define MAX_DECIBELS (-30.0f) // https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/maxDecibels
|
||||
#define INVERSE_DECIBEL_RANGE (1.0f/(MAX_DECIBELS - MIN_DECIBELS))
|
||||
#define DB_TO_LINEAR_SCALE (20.0f/2.302585092994046f)
|
||||
#define SMOOTHING_TIME_CONSTANT 0.8f // https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/smoothingTimeConstant
|
||||
#define TEXTURE_HEIGHT 1
|
||||
#define FFT_ROW 0
|
||||
#define UNUSED_CHANNEL 0.0f
|
||||
|
||||
typedef struct FFTComplex { float real, imaginary; } FFTComplex;
|
||||
|
||||
typedef struct FFTData {
|
||||
FFTComplex *spectrum;
|
||||
FFTComplex *workBuffer;
|
||||
float *prevMagnitudes;
|
||||
float (*fftHistory)[BUFFER_SIZE];
|
||||
int fftHistoryLen;
|
||||
int historyPos;
|
||||
double lastFftTime;
|
||||
float tapbackPos;
|
||||
} FFTData;
|
||||
|
||||
static void CaptureFrame(FFTData *fftData, const float *audioSamples);
|
||||
static void RenderFrame(const FFTData *fftData, Image *fftImage);
|
||||
static void CooleyTukeyFFTSlow(FFTComplex *spectrum, int n);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//----------------------------------------------------------------------------------- ---
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - spectrum visualizer");
|
||||
|
||||
Image fftImage = GenImageColor(BUFFER_SIZE, TEXTURE_HEIGHT, WHITE);
|
||||
Texture2D fftTexture = LoadTextureFromImage(fftImage);
|
||||
RenderTexture2D bufferA = LoadRenderTexture(screenWidth, screenHeight);
|
||||
Vector2 iResolution = { (float)screenWidth, (float)screenHeight };
|
||||
|
||||
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/fft.fs", GLSL_VERSION));
|
||||
|
||||
int iResolutionLocation = GetShaderLocation(shader, "iResolution");
|
||||
int iChannel0Location = GetShaderLocation(shader, "iChannel0");
|
||||
SetShaderValue(shader, iResolutionLocation, &iResolution, SHADER_UNIFORM_VEC2);
|
||||
SetShaderValueTexture(shader, iChannel0Location, fftTexture);
|
||||
|
||||
InitAudioDevice();
|
||||
SetAudioStreamBufferSizeDefault(AUDIO_STREAM_RING_BUFFER_SIZE);
|
||||
|
||||
// WARNING: Memory out-of-bounds on PLATFORM_WEB
|
||||
Wave wav = LoadWave("resources/country.mp3");
|
||||
WaveFormat(&wav, SAMPLE_RATE, PER_SAMPLE_BIT_DEPTH, MONO);
|
||||
|
||||
AudioStream audioStream = LoadAudioStream(SAMPLE_RATE, PER_SAMPLE_BIT_DEPTH, MONO);
|
||||
PlayAudioStream(audioStream);
|
||||
|
||||
int fftHistoryLen = (int)ceilf(FFT_HISTORICAL_SMOOTHING_DUR/WINDOW_TIME) + 1;
|
||||
|
||||
FFTData fft = {
|
||||
.spectrum = RL_CALLOC(sizeof(FFTComplex), FFT_WINDOW_SIZE),
|
||||
.workBuffer = RL_CALLOC(sizeof(FFTComplex), FFT_WINDOW_SIZE),
|
||||
.prevMagnitudes = RL_CALLOC(BUFFER_SIZE, sizeof(float)),
|
||||
.fftHistory = RL_CALLOC(fftHistoryLen, sizeof(float[BUFFER_SIZE])),
|
||||
.fftHistoryLen = fftHistoryLen,
|
||||
.historyPos = 0,
|
||||
.lastFftTime = 0.0,
|
||||
.tapbackPos = 0.01f
|
||||
};
|
||||
|
||||
unsigned int wavCursor = 0;
|
||||
const short *wavPCM16 = wav.data;
|
||||
|
||||
short chunkSamples[AUDIO_STREAM_RING_BUFFER_SIZE] = { 0 };
|
||||
float audioSamples[FFT_WINDOW_SIZE] = { 0 };
|
||||
|
||||
SetTargetFPS(60);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
while (IsAudioStreamProcessed(audioStream))
|
||||
{
|
||||
for (int i = 0; i < AUDIO_STREAM_RING_BUFFER_SIZE; i++)
|
||||
{
|
||||
int left = (wav.channels == 2)? wavPCM16[wavCursor*2 + 0] : wavPCM16[wavCursor];
|
||||
int right = (wav.channels == 2)? wavPCM16[wavCursor*2 + 1] : left;
|
||||
chunkSamples[i] = (short)((left + right)/2);
|
||||
|
||||
if (++wavCursor >= wav.frameCount) wavCursor = 0;
|
||||
}
|
||||
|
||||
UpdateAudioStream(audioStream, chunkSamples, AUDIO_STREAM_RING_BUFFER_SIZE);
|
||||
|
||||
for (int i = 0; i < FFT_WINDOW_SIZE; i++) audioSamples[i] = (chunkSamples[i*2] + chunkSamples[i*2 + 1])*0.5f/32767.0f;
|
||||
}
|
||||
|
||||
CaptureFrame(&fft, audioSamples);
|
||||
RenderFrame(&fft, &fftImage);
|
||||
UpdateTexture(fftTexture, fftImage.data);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginShaderMode(shader);
|
||||
SetShaderValueTexture(shader, iChannel0Location, fftTexture);
|
||||
DrawTextureRec(bufferA.texture,
|
||||
(Rectangle){ 0, 0, (float)screenWidth, (float)-screenHeight },
|
||||
(Vector2){ 0, 0 }, WHITE);
|
||||
EndShaderMode();
|
||||
|
||||
EndDrawing();
|
||||
//------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(shader);
|
||||
UnloadRenderTexture(bufferA);
|
||||
UnloadTexture(fftTexture);
|
||||
UnloadImage(fftImage);
|
||||
UnloadAudioStream(audioStream);
|
||||
UnloadWave(wav);
|
||||
CloseAudioDevice();
|
||||
|
||||
RL_FREE(fft.spectrum);
|
||||
RL_FREE(fft.workBuffer);
|
||||
RL_FREE(fft.prevMagnitudes);
|
||||
RL_FREE(fft.fftHistory);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Cooley–Tukey FFT https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm#Data_reordering,_bit_reversal,_and_in-place_algorithms
|
||||
static void CooleyTukeyFFTSlow(FFTComplex *spectrum, int n)
|
||||
{
|
||||
int j = 0;
|
||||
for (int i = 1; i < n - 1; i++)
|
||||
{
|
||||
int bit = n >> 1;
|
||||
while (j >= bit)
|
||||
{
|
||||
j -= bit;
|
||||
bit >>= 1;
|
||||
}
|
||||
j += bit;
|
||||
if (i < j)
|
||||
{
|
||||
FFTComplex temp = spectrum[i];
|
||||
spectrum[i] = spectrum[j];
|
||||
spectrum[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
for (int len = 2; len <= n; len <<= 1)
|
||||
{
|
||||
float angle = -2.0f*PI/len;
|
||||
FFTComplex twiddleUnit = { cosf(angle), sinf(angle) };
|
||||
for (int i = 0; i < n; i += len)
|
||||
{
|
||||
FFTComplex twiddleCurrent = { 1.0f, 0.0f };
|
||||
for (int j = 0; j < len/2; j++)
|
||||
{
|
||||
FFTComplex even = spectrum[i + j];
|
||||
FFTComplex odd = spectrum[i + j + len/2];
|
||||
FFTComplex twiddledOdd = {
|
||||
odd.real*twiddleCurrent.real - odd.imaginary*twiddleCurrent.imaginary,
|
||||
odd.real*twiddleCurrent.imaginary + odd.imaginary*twiddleCurrent.real
|
||||
};
|
||||
|
||||
spectrum[i + j].real = even.real + twiddledOdd.real;
|
||||
spectrum[i + j].imaginary = even.imaginary + twiddledOdd.imaginary;
|
||||
spectrum[i + j + len/2].real = even.real - twiddledOdd.real;
|
||||
spectrum[i + j + len/2].imaginary = even.imaginary - twiddledOdd.imaginary;
|
||||
|
||||
float twiddleRealNext = twiddleCurrent.real*twiddleUnit.real - twiddleCurrent.imaginary*twiddleUnit.imaginary;
|
||||
twiddleCurrent.imaginary = twiddleCurrent.real*twiddleUnit.imaginary + twiddleCurrent.imaginary*twiddleUnit.real;
|
||||
twiddleCurrent.real = twiddleRealNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CaptureFrame(FFTData *fftData, const float *audioSamples)
|
||||
{
|
||||
for (int i = 0; i < FFT_WINDOW_SIZE; i++)
|
||||
{
|
||||
float x = (2.0f*PI*i)/(FFT_WINDOW_SIZE - 1.0f);
|
||||
float blackmanWeight = 0.42f - 0.5f*cosf(x) + 0.08f*cosf(2.0f*x); // https://en.wikipedia.org/wiki/Window_function#Blackman_window
|
||||
fftData->workBuffer[i].real = audioSamples[i]*blackmanWeight;
|
||||
fftData->workBuffer[i].imaginary = 0.0f;
|
||||
}
|
||||
|
||||
CooleyTukeyFFTSlow(fftData->workBuffer, FFT_WINDOW_SIZE);
|
||||
memcpy(fftData->spectrum, fftData->workBuffer, sizeof(FFTComplex)*FFT_WINDOW_SIZE);
|
||||
|
||||
float smoothedSpectrum[BUFFER_SIZE];
|
||||
|
||||
for (int bin = 0; bin < BUFFER_SIZE; bin++)
|
||||
{
|
||||
float re = fftData->workBuffer[bin].real;
|
||||
float im = fftData->workBuffer[bin].imaginary;
|
||||
float linearMagnitude = sqrtf(re*re + im*im)/FFT_WINDOW_SIZE;
|
||||
|
||||
float smoothedMagnitude = SMOOTHING_TIME_CONSTANT*fftData->prevMagnitudes[bin] + (1.0f - SMOOTHING_TIME_CONSTANT)*linearMagnitude;
|
||||
fftData->prevMagnitudes[bin] = smoothedMagnitude;
|
||||
|
||||
float db = logf(fmaxf(smoothedMagnitude, 1e-40f))*DB_TO_LINEAR_SCALE;
|
||||
float normalized = (db - MIN_DECIBELS)*INVERSE_DECIBEL_RANGE;
|
||||
smoothedSpectrum[bin] = Clamp(normalized, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
fftData->lastFftTime = GetTime();
|
||||
memcpy(fftData->fftHistory[fftData->historyPos], smoothedSpectrum, sizeof(smoothedSpectrum));
|
||||
fftData->historyPos = (fftData->historyPos + 1)%fftData->fftHistoryLen;
|
||||
}
|
||||
|
||||
static void RenderFrame(const FFTData *fftData, Image *fftImage)
|
||||
{
|
||||
float framesSinceTapback = floorf((float)(fftData->tapbackPos/WINDOW_TIME));
|
||||
framesSinceTapback = Clamp(framesSinceTapback, 0.0f, (float)(fftData->fftHistoryLen - 1));
|
||||
|
||||
int historyPosition = (fftData->historyPos - 1 - (int)framesSinceTapback)%fftData->fftHistoryLen;
|
||||
if (historyPosition < 0) historyPosition += fftData->fftHistoryLen;
|
||||
|
||||
const float *amplitude = fftData->fftHistory[historyPosition];
|
||||
for (int bin = 0; bin < BUFFER_SIZE; bin++) ImageDrawPixel(fftImage, bin, FFT_ROW, ColorFromNormalized((Vector4){ amplitude[bin], UNUSED_CHANNEL, UNUSED_CHANNEL, UNUSED_CHANNEL }));
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,246 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - stream callback
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example created by Dan Hoang (@dan-hoang) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* NOTE: Example sends a wave to the audio device,
|
||||
* user gets the choice of four waves: sine, square, triangle, and sawtooth
|
||||
* A stream is set up to play to the audio device; stream is hooked to a callback that
|
||||
* generates a wave, that is determined by user choice
|
||||
*
|
||||
* 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) 2026 Dan Hoang (@dan-hoang)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
#define SAMPLE_RATE 44100
|
||||
|
||||
// Wave type
|
||||
typedef enum {
|
||||
SINE,
|
||||
SQUARE,
|
||||
TRIANGLE,
|
||||
SAWTOOTH
|
||||
} WaveType;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void SineCallback(void *framesOut, unsigned int frameCount);
|
||||
static void SquareCallback(void *framesOut, unsigned int frameCount);
|
||||
static void TriangleCallback(void *framesOut, unsigned int frameCount);
|
||||
static void SawtoothCallback(void *framesOut, unsigned int frameCount);
|
||||
|
||||
static int waveFrequency = 440;
|
||||
static int newWaveFrequency = 440;
|
||||
static int waveIndex = 0;
|
||||
|
||||
// Buffer to keep the last second of uploaded audio,
|
||||
// part of which will be drawn on the screen
|
||||
static float buffer[SAMPLE_RATE] = { 0 };
|
||||
static AudioCallback waveCallbacks[] = { SineCallback, SquareCallback, TriangleCallback, SawtoothCallback };
|
||||
static char *waveTypesAsString[] = { "sine", "square", "triangle", "sawtooth" };
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - stream callback");
|
||||
|
||||
InitAudioDevice();
|
||||
|
||||
// Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE
|
||||
SetAudioStreamBufferSizeDefault(BUFFER_SIZE);
|
||||
|
||||
// Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono)
|
||||
AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1);
|
||||
PlayAudioStream(stream);
|
||||
|
||||
// Configure it so that waveCallbacks[waveType] is called whenever stream is out of samples
|
||||
WaveType waveType = SINE;
|
||||
SetAudioStreamCallback(stream, waveCallbacks[waveType]);
|
||||
|
||||
SetTargetFPS(30);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KEY_UP))
|
||||
{
|
||||
newWaveFrequency += 10;
|
||||
if (newWaveFrequency > 12500) newWaveFrequency = 12500;
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_DOWN))
|
||||
{
|
||||
newWaveFrequency -= 10;
|
||||
if (newWaveFrequency < 20) newWaveFrequency = 20;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_LEFT))
|
||||
{
|
||||
if (waveType == SINE) waveType = SAWTOOTH;
|
||||
else if (waveType == SQUARE) waveType = SINE;
|
||||
else if (waveType == TRIANGLE) waveType = SQUARE;
|
||||
else waveType = TRIANGLE;
|
||||
|
||||
SetAudioStreamCallback(stream, waveCallbacks[waveType]);
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_RIGHT))
|
||||
{
|
||||
if (waveType == SINE) waveType = SQUARE;
|
||||
else if (waveType == SQUARE) waveType = TRIANGLE;
|
||||
else if (waveType == TRIANGLE) waveType = SAWTOOTH;
|
||||
else waveType = SINE;
|
||||
|
||||
SetAudioStreamCallback(stream, waveCallbacks[waveType]);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
DrawText(TextFormat("frequency: %i", newWaveFrequency), screenWidth - 220, 10, 20, RED);
|
||||
DrawText(TextFormat("wave type: %s", waveTypesAsString[waveType]), screenWidth - 220, 30, 20, RED);
|
||||
DrawText("Up/down to change frequency", 10, 10, 20, DARKGRAY);
|
||||
DrawText("Left/right to change wave type", 10, 30, 20, DARKGRAY);
|
||||
|
||||
// Draw the last 10 ms of uploaded audio
|
||||
for (int i = 0; i < screenWidth; i++)
|
||||
{
|
||||
Vector2 startPos = { i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
|
||||
Vector2 endPos = { i + 1, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
|
||||
DrawLineV(startPos, endPos, RED);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadAudioStream(stream); // Close raw audio stream and delete buffers from RAM
|
||||
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
static void SineCallback(void *framesOut, unsigned int frameCount)
|
||||
{
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the sine wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = sin(2*PI*waveIndex/wavelength);
|
||||
|
||||
waveIndex++;
|
||||
|
||||
if (waveIndex >= wavelength)
|
||||
{
|
||||
waveFrequency = newWaveFrequency;
|
||||
waveIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
||||
static void SquareCallback(void *framesOut, unsigned int frameCount)
|
||||
{
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the square wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1 : -1;
|
||||
waveIndex++;
|
||||
|
||||
if (waveIndex >= wavelength)
|
||||
{
|
||||
waveFrequency = newWaveFrequency;
|
||||
waveIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
||||
static void TriangleCallback(void *framesOut, unsigned int frameCount)
|
||||
{
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the triangle wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = (waveIndex < wavelength/2)? (-1 + 2.0f*waveIndex/(wavelength/2)) : (1 - 2.0f*(waveIndex - wavelength/2)/(wavelength/2));
|
||||
waveIndex++;
|
||||
|
||||
if (waveIndex >= wavelength)
|
||||
{
|
||||
waveFrequency = newWaveFrequency;
|
||||
waveIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
||||
static void SawtoothCallback(void *framesOut, unsigned int frameCount)
|
||||
{
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the sawtooth wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = -1 + 2.0f*waveIndex/wavelength;
|
||||
waveIndex++;
|
||||
|
||||
if (waveIndex >= wavelength)
|
||||
{
|
||||
waveFrequency = newWaveFrequency;
|
||||
waveIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,187 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - stream effects
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 5.0
|
||||
*
|
||||
* 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) 2022-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h> // Required for: NULL
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static float *delayBuffer = NULL;
|
||||
static unsigned int delayBufferSize = 0;
|
||||
static unsigned int delayReadIndex = 2;
|
||||
static unsigned int delayWriteIndex = 0;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void AudioProcessEffectLPF(void *buffer, unsigned int frames); // Audio effect: lowpass filter
|
||||
static void AudioProcessEffectDelay(void *buffer, unsigned int frames); // Audio effect: delay
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - stream effects");
|
||||
|
||||
InitAudioDevice(); // Initialize audio device
|
||||
|
||||
Music music = LoadMusicStream("resources/country.mp3");
|
||||
|
||||
// Allocate buffer for the delay effect
|
||||
delayBufferSize = 48000*2; // 1 second delay (device sampleRate*channels)
|
||||
delayBuffer = (float *)RL_CALLOC(delayBufferSize, sizeof(float));
|
||||
|
||||
PlayMusicStream(music);
|
||||
|
||||
float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f]
|
||||
bool pause = false; // Music playing paused
|
||||
|
||||
bool enableEffectLPF = false; // Enable effect low-pass-filter
|
||||
bool enableEffectDelay = false; // Enable effect delay (1 second)
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateMusicStream(music); // Update music buffer with new stream data
|
||||
|
||||
// Restart music playing (stop and play)
|
||||
if (IsKeyPressed(KEY_SPACE))
|
||||
{
|
||||
StopMusicStream(music);
|
||||
PlayMusicStream(music);
|
||||
}
|
||||
|
||||
// Pause/Resume music playing
|
||||
if (IsKeyPressed(KEY_P))
|
||||
{
|
||||
pause = !pause;
|
||||
|
||||
if (pause) PauseMusicStream(music);
|
||||
else ResumeMusicStream(music);
|
||||
}
|
||||
|
||||
// Add/Remove effect: lowpass filter
|
||||
if (IsKeyPressed(KEY_F))
|
||||
{
|
||||
enableEffectLPF = !enableEffectLPF;
|
||||
if (enableEffectLPF) AttachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
|
||||
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
|
||||
}
|
||||
|
||||
// Add/Remove effect: delay
|
||||
if (IsKeyPressed(KEY_D))
|
||||
{
|
||||
enableEffectDelay = !enableEffectDelay;
|
||||
if (enableEffectDelay) AttachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
|
||||
else DetachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
|
||||
}
|
||||
|
||||
// Get normalized time played for current music stream
|
||||
timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music);
|
||||
|
||||
if (timePlayed > 1.0f) timePlayed = 1.0f; // Make sure time played is no longer than music
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("MUSIC SHOULD BE PLAYING!", 245, 150, 20, LIGHTGRAY);
|
||||
|
||||
DrawRectangle(200, 180, 400, 12, LIGHTGRAY);
|
||||
DrawRectangle(200, 180, (int)(timePlayed*400.0f), 12, MAROON);
|
||||
DrawRectangleLines(200, 180, 400, 12, GRAY);
|
||||
|
||||
DrawText("PRESS SPACE TO RESTART MUSIC", 215, 230, 20, LIGHTGRAY);
|
||||
DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 260, 20, LIGHTGRAY);
|
||||
|
||||
DrawText(TextFormat("PRESS F TO TOGGLE LPF EFFECT: %s", enableEffectLPF? "ON" : "OFF"), 200, 320, 20, GRAY);
|
||||
DrawText(TextFormat("PRESS D TO TOGGLE DELAY EFFECT: %s", enableEffectDelay? "ON" : "OFF"), 180, 350, 20, GRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
|
||||
CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
RL_FREE(delayBuffer); // Free delay buffer
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
// Audio effect: lowpass filter
|
||||
static void AudioProcessEffectLPF(void *buffer, unsigned int frames)
|
||||
{
|
||||
static float low[2] = { 0.0f, 0.0f };
|
||||
static const float cutoff = 70.0f/44100.0f; // 70 Hz lowpass filter
|
||||
const float k = cutoff/(cutoff + 0.1591549431f); // RC filter formula
|
||||
|
||||
// Converts the buffer data before using it
|
||||
float *bufferData = (float *)buffer;
|
||||
for (unsigned int i = 0; i < frames*2; i += 2)
|
||||
{
|
||||
const float l = bufferData[i];
|
||||
const float r = bufferData[i + 1];
|
||||
|
||||
low[0] += k*(l - low[0]);
|
||||
low[1] += k*(r - low[1]);
|
||||
bufferData[i] = low[0];
|
||||
bufferData[i + 1] = low[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Audio effect: delay
|
||||
static void AudioProcessEffectDelay(void *buffer, unsigned int frames)
|
||||
{
|
||||
for (unsigned int i = 0; i < frames*2; i += 2)
|
||||
{
|
||||
float leftDelay = delayBuffer[delayReadIndex++]; // ERROR: Reading buffer -> WHY??? Maybe thread related???
|
||||
float rightDelay = delayBuffer[delayReadIndex++];
|
||||
|
||||
if (delayReadIndex == delayBufferSize) delayReadIndex = 0;
|
||||
|
||||
((float *)buffer)[i] = 0.5f*((float *)buffer)[i] + 0.5f*leftDelay;
|
||||
((float *)buffer)[i + 1] = 0.5f*((float *)buffer)[i + 1] + 0.5f*rightDelay;
|
||||
|
||||
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i];
|
||||
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i + 1];
|
||||
if (delayWriteIndex == delayBufferSize) delayWriteIndex = 0;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,10 @@
|
||||
| resource | author | licence | notes |
|
||||
| :------------------- | :---------: | :------ | :---- |
|
||||
| country.mp3 | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Originally created for "DART that TARGET" game |
|
||||
| target.ogg | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Originally created for "DART that TARGET" game |
|
||||
| target.flac | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Originally created for "DART that TARGET" game |
|
||||
| coin.wav | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [rFXGen](https://raylibtech.itch.io/rfxgen) |
|
||||
| sound.wav | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [rFXGen](https://raylibtech.itch.io/rfxgen) |
|
||||
| spring.wav | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [rFXGen](https://raylibtech.itch.io/rfxgen) |
|
||||
| weird.wav | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [rFXGen](https://raylibtech.itch.io/rfxgen) |
|
||||
| mini1111.xm | [tPORt](https://modarchive.org/index.php?request=view_by_moduleid&query=51891) | [Mod Archive Distribution license](https://modarchive.org/index.php?terms-upload) | - |
|
||||
@ -0,0 +1,37 @@
|
||||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform vec2 iResolution;
|
||||
uniform sampler2D iChannel0;
|
||||
|
||||
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
const float FFT_ROW = 0.0;
|
||||
const float NUM_OF_BINS = 512.0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 fragCoord = fragTexCoord*iResolution;
|
||||
float cellWidth = iResolution.x/NUM_OF_BINS;
|
||||
float binIndex = floor(fragCoord.x/cellWidth);
|
||||
float localX = mod(fragCoord.x, cellWidth);
|
||||
float barWidth = cellWidth - 1.0;
|
||||
vec4 color = WHITE;
|
||||
|
||||
if (localX <= barWidth)
|
||||
{
|
||||
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
||||
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
||||
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
||||
|
||||
if (fragTexCoord.y < amplitude) color = BLACK;
|
||||
}
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
#version 120
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform vec2 iResolution;
|
||||
uniform sampler2D iChannel0;
|
||||
|
||||
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
const float FFT_ROW = 0.0;
|
||||
const float NUM_OF_BINS = 512.0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 fragCoord = fragTexCoord*iResolution;
|
||||
float cellWidth = iResolution.x/NUM_OF_BINS;
|
||||
float binIndex = floor(fragCoord.x/cellWidth);
|
||||
float localX = mod(fragCoord.x, cellWidth);
|
||||
float barWidth = cellWidth - 1.0;
|
||||
vec4 color = WHITE;
|
||||
|
||||
if (localX <= barWidth)
|
||||
{
|
||||
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
||||
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
||||
float amplitude = texture2D(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
||||
|
||||
if (fragTexCoord.y < amplitude) color = BLACK;
|
||||
}
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
#version 330
|
||||
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
|
||||
out vec4 finalColor;
|
||||
|
||||
uniform vec2 iResolution;
|
||||
uniform sampler2D iChannel0;
|
||||
|
||||
const vec4 BLACK = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
const vec4 WHITE = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
const float FFT_ROW = 0.0;
|
||||
const float NUM_OF_BINS = 512.0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 fragCoord = fragTexCoord*iResolution;
|
||||
float cellWidth = iResolution.x/NUM_OF_BINS;
|
||||
float binIndex = floor(fragCoord.x/cellWidth);
|
||||
float localX = mod(fragCoord.x, cellWidth);
|
||||
float barWidth = cellWidth - 1.0;
|
||||
vec4 color = WHITE;
|
||||
|
||||
if (localX <= barWidth)
|
||||
{
|
||||
float sampleX = (binIndex + 0.5)/NUM_OF_BINS;
|
||||
vec2 sampleCoord = vec2(sampleX, FFT_ROW);
|
||||
float amplitude = texture(iChannel0, sampleCoord).r; // Only filled the red channel, all channels left open for alternative use
|
||||
|
||||
if (fragTexCoord.y < amplitude) color = BLACK;
|
||||
}
|
||||
|
||||
finalColor = color;
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
::@echo off
|
||||
:: .
|
||||
:: Compile your examples for web using: build_example_web.bat <example_category>/<example_name>
|
||||
:: .
|
||||
SET "INPUT_FILE=%1"
|
||||
:: Change delimiter for the FOR loop
|
||||
FOR /f "tokens=1-10 delims=/" %%a IN ("%INPUT_FILE%") DO (
|
||||
SET CATEGORY=%%a
|
||||
SET FILENAME=%%b
|
||||
)
|
||||
:: > SETup required Environment
|
||||
:: -------------------------------------
|
||||
SET RAYLIB_PATH=C:\GitHub\raylib
|
||||
SET EMSDK_PATH=C:\raylib\emsdk
|
||||
SET COMPILER_PATH=C:\raylib\w64devkit\bin
|
||||
ENV_SET PATH=%COMPILER_PATH%
|
||||
SET MAKE=mingw32-make
|
||||
echo
|
||||
:: Set required web compilation options
|
||||
:: -------------------------------------
|
||||
::SET CC=%EMSDK_PATH%\upstream\emscripten\emcc
|
||||
::SET CFLAGS=-Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces -Wunused-result -O3 -I. -Iexternal -I%RAYLIB_PATH%\src -I%RAYLIB_PATH%\external -DPLATFORM_WEB
|
||||
::SET LDFLAGS=-L. -L$(RAYLIB_PATH)\src -sUSE_GLFW=3 -sEXPORTED_RUNTIME_METHODS=ccall -sASYNCIFY --shell-file %RAYLIB_PATH%\src\shell.html
|
||||
::SET LDLIBS=%RAYLIB_PATH%\src\libraylib.web.a
|
||||
echo
|
||||
:: Clean latest build
|
||||
:: ------------------------
|
||||
cmd /c if exist %FILENAME%.html del /F %FILENAME%.html
|
||||
cmd /c if exist %FILENAME%.wasm del /F %FILENAME%.wasm
|
||||
cmd /c if exist %FILENAME%.js del /F %FILENAME%.js
|
||||
cmd /c if exist %FILENAME%.data del /F %FILENAME%.data
|
||||
echo
|
||||
:: Setup emsdk environment
|
||||
:: --------------------------
|
||||
call %EMSDK_PATH%\emsdk_env.bat
|
||||
echo on
|
||||
:: Compile program
|
||||
:: -----------------------
|
||||
C:
|
||||
cd %RAYLIB_PATH%\examples
|
||||
%MAKE% -f Makefile.Web %CATEGORY%/%FILENAME% PLATFORM=PLATFORM_WEB -B
|
||||
::%CC% -o %FILENAME%.html %FILENAME%.c %CFLAGS% %LDFLAGS% %LDLIBS% %RESOURCES%
|
||||
cd ..
|
||||
echo
|
||||
@ -0,0 +1,144 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 1.5, last time updated with raylib 3.0
|
||||
*
|
||||
* 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) 2016-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
#define MAX_BUILDINGS 100
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
|
||||
|
||||
Rectangle player = { 400, 280, 40, 40 };
|
||||
Rectangle buildings[MAX_BUILDINGS] = { 0 };
|
||||
Color buildColors[MAX_BUILDINGS] = { 0 };
|
||||
|
||||
int spacing = 0;
|
||||
|
||||
for (int i = 0; i < MAX_BUILDINGS; i++)
|
||||
{
|
||||
buildings[i].width = (float)GetRandomValue(50, 200);
|
||||
buildings[i].height = (float)GetRandomValue(100, 800);
|
||||
buildings[i].y = screenHeight - 130.0f - buildings[i].height;
|
||||
buildings[i].x = -6000.0f + spacing;
|
||||
|
||||
spacing += (int)buildings[i].width;
|
||||
|
||||
buildColors[i] = (Color){
|
||||
(unsigned char)GetRandomValue(200, 240),
|
||||
(unsigned char)GetRandomValue(200, 240),
|
||||
(unsigned char)GetRandomValue(200, 250),
|
||||
255};
|
||||
}
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f };
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Player movement
|
||||
if (IsKeyDown(KEY_RIGHT)) player.x += 2;
|
||||
else if (IsKeyDown(KEY_LEFT)) player.x -= 2;
|
||||
|
||||
// Camera target follows player
|
||||
camera.target = (Vector2){ player.x + 20, player.y + 20 };
|
||||
|
||||
// Camera rotation controls
|
||||
if (IsKeyDown(KEY_A)) camera.rotation--;
|
||||
else if (IsKeyDown(KEY_S)) camera.rotation++;
|
||||
|
||||
// Limit camera rotation to 80 degrees (-40 to 40)
|
||||
if (camera.rotation > 40) camera.rotation = 40;
|
||||
else if (camera.rotation < -40) camera.rotation = -40;
|
||||
|
||||
// Camera zoom controls
|
||||
// Uses log scaling to provide consistent zoom speed
|
||||
camera.zoom = expf(logf(camera.zoom) + ((float)GetMouseWheelMove()*0.1f));
|
||||
|
||||
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
|
||||
else if (camera.zoom < 0.1f) camera.zoom = 0.1f;
|
||||
|
||||
// Camera reset (zoom and rotation)
|
||||
if (IsKeyPressed(KEY_R))
|
||||
{
|
||||
camera.zoom = 1.0f;
|
||||
camera.rotation = 0.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
DrawRectangle(-6000, 320, 13000, 8000, DARKGRAY);
|
||||
|
||||
for (int i = 0; i < MAX_BUILDINGS; i++) DrawRectangleRec(buildings[i], buildColors[i]);
|
||||
|
||||
DrawRectangleRec(player, RED);
|
||||
|
||||
DrawLine((int)camera.target.x, -screenHeight*10, (int)camera.target.x, screenHeight*10, GREEN);
|
||||
DrawLine(-screenWidth*10, (int)camera.target.y, screenWidth*10, (int)camera.target.y, GREEN);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawText("SCREEN AREA", 640, 10, 20, RED);
|
||||
|
||||
DrawRectangle(0, 0, screenWidth, 5, RED);
|
||||
DrawRectangle(0, 5, 5, screenHeight - 10, RED);
|
||||
DrawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, RED);
|
||||
DrawRectangle(0, screenHeight - 5, screenWidth, 5, RED);
|
||||
|
||||
DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines( 10, 10, 250, 113, BLUE);
|
||||
|
||||
DrawText("Free 2D camera controls:", 20, 20, 10, BLACK);
|
||||
DrawText("- Right/Left to move player", 40, 40, 10, DARKGRAY);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY);
|
||||
DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY);
|
||||
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.3 KiB |
@ -0,0 +1,146 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera mouse zoom
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
*
|
||||
* Example contributed by Jeffery Myers (@JeffM2501) 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) 2022-2025 Jeffery Myers (@JeffM2501)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "rlgl.h"
|
||||
#include "raymath.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera mouse zoom");
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
int zoomMode = 0; // 0-Mouse Wheel, 1-Mouse Move
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_ONE)) zoomMode = 0;
|
||||
else if (IsKeyPressed(KEY_TWO)) zoomMode = 1;
|
||||
|
||||
// Translate based on mouse right click
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
Vector2 delta = GetMouseDelta();
|
||||
delta = Vector2Scale(delta, -1.0f/camera.zoom);
|
||||
camera.target = Vector2Add(camera.target, delta);
|
||||
}
|
||||
|
||||
if (zoomMode == 0)
|
||||
{
|
||||
// Zoom based on mouse wheel
|
||||
float wheel = GetMouseWheelMove();
|
||||
if (wheel != 0)
|
||||
{
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera.offset = GetMousePosition();
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera.target = mouseWorldPos;
|
||||
|
||||
// Zoom increment
|
||||
// Uses log scaling to provide consistent zoom speed
|
||||
float scale = 0.2f*wheel;
|
||||
camera.zoom = Clamp(expf(logf(camera.zoom)+scale), 0.125f, 64.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Zoom based on mouse right click
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
|
||||
{
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera.offset = GetMousePosition();
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera.target = mouseWorldPos;
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
|
||||
{
|
||||
// Zoom increment
|
||||
// Uses log scaling to provide consistent zoom speed
|
||||
float deltaX = GetMouseDelta().x;
|
||||
float scale = 0.005f*deltaX;
|
||||
camera.zoom = Clamp(expf(logf(camera.zoom)+scale), 0.125f, 64.0f);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode2D(camera);
|
||||
// Draw the 3d grid, rotated 90 degrees and centered around 0,0
|
||||
// just so we have something in the XY plane
|
||||
rlPushMatrix();
|
||||
rlTranslatef(0, 25*50, 0);
|
||||
rlRotatef(90, 1, 0, 0);
|
||||
DrawGrid(100, 50);
|
||||
rlPopMatrix();
|
||||
|
||||
// Draw a reference circle
|
||||
DrawCircle(GetScreenWidth()/2, GetScreenHeight()/2, 50, MAROON);
|
||||
EndMode2D();
|
||||
|
||||
// Draw mouse reference
|
||||
//Vector2 mousePos = GetWorldToScreen2D(GetMousePosition(), camera)
|
||||
DrawCircleV(GetMousePosition(), 4, DARKGRAY);
|
||||
DrawTextEx(GetFontDefault(), TextFormat("[%i, %i]", GetMouseX(), GetMouseY()),
|
||||
Vector2Add(GetMousePosition(), (Vector2){ -44, -24 }), 20, 2, BLACK);
|
||||
|
||||
DrawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, DARKGRAY);
|
||||
if (zoomMode == 0) DrawText("Mouse left button drag to move, mouse wheel to zoom", 20, 50, 20, DARKGRAY);
|
||||
else DrawText("Mouse left button drag to move, mouse press and move to zoom", 20, 50, 20, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,307 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera platformer
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 3.0
|
||||
*
|
||||
* Example contributed by arvyy (@arvyy) 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) 2019-2025 arvyy (@arvyy)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
|
||||
#define G 400
|
||||
#define PLAYER_JUMP_SPD 350.0f
|
||||
#define PLAYER_HOR_SPD 200.0f
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef struct Player {
|
||||
Vector2 position;
|
||||
float speed;
|
||||
bool canJump;
|
||||
} Player;
|
||||
|
||||
typedef struct EnvItem {
|
||||
Rectangle rect;
|
||||
int blocking;
|
||||
Color color;
|
||||
} EnvItem;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
void UpdatePlayer(Player *player, EnvItem *envItems, int envItemsLength, float delta);
|
||||
void UpdateCameraCenter(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
|
||||
void UpdateCameraCenterInsideMap(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
|
||||
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
|
||||
void UpdateCameraEvenOutOnLanding(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
|
||||
void UpdateCameraPlayerBoundsPush(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera platformer");
|
||||
|
||||
Player player = { 0 };
|
||||
player.position = (Vector2){ 400, 280 };
|
||||
player.speed = 0;
|
||||
player.canJump = false;
|
||||
EnvItem envItems[] = {
|
||||
{{ 0, 0, 1000, 400 }, 0, LIGHTGRAY },
|
||||
{{ 0, 400, 1000, 200 }, 1, GRAY },
|
||||
{{ 300, 200, 400, 10 }, 1, GRAY },
|
||||
{{ 250, 300, 100, 10 }, 1, GRAY },
|
||||
{{ 650, 300, 100, 10 }, 1, GRAY }
|
||||
};
|
||||
|
||||
int envItemsLength = sizeof(envItems)/sizeof(envItems[0]);
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
// Store pointers to the multiple update camera functions
|
||||
void (*cameraUpdaters[])(Camera2D*, Player*, EnvItem*, int, float, int, int) = {
|
||||
UpdateCameraCenter,
|
||||
UpdateCameraCenterInsideMap,
|
||||
UpdateCameraCenterSmoothFollow,
|
||||
UpdateCameraEvenOutOnLanding,
|
||||
UpdateCameraPlayerBoundsPush
|
||||
};
|
||||
|
||||
int cameraOption = 0;
|
||||
int cameraUpdatersLength = sizeof(cameraUpdaters)/sizeof(cameraUpdaters[0]);
|
||||
|
||||
char *cameraDescriptions[] = {
|
||||
"Follow player center",
|
||||
"Follow player center, but clamp to map edges",
|
||||
"Follow player center; smoothed",
|
||||
"Follow player center horizontally; update player center vertically after landing",
|
||||
"Player push camera on getting too close to screen edge"
|
||||
};
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float deltaTime = GetFrameTime();
|
||||
|
||||
UpdatePlayer(&player, envItems, envItemsLength, deltaTime);
|
||||
|
||||
camera.zoom += ((float)GetMouseWheelMove()*0.05f);
|
||||
|
||||
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
|
||||
else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
|
||||
|
||||
if (IsKeyPressed(KEY_R))
|
||||
{
|
||||
camera.zoom = 1.0f;
|
||||
player.position = (Vector2){ 400, 280 };
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_C)) cameraOption = (cameraOption + 1)%cameraUpdatersLength;
|
||||
|
||||
// Call update camera function by its pointer
|
||||
cameraUpdaters[cameraOption](&camera, &player, envItems, envItemsLength, deltaTime, screenWidth, screenHeight);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(LIGHTGRAY);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
for (int i = 0; i < envItemsLength; i++) DrawRectangleRec(envItems[i].rect, envItems[i].color);
|
||||
|
||||
Rectangle playerRect = { player.position.x - 20, player.position.y - 40, 40.0f, 40.0f };
|
||||
DrawRectangleRec(playerRect, RED);
|
||||
|
||||
DrawCircleV(player.position, 5.0f, GOLD);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawText("Controls:", 20, 20, 10, BLACK);
|
||||
DrawText("- Right/Left to move", 40, 40, 10, DARKGRAY);
|
||||
DrawText("- Space to jump", 40, 60, 10, DARKGRAY);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 80, 10, DARKGRAY);
|
||||
DrawText("- R to reset position + zoom", 40, 100, 10, DARKGRAY);
|
||||
DrawText("- C to change camera mode", 40, 120, 10, DARKGRAY);
|
||||
DrawText("Current camera mode:", 20, 140, 10, BLACK);
|
||||
DrawText(cameraDescriptions[cameraOption], 40, 160, 10, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdatePlayer(Player *player, EnvItem *envItems, int envItemsLength, float delta)
|
||||
{
|
||||
if (IsKeyDown(KEY_LEFT)) player->position.x -= PLAYER_HOR_SPD*delta;
|
||||
if (IsKeyDown(KEY_RIGHT)) player->position.x += PLAYER_HOR_SPD*delta;
|
||||
if (IsKeyDown(KEY_SPACE) && player->canJump)
|
||||
{
|
||||
player->speed = -PLAYER_JUMP_SPD;
|
||||
player->canJump = false;
|
||||
}
|
||||
|
||||
bool hitObstacle = false;
|
||||
for (int i = 0; i < envItemsLength; i++)
|
||||
{
|
||||
EnvItem *ei = envItems + i;
|
||||
Vector2 *p = &(player->position);
|
||||
if (ei->blocking &&
|
||||
ei->rect.x <= p->x &&
|
||||
ei->rect.x + ei->rect.width >= p->x &&
|
||||
ei->rect.y >= p->y &&
|
||||
ei->rect.y <= p->y + player->speed*delta)
|
||||
{
|
||||
hitObstacle = true;
|
||||
player->speed = 0.0f;
|
||||
p->y = ei->rect.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hitObstacle)
|
||||
{
|
||||
player->position.y += player->speed*delta;
|
||||
player->speed += G*delta;
|
||||
player->canJump = false;
|
||||
}
|
||||
else player->canJump = true;
|
||||
}
|
||||
|
||||
void UpdateCameraCenter(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
||||
{
|
||||
camera->offset = (Vector2){ width/2.0f, height/2.0f };
|
||||
camera->target = player->position;
|
||||
}
|
||||
|
||||
void UpdateCameraCenterInsideMap(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
||||
{
|
||||
camera->target = player->position;
|
||||
camera->offset = (Vector2){ width/2.0f, height/2.0f };
|
||||
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
|
||||
|
||||
for (int i = 0; i < envItemsLength; i++)
|
||||
{
|
||||
EnvItem *ei = envItems + i;
|
||||
minX = fminf(ei->rect.x, minX);
|
||||
maxX = fmaxf(ei->rect.x + ei->rect.width, maxX);
|
||||
minY = fminf(ei->rect.y, minY);
|
||||
maxY = fmaxf(ei->rect.y + ei->rect.height, maxY);
|
||||
}
|
||||
|
||||
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera);
|
||||
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera);
|
||||
|
||||
if (max.x < width) camera->offset.x = width - (max.x - (float)width/2);
|
||||
if (max.y < height) camera->offset.y = height - (max.y - (float)height/2);
|
||||
if (min.x > 0) camera->offset.x = (float)width/2 - min.x;
|
||||
if (min.y > 0) camera->offset.y = (float)height/2 - min.y;
|
||||
}
|
||||
|
||||
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
||||
{
|
||||
static float minSpeed = 30;
|
||||
static float minEffectLength = 10;
|
||||
static float fractionSpeed = 0.8f;
|
||||
|
||||
camera->offset = (Vector2){ width/2.0f, height/2.0f };
|
||||
Vector2 diff = Vector2Subtract(player->position, camera->target);
|
||||
float length = Vector2Length(diff);
|
||||
|
||||
if (length > minEffectLength)
|
||||
{
|
||||
float speed = fmaxf(fractionSpeed*length, minSpeed);
|
||||
camera->target = Vector2Add(camera->target, Vector2Scale(diff, speed*delta/length));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCameraEvenOutOnLanding(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
||||
{
|
||||
static float evenOutSpeed = 700;
|
||||
static int eveningOut = false;
|
||||
static float evenOutTarget;
|
||||
|
||||
camera->offset = (Vector2){ width/2.0f, height/2.0f };
|
||||
camera->target.x = player->position.x;
|
||||
|
||||
if (eveningOut)
|
||||
{
|
||||
if (evenOutTarget > camera->target.y)
|
||||
{
|
||||
camera->target.y += evenOutSpeed*delta;
|
||||
|
||||
if (camera->target.y > evenOutTarget)
|
||||
{
|
||||
camera->target.y = evenOutTarget;
|
||||
eveningOut = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
camera->target.y -= evenOutSpeed*delta;
|
||||
|
||||
if (camera->target.y < evenOutTarget)
|
||||
{
|
||||
camera->target.y = evenOutTarget;
|
||||
eveningOut = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->canJump && (player->speed == 0) && (player->position.y != camera->target.y))
|
||||
{
|
||||
eveningOut = 1;
|
||||
evenOutTarget = player->position.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCameraPlayerBoundsPush(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)
|
||||
{
|
||||
static Vector2 bbox = { 0.2f, 0.2f };
|
||||
|
||||
Vector2 bboxWorldMin = GetScreenToWorld2D((Vector2){ (1 - bbox.x)*0.5f*width, (1 - bbox.y)*0.5f*height }, *camera);
|
||||
Vector2 bboxWorldMax = GetScreenToWorld2D((Vector2){ (1 + bbox.x)*0.5f*width, (1 + bbox.y)*0.5f*height }, *camera);
|
||||
camera->offset = (Vector2){ (1 - bbox.x)*0.5f*width, (1 - bbox.y)*0.5f*height };
|
||||
|
||||
if (player->position.x < bboxWorldMin.x) camera->target.x = player->position.x;
|
||||
if (player->position.y < bboxWorldMin.y) camera->target.y = player->position.y;
|
||||
if (player->position.x > bboxWorldMax.x) camera->target.x = bboxWorldMin.x + (player->position.x - bboxWorldMax.x);
|
||||
if (player->position.y > bboxWorldMax.y) camera->target.y = bboxWorldMin.y + (player->position.y - bboxWorldMax.y);
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,169 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 2d camera split screen
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Addapted from the core_3d_camera_split_screen example:
|
||||
* https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_split_screen.c
|
||||
*
|
||||
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||
*
|
||||
* Example contributed by Gabriel dos Santos Sanches (@gabrielssanches) 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) 2023-2025 Gabriel dos Santos Sanches (@gabrielssanches)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define PLAYER_SIZE 40
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 440;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera split screen");
|
||||
|
||||
Rectangle player1 = { 200, 200, PLAYER_SIZE, PLAYER_SIZE };
|
||||
Rectangle player2 = { 250, 200, PLAYER_SIZE, PLAYER_SIZE };
|
||||
|
||||
Camera2D camera1 = { 0 };
|
||||
camera1.target = (Vector2){ player1.x, player1.y };
|
||||
camera1.offset = (Vector2){ 200.0f, 200.0f };
|
||||
camera1.rotation = 0.0f;
|
||||
camera1.zoom = 1.0f;
|
||||
|
||||
Camera2D camera2 = { 0 };
|
||||
camera2.target = (Vector2){ player2.x, player2.y };
|
||||
camera2.offset = (Vector2){ 200.0f, 200.0f };
|
||||
camera2.rotation = 0.0f;
|
||||
camera2.zoom = 1.0f;
|
||||
|
||||
RenderTexture screenCamera1 = LoadRenderTexture(screenWidth/2, screenHeight);
|
||||
RenderTexture screenCamera2 = LoadRenderTexture(screenWidth/2, screenHeight);
|
||||
|
||||
// Build a flipped rectangle the size of the split view to use for drawing later
|
||||
Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenCamera1.texture.width, (float)-screenCamera1.texture.height };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KEY_S)) player1.y += 3.0f;
|
||||
else if (IsKeyDown(KEY_W)) player1.y -= 3.0f;
|
||||
if (IsKeyDown(KEY_D)) player1.x += 3.0f;
|
||||
else if (IsKeyDown(KEY_A)) player1.x -= 3.0f;
|
||||
|
||||
if (IsKeyDown(KEY_UP)) player2.y -= 3.0f;
|
||||
else if (IsKeyDown(KEY_DOWN)) player2.y += 3.0f;
|
||||
if (IsKeyDown(KEY_RIGHT)) player2.x += 3.0f;
|
||||
else if (IsKeyDown(KEY_LEFT)) player2.x -= 3.0f;
|
||||
|
||||
camera1.target = (Vector2){ player1.x, player1.y };
|
||||
camera2.target = (Vector2){ player2.x, player2.y };
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginTextureMode(screenCamera1);
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode2D(camera1);
|
||||
|
||||
// Draw full scene with first camera
|
||||
for (int i = 0; i < screenWidth/PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV((Vector2){(float)PLAYER_SIZE*i, 0}, (Vector2){ (float)PLAYER_SIZE*i, (float)screenHeight}, LIGHTGRAY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenHeight/PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV((Vector2){0, (float)PLAYER_SIZE*i}, (Vector2){ (float)screenWidth, (float)PLAYER_SIZE*i}, LIGHTGRAY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenWidth/PLAYER_SIZE; i++)
|
||||
{
|
||||
for (int j = 0; j < screenHeight/PLAYER_SIZE; j++)
|
||||
{
|
||||
DrawText(TextFormat("[%i,%i]", i, j), 10 + PLAYER_SIZE*i, 15 + PLAYER_SIZE*j, 10, LIGHTGRAY);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(player1, RED);
|
||||
DrawRectangleRec(player2, BLUE);
|
||||
EndMode2D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth()/2, 30, Fade(RAYWHITE, 0.6f));
|
||||
DrawText("PLAYER1: W/S/A/D to move", 10, 10, 10, MAROON);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
BeginTextureMode(screenCamera2);
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode2D(camera2);
|
||||
|
||||
// Draw full scene with second camera
|
||||
for (int i = 0; i < screenWidth/PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV((Vector2){ (float)PLAYER_SIZE*i, 0}, (Vector2){ (float)PLAYER_SIZE*i, (float)screenHeight}, LIGHTGRAY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenHeight/PLAYER_SIZE + 1; i++)
|
||||
{
|
||||
DrawLineV((Vector2){0, (float)PLAYER_SIZE*i}, (Vector2){ (float)screenWidth, (float)PLAYER_SIZE*i}, LIGHTGRAY);
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenWidth/PLAYER_SIZE; i++)
|
||||
{
|
||||
for (int j = 0; j < screenHeight/PLAYER_SIZE; j++)
|
||||
{
|
||||
DrawText(TextFormat("[%i,%i]", i, j), 10 + PLAYER_SIZE*i, 15 + PLAYER_SIZE*j, 10, LIGHTGRAY);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRectangleRec(player1, RED);
|
||||
DrawRectangleRec(player2, BLUE);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth()/2, 30, Fade(RAYWHITE, 0.6f));
|
||||
DrawText("PLAYER2: UP/DOWN/LEFT/RIGHT to move", 10, 10, 10, DARKBLUE);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw both views render textures to the screen side by side
|
||||
BeginDrawing();
|
||||
ClearBackground(BLACK);
|
||||
|
||||
DrawTextureRec(screenCamera1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
|
||||
DrawTextureRec(screenCamera2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
|
||||
|
||||
DrawRectangle(GetScreenWidth()/2 - 2, 0, 4, GetScreenHeight(), LIGHTGRAY);
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(screenCamera1); // Unload render texture
|
||||
UnloadRenderTexture(screenCamera2); // Unload render texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,207 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d camera first person
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 1.3
|
||||
*
|
||||
* 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "rcamera.h"
|
||||
|
||||
#define MAX_COLUMNS 20
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person");
|
||||
|
||||
// Define the camera to look into our 3d world (position, target, up vector)
|
||||
Camera camera = { 0 };
|
||||
camera.position = (Vector3){ 0.0f, 2.0f, 4.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 60.0f; // Camera field-of-view Y
|
||||
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
|
||||
|
||||
int cameraMode = CAMERA_FIRST_PERSON;
|
||||
|
||||
// Generates some random columns
|
||||
float heights[MAX_COLUMNS] = { 0 };
|
||||
Vector3 positions[MAX_COLUMNS] = { 0 };
|
||||
Color colors[MAX_COLUMNS] = { 0 };
|
||||
|
||||
for (int i = 0; i < MAX_COLUMNS; i++)
|
||||
{
|
||||
heights[i] = (float)GetRandomValue(1, 12);
|
||||
positions[i] = (Vector3){ (float)GetRandomValue(-15, 15), heights[i]/2.0f, (float)GetRandomValue(-15, 15) };
|
||||
colors[i] = (Color){ GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 };
|
||||
}
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Switch camera mode
|
||||
if (IsKeyPressed(KEY_ONE))
|
||||
{
|
||||
cameraMode = CAMERA_FREE;
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_TWO))
|
||||
{
|
||||
cameraMode = CAMERA_FIRST_PERSON;
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_THREE))
|
||||
{
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_FOUR))
|
||||
{
|
||||
cameraMode = CAMERA_ORBITAL;
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Reset roll
|
||||
}
|
||||
|
||||
// Switch camera projection
|
||||
if (IsKeyPressed(KEY_P))
|
||||
{
|
||||
if (camera.projection == CAMERA_PERSPECTIVE)
|
||||
{
|
||||
// Create isometric view
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
// Note: The target distance is related to the render distance in the orthographic projection
|
||||
camera.position = (Vector3){ 0.0f, 2.0f, -100.0f };
|
||||
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f };
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
camera.projection = CAMERA_ORTHOGRAPHIC;
|
||||
camera.fovy = 20.0f; // near plane width in CAMERA_ORTHOGRAPHIC
|
||||
CameraYaw(&camera, -135*DEG2RAD, true);
|
||||
CameraPitch(&camera, -45*DEG2RAD, true, true, false);
|
||||
}
|
||||
else if (camera.projection == CAMERA_ORTHOGRAPHIC)
|
||||
{
|
||||
// Reset to default view
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
camera.position = (Vector3){ 0.0f, 2.0f, 10.0f };
|
||||
camera.target = (Vector3){ 0.0f, 2.0f, 0.0f };
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
camera.fovy = 60.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera computes movement internally depending on the camera mode
|
||||
// Some default standard keyboard/mouse inputs are hardcoded to simplify use
|
||||
// For advanced camera controls, it's recommended to compute camera movement manually
|
||||
UpdateCamera(&camera, cameraMode); // Update camera
|
||||
/*
|
||||
// Camera PRO usage example (EXPERIMENTAL)
|
||||
// This new camera function allows custom movement/rotation values to be directly provided
|
||||
// as input parameters, with this approach, rcamera module is internally independent of raylib inputs
|
||||
UpdateCameraPro(&camera,
|
||||
(Vector3){
|
||||
(IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f - // Move forward-backward
|
||||
(IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f,
|
||||
(IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f - // Move right-left
|
||||
(IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f,
|
||||
0.0f // Move up-down
|
||||
},
|
||||
(Vector3){
|
||||
GetMouseDelta().x*0.05f, // Rotation: yaw
|
||||
GetMouseDelta().y*0.05f, // Rotation: pitch
|
||||
0.0f // Rotation: roll
|
||||
},
|
||||
GetMouseWheelMove()*2.0f); // Move to target (zoom)
|
||||
*/
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawPlane((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector2){ 32.0f, 32.0f }, LIGHTGRAY); // Draw ground
|
||||
DrawCube((Vector3){ -16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, BLUE); // Draw a blue wall
|
||||
DrawCube((Vector3){ 16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, LIME); // Draw a green wall
|
||||
DrawCube((Vector3){ 0.0f, 2.5f, 16.0f }, 32.0f, 5.0f, 1.0f, GOLD); // Draw a yellow wall
|
||||
|
||||
// Draw some cubes around
|
||||
for (int i = 0; i < MAX_COLUMNS; i++)
|
||||
{
|
||||
DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]);
|
||||
DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON);
|
||||
}
|
||||
|
||||
// Draw player cube
|
||||
if (cameraMode == CAMERA_THIRD_PERSON)
|
||||
{
|
||||
DrawCube(camera.target, 0.5f, 0.5f, 0.5f, PURPLE);
|
||||
DrawCubeWires(camera.target, 0.5f, 0.5f, 0.5f, DARKPURPLE);
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Draw info boxes
|
||||
DrawRectangle(5, 5, 330, 100, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(5, 5, 330, 100, BLUE);
|
||||
|
||||
DrawText("Camera controls:", 15, 15, 10, BLACK);
|
||||
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
|
||||
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
|
||||
DrawText("- Camera mode keys: 1, 2, 3, 4", 15, 60, 10, BLACK);
|
||||
DrawText("- Zoom keys: num-plus, num-minus or mouse scroll", 15, 75, 10, BLACK);
|
||||
DrawText("- Camera projection key: P", 15, 90, 10, BLACK);
|
||||
|
||||
DrawRectangle(600, 5, 195, 100, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(600, 5, 195, 100, BLUE);
|
||||
|
||||
DrawText("Camera status:", 610, 15, 10, BLACK);
|
||||
DrawText(TextFormat("- Mode: %s", (cameraMode == CAMERA_FREE) ? "FREE" :
|
||||
(cameraMode == CAMERA_FIRST_PERSON) ? "FIRST_PERSON" :
|
||||
(cameraMode == CAMERA_THIRD_PERSON) ? "THIRD_PERSON" :
|
||||
(cameraMode == CAMERA_ORBITAL) ? "ORBITAL" : "CUSTOM"), 610, 30, 10, BLACK);
|
||||
DrawText(TextFormat("- Projection: %s", (camera.projection == CAMERA_PERSPECTIVE) ? "PERSPECTIVE" :
|
||||
(camera.projection == CAMERA_ORTHOGRAPHIC) ? "ORTHOGRAPHIC" : "CUSTOM"), 610, 45, 10, BLACK);
|
||||
DrawText(TextFormat("- Position: (%06.3f, %06.3f, %06.3f)", camera.position.x, camera.position.y, camera.position.z), 610, 60, 10, BLACK);
|
||||
DrawText(TextFormat("- Target: (%06.3f, %06.3f, %06.3f)", camera.target.x, camera.target.y, camera.target.z), 610, 75, 10, BLACK);
|
||||
DrawText(TextFormat("- Up: (%06.3f, %06.3f, %06.3f)", camera.up.x, camera.up.y, camera.up.z), 610, 90, 10, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,329 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d camera fps
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Agnis Aldiņš (@nezvers) 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 Agnis Aldiņš (@nezvers)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
// Movement constants
|
||||
#define GRAVITY 32.0f
|
||||
#define MAX_SPEED 20.0f
|
||||
#define CROUCH_SPEED 5.0f
|
||||
#define JUMP_FORCE 12.0f
|
||||
#define MAX_ACCEL 150.0f
|
||||
// Grounded drag
|
||||
#define FRICTION 0.86f
|
||||
// Increasing air drag, increases strafing speed
|
||||
#define AIR_DRAG 0.98f
|
||||
// Responsiveness for turning movement direction to looked direction
|
||||
#define CONTROL 15.0f
|
||||
#define CROUCH_HEIGHT 0.0f
|
||||
#define STAND_HEIGHT 1.0f
|
||||
#define BOTTOM_HEIGHT 0.5f
|
||||
|
||||
#define NORMALIZE_INPUT 0
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Body structure
|
||||
typedef struct {
|
||||
Vector3 position;
|
||||
Vector3 velocity;
|
||||
Vector3 dir;
|
||||
bool isGrounded;
|
||||
} Body;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static Vector2 sensitivity = { 0.001f, 0.001f };
|
||||
|
||||
static Body player = { 0 };
|
||||
static Vector2 lookRotation = { 0 };
|
||||
static float headTimer = 0.0f;
|
||||
static float walkLerp = 0.0f;
|
||||
static float headLerp = STAND_HEIGHT;
|
||||
static Vector2 lean = { 0 };
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void DrawLevel(void);
|
||||
static void UpdateCameraFPS(Camera *camera);
|
||||
static void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera fps");
|
||||
|
||||
// Initialize camera variables
|
||||
// NOTE: UpdateCameraFPS() takes care of the rest
|
||||
Camera camera = { 0 };
|
||||
camera.fovy = 60.0f;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
camera.position = (Vector3){
|
||||
player.position.x,
|
||||
player.position.y + (BOTTOM_HEIGHT + headLerp),
|
||||
player.position.z,
|
||||
};
|
||||
|
||||
UpdateCameraFPS(&camera); // Update camera parameters
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mouseDelta = GetMouseDelta();
|
||||
lookRotation.x -= mouseDelta.x*sensitivity.x;
|
||||
lookRotation.y += mouseDelta.y*sensitivity.y;
|
||||
|
||||
char sideway = (IsKeyDown(KEY_D) - IsKeyDown(KEY_A));
|
||||
char forward = (IsKeyDown(KEY_W) - IsKeyDown(KEY_S));
|
||||
bool crouching = IsKeyDown(KEY_LEFT_CONTROL);
|
||||
UpdateBody(&player, lookRotation.x, sideway, forward, IsKeyPressed(KEY_SPACE), crouching);
|
||||
|
||||
float delta = GetFrameTime();
|
||||
headLerp = Lerp(headLerp, (crouching ? CROUCH_HEIGHT : STAND_HEIGHT), 20.0f*delta);
|
||||
camera.position = (Vector3){
|
||||
player.position.x,
|
||||
player.position.y + (BOTTOM_HEIGHT + headLerp),
|
||||
player.position.z,
|
||||
};
|
||||
|
||||
if (player.isGrounded && ((forward != 0) || (sideway != 0)))
|
||||
{
|
||||
headTimer += delta*3.0f;
|
||||
walkLerp = Lerp(walkLerp, 1.0f, 10.0f*delta);
|
||||
camera.fovy = Lerp(camera.fovy, 55.0f, 5.0f*delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
walkLerp = Lerp(walkLerp, 0.0f, 10.0f*delta);
|
||||
camera.fovy = Lerp(camera.fovy, 60.0f, 5.0f*delta);
|
||||
}
|
||||
|
||||
lean.x = Lerp(lean.x, sideway*0.02f, 10.0f*delta);
|
||||
lean.y = Lerp(lean.y, forward*0.015f, 10.0f*delta);
|
||||
|
||||
UpdateCameraFPS(&camera);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawLevel();
|
||||
EndMode3D();
|
||||
|
||||
// Draw info box
|
||||
DrawRectangle(5, 5, 330, 75, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(5, 5, 330, 75, BLUE);
|
||||
|
||||
DrawText("Camera controls:", 15, 15, 10, BLACK);
|
||||
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
|
||||
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
|
||||
DrawText(TextFormat("- Velocity Len: (%06.3f)", Vector2Length((Vector2){ player.velocity.x, player.velocity.z })), 15, 60, 10, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Update body considering current world state
|
||||
void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed, bool crouchHold)
|
||||
{
|
||||
Vector2 input = (Vector2){ (float)side, (float)-forward };
|
||||
|
||||
#if defined(NORMALIZE_INPUT)
|
||||
// Slow down diagonal movement
|
||||
if ((side != 0) && (forward != 0)) input = Vector2Normalize(input);
|
||||
#endif
|
||||
|
||||
float delta = GetFrameTime();
|
||||
|
||||
if (!body->isGrounded) body->velocity.y -= GRAVITY*delta;
|
||||
|
||||
if (body->isGrounded && jumpPressed)
|
||||
{
|
||||
body->velocity.y = JUMP_FORCE;
|
||||
body->isGrounded = false;
|
||||
|
||||
// Sound can be played at this moment
|
||||
//SetSoundPitch(fxJump, 1.0f + (GetRandomValue(-100, 100)*0.001));
|
||||
//PlaySound(fxJump);
|
||||
}
|
||||
|
||||
Vector3 front = (Vector3){ sinf(rot), 0.f, cosf(rot) };
|
||||
Vector3 right = (Vector3){ cosf(-rot), 0.f, sinf(-rot) };
|
||||
|
||||
Vector3 desiredDir = (Vector3){ input.x*right.x + input.y*front.x, 0.0f, input.x*right.z + input.y*front.z, };
|
||||
body->dir = Vector3Lerp(body->dir, desiredDir, CONTROL*delta);
|
||||
|
||||
float decel = (body->isGrounded ? FRICTION : AIR_DRAG);
|
||||
Vector3 hvel = (Vector3){ body->velocity.x*decel, 0.0f, body->velocity.z*decel };
|
||||
|
||||
float hvelLength = Vector3Length(hvel); // Magnitude
|
||||
if (hvelLength < (MAX_SPEED*0.01f)) hvel = (Vector3){ 0 };
|
||||
|
||||
// This is what creates strafing
|
||||
float speed = Vector3DotProduct(hvel, body->dir);
|
||||
|
||||
// Whenever the amount of acceleration to add is clamped by the maximum acceleration constant,
|
||||
// a Player can make the speed faster by bringing the direction closer to horizontal velocity angle
|
||||
// More info here: https://youtu.be/v3zT3Z5apaM?t=165
|
||||
float maxSpeed = (crouchHold? CROUCH_SPEED : MAX_SPEED);
|
||||
float accel = Clamp(maxSpeed - speed, 0.f, MAX_ACCEL*delta);
|
||||
hvel.x += body->dir.x*accel;
|
||||
hvel.z += body->dir.z*accel;
|
||||
|
||||
body->velocity.x = hvel.x;
|
||||
body->velocity.z = hvel.z;
|
||||
|
||||
body->position.x += body->velocity.x*delta;
|
||||
body->position.y += body->velocity.y*delta;
|
||||
body->position.z += body->velocity.z*delta;
|
||||
|
||||
// Fancy collision system against the floor
|
||||
if (body->position.y <= 0.0f)
|
||||
{
|
||||
body->position.y = 0.0f;
|
||||
body->velocity.y = 0.0f;
|
||||
body->isGrounded = true; // Enable jumping
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera for FPS behaviour
|
||||
static void UpdateCameraFPS(Camera *camera)
|
||||
{
|
||||
const Vector3 up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
const Vector3 targetOffset = (Vector3){ 0.0f, 0.0f, -1.0f };
|
||||
|
||||
// Left and right
|
||||
Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, lookRotation.x);
|
||||
|
||||
// Clamp view up
|
||||
float maxAngleUp = Vector3Angle(up, yaw);
|
||||
maxAngleUp -= 0.001f; // Avoid numerical errors
|
||||
if ( -(lookRotation.y) > maxAngleUp) { lookRotation.y = -maxAngleUp; }
|
||||
|
||||
// Clamp view down
|
||||
float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw);
|
||||
maxAngleDown *= -1.0f; // Downwards angle is negative
|
||||
maxAngleDown += 0.001f; // Avoid numerical errors
|
||||
if ( -(lookRotation.y) < maxAngleDown) { lookRotation.y = -maxAngleDown; }
|
||||
|
||||
// Up and down
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up));
|
||||
|
||||
// Rotate view vector around right axis
|
||||
float pitchAngle = -lookRotation.y - lean.y;
|
||||
pitchAngle = Clamp(pitchAngle, -PI/2 + 0.0001f, PI/2 - 0.0001f); // Clamp angle so it doesn't go past straight up or straight down
|
||||
Vector3 pitch = Vector3RotateByAxisAngle(yaw, right, pitchAngle);
|
||||
|
||||
// Head animation
|
||||
// Rotate up direction around forward axis
|
||||
float headSin = sinf(headTimer*PI);
|
||||
float headCos = cosf(headTimer*PI);
|
||||
const float stepRotation = 0.01f;
|
||||
camera->up = Vector3RotateByAxisAngle(up, pitch, headSin*stepRotation + lean.x);
|
||||
|
||||
// Camera BOB
|
||||
const float bobSide = 0.1f;
|
||||
const float bobUp = 0.15f;
|
||||
Vector3 bobbing = Vector3Scale(right, headSin*bobSide);
|
||||
bobbing.y = fabsf(headCos*bobUp);
|
||||
|
||||
camera->position = Vector3Add(camera->position, Vector3Scale(bobbing, walkLerp));
|
||||
camera->target = Vector3Add(camera->position, pitch);
|
||||
}
|
||||
|
||||
// Draw game level
|
||||
static void DrawLevel(void)
|
||||
{
|
||||
const int floorExtent = 25;
|
||||
const float tileSize = 5.0f;
|
||||
const Color tileColor1 = (Color){ 150, 200, 200, 255 };
|
||||
|
||||
// Floor tiles
|
||||
for (int y = -floorExtent; y < floorExtent; y++)
|
||||
{
|
||||
for (int x = -floorExtent; x < floorExtent; x++)
|
||||
{
|
||||
if ((y & 1) && (x & 1))
|
||||
{
|
||||
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, tileColor1);
|
||||
}
|
||||
else if (!(y & 1) && !(x & 1))
|
||||
{
|
||||
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, LIGHTGRAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Vector3 towerSize = (Vector3){ 16.0f, 32.0f, 16.0f };
|
||||
const Color towerColor = (Color){ 150, 200, 200, 255 };
|
||||
|
||||
Vector3 towerPos = (Vector3){ 16.0f, 16.0f, 16.0f };
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
towerPos.x *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
towerPos.z *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
towerPos.x *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
// Red sun
|
||||
DrawSphere((Vector3){ 300.0f, 300.0f, 0.0f }, 100.0f, (Color){ 255, 0, 0, 255 });
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
@ -0,0 +1,88 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d camera free
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 1.3
|
||||
*
|
||||
* 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = { 0 };
|
||||
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 45.0f; // Camera field-of-view Y
|
||||
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
|
||||
|
||||
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera, CAMERA_FREE);
|
||||
|
||||
if (IsKeyPressed(KEY_Z)) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle( 10, 10, 320, 93, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines( 10, 10, 320, 93, BLUE);
|
||||
|
||||
DrawText("Free camera default controls:", 20, 20, 10, BLACK);
|
||||
DrawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, DARKGRAY);
|
||||
DrawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, DARKGRAY);
|
||||
DrawText("- Z to zoom to (0, 0, 0)", 40, 80, 10, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,80 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d camera mode
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera mode");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera3D camera = { 0 };
|
||||
camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 45.0f; // Camera field-of-view Y
|
||||
camera.projection = CAMERA_PERSPECTIVE; // Camera mode type
|
||||
|
||||
Vector3 cubePosition = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED);
|
||||
DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON);
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Welcome to the third dimension!", 10, 40, 20, DARKGRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.3 KiB |
@ -0,0 +1,176 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d camera split screen
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 3.7, last time updated with raylib 4.0
|
||||
*
|
||||
* Example contributed by Jeffery Myers (@JeffM2501) 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) 2021-2025 Jeffery Myers (@JeffM2501)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera split screen");
|
||||
|
||||
// Setup player 1 camera and screen
|
||||
Camera cameraPlayer1 = { 0 };
|
||||
cameraPlayer1.fovy = 45.0f;
|
||||
cameraPlayer1.up.y = 1.0f;
|
||||
cameraPlayer1.target.y = 1.0f;
|
||||
cameraPlayer1.position.z = -3.0f;
|
||||
cameraPlayer1.position.y = 1.0f;
|
||||
|
||||
RenderTexture screenPlayer1 = LoadRenderTexture(screenWidth/2, screenHeight);
|
||||
|
||||
// Setup player two camera and screen
|
||||
Camera cameraPlayer2 = { 0 };
|
||||
cameraPlayer2.fovy = 45.0f;
|
||||
cameraPlayer2.up.y = 1.0f;
|
||||
cameraPlayer2.target.y = 3.0f;
|
||||
cameraPlayer2.position.x = -3.0f;
|
||||
cameraPlayer2.position.y = 3.0f;
|
||||
|
||||
RenderTexture screenPlayer2 = LoadRenderTexture(screenWidth/2, screenHeight);
|
||||
|
||||
// Build a flipped rectangle the size of the split view to use for drawing later
|
||||
Rectangle splitScreenRect = { 0.0f, 0.0f, (float)screenPlayer1.texture.width, (float)-screenPlayer1.texture.height };
|
||||
|
||||
// Grid data
|
||||
int count = 5;
|
||||
float spacing = 4;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// If anyone moves this frame, how far will they move based on the time since the last frame
|
||||
// this moves things at 10 world units per second, regardless of the actual FPS
|
||||
float offsetThisFrame = 10.0f*GetFrameTime();
|
||||
|
||||
// Move Player1 forward and backwards (no turning)
|
||||
if (IsKeyDown(KEY_W))
|
||||
{
|
||||
cameraPlayer1.position.z += offsetThisFrame;
|
||||
cameraPlayer1.target.z += offsetThisFrame;
|
||||
}
|
||||
else if (IsKeyDown(KEY_S))
|
||||
{
|
||||
cameraPlayer1.position.z -= offsetThisFrame;
|
||||
cameraPlayer1.target.z -= offsetThisFrame;
|
||||
}
|
||||
|
||||
// Move Player2 forward and backwards (no turning)
|
||||
if (IsKeyDown(KEY_UP))
|
||||
{
|
||||
cameraPlayer2.position.x += offsetThisFrame;
|
||||
cameraPlayer2.target.x += offsetThisFrame;
|
||||
}
|
||||
else if (IsKeyDown(KEY_DOWN))
|
||||
{
|
||||
cameraPlayer2.position.x -= offsetThisFrame;
|
||||
cameraPlayer2.target.x -= offsetThisFrame;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw Player1 view to the render texture
|
||||
BeginTextureMode(screenPlayer1);
|
||||
ClearBackground(SKYBLUE);
|
||||
|
||||
BeginMode3D(cameraPlayer1);
|
||||
|
||||
// Draw scene: grid of cube trees on a plane to make a "world"
|
||||
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
|
||||
|
||||
for (float x = -count*spacing; x <= count*spacing; x += spacing)
|
||||
{
|
||||
for (float z = -count*spacing; z <= count*spacing; z += spacing)
|
||||
{
|
||||
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
|
||||
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a cube at each player's position
|
||||
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
|
||||
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth()/2, 40, Fade(RAYWHITE, 0.8f));
|
||||
DrawText("PLAYER1: W/S to move", 10, 10, 20, MAROON);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw Player2 view to the render texture
|
||||
BeginTextureMode(screenPlayer2);
|
||||
ClearBackground(SKYBLUE);
|
||||
|
||||
BeginMode3D(cameraPlayer2);
|
||||
|
||||
// Draw scene: grid of cube trees on a plane to make a "world"
|
||||
DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 50, 50 }, BEIGE); // Simple world plane
|
||||
|
||||
for (float x = -count*spacing; x <= count*spacing; x += spacing)
|
||||
{
|
||||
for (float z = -count*spacing; z <= count*spacing; z += spacing)
|
||||
{
|
||||
DrawCube((Vector3) { x, 1.5f, z }, 1, 1, 1, LIME);
|
||||
DrawCube((Vector3) { x, 0.5f, z }, 0.25f, 1, 0.25f, BROWN);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a cube at each player's position
|
||||
DrawCube(cameraPlayer1.position, 1, 1, 1, RED);
|
||||
DrawCube(cameraPlayer2.position, 1, 1, 1, BLUE);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawRectangle(0, 0, GetScreenWidth()/2, 40, Fade(RAYWHITE, 0.8f));
|
||||
DrawText("PLAYER2: UP/DOWN to move", 10, 10, 20, DARKBLUE);
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Draw both views render textures to the screen side by side
|
||||
BeginDrawing();
|
||||
ClearBackground(BLACK);
|
||||
|
||||
DrawTextureRec(screenPlayer1.texture, splitScreenRect, (Vector2){ 0, 0 }, WHITE);
|
||||
DrawTextureRec(screenPlayer2.texture, splitScreenRect, (Vector2){ screenWidth/2.0f, 0 }, WHITE);
|
||||
|
||||
DrawRectangle(GetScreenWidth()/2 - 2, 0, 4, GetScreenHeight(), LIGHTGRAY);
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadRenderTexture(screenPlayer1); // Unload render texture
|
||||
UnloadRenderTexture(screenPlayer2); // Unload render texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,120 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - 3d picking
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.0
|
||||
*
|
||||
* 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera camera = { 0 };
|
||||
camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 45.0f; // Camera field-of-view Y
|
||||
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
|
||||
|
||||
Vector3 cubePosition = { 0.0f, 1.0f, 0.0f };
|
||||
Vector3 cubeSize = { 2.0f, 2.0f, 2.0f };
|
||||
|
||||
Ray ray = { 0 }; // Picking line ray
|
||||
RayCollision collision = { 0 }; // Ray collision hit info
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsCursorHidden()) UpdateCamera(&camera, CAMERA_FIRST_PERSON);
|
||||
|
||||
// Toggle camera controls
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
|
||||
{
|
||||
if (IsCursorHidden()) EnableCursor();
|
||||
else DisableCursor();
|
||||
}
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
if (!collision.hit)
|
||||
{
|
||||
ray = GetScreenToWorldRay(GetMousePosition(), camera);
|
||||
|
||||
// Check collision between ray and box
|
||||
collision = GetRayCollisionBox(ray,
|
||||
(BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 },
|
||||
(Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }});
|
||||
}
|
||||
else collision.hit = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
if (collision.hit)
|
||||
{
|
||||
DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED);
|
||||
DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON);
|
||||
|
||||
DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY);
|
||||
DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY);
|
||||
}
|
||||
|
||||
DrawRay(ray, MAROON);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawText("Try clicking on the box with your mouse!", 240, 10, 20, DARKGRAY);
|
||||
|
||||
if (collision.hit) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30))/2, (int)(screenHeight*0.1f), 30, GREEN);
|
||||
|
||||
DrawText("Right click mouse to toggle camera controls", 10, 430, 10, GRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,340 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - automation events
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.0
|
||||
*
|
||||
* Example based on 2d_camera_platformer example by arvyy (@arvyy)
|
||||
*
|
||||
* 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) 2023-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
|
||||
#define GRAVITY 400
|
||||
#define PLAYER_JUMP_SPD 350.0f
|
||||
#define PLAYER_HOR_SPD 200.0f
|
||||
|
||||
#define MAX_ENVIRONMENT_ELEMENTS 5
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef struct Player {
|
||||
Vector2 position;
|
||||
float speed;
|
||||
bool canJump;
|
||||
} Player;
|
||||
|
||||
typedef struct EnvElement {
|
||||
Rectangle rect;
|
||||
int blocking;
|
||||
Color color;
|
||||
} EnvElement;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - automation events");
|
||||
|
||||
// Define player
|
||||
Player player = { 0 };
|
||||
player.position = (Vector2){ 400, 280 };
|
||||
player.speed = 0;
|
||||
player.canJump = false;
|
||||
|
||||
// Define environment elements (platforms)
|
||||
EnvElement envElements[MAX_ENVIRONMENT_ELEMENTS] = {
|
||||
{{ 0, 0, 1000, 400 }, 0, LIGHTGRAY },
|
||||
{{ 0, 400, 1000, 200 }, 1, GRAY },
|
||||
{{ 300, 200, 400, 10 }, 1, GRAY },
|
||||
{{ 250, 300, 100, 10 }, 1, GRAY },
|
||||
{{ 650, 300, 100, 10 }, 1, GRAY }
|
||||
};
|
||||
|
||||
// Define camera
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
// Automation events
|
||||
AutomationEventList aelist = LoadAutomationEventList(0); // Initialize list of automation events to record new events
|
||||
SetAutomationEventList(&aelist);
|
||||
bool eventRecording = false;
|
||||
bool eventPlaying = false;
|
||||
|
||||
unsigned int frameCounter = 0;
|
||||
unsigned int playFrameCounter = 0;
|
||||
unsigned int currentPlayFrame = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
float deltaTime = 0.015f;//GetFrameTime();
|
||||
|
||||
// Dropped files logic
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsFileDropped())
|
||||
{
|
||||
FilePathList droppedFiles = LoadDroppedFiles();
|
||||
|
||||
// Supports loading .rgs style files (text or binary) and .png style palette images
|
||||
if (IsFileExtension(droppedFiles.paths[0], ".txt;.rae"))
|
||||
{
|
||||
UnloadAutomationEventList(aelist);
|
||||
aelist = LoadAutomationEventList(droppedFiles.paths[0]);
|
||||
|
||||
eventRecording = false;
|
||||
|
||||
// Reset scene state to play
|
||||
eventPlaying = true;
|
||||
playFrameCounter = 0;
|
||||
currentPlayFrame = 0;
|
||||
|
||||
player.position = (Vector2){ 400, 280 };
|
||||
player.speed = 0;
|
||||
player.canJump = false;
|
||||
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
}
|
||||
|
||||
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Update player
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KEY_LEFT)) player.position.x -= PLAYER_HOR_SPD*deltaTime;
|
||||
if (IsKeyDown(KEY_RIGHT)) player.position.x += PLAYER_HOR_SPD*deltaTime;
|
||||
if (IsKeyDown(KEY_SPACE) && player.canJump)
|
||||
{
|
||||
player.speed = -PLAYER_JUMP_SPD;
|
||||
player.canJump = false;
|
||||
}
|
||||
|
||||
int hitObstacle = 0;
|
||||
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
|
||||
{
|
||||
EnvElement *element = &envElements[i];
|
||||
Vector2 *p = &(player.position);
|
||||
if (element->blocking &&
|
||||
element->rect.x <= p->x &&
|
||||
element->rect.x + element->rect.width >= p->x &&
|
||||
element->rect.y >= p->y &&
|
||||
element->rect.y <= p->y + player.speed*deltaTime)
|
||||
{
|
||||
hitObstacle = 1;
|
||||
player.speed = 0.0f;
|
||||
p->y = element->rect.y;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hitObstacle)
|
||||
{
|
||||
player.position.y += player.speed*deltaTime;
|
||||
player.speed += GRAVITY*deltaTime;
|
||||
player.canJump = false;
|
||||
}
|
||||
else player.canJump = true;
|
||||
|
||||
if (IsKeyPressed(KEY_R))
|
||||
{
|
||||
// Reset game state
|
||||
player.position = (Vector2){ 400, 280 };
|
||||
player.speed = 0;
|
||||
player.canJump = false;
|
||||
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Events playing
|
||||
// NOTE: Logic must be before Camera update because it depends on mouse-wheel value,
|
||||
// that can be set by the played event... but some other inputs could be affected
|
||||
//----------------------------------------------------------------------------------
|
||||
if (eventPlaying)
|
||||
{
|
||||
// NOTE: Multiple events could be executed in a single frame
|
||||
while (playFrameCounter == aelist.events[currentPlayFrame].frame)
|
||||
{
|
||||
PlayAutomationEvent(aelist.events[currentPlayFrame]);
|
||||
currentPlayFrame++;
|
||||
|
||||
if (currentPlayFrame == aelist.count)
|
||||
{
|
||||
eventPlaying = false;
|
||||
currentPlayFrame = 0;
|
||||
playFrameCounter = 0;
|
||||
|
||||
TraceLog(LOG_INFO, "FINISH PLAYING!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
playFrameCounter++;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
|
||||
|
||||
// WARNING: On event replay, mouse-wheel internal value is set
|
||||
camera.zoom += ((float)GetMouseWheelMove()*0.05f);
|
||||
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
|
||||
else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
|
||||
|
||||
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
|
||||
{
|
||||
EnvElement *element = &envElements[i];
|
||||
minX = fminf(element->rect.x, minX);
|
||||
maxX = fmaxf(element->rect.x + element->rect.width, maxX);
|
||||
minY = fminf(element->rect.y, minY);
|
||||
maxY = fmaxf(element->rect.y + element->rect.height, maxY);
|
||||
}
|
||||
|
||||
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, camera);
|
||||
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, camera);
|
||||
|
||||
if (max.x < screenWidth) camera.offset.x = screenWidth - (max.x - (float)screenWidth/2);
|
||||
if (max.y < screenHeight) camera.offset.y = screenHeight - (max.y - (float)screenHeight/2);
|
||||
if (min.x > 0) camera.offset.x = (float)screenWidth/2 - min.x;
|
||||
if (min.y > 0) camera.offset.y = (float)screenHeight/2 - min.y;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Events management
|
||||
if (IsKeyPressed(KEY_S)) // Toggle events recording
|
||||
{
|
||||
if (!eventPlaying)
|
||||
{
|
||||
if (eventRecording)
|
||||
{
|
||||
StopAutomationEventRecording();
|
||||
eventRecording = false;
|
||||
|
||||
ExportAutomationEventList(aelist, "automation.rae");
|
||||
|
||||
TraceLog(LOG_INFO, "RECORDED FRAMES: %i", aelist.count);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAutomationEventBaseFrame(180);
|
||||
StartAutomationEventRecording();
|
||||
eventRecording = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (IsKeyPressed(KEY_A)) // Toggle events playing (WARNING: Starts next frame)
|
||||
{
|
||||
if (!eventRecording && (aelist.count > 0))
|
||||
{
|
||||
// Reset scene state to play
|
||||
eventPlaying = true;
|
||||
playFrameCounter = 0;
|
||||
currentPlayFrame = 0;
|
||||
|
||||
player.position = (Vector2){ 400, 280 };
|
||||
player.speed = 0;
|
||||
player.canJump = false;
|
||||
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventRecording || eventPlaying) frameCounter++;
|
||||
else frameCounter = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(LIGHTGRAY);
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
// Draw environment elements
|
||||
for (int i = 0; i < MAX_ENVIRONMENT_ELEMENTS; i++)
|
||||
{
|
||||
DrawRectangleRec(envElements[i].rect, envElements[i].color);
|
||||
}
|
||||
|
||||
// Draw player rectangle
|
||||
DrawRectangleRec((Rectangle){ player.position.x - 20, player.position.y - 40, 40, 40 }, RED);
|
||||
|
||||
EndMode2D();
|
||||
|
||||
// Draw game controls
|
||||
DrawRectangle(10, 10, 290, 145, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(10, 10, 290, 145, Fade(BLUE, 0.8f));
|
||||
|
||||
DrawText("Controls:", 20, 20, 10, BLACK);
|
||||
DrawText("- RIGHT | LEFT: Player movement", 30, 40, 10, DARKGRAY);
|
||||
DrawText("- SPACE: Player jump", 30, 60, 10, DARKGRAY);
|
||||
DrawText("- R: Reset game state", 30, 80, 10, DARKGRAY);
|
||||
|
||||
DrawText("- S: START/STOP RECORDING INPUT EVENTS", 30, 110, 10, BLACK);
|
||||
DrawText("- A: REPLAY LAST RECORDED INPUT EVENTS", 30, 130, 10, BLACK);
|
||||
|
||||
// Draw automation events recording indicator
|
||||
if (eventRecording)
|
||||
{
|
||||
DrawRectangle(10, 160, 290, 30, Fade(RED, 0.3f));
|
||||
DrawRectangleLines(10, 160, 290, 30, Fade(MAROON, 0.8f));
|
||||
DrawCircle(30, 175, 10, MAROON);
|
||||
|
||||
if (((frameCounter/15)%2) == 1) DrawText(TextFormat("RECORDING EVENTS... [%i]", aelist.count), 50, 170, 10, MAROON);
|
||||
}
|
||||
else if (eventPlaying)
|
||||
{
|
||||
DrawRectangle(10, 160, 290, 30, Fade(LIME, 0.3f));
|
||||
DrawRectangleLines(10, 160, 290, 30, Fade(DARKGREEN, 0.8f));
|
||||
DrawTriangle((Vector2){ 20, 155 + 10 }, (Vector2){ 20, 155 + 30 }, (Vector2){ 40, 155 + 20 }, DARKGREEN);
|
||||
|
||||
if (((frameCounter/15)%2) == 1) DrawText(TextFormat("PLAYING RECORDED EVENTS... [%i]", currentPlayFrame), 50, 170, 10, DARKGREEN);
|
||||
}
|
||||
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,154 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - basic screen manager
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: This example illustrates a very simple screen manager based on a states machines
|
||||
*
|
||||
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||
*
|
||||
* 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) 2021-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//------------------------------------------------------------------------------------------
|
||||
typedef enum GameScreen { LOGO = 0, TITLE, GAMEPLAY, ENDING } GameScreen;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic screen manager");
|
||||
|
||||
GameScreen currentScreen = LOGO;
|
||||
|
||||
// TODO: Initialize all required variables and load all required data here!
|
||||
|
||||
int framesCounter = 0; // Useful to count frames
|
||||
|
||||
SetTargetFPS(60); // Set desired framerate (frames-per-second)
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (currentScreen)
|
||||
{
|
||||
case LOGO:
|
||||
{
|
||||
// TODO: Update LOGO screen variables here!
|
||||
|
||||
framesCounter++; // Count frames
|
||||
|
||||
// Wait for 2 seconds (120 frames) before jumping to TITLE screen
|
||||
if (framesCounter > 120)
|
||||
{
|
||||
currentScreen = TITLE;
|
||||
}
|
||||
} break;
|
||||
case TITLE:
|
||||
{
|
||||
// TODO: Update TITLE screen variables here!
|
||||
|
||||
// Press enter to change to GAMEPLAY screen
|
||||
if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
|
||||
{
|
||||
currentScreen = GAMEPLAY;
|
||||
}
|
||||
} break;
|
||||
case GAMEPLAY:
|
||||
{
|
||||
// TODO: Update GAMEPLAY screen variables here!
|
||||
|
||||
// Press enter to change to ENDING screen
|
||||
if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
|
||||
{
|
||||
currentScreen = ENDING;
|
||||
}
|
||||
} break;
|
||||
case ENDING:
|
||||
{
|
||||
// TODO: Update ENDING screen variables here!
|
||||
|
||||
// Press enter to return to TITLE screen
|
||||
if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
|
||||
{
|
||||
currentScreen = TITLE;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
switch(currentScreen)
|
||||
{
|
||||
case LOGO:
|
||||
{
|
||||
// TODO: Draw LOGO screen here!
|
||||
DrawText("LOGO SCREEN", 20, 20, 40, LIGHTGRAY);
|
||||
DrawText("WAIT for 2 SECONDS...", 290, 220, 20, GRAY);
|
||||
|
||||
} break;
|
||||
case TITLE:
|
||||
{
|
||||
// TODO: Draw TITLE screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, GREEN);
|
||||
DrawText("TITLE SCREEN", 20, 20, 40, DARKGREEN);
|
||||
DrawText("PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN", 120, 220, 20, DARKGREEN);
|
||||
|
||||
} break;
|
||||
case GAMEPLAY:
|
||||
{
|
||||
// TODO: Draw GAMEPLAY screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, PURPLE);
|
||||
DrawText("GAMEPLAY SCREEN", 20, 20, 40, MAROON);
|
||||
DrawText("PRESS ENTER or TAP to JUMP to ENDING SCREEN", 130, 220, 20, MAROON);
|
||||
|
||||
} break;
|
||||
case ENDING:
|
||||
{
|
||||
// TODO: Draw ENDING screen here!
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, BLUE);
|
||||
DrawText("ENDING SCREEN", 20, 20, 40, DARKBLUE);
|
||||
DrawText("PRESS ENTER or TAP to RETURN to TITLE SCREEN", 120, 220, 20, DARKBLUE);
|
||||
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Unload all loaded data (textures, fonts, audio) here!
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,72 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - basic window
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Welcome to raylib!
|
||||
*
|
||||
* To test examples, just press F6 and execute 'raylib_compile_execute' script
|
||||
* Note that compiled executable is placed in the same folder as .c file
|
||||
*
|
||||
* To test the examples on Web, press F6 and execute 'raylib_compile_execute_web' script
|
||||
* Web version of the program is generated in the same folder as .c file
|
||||
*
|
||||
* You can find all basic examples on C:\raylib\raylib\examples folder or
|
||||
* raylib official webpage: www.raylib.com
|
||||
*
|
||||
* Enjoy using raylib. :)
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
*
|
||||
* 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) 2013-2026 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,164 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - clipboard text
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Ananth S (@Ananth1839) 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 Ananth S (@Ananth1839)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#define MAX_TEXT_SAMPLES 5
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - clipboard text");
|
||||
|
||||
// Define some sample texts
|
||||
const char *sampleTexts[MAX_TEXT_SAMPLES] = {
|
||||
"Hello from raylib!",
|
||||
"The quick brown fox jumps over the lazy dog",
|
||||
"Clipboard operations are useful!",
|
||||
"raylib is a simple and easy-to-use library",
|
||||
"Copy and paste me!"
|
||||
};
|
||||
|
||||
const char *clipboardText = NULL;
|
||||
char inputBuffer[256] = "Hello from raylib!"; // Random initial string
|
||||
|
||||
// UI required variables
|
||||
bool textBoxEditMode = false;
|
||||
|
||||
bool btnCutPressed = false;
|
||||
bool btnCopyPressed = false;
|
||||
bool btnPastePressed = false;
|
||||
bool btnClearPressed = false;
|
||||
bool btnRandomPressed = false;
|
||||
|
||||
// Set UI style
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
|
||||
GuiSetIconScale(2);
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Handle button interactions
|
||||
if (btnCutPressed)
|
||||
{
|
||||
SetClipboardText(inputBuffer);
|
||||
clipboardText = GetClipboardText();
|
||||
inputBuffer[0] = '\0'; // Quick solution to clear text
|
||||
//memset(inputBuffer, 0, 256); // Clear full buffer properly
|
||||
}
|
||||
|
||||
if (btnCopyPressed)
|
||||
{
|
||||
SetClipboardText(inputBuffer); // Copy text to clipboard
|
||||
clipboardText = GetClipboardText(); // Get text from clipboard
|
||||
}
|
||||
|
||||
if (btnPastePressed)
|
||||
{
|
||||
// Paste text from clipboard
|
||||
clipboardText = GetClipboardText();
|
||||
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
|
||||
}
|
||||
|
||||
if (btnClearPressed)
|
||||
{
|
||||
inputBuffer[0] = '\0'; // Quick solution to clear text
|
||||
//memset(inputBuffer, 0, 256); // Clear full buffer properly
|
||||
}
|
||||
|
||||
if (btnRandomPressed)
|
||||
{
|
||||
// Get random text from sample list
|
||||
TextCopy(inputBuffer, sampleTexts[GetRandomValue(0, MAX_TEXT_SAMPLES - 1)]);
|
||||
}
|
||||
|
||||
// Quick cut/copy/paste with keyboard shortcuts
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))
|
||||
{
|
||||
if (IsKeyPressed(KEY_X))
|
||||
{
|
||||
SetClipboardText(inputBuffer);
|
||||
inputBuffer[0] = '\0'; // Quick solution to clear text
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_C)) SetClipboardText(inputBuffer);
|
||||
|
||||
if (IsKeyPressed(KEY_V))
|
||||
{
|
||||
clipboardText = GetClipboardText();
|
||||
if (clipboardText != NULL) TextCopy(inputBuffer, clipboardText);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw instructions
|
||||
GuiLabel((Rectangle){ 50, 20, 700, 36 }, "Use the BUTTONS or KEY SHORTCUTS:");
|
||||
DrawText("[CTRL+X] - CUT | [CTRL+C] COPY | [CTRL+V] | PASTE", 50, 60, 20, MAROON);
|
||||
|
||||
// Draw text box
|
||||
if (GuiTextBox((Rectangle){ 50, 120, 652, 40 }, inputBuffer, 256, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
|
||||
|
||||
// Random text button
|
||||
btnRandomPressed = GuiButton((Rectangle){ 50 + 652 + 8, 120, 40, 40 }, "#77#");
|
||||
|
||||
// Draw buttons
|
||||
btnCutPressed = GuiButton((Rectangle){ 50, 180, 158, 40 }, "#17#CUT");
|
||||
btnCopyPressed = GuiButton((Rectangle){ 50 + 165, 180, 158, 40 }, "#16#COPY");
|
||||
btnPastePressed = GuiButton((Rectangle){ 50 + 165*2, 180, 158, 40 }, "#18#PASTE");
|
||||
btnClearPressed = GuiButton((Rectangle){ 50 + 165*3, 180, 158, 40 }, "#143#CLEAR");
|
||||
|
||||
// Draw clipboard status
|
||||
GuiSetState(STATE_DISABLED);
|
||||
GuiLabel((Rectangle){ 50, 260, 700, 40 }, "Clipboard current text data:");
|
||||
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
|
||||
GuiTextBox((Rectangle){ 50, 300, 700, 40 }, (char *)clipboardText, 256, false);
|
||||
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
|
||||
GuiLabel((Rectangle){ 50, 360, 700, 40 }, "Try copying text from other applications and pasting here!");
|
||||
GuiSetState(STATE_NORMAL);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,143 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - compute hash
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* 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 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static char *GetDataAsHexText(const unsigned int *data, int dataSize);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - compute hash");
|
||||
|
||||
// UI controls variables
|
||||
char textInput[96] = "The quick brown fox jumps over the lazy dog.";
|
||||
bool textBoxEditMode = false;
|
||||
bool btnComputeHashes = false;
|
||||
|
||||
// Data hash values
|
||||
unsigned int hashCRC32 = 0;
|
||||
unsigned int *hashMD5 = NULL;
|
||||
unsigned int *hashSHA1 = NULL;
|
||||
unsigned int *hashSHA256 = NULL;
|
||||
|
||||
// Base64 encoded data
|
||||
char *base64Text = NULL;
|
||||
int base64TextSize = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (btnComputeHashes)
|
||||
{
|
||||
int textInputLen = (int)strlen(textInput);
|
||||
|
||||
// Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
|
||||
base64Text = EncodeDataBase64((unsigned char *)textInput, textInputLen, &base64TextSize);
|
||||
|
||||
hashCRC32 = ComputeCRC32((unsigned char *)textInput, textInputLen); // Compute CRC32 hash code (4 bytes)
|
||||
hashMD5 = ComputeMD5((unsigned char *)textInput, textInputLen); // Compute MD5 hash code, returns static int[4] (16 bytes)
|
||||
hashSHA1 = ComputeSHA1((unsigned char *)textInput, textInputLen); // Compute SHA1 hash code, returns static int[5] (20 bytes)
|
||||
hashSHA256 = ComputeSHA256((unsigned char *)textInput, textInputLen); // Compute SHA256 hash code, returns static int[8] (32 bytes)
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
|
||||
GuiSetStyle(DEFAULT, TEXT_SPACING, 2);
|
||||
GuiLabel((Rectangle){ 40, 26, 720, 32 }, "INPUT DATA (TEXT):");
|
||||
GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
|
||||
|
||||
if (GuiTextBox((Rectangle){ 40, 64, 720, 32 }, textInput, 95, textBoxEditMode)) textBoxEditMode = !textBoxEditMode;
|
||||
|
||||
btnComputeHashes = GuiButton((Rectangle){ 40, 64 + 40, 720, 32 }, "COMPUTE INPUT DATA HASHES");
|
||||
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
|
||||
GuiSetStyle(DEFAULT, TEXT_SPACING, 2);
|
||||
GuiLabel((Rectangle){ 40, 160, 720, 32 }, "INPUT DATA HASH VALUES:");
|
||||
GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
|
||||
|
||||
GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
|
||||
GuiLabel((Rectangle){ 40, 200, 120, 32 }, "CRC32 [32 bit]:");
|
||||
GuiTextBox((Rectangle){ 40 + 120, 200, 720 - 120, 32 }, GetDataAsHexText(&hashCRC32, 1), 120, false);
|
||||
GuiLabel((Rectangle){ 40, 200 + 36, 120, 32 }, "MD5 [128 bit]:");
|
||||
GuiTextBox((Rectangle){ 40 + 120, 200 + 36, 720 - 120, 32 }, GetDataAsHexText(hashMD5, 4), 120, false);
|
||||
GuiLabel((Rectangle){ 40, 200 + 36*2, 120, 32 }, "SHA1 [160 bit]:");
|
||||
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*2, 720 - 120, 32 }, GetDataAsHexText(hashSHA1, 5), 120, false);
|
||||
GuiLabel((Rectangle){ 40, 200 + 36*3, 120, 32 }, "SHA256 [256 bit]:");
|
||||
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*3, 720 - 120, 32 }, GetDataAsHexText(hashSHA256, 8), 120, false);
|
||||
|
||||
GuiSetState(STATE_FOCUSED);
|
||||
GuiLabel((Rectangle){ 40, 200 + 36*5 - 30, 320, 32 }, "BONUS - BAS64 ENCODED STRING:");
|
||||
GuiSetState(STATE_NORMAL);
|
||||
GuiLabel((Rectangle){ 40, 200 + 36*5, 120, 32 }, "BASE64 ENCODING:");
|
||||
GuiTextBox((Rectangle){ 40 + 120, 200 + 36*5, 720 - 120, 32 }, base64Text, 120, false);
|
||||
GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
MemFree(base64Text); // Free Base64 text data
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static char *GetDataAsHexText(const unsigned int *data, int dataSize)
|
||||
{
|
||||
static char text[128] = { 0 };
|
||||
memset(text, 0, 128);
|
||||
|
||||
if ((data != NULL) && (dataSize > 0) && (dataSize < ((128/8) - 1)))
|
||||
{
|
||||
for (int i = 0; i < dataSize; i++) TextCopy(text + i*8, TextFormat("%08X", data[i]));
|
||||
}
|
||||
else TextCopy(text, "00000000");
|
||||
|
||||
return text;
|
||||
}
|
||||
|
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,141 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - custom frame control
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* NOTE: WARNING: This is an example for advanced users willing to have full control over
|
||||
* the frame processes. By default, EndDrawing() calls the following processes:
|
||||
* 1. Draw remaining batch data: rlDrawRenderBatchActive()
|
||||
* 2. SwapScreenBuffer()
|
||||
* 3. Frame time control: WaitTime()
|
||||
* 4. PollInputEvents()
|
||||
*
|
||||
* To avoid steps 2, 3 and 4, flag SUPPORT_CUSTOM_FRAME_CONTROL can be enabled in
|
||||
* config.h (it requires recompiling raylib). This way those steps are up to the user
|
||||
*
|
||||
* Note that enabling this flag invalidates some functions:
|
||||
* - GetFrameTime()
|
||||
* - SetTargetFPS()
|
||||
* - GetFPS()
|
||||
*
|
||||
* Example originally created with raylib 4.0, last time updated with raylib 4.0
|
||||
*
|
||||
* 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) 2021-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom frame control");
|
||||
|
||||
// Custom timming variables
|
||||
double previousTime = GetTime(); // Previous time measure
|
||||
double currentTime = 0.0; // Current time measure
|
||||
double updateDrawTime = 0.0; // Update + Draw time
|
||||
double waitTime = 0.0; // Wait time (if target fps required)
|
||||
float deltaTime = 0.0f; // Frame time (Update + Draw + Wait time)
|
||||
|
||||
float timeCounter = 0.0f; // Accumulative time counter (seconds)
|
||||
float position = 0.0f; // Circle position
|
||||
bool pause = false; // Pause control flag
|
||||
|
||||
int targetFPS = 60; // Our initial target fps
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
#ifndef PLATFORM_WEB // NOTE: On non web platforms the PollInputEvents just works before the inputs checks
|
||||
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||
#endif
|
||||
|
||||
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
|
||||
|
||||
if (IsKeyPressed(KEY_UP)) targetFPS += 20;
|
||||
else if (IsKeyPressed(KEY_DOWN)) targetFPS -= 20;
|
||||
|
||||
if (targetFPS < 0) targetFPS = 0;
|
||||
|
||||
if (!pause)
|
||||
{
|
||||
position += 200*deltaTime; // We move at 200 pixels per second
|
||||
if (position >= GetScreenWidth()) position = 0;
|
||||
timeCounter += deltaTime; // We count time (seconds)
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WEB // NOTE: On web platform for some reason the PollInputEvents only works after the inputs check, so just call it after check all your inputs (on web)
|
||||
PollInputEvents(); // Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL)
|
||||
#endif
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
for (int i = 0; i < GetScreenWidth()/200; i++) DrawRectangle(200*i, 0, 1, GetScreenHeight(), SKYBLUE);
|
||||
|
||||
DrawCircle((int)position, GetScreenHeight()/2 - 25, 50, RED);
|
||||
|
||||
DrawText(TextFormat("%03.0f ms", timeCounter*1000.0f), (int)position - 40, GetScreenHeight()/2 - 100, 20, MAROON);
|
||||
DrawText(TextFormat("PosX: %03.0f", position), (int)position - 50, GetScreenHeight()/2 + 40, 20, BLACK);
|
||||
|
||||
DrawText("Circle is moving at a constant 200 pixels/sec,\nindependently of the frame rate.", 10, 10, 20, DARKGRAY);
|
||||
DrawText("PRESS SPACE to PAUSE MOVEMENT", 10, GetScreenHeight() - 60, 20, GRAY);
|
||||
DrawText("PRESS UP | DOWN to CHANGE TARGET FPS", 10, GetScreenHeight() - 30, 20, GRAY);
|
||||
DrawText(TextFormat("TARGET FPS: %i", targetFPS), GetScreenWidth() - 220, 10, 20, LIME);
|
||||
if (deltaTime != 0)
|
||||
{
|
||||
DrawText(TextFormat("CURRENT FPS: %i", (int)(1.0f/deltaTime)), GetScreenWidth() - 220, 40, 20, GREEN);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
|
||||
// NOTE: In case raylib is configured to SUPPORT_CUSTOM_FRAME_CONTROL,
|
||||
// Events polling, screen buffer swap and frame time control must be managed by the user
|
||||
|
||||
SwapScreenBuffer(); // Flip the back buffer to screen (front buffer)
|
||||
|
||||
currentTime = GetTime();
|
||||
updateDrawTime = currentTime - previousTime;
|
||||
|
||||
if (targetFPS > 0) // We want a fixed frame rate
|
||||
{
|
||||
waitTime = (1.0f/(float)targetFPS) - updateDrawTime;
|
||||
if (waitTime > 0.0)
|
||||
{
|
||||
WaitTime((float)waitTime);
|
||||
currentTime = GetTime();
|
||||
deltaTime = (float)(currentTime - previousTime);
|
||||
}
|
||||
}
|
||||
else deltaTime = (float)updateDrawTime; // Framerate could be variable
|
||||
|
||||
previousTime = currentTime;
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,90 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - custom logging
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 2.5, last time updated with raylib 2.5
|
||||
*
|
||||
* Example contributed by Pablo Marcos Oltra (@pamarcos) 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) 2018-2025 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdio.h> // Required for: printf(), vprintf(), fprintf()
|
||||
#include <time.h> // Required for: time_t, tm, time(), localtime(), strftime()
|
||||
|
||||
// Custom logging function
|
||||
void CustomTraceLog(int msgType, const char *text, va_list args)
|
||||
{
|
||||
char timeStr[64] = { 0 };
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
|
||||
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm_info);
|
||||
printf("[%s] ", timeStr);
|
||||
|
||||
switch (msgType)
|
||||
{
|
||||
case LOG_INFO: printf("[INFO] : "); break;
|
||||
case LOG_ERROR: printf("[ERROR]: "); break;
|
||||
case LOG_WARNING: printf("[WARN] : "); break;
|
||||
case LOG_DEBUG: printf("[DEBUG]: "); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
vprintf(text, args);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
// Set custom logger
|
||||
SetTraceLogCallback(CustomTraceLog);
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - custom logging");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,112 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - delta time
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Robin (@RobinsAviary) 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 Robin (@RobinsAviary)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - delta time");
|
||||
|
||||
int currentFps = 60;
|
||||
|
||||
// Store the position for the both of the circles
|
||||
Vector2 deltaCircle = { 0, (float)screenHeight/3.0f };
|
||||
Vector2 frameCircle = { 0, (float)screenHeight*(2.0f/3.0f) };
|
||||
|
||||
// The speed applied to both circles
|
||||
const float speed = 10.0f;
|
||||
const float circleRadius = 32.0f;
|
||||
|
||||
SetTargetFPS(currentFps);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Adjust the FPS target based on the mouse wheel
|
||||
float mouseWheel = GetMouseWheelMove();
|
||||
if (mouseWheel != 0)
|
||||
{
|
||||
currentFps += (int)mouseWheel;
|
||||
if (currentFps < 0) currentFps = 0;
|
||||
SetTargetFPS(currentFps);
|
||||
}
|
||||
|
||||
// GetFrameTime() returns the time it took to draw the last frame, in seconds (usually called delta time)
|
||||
// Uses the delta time to make the circle look like it's moving at a "consistent" speed regardless of FPS
|
||||
|
||||
// Multiply by 6.0 (an arbitrary value) in order to make the speed
|
||||
// visually closer to the other circle (at 60 fps), for comparison
|
||||
deltaCircle.x += GetFrameTime()*6.0f*speed;
|
||||
// This circle can move faster or slower visually depending on the FPS
|
||||
frameCircle.x += 0.1f*speed;
|
||||
|
||||
// If either circle is off the screen, reset it back to the start
|
||||
if (deltaCircle.x > screenWidth) deltaCircle.x = 0;
|
||||
if (frameCircle.x > screenWidth) frameCircle.x = 0;
|
||||
|
||||
// Reset both circles positions
|
||||
if (IsKeyPressed(KEY_R))
|
||||
{
|
||||
deltaCircle.x = 0;
|
||||
frameCircle.x = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw both circles to the screen
|
||||
DrawCircleV(deltaCircle, circleRadius, RED);
|
||||
DrawCircleV(frameCircle, circleRadius, BLUE);
|
||||
|
||||
// Draw the help text
|
||||
// Determine what help text to show depending on the current FPS target
|
||||
const char *fpsText = 0;
|
||||
if (currentFps <= 0) fpsText = TextFormat("FPS: unlimited (%i)", GetFPS());
|
||||
else fpsText = TextFormat("FPS: %i (target: %i)", GetFPS(), currentFps);
|
||||
DrawText(fpsText, 10, 10, 20, DARKGRAY);
|
||||
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()), 10, 30, 20, DARKGRAY);
|
||||
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, DARKGRAY);
|
||||
|
||||
// Draw the text above the circles
|
||||
DrawText("FUNC: x += GetFrameTime()*speed", 10, 90, 20, RED);
|
||||
DrawText("FUNC: x += speed", 10, 240, 20, BLUE);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,96 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - directory files
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Hugo ARNAL (@hugoarnal) 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 Hugo ARNAL (@hugoarnal)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
#define MAX_FILEPATH_SIZE 1024
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - directory files");
|
||||
|
||||
char directory[MAX_FILEPATH_SIZE] = { 0 };
|
||||
strcpy(directory, GetWorkingDirectory());
|
||||
|
||||
// Load file-paths on current working directory
|
||||
// NOTE: LoadDirectoryFiles() loads files and directories by default,
|
||||
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
|
||||
//FilePathList files = LoadDirectoryFiles(directory);
|
||||
FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false);
|
||||
|
||||
int btnBackPressed = false;
|
||||
|
||||
int listScrollIndex = 0;
|
||||
int listItemActive = -1;
|
||||
int listItemFocused = -1;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (btnBackPressed)
|
||||
{
|
||||
TextCopy(directory, GetPrevDirectoryPath(directory));
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFiles(directory);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
btnBackPressed = GuiButton((Rectangle){ 40.0f, 10.0f, 48, 28 }, "<");
|
||||
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize*2);
|
||||
GuiLabel((Rectangle){ 40 + 48 + 10, 10, 700, 28 }, directory);
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize);
|
||||
|
||||
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
||||
GuiSetStyle(LISTVIEW, TEXT_PADDING, 40);
|
||||
GuiListViewEx((Rectangle){ 0, 50, (float)GetScreenWidth(), (float)GetScreenHeight() - 50 },
|
||||
files.paths, files.count, &listScrollIndex, &listItemActive, &listItemFocused);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadDirectoryFiles(files);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,108 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - drop files
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* NOTE: This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?)
|
||||
*
|
||||
* Example originally created with raylib 1.3, last time updated with raylib 4.2
|
||||
*
|
||||
* 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) 2015-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <stdlib.h> // Required for: calloc(), free()
|
||||
|
||||
#define MAX_FILEPATH_RECORDED 4096
|
||||
#define MAX_FILEPATH_SIZE 2048
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - drop files");
|
||||
|
||||
int filePathCounter = 0;
|
||||
char *filePaths[MAX_FILEPATH_RECORDED] = { 0 }; // We will register a maximum of filepaths
|
||||
|
||||
// Allocate space for the required file paths
|
||||
for (int i = 0; i < MAX_FILEPATH_RECORDED; i++)
|
||||
{
|
||||
filePaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_SIZE, 1);
|
||||
}
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsFileDropped())
|
||||
{
|
||||
FilePathList droppedFiles = LoadDroppedFiles();
|
||||
|
||||
for (int i = 0, offset = filePathCounter; i < (int)droppedFiles.count; i++)
|
||||
{
|
||||
if (filePathCounter < (MAX_FILEPATH_RECORDED - 1))
|
||||
{
|
||||
TextCopy(filePaths[offset + i], droppedFiles.paths[i]);
|
||||
filePathCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
UnloadDroppedFiles(droppedFiles); // Unload filepaths from memory
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (filePathCounter == 0) DrawText("Drop your files to this window!", 100, 40, 20, DARKGRAY);
|
||||
else
|
||||
{
|
||||
DrawText("Dropped files:", 100, 40, 20, DARKGRAY);
|
||||
|
||||
for (int i = 0; i < filePathCounter; i++)
|
||||
{
|
||||
if (i%2 == 0) DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.5f));
|
||||
else DrawRectangle(0, 85 + 40*i, screenWidth, 40, Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
DrawText(filePaths[i], 120, 100 + 40*i, 10, GRAY);
|
||||
}
|
||||
|
||||
DrawText("Drop new files...", 100, 110 + 40*filePathCounter, 20, DARKGRAY);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
for (int i = 0; i < MAX_FILEPATH_RECORDED; i++)
|
||||
{
|
||||
RL_FREE(filePaths[i]); // Free allocated memory for all filepaths
|
||||
}
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
@ -0,0 +1,134 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - highdpi demo
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 5.5
|
||||
*
|
||||
* Example contributed by Jonathan Marler (@marler8997) 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 Jonathan Marler (@marler8997)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void DrawTextCenter(const char *text, int x, int y, int fontSize, Color color);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi demo");
|
||||
SetWindowMinSize(450, 450);
|
||||
|
||||
int logicalGridDescY = 120;
|
||||
int logicalGridLabelY = logicalGridDescY + 30;
|
||||
int logicalGridTop = logicalGridLabelY + 30;
|
||||
int logicalGridBottom = logicalGridTop + 80;
|
||||
int pixelGridTop = logicalGridBottom - 20;
|
||||
int pixelGridBottom = pixelGridTop + 80;
|
||||
int pixelGridLabelY = pixelGridBottom + 30;
|
||||
int pixelGridDescY = pixelGridLabelY + 30;
|
||||
int cellSize = 50;
|
||||
float cellSizePx = (float)cellSize;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
int monitorCount = GetMonitorCount();
|
||||
|
||||
if ((monitorCount > 1) && IsKeyPressed(KEY_N))
|
||||
{
|
||||
SetWindowMonitor((GetCurrentMonitor() + 1)%monitorCount);
|
||||
}
|
||||
|
||||
int currentMonitor = GetCurrentMonitor();
|
||||
Vector2 dpiScale = GetWindowScaleDPI();
|
||||
cellSizePx = ((float)cellSize)/dpiScale.x;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
int windowCenter = GetScreenWidth()/2;
|
||||
DrawTextCenter(TextFormat("Dpi Scale: %f", dpiScale.x), windowCenter, 30, 40, DARKGRAY);
|
||||
DrawTextCenter(TextFormat("Monitor: %d/%d ([N] next monitor)", currentMonitor+1, monitorCount), windowCenter, 70, 20, LIGHTGRAY);
|
||||
DrawTextCenter(TextFormat("Window is %d \"logical points\" wide", GetScreenWidth()), windowCenter, logicalGridDescY, 20, ORANGE);
|
||||
|
||||
bool odd = true;
|
||||
for (int i = cellSize; i < GetScreenWidth(); i += cellSize, odd = !odd)
|
||||
{
|
||||
if (odd) DrawRectangle(i, logicalGridTop, cellSize, logicalGridBottom-logicalGridTop, ORANGE);
|
||||
|
||||
DrawTextCenter(TextFormat("%d", i), i, logicalGridLabelY, 10, LIGHTGRAY);
|
||||
DrawLine(i, logicalGridLabelY + 10, i, logicalGridBottom, GRAY);
|
||||
}
|
||||
|
||||
odd = true;
|
||||
const int minTextSpace = 30;
|
||||
int lastTextX = -minTextSpace;
|
||||
for (int i = cellSize; i < GetRenderWidth(); i += cellSize, odd = !odd)
|
||||
{
|
||||
int x = (int)(((float)i)/dpiScale.x);
|
||||
if (odd) DrawRectangle(x, pixelGridTop, (int)cellSizePx, pixelGridBottom - pixelGridTop, CLITERAL(Color){ 0, 121, 241, 100 });
|
||||
|
||||
DrawLine(x, pixelGridTop, (int)(((float)i)/dpiScale.x), pixelGridLabelY - 10, GRAY);
|
||||
|
||||
if ((x - lastTextX) >= minTextSpace)
|
||||
{
|
||||
DrawTextCenter(TextFormat("%d", i), x, pixelGridLabelY, 10, LIGHTGRAY);
|
||||
lastTextX = x;
|
||||
}
|
||||
}
|
||||
|
||||
DrawTextCenter(TextFormat("Window is %d \"physical pixels\" wide", GetRenderWidth()), windowCenter, pixelGridDescY, 20, BLUE);
|
||||
|
||||
const char *text = "Can you see this?";
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), text, 20, 3);
|
||||
Vector2 pos = (Vector2){ GetScreenWidth() - size.x - 5, GetScreenHeight() - size.y - 5 };
|
||||
DrawTextEx(GetFontDefault(), text, pos, 20, 3, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
static void DrawTextCenter(const char *text, int x, int y, int fontSize, Color color)
|
||||
{
|
||||
Vector2 size = MeasureTextEx(GetFontDefault(), text, (float)fontSize, 3);
|
||||
Vector2 pos = (Vector2){ x - size.x/2, y - size.y/2 };
|
||||
DrawTextEx(GetFontDefault(), text, pos, (float)fontSize, 3, color);
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@ -0,0 +1,107 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - highdpi testbed
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Ramon Santamaria (@raysan5) 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 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
|
||||
|
||||
Vector2 scaleDpi = GetWindowScaleDPI();
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
int currentMonitor = GetCurrentMonitor();
|
||||
Vector2 windowPos = GetWindowPosition();
|
||||
|
||||
int gridSpacing = 40; // Grid spacing in pixels
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
mousePos = GetMousePosition();
|
||||
currentMonitor = GetCurrentMonitor();
|
||||
scaleDpi = GetWindowScaleDPI();
|
||||
windowPos = GetWindowPosition();
|
||||
|
||||
if (IsKeyPressed(KEY_SPACE)) ToggleBorderlessWindowed();
|
||||
if (IsKeyPressed(KEY_F)) ToggleFullscreen();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw grid
|
||||
for (int h = 0; h < GetScreenHeight()/gridSpacing + 1; h++)
|
||||
{
|
||||
DrawText(TextFormat("%02i", h*gridSpacing), 4, h*gridSpacing - 4, 10, GRAY);
|
||||
DrawLine(24, h*gridSpacing, GetScreenWidth(), h*gridSpacing, LIGHTGRAY);
|
||||
}
|
||||
for (int v = 0; v < GetScreenWidth()/gridSpacing + 1; v++)
|
||||
{
|
||||
DrawText(TextFormat("%02i", v*gridSpacing), v*gridSpacing - 10, 4, 10, GRAY);
|
||||
DrawLine(v*gridSpacing, 20, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
|
||||
}
|
||||
|
||||
// Draw UI info
|
||||
DrawText(TextFormat("CURRENT MONITOR: %i/%i (%ix%i)", currentMonitor + 1, GetMonitorCount(),
|
||||
GetMonitorWidth(currentMonitor), GetMonitorHeight(currentMonitor)), 50, 50, 20, DARKGRAY);
|
||||
DrawText(TextFormat("WINDOW POSITION: %ix%i", (int)windowPos.x, (int)windowPos.y), 50, 90, 20, DARKGRAY);
|
||||
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 50, 130, 20, DARKGRAY);
|
||||
DrawText(TextFormat("RENDER SIZE: %ix%i", GetRenderWidth(), GetRenderHeight()), 50, 170, 20, DARKGRAY);
|
||||
DrawText(TextFormat("SCALE FACTOR: %.2fx%.2f", scaleDpi.x, scaleDpi.y), 50, 210, 20, GRAY);
|
||||
|
||||
// Draw reference rectangles, top-left and bottom-right corners
|
||||
DrawRectangle(0, 0, 30, 60, RED);
|
||||
DrawRectangle(GetScreenWidth() - 30, GetScreenHeight() - 60, 30, 60, BLUE);
|
||||
|
||||
// Draw mouse position
|
||||
DrawCircleV(GetMousePosition(), 20, MAROON);
|
||||
DrawRectangleRec((Rectangle) { mousePos.x - 25, mousePos.y, 50, 2 }, BLACK);
|
||||
DrawRectangleRec((Rectangle) { mousePos.x, mousePos.y - 25, 2, 50 }, BLACK);
|
||||
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
|
||||
(mousePos.y > GetScreenHeight() - 60)? (int)mousePos.y - 46 : (int)mousePos.y + 30, 20, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Unload all loaded resources at this point
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,203 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input actions
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.6
|
||||
*
|
||||
* Example contributed by Jett (@JettMonstersGoBoom) 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 Jett (@JettMonstersGoBoom)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
// Simple example for decoding input as actions, allowing remapping of input to different keys or gamepad buttons
|
||||
// For example instead of using `IsKeyDown(KEY_LEFT)`, you can use `IsActionDown(ACTION_LEFT)`
|
||||
// which can be reassigned to e.g. KEY_A and also assigned to a gamepad button. the action will trigger with either gamepad or keys
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef enum ActionType {
|
||||
NO_ACTION = 0,
|
||||
ACTION_UP,
|
||||
ACTION_DOWN,
|
||||
ACTION_LEFT,
|
||||
ACTION_RIGHT,
|
||||
ACTION_FIRE,
|
||||
MAX_ACTION
|
||||
} ActionType;
|
||||
|
||||
// Key and button inputs
|
||||
typedef struct ActionInput {
|
||||
int key;
|
||||
int button;
|
||||
} ActionInput;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static int gamepadIndex = 0; // Gamepad default index
|
||||
static ActionInput actionInputs[MAX_ACTION] = { 0 };
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static bool IsActionPressed(int action); // Check action key/button pressed
|
||||
static bool IsActionReleased(int action); // Check action key/button released
|
||||
static bool IsActionDown(int action); // Check action key/button down
|
||||
|
||||
static void SetActionsDefault(void); // Set the "default" keyset
|
||||
static void SetActionsCursor(void); // Set the "alternate" keyset
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input actions");
|
||||
|
||||
// Set default actions
|
||||
char actionSet = 0;
|
||||
SetActionsDefault();
|
||||
bool releaseAction = false;
|
||||
|
||||
Vector2 position = (Vector2){ 400.0f, 200.0f };
|
||||
Vector2 size = (Vector2){ 40.0f, 40.0f };
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
gamepadIndex = 0; // Set gamepad being checked
|
||||
|
||||
if (IsActionDown(ACTION_UP)) position.y -= 2;
|
||||
if (IsActionDown(ACTION_DOWN)) position.y += 2;
|
||||
if (IsActionDown(ACTION_LEFT)) position.x -= 2;
|
||||
if (IsActionDown(ACTION_RIGHT)) position.x += 2;
|
||||
if (IsActionPressed(ACTION_FIRE))
|
||||
{
|
||||
position.x = (screenWidth-size.x)/2;
|
||||
position.y = (screenHeight-size.y)/2;
|
||||
}
|
||||
|
||||
// Register release action for one frame
|
||||
releaseAction = false;
|
||||
if (IsActionReleased(ACTION_FIRE)) releaseAction = true;
|
||||
|
||||
// Switch control scheme by pressing TAB
|
||||
if (IsKeyPressed(KEY_TAB))
|
||||
{
|
||||
actionSet = !actionSet;
|
||||
if (actionSet == 0) SetActionsDefault();
|
||||
else SetActionsCursor();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(GRAY);
|
||||
|
||||
DrawRectangleV(position, size, releaseAction? BLUE : RED);
|
||||
|
||||
DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Arrow keys", 10, 10, 20, WHITE);
|
||||
DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Check action key/button pressed
|
||||
// NOTE: Combines key pressed and gamepad button pressed in one action
|
||||
static bool IsActionPressed(int action)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (action < MAX_ACTION) result = (IsKeyPressed(actionInputs[action].key) || IsGamepadButtonPressed(gamepadIndex, actionInputs[action].button));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check action key/button released
|
||||
// NOTE: Combines key released and gamepad button released in one action
|
||||
static bool IsActionReleased(int action)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (action < MAX_ACTION) result = (IsKeyReleased(actionInputs[action].key) || IsGamepadButtonReleased(gamepadIndex, actionInputs[action].button));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check action key/button down
|
||||
// NOTE: Combines key down and gamepad button down in one action
|
||||
static bool IsActionDown(int action)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (action < MAX_ACTION) result = (IsKeyDown(actionInputs[action].key) || IsGamepadButtonDown(gamepadIndex, actionInputs[action].button));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set the "default" keyset
|
||||
// NOTE: Here WASD and gamepad buttons on the left side for movement
|
||||
static void SetActionsDefault(void)
|
||||
{
|
||||
actionInputs[ACTION_UP].key = KEY_W;
|
||||
actionInputs[ACTION_DOWN].key = KEY_S;
|
||||
actionInputs[ACTION_LEFT].key = KEY_A;
|
||||
actionInputs[ACTION_RIGHT].key = KEY_D;
|
||||
actionInputs[ACTION_FIRE].key = KEY_SPACE;
|
||||
|
||||
actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_LEFT_FACE_UP;
|
||||
actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
|
||||
actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_LEFT_FACE_LEFT;
|
||||
actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT;
|
||||
actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
|
||||
}
|
||||
|
||||
// Set the "alternate" keyset
|
||||
// NOTE: Here cursor keys and gamepad buttons on the right side for movement
|
||||
static void SetActionsCursor(void)
|
||||
{
|
||||
actionInputs[ACTION_UP].key = KEY_UP;
|
||||
actionInputs[ACTION_DOWN].key = KEY_DOWN;
|
||||
actionInputs[ACTION_LEFT].key = KEY_LEFT;
|
||||
actionInputs[ACTION_RIGHT].key = KEY_RIGHT;
|
||||
actionInputs[ACTION_FIRE].key = KEY_SPACE;
|
||||
|
||||
actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_RIGHT_FACE_UP;
|
||||
actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
|
||||
actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT;
|
||||
actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT;
|
||||
actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,291 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input gamepad
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* NOTE: This example requires a Gamepad connected to the system
|
||||
* raylib is configured to work with the following gamepads:
|
||||
* - Xbox 360 Controller (Xbox 360, Xbox One)
|
||||
* - PLAYSTATION(R)3 Controller
|
||||
* Check raylib.h for buttons configuration
|
||||
*
|
||||
* Example originally created with raylib 1.1, last time updated with raylib 4.2
|
||||
*
|
||||
* 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) 2013-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
// NOTE: Gamepad name ID depends on drivers and OS
|
||||
#define XBOX_ALIAS_1 "xbox"
|
||||
#define XBOX_ALIAS_2 "x-box"
|
||||
#define PS_ALIAS_1 "playstation"
|
||||
#define PS_ALIAS_2 "sony"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT); // Set MSAA 4X hint before windows creation
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gamepad");
|
||||
|
||||
Texture2D texPs3Pad = LoadTexture("resources/ps3.png");
|
||||
Texture2D texXboxPad = LoadTexture("resources/xbox.png");
|
||||
|
||||
// Set axis deadzones
|
||||
const float leftStickDeadzoneX = 0.1f;
|
||||
const float leftStickDeadzoneY = 0.1f;
|
||||
const float rightStickDeadzoneX = 0.1f;
|
||||
const float rightStickDeadzoneY = 0.1f;
|
||||
const float leftTriggerDeadzone = -0.9f;
|
||||
const float rightTriggerDeadzone = -0.9f;
|
||||
|
||||
Rectangle vibrateButton = { 0 };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
int gamepad = 0; // which gamepad to display
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_LEFT) && gamepad > 0) gamepad--;
|
||||
if (IsKeyPressed(KEY_RIGHT)) gamepad++;
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
|
||||
vibrateButton = (Rectangle){ 10, 70.0f + 20*GetGamepadAxisCount(gamepad) + 20, 75, 24 };
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, vibrateButton)) SetGamepadVibration(gamepad, 1.0, 1.0, 1.0);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
if (IsGamepadAvailable(gamepad))
|
||||
{
|
||||
DrawText(TextFormat("GP%d: %s", gamepad, GetGamepadName(gamepad)), 10, 10, 10, BLACK);
|
||||
|
||||
// Get axis values
|
||||
float leftStickX = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_X);
|
||||
float leftStickY = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_Y);
|
||||
float rightStickX = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_X);
|
||||
float rightStickY = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_Y);
|
||||
float leftTrigger = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER);
|
||||
float rightTrigger = GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER);
|
||||
|
||||
// Calculate deadzones
|
||||
if (leftStickX > -leftStickDeadzoneX && leftStickX < leftStickDeadzoneX) leftStickX = 0.0f;
|
||||
if (leftStickY > -leftStickDeadzoneY && leftStickY < leftStickDeadzoneY) leftStickY = 0.0f;
|
||||
if (rightStickX > -rightStickDeadzoneX && rightStickX < rightStickDeadzoneX) rightStickX = 0.0f;
|
||||
if (rightStickY > -rightStickDeadzoneY && rightStickY < rightStickDeadzoneY) rightStickY = 0.0f;
|
||||
if (leftTrigger < leftTriggerDeadzone) leftTrigger = -1.0f;
|
||||
if (rightTrigger < rightTriggerDeadzone) rightTrigger = -1.0f;
|
||||
|
||||
if ((TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_1) > -1) ||
|
||||
(TextFindIndex(TextToLower(GetGamepadName(gamepad)), XBOX_ALIAS_2) > -1))
|
||||
{
|
||||
DrawTexture(texXboxPad, 0, 0, DARKGRAY);
|
||||
|
||||
// Draw buttons: xbox home
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(394, 89, 19, RED);
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawCircle(436, 150, 9, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawCircle(352, 150, 9, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(501, 151, 15, BLUE);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(536, 187, 15, LIME);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(572, 151, 15, MAROON);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(536, 115, 15, GOLD);
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(317, 202, 19, 71, BLACK);
|
||||
DrawRectangle(293, 228, 69, 19, BLACK);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(317, 202, 19, 26, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(317, 202 + 45, 19, 26, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(292, 228, 25, 19, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(292 + 44, 228, 26, 19, RED);
|
||||
|
||||
// Draw buttons: left-right back
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawCircle(259, 61, 20, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(536, 61, 20, RED);
|
||||
|
||||
// Draw axis: left joystick
|
||||
Color leftGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
|
||||
DrawCircle(259, 152, 39, BLACK);
|
||||
DrawCircle(259, 152, 34, LIGHTGRAY);
|
||||
DrawCircle(259 + (int)(leftStickX*20), 152 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
Color rightGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
|
||||
DrawCircle(461, 237, 38, BLACK);
|
||||
DrawCircle(461, 237, 33, LIGHTGRAY);
|
||||
DrawCircle(461 + (int)(rightStickX*20), 237 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(170, 30, 15, 70, GRAY);
|
||||
DrawRectangle(604, 30, 15, 70, GRAY);
|
||||
DrawRectangle(170, 30, 15, (int)(((1 + leftTrigger)/2)*70), RED);
|
||||
DrawRectangle(604, 30, 15, (int)(((1 + rightTrigger)/2)*70), RED);
|
||||
|
||||
//DrawText(TextFormat("Xbox axis LT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_LEFT_TRIGGER)), 10, 40, 10, BLACK);
|
||||
//DrawText(TextFormat("Xbox axis RT: %02.02f", GetGamepadAxisMovement(gamepad, GAMEPAD_AXIS_RIGHT_TRIGGER)), 10, 60, 10, BLACK);
|
||||
}
|
||||
else if ((TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS_1) > -1) ||
|
||||
(TextFindIndex(TextToLower(GetGamepadName(gamepad)), PS_ALIAS_2) > -1))
|
||||
{
|
||||
DrawTexture(texPs3Pad, 0, 0, DARKGRAY);
|
||||
|
||||
// Draw buttons: ps
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(396, 222, 13, RED);
|
||||
|
||||
// Draw buttons: basic
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawRectangle(328, 170, 32, 13, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawTriangle((Vector2){ 436, 168 }, (Vector2){ 436, 185 }, (Vector2){ 464, 177 }, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(557, 144, 13, LIME);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(586, 173, 13, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(557, 203, 13, VIOLET);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(527, 173, 13, PINK);
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(225, 132, 24, 84, BLACK);
|
||||
DrawRectangle(195, 161, 84, 25, BLACK);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(225, 132, 24, 29, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(225, 132 + 54, 24, 30, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(195, 161, 30, 25, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(195 + 54, 161, 30, 25, RED);
|
||||
|
||||
// Draw buttons: left-right back buttons
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawCircle(239, 82, 20, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawCircle(557, 82, 20, RED);
|
||||
|
||||
// Draw axis: left joystick
|
||||
Color leftGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
|
||||
DrawCircle(319, 255, 35, BLACK);
|
||||
DrawCircle(319, 255, 31, LIGHTGRAY);
|
||||
DrawCircle(319 + (int)(leftStickX*20), 255 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
Color rightGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
|
||||
DrawCircle(475, 255, 35, BLACK);
|
||||
DrawCircle(475, 255, 31, LIGHTGRAY);
|
||||
DrawCircle(475 + (int)(rightStickX*20), 255 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(169, 48, 15, 70, GRAY);
|
||||
DrawRectangle(611, 48, 15, 70, GRAY);
|
||||
DrawRectangle(169, 48, 15, (int)(((1 + leftTrigger)/2)*70), RED);
|
||||
DrawRectangle(611, 48, 15, (int)(((1 + rightTrigger)/2)*70), RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Draw background: generic
|
||||
DrawRectangleRounded((Rectangle){ 175, 110, 460, 220}, 0.3f, 16, DARKGRAY);
|
||||
|
||||
// Draw buttons: basic
|
||||
DrawCircle(365, 170, 12, RAYWHITE);
|
||||
DrawCircle(405, 170, 12, RAYWHITE);
|
||||
DrawCircle(445, 170, 12, RAYWHITE);
|
||||
DrawCircle(516, 191, 17, RAYWHITE);
|
||||
DrawCircle(551, 227, 17, RAYWHITE);
|
||||
DrawCircle(587, 191, 17, RAYWHITE);
|
||||
DrawCircle(551, 155, 17, RAYWHITE);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_LEFT)) DrawCircle(365, 170, 10, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE)) DrawCircle(405, 170, 10, GREEN);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_MIDDLE_RIGHT)) DrawCircle(445, 170, 10, BLUE);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_LEFT)) DrawCircle(516, 191, 15, GOLD);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_DOWN)) DrawCircle(551, 227, 15, BLUE);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT)) DrawCircle(587, 191, 15, GREEN);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_FACE_UP)) DrawCircle(551, 155, 15, RED);
|
||||
|
||||
// Draw buttons: d-pad
|
||||
DrawRectangle(245, 145, 28, 88, RAYWHITE);
|
||||
DrawRectangle(215, 174, 88, 29, RAYWHITE);
|
||||
DrawRectangle(247, 147, 24, 84, BLACK);
|
||||
DrawRectangle(217, 176, 84, 25, BLACK);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_UP)) DrawRectangle(247, 147, 24, 29, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) DrawRectangle(247, 147 + 54, 24, 30, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) DrawRectangle(217, 176, 30, 25, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) DrawRectangle(217 + 54, 176, 30, 25, RED);
|
||||
|
||||
// Draw buttons: left-right back
|
||||
DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 16, DARKGRAY);
|
||||
DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 16, DARKGRAY);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 215, 98, 100, 10}, 0.5f, 16, RED);
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_TRIGGER_1)) DrawRectangleRounded((Rectangle){ 495, 98, 100, 10}, 0.5f, 16, RED);
|
||||
|
||||
// Draw axis: left joystick
|
||||
Color leftGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_LEFT_THUMB)) leftGamepadColor = RED;
|
||||
DrawCircle(345, 260, 40, BLACK);
|
||||
DrawCircle(345, 260, 35, LIGHTGRAY);
|
||||
DrawCircle(345 + (int)(leftStickX*20), 260 + (int)(leftStickY*20), 25, leftGamepadColor);
|
||||
|
||||
// Draw axis: right joystick
|
||||
Color rightGamepadColor = BLACK;
|
||||
if (IsGamepadButtonDown(gamepad, GAMEPAD_BUTTON_RIGHT_THUMB)) rightGamepadColor = RED;
|
||||
DrawCircle(465, 260, 40, BLACK);
|
||||
DrawCircle(465, 260, 35, LIGHTGRAY);
|
||||
DrawCircle(465 + (int)(rightStickX*20), 260 + (int)(rightStickY*20), 25, rightGamepadColor);
|
||||
|
||||
// Draw axis: left-right triggers
|
||||
DrawRectangle(151, 110, 15, 70, GRAY);
|
||||
DrawRectangle(644, 110, 15, 70, GRAY);
|
||||
DrawRectangle(151, 110, 15, (int)(((1 + leftTrigger)/2)*70), RED);
|
||||
DrawRectangle(644, 110, 15, (int)(((1 + rightTrigger)/2)*70), RED);
|
||||
}
|
||||
|
||||
DrawText(TextFormat("DETECTED AXIS [%i]:", GetGamepadAxisCount(gamepad)), 10, 50, 10, MAROON);
|
||||
|
||||
for (int i = 0; i < GetGamepadAxisCount(gamepad); i++)
|
||||
{
|
||||
DrawText(TextFormat("AXIS %i: %.02f", i, GetGamepadAxisMovement(gamepad, i)), 20, 70 + 20*i, 10, DARKGRAY);
|
||||
}
|
||||
|
||||
// Draw vibrate button
|
||||
DrawRectangleRec(vibrateButton, SKYBLUE);
|
||||
DrawText("VIBRATE", (int)(vibrateButton.x + 14), (int)(vibrateButton.y + 1), 10, DARKGRAY);
|
||||
|
||||
if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED);
|
||||
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawText(TextFormat("GP%d: NOT DETECTED", gamepad), 10, 10, 10, GRAY);
|
||||
DrawTexture(texXboxPad, 0, 0, LIGHTGRAY);
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texPs3Pad);
|
||||
UnloadTexture(texXboxPad);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 37 KiB |
@ -0,0 +1,123 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input gestures
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 1.4, last time updated with raylib 4.2
|
||||
*
|
||||
* 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) 2016-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define MAX_GESTURE_STRINGS 20
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures");
|
||||
|
||||
Vector2 touchPosition = { 0, 0 };
|
||||
Rectangle touchArea = { 220, 10, screenWidth - 230.0f, screenHeight - 20.0f };
|
||||
|
||||
int gesturesCount = 0;
|
||||
char gestureStrings[MAX_GESTURE_STRINGS][32];
|
||||
|
||||
int currentGesture = GESTURE_NONE;
|
||||
int lastGesture = GESTURE_NONE;
|
||||
|
||||
//SetGesturesEnabled(0b0000000000001001); // Enable only some gestures to be detected
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
lastGesture = currentGesture;
|
||||
currentGesture = GetGestureDetected();
|
||||
touchPosition = GetTouchPosition(0);
|
||||
|
||||
if (CheckCollisionPointRec(touchPosition, touchArea) && (currentGesture != GESTURE_NONE))
|
||||
{
|
||||
if (currentGesture != lastGesture)
|
||||
{
|
||||
// Store gesture string
|
||||
switch (currentGesture)
|
||||
{
|
||||
case GESTURE_TAP: TextCopy(gestureStrings[gesturesCount], "GESTURE TAP"); break;
|
||||
case GESTURE_DOUBLETAP: TextCopy(gestureStrings[gesturesCount], "GESTURE DOUBLETAP"); break;
|
||||
case GESTURE_HOLD: TextCopy(gestureStrings[gesturesCount], "GESTURE HOLD"); break;
|
||||
case GESTURE_DRAG: TextCopy(gestureStrings[gesturesCount], "GESTURE DRAG"); break;
|
||||
case GESTURE_SWIPE_RIGHT: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE RIGHT"); break;
|
||||
case GESTURE_SWIPE_LEFT: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE LEFT"); break;
|
||||
case GESTURE_SWIPE_UP: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE UP"); break;
|
||||
case GESTURE_SWIPE_DOWN: TextCopy(gestureStrings[gesturesCount], "GESTURE SWIPE DOWN"); break;
|
||||
case GESTURE_PINCH_IN: TextCopy(gestureStrings[gesturesCount], "GESTURE PINCH IN"); break;
|
||||
case GESTURE_PINCH_OUT: TextCopy(gestureStrings[gesturesCount], "GESTURE PINCH OUT"); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
gesturesCount++;
|
||||
|
||||
// Reset gestures strings
|
||||
if (gesturesCount >= MAX_GESTURE_STRINGS)
|
||||
{
|
||||
for (int i = 0; i < MAX_GESTURE_STRINGS; i++) TextCopy(gestureStrings[i], "\0");
|
||||
|
||||
gesturesCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawRectangleRec(touchArea, GRAY);
|
||||
DrawRectangle(225, 15, screenWidth - 240, screenHeight - 30, RAYWHITE);
|
||||
|
||||
DrawText("GESTURES TEST AREA", screenWidth - 270, screenHeight - 40, 20, Fade(GRAY, 0.5f));
|
||||
|
||||
for (int i = 0; i < gesturesCount; i++)
|
||||
{
|
||||
if (i%2 == 0) DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.5f));
|
||||
else DrawRectangle(10, 30 + 20*i, 200, 20, Fade(LIGHTGRAY, 0.3f));
|
||||
|
||||
if (i < gesturesCount - 1) DrawText(gestureStrings[i], 35, 36 + 20*i, 10, DARKGRAY);
|
||||
else DrawText(gestureStrings[i], 35, 36 + 20*i, 10, MAROON);
|
||||
}
|
||||
|
||||
DrawRectangleLines(10, 29, 200, screenHeight - 50, GRAY);
|
||||
DrawText("DETECTED GESTURES", 50, 15, 10, GRAY);
|
||||
|
||||
if (currentGesture != GESTURE_NONE) DrawCircleV(touchPosition, 30, MAROON);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,315 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input gestures testbed
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 5.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by ubkp (@ubkp) 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) 2023-2025 ubkp (@ubkp)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <math.h> // Required for the protractor angle graphic drawing
|
||||
|
||||
#define GESTURE_LOG_SIZE 20
|
||||
#define MAX_TOUCH_COUNT 32
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static char const *GetGestureName(int gesture); // Get text string for gesture value
|
||||
static Color GetGestureColor(int gesture); // Get color for gesture value
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures testbed");
|
||||
|
||||
Vector2 messagePosition = { 160, 7 };
|
||||
|
||||
// Last gesture variables definitions
|
||||
int lastGesture = 0;
|
||||
Vector2 lastGesturePosition = { 165, 130 };
|
||||
|
||||
// Gesture log variables definitions
|
||||
// NOTE: The gesture log uses an array (as an inverted circular queue) to store the performed gestures
|
||||
char gestureLog[GESTURE_LOG_SIZE][12] = { "" };
|
||||
// NOTE: The index for the inverted circular queue (moving from last to first direction, then looping around)
|
||||
int gestureLogIndex = GESTURE_LOG_SIZE;
|
||||
int previousGesture = 0;
|
||||
|
||||
// Log mode values:
|
||||
// - 0 shows repeated events
|
||||
// - 1 hides repeated events
|
||||
// - 2 shows repeated events but hide hold events
|
||||
// - 3 hides repeated events and hide hold events
|
||||
int logMode = 1;
|
||||
|
||||
Color gestureColor = { 0, 0, 0, 255 };
|
||||
Rectangle logButton1 = { 53, 7, 48, 26 };
|
||||
Rectangle logButton2 = { 108, 7, 36, 26 };
|
||||
Vector2 gestureLogPosition = { 10, 10 };
|
||||
|
||||
// Protractor variables definitions
|
||||
float angleLength = 90.0f;
|
||||
float currentAngleDegrees = 0.0f;
|
||||
Vector2 finalVector = { 0.0f, 0.0f };
|
||||
Vector2 protractorPosition = { 266.0f, 315.0f };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Handle common gestures data
|
||||
int i, ii; // Iterators that will be reused by all for loops
|
||||
const int currentGesture = GetGestureDetected();
|
||||
const float currentDragDegrees = GetGestureDragAngle();
|
||||
const float currentPitchDegrees = GetGesturePinchAngle();
|
||||
const int touchCount = GetTouchPointCount();
|
||||
|
||||
// Handle last gesture
|
||||
if ((currentGesture != 0) && (currentGesture != 4) && (currentGesture != previousGesture))
|
||||
lastGesture = currentGesture; // Filter the meaningful gestures (1, 2, 8 to 512) for the display
|
||||
|
||||
// Handle gesture log
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
if (CheckCollisionPointRec(GetMousePosition(), logButton1))
|
||||
{
|
||||
switch (logMode)
|
||||
{
|
||||
case 3: logMode = 2; break;
|
||||
case 2: logMode = 3; break;
|
||||
case 1: logMode = 0; break;
|
||||
default: logMode = 1; break;
|
||||
}
|
||||
}
|
||||
else if (CheckCollisionPointRec(GetMousePosition(), logButton2))
|
||||
{
|
||||
switch (logMode)
|
||||
{
|
||||
case 3: logMode = 1; break;
|
||||
case 2: logMode = 0; break;
|
||||
case 1: logMode = 3; break;
|
||||
default: logMode = 2; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int fillLog = 0; // Gate variable to be used to allow or not the gesture log to be filled
|
||||
if (currentGesture !=0)
|
||||
{
|
||||
if (logMode == 3) // 3 hides repeated events and hide hold events
|
||||
{
|
||||
if (((currentGesture != 4) && (currentGesture != previousGesture)) || (currentGesture < 3)) fillLog = 1;
|
||||
}
|
||||
else if (logMode == 2) // 2 shows repeated events but hide hold events
|
||||
{
|
||||
if (currentGesture != 4) fillLog = 1;
|
||||
}
|
||||
else if (logMode == 1) // 1 hides repeated events
|
||||
{
|
||||
if (currentGesture != previousGesture) fillLog = 1;
|
||||
}
|
||||
else // 0 shows repeated events
|
||||
{
|
||||
fillLog = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fillLog) // If one of the conditions from logMode was met, fill the gesture log
|
||||
{
|
||||
previousGesture = currentGesture;
|
||||
gestureColor = GetGestureColor(currentGesture);
|
||||
if (gestureLogIndex <= 0) gestureLogIndex = GESTURE_LOG_SIZE;
|
||||
gestureLogIndex--;
|
||||
|
||||
// Copy the gesture respective name to the gesture log array
|
||||
TextCopy(gestureLog[gestureLogIndex], GetGestureName(currentGesture));
|
||||
}
|
||||
|
||||
// Handle protractor
|
||||
if (currentGesture > 255) currentAngleDegrees = currentPitchDegrees; // Pinch In and Pinch Out
|
||||
else if (currentGesture > 15) currentAngleDegrees = currentDragDegrees; // Swipe Right, Swipe Left, Swipe Up and Swipe Down
|
||||
else if (currentGesture > 0) currentAngleDegrees = 0.0f; // Tap, Doubletap, Hold and Grab
|
||||
|
||||
float currentAngleRadians = ((currentAngleDegrees + 90.0f)*PI/180); // Convert the current angle to Radians
|
||||
// Calculate the final vector for display
|
||||
finalVector = (Vector2){ (angleLength*sinf(currentAngleRadians)) + protractorPosition.x,
|
||||
(angleLength*cosf(currentAngleRadians)) + protractorPosition.y };
|
||||
|
||||
// Handle touch and mouse pointer points
|
||||
Vector2 touchPosition[MAX_TOUCH_COUNT] = { 0 };
|
||||
Vector2 mousePosition = { 0 };
|
||||
if (currentGesture != GESTURE_NONE)
|
||||
{
|
||||
if (touchCount != 0)
|
||||
{
|
||||
for (i = 0; i < touchCount; i++) touchPosition[i] = GetTouchPosition(i); // Fill the touch positions
|
||||
}
|
||||
else mousePosition = GetMousePosition();
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Draw common elements
|
||||
DrawText("*", (int)messagePosition.x + 5, (int)messagePosition.y + 5, 10, BLACK);
|
||||
DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", (int)messagePosition.x + 15, (int)messagePosition.y + 5, 10, BLACK);
|
||||
DrawText("*", (int)messagePosition.x + 5, (int)messagePosition.y + 35, 10, BLACK);
|
||||
DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.", (int)messagePosition.x + 15, (int)messagePosition.y + 35, 10, BLACK);
|
||||
|
||||
// Draw last gesture
|
||||
DrawText("Last gesture", (int)lastGesturePosition.x + 33, (int)lastGesturePosition.y - 47, 20, BLACK);
|
||||
DrawText("Swipe Tap Pinch Touch", (int)lastGesturePosition.x + 17, (int)lastGesturePosition.y - 18, 10, BLACK);
|
||||
DrawRectangle((int)lastGesturePosition.x + 20, (int)lastGesturePosition.y, 20, 20, lastGesture == GESTURE_SWIPE_UP ? RED : LIGHTGRAY);
|
||||
DrawRectangle((int)lastGesturePosition.x, (int)lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_LEFT ? RED : LIGHTGRAY);
|
||||
DrawRectangle((int)lastGesturePosition.x + 40, (int)lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_RIGHT ? RED : LIGHTGRAY);
|
||||
DrawRectangle((int)lastGesturePosition.x + 20, (int)lastGesturePosition.y + 40, 20, 20, lastGesture == GESTURE_SWIPE_DOWN ? RED : LIGHTGRAY);
|
||||
DrawCircle((int)lastGesturePosition.x + 80, (int)lastGesturePosition.y + 16, 10, lastGesture == GESTURE_TAP ? BLUE : LIGHTGRAY);
|
||||
DrawRing( (Vector2){lastGesturePosition.x + 103, lastGesturePosition.y + 16}, 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == GESTURE_DRAG ? LIME : LIGHTGRAY);
|
||||
DrawCircle((int)lastGesturePosition.x + 80, (int)lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY);
|
||||
DrawCircle((int)lastGesturePosition.x + 103, (int)lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY);
|
||||
DrawTriangle((Vector2){ lastGesturePosition.x + 122, lastGesturePosition.y + 16 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 26 }, (Vector2){lastGesturePosition.x + 137, lastGesturePosition.y + 6 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY);
|
||||
DrawTriangle((Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 6 }, (Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 26 }, (Vector2){ lastGesturePosition.x + 162, lastGesturePosition.y + 16 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY);
|
||||
DrawTriangle((Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 33 }, (Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 140, lastGesturePosition.y + 43 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY);
|
||||
DrawTriangle((Vector2){ lastGesturePosition.x + 144, lastGesturePosition.y + 43 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 33 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY);
|
||||
for (i = 0; i < 4; i++) DrawCircle((int)lastGesturePosition.x + 180, (int)lastGesturePosition.y + 7 + i*15, 5, touchCount <= i? LIGHTGRAY : gestureColor);
|
||||
|
||||
// Draw gesture log
|
||||
DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK);
|
||||
|
||||
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
|
||||
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1)%GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY));
|
||||
Color logButton1Color, logButton2Color;
|
||||
switch (logMode)
|
||||
{
|
||||
case 3: logButton1Color=MAROON; logButton2Color=MAROON; break;
|
||||
case 2: logButton1Color=GRAY; logButton2Color=MAROON; break;
|
||||
case 1: logButton1Color=MAROON; logButton2Color=GRAY; break;
|
||||
default: logButton1Color=GRAY; logButton2Color=GRAY; break;
|
||||
}
|
||||
DrawRectangleRec(logButton1, logButton1Color);
|
||||
DrawText("Hide", (int)logButton1.x + 7, (int)logButton1.y + 3, 10, WHITE);
|
||||
DrawText("Repeat", (int)logButton1.x + 7, (int)logButton1.y + 13, 10, WHITE);
|
||||
DrawRectangleRec(logButton2, logButton2Color);
|
||||
DrawText("Hide", (int)logButton1.x + 62, (int)logButton1.y + 3, 10, WHITE);
|
||||
DrawText("Hold", (int)logButton1.x + 62, (int)logButton1.y + 13, 10, WHITE);
|
||||
|
||||
// Draw protractor
|
||||
DrawText("Angle", (int)protractorPosition.x + 55, (int)protractorPosition.y + 76, 10, BLACK);
|
||||
const char *angleString = TextFormat("%f", currentAngleDegrees);
|
||||
const int angleStringDot = TextFindIndex(angleString, ".");
|
||||
const char *angleStringTrim = TextSubtext(angleString, 0, angleStringDot + 3);
|
||||
DrawText( angleStringTrim, (int)protractorPosition.x + 55, (int)protractorPosition.y + 92, 20, gestureColor);
|
||||
DrawCircleV(protractorPosition, 80.0f, WHITE);
|
||||
DrawLineEx((Vector2){ protractorPosition.x - 90, protractorPosition.y }, (Vector2){ protractorPosition.x + 90, protractorPosition.y }, 3.0f, LIGHTGRAY);
|
||||
DrawLineEx((Vector2){ protractorPosition.x, protractorPosition.y - 90 }, (Vector2){ protractorPosition.x, protractorPosition.y + 90 }, 3.0f, LIGHTGRAY);
|
||||
DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y - 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y + 45 }, 3.0f, GREEN);
|
||||
DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y + 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y - 45 }, 3.0f, GREEN);
|
||||
DrawText("0", (int)protractorPosition.x + 96, (int)protractorPosition.y - 9, 20, BLACK);
|
||||
DrawText("30", (int)protractorPosition.x + 74, (int)protractorPosition.y - 68, 20, BLACK);
|
||||
DrawText("90", (int)protractorPosition.x - 11, (int)protractorPosition.y - 110, 20, BLACK);
|
||||
DrawText("150", (int)protractorPosition.x - 100, (int)protractorPosition.y - 68, 20, BLACK);
|
||||
DrawText("180", (int)protractorPosition.x - 124, (int)protractorPosition.y - 9, 20, BLACK);
|
||||
DrawText("210", (int)protractorPosition.x - 100, (int)protractorPosition.y + 50, 20, BLACK);
|
||||
DrawText("270", (int)protractorPosition.x - 18, (int)protractorPosition.y + 92, 20, BLACK);
|
||||
DrawText("330", (int)protractorPosition.x + 72, (int)protractorPosition.y + 50, 20, BLACK);
|
||||
if (currentAngleDegrees != 0.0f) DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor);
|
||||
|
||||
// Draw touch and mouse pointer points
|
||||
if (currentGesture != GESTURE_NONE)
|
||||
{
|
||||
if ( touchCount != 0 )
|
||||
{
|
||||
for (i = 0; i < touchCount; i++)
|
||||
{
|
||||
DrawCircleV(touchPosition[i], 50.0f, Fade(gestureColor, 0.5f));
|
||||
DrawCircleV(touchPosition[i], 5.0f, gestureColor);
|
||||
}
|
||||
|
||||
if (touchCount == 2) DrawLineEx(touchPosition[0], touchPosition[1], ((currentGesture == 512)? 8.0f : 12.0f), gestureColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawCircleV(mousePosition, 35.0f, Fade(gestureColor, 0.5f));
|
||||
DrawCircleV(mousePosition, 5.0f, gestureColor);
|
||||
}
|
||||
}
|
||||
|
||||
EndDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
// Get text string for gesture value
|
||||
static char const *GetGestureName(int gesture)
|
||||
{
|
||||
switch (gesture)
|
||||
{
|
||||
case 0: return "None"; break;
|
||||
case 1: return "Tap"; break;
|
||||
case 2: return "Double Tap"; break;
|
||||
case 4: return "Hold"; break;
|
||||
case 8: return "Drag"; break;
|
||||
case 16: return "Swipe Right"; break;
|
||||
case 32: return "Swipe Left"; break;
|
||||
case 64: return "Swipe Up"; break;
|
||||
case 128: return "Swipe Down"; break;
|
||||
case 256: return "Pinch In"; break;
|
||||
case 512: return "Pinch Out"; break;
|
||||
default: return "Unknown"; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get color for gesture value
|
||||
static Color GetGestureColor(int gesture)
|
||||
{
|
||||
switch (gesture)
|
||||
{
|
||||
case 0: return BLACK; break;
|
||||
case 1: return BLUE; break;
|
||||
case 2: return SKYBLUE; break;
|
||||
case 4: return BLACK; break;
|
||||
case 8: return LIME; break;
|
||||
case 16: return RED; break;
|
||||
case 32: return RED; break;
|
||||
case 64: return RED; break;
|
||||
case 128: return RED; break;
|
||||
case 256: return VIOLET; break;
|
||||
case 512: return ORANGE; break;
|
||||
default: return BLACK; break;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.7 KiB |
@ -0,0 +1,66 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input keys
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input keys");
|
||||
|
||||
Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 };
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KEY_RIGHT)) ballPosition.x += 2.0f;
|
||||
if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 2.0f;
|
||||
if (IsKeyDown(KEY_UP)) ballPosition.y -= 2.0f;
|
||||
if (IsKeyDown(KEY_DOWN)) ballPosition.y += 2.0f;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("move the ball with arrow keys", 10, 10, 20, DARKGRAY);
|
||||
|
||||
DrawCircleV(ballPosition, 50, MAROON);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,82 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [core] example - input mouse
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 1.0, last time updated with raylib 5.5
|
||||
*
|
||||
* 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) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - input mouse");
|
||||
|
||||
Vector2 ballPosition = { -100.0f, -100.0f };
|
||||
Color ballColor = DARKBLUE;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_H))
|
||||
{
|
||||
if (IsCursorHidden()) ShowCursor();
|
||||
else HideCursor();
|
||||
}
|
||||
|
||||
ballPosition = GetMousePosition();
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) ballColor = MAROON;
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) ballColor = LIME;
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) ballColor = DARKBLUE;
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_SIDE)) ballColor = PURPLE;
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_EXTRA)) ballColor = YELLOW;
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_FORWARD)) ballColor = ORANGE;
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_BACK)) ballColor = BEIGE;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawCircleV(ballPosition, 40, ballColor);
|
||||
|
||||
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY);
|
||||
DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, DARKGRAY);
|
||||
|
||||
if (IsCursorHidden()) DrawText("CURSOR HIDDEN", 20, 60, 20, RED);
|
||||
else DrawText("CURSOR VISIBLE", 20, 60, 20, LIME);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||