Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4d18b2d1c | ||
|
|
3cd4d3179d | ||
|
|
6ecc0455eb | ||
|
|
d9933008f5 | ||
|
|
163b1ef2e9 | ||
|
|
1e257d1738 | ||
|
|
a1d02a5ec8 | ||
|
|
0248dc6e98 | ||
|
|
d64fc43f38 | ||
|
|
39ce5d4a8e | ||
|
|
33f216d4fc | ||
|
|
651b37a025 | ||
|
|
c84506a92d | ||
|
|
9ad8b8ba74 | ||
|
|
c7ea429994 | ||
|
|
ed42d5dbdc | ||
|
|
c5d9cf405d | ||
|
|
acd5507b0e | ||
|
|
b44a355a81 | ||
|
|
df70c5c952 | ||
|
|
4bb5254d6b | ||
|
|
e623387b8c | ||
|
|
166996bccc | ||
|
|
42956d00c0 | ||
|
|
d39c75c234 | ||
|
|
180d2e04de | ||
|
|
10c8f7d7ad | ||
|
|
6efd4175ef | ||
|
|
a787270fea | ||
|
|
6ab4e51407 | ||
|
|
3c33e0469f | ||
|
|
55937dd8a9 | ||
|
|
492e809dd5 | ||
|
|
178530d5f5 | ||
|
|
dfea9ed840 | ||
|
|
125ead95a3 | ||
|
|
813f0323af | ||
|
|
346e87c8aa | ||
|
|
be3790195a | ||
|
|
52767eb8ae | ||
|
|
b7d89cb7b9 | ||
|
|
7bdb0cd320 | ||
|
|
a6e9ce520f | ||
|
|
3eee232f10 | ||
|
|
22bb251252 | ||
|
|
ac0b07c4bd | ||
|
|
e8167c2e56 | ||
|
|
14f49a38dd | ||
|
|
5013830647 | ||
|
|
97cb212bf0 | ||
|
|
3bf08a304c | ||
|
|
2e60ac0127 | ||
|
|
0de5f8aed0 | ||
|
|
67fd5af55a | ||
|
|
f4b69764db | ||
|
|
d6c77762cb | ||
|
|
c30197911a | ||
|
|
a00552ea79 | ||
|
|
e072ff119b | ||
|
|
dfe22275cf | ||
|
|
8d5a7d382c | ||
|
|
d4fc514d54 | ||
|
|
03ec79ef85 | ||
|
|
17a1754271 | ||
|
|
a7f626993c | ||
|
|
5bbafa4f86 | ||
|
|
b6af3509c8 | ||
|
|
e18e2db5e5 | ||
|
|
1a9b848c06 | ||
|
|
279bcc0a13 | ||
|
|
9444b5a438 | ||
|
|
57a8a21b48 | ||
|
|
9e69ca5946 | ||
|
|
1b6a05ca3b | ||
|
|
e4d66a8dae | ||
|
|
94fa7e23b0 | ||
|
|
bc82c6ebd7 | ||
|
|
4d452b2bcd | ||
|
|
8e5ef1045d | ||
|
|
d3fdd327d5 | ||
|
|
09ec2ca22b | ||
|
|
9882dd4ba1 | ||
|
|
5004bb2316 | ||
|
|
9faf4b97a1 | ||
|
|
58724227e7 | ||
|
|
ae7cb3fa93 | ||
|
|
ae76994a2d | ||
|
|
1ef4995f82 | ||
|
|
cb9fb452c6 | ||
|
|
41022159ad | ||
|
|
30ce68004f | ||
|
|
561481f4ae | ||
|
|
f8b1495c69 | ||
|
|
882b69d8c9 | ||
|
|
9f30de1eac | ||
|
|
3720deda6d | ||
|
|
a7deec3964 | ||
|
|
2fcdf3af45 | ||
|
|
16f4871846 | ||
|
|
21e7bb8cd3 | ||
|
|
2a569ea2ef | ||
|
|
4e08de5584 | ||
|
|
350388c8ec | ||
|
|
4e05ee5a3f | ||
|
|
57041e707c | ||
|
|
16a388c9c2 | ||
|
|
265461f4ec | ||
|
|
845af357e4 | ||
|
|
0dcee846f4 | ||
|
|
de8c2d4585 | ||
|
|
606d9bb9ba | ||
|
|
94570c4b60 | ||
|
|
ff775330c7 | ||
|
|
90109ff804 | ||
|
|
2f773da6b3 | ||
|
|
a420751c0d | ||
|
|
f5abffe4f7 | ||
|
|
6c0774619d | ||
|
|
c191e12e7c | ||
|
|
817f91b57c | ||
|
|
a6f94ce655 | ||
|
|
a2397363aa | ||
|
|
01b6e1a2e2 | ||
|
|
855ab9cd70 | ||
|
|
a087398387 | ||
|
|
d4541b29e0 | ||
|
|
1224eb2290 | ||
|
|
c94e68d872 | ||
|
|
6418a87091 | ||
|
|
87e18ab398 | ||
|
|
d7d9e41863 | ||
|
|
f26b2ab084 | ||
|
|
e3e3a7518a | ||
|
|
2176d37bcc |
95
README.md
Executable file → Normal file
@ -1,12 +1,12 @@
|
||||

|
||||

|
||||
|
||||
# raylib-zig
|
||||
|
||||
Manually tweaked, auto-generated [raylib](https://github.com/raysan5/raylib) bindings for zig.
|
||||
|
||||
Bindings tested on raylib version 5.1-dev and Zig 0.13.0
|
||||
Bindings tested on raylib version 5.6-dev and Zig 0.15.1
|
||||
|
||||
Thanks to all the [contributors](https://github.com/Not-Nik/raylib-zig/graphs/contributors) for their help with this
|
||||
Thanks to all the [contributors](https://github.com/raylib-zig/raylib-zig/graphs/contributors) for their help with this
|
||||
binding.
|
||||
|
||||
## Example
|
||||
@ -38,9 +38,9 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.white);
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawText("Congrats! You created your first window!", 190, 200, 20, rl.Color.light_gray);
|
||||
rl.drawText("Congrats! You created your first window!", 190, 200, 20, .light_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@ -55,22 +55,22 @@ want to run an example, say `basic_window` run `zig build basic_window`
|
||||
|
||||
### Using raylib-zig's template
|
||||
|
||||
* Execute `project_setup.sh project_name`, this will create a folder with the name specified
|
||||
* You can copy that folder anywhere you want and edit the source
|
||||
* Run `zig build run` at any time to test your project
|
||||
- Execute `project_setup.sh project_name`, this will create a folder with the name specified
|
||||
- You can copy that folder anywhere you want and edit the source
|
||||
- Run `zig build run` at any time to test your project
|
||||
|
||||
### In an existing project (e.g. created with `zig init`)
|
||||
|
||||
Download and add raylib-zig as a dependency by running the following command in your project root:
|
||||
|
||||
```
|
||||
zig fetch --save https://github.com/Not-Nik/raylib-zig/archive/devel.tar.gz
|
||||
zig fetch --save git+https://github.com/raylib-zig/raylib-zig#devel
|
||||
```
|
||||
|
||||
Then add raylib-zig as a dependency and import its modules and artifact in your `build.zig`:
|
||||
|
||||
```zig
|
||||
const raylib_dep = b.dependency("raylib-zig", .{
|
||||
const raylib_dep = b.dependency("raylib_zig", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
@ -88,31 +88,80 @@ exe.root_module.addImport("raylib", raylib);
|
||||
exe.root_module.addImport("raygui", raygui);
|
||||
```
|
||||
|
||||
If you additionally want to support Web as a platform with emscripten, you will need to use `emcc.zig` by importing
|
||||
raylib-zig's build script with `const rlz = @import("raylib-zig");` and then accessing its functions with `rlz.emcc`.
|
||||
If you additionally want to support Web as a platform with emscripten, you will need to use `emsdk` by importing
|
||||
raylib-zig's build script with `const rlz = @import("raylib_zig");` and then accessing like described here [Exporting for web](https://github.com/raylib-zig/raylib-zig?tab=readme-ov-file#exporting-for-web).
|
||||
Refer to raylib-zig's project template on how to use them.
|
||||
|
||||
### Passing build options
|
||||
|
||||
raylib allows customisations of certain parts of its build process such as choosing an OpenGL version, building as a
|
||||
shared library or not including certain modules. You can optionally pass these options to raylib-zig dependency like so
|
||||
|
||||
```zig
|
||||
const raylib_dep = b.dependency("raylib_zig", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.linkage = .dynamic, // Build raylib as a shared library
|
||||
.opengl_version = rlz.OpenglVersion.gl_2_1, // Use OpenGL 2.1 (requires importing raylib-zig's build script)
|
||||
});
|
||||
```
|
||||
|
||||
### Defining feature macros
|
||||
|
||||
Raylib lets the user enable and disable options for different features, loading different file formats for images,
|
||||
raylib lets the user enable and disable options for different features, loading different file formats for images,
|
||||
fonts, 3D models and audio, linkage variants. You can specify these options for your raylib-zig build by defining the
|
||||
corresponding C macro before you link with it, e.g.:
|
||||
|
||||
```zig
|
||||
raylib_artifact.defineCMacro("SUPPORT_FILEFORMAT_JPG", null);
|
||||
raylib_artifact.root_module.addCMacro("SUPPORT_FILEFORMAT_JPG", "");
|
||||
```
|
||||
|
||||
## Exporting for web
|
||||
To export your project for the web, first install emsdk.
|
||||
Once emsdk is installed, set it up by running
|
||||
|
||||
`emsdk install latest`
|
||||
To export your project for the web, first add emsdk to your dependencies.
|
||||
Its also possible to use a local emsdk folder.
|
||||
|
||||
Find the folder where it's installed and run
|
||||
`zig fetch --save=emsdk git+https://github.com/emscripten-core/emsdk#4.0.9`
|
||||
|
||||
`zig build -Dtarget=wasm32-emscripten --sysroot [path to emsdk]/upstream/emscripten`
|
||||
Add this to your build method to build for the web
|
||||
|
||||
once that is finished, the exported project should be located at `zig-out/htmlout`
|
||||
```zig
|
||||
if (target.query.os_tag == .emscripten) {
|
||||
const emsdk = rlz.emsdk;
|
||||
const wasm = b.addLibrary(.{
|
||||
.name = <your_project_name>,
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
|
||||
const install_dir: std.Build.InstallDir = .{ .custom = "web" };
|
||||
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_artifact, wasm, .{
|
||||
.optimize = optimize,
|
||||
.flags = emcc_flags,
|
||||
.settings = emcc_settings,
|
||||
.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);
|
||||
}
|
||||
```
|
||||
|
||||
then you can run
|
||||
|
||||
`zig build -Dtarget=wasm32-emscripten`
|
||||
|
||||
once that is finished, the exported project should be located at `zig-out/web`
|
||||
|
||||
### When is the binding updated?
|
||||
|
||||
@ -121,6 +170,6 @@ implementation stuff should be updatable with some hacks on your side.
|
||||
|
||||
### What needs to be done?
|
||||
|
||||
+ _(Done)_ Set up a proper package build and a build script for the examples
|
||||
+ Port all the examples
|
||||
+ Member functions/initialisers
|
||||
- _(Done)_ Set up a proper package build and a build script for the examples
|
||||
- Port all the examples
|
||||
- Member functions/initialisers
|
||||
|
||||
485
build.zig
Executable file → Normal file
@ -3,35 +3,12 @@
|
||||
const std = @import("std");
|
||||
const this = @This();
|
||||
const rl = @import("raylib");
|
||||
pub const emsdk = rl.emsdk;
|
||||
|
||||
pub const emcc = @import("emcc.zig");
|
||||
|
||||
pub const Options = struct {
|
||||
raudio: bool = true,
|
||||
rmodels: bool = true,
|
||||
rshapes: bool = true,
|
||||
rtext: bool = true,
|
||||
rtextures: bool = true,
|
||||
platform_drm: bool = false,
|
||||
shared: bool = false,
|
||||
linux_display_backend: LinuxDisplayBackend = .X11,
|
||||
opengl_version: OpenglVersion = .auto,
|
||||
};
|
||||
|
||||
pub const OpenglVersion = enum {
|
||||
auto,
|
||||
gl_1_1,
|
||||
gl_2_1,
|
||||
gl_3_3,
|
||||
gl_4_3,
|
||||
gles_2,
|
||||
gles_3,
|
||||
};
|
||||
|
||||
pub const LinuxDisplayBackend = enum {
|
||||
X11,
|
||||
Wayland,
|
||||
};
|
||||
pub const Options = rl.Options;
|
||||
pub const OpenglVersion = rl.OpenglVersion;
|
||||
pub const LinuxDisplayBackend = rl.LinuxDisplayBackend;
|
||||
pub const PlatformBackend = rl.PlatformBackend;
|
||||
|
||||
const Program = struct {
|
||||
name: []const u8,
|
||||
@ -39,103 +16,37 @@ const Program = struct {
|
||||
desc: []const u8,
|
||||
};
|
||||
|
||||
fn link(
|
||||
b: *std.Build,
|
||||
exe: *std.Build.Step.Compile,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
options: Options
|
||||
) void {
|
||||
const lib = getRaylib(b, target, optimize, options);
|
||||
fn getRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) *std.Build.Step.Compile {
|
||||
const raylib_dep = b.dependency("raylib", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.raudio = options.raudio,
|
||||
.rmodels = options.rmodels,
|
||||
.rshapes = options.rshapes,
|
||||
.rtext = options.rtext,
|
||||
.rtextures = options.rtextures,
|
||||
.platform = options.platform,
|
||||
.linkage = options.linkage,
|
||||
.linux_display_backend = options.linux_display_backend,
|
||||
.opengl_version = options.opengl_version,
|
||||
.android_api_version = options.android_api_version,
|
||||
.android_ndk = options.android_ndk,
|
||||
});
|
||||
|
||||
const target_os = exe.rootModuleTarget().os.tag;
|
||||
switch (target_os) {
|
||||
.windows => {
|
||||
exe.linkSystemLibrary("winmm");
|
||||
exe.linkSystemLibrary("gdi32");
|
||||
exe.linkSystemLibrary("opengl32");
|
||||
},
|
||||
.macos => {
|
||||
exe.linkFramework("OpenGL");
|
||||
exe.linkFramework("Cocoa");
|
||||
exe.linkFramework("IOKit");
|
||||
exe.linkFramework("CoreAudio");
|
||||
exe.linkFramework("CoreVideo");
|
||||
},
|
||||
.freebsd, .openbsd, .netbsd, .dragonfly => {
|
||||
exe.linkSystemLibrary("GL");
|
||||
exe.linkSystemLibrary("rt");
|
||||
exe.linkSystemLibrary("dl");
|
||||
exe.linkSystemLibrary("m");
|
||||
exe.linkSystemLibrary("X11");
|
||||
exe.linkSystemLibrary("Xrandr");
|
||||
exe.linkSystemLibrary("Xinerama");
|
||||
exe.linkSystemLibrary("Xi");
|
||||
exe.linkSystemLibrary("Xxf86vm");
|
||||
exe.linkSystemLibrary("Xcursor");
|
||||
},
|
||||
.emscripten, .wasi => {
|
||||
// When using emscripten, the libries don't need to be linked
|
||||
// because emscripten is going to do that later.
|
||||
},
|
||||
else => { // Linux and possibly others.
|
||||
exe.linkSystemLibrary("GL");
|
||||
exe.linkSystemLibrary("rt");
|
||||
exe.linkSystemLibrary("dl");
|
||||
exe.linkSystemLibrary("m");
|
||||
exe.linkSystemLibrary("X11");
|
||||
},
|
||||
}
|
||||
const raylib = raylib_dep.artifact("raylib");
|
||||
|
||||
exe.linkLibrary(lib);
|
||||
const raygui_dep = b.dependency("raygui", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
rl.addRaygui(b, raylib, raygui_dep, options);
|
||||
|
||||
b.installArtifact(raylib);
|
||||
return raylib;
|
||||
}
|
||||
|
||||
var _raylib_lib_cache: ?*std.Build.Step.Compile = null;
|
||||
fn getRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.Mode, options: Options) *std.Build.Step.Compile {
|
||||
if (_raylib_lib_cache) |lib| return lib else {
|
||||
const raylib = b.dependency("raylib", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.raudio = options.raudio,
|
||||
.rmodels = options.rmodels,
|
||||
.rshapes = options.rshapes,
|
||||
.rtext = options.rtext,
|
||||
.rtextures = options.rtextures,
|
||||
.platform_drm = options.platform_drm,
|
||||
.shared = options.shared,
|
||||
.linux_display_backend = options.linux_display_backend,
|
||||
.opengl_version = options.opengl_version
|
||||
});
|
||||
|
||||
const lib = raylib.artifact("raylib");
|
||||
|
||||
const raygui_dep = b.dependency("raygui", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
var gen_step = b.addWriteFiles();
|
||||
lib.step.dependOn(&gen_step.step);
|
||||
|
||||
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
|
||||
lib.addCSourceFile(.{ .file = raygui_c_path, .flags = &[_][]const u8{
|
||||
"-std=gnu99",
|
||||
"-D_GNU_SOURCE",
|
||||
"-DGL_SILENCE_DEPRECATION=199309L",
|
||||
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/3674
|
||||
}});
|
||||
lib.addIncludePath(raylib.path("src"));
|
||||
lib.addIncludePath(raygui_dep.path("src"));
|
||||
|
||||
lib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
|
||||
|
||||
b.installArtifact(lib);
|
||||
_raylib_lib_cache = lib;
|
||||
return lib;
|
||||
}
|
||||
}
|
||||
|
||||
fn getModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.Mode) *std.Build.Module {
|
||||
fn getModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Module {
|
||||
if (b.modules.contains("raylib")) {
|
||||
return b.modules.get("raylib").?;
|
||||
}
|
||||
@ -147,7 +58,7 @@ fn getModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.buil
|
||||
}
|
||||
|
||||
const gui = struct {
|
||||
fn getModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.Mode) *std.Build.Module {
|
||||
fn getModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Module {
|
||||
const raylib = this.getModule(b, target, optimize);
|
||||
return b.addModule("raygui", .{
|
||||
.root_source_file = b.path("lib/raygui.zig"),
|
||||
@ -162,18 +73,11 @@ pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const defaults = Options{};
|
||||
const options = Options{
|
||||
.platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)") orelse defaults.platform_drm,
|
||||
.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,
|
||||
.shared = b.option(bool, "shared", "Compile as shared library") orelse defaults.shared,
|
||||
.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,
|
||||
};
|
||||
const raylib_artifact = this.getRaylib(b, target, optimize, Options.getOptions(b));
|
||||
const raylib = this.getModule(b, target, optimize);
|
||||
const raygui = this.gui.getModule(b, target, optimize);
|
||||
|
||||
raylib.linkLibrary(raylib_artifact);
|
||||
|
||||
const examples = [_]Program{
|
||||
.{
|
||||
@ -181,6 +85,21 @@ pub fn build(b: *std.Build) !void {
|
||||
.path = "examples/audio/raw_stream.zig",
|
||||
.desc = "Plays a sine wave",
|
||||
},
|
||||
.{
|
||||
.name = "music_stream",
|
||||
.path = "examples/audio/music_stream.zig",
|
||||
.desc = "Use music stream to play an audio file",
|
||||
},
|
||||
.{
|
||||
.name = "sound_loading",
|
||||
.path = "examples/audio/sound_loading.zig",
|
||||
.desc = "Load and play a song",
|
||||
},
|
||||
.{
|
||||
.name = "module_playing",
|
||||
.path = "examples/audio/module_playing.zig",
|
||||
.desc = "Module playing (streaming)",
|
||||
},
|
||||
.{
|
||||
.name = "basic_screen_manager",
|
||||
.path = "examples/core/basic_screen_manager.zig",
|
||||
@ -191,6 +110,16 @@ pub fn build(b: *std.Build) !void {
|
||||
.path = "examples/core/basic_window.zig",
|
||||
.desc = "Creates a basic window with text",
|
||||
},
|
||||
.{
|
||||
.name = "core_monitor_change",
|
||||
.path = "examples/core/core_monitor_change.zig",
|
||||
.desc = "Simple Monitor Manager",
|
||||
},
|
||||
.{
|
||||
.name = "basic_window_web",
|
||||
.path = "examples/core/basic_window_web.zig",
|
||||
.desc = "Creates a basic window with text (web)",
|
||||
},
|
||||
.{
|
||||
.name = "input_keys",
|
||||
.path = "examples/core/input_keys.zig",
|
||||
@ -216,22 +145,66 @@ pub fn build(b: *std.Build) !void {
|
||||
.path = "examples/core/2d_camera.zig",
|
||||
.desc = "Shows the functionality of a 2D camera",
|
||||
},
|
||||
.{
|
||||
.name = "2d_camera_platformer",
|
||||
.path = "examples/core/2d_camera_platformer.zig",
|
||||
.desc = "2D camera platformer",
|
||||
},
|
||||
.{
|
||||
.name = "3d_camera_first_person",
|
||||
.path = "examples/core/3d_camera_first_person.zig",
|
||||
.desc = "Simple first person demo",
|
||||
},
|
||||
.{
|
||||
.name = "3d_camera_free",
|
||||
.path = "examples/core/3d_camera_free.zig",
|
||||
.desc = "Shows basic 3d camera initialization",
|
||||
},
|
||||
.{
|
||||
.name = "2d_camera_mouse_zoom",
|
||||
.path = "examples/core/2d_camera_mouse_zoom.zig",
|
||||
.desc = "Shows mouse zoom demo",
|
||||
},
|
||||
|
||||
.{
|
||||
.name = "3d_picking",
|
||||
.path = "examples/core/3d_picking.zig",
|
||||
.desc = "Shows picking in 3d mode",
|
||||
},
|
||||
.{
|
||||
.name = "drop_files",
|
||||
.path = "examples/core/drop_files.zig",
|
||||
.desc = "Demonstrates how to implement a drop files functionality",
|
||||
},
|
||||
.{
|
||||
.name = "window_flags",
|
||||
.path = "examples/core/window_flags.zig",
|
||||
.desc = "Demonstrates various flags used during and after window creation",
|
||||
},
|
||||
.{
|
||||
.name = "gui_message_box",
|
||||
.path = "examples/gui/message_box.zig",
|
||||
.desc = "Demonstrates showing and hiding a message box",
|
||||
},
|
||||
.{
|
||||
.name = "raymarching",
|
||||
.path = "examples/shaders/raymarching.zig",
|
||||
.desc = "Uses a raymarching in a shader to render shapes",
|
||||
},
|
||||
.{
|
||||
.name = "shaders_ascii_rendering",
|
||||
.path = "examples/shaders/shaders_ascii_rendering.zig",
|
||||
.desc = "Post-processing to render in ASCII",
|
||||
},
|
||||
.{
|
||||
.name = "shaders_basic_pbr",
|
||||
.path = "examples/shaders/shaders_basic_pbr.zig",
|
||||
.desc = "Demonstrates physically based rendering",
|
||||
},
|
||||
.{
|
||||
.name = "shaders_hybrid_render",
|
||||
.path = "examples/shaders/shaders_hybrid_render.zig",
|
||||
.desc = "Demonstrates hybrid rendering",
|
||||
},
|
||||
.{
|
||||
.name = "texture_outline",
|
||||
.path = "examples/shaders/texture_outline.zig",
|
||||
@ -242,6 +215,86 @@ pub fn build(b: *std.Build) !void {
|
||||
.path = "examples/shapes/logo_raylib.zig",
|
||||
.desc = "Renders the raylib-zig logo",
|
||||
},
|
||||
.{
|
||||
.name = "logo_raylib_anim",
|
||||
.path = "examples/shapes/logo_raylib_anim.zig",
|
||||
.desc = "Animates the raylib logo",
|
||||
},
|
||||
.{
|
||||
.name = "basic_shapes",
|
||||
.path = "examples/shapes/basic_shapes.zig",
|
||||
.desc = "Renders various shapes",
|
||||
},
|
||||
.{
|
||||
.name = "bouncing_ball",
|
||||
.path = "examples/shapes/bouncing_ball.zig",
|
||||
.desc = "Bouncing ball animation with collision detection",
|
||||
},
|
||||
.{
|
||||
.name = "collision_area",
|
||||
.path = "examples/shapes/collision_area.zig",
|
||||
.desc = "Demonstrates collision detection",
|
||||
},
|
||||
.{
|
||||
.name = "colors_palette",
|
||||
.path = "examples/shapes/colors_palette.zig",
|
||||
.desc = "Renders an interactive color palette",
|
||||
},
|
||||
.{
|
||||
.name = "draw_circle_sector",
|
||||
.path = "examples/shapes/draw_circle_sector.zig",
|
||||
.desc = "Dynamically renders a circle sector using raygui",
|
||||
},
|
||||
.{
|
||||
.name = "draw_rectangle_rounded",
|
||||
.path = "examples/shapes/draw_rectangle_rounded.zig",
|
||||
.desc = "Dynamically renders a rounded rectangle using raygui",
|
||||
},
|
||||
.{
|
||||
.name = "draw_ring",
|
||||
.path = "examples/shapes/draw_ring.zig",
|
||||
.desc = "Dynaically renders a ring using raygui",
|
||||
},
|
||||
.{
|
||||
.name = "easings_ball_anim",
|
||||
.path = "examples/shapes/easings_ball_anim.zig",
|
||||
.desc = "Renders a ball that demonstrates various easing functions",
|
||||
},
|
||||
.{
|
||||
.name = "easings_box_anim",
|
||||
.path = "examples/shapes/easings_box_anim.zig",
|
||||
.desc = "Renders a box that demonstrates various easing functions",
|
||||
},
|
||||
.{
|
||||
.name = "easings_rectangle_array",
|
||||
.path = "examples/shapes/easings_rectangle_array.zig",
|
||||
.desc = "Renders a box that demonstrates various easing functions",
|
||||
},
|
||||
.{
|
||||
.name = "following_eyes",
|
||||
.path = "examples/shapes/following_eyes.zig",
|
||||
.desc = "Renders eyes that follow mouse movement",
|
||||
},
|
||||
.{
|
||||
.name = "lines_bezier",
|
||||
.path = "examples/shapes/lines_bezier.zig",
|
||||
.desc = "Renders an interactive line bezier",
|
||||
},
|
||||
.{
|
||||
.name = "rectangle_scaling",
|
||||
.path = "examples/shapes/rectangle_scaling.zig",
|
||||
.desc = "Renders a resizable rectangle",
|
||||
},
|
||||
.{
|
||||
.name = "splines_drawing",
|
||||
.path = "examples/shapes/splines_drawing.zig",
|
||||
.desc = "Renders a spline",
|
||||
},
|
||||
.{
|
||||
.name = "top_down_lights",
|
||||
.path = "examples/shapes/top_down_lights.zig",
|
||||
.desc = "Renders a sceen with shadows and a top down persepective",
|
||||
},
|
||||
.{
|
||||
.name = "sprite_anim",
|
||||
.path = "examples/textures/sprite_anim.zig",
|
||||
@ -252,11 +305,91 @@ pub fn build(b: *std.Build) !void {
|
||||
.path = "examples/textures/textures_background_scrolling.zig",
|
||||
.desc = "Background scrolling & parallax demo",
|
||||
},
|
||||
// .{
|
||||
// .name = "models_loading",
|
||||
// .path = "examples/models/models_loading.zig",
|
||||
// .desc = "Loads a model and renders it",
|
||||
// },
|
||||
.{
|
||||
.name = "codepoints_loading",
|
||||
.path = "examples/text/codepoints_loading.zig",
|
||||
.desc = "Renders UTF-8 text",
|
||||
},
|
||||
.{
|
||||
.name = "draw_3d",
|
||||
.path = "examples/text/draw_3d.zig",
|
||||
.desc = "Renders an example of text rendered in a 3d world",
|
||||
},
|
||||
.{
|
||||
.name = "font_filters",
|
||||
.path = "examples/text/font_filters.zig",
|
||||
.desc = "Demonstrates the various font filters",
|
||||
},
|
||||
.{
|
||||
.name = "font_loading",
|
||||
.path = "examples/text/font_loading.zig",
|
||||
.desc = "Demonstrates how to load fonts",
|
||||
},
|
||||
.{
|
||||
.name = "font_sdf",
|
||||
.path = "examples/text/font_sdf.zig",
|
||||
.desc = "Demonstrates rending a sdf font",
|
||||
},
|
||||
.{
|
||||
.name = "font_spritefont",
|
||||
.path = "examples/text/font_spritefont.zig",
|
||||
.desc = "Demonstrates rendering spritefonts",
|
||||
},
|
||||
.{
|
||||
.name = "format_text",
|
||||
.path = "examples/text/format_text.zig",
|
||||
.desc = "Renders variables as text",
|
||||
},
|
||||
.{
|
||||
.name = "input_box",
|
||||
.path = "examples/text/input_box.zig",
|
||||
.desc = "Show and example of an input_box",
|
||||
},
|
||||
.{
|
||||
.name = "raylib_fonts",
|
||||
.path = "examples/text/raylib_fonts.zig",
|
||||
.desc = "Show fonts included with raylib",
|
||||
},
|
||||
.{
|
||||
.name = "rectangle_bounds",
|
||||
.path = "examples/text/rectangle_bounds.zig",
|
||||
.desc = "demonstrate a flexible, resizeable, text box",
|
||||
},
|
||||
.{
|
||||
.name = "unicode",
|
||||
.path = "examples/text/unicode.zig",
|
||||
.desc = "demonstrate rendering of unicode",
|
||||
},
|
||||
.{
|
||||
.name = "writing_anim",
|
||||
.path = "examples/text/writing_anim.zig",
|
||||
.desc = "Simple text animation",
|
||||
},
|
||||
.{
|
||||
.name = "textures_image_loading",
|
||||
.path = "examples/textures/textures_image_loading.zig",
|
||||
.desc = "Image loading and texture creation",
|
||||
},
|
||||
.{
|
||||
.name = "models_heightmap",
|
||||
.path = "examples/models/models_heightmap.zig",
|
||||
.desc = "Heightmap loading and drawing",
|
||||
},
|
||||
.{
|
||||
.name = "models_bone_socket",
|
||||
.path = "examples/models/models_bone_socket.zig",
|
||||
.desc = "Bone socket",
|
||||
},
|
||||
.{
|
||||
.name = "models_box_collisions",
|
||||
.path = "examples/models/models_box_collisions.zig",
|
||||
.desc = "Box collisions",
|
||||
},
|
||||
.{
|
||||
.name = "models_rlgl_solar_system",
|
||||
.path = "examples/models/models_rlgl_solar_system.zig",
|
||||
.desc = "Solar System",
|
||||
},
|
||||
// .{
|
||||
// .name = "shaders_basic_lighting",
|
||||
// .path = "examples/shaders/shaders_basic_lighting.zig",
|
||||
@ -264,21 +397,16 @@ pub fn build(b: *std.Build) !void {
|
||||
// },
|
||||
};
|
||||
|
||||
const raylib = this.getModule(b, target, optimize);
|
||||
const raygui = this.gui.getModule(b, target, optimize);
|
||||
|
||||
const raylib_test = b.addTest(.{
|
||||
.root_source_file = b.path("lib/raylib.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.root_module = raylib,
|
||||
});
|
||||
raylib_test.linkLibC();
|
||||
|
||||
const raygui_test = b.addTest(.{
|
||||
.root_source_file = b.path("lib/raygui.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.root_module = raygui,
|
||||
});
|
||||
raygui_test.root_module.addImport("raylib-zig", raylib);
|
||||
raygui_test.linkLibC();
|
||||
|
||||
const test_step = b.step("test", "Check for library compilation errors");
|
||||
test_step.dependOn(&raylib_test.step);
|
||||
@ -287,33 +415,54 @@ pub fn build(b: *std.Build) !void {
|
||||
const examples_step = b.step("examples", "Builds all the examples");
|
||||
|
||||
for (examples) |ex| {
|
||||
const mod = b.createModule(.{
|
||||
.root_source_file = b.path(ex.path),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
if (target.query.os_tag == .emscripten) {
|
||||
const exe_lib = emcc.compileForEmscripten(b, ex.name, ex.path, target, optimize);
|
||||
exe_lib.root_module.addImport("raylib", raylib);
|
||||
exe_lib.root_module.addImport("raygui", raygui);
|
||||
const raylib_lib = getRaylib(b, target, optimize, options);
|
||||
const wasm = b.addLibrary(.{
|
||||
.name = ex.name,
|
||||
.root_module = mod,
|
||||
});
|
||||
wasm.root_module.addImport("raylib", raylib);
|
||||
wasm.root_module.addImport("raygui", raygui);
|
||||
|
||||
// Note that raylib itself isn't actually added to the exe_lib
|
||||
// output file, so it also needs to be linked with emscripten.
|
||||
exe_lib.linkLibrary(raylib_lib);
|
||||
const link_step = try emcc.linkWithEmscripten(b, &[_]*std.Build.Step.Compile{ exe_lib, raylib_lib });
|
||||
link_step.addArg("--embed-file");
|
||||
link_step.addArg("resources/");
|
||||
const install_dir: std.Build.InstallDir = .{ .custom = "web" };
|
||||
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{
|
||||
.optimize = optimize,
|
||||
.asyncify = !std.mem.endsWith(u8, ex.name, "web"),
|
||||
});
|
||||
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const emcc_step = emsdk.emccStep(b, raylib_artifact, wasm, .{
|
||||
.optimize = optimize,
|
||||
.flags = emcc_flags,
|
||||
.settings = emcc_settings,
|
||||
.shell_file_path = emsdk.shell(b),
|
||||
.install_dir = install_dir,
|
||||
.embed_paths = &.{.{ .src_path = "resources/" }},
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
const run_step = try emcc.emscriptenRunStep(b);
|
||||
run_step.step.dependOn(&link_step.step);
|
||||
const run_option = b.step(ex.name, ex.desc);
|
||||
|
||||
run_option.dependOn(&run_step.step);
|
||||
examples_step.dependOn(&exe_lib.step);
|
||||
run_option.dependOn(emrun_step);
|
||||
examples_step.dependOn(emcc_step);
|
||||
} else {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = ex.name,
|
||||
.root_source_file = b.path(ex.path),
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
.root_module = mod,
|
||||
});
|
||||
this.link(b, exe, target, optimize, options);
|
||||
exe.root_module.addImport("raylib", raylib);
|
||||
exe.root_module.addImport("raygui", raygui);
|
||||
|
||||
|
||||
@ -1,17 +1,26 @@
|
||||
.{
|
||||
.name = "raylib-zig",
|
||||
.version = "5.1.0",
|
||||
.name = .raylib_zig,
|
||||
.version = "5.6.0-dev",
|
||||
.fingerprint = 0xc4cfa8c610114f28,
|
||||
.dependencies = .{
|
||||
.raylib = .{
|
||||
.url = "https://github.com/raysan5/raylib/archive/5767c4cd059e07355ae5588966d0aee97038a86b.tar.gz",
|
||||
.hash = "1220aa75240ee6459499456ef520ab7e8bddffaed8a5055441da457b198fc4e92b26",
|
||||
.url = "git+https://github.com/raysan5/raylib#8ada37d9671682f420a2be1f1afd4b06173b81ad",
|
||||
.hash = "raylib-5.6.0-dev-whq8uCg2ywTzCiX3VEP9RuCMXR6_VnDBmkj8GjL_p5QN",
|
||||
},
|
||||
.raygui = .{
|
||||
.url = "https://github.com/raysan5/raygui/archive/4b3d94f5df6a5a2aa86286350f7e20c0ca35f516.tar.gz",
|
||||
.hash = "122002d98ca255ec706ef8e5497b3723d6c6e163511761d116dac3aee87747d46cf1",
|
||||
}
|
||||
.url = "git+https://github.com/raysan5/raygui#9cdfec460b43a17264af3c181c46f62bf107ac17",
|
||||
.hash = "N-V-__8AALUbbwDKkSH4nbf3Ml_dTWo9qbELvle5i9eQZMuo",
|
||||
},
|
||||
.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?ref=main#00da03b188220374a57cb34cda6230b8d53737ea",
|
||||
.hash = "zemscripten-0.2.0-dev-sRlDqFJSAAB8hgnRt5DDMKP3zLlDtMnUDwYRJVCa5lGY",
|
||||
},
|
||||
},
|
||||
.minimum_zig_version = "0.13.0",
|
||||
.minimum_zig_version = "0.15.1",
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
"build.zig.zon",
|
||||
@ -23,6 +32,6 @@
|
||||
"lib/rlgl.zig",
|
||||
"lib/rlgl-ext.zig",
|
||||
"lib/raygui.zig",
|
||||
"lib/raygui-ext.zig"
|
||||
"lib/raygui-ext.zig",
|
||||
},
|
||||
}
|
||||
|
||||
139
emcc.zig
@ -1,139 +0,0 @@
|
||||
// raylib-zig (c) Nikolas Wipper 2020-2024
|
||||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
||||
const emccOutputFile = "index.html";
|
||||
pub fn emscriptenRunStep(b: *std.Build) !*std.Build.Step.Run {
|
||||
// Find emrun.
|
||||
if (b.sysroot == null) {
|
||||
@panic("Pass '--sysroot \"[path to emsdk installation]/upstream/emscripten\"'");
|
||||
}
|
||||
// If compiling on windows , use emrun.bat.
|
||||
const emrunExe = switch (builtin.os.tag) {
|
||||
.windows => "emrun.bat",
|
||||
else => "emrun",
|
||||
};
|
||||
const emrun_run_arg = try b.allocator.alloc(u8, b.sysroot.?.len + emrunExe.len + 1);
|
||||
defer b.allocator.free(emrun_run_arg);
|
||||
|
||||
_ = try std.fmt.bufPrint(emrun_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ b.sysroot.?, emrunExe });
|
||||
|
||||
const run_cmd = b.addSystemCommand(&[_][]const u8{ emrun_run_arg, emccOutputDir ++ emccOutputFile });
|
||||
return run_cmd;
|
||||
}
|
||||
|
||||
// Creates the static library to build a project for Emscripten.
|
||||
pub fn compileForEmscripten(
|
||||
b: *std.Build,
|
||||
name: []const u8,
|
||||
root_source_file: []const u8,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
) *std.Build.Step.Compile {
|
||||
// TODO: It might be a good idea to create a custom compile step, that does
|
||||
// both the compile to static library and the link with emcc by overidding
|
||||
// the make function of the step. However it might also be a bad idea since
|
||||
// it messes with the build system itself.
|
||||
|
||||
//const new_target = updateTargetForWeb(target);
|
||||
|
||||
// The project is built as a library and linked later.
|
||||
const exe_lib = b.addStaticLibrary(.{
|
||||
.name = name,
|
||||
.root_source_file = b.path(root_source_file),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// There are some symbols that need to be defined in C.
|
||||
const webhack_c_file_step = b.addWriteFiles();
|
||||
const webhack_c_file = webhack_c_file_step.add("webhack.c", webhack_c);
|
||||
exe_lib.addCSourceFile(.{ .file = webhack_c_file, .flags = &[_][]u8{} });
|
||||
// Since it's creating a static library, the symbols raylib uses to webgl
|
||||
// and glfw don't need to be linked by emscripten yet.
|
||||
exe_lib.step.dependOn(&webhack_c_file_step.step);
|
||||
return exe_lib;
|
||||
}
|
||||
|
||||
// Links a set of items together using emscripten.
|
||||
//
|
||||
// Will accept objects and static libraries as items to link. As for files to
|
||||
// include, it is recomended to have a single resources directory and just pass
|
||||
// the entire directory instead of passing every file individually. The entire
|
||||
// path given will be the path to read the file within the program. So, if
|
||||
// "resources/image.png" is passed, your program will use "resources/image.png"
|
||||
// as the path to load the file.
|
||||
//
|
||||
// TODO: Test if shared libraries are accepted, I don't remember if emcc can
|
||||
// link a shared library with a project or not.
|
||||
// TODO: Add a parameter that allows a custom output directory.
|
||||
pub fn linkWithEmscripten(
|
||||
b: *std.Build,
|
||||
itemsToLink: []const *std.Build.Step.Compile,
|
||||
) !*std.Build.Step.Run {
|
||||
// Raylib uses --sysroot in order to find emscripten, so do the same here.
|
||||
if (b.sysroot == null) {
|
||||
@panic("Pass '--sysroot \"[path to emsdk installation]/upstream/emscripten\"'");
|
||||
}
|
||||
const emccExe = switch (builtin.os.tag) {
|
||||
.windows => "emcc.bat",
|
||||
else => "emcc",
|
||||
};
|
||||
var emcc_run_arg = try b.allocator.alloc(u8, b.sysroot.?.len + emccExe.len + 1);
|
||||
defer b.allocator.free(emcc_run_arg);
|
||||
|
||||
emcc_run_arg = try std.fmt.bufPrint(
|
||||
emcc_run_arg,
|
||||
"{s}" ++ std.fs.path.sep_str ++ "{s}",
|
||||
.{ b.sysroot.?, emccExe },
|
||||
);
|
||||
|
||||
// Create the output directory because emcc can't do it.
|
||||
const mkdir_command = b.addSystemCommand(&[_][]const u8{ "mkdir", "-p", emccOutputDir });
|
||||
|
||||
// Actually link everything together.
|
||||
const emcc_command = b.addSystemCommand(&[_][]const u8{emcc_run_arg});
|
||||
|
||||
for (itemsToLink) |item| {
|
||||
emcc_command.addFileArg(item.getEmittedBin());
|
||||
emcc_command.step.dependOn(&item.step);
|
||||
}
|
||||
// This puts the file in zig-out/htmlout/index.html.
|
||||
emcc_command.step.dependOn(&mkdir_command.step);
|
||||
emcc_command.addArgs(&[_][]const u8{
|
||||
"-o",
|
||||
emccOutputDir ++ emccOutputFile,
|
||||
"-sFULL-ES3=1",
|
||||
"-sUSE_GLFW=3",
|
||||
"-sASYNCIFY",
|
||||
"-O3",
|
||||
"--emrun",
|
||||
});
|
||||
return emcc_command;
|
||||
}
|
||||
|
||||
// TODO: See if zig's standard library already has somehing like this.
|
||||
fn lastIndexOf(string: []const u8, character: u8) usize {
|
||||
// Interestingly, Zig has no nice way of iterating a slice backwards.
|
||||
for (0..string.len) |i| {
|
||||
const index = string.len - i - 1;
|
||||
if (string[index] == character) return index;
|
||||
}
|
||||
return string.len - 1;
|
||||
}
|
||||
|
||||
const webhack_c =
|
||||
\\// Zig adds '__stack_chk_guard', '__stack_chk_fail', and 'errno',
|
||||
\\// which emscripten doesn't actually support.
|
||||
\\// Seems that zig ignores disabling stack checking,
|
||||
\\// and I honestly don't know why emscripten doesn't have errno.
|
||||
\\// TODO: when the updateTargetForWeb workaround gets removed, see if those are nessesary anymore
|
||||
\\#include <stdint.h>
|
||||
\\uintptr_t __stack_chk_guard;
|
||||
\\//I'm not certain if this means buffer overflows won't be detected,
|
||||
\\// However, zig is pretty safe from those, so don't worry about it too much.
|
||||
\\void __stack_chk_fail(void){}
|
||||
\\int errno;
|
||||
;
|
||||
141
examples/audio/module_playing.zig
Normal file
@ -0,0 +1,141 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
const MAX_CIRCLES = 64;
|
||||
|
||||
const CircleWave = struct {
|
||||
position: rl.Vector2,
|
||||
radius: f32,
|
||||
alpha: f32,
|
||||
speed: f32,
|
||||
color: rl.Color,
|
||||
};
|
||||
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
const colors = [14]rl.Color{ .orange, .red, .gold, .lime, .blue, .violet, .brown, .light_gray, .pink, .yellow, .green, .sky_blue, .purple, .beige };
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() !void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
rl.setConfigFlags(rl.ConfigFlags{ .msaa_4x_hint = true }); // NOTE: Try to enable MSAA 4X
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [audio] example - module playing (streaming)");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
rl.initAudioDevice(); // Initialize audio device
|
||||
defer rl.closeAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
// Creates some circles for visual effect
|
||||
var circles: [MAX_CIRCLES]CircleWave = undefined;
|
||||
|
||||
for (&circles) |*circle| {
|
||||
initCircle(circle);
|
||||
}
|
||||
|
||||
var music: rl.Music = try rl.loadMusicStream("resources/audio/mini1111.xm");
|
||||
defer rl.unloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
|
||||
music.looping = false;
|
||||
var pitch: f32 = 1;
|
||||
|
||||
rl.playMusicStream(music);
|
||||
|
||||
var timePlayed: f32 = 0;
|
||||
var pause: bool = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.updateMusicStream(music); // Update music buffer with new stream data
|
||||
|
||||
// Restart music playing (stop and play)
|
||||
if (rl.isKeyPressed(.space)) {
|
||||
rl.stopMusicStream(music);
|
||||
rl.playMusicStream(music);
|
||||
pause = false;
|
||||
}
|
||||
|
||||
// Pause/Resume music playing
|
||||
if (rl.isKeyPressed(.p)) {
|
||||
pause = !pause;
|
||||
|
||||
if (pause) {
|
||||
rl.pauseMusicStream(music);
|
||||
} else {
|
||||
rl.resumeMusicStream(music);
|
||||
}
|
||||
}
|
||||
|
||||
if (rl.isKeyDown(.down)) {
|
||||
pitch -= 0.01;
|
||||
} else if (rl.isKeyDown(.up)) {
|
||||
pitch += 0.01;
|
||||
}
|
||||
|
||||
rl.setMusicPitch(music, pitch);
|
||||
|
||||
// Get timePlayed scaled to bar dimensions
|
||||
timePlayed = rl.getMusicTimePlayed(music) / rl.getMusicTimeLength(music) * (screenWidth - 40);
|
||||
|
||||
if (!pause) {
|
||||
for (&circles) |*circle| {
|
||||
circle.alpha += circle.speed;
|
||||
circle.radius += circle.speed * 10.0;
|
||||
|
||||
if (circle.alpha > 1.0) circle.speed *= -1;
|
||||
|
||||
if (circle.alpha <= 0.0) {
|
||||
initCircle(circle);
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
for (circles) |circle| {
|
||||
rl.drawCircleV(circle.position, circle.radius, .fade(circle.color, circle.alpha));
|
||||
}
|
||||
|
||||
// Draw time bar
|
||||
rl.drawRectangle(20, screenHeight - 20 - 12, screenWidth - 40, 12, .light_gray);
|
||||
rl.drawRectangle(20, screenHeight - 20 - 12, @intFromFloat(timePlayed), 12, .maroon);
|
||||
rl.drawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, .gray);
|
||||
|
||||
// Draw help instructions
|
||||
rl.drawRectangle(20, 20, 425, 145, .white);
|
||||
rl.drawRectangleLines(20, 20, 425, 145, .gray);
|
||||
rl.drawText("PRESS SPACE TO RESTART MUSIC", 40, 40, 20, .black);
|
||||
rl.drawText("PRESS P TO PAUSE/RESUME", 40, 70, 20, .black);
|
||||
rl.drawText("PRESS UP/DOWN TO CHANGE SPEED", 40, 100, 20, .black);
|
||||
rl.drawText(rl.textFormat("SPEED: %f", .{pitch}), 40, 130, 20, .maroon);
|
||||
|
||||
rl.endDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
fn initCircle(circle: *CircleWave) void {
|
||||
circle.alpha = 0.0;
|
||||
circle.radius = getRandomValuef32(10, 40);
|
||||
circle.position.x = getRandomValuef32(@intFromFloat(circle.radius), @intFromFloat(screenWidth - circle.radius));
|
||||
circle.position.y = getRandomValuef32(@intFromFloat(circle.radius), @intFromFloat(screenHeight - circle.radius));
|
||||
circle.speed = getRandomValuef32(1, 100) / 2000.0;
|
||||
circle.color = colors[@intCast(rl.getRandomValue(0, 13))];
|
||||
}
|
||||
|
||||
fn getRandomValuef32(min: i32, max: i32) f32 {
|
||||
return @as(f32, @floatFromInt(rl.getRandomValue(min, max)));
|
||||
}
|
||||
78
examples/audio/music_stream.zig
Normal file
@ -0,0 +1,78 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() !void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [audio] example - music playing (streaming)");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
rl.initAudioDevice(); // Initialize audio device
|
||||
defer rl.closeAudioDevice(); // Close audio device (music streaming is automatically stopped)
|
||||
|
||||
const music: rl.Music = try rl.loadMusicStream("resources/audio/country.mp3");
|
||||
defer rl.unloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
|
||||
rl.playMusicStream(music);
|
||||
|
||||
var timePlayed: f32 = 0; // Time played normalized [0.0f..1.0f]
|
||||
var pause: bool = false; // Music playing paused
|
||||
|
||||
rl.setTargetFPS(30); // Set our game to run at 30 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.updateMusicStream(music); // Update music buffer with new stream data
|
||||
|
||||
// Restart music playing (stop and play)
|
||||
if (rl.isKeyPressed(.space)) {
|
||||
rl.stopMusicStream(music);
|
||||
rl.playMusicStream(music);
|
||||
}
|
||||
|
||||
// Pause/Resume music playing
|
||||
if (rl.isKeyPressed(.p)) {
|
||||
pause = !pause;
|
||||
|
||||
if (pause) {
|
||||
rl.pauseMusicStream(music);
|
||||
} else {
|
||||
rl.resumeMusicStream(music);
|
||||
}
|
||||
}
|
||||
|
||||
// Get normalized time played for current music stream
|
||||
timePlayed = rl.getMusicTimePlayed(music) / rl.getMusicTimeLength(music);
|
||||
|
||||
if (timePlayed > 1.0) {
|
||||
timePlayed = 1.0; // Make sure time played is no longer than music
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, .light_gray);
|
||||
|
||||
rl.drawRectangle(200, 200, 400, 12, .light_gray);
|
||||
rl.drawRectangle(200, 200, @intFromFloat(timePlayed * 400), 12, .maroon);
|
||||
rl.drawRectangleLines(200, 200, 400, 12, .gray);
|
||||
|
||||
rl.drawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, .light_gray);
|
||||
rl.drawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, .light_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,20 @@
|
||||
// raylib-zig (c) Nikolas Wipper 2023
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
const MAX_SAMPLES = 512;
|
||||
const MAX_SAMPLES_PER_UPDATE = 4096;
|
||||
|
||||
const pi = @import("std").math.pi;
|
||||
const C = std.builtin.CallingConvention.c;
|
||||
|
||||
var frequency: f32 = 440;
|
||||
var audioFrequency: f32 = 440;
|
||||
var oldFrequency: f32 = 1;
|
||||
var sineIdx: f32 = 0;
|
||||
|
||||
fn audioInputCallback(buffer: ?*anyopaque, frames: c_uint) callconv(.C) void {
|
||||
fn audioInputCallback(buffer: ?*anyopaque, frames: c_uint) callconv(C) void {
|
||||
audioFrequency = frequency + (audioFrequency - frequency) * 0.95;
|
||||
|
||||
const incr = audioFrequency / 44100;
|
||||
@ -41,7 +44,7 @@ pub fn main() anyerror!void {
|
||||
rl.setAudioStreamBufferSizeDefault(MAX_SAMPLES_PER_UPDATE);
|
||||
|
||||
// Init raw audio stream (sample rate: 44100, sample size: 16bit-short, channels: 1-mono)
|
||||
const stream = rl.loadAudioStream(44100, 16, 1);
|
||||
const stream = try rl.loadAudioStream(44100, 16, 1);
|
||||
defer rl.unloadAudioStream(stream); // Close raw audio stream and delete buffers from RAM
|
||||
|
||||
rl.setAudioStreamCallback(stream, &audioInputCallback);
|
||||
@ -69,7 +72,7 @@ pub fn main() anyerror!void {
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
if (rl.isMouseButtonDown(.mouse_button_left)) {
|
||||
if (rl.isMouseButtonDown(.left)) {
|
||||
// Sample mouse input.
|
||||
const mousePosition = rl.getMousePosition();
|
||||
|
||||
@ -111,12 +114,12 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText(rl.textFormat("sine frequency: %i", .{@as(i32, @intFromFloat(frequency))}),
|
||||
rl.getScreenWidth() - 220, 10, 20, rl.Color.red);
|
||||
rl.getScreenWidth() - 220, 10, 20, .red);
|
||||
rl.drawText("click mouse button to change frequency or pan",
|
||||
10, 10, 20, rl.Color.dark_gray);
|
||||
10, 10, 20, .dark_gray);
|
||||
|
||||
// Draw the current buffer state proportionate to the screen
|
||||
for (0..screenWidth) |i| {
|
||||
@ -124,7 +127,7 @@ pub fn main() anyerror!void {
|
||||
const y: f32 = @floatFromInt(data[@divFloor(i * MAX_SAMPLES, screenWidth)]);
|
||||
position.y = 250 + 50 * y / 32000;
|
||||
|
||||
rl.drawPixelV(position, rl.Color.red);
|
||||
rl.drawPixelV(position, .red);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
46
examples/audio/sound_loading.zig
Normal file
@ -0,0 +1,46 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() !void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [audio] example - sound loading and playing");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
rl.initAudioDevice(); // Initialize audio device
|
||||
defer rl.closeAudioDevice(); // Close audio device
|
||||
|
||||
const fxWav: rl.Sound = try rl.loadSound("resources/audio/sound.wav"); // Load WAV audio file
|
||||
const fxOgg: rl.Sound = try rl.loadSound("resources/audio/target.ogg"); // Load OGG audio file
|
||||
defer rl.unloadSound(fxWav); // Unload sound data
|
||||
defer rl.unloadSound(fxOgg); // Unload sound data
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyPressed(.space)) rl.playSound(fxWav); // Play WAV sound
|
||||
if (rl.isKeyPressed(.enter)) rl.playSound(fxOgg); // Play OGG sound
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawText("Press SPACE to PLAY the WAV sound!", 200, 180, 20, .light_gray);
|
||||
rl.drawText("Press ENTER to PLAY the OGG sound!", 200, 220, 20, .light_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
52
examples/core/2d_camera.zig
Executable file → Normal file
@ -27,7 +27,7 @@ pub fn main() anyerror!void {
|
||||
|
||||
spacing += @as(i32, @intFromFloat(buildings[i].width));
|
||||
|
||||
buildColors[i] = rl.Color.init(
|
||||
buildColors[i] = .init(
|
||||
@as(u8, @intCast(rl.getRandomValue(200, 240))),
|
||||
@as(u8, @intCast(rl.getRandomValue(200, 240))),
|
||||
@as(u8, @intCast(rl.getRandomValue(200, 250))),
|
||||
@ -36,8 +36,8 @@ pub fn main() anyerror!void {
|
||||
}
|
||||
|
||||
var camera = rl.Camera2D{
|
||||
.target = rl.Vector2.init(player.x + 20, player.y + 20),
|
||||
.offset = rl.Vector2.init(screenWidth / 2, screenHeight / 2),
|
||||
.target = .init(player.x + 20, player.y + 20),
|
||||
.offset = .init(screenWidth / 2, screenHeight / 2),
|
||||
.rotation = 0,
|
||||
.zoom = 1,
|
||||
};
|
||||
@ -51,19 +51,19 @@ pub fn main() anyerror!void {
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Player movement
|
||||
if (rl.isKeyDown(rl.KeyboardKey.key_right)) {
|
||||
if (rl.isKeyDown(.right)) {
|
||||
player.x += 2;
|
||||
} else if (rl.isKeyDown(rl.KeyboardKey.key_left)) {
|
||||
} else if (rl.isKeyDown(.left)) {
|
||||
player.x -= 2;
|
||||
}
|
||||
|
||||
// Camera target follows player
|
||||
camera.target = rl.Vector2.init(player.x + 20, player.y + 20);
|
||||
camera.target = .init(player.x + 20, player.y + 20);
|
||||
|
||||
// Camera rotation controls
|
||||
if (rl.isKeyDown(rl.KeyboardKey.key_a)) {
|
||||
if (rl.isKeyDown(.a)) {
|
||||
camera.rotation -= 1;
|
||||
} else if (rl.isKeyDown(rl.KeyboardKey.key_s)) {
|
||||
} else if (rl.isKeyDown(.s)) {
|
||||
camera.rotation += 1;
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ pub fn main() anyerror!void {
|
||||
camera.zoom = rl.math.clamp(camera.zoom, 0.1, 3.0);
|
||||
|
||||
// Camera reset (zoom and rotation)
|
||||
if (rl.isKeyPressed(rl.KeyboardKey.key_r)) {
|
||||
if (rl.isKeyPressed(.r)) {
|
||||
camera.zoom = 1.0;
|
||||
camera.rotation = 0.0;
|
||||
}
|
||||
@ -87,51 +87,51 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
{
|
||||
camera.begin();
|
||||
defer camera.end();
|
||||
|
||||
rl.drawRectangle(-6000, 320, 13000, 8000, rl.Color.dark_gray);
|
||||
rl.drawRectangle(-6000, 320, 13000, 8000, .dark_gray);
|
||||
|
||||
for (buildings, 0..) |building, i| {
|
||||
rl.drawRectangleRec(building, buildColors[i]);
|
||||
}
|
||||
|
||||
rl.drawRectangleRec(player, rl.Color.red);
|
||||
rl.drawRectangleRec(player, .red);
|
||||
|
||||
rl.drawLine(
|
||||
@as(i32, @intFromFloat(camera.target.x)),
|
||||
-screenHeight * 10,
|
||||
@as(i32, @intFromFloat(camera.target.x)),
|
||||
screenHeight * 10,
|
||||
rl.Color.green,
|
||||
.green,
|
||||
);
|
||||
rl.drawLine(
|
||||
-screenWidth * 10,
|
||||
@as(i32, @intFromFloat(camera.target.y)),
|
||||
screenWidth * 10,
|
||||
@as(i32, @intFromFloat(camera.target.y)),
|
||||
rl.Color.green,
|
||||
.green,
|
||||
);
|
||||
}
|
||||
|
||||
rl.drawText("SCREEN AREA", 640, 10, 20, rl.Color.red);
|
||||
rl.drawText("SCREEN AREA", 640, 10, 20, .red);
|
||||
|
||||
rl.drawRectangle(0, 0, screenWidth, 5, rl.Color.red);
|
||||
rl.drawRectangle(0, 5, 5, screenHeight - 10, rl.Color.red);
|
||||
rl.drawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, rl.Color.red);
|
||||
rl.drawRectangle(0, screenHeight - 5, screenWidth, 5, rl.Color.red);
|
||||
rl.drawRectangle(0, 0, screenWidth, 5, .red);
|
||||
rl.drawRectangle(0, 5, 5, screenHeight - 10, .red);
|
||||
rl.drawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, .red);
|
||||
rl.drawRectangle(0, screenHeight - 5, screenWidth, 5, .red);
|
||||
|
||||
rl.drawRectangle(10, 10, 250, 113, rl.Color.sky_blue.fade(0.5));
|
||||
rl.drawRectangleLines(10, 10, 250, 113, rl.Color.blue);
|
||||
rl.drawRectangle(10, 10, 250, 113, .fade(.sky_blue, 0.5));
|
||||
rl.drawRectangleLines(10, 10, 250, 113, .blue);
|
||||
|
||||
rl.drawText("Free 2d camera controls:", 20, 20, 10, rl.Color.black);
|
||||
rl.drawText("- Right/Left to move Offset", 40, 40, 10, rl.Color.dark_gray);
|
||||
rl.drawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, rl.Color.dark_gray);
|
||||
rl.drawText("- A / S to Rotate", 40, 80, 10, rl.Color.dark_gray);
|
||||
rl.drawText("- R to reset Zoom and Rotation", 40, 100, 10, rl.Color.dark_gray);
|
||||
rl.drawText("Free 2d camera controls:", 20, 20, 10, .black);
|
||||
rl.drawText("- Right/Left to move Offset", 40, 40, 10, .dark_gray);
|
||||
rl.drawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, .dark_gray);
|
||||
rl.drawText("- A / S to Rotate", 40, 80, 10, .dark_gray);
|
||||
rl.drawText("- R to reset Zoom and Rotation", 40, 100, 10, .dark_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,14 +27,14 @@ pub fn main() anyerror!void {
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyPressed(.key_one)) {
|
||||
if (rl.isKeyPressed(.one)) {
|
||||
zoomMode = 0;
|
||||
} else if (rl.isKeyPressed(.key_two)) {
|
||||
} else if (rl.isKeyPressed(.two)) {
|
||||
zoomMode = 1;
|
||||
}
|
||||
|
||||
// Translate based on mouse right click
|
||||
if (rl.isMouseButtonDown(.mouse_button_right)) {
|
||||
if (rl.isMouseButtonDown(.right)) {
|
||||
var delta = rl.getMouseDelta();
|
||||
delta = rl.math.vector2Scale(delta, -1.0 / camera.zoom);
|
||||
camera.target = rl.math.vector2Add(camera.target, delta);
|
||||
@ -63,7 +63,7 @@ pub fn main() anyerror!void {
|
||||
}
|
||||
} else {
|
||||
// Zoom based on left click
|
||||
if (rl.isMouseButtonPressed(.mouse_button_left)) {
|
||||
if (rl.isMouseButtonPressed(.left)) {
|
||||
// Get the world point that is under the mouse
|
||||
const mouseWorldPos = rl.getScreenToWorld2D(rl.getMousePosition(), camera);
|
||||
|
||||
@ -74,7 +74,7 @@ pub fn main() anyerror!void {
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
camera.target = mouseWorldPos;
|
||||
}
|
||||
if (rl.isMouseButtonDown(.mouse_button_left)) {
|
||||
if (rl.isMouseButtonDown(.left)) {
|
||||
// Zoom increment
|
||||
const deltaX = rl.getMouseDelta().x;
|
||||
var scaleFactor = 1.0 + (0.01 * @abs(deltaX));
|
||||
@ -91,7 +91,7 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
{
|
||||
camera.begin();
|
||||
@ -103,14 +103,14 @@ pub fn main() anyerror!void {
|
||||
rl.drawGrid(100, 50);
|
||||
rl.gl.rlPopMatrix();
|
||||
|
||||
rl.drawCircle(screenWidth / 2, screenHeight / 2, 50, rl.Color.maroon);
|
||||
rl.drawCircle(screenWidth / 2, screenHeight / 2, 50, .maroon);
|
||||
}
|
||||
|
||||
rl.drawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, rl.Color.dark_gray);
|
||||
rl.drawText("[1][2] Select mouse zoom mode (Wheel or Move)", 20, 20, 20, .dark_gray);
|
||||
if (zoomMode == 0) {
|
||||
rl.drawText("Mouse right button drag to move, mouse wheel to zoom", 20, 50, 20, rl.Color.dark_gray);
|
||||
rl.drawText("Mouse right button drag to move, mouse wheel to zoom", 20, 50, 20, .dark_gray);
|
||||
} else {
|
||||
rl.drawText("Mouse right button drag to move, mouse press and move to zoom", 20, 50, 20, rl.Color.dark_gray);
|
||||
rl.drawText("Mouse right button drag to move, mouse press and move to zoom", 20, 50, 20, .dark_gray);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
334
examples/core/2d_camera_platformer.zig
Normal file
@ -0,0 +1,334 @@
|
||||
// raylib-zig (c) Axel Magnuson 2025
|
||||
//
|
||||
// This is a fairly close 1-1 copy of the original example from raylib, and
|
||||
// thus might not represent completely idiomatic or clean zig.
|
||||
|
||||
const rl = @import("raylib");
|
||||
const rm = @import("raymath");
|
||||
|
||||
const Rect = rl.Rectangle;
|
||||
const Vec2 = rl.Vector2;
|
||||
const Color = rl.Color;
|
||||
const Camera2D = rl.Camera2D;
|
||||
|
||||
const CameraUpdater = *const fn (
|
||||
camera: *Camera2D,
|
||||
player: *Player,
|
||||
env_items: []EnvItem,
|
||||
delta: f32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) void;
|
||||
|
||||
const G: i32 = 400;
|
||||
const PLAYER_JUMP_SPD: f32 = 350;
|
||||
const PLAYER_HOR_SPD: f32 = 200;
|
||||
|
||||
const Player = struct {
|
||||
can_jump: bool,
|
||||
speed: f32,
|
||||
position: rl.Vector2,
|
||||
};
|
||||
|
||||
const EnvItem = struct {
|
||||
blocking: bool,
|
||||
rect: rl.Rectangle,
|
||||
color: rl.Color,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [core] example - 2d camera");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var player: Player = .{ .can_jump = false, .speed = 0, .position = Vec2.init(400, 280) };
|
||||
var env_items = [_]EnvItem{
|
||||
.{ .rect = Rect.init(0, 0, 1000, 400), .blocking = false, .color = .light_gray },
|
||||
.{ .rect = Rect.init(0, 400, 1000, 200), .blocking = true, .color = .gray },
|
||||
.{ .rect = Rect.init(300, 200, 400, 10), .blocking = true, .color = .gray },
|
||||
.{ .rect = Rect.init(250, 300, 100, 10), .blocking = true, .color = .gray },
|
||||
.{ .rect = Rect.init(650, 300, 100, 10), .blocking = true, .color = .gray },
|
||||
};
|
||||
|
||||
var camera: rl.Camera2D = .{
|
||||
.target = player.position,
|
||||
.offset = Vec2.init(screen_width / 2, screen_height / 2),
|
||||
.rotation = 0,
|
||||
.zoom = 1,
|
||||
};
|
||||
|
||||
// store pointers to the multiple functions that could be used to update the camera
|
||||
const camera_updaters = [_]CameraUpdater{
|
||||
updateCameraCenter,
|
||||
updatecameraCenterInsideMap,
|
||||
updateCameraCenterSmoothFollow,
|
||||
updateCameraEvenOutOnLanding,
|
||||
updateCameraPlayerBoundsPush,
|
||||
};
|
||||
|
||||
var camera_option: usize = 0;
|
||||
|
||||
const camera_descriptions = [_][:0]const u8{
|
||||
"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",
|
||||
};
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames per second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) {
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
const delta_time = rl.getFrameTime();
|
||||
|
||||
updatePlayer(&player, &env_items, delta_time);
|
||||
|
||||
camera.zoom += rl.getMouseWheelMove() * 0.05;
|
||||
if (camera.zoom > 3) camera.zoom = 3;
|
||||
if (camera.zoom < 0.25) camera.zoom = 0.25;
|
||||
|
||||
// input: reset
|
||||
if (rl.isKeyPressed(.r)) {
|
||||
camera.zoom = 1;
|
||||
player.position = Vec2.init(400, 280);
|
||||
}
|
||||
|
||||
// input: cycle camera mode
|
||||
if (rl.isKeyPressed(.c)) {
|
||||
camera_option = (camera_option + 1) % camera_updaters.len;
|
||||
}
|
||||
|
||||
// call update camera by pointer
|
||||
camera_updaters[camera_option](
|
||||
&camera,
|
||||
&player,
|
||||
&env_items,
|
||||
delta_time,
|
||||
screen_width,
|
||||
screen_height,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
{
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.light_gray);
|
||||
|
||||
{
|
||||
rl.beginMode2D(camera);
|
||||
defer rl.endMode2D();
|
||||
|
||||
for (env_items) |env_item| {
|
||||
rl.drawRectangleRec(env_item.rect, env_item.color);
|
||||
}
|
||||
|
||||
const player_rect = Rect.init(player.position.x - 20, player.position.y - 40, 40, 40);
|
||||
rl.drawRectangleRec(player_rect, .red);
|
||||
rl.drawCircleV(player.position, 5, .gold);
|
||||
}
|
||||
|
||||
rl.drawText("Controls:", 20, 20, 10, .black);
|
||||
rl.drawText("- Right/Left to move", 40, 40, 10, .dark_gray);
|
||||
// todo: controls text
|
||||
rl.drawText("- Current camera mode:", 20, 120, 10, .black);
|
||||
rl.drawText(camera_descriptions[camera_option], 40, 140, 10, .dark_gray);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Player update function
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
fn updatePlayer(player: *Player, env_items: []EnvItem, delta: f32) void {
|
||||
if (rl.isKeyDown(.left)) player.position.x -= PLAYER_HOR_SPD * delta;
|
||||
if (rl.isKeyDown(.right)) player.position.x += PLAYER_HOR_SPD * delta;
|
||||
if (rl.isKeyDown(.space) and player.can_jump) {
|
||||
player.speed = -PLAYER_JUMP_SPD;
|
||||
player.can_jump = false;
|
||||
}
|
||||
|
||||
var hit_obstacle = false;
|
||||
for (env_items) |ei| {
|
||||
var p: *Vec2 = &player.position;
|
||||
if (ei.blocking and
|
||||
ei.rect.x <= p.x and
|
||||
ei.rect.x + ei.rect.width >= p.x and
|
||||
ei.rect.y >= p.y and
|
||||
ei.rect.y <= p.y + player.speed * delta)
|
||||
{
|
||||
hit_obstacle = true;
|
||||
player.speed = 0;
|
||||
p.y = ei.rect.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hit_obstacle) {
|
||||
player.position.y += player.speed * delta;
|
||||
player.speed += G * delta;
|
||||
player.can_jump = false;
|
||||
} else player.can_jump = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Selectable camera update functions
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
// Follow player center
|
||||
fn updateCameraCenter(
|
||||
camera: *Camera2D,
|
||||
player: *Player,
|
||||
_: []EnvItem,
|
||||
_: f32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) void {
|
||||
const widthf: f32 = @floatFromInt(width);
|
||||
const heightf: f32 = @floatFromInt(height);
|
||||
camera.offset = Vec2.init(widthf / 2, heightf / 2);
|
||||
camera.target = player.position;
|
||||
}
|
||||
|
||||
// Follow player center, but clamp to map edges
|
||||
fn updatecameraCenterInsideMap(
|
||||
camera: *Camera2D,
|
||||
player: *Player,
|
||||
env_items: []EnvItem,
|
||||
_: f32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) void {
|
||||
const widthf: f32 = @floatFromInt(width);
|
||||
const heightf: f32 = @floatFromInt(height);
|
||||
camera.offset = Vec2.init(widthf / 2, heightf / 2);
|
||||
camera.target = player.position;
|
||||
|
||||
var min_x: f32 = 1000;
|
||||
var min_y: f32 = 1000;
|
||||
var max_x: f32 = -1000;
|
||||
var max_y: f32 = -1000;
|
||||
|
||||
for (env_items) |ei| {
|
||||
min_x = @min(ei.rect.x, min_x);
|
||||
min_y = @min(ei.rect.y, min_y);
|
||||
max_x = @max(ei.rect.x + ei.rect.width, max_x);
|
||||
max_y = @max(ei.rect.y + ei.rect.height, max_y);
|
||||
}
|
||||
|
||||
const max = rl.getWorldToScreen2D(Vec2.init(max_x, max_y), camera.*);
|
||||
const min = rl.getWorldToScreen2D(Vec2.init(min_x, min_y), camera.*);
|
||||
|
||||
if (max.x < widthf) camera.offset.x = widthf - (max.x - widthf / 2);
|
||||
if (max.y < heightf) camera.offset.y = heightf - (max.y - heightf / 2);
|
||||
if (min.x > 0) camera.offset.x = widthf / 2 - min.x;
|
||||
if (min.y > 0) camera.offset.y = heightf / 2 - min.y;
|
||||
}
|
||||
|
||||
// Follow player center; smoothed
|
||||
fn updateCameraCenterSmoothFollow(
|
||||
camera: *Camera2D,
|
||||
player: *Player,
|
||||
_: []EnvItem,
|
||||
delta: f32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) void {
|
||||
const min_speed = 30;
|
||||
const min_effect_length = 10;
|
||||
const fraction_speed = 0.8;
|
||||
|
||||
const widthf: f32 = @floatFromInt(width);
|
||||
const heightf: f32 = @floatFromInt(height);
|
||||
|
||||
camera.offset = Vec2.init(widthf / 2, heightf / 2);
|
||||
const diff = player.position.subtract(camera.target);
|
||||
const length = diff.length();
|
||||
|
||||
if (length > min_effect_length) {
|
||||
const speed = @max(fraction_speed * length, min_speed);
|
||||
camera.target = camera.target.add(diff.scale(speed * delta / length));
|
||||
}
|
||||
}
|
||||
|
||||
var evening_out: bool = false;
|
||||
var even_out_target: f32 = 0;
|
||||
|
||||
// Follow player center horizontally; update player center vertically after landing
|
||||
fn updateCameraEvenOutOnLanding(
|
||||
camera: *Camera2D,
|
||||
player: *Player,
|
||||
_: []EnvItem,
|
||||
delta: f32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) void {
|
||||
const even_out_speed = 700;
|
||||
|
||||
const widthf: f32 = @floatFromInt(width);
|
||||
const heightf: f32 = @floatFromInt(height);
|
||||
|
||||
camera.offset = Vec2.init(widthf / 2, heightf / 2);
|
||||
camera.target.x = player.position.x;
|
||||
|
||||
if (evening_out) {
|
||||
if (even_out_target > camera.target.y) {
|
||||
camera.target.y += even_out_speed * delta;
|
||||
if (camera.target.y > even_out_target) {
|
||||
camera.target.y = even_out_target;
|
||||
evening_out = false;
|
||||
}
|
||||
} else {
|
||||
camera.target.y -= even_out_speed * delta;
|
||||
if (camera.target.y < even_out_target) {
|
||||
camera.target.y = even_out_target;
|
||||
evening_out = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (player.can_jump and player.speed == 0 and player.position.y != camera.target.y) {
|
||||
evening_out = true;
|
||||
even_out_target = player.position.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Player push camera on getting too close to screen edge
|
||||
fn updateCameraPlayerBoundsPush(
|
||||
camera: *Camera2D,
|
||||
player: *Player,
|
||||
_: []EnvItem,
|
||||
_: f32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) void {
|
||||
const bbox = Vec2.init(0.2, 0.2);
|
||||
|
||||
const widthf: f32 = @floatFromInt(width);
|
||||
const heightf: f32 = @floatFromInt(height);
|
||||
|
||||
const bbox_world_min = rl.getScreenToWorld2D(Vec2.init((1 - bbox.x) * 0.5 * widthf, (1 - bbox.y) * 0.5 * heightf), camera.*);
|
||||
const bbox_world_max = rl.getScreenToWorld2D(Vec2.init((1 + bbox.x) * 0.5 * widthf, (1 + bbox.y) * 0.5 * heightf), camera.*);
|
||||
camera.offset = Vec2.init((1 - bbox.x) * 0.5 * widthf, (1 - bbox.y) * 0.5 * heightf);
|
||||
|
||||
if (player.position.x < bbox_world_min.x) camera.target.x = player.position.x;
|
||||
if (player.position.y < bbox_world_min.y) camera.target.y = player.position.y;
|
||||
if (player.position.x > bbox_world_max.x) camera.target.x = bbox_world_min.x + (player.position.x - bbox_world_max.x);
|
||||
if (player.position.y > bbox_world_max.y) camera.target.y = bbox_world_min.y + (player.position.y - bbox_world_max.y);
|
||||
}
|
||||
@ -14,11 +14,11 @@ pub fn main() anyerror!void {
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var camera = rl.Camera3D{
|
||||
.position = rl.Vector3.init(4, 2, 4),
|
||||
.target = rl.Vector3.init(0, 1.8, 0),
|
||||
.up = rl.Vector3.init(0, 1, 0),
|
||||
.position = .init(4, 2, 4),
|
||||
.target = .init(0, 1.8, 0),
|
||||
.up = .init(0, 1, 0),
|
||||
.fovy = 60,
|
||||
.projection = rl.CameraProjection.camera_perspective,
|
||||
.projection = .perspective,
|
||||
};
|
||||
|
||||
var heights: [MAX_COLUMNS]f32 = undefined;
|
||||
@ -27,12 +27,12 @@ pub fn main() anyerror!void {
|
||||
|
||||
for (0..heights.len) |i| {
|
||||
heights[i] = @as(f32, @floatFromInt(rl.getRandomValue(1, 12)));
|
||||
positions[i] = rl.Vector3.init(
|
||||
positions[i] = .init(
|
||||
@as(f32, @floatFromInt(rl.getRandomValue(-15, 15))),
|
||||
heights[i] / 2.0,
|
||||
@as(f32, @floatFromInt(rl.getRandomValue(-15, 15))),
|
||||
);
|
||||
colors[i] = rl.Color.init(
|
||||
colors[i] = .init(
|
||||
@as(u8, @intCast(rl.getRandomValue(20, 255))),
|
||||
@as(u8, @intCast(rl.getRandomValue(10, 55))),
|
||||
30,
|
||||
@ -48,7 +48,7 @@ pub fn main() anyerror!void {
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.update(rl.CameraMode.camera_first_person);
|
||||
camera.update(.first_person);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -56,31 +56,31 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
{
|
||||
camera.begin();
|
||||
defer camera.end();
|
||||
|
||||
// Draw ground
|
||||
rl.drawPlane(rl.Vector3.init(0, 0, 0), rl.Vector2.init(32, 32), rl.Color.light_gray);
|
||||
rl.drawCube(rl.Vector3.init(-16.0, 2.5, 0.0), 1.0, 5.0, 32.0, rl.Color.blue); // Draw a blue wall
|
||||
rl.drawCube(rl.Vector3.init(16.0, 2.5, 0.0), 1.0, 5.0, 32.0, rl.Color.lime); // Draw a green wall
|
||||
rl.drawCube(rl.Vector3.init(0.0, 2.5, 16.0), 32.0, 5.0, 1.0, rl.Color.gold); // Draw a yellow wall
|
||||
rl.drawPlane(.init(0, 0, 0), .init(32, 32), .light_gray);
|
||||
rl.drawCube(.init(-16.0, 2.5, 0.0), 1.0, 5.0, 32.0, .blue); // Draw a blue wall
|
||||
rl.drawCube(.init(16.0, 2.5, 0.0), 1.0, 5.0, 32.0, .lime); // Draw a green wall
|
||||
rl.drawCube(.init(0.0, 2.5, 16.0), 32.0, 5.0, 1.0, .gold); // Draw a yellow wall
|
||||
|
||||
// Draw some cubes around
|
||||
for (heights, 0..) |height, i| {
|
||||
rl.drawCube(positions[i], 2.0, height, 2.0, colors[i]);
|
||||
rl.drawCubeWires(positions[i], 2.0, height, 2.0, rl.Color.maroon);
|
||||
rl.drawCubeWires(positions[i], 2.0, height, 2.0, .maroon);
|
||||
}
|
||||
}
|
||||
|
||||
rl.drawRectangle(10, 10, 220, 70, rl.Color.sky_blue.fade(0.5));
|
||||
rl.drawRectangleLines(10, 10, 220, 70, rl.Color.blue);
|
||||
rl.drawRectangle(10, 10, 220, 70, .fade(.sky_blue, 0.5));
|
||||
rl.drawRectangleLines(10, 10, 220, 70, .blue);
|
||||
|
||||
rl.drawText("First person camera default controls:", 20, 20, 10, rl.Color.black);
|
||||
rl.drawText("- Move with keys: W, A, S, D", 40, 40, 10, rl.Color.dark_gray);
|
||||
rl.drawText("- Mouse move to look around", 40, 60, 10, rl.Color.dark_gray);
|
||||
rl.drawText("First person camera default controls:", 20, 20, 10, .black);
|
||||
rl.drawText("- Move with keys: W, A, S, D", 40, 40, 10, .dark_gray);
|
||||
rl.drawText("- Mouse move to look around", 40, 60, 10, .dark_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
69
examples/core/3d_camera_free.zig
Normal file
@ -0,0 +1,69 @@
|
||||
// A raylib port of https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_camera_free.c
|
||||
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera = rl.Camera{
|
||||
.position = .init(10, 10, 10),
|
||||
.target = .init(0, 0, 0),
|
||||
.up = .init(0, 1, 0),
|
||||
.fovy = 45,
|
||||
.projection = .perspective,
|
||||
};
|
||||
|
||||
const cubePosition = rl.Vector3.init(0, 0, 0);
|
||||
|
||||
rl.disableCursor(); // Limit cursor to relative movement inside the window
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//-----------------------------------------------------------------------------
|
||||
camera.update(.free);
|
||||
|
||||
if (rl.isKeyPressed(.z)) {
|
||||
camera.target = .init(0, 0, 0);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//-----------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
{
|
||||
camera.begin();
|
||||
defer camera.end();
|
||||
|
||||
rl.drawCube(cubePosition, 2, 2, 2, .red);
|
||||
rl.drawCubeWires(cubePosition, 2, 2, 2, .maroon);
|
||||
|
||||
rl.drawGrid(10, 1);
|
||||
}
|
||||
|
||||
rl.drawRectangle(10, 10, 320, 93, .fade(.sky_blue, 0.5));
|
||||
rl.drawRectangleLines(10, 10, 320, 93, .blue);
|
||||
|
||||
rl.drawText("Free camera default controls:", 20, 20, 10, .black);
|
||||
rl.drawText("- Mouse Wheel to Zoom in-out", 40, 40, 10, .dark_gray);
|
||||
rl.drawText("- Mouse Wheel Pressed to Pan", 40, 60, 10, .dark_gray);
|
||||
rl.drawText("- Z to zoom to (0, 0, 0)", 40, 80, 10, .dark_gray);
|
||||
//-----------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
89
examples/core/3d_picking.zig
Normal file
@ -0,0 +1,89 @@
|
||||
// A raylib-zig port of https://github.com/raysan5/raylib/blob/master/examples/core/core_3d_picking.c
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - 3d picking");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera = rl.Camera{
|
||||
.position = .init(10, 10, 10),
|
||||
.target = .init(0, 0, 0),
|
||||
.up = .init(0, 1, 0),
|
||||
.fovy = 45,
|
||||
.projection = .perspective,
|
||||
};
|
||||
|
||||
const cubePosition = rl.Vector3.init(0, 1, 0);
|
||||
const cubeSize = rl.Vector3.init(2, 2, 2);
|
||||
|
||||
var ray: rl.Ray = undefined; // Picking line ray
|
||||
var collision: rl.RayCollision = undefined; // Ray collision hit info
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isCursorHidden()) rl.updateCamera(&camera, .first_person);
|
||||
|
||||
// Toggle camera controls
|
||||
if (rl.isMouseButtonPressed(.right)) {
|
||||
if (rl.isCursorHidden()) rl.enableCursor() else rl.disableCursor();
|
||||
}
|
||||
|
||||
if (rl.isMouseButtonPressed(.left)) {
|
||||
if (!collision.hit) {
|
||||
ray = rl.getScreenToWorldRay(rl.getMousePosition(), camera);
|
||||
|
||||
// Check collision between ray and box
|
||||
collision = rl.getRayCollisionBox(ray, rl.BoundingBox{
|
||||
.max = .init(cubePosition.x - cubeSize.x / 2, cubePosition.y - cubeSize.y / 2, cubePosition.z - cubeSize.z / 2),
|
||||
.min = .init(cubePosition.x + cubeSize.x / 2, cubePosition.y + cubeSize.y / 2, cubePosition.z + cubeSize.z / 2),
|
||||
});
|
||||
} else collision.hit = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
{
|
||||
camera.begin();
|
||||
defer camera.end();
|
||||
|
||||
if (collision.hit) {
|
||||
rl.drawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, .red);
|
||||
rl.drawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, .maroon);
|
||||
|
||||
rl.drawCubeWires(cubePosition, cubeSize.x + 0.2, cubeSize.y + 0.2, cubeSize.z + 0.2, .green);
|
||||
} else {
|
||||
rl.drawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, .gray);
|
||||
rl.drawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, .dark_gray);
|
||||
}
|
||||
|
||||
rl.drawRay(ray, .maroon);
|
||||
rl.drawGrid(10, 1);
|
||||
}
|
||||
|
||||
rl.drawText("Try clicking on the box with your mouse!", 240, 10, 20, .dark_gray);
|
||||
|
||||
if (collision.hit) {
|
||||
rl.drawText("BOX SELECTED", @divTrunc((screenWidth - rl.measureText("BOX SELECTED", 30)), 2), screenHeight * 0.1, 30, .green);
|
||||
}
|
||||
|
||||
rl.drawText("Right click mouse to toggle camera controls", 10, 430, 10, .gray);
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ pub fn main() anyerror!void {
|
||||
// TODO: Update `title` state variables here!
|
||||
|
||||
// Press ENTER to change to `gameplay` state
|
||||
if (rl.isKeyPressed(.key_enter) or rl.isGestureDetected(.gesture_tap)) {
|
||||
if (rl.isKeyPressed(.enter) or rl.isGestureDetected(.{ .tap = true })) {
|
||||
current_screen = .gameplay;
|
||||
}
|
||||
},
|
||||
@ -64,7 +64,7 @@ pub fn main() anyerror!void {
|
||||
// TODO: Update `gameplay` state variables here!
|
||||
|
||||
// Press ENTER to change to `ending` state
|
||||
if (rl.isKeyPressed(.key_enter) or rl.isGestureDetected(.gesture_tap)) {
|
||||
if (rl.isKeyPressed(.enter) or rl.isGestureDetected(.{ .tap = true })) {
|
||||
current_screen = .ending;
|
||||
}
|
||||
},
|
||||
@ -72,7 +72,7 @@ pub fn main() anyerror!void {
|
||||
// TODO: Update `ending` state variables here!
|
||||
|
||||
// Press ENTER to return to `title` state
|
||||
if (rl.isKeyPressed(.key_enter) or rl.isGestureDetected(.gesture_tap)) {
|
||||
if (rl.isKeyPressed(.enter) or rl.isGestureDetected(.{ .tap = true })) {
|
||||
current_screen = .title;
|
||||
}
|
||||
},
|
||||
@ -85,18 +85,18 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
switch (current_screen) {
|
||||
.logo => {
|
||||
// TODO: Draw `logo` state here!
|
||||
rl.drawText("LOGO SCREEN", 20, 20, 40, rl.Color.light_gray);
|
||||
rl.drawText("LOGO SCREEN", 20, 20, 40, .light_gray);
|
||||
rl.drawText(
|
||||
"WAIT for 2 SECONDS...",
|
||||
290,
|
||||
220,
|
||||
20,
|
||||
rl.Color.gray,
|
||||
.gray,
|
||||
);
|
||||
},
|
||||
.title => {
|
||||
@ -106,21 +106,21 @@ pub fn main() anyerror!void {
|
||||
0,
|
||||
screen_width,
|
||||
screen_height,
|
||||
rl.Color.green,
|
||||
.green,
|
||||
);
|
||||
rl.drawText(
|
||||
"TITLE SCREEN",
|
||||
20,
|
||||
20,
|
||||
40,
|
||||
rl.Color.dark_green,
|
||||
.dark_green,
|
||||
);
|
||||
rl.drawText(
|
||||
"PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN",
|
||||
120,
|
||||
220,
|
||||
20,
|
||||
rl.Color.dark_green,
|
||||
.dark_green,
|
||||
);
|
||||
},
|
||||
.gameplay => {
|
||||
@ -130,15 +130,15 @@ pub fn main() anyerror!void {
|
||||
0,
|
||||
screen_width,
|
||||
screen_height,
|
||||
rl.Color.purple,
|
||||
.purple,
|
||||
);
|
||||
rl.drawText("GAMEPLAY SCREEN", 20, 20, 40, rl.Color.maroon);
|
||||
rl.drawText("GAMEPLAY SCREEN", 20, 20, 40, .maroon);
|
||||
rl.drawText(
|
||||
"PRESS ENTER or TAP to JUMP to ENDING SCREEN",
|
||||
130,
|
||||
220,
|
||||
20,
|
||||
rl.Color.maroon,
|
||||
.maroon,
|
||||
);
|
||||
},
|
||||
.ending => {
|
||||
@ -148,21 +148,21 @@ pub fn main() anyerror!void {
|
||||
0,
|
||||
screen_width,
|
||||
screen_height,
|
||||
rl.Color.blue,
|
||||
.blue,
|
||||
);
|
||||
rl.drawText(
|
||||
"ENDING SCREEN",
|
||||
20,
|
||||
20,
|
||||
40,
|
||||
rl.Color.dark_blue,
|
||||
.dark_blue,
|
||||
);
|
||||
rl.drawText(
|
||||
"PRESS ENTER or TAP to RETURN to TITLE SCREEN",
|
||||
120,
|
||||
220,
|
||||
20,
|
||||
rl.Color.dark_blue,
|
||||
.dark_blue,
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
4
examples/core/basic_window.zig
Executable file → Normal file
@ -26,9 +26,9 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.white);
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawText("Congrats! You created your first window!", 190, 200, 20, rl.Color.light_gray);
|
||||
rl.drawText("Congrats! You created your first window!", 190, 200, 20, .light_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
53
examples/core/basic_window_web.zig
Normal file
@ -0,0 +1,53 @@
|
||||
// A raylib-zig port of https://github.com/raysan5/raylib/blob/master/examples/core/core_basic_window_web.c
|
||||
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const emscripten = std.os.emscripten;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - basic window");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
if (builtin.os.tag == .emscripten) {
|
||||
emscripten.emscripten_set_main_loop(@ptrCast(&updateDrawFrame), 0, 1);
|
||||
} else {
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
updateDrawFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update and Draw one frame
|
||||
fn updateDrawFrame() void {
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawText("Congrats! You created your first window!", 190, 200, 20, .light_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
153
examples/core/core_monitor_change.zig
Normal file
@ -0,0 +1,153 @@
|
||||
// raylib-zig (c) 2025 Maicon Santana (@maiconpintoabreu)
|
||||
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
|
||||
const MAX_MONITORS = 10;
|
||||
|
||||
// Monitor Details
|
||||
const Monitor = struct {
|
||||
position: rl.Vector2,
|
||||
name: [*c]const u8,
|
||||
width: i32,
|
||||
height: i32,
|
||||
physicalWidth: i32,
|
||||
physicalHeight: i32,
|
||||
refreshRate: i32,
|
||||
};
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth: i32 = 800;
|
||||
const screenHeight: i32 = 450;
|
||||
|
||||
var monitors: [MAX_MONITORS]Monitor = undefined;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - monitor change");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var currentMonitorIndex: i32 = rl.getCurrentMonitor();
|
||||
var monitorCount: usize = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Variables to find the max x and Y to calculate the scale
|
||||
var maxWidth: i32 = 1;
|
||||
var maxHeight: i32 = 1;
|
||||
|
||||
// Monitor offset is to fix when monitor position x is negative
|
||||
var monitorOffsetX: f32 = 0;
|
||||
|
||||
// Rebuild monitors array every frame
|
||||
monitorCount = @intCast(rl.getMonitorCount());
|
||||
for (0..monitorCount) |i| {
|
||||
const intI: i32 = @intCast(i);
|
||||
monitors[i] = .{
|
||||
.position = rl.getMonitorPosition(intI),
|
||||
.name = rl.getMonitorName(intI),
|
||||
.width = rl.getMonitorWidth(intI),
|
||||
.height = rl.getMonitorHeight(intI),
|
||||
.physicalWidth = rl.getMonitorPhysicalWidth(intI),
|
||||
.physicalHeight = rl.getMonitorPhysicalHeight(intI),
|
||||
.refreshRate = rl.getMonitorRefreshRate(intI),
|
||||
};
|
||||
if (monitors[i].position.x < monitorOffsetX) {
|
||||
monitorOffsetX = monitors[i].position.x * -1.0;
|
||||
}
|
||||
|
||||
const width: i32 = @as(i32, @intFromFloat(monitors[i].position.x)) + monitors[i].width;
|
||||
const height: i32 = @as(i32, @intFromFloat(monitors[i].position.y)) + monitors[i].height;
|
||||
|
||||
if (maxWidth < width) maxWidth = width;
|
||||
if (maxHeight < height) maxHeight = height;
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.enter) and monitorCount > 1) {
|
||||
currentMonitorIndex += 1;
|
||||
|
||||
// Set index to 0 if the last one
|
||||
if (currentMonitorIndex == monitorCount) currentMonitorIndex = 0;
|
||||
|
||||
rl.setWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex
|
||||
} else {
|
||||
// Get currentMonitorIndex if manually moved
|
||||
currentMonitorIndex = rl.getCurrentMonitor();
|
||||
}
|
||||
|
||||
var monitorScale: f32 = 0.6;
|
||||
|
||||
const intMonitorOffsetX: i32 = @intFromFloat(monitorOffsetX);
|
||||
|
||||
if (maxHeight > maxWidth + intMonitorOffsetX) {
|
||||
monitorScale *= @as(f32, @floatFromInt(screenHeight)) / @as(f32, @floatFromInt(maxHeight));
|
||||
} else {
|
||||
monitorScale *= @as(f32, @floatFromInt(screenWidth)) / @as(f32, @floatFromInt((maxWidth + intMonitorOffsetX)));
|
||||
}
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("Press [Enter] to move window to next monitor available", 20, 20, 20, .dark_gray);
|
||||
|
||||
rl.drawRectangleLines(20, 60, screenWidth - 40, screenHeight - 100, .dark_gray);
|
||||
|
||||
// Draw Monitor Rectangles with information inside
|
||||
for (0..monitorCount) |i| {
|
||||
// Calculate retangle position and size using monitorScale
|
||||
const rec: rl.Rectangle = .{
|
||||
.x = (monitors[i].position.x + monitorOffsetX) * monitorScale + 140,
|
||||
.y = monitors[i].position.y * monitorScale + 80,
|
||||
.width = @as(f32, @floatFromInt(monitors[i].width)) * monitorScale,
|
||||
.height = @as(f32, @floatFromInt(monitors[i].height)) * monitorScale,
|
||||
};
|
||||
|
||||
// Draw monitor name and information inside the rectangle
|
||||
rl.drawText(
|
||||
rl.textFormat("[%i] %s", .{ i, monitors[i].name }),
|
||||
@intFromFloat(rec.x + 10.0),
|
||||
@intFromFloat(rec.y + (100.0 * monitorScale)),
|
||||
@as(i32, @intFromFloat(120.0 * monitorScale)),
|
||||
.blue,
|
||||
);
|
||||
rl.drawText(rl.textFormat("Resolution: [%ipx x %ipx]\nRefreshRate: [%ihz]\nPhysical Size: [%imm x %imm]\nPosition: %3.0f x %3.0f", .{
|
||||
monitors[i].width,
|
||||
monitors[i].height,
|
||||
monitors[i].refreshRate,
|
||||
monitors[i].physicalWidth,
|
||||
monitors[i].physicalHeight,
|
||||
monitors[i].position.x,
|
||||
monitors[i].position.y,
|
||||
}), @intFromFloat(rec.x + 10), @intFromFloat(rec.y + (200 * monitorScale)), @as(i32, @intFromFloat(120.0 * monitorScale)), .dark_gray);
|
||||
|
||||
// Highlight current monitor
|
||||
if (i == currentMonitorIndex) {
|
||||
rl.drawRectangleLinesEx(rec, 5, .red);
|
||||
const windowPosition: rl.Vector2 = .{
|
||||
.x = (rl.getWindowPosition().x + monitorOffsetX) * monitorScale + 140,
|
||||
.y = rl.getWindowPosition().y * monitorScale + 80,
|
||||
};
|
||||
|
||||
// Draw window position based on monitors
|
||||
rl.drawRectangleV(
|
||||
windowPosition,
|
||||
.{ .x = @as(f32, @floatFromInt(screenWidth)) * monitorScale, .y = @as(f32, @floatFromInt(screenHeight)) * monitorScale },
|
||||
rl.fade(.green, 0.5),
|
||||
);
|
||||
} else {
|
||||
rl.drawRectangleLinesEx(rec, 5, .gray);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
102
examples/core/drop_files.zig
Normal file
@ -0,0 +1,102 @@
|
||||
// raylib-zig (c) Leonardo Kreienbuehl 2025
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
const MAX_FILEPATH_RECORDED = 4096;
|
||||
const MAX_FILEPATH_SIZE = 2048;
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - drop files");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var filePathCounter: usize = 0;
|
||||
var filePaths: [MAX_FILEPATH_RECORDED][MAX_FILEPATH_SIZE]u8 = std.mem.zeroes([MAX_FILEPATH_RECORDED][MAX_FILEPATH_SIZE]u8);
|
||||
|
||||
rl.setTargetFPS(60);
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) {
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isFileDropped()) {
|
||||
const droppedFiles: rl.FilePathList = rl.loadDroppedFiles();
|
||||
|
||||
for (0..droppedFiles.count) |i| {
|
||||
const offset: usize = @as(usize, @intCast(filePathCounter));
|
||||
const droppedFilePathLength: usize = std.mem.len(droppedFiles.paths[i]);
|
||||
|
||||
if (filePathCounter < (MAX_FILEPATH_RECORDED - 1)) {
|
||||
_ = rl.textCopy(
|
||||
@ptrCast(@constCast(&filePaths[offset])),
|
||||
droppedFiles.paths[i][0..droppedFilePathLength :0],
|
||||
);
|
||||
filePathCounter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
rl.unloadDroppedFiles(droppedFiles);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
|
||||
if (filePathCounter == 0) {
|
||||
rl.drawText(
|
||||
"Drop your files to this window!",
|
||||
100,
|
||||
40,
|
||||
20,
|
||||
rl.Color.dark_gray,
|
||||
);
|
||||
} else {
|
||||
rl.drawText(
|
||||
"Dropped files:",
|
||||
100,
|
||||
40,
|
||||
20,
|
||||
rl.Color.dark_gray,
|
||||
);
|
||||
|
||||
for (0..filePathCounter) |i| {
|
||||
const castedI: i32 = @intCast(i);
|
||||
if (@mod(i, 2) == 0) {
|
||||
rl.drawRectangle(
|
||||
0,
|
||||
85 + 40 * castedI,
|
||||
screenWidth,
|
||||
40,
|
||||
rl.fade(rl.Color.light_gray, 0.5),
|
||||
);
|
||||
} else {
|
||||
rl.drawRectangle(
|
||||
0,
|
||||
85 + 40 * castedI,
|
||||
screenWidth,
|
||||
40,
|
||||
rl.fade(rl.Color.light_gray, 0.3),
|
||||
);
|
||||
}
|
||||
|
||||
rl.drawText(
|
||||
filePaths[i][0 .. MAX_FILEPATH_SIZE - 1 :0],
|
||||
120,
|
||||
100 + 40 * castedI,
|
||||
10,
|
||||
rl.Color.gray,
|
||||
);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
14
examples/core/input_keys.zig
Executable file → Normal file
@ -21,16 +21,16 @@ pub fn main() anyerror!void {
|
||||
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyDown(rl.KeyboardKey.key_right)) {
|
||||
if (rl.isKeyDown(.right)) {
|
||||
ballPosition.x += 2.0;
|
||||
}
|
||||
if (rl.isKeyDown(rl.KeyboardKey.key_left)) {
|
||||
if (rl.isKeyDown(.left)) {
|
||||
ballPosition.x -= 2.0;
|
||||
}
|
||||
if (rl.isKeyDown(rl.KeyboardKey.key_up)) {
|
||||
if (rl.isKeyDown(.up)) {
|
||||
ballPosition.y -= 2.0;
|
||||
}
|
||||
if (rl.isKeyDown(rl.KeyboardKey.key_down)) {
|
||||
if (rl.isKeyDown(.down)) {
|
||||
ballPosition.y += 2.0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -40,11 +40,11 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("move the ball with arrow keys", 10, 10, 20, rl.Color.dark_gray);
|
||||
rl.drawText("move the ball with arrow keys", 10, 10, 20, .dark_gray);
|
||||
|
||||
rl.drawCircleV(ballPosition, 50, rl.Color.maroon);
|
||||
rl.drawCircleV(ballPosition, 50, .maroon);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
16
examples/core/input_mouse.zig
Executable file → Normal file
@ -25,12 +25,12 @@ pub fn main() anyerror!void {
|
||||
ballPosition.x = @as(f32, @floatFromInt(rl.getMouseX()));
|
||||
ballPosition.y = @as(f32, @floatFromInt(rl.getMouseY()));
|
||||
|
||||
if (rl.isMouseButtonPressed(rl.MouseButton.mouse_button_left)) {
|
||||
ballColor = rl.Color.maroon;
|
||||
} else if (rl.isMouseButtonPressed(rl.MouseButton.mouse_button_middle)) {
|
||||
ballColor = rl.Color.lime;
|
||||
} else if (rl.isMouseButtonPressed(rl.MouseButton.mouse_button_right)) {
|
||||
ballColor = rl.Color.dark_blue;
|
||||
if (rl.isMouseButtonPressed(.left)) {
|
||||
ballColor = .maroon;
|
||||
} else if (rl.isMouseButtonPressed(.middle)) {
|
||||
ballColor = .lime;
|
||||
} else if (rl.isMouseButtonPressed(.right)) {
|
||||
ballColor = .dark_blue;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
@ -39,11 +39,11 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawCircleV(ballPosition, 40, ballColor);
|
||||
|
||||
rl.drawText("move ball with mouse and click mouse button to change color", 10, 10, 20, rl.Color.dark_gray);
|
||||
rl.drawText("move ball with mouse and click mouse button to change color", 10, 10, 20, .dark_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
8
examples/core/input_mouse_wheel.zig
Executable file → Normal file
@ -30,18 +30,18 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.white);
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawRectangle(screenWidth / 2 - 40, @as(i32, @intFromFloat(boxPositionY)), 80, 80, rl.Color.maroon);
|
||||
rl.drawRectangle(screenWidth / 2 - 40, @as(i32, @intFromFloat(boxPositionY)), 80, 80, .maroon);
|
||||
|
||||
rl.drawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, rl.Color.gray);
|
||||
rl.drawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, .gray);
|
||||
|
||||
rl.drawText(
|
||||
rl.textFormat("Box position Y: %03i", .{@as(i32, @intFromFloat(boxPositionY))}),
|
||||
10,
|
||||
40,
|
||||
20,
|
||||
rl.Color.light_gray,
|
||||
.light_gray,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
30
examples/core/input_multitouch.zig
Executable file → Normal file
@ -26,25 +26,25 @@ pub fn main() anyerror!void {
|
||||
//----------------------------------------------------------------------------------
|
||||
ballPosition = rl.getMousePosition();
|
||||
|
||||
ballColor = rl.Color.beige;
|
||||
ballColor = .beige;
|
||||
|
||||
if (rl.isMouseButtonDown(rl.MouseButton.mouse_button_left)) {
|
||||
ballColor = rl.Color.maroon;
|
||||
if (rl.isMouseButtonDown(.left)) {
|
||||
ballColor = .maroon;
|
||||
}
|
||||
if (rl.isMouseButtonDown(rl.MouseButton.mouse_button_middle)) {
|
||||
ballColor = rl.Color.lime;
|
||||
if (rl.isMouseButtonDown(.middle)) {
|
||||
ballColor = .lime;
|
||||
}
|
||||
if (rl.isMouseButtonDown(rl.MouseButton.mouse_button_right)) {
|
||||
ballColor = rl.Color.dark_blue;
|
||||
if (rl.isMouseButtonDown(.right)) {
|
||||
ballColor = .dark_blue;
|
||||
}
|
||||
|
||||
if (rl.isMouseButtonPressed(rl.MouseButton.mouse_button_left)) {
|
||||
if (rl.isMouseButtonPressed(.left)) {
|
||||
touchCounter = 10;
|
||||
}
|
||||
if (rl.isMouseButtonPressed(rl.MouseButton.mouse_button_middle)) {
|
||||
if (rl.isMouseButtonPressed(.middle)) {
|
||||
touchCounter = 10;
|
||||
}
|
||||
if (rl.isMouseButtonPressed(rl.MouseButton.mouse_button_right)) {
|
||||
if (rl.isMouseButtonPressed(.right)) {
|
||||
touchCounter = 10;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
const nums = [_]i32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
for (nums) |i| {
|
||||
@ -68,13 +68,13 @@ pub fn main() anyerror!void {
|
||||
if ((touchPosition.x >= 0) and (touchPosition.y >= 0)) {
|
||||
|
||||
// Draw circle and touch index number
|
||||
rl.drawCircleV(touchPosition, 34, rl.Color.orange);
|
||||
rl.drawCircleV(touchPosition, 34, .orange);
|
||||
rl.drawText(
|
||||
rl.textFormat("%d", .{i}),
|
||||
@as(i32, @intFromFloat(touchPosition.x)) - 10,
|
||||
@as(i32, @intFromFloat(touchPosition.y)) - 70,
|
||||
40,
|
||||
rl.Color.black,
|
||||
.black,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -82,8 +82,8 @@ pub fn main() anyerror!void {
|
||||
// Draw the normal mouse location
|
||||
rl.drawCircleV(ballPosition, 30 + (touchCounter * 3), ballColor);
|
||||
|
||||
rl.drawText("move ball with mouse and click mouse button to change color", 10, 10, 20, rl.Color.dark_gray);
|
||||
rl.drawText("touch the screen at multiple locations to get multiple balls", 10, 30, 20, rl.Color.dark_gray);
|
||||
rl.drawText("move ball with mouse and click mouse button to change color", 10, 10, 20, .dark_gray);
|
||||
rl.drawText("touch the screen at multiple locations to get multiple balls", 10, 30, 20, .dark_gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,9 +58,9 @@ pub fn main() anyerror!void {
|
||||
while (!rl.windowShouldClose()) {
|
||||
// Update
|
||||
// ---------------------------------------------------------------------
|
||||
if (rl.isKeyPressed(.key_f)) rl.toggleFullscreen(); // Modifies window size when scaling!
|
||||
if (rl.isKeyPressed(.f)) rl.toggleFullscreen(); // Modifies window size when scaling!
|
||||
|
||||
if (rl.isKeyPressed(.key_r)) {
|
||||
if (rl.isKeyPressed(.r)) {
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_resizable = true })) {
|
||||
rl.clearWindowState(rl.ConfigFlags { .window_resizable = true });
|
||||
} else {
|
||||
@ -68,7 +68,7 @@ pub fn main() anyerror!void {
|
||||
}
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_d)) {
|
||||
if (rl.isKeyPressed(.d)) {
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_undecorated = true })) {
|
||||
rl.clearWindowState(rl.ConfigFlags { .window_undecorated = true });
|
||||
} else {
|
||||
@ -76,7 +76,7 @@ pub fn main() anyerror!void {
|
||||
}
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_h)) {
|
||||
if (rl.isKeyPressed(.h)) {
|
||||
if (!rl.isWindowState(rl.ConfigFlags { .window_hidden = true })) {
|
||||
rl.setWindowState(rl.ConfigFlags { .window_hidden = true });
|
||||
}
|
||||
@ -88,7 +88,7 @@ pub fn main() anyerror!void {
|
||||
if (frames_counter >= 240) rl.clearWindowState(rl.ConfigFlags { .window_hidden = true }); // Show window after 3 seconds
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_n)) {
|
||||
if (rl.isKeyPressed(.n)) {
|
||||
if (!rl.isWindowState(rl.ConfigFlags { .window_minimized = true })) {
|
||||
rl.minimizeWindow();
|
||||
}
|
||||
@ -100,32 +100,32 @@ pub fn main() anyerror!void {
|
||||
if (frames_counter >= 240) rl.restoreWindow(); // Restore window after 3 seconds
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_m)) {
|
||||
if (rl.isKeyPressed(.m)) {
|
||||
// NOTE: Requires `flag_window_resizable` enabled!
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_maximized = true })) {
|
||||
rl.restoreWindow();
|
||||
} else rl.maximizeWindow();
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_u)) {
|
||||
if (rl.isKeyPressed(.u)) {
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_unfocused = true })) {
|
||||
rl.clearWindowState(rl.ConfigFlags { .window_unfocused = true });
|
||||
} else rl.setWindowState(rl.ConfigFlags { .window_unfocused = true });
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_t)) {
|
||||
if (rl.isKeyPressed(.t)) {
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_topmost = true })) {
|
||||
rl.clearWindowState(rl.ConfigFlags { .window_topmost = true });
|
||||
} else rl.setWindowState(rl.ConfigFlags { .window_topmost = true });
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_a)) {
|
||||
if (rl.isKeyPressed(.a)) {
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_always_run = true })) {
|
||||
rl.clearWindowState(rl.ConfigFlags { .window_always_run = true });
|
||||
} else rl.setWindowState(rl.ConfigFlags { .window_always_run = true });
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.key_v)) {
|
||||
if (rl.isKeyPressed(.v)) {
|
||||
if (rl.isWindowState(rl.ConfigFlags { .vsync_hint = true })) {
|
||||
rl.clearWindowState(rl.ConfigFlags { .vsync_hint = true });
|
||||
} else rl.setWindowState(rl.ConfigFlags { .vsync_hint = true });
|
||||
@ -149,17 +149,17 @@ pub fn main() anyerror!void {
|
||||
defer rl.endDrawing();
|
||||
|
||||
if (rl.isWindowState(rl.ConfigFlags { .window_transparent = true })) {
|
||||
rl.clearBackground(rl.Color.blank);
|
||||
} else rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.blank);
|
||||
} else rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawCircleV(ball_position, ball_radius, rl.Color.maroon);
|
||||
rl.drawCircleV(ball_position, ball_radius, .maroon);
|
||||
rl.drawRectangleLinesEx(
|
||||
rl.Rectangle.init(0, 0, @floatFromInt(rl.getScreenWidth()), @floatFromInt(rl.getScreenHeight())),
|
||||
.init(0, 0, @floatFromInt(rl.getScreenWidth()), @floatFromInt(rl.getScreenHeight())),
|
||||
4,
|
||||
rl.Color.ray_white,
|
||||
.ray_white,
|
||||
);
|
||||
|
||||
rl.drawCircleV(rl.getMousePosition(), 10, rl.Color.dark_blue);
|
||||
rl.drawCircleV(rl.getMousePosition(), 10, .dark_blue);
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
|
||||
@ -168,7 +168,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
40,
|
||||
10,
|
||||
rl.Color.green,
|
||||
.green,
|
||||
);
|
||||
|
||||
// Draw window state info
|
||||
@ -177,7 +177,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
60,
|
||||
10,
|
||||
rl.Color.gray,
|
||||
.gray,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[F] flag_fullscreen_mode: %d", .{
|
||||
@ -186,7 +186,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
80,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[R] flag_window_resizable: %d", .{
|
||||
@ -195,7 +195,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
100,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[D] flag_window_undecorated: %d", .{
|
||||
@ -204,7 +204,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
120,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[H] flag_window_hidden: %d", .{
|
||||
@ -213,7 +213,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
140,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[N] flag_window_minimized: %d", .{
|
||||
@ -222,7 +222,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
160,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[M] flag_window_maximized: %d", .{
|
||||
@ -231,7 +231,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
180,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[U] flag_window_unfocused: %d", .{
|
||||
@ -240,7 +240,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
200,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[T] flag_window_topmost: %d", .{
|
||||
@ -249,7 +249,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
220,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[A] flag_window_always_run: %d", .{
|
||||
@ -258,7 +258,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
240,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("[V] flag_vsync_hint: %d", .{
|
||||
@ -267,7 +267,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
260,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
|
||||
rl.drawText(
|
||||
@ -275,7 +275,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
300,
|
||||
10,
|
||||
rl.Color.gray,
|
||||
.gray,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("flag_window_highdpi: %d", .{
|
||||
@ -284,7 +284,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
320,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("flag_window_transparent: %d", .{
|
||||
@ -293,7 +293,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
340,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
rl.drawText(
|
||||
rl.textFormat("flag_msaa_4x_hint: %d", .{
|
||||
@ -302,7 +302,7 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
360,
|
||||
10,
|
||||
rl.Color.lime,
|
||||
.lime,
|
||||
);
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
60
examples/gui/message_box.zig
Normal file
@ -0,0 +1,60 @@
|
||||
//! # raylib-zig [gui] example - message box
|
||||
//!
|
||||
//! Example originally created with raylib-zig 5.6-dev, last time updated with
|
||||
//! raylib-zig 5.6-dev
|
||||
//!
|
||||
//! 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) Nikolas Wipper 2025
|
||||
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const rg = @import("raygui");
|
||||
|
||||
/// `rl.getColor` only accepts a `u32`. Performing `@intCast` on the return value
|
||||
/// of `rg.getStyle` invokes checked undefined behavior from Zig when passed to
|
||||
/// `rl.getColor`, hence the custom implementation here...
|
||||
fn getColor(hex: i32) rl.Color {
|
||||
var color: rl.Color = .black;
|
||||
// zig fmt: off
|
||||
color.r = @intCast((hex >> 24) & 0xFF);
|
||||
color.g = @intCast((hex >> 16) & 0xFF);
|
||||
color.b = @intCast((hex >> 8) & 0xFF);
|
||||
color.a = @intCast((hex >> 0) & 0xFF);
|
||||
// zig fmt: on
|
||||
return color;
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
rl.initWindow(400, 200, "raygui - controls test suite");
|
||||
defer rl.closeWindow();
|
||||
|
||||
rl.setTargetFPS(60);
|
||||
|
||||
var show_message_box = false;
|
||||
|
||||
const color_int = rg.getStyle(.default, .{ .default = .background_color });
|
||||
|
||||
while (!rl.windowShouldClose()) {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(getColor(color_int));
|
||||
|
||||
if (rg.button(.init(24, 24, 120, 30), "#191#Show Message"))
|
||||
show_message_box = true;
|
||||
|
||||
if (show_message_box) {
|
||||
const result = rg.messageBox(
|
||||
.init(85, 70, 250, 100),
|
||||
"#191#Message Box",
|
||||
"Hi! This is a message",
|
||||
"Nice;Cool",
|
||||
);
|
||||
|
||||
if (result >= 0) show_message_box = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
148
examples/models/models_bone_socket.zig
Normal file
@ -0,0 +1,148 @@
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
|
||||
const BONE_SOCKETS = 3;
|
||||
const BONE_SOCKET_HAT = 0;
|
||||
const BONE_SOCKET_HAND_R = 1;
|
||||
const BONE_SOCKET_HAND_L = 2;
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
const screenWidth: i32 = 800;
|
||||
const screenHeight: i32 = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [models] example - bone socket");
|
||||
defer rl.closeWindow();
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera: rl.Camera3D = .{
|
||||
.position = .{ .x = 5.0, .y = 5.0, .z = 5.0 },
|
||||
.target = .{ .x = 0.0, .y = 2.0, .z = 0.0 },
|
||||
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 },
|
||||
.fovy = 45.0,
|
||||
.projection = .perspective,
|
||||
};
|
||||
|
||||
// Load gltf model
|
||||
var characterModel: rl.Model = try rl.loadModel("examples/models/resources/models/gltf/greenman.glb"); // Load character model
|
||||
defer characterModel.unload();
|
||||
const equipModel: [BONE_SOCKETS]rl.Model = .{
|
||||
try rl.loadModel("examples/models/resources/models/gltf/greenman_hat.glb"), // Index for the hat model is the same as BONE_SOCKET_HAT
|
||||
try rl.loadModel("examples/models/resources/models/gltf/greenman_sword.glb"), // Index for the sword model is the same as BONE_SOCKET_HAND_R
|
||||
try rl.loadModel("examples/models/resources/models/gltf/greenman_shield.glb"), // Index for the shield model is the same as BONE_SOCKET_HAND_L
|
||||
};
|
||||
defer for (equipModel) |model| {
|
||||
model.unload();
|
||||
};
|
||||
|
||||
var showEquip: [3]bool = .{ true, true, true }; // Toggle on/off equip
|
||||
|
||||
// Load gltf model animations
|
||||
var animIndex: usize = 0;
|
||||
var animCurrentFrame: i32 = 0;
|
||||
const modelAnimations = try rl.loadModelAnimations("examples/models/resources/models/gltf/greenman.glb");
|
||||
const animsCount = modelAnimations.len;
|
||||
defer rl.unloadModelAnimations(modelAnimations);
|
||||
|
||||
// indices of bones for sockets
|
||||
var boneSocketIndex: [BONE_SOCKETS]usize = undefined;
|
||||
|
||||
// search bones for sockets
|
||||
for (0..@as(usize, @intCast(characterModel.boneCount))) |i| {
|
||||
const boneName: [:0]const u8 = @ptrCast(&characterModel.bones[i].name);
|
||||
if (rl.textIsEqual(boneName, "socket_hat")) {
|
||||
boneSocketIndex[BONE_SOCKET_HAT] = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rl.textIsEqual(boneName, "socket_hand_R")) {
|
||||
boneSocketIndex[BONE_SOCKET_HAND_R] = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rl.textIsEqual(boneName, "socket_hand_L")) {
|
||||
boneSocketIndex[BONE_SOCKET_HAND_L] = i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const position: rl.Vector3 = .zero(); // Set model position
|
||||
var angle: f32 = 0.0; // Set angle for rotate character
|
||||
|
||||
rl.disableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
||||
while (!rl.windowShouldClose()) {
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.updateCamera(&camera, .third_person);
|
||||
|
||||
// Rotate character
|
||||
if (rl.isKeyDown(.f)) {
|
||||
angle += 1.0;
|
||||
angle = @mod(angle, 360.0);
|
||||
} else if (rl.isKeyDown(.h)) {
|
||||
angle -= 1.0;
|
||||
angle = @mod(angle, 360.0);
|
||||
}
|
||||
|
||||
// Select current animation
|
||||
if (rl.isKeyPressed(.t)) animIndex = (animIndex + 1) % animsCount else if (rl.isKeyPressed(.g)) animIndex = (animIndex + animsCount - 1) % animsCount;
|
||||
|
||||
// Toggle shown of equip
|
||||
if (rl.isKeyPressed(.one)) showEquip[BONE_SOCKET_HAT] = !showEquip[BONE_SOCKET_HAT];
|
||||
if (rl.isKeyPressed(.two)) showEquip[BONE_SOCKET_HAND_R] = !showEquip[BONE_SOCKET_HAND_R];
|
||||
if (rl.isKeyPressed(.three)) showEquip[BONE_SOCKET_HAND_L] = !showEquip[BONE_SOCKET_HAND_L];
|
||||
|
||||
// Update model animation
|
||||
const anim = modelAnimations[animIndex];
|
||||
animCurrentFrame = @mod(animCurrentFrame + 1, anim.frameCount);
|
||||
rl.updateModelAnimation(characterModel, anim, animCurrentFrame);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
{
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
{
|
||||
rl.beginMode3D(camera);
|
||||
defer rl.endMode3D();
|
||||
// Draw character
|
||||
const characterRotate: rl.Quaternion = rl.math.quaternionFromAxisAngle(.{ .x = 0.0, .y = 1.0, .z = 0.0 }, angle * std.math.rad_per_deg);
|
||||
characterModel.transform = rl.math.matrixMultiply(rl.math.quaternionToMatrix(characterRotate), rl.math.matrixTranslate(position.x, position.y, position.z));
|
||||
rl.updateModelAnimation(characterModel, anim, animCurrentFrame);
|
||||
rl.drawMesh(characterModel.meshes[0], characterModel.materials[1], characterModel.transform);
|
||||
|
||||
// Draw equipments (hat, sword, shield)
|
||||
for (0..BONE_SOCKETS) |i| {
|
||||
if (!showEquip[i]) continue;
|
||||
|
||||
const transform = &anim.framePoses[@intCast(animCurrentFrame)][boneSocketIndex[i]];
|
||||
const inRotation = characterModel.bindPose[boneSocketIndex[i]].rotation;
|
||||
const outRotation = transform.rotation;
|
||||
|
||||
// Calculate socket rotation (angle between bone in initial pose and same bone in current animation frame)
|
||||
const rotate = rl.math.quaternionMultiply(outRotation, rl.math.quaternionInvert(inRotation));
|
||||
var matrixTransform = rl.math.quaternionToMatrix(rotate);
|
||||
// Translate socket to its position in the current animation
|
||||
matrixTransform = rl.math.matrixMultiply(matrixTransform, rl.math.matrixTranslate(transform.translation.x, transform.translation.y, transform.translation.z));
|
||||
// Transform the socket using the transform of the character (angle and translate)
|
||||
matrixTransform = rl.math.matrixMultiply(matrixTransform, characterModel.transform);
|
||||
|
||||
// Draw mesh at socket position with socket angle rotation
|
||||
rl.drawMesh(equipModel[i].meshes[0], equipModel[i].materials[1], matrixTransform);
|
||||
}
|
||||
|
||||
rl.drawGrid(10, 1.0);
|
||||
}
|
||||
|
||||
rl.drawText("Use the T/G to switch animation", 10, 10, 20, .gray);
|
||||
rl.drawText("Use the F/H to rotate character left/right", 10, 35, 20, .gray);
|
||||
rl.drawText("Use the 1,2,3 to toggle shown of hat, sword and shield", 10, 60, 20, .gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
}
|
||||
119
examples/models/models_box_collisions.zig
Normal file
@ -0,0 +1,119 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
const screenWidth: i32 = 800;
|
||||
const screenHeight: i32 = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [models] example - box collisions");
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
const camera: rl.Camera = .{
|
||||
.position = .{ .x = 0.0, .y = 10.0, .z = 10.0 },
|
||||
.target = .{ .x = 0.0, .y = 0.0, .z = 0.0 },
|
||||
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 },
|
||||
.fovy = 45.0,
|
||||
.projection = .perspective,
|
||||
};
|
||||
|
||||
var playerPosition: rl.Vector3 = .{ .x = 0.0, .y = 1.0, .z = 2.0 };
|
||||
const playerSize: rl.Vector3 = .{ .x = 1.0, .y = 2.0, .z = 1.0 };
|
||||
var playerColor: rl.Color = .green;
|
||||
|
||||
const enemyBoxPos: rl.Vector3 = .{ .x = -4.0, .y = 1.0, .z = 0.0 };
|
||||
const enemyBoxSize: rl.Vector3 = .{ .x = 2.0, .y = 2.0, .z = 2.0 };
|
||||
|
||||
const enemySpherePos: rl.Vector3 = .{ .x = 4.0, .y = 0.0, .z = 0.0 };
|
||||
const enemySphereSize: f32 = 1.5;
|
||||
|
||||
var collision: bool = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
||||
while (!rl.windowShouldClose()) {
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Move player
|
||||
if (rl.isKeyDown(.right)) playerPosition.x += 0.2 else if (rl.isKeyDown(.left)) playerPosition.x -= 0.2 else if (rl.isKeyDown(.down)) playerPosition.z += 0.2 else if (rl.isKeyDown(.up)) playerPosition.z -= 0.2;
|
||||
|
||||
collision = false;
|
||||
|
||||
// Check collisions player vs enemy-box
|
||||
if (rl.checkCollisionBoxes(.{
|
||||
.min = .{
|
||||
.x = playerPosition.x - playerSize.x / 2,
|
||||
.y = playerPosition.y - playerSize.y / 2,
|
||||
.z = playerPosition.z - playerSize.z / 2,
|
||||
},
|
||||
.max = .{
|
||||
.x = playerPosition.x + playerSize.x / 2,
|
||||
.y = playerPosition.y + playerSize.y / 2,
|
||||
.z = playerPosition.z + playerSize.z / 2,
|
||||
},
|
||||
}, .{
|
||||
.min = .{
|
||||
.x = enemyBoxPos.x - enemyBoxSize.x / 2,
|
||||
.y = enemyBoxPos.y - enemyBoxSize.y / 2,
|
||||
.z = enemyBoxPos.z - enemyBoxSize.z / 2,
|
||||
},
|
||||
.max = .{
|
||||
.x = enemyBoxPos.x + enemyBoxSize.x / 2,
|
||||
.y = enemyBoxPos.y + enemyBoxSize.y / 2,
|
||||
.z = enemyBoxPos.z + enemyBoxSize.z / 2,
|
||||
},
|
||||
})) collision = true;
|
||||
|
||||
// Check collisions player vs enemy-sphere
|
||||
if (rl.checkCollisionBoxSphere(.{
|
||||
.min = .{
|
||||
.x = playerPosition.x - playerSize.x / 2,
|
||||
.y = playerPosition.y - playerSize.y / 2,
|
||||
.z = playerPosition.z - playerSize.z / 2,
|
||||
},
|
||||
.max = .{
|
||||
.x = playerPosition.x + playerSize.x / 2,
|
||||
.y = playerPosition.y + playerSize.y / 2,
|
||||
.z = playerPosition.z + playerSize.z / 2,
|
||||
},
|
||||
}, enemySpherePos, enemySphereSize)) collision = true;
|
||||
|
||||
if (collision) playerColor = .red else playerColor = .green;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
{
|
||||
rl.beginMode3D(camera);
|
||||
defer rl.endMode3D();
|
||||
|
||||
// Draw enemy-box
|
||||
rl.drawCube(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, .gray);
|
||||
rl.drawCubeWires(enemyBoxPos, enemyBoxSize.x, enemyBoxSize.y, enemyBoxSize.z, .dark_gray);
|
||||
|
||||
// Draw enemy-sphere
|
||||
rl.drawSphere(enemySpherePos, enemySphereSize, .gray);
|
||||
rl.drawSphereWires(enemySpherePos, enemySphereSize, 16, 16, .dark_gray);
|
||||
|
||||
// Draw player
|
||||
rl.drawCubeV(playerPosition, playerSize, playerColor);
|
||||
|
||||
rl.drawGrid(10, 1.0); // Draw a grid
|
||||
|
||||
}
|
||||
|
||||
rl.drawText("Move player with arrow keys to collide", 220, 40, 20, .gray);
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
49
examples/models/models_heightmap.zig
Normal file
@ -0,0 +1,49 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
const screenWidth: i32 = 800;
|
||||
const screenHeight: i32 = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing");
|
||||
const cameraPosition: rl.Vector3 = .{ .x = 18, .y = 21, .z = 18 };
|
||||
const cameraTarget: rl.Vector3 = .{ .x = 0, .y = 0, .z = 0 };
|
||||
const cameraUp: rl.Vector3 = .{ .x = 0, .y = 1, .z = 0 };
|
||||
const cameraProjection = rl.CameraProjection.perspective;
|
||||
var camera = rl.Camera{ .fovy = 45.0, .position = cameraPosition, .up = cameraUp, .projection = cameraProjection, .target = cameraTarget };
|
||||
|
||||
const image: rl.Image = try rl.loadImage("examples/models/resources/heightmap.png");
|
||||
|
||||
const texture: rl.Texture2D = try rl.loadTextureFromImage(image);
|
||||
|
||||
const meshSize = rl.Vector3{ .x = 16, .y = 8, .z = 16 };
|
||||
const mesh = rl.genMeshHeightmap(image, meshSize);
|
||||
|
||||
var model = try rl.loadModelFromMesh(mesh);
|
||||
model.materials[0].maps[@intFromEnum(rl.MATERIAL_MAP_DIFFUSE)].texture = texture;
|
||||
|
||||
const mapPosition = rl.Vector3{ .x = -8.0, .y = 0.0, .z = -8.0 };
|
||||
|
||||
rl.unloadImage(image);
|
||||
|
||||
rl.setTargetFPS(60);
|
||||
|
||||
while (!rl.windowShouldClose()) {
|
||||
rl.updateCamera(&camera, .orbital);
|
||||
rl.beginDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
rl.beginMode3D(camera);
|
||||
rl.drawModel(model, mapPosition, 1, .red);
|
||||
rl.drawGrid(20, 1.0);
|
||||
rl.endMode3D();
|
||||
rl.drawTexture(texture, screenWidth - texture.width - 20, 20, .white);
|
||||
rl.drawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, .green);
|
||||
rl.drawFPS(10, 10);
|
||||
|
||||
rl.endDrawing();
|
||||
}
|
||||
rl.unloadTexture(texture);
|
||||
rl.unloadModel(model);
|
||||
|
||||
rl.closeWindow();
|
||||
}
|
||||
153
examples/models/models_rlgl_solar_system.zig
Normal file
@ -0,0 +1,153 @@
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const rlgl = rl.gl;
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
const screenWidth: i32 = 800;
|
||||
const screenHeight: i32 = 450;
|
||||
|
||||
const sunRadius = 4.0;
|
||||
const earthRadius = 0.6;
|
||||
const earthOrbitRadius = 8.0;
|
||||
const moonRadius = 0.16;
|
||||
const moonOrbitRadius = 1.5;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [models] example - rlgl solar system");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera: rl.Camera = std.mem.zeroes(rl.Camera);
|
||||
|
||||
camera.position = .{ .x = 16.0, .y = 16.0, .z = 16.0 }; // Camera position
|
||||
camera.target = .{ .x = 0.0, .y = 0.0, .z = 0.0 }; // Camera looking at point
|
||||
camera.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 }; // Camera up vector (rotation towards target)
|
||||
camera.fovy = 45.0; // Camera field-of-view Y
|
||||
camera.projection = .perspective; // Camera projection type
|
||||
|
||||
const rotationSpeed: f32 = 0.2; // General system rotation speed
|
||||
|
||||
var earthRotation: f32 = 0.0; // Rotation of earth around itself (days) in degrees
|
||||
var earthOrbitRotation: f32 = 0.0; // Rotation of earth around the Sun (years) in degrees
|
||||
var moonRotation: f32 = 0.0; // Rotation of moon around itself
|
||||
var moonOrbitRotation: f32 = 0.0; // Rotation of moon around earth in degrees
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
||||
while (!rl.windowShouldClose()) {
|
||||
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.updateCamera(&camera, .orbital);
|
||||
|
||||
earthRotation += (5.0 * rotationSpeed);
|
||||
earthOrbitRotation += (365.0 / 360.0 * (5.0 * rotationSpeed) * rotationSpeed);
|
||||
moonRotation += (2.0 * rotationSpeed);
|
||||
moonOrbitRotation += (8.0 * rotationSpeed);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
{
|
||||
rl.beginMode3D(camera);
|
||||
defer rl.endMode3D();
|
||||
|
||||
rlgl.rlPushMatrix();
|
||||
rlgl.rlScalef(sunRadius, sunRadius, sunRadius); // Scale Sun
|
||||
drawSphereBasic(.gold); // Draw the Sun
|
||||
rlgl.rlPopMatrix();
|
||||
|
||||
rlgl.rlPushMatrix();
|
||||
rlgl.rlRotatef(earthOrbitRotation, 0.0, 1.0, 0.0); // Rotation for Earth orbit around Sun
|
||||
rlgl.rlTranslatef(earthOrbitRadius, 0.0, 0.0); // Translation for Earth orbit
|
||||
|
||||
rlgl.rlPushMatrix();
|
||||
rlgl.rlRotatef(earthRotation, 0.25, 1.0, 0.0); // Rotation for Earth itself
|
||||
rlgl.rlScalef(earthRadius, earthRadius, earthRadius); // Scale Earth
|
||||
|
||||
drawSphereBasic(.blue); // Draw the Earth
|
||||
rlgl.rlPopMatrix();
|
||||
|
||||
rlgl.rlRotatef(moonOrbitRotation, 0.0, 1.0, 0.0); // Rotation for Moon orbit around Earth
|
||||
rlgl.rlTranslatef(moonOrbitRadius, 0.0, 0.0); // Translation for Moon orbit
|
||||
rlgl.rlRotatef(moonRotation, 0.0, 1.0, 0.0); // Rotation for Moon itself
|
||||
rlgl.rlScalef(moonRadius, moonRadius, moonRadius); // Scale Moon
|
||||
|
||||
drawSphereBasic(.light_gray); // Draw the Moon
|
||||
rlgl.rlPopMatrix();
|
||||
|
||||
// Some reference elements (not affected by previous matrix transformations)
|
||||
rl.drawCircle3D(.{ .x = 0.0, .y = 0.0, .z = 0.0 }, earthOrbitRadius, .{ .x = 1, .y = 0, .z = 0 }, 90.0, rl.fade(.red, 0.5));
|
||||
rl.drawGrid(20, 1.0);
|
||||
}
|
||||
|
||||
rl.drawText("EARTH ORBITING AROUND THE SUN!", 400, 10, 20, .maroon);
|
||||
rl.drawFPS(10, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//--------------------------------------------------------------------------------------------
|
||||
// Draw sphere without any matrix transformation
|
||||
// NOTE: Sphere is drawn in world position ( 0, 0, 0 ) with radius 1.0f
|
||||
fn drawSphereBasic(color: rl.Color) void {
|
||||
const rings: usize = 16;
|
||||
const slices: usize = 16;
|
||||
const floatRings: f32 = @floatFromInt(rings);
|
||||
const floatSlices: f32 = @floatFromInt(slices);
|
||||
|
||||
// Make sure there is enough space in the internal render batch
|
||||
// buffer to store all required vertex, batch is reseted if required
|
||||
_ = rlgl.rlCheckRenderBatchLimit((rings + 2) * slices * 6);
|
||||
|
||||
rlgl.rlBegin(rlgl.rl_triangles);
|
||||
rlgl.rlColor4ub(color.r, color.g, color.b, color.a);
|
||||
|
||||
for (0..(rings + 2)) |i| {
|
||||
const floatI: f32 = @floatFromInt(i);
|
||||
for (0..slices) |j| {
|
||||
const floatJ: f32 = @floatFromInt(j);
|
||||
rlgl.rlVertex3f(
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * floatI)) * std.math.sin(std.math.rad_per_deg * (floatJ * 360 / floatSlices)),
|
||||
std.math.sin(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * floatI)),
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * floatI)) * std.math.cos(std.math.rad_per_deg * (floatJ * 360 / floatSlices)),
|
||||
);
|
||||
rlgl.rlVertex3f(
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))) * std.math.sin(std.math.rad_per_deg * ((floatJ + 1.0) * 360 / floatSlices)),
|
||||
std.math.sin(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))),
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))) * std.math.cos(std.math.rad_per_deg * ((floatJ + 1.0) * 360 / floatSlices)),
|
||||
);
|
||||
rlgl.rlVertex3f(
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))) * std.math.sin(std.math.rad_per_deg * (floatJ * 360 / floatSlices)),
|
||||
std.math.sin(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))),
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))) * std.math.cos(std.math.rad_per_deg * (floatJ * 360 / floatSlices)),
|
||||
);
|
||||
|
||||
rlgl.rlVertex3f(
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * floatI)) * std.math.sin(std.math.rad_per_deg * (floatJ * 360 / floatSlices)),
|
||||
std.math.sin(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * floatI)),
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * floatI)) * std.math.cos(std.math.rad_per_deg * (floatJ * 360 / floatSlices)),
|
||||
);
|
||||
rlgl.rlVertex3f(
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI))) * std.math.sin(std.math.rad_per_deg * ((floatJ + 1.0) * 360 / floatSlices)),
|
||||
std.math.sin(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI))),
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI))) * std.math.cos(std.math.rad_per_deg * ((floatJ + 1.0) * 360 / floatSlices)),
|
||||
);
|
||||
rlgl.rlVertex3f(
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))) * std.math.sin(std.math.rad_per_deg * ((floatJ + 1.0) * 360 / floatSlices)),
|
||||
std.math.sin(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))),
|
||||
std.math.cos(std.math.rad_per_deg * (270.0 + (180.0 / (floatRings + 1.0)) * (floatI + 1.0))) * std.math.cos(std.math.rad_per_deg * ((floatJ + 1.0) * 360 / floatSlices)),
|
||||
);
|
||||
}
|
||||
}
|
||||
rlgl.rlEnd();
|
||||
}
|
||||
BIN
examples/models/resources/heightmap.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
5
examples/models/resources/models/gltf/LICENSE
Normal file
@ -0,0 +1,5 @@
|
||||
robot.glb model by @Quaternius (https://www.patreon.com/quaternius)
|
||||
Licensed under CC0 1.0 Universal (CC0 1.0) - Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
|
||||
greenman.glb, greenman_hat.glb, greenman_sword.glb, greenman_shield.glb models by @iP (https://github.com/ipzaur)
|
||||
Licensed under CC0 1.0 Universal (CC0 1.0) - Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
BIN
examples/models/resources/models/gltf/greenman.glb
Normal file
BIN
examples/models/resources/models/gltf/greenman_hat.glb
Normal file
BIN
examples/models/resources/models/gltf/greenman_shield.glb
Normal file
BIN
examples/models/resources/models/gltf/greenman_sword.glb
Normal file
117
examples/shaders/raymarching.zig
Normal file
@ -0,0 +1,117 @@
|
||||
// raylib [shaders] example - Raymarching shapes generation
|
||||
//
|
||||
// Example complexity rating: [★★★★] 4/4
|
||||
//
|
||||
// NOTE: This example requires raylib OpenGL 3.3 for shaders support and only #version 330
|
||||
// is currently supported. OpenGL ES 2.0 platforms are not supported at the moment.
|
||||
//
|
||||
// Example originally created with raylib 2.0, 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) 2018-2025 Ramon Santamaria (@raysan5)
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.setConfigFlags(rl.ConfigFlags{ .window_resizable = true });
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [shaders] example - raymarching shapes");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera = rl.Camera3D{
|
||||
.position = .{ .x = 2.5, .y = 2.5, .z = 3.0 }, // Camera position
|
||||
.target = .{ .x = 0.0, .y = 0.0, .z = 0.7 }, // Camera looking at point
|
||||
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 }, // Camera up vector (rotation towards target)
|
||||
.fovy = 65.0, // Camera field-of-view Y
|
||||
.projection = .perspective, // Camera projection type
|
||||
};
|
||||
|
||||
// Load raymarching shader
|
||||
const shader = try rl.loadShader(null, "resources/shaders/glsl330/raymarching.fs");
|
||||
defer rl.unloadShader(shader);
|
||||
|
||||
// Get shader locations for required uniforms
|
||||
const viewEyeLoc = rl.getShaderLocation(shader, "viewEye");
|
||||
const viewCenterLoc = rl.getShaderLocation(shader, "viewCenter");
|
||||
const runTimeLoc = rl.getShaderLocation(shader, "runTime");
|
||||
const resolutionLoc = rl.getShaderLocation(shader, "resolution");
|
||||
|
||||
var resolution = [2]f32{ @floatFromInt(screenWidth), @floatFromInt(screenHeight) };
|
||||
rl.setShaderValue(shader, resolutionLoc, &resolution, .vec2);
|
||||
|
||||
var runTime: f32 = 0.0;
|
||||
|
||||
rl.disableCursor(); // Limit cursor to relative movement inside the window
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.updateCamera(&camera, .first_person);
|
||||
|
||||
const cameraPos = [3]f32{ camera.position.x, camera.position.y, camera.position.z };
|
||||
const cameraTarget = [3]f32{ camera.target.x, camera.target.y, camera.target.z };
|
||||
|
||||
const deltaTime = rl.getFrameTime();
|
||||
runTime += deltaTime;
|
||||
|
||||
// Set shader required uniform values
|
||||
rl.setShaderValue(shader, viewEyeLoc, &cameraPos, .vec3);
|
||||
rl.setShaderValue(shader, viewCenterLoc, &cameraTarget, .vec3);
|
||||
rl.setShaderValue(shader, runTimeLoc, &runTime, .float);
|
||||
|
||||
// Check if screen is resized
|
||||
if (rl.isWindowResized()) {
|
||||
resolution = [2]f32{
|
||||
@floatFromInt(rl.getScreenWidth()),
|
||||
@floatFromInt(rl.getScreenHeight()),
|
||||
};
|
||||
rl.setShaderValue(shader, resolutionLoc, &resolution, .vec2);
|
||||
}
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
// We only draw a white full-screen rectangle,
|
||||
// frame is generated in shader using raymarching
|
||||
{
|
||||
rl.beginShaderMode(shader);
|
||||
defer rl.endShaderMode();
|
||||
|
||||
rl.drawRectangle(
|
||||
0,
|
||||
0,
|
||||
rl.getScreenWidth(),
|
||||
rl.getScreenHeight(),
|
||||
.white,
|
||||
);
|
||||
}
|
||||
|
||||
rl.drawText(
|
||||
"(c) Raymarching shader by Iñigo Quilez. MIT License.",
|
||||
rl.getScreenWidth() - 280,
|
||||
rl.getScreenHeight() - 20,
|
||||
10,
|
||||
.black,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
4
examples/shaders/resources/LICENSE.md
Normal file
@ -0,0 +1,4 @@
|
||||
| resource | author | licence | notes |
|
||||
| :----------------- | :-----------: | :------ | :---- |
|
||||
| fudesumi.png | [Eiden Marsal](https://www.artstation.com/marshall_z) | [CC-BY-NC](https://creativecommons.org/licenses/by-nc/4.0/) | - |
|
||||
| raysan.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
BIN
examples/shaders/resources/fudesumi.png
Normal file
|
After Width: | Height: | Size: 218 KiB |
BIN
examples/shaders/resources/raysan.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
80
examples/shaders/resources/shaders/glsl100/ascii.fs
Normal file
@ -0,0 +1,80 @@
|
||||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input from the vertex shader
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
// Output color for the screen
|
||||
varying vec4 finalColor;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
uniform vec2 resolution;
|
||||
|
||||
// Fontsize less then 9 may be not complete
|
||||
uniform float fontSize;
|
||||
|
||||
float GreyScale(in vec3 col)
|
||||
{
|
||||
return dot(col, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
float GetCharacter(float n, vec2 p)
|
||||
{
|
||||
p = floor(p*vec2(-4.0, 4.0) + 2.5);
|
||||
|
||||
// Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
|
||||
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
|
||||
{
|
||||
float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
|
||||
|
||||
// This checked if the 'a'-th bit of 'n' was set
|
||||
float shiftedN = floor(n/pow(2.0, a));
|
||||
|
||||
if (mod(shiftedN, 2.0) == 1.0)
|
||||
{
|
||||
return 1.0; // The bit is on
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0; // The bit is off, or we are outside the grid
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main shader logic
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 charPixelSize = vec2(fontSize, fontSize);
|
||||
vec2 uvCellSize = charPixelSize/resolution;
|
||||
|
||||
// The cell size is based on the fontSize set by application
|
||||
vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
|
||||
|
||||
vec3 cellColor = texture2D(texture0, cellUV).rgb;
|
||||
|
||||
// Gray is used to define what character will be selected to draw
|
||||
float gray = GreyScale(cellColor);
|
||||
|
||||
float n = 4096.0;
|
||||
|
||||
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||
if (gray > 0.2) n = 65600.0; // :
|
||||
if (gray > 0.3) n = 18725316.0; // v
|
||||
if (gray > 0.4) n = 15255086.0; // o
|
||||
if (gray > 0.5) n = 13121101.0; // &
|
||||
if (gray > 0.6) n = 15252014.0; // 8
|
||||
if (gray > 0.7) n = 13195790.0; // @
|
||||
if (gray > 0.8) n = 11512810.0; // #
|
||||
|
||||
vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
|
||||
|
||||
vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
|
||||
|
||||
// cellColor and charShape will define the color of the char
|
||||
vec3 color = cellColor*GetCharacter(n, p);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
||||
78
examples/shaders/resources/shaders/glsl120/ascii.fs
Normal file
@ -0,0 +1,78 @@
|
||||
#version 120
|
||||
|
||||
// Input from the vertex shader
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
// Output color for the screen
|
||||
varying vec4 finalColor;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
uniform vec2 resolution;
|
||||
|
||||
// Fontsize less then 9 may be not complete
|
||||
uniform float fontSize;
|
||||
|
||||
float GreyScale(in vec3 col)
|
||||
{
|
||||
return dot(col, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
float GetCharacter(float n, vec2 p)
|
||||
{
|
||||
p = floor(p*vec2(-4.0, 4.0) + 2.5);
|
||||
|
||||
// Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
|
||||
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
|
||||
{
|
||||
float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
|
||||
|
||||
// This checked if the 'a'-th bit of 'n' was set
|
||||
float shiftedN = floor(n/pow(2.0, a));
|
||||
|
||||
if (mod(shiftedN, 2.0) == 1.0)
|
||||
{
|
||||
return 1.0; // The bit is on
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0; // The bit is off, or we are outside the grid
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main shader logic
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 charPixelSize = vec2(fontSize, fontSize);
|
||||
vec2 uvCellSize = charPixelSize / resolution;
|
||||
|
||||
// The cell size is based on the fontSize set by application
|
||||
vec2 cellUV = floor(fragTexCoord / uvCellSize)*uvCellSize;
|
||||
|
||||
vec3 cellColor = texture2D(texture0, cellUV).rgb;
|
||||
|
||||
// Gray is used to define what character will be selected to draw
|
||||
float gray = GreyScale(cellColor);
|
||||
|
||||
float n = 4096.0;
|
||||
|
||||
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||
if (gray > 0.2) n = 65600.0; // :
|
||||
if (gray > 0.3) n = 18725316.0; // v
|
||||
if (gray > 0.4) n = 15255086.0; // o
|
||||
if (gray > 0.5) n = 13121101.0; // &
|
||||
if (gray > 0.6) n = 15252014.0; // 8
|
||||
if (gray > 0.7) n = 13195790.0; // @
|
||||
if (gray > 0.8) n = 11512810.0; // #
|
||||
|
||||
vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
|
||||
|
||||
vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
|
||||
|
||||
// cellColor and charShape will define the color of the char
|
||||
vec3 color = cellColor*GetCharacter(n, p);
|
||||
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
}
|
||||
73
examples/shaders/resources/shaders/glsl330/ascii.fs
Normal file
@ -0,0 +1,73 @@
|
||||
#version 330
|
||||
|
||||
// Input from the vertex shader
|
||||
in vec2 fragTexCoord;
|
||||
|
||||
// Output color for the screen
|
||||
out vec4 finalColor;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
uniform vec2 resolution;
|
||||
|
||||
// Fontsize less then 9 may be not complete
|
||||
uniform float fontSize;
|
||||
|
||||
float GreyScale(in vec3 col)
|
||||
{
|
||||
return dot(col, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
float GetCharacter(int n, vec2 p)
|
||||
{
|
||||
p = floor(p*vec2(-4.0, 4.0) + 2.5);
|
||||
|
||||
// Check if the coordinate is inside the 5x5 grid (0 to 4)
|
||||
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
|
||||
{
|
||||
int a = int(round(p.x) + 5.0*round(p.y));
|
||||
if (((n >> a) & 1) == 1)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0; // The bit is off, or we are outside the grid
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Main shader logic
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 charPixelSize = vec2(fontSize, fontSize);
|
||||
vec2 uvCellSize = charPixelSize/resolution;
|
||||
|
||||
// The cell size is based on the fontSize set by application
|
||||
vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
|
||||
|
||||
vec3 cellColor = texture(texture0, cellUV).rgb;
|
||||
|
||||
// Gray is used to define what character will be selected to draw
|
||||
float gray = GreyScale(cellColor);
|
||||
|
||||
int n = 4096;
|
||||
|
||||
// Character set from https://www.shadertoy.com/view/lssGDj
|
||||
// Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
|
||||
if (gray > 0.2) n = 65600; // :
|
||||
if (gray > 0.3) n = 18725316; // v
|
||||
if (gray > 0.4) n = 15255086; // o
|
||||
if (gray > 0.5) n = 13121101; // &
|
||||
if (gray > 0.6) n = 15252014; // 8
|
||||
if (gray > 0.7) n = 13195790; // @
|
||||
if (gray > 0.8) n = 11512810; // #
|
||||
|
||||
vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
|
||||
|
||||
vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
|
||||
|
||||
vec3 color = cellColor*GetCharacter(n, p);
|
||||
|
||||
finalColor = vec4(color, 1.0);
|
||||
}
|
||||
100
examples/shaders/shaders_ascii_rendering.zig
Normal file
@ -0,0 +1,100 @@
|
||||
// raylib-zig (c) 2025 Maicon Santana (@maiconpintoabreu)
|
||||
|
||||
const builtin = @import("builtin");
|
||||
const rl = @import("raylib");
|
||||
|
||||
const GLSL_VERSION: i16 = if (builtin.cpu.arch.isWasm()) 100 else 330;
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - monitor change");
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Texture to test static drawing
|
||||
const fudesumi: rl.Texture2D = try rl.loadTexture("examples/shaders/resources/fudesumi.png");
|
||||
defer fudesumi.unload();
|
||||
// Texture to test moving drawing
|
||||
const raysan: rl.Texture2D = try rl.loadTexture("examples/shaders/resources/raysan.png");
|
||||
defer raysan.unload();
|
||||
|
||||
// Load shader to be used on postprocessing
|
||||
const shader: rl.Shader = try rl.loadShader(
|
||||
null,
|
||||
rl.textFormat("examples/shaders/resources/shaders/glsl%i/ascii.fs", .{GLSL_VERSION}),
|
||||
);
|
||||
|
||||
// These locations are used to send data to the GPU
|
||||
const resolutionLoc: i32 = rl.getShaderLocation(shader, "resolution");
|
||||
const fontSizeLoc: i32 = rl.getShaderLocation(shader, "fontSize");
|
||||
|
||||
// Set the character size for the ASCII effect
|
||||
// Fontsize should be 9 or more
|
||||
var fontSize: f32 = 9.0;
|
||||
|
||||
// Send the updated values to the shader
|
||||
const resolution: rl.Vector2 = .{ .x = @floatFromInt(screenWidth), .y = @floatFromInt(screenHeight) };
|
||||
rl.setShaderValue(shader, resolutionLoc, &resolution, .vec2);
|
||||
|
||||
var circlePos: rl.Vector2 = .{ .x = 40.0, .y = @as(f32, @floatFromInt(screenHeight)) * 0.5 };
|
||||
var circleSpeed: f32 = 1.0;
|
||||
|
||||
// RenderTexture to apply the postprocessing later
|
||||
const target: rl.RenderTexture2D = try rl.loadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
circlePos.x += circleSpeed;
|
||||
if ((circlePos.x > 200.0) or (circlePos.x < 40.0)) circleSpeed *= -1; // Revert speed
|
||||
|
||||
if (rl.isKeyPressed(.left) and (fontSize > 9.0)) fontSize -= 1.0; // Reduce fontSize
|
||||
if (rl.isKeyPressed(.right) and (fontSize < 15.0)) fontSize += 1.0; // Increase fontSize
|
||||
|
||||
// Set fontsize for the shader
|
||||
rl.setShaderValue(shader, fontSizeLoc, &fontSize, .float);
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
{
|
||||
rl.beginTextureMode(target);
|
||||
defer rl.endTextureMode();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
// Draw scene in our render texture
|
||||
rl.drawTexture(fudesumi, 500, -30, .white);
|
||||
rl.drawTextureV(raysan, circlePos, .white);
|
||||
}
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
rl.clearBackground(.ray_white);
|
||||
{
|
||||
rl.beginShaderMode(shader);
|
||||
defer rl.endShaderMode();
|
||||
// Draw the scene texture (that we rendered earlier) to the screen
|
||||
// The shader will process every pixel of this texture
|
||||
rl.drawTextureRec(target.texture, .{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = @floatFromInt(target.texture.width),
|
||||
.height = -@as(f32, @floatFromInt(target.texture.height)),
|
||||
}, .zero(), .white);
|
||||
}
|
||||
|
||||
rl.drawRectangle(0, 0, screenWidth, 40, .black);
|
||||
rl.drawText(rl.textFormat("Ascii effect - FontSize:%2.0f - [Left] -1 [Right] +1 ", .{fontSize}), 120, 10, 20, .light_gray);
|
||||
rl.drawFPS(10, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
366
examples/shaders/shaders_basic_pbr.zig
Normal file
@ -0,0 +1,366 @@
|
||||
// raylib [shaders] example - Basic PBR
|
||||
//
|
||||
// Example complexity rating: [★★★★] 4/4
|
||||
//
|
||||
// Example originally created with raylib 5.0, last time updated with raylib 5.1-dev
|
||||
//
|
||||
// Example contributed by Afan OLOVCIC (@_DevDad) 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 Afan OLOVCIC (@_DevDad)
|
||||
//
|
||||
// Model: "Old Rusty Car" (https://skfb.ly/LxRy) by Renafox,
|
||||
// licensed under Creative Commons Attribution-NonCommercial
|
||||
// (http://creativecommons.org/licenses/by-nc/4.0/)
|
||||
|
||||
const rl = @import("raylib");
|
||||
|
||||
/// Casts ShaderLocationIndex to a u32
|
||||
fn uSli(sli: rl.ShaderLocationIndex) u32 {
|
||||
return @intCast(@intFromEnum(sli));
|
||||
}
|
||||
|
||||
/// Casts MaterialMapIndex to a u32
|
||||
fn uMmi(mmi: rl.MaterialMapIndex) u32 {
|
||||
return @intCast(@intFromEnum(mmi));
|
||||
}
|
||||
|
||||
/// Max dynamic lights supported by shader
|
||||
const max_lights = 4;
|
||||
/// Current number of dynamic lights that have been created
|
||||
var light_count: u32 = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Light data
|
||||
const Light = extern struct {
|
||||
type: Type = .directional,
|
||||
enabled: bool = false,
|
||||
_enabled_pad1: u8 = 0,
|
||||
_enabled_pad2: @Type(.{.int = .{
|
||||
.signedness = .unsigned,
|
||||
.bits = @bitSizeOf(c_uint) - 16,
|
||||
}}) = 0,
|
||||
position: rl.Vector3 = .init(0, 0, 0),
|
||||
target: rl.Vector3 = .init(0, 0, 0),
|
||||
color: [4]f32 = .{ 0, 0, 0, 0 },
|
||||
intensity: f32 = 0,
|
||||
|
||||
// Shader light parameters locations
|
||||
loc: extern struct {
|
||||
type: i32 = 0,
|
||||
enabled: i32 = 0,
|
||||
position: i32 = 0,
|
||||
target: i32 = 0,
|
||||
color: i32 = 0,
|
||||
intensity: i32 = 0,
|
||||
} = .{},
|
||||
|
||||
/// Light type
|
||||
const Type = enum(c_uint) {
|
||||
directional = 0,
|
||||
point,
|
||||
spot,
|
||||
};
|
||||
|
||||
/// Create light with provided data
|
||||
///
|
||||
/// NOTE: It updates `light_count` and is limited to `max_lights`
|
||||
fn init(
|
||||
t: Type,
|
||||
position: rl.Vector3,
|
||||
target: rl.Vector3,
|
||||
color: rl.Color,
|
||||
intensity: f32,
|
||||
shader: rl.Shader,
|
||||
) Light {
|
||||
if (light_count >= max_lights) {
|
||||
return .{};
|
||||
}
|
||||
const light: Light = .{
|
||||
.type = t,
|
||||
.enabled = true,
|
||||
.position = position,
|
||||
.target = target,
|
||||
.color = .{
|
||||
@as(f32, @floatFromInt(color.r)) / 255.0,
|
||||
@as(f32, @floatFromInt(color.g)) / 255.0,
|
||||
@as(f32, @floatFromInt(color.b)) / 255.0,
|
||||
@as(f32, @floatFromInt(color.a)) / 255.0,
|
||||
},
|
||||
.intensity = intensity,
|
||||
|
||||
// NOTE: Shader parameters names for lights must match the requested ones
|
||||
.loc = .{
|
||||
.type = rl.getShaderLocation(shader, rl.textFormat("lights[%i].type", .{ light_count })),
|
||||
.enabled = rl.getShaderLocation(shader, rl.textFormat("lights[%i].enabled", .{ light_count })),
|
||||
.position = rl.getShaderLocation(shader, rl.textFormat("lights[%i].position", .{ light_count })),
|
||||
.target = rl.getShaderLocation(shader, rl.textFormat("lights[%i].target", .{ light_count })),
|
||||
.color = rl.getShaderLocation(shader, rl.textFormat("lights[%i].color", .{ light_count })),
|
||||
.intensity = rl.getShaderLocation(shader, rl.textFormat("lights[%i].intensity", .{ light_count })),
|
||||
},
|
||||
};
|
||||
light.update(shader);
|
||||
light_count += 1;
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
/// Send light properties to shader
|
||||
///
|
||||
/// NOTE: Light shader locations should be available
|
||||
fn update(self: Light, shader: rl.Shader) void {
|
||||
rl.setShaderValue(shader, self.loc.type, &self.type, .int);
|
||||
rl.setShaderValue(shader, self.loc.enabled, &self.enabled, .int);
|
||||
|
||||
// Send to shader light position values
|
||||
const position: [3]f32 = .{ self.position.x, self.position.y, self.position.z };
|
||||
rl.setShaderValue(shader, self.loc.position, &position, .vec3);
|
||||
|
||||
// Send to shader light target position values
|
||||
const target: [3]f32 = .{ self.target.x, self.target.y, self.target.z };
|
||||
rl.setShaderValue(shader, self.loc.target, &target, .vec3);
|
||||
rl.setShaderValue(shader, self.loc.color, &self.color, .vec4);
|
||||
rl.setShaderValue(shader, self.loc.intensity, &self.intensity, .float);
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Main Entry Point
|
||||
//----------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.setConfigFlags(.{ .msaa_4x_hint = true });
|
||||
rl.initWindow(screen_width, screen_height, "raylib [shaders] example - basic pbr");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera: rl.Camera = .{
|
||||
.position = .init(2, 2, 6), // Camera position
|
||||
.target = .init(0, 0.5, 0), // Camera looking at point
|
||||
.up = .init(0, 1, 0), // Camera up vector (rotation towards target)
|
||||
.fovy = 45, // Camera field-of-view Y
|
||||
.projection = .perspective, // Camera projection type
|
||||
};
|
||||
|
||||
// Load PBR shader and setup all required locations
|
||||
const shader: rl.Shader = try rl.loadShader(
|
||||
"resources/shaders/glsl330/pbr.vs",
|
||||
"resources/shaders/glsl330/pbr.fs",
|
||||
);
|
||||
defer rl.unloadShader(shader);
|
||||
|
||||
shader.locs[uSli(.map_albedo)] = rl.getShaderLocation(shader, "albedoMap");
|
||||
// WARNING: Metalness, roughness, and ambient occlusion are all packed into a MRA texture
|
||||
// They are passed as to the SHADER_LOC_MAP_METALNESS location for convenience,
|
||||
// shader already takes care of it accordingly
|
||||
shader.locs[uSli(.map_metalness)] = rl.getShaderLocation(shader, "mraMap");
|
||||
shader.locs[uSli(.map_normal)] = rl.getShaderLocation(shader, "normalMap");
|
||||
// WARNING: Similar to the MRA map, the emissive map packs different information
|
||||
// into a single texture: it stores height and emission data
|
||||
// It is binded to SHADER_LOC_MAP_EMISSION location an properly processed on shader
|
||||
shader.locs[uSli(.map_emission)] = rl.getShaderLocation(shader, "emissiveMap");
|
||||
shader.locs[uSli(.color_diffuse)] = rl.getShaderLocation(shader, "albedoColor");
|
||||
|
||||
// Setup additional required shader locations, including lights data
|
||||
shader.locs[uSli(.vector_view)] = rl.getShaderLocation(shader, "viewPos");
|
||||
const loc_light_count: i32 = rl.getShaderLocation(shader, "numOfLights");
|
||||
const max_light_count: i32 = max_lights;
|
||||
rl.setShaderValue(shader, loc_light_count, &max_light_count, .int);
|
||||
|
||||
// Setup ambient color and intensity parameters
|
||||
const ambient_intensity: f32 = 0.02;
|
||||
const ambient_color: rl.Vector3 = blk: {
|
||||
const c: rl.Color = .init(26, 32, 135, 255);
|
||||
break :blk .init(
|
||||
@as(f32, @floatFromInt(c.r)) / 255.0,
|
||||
@as(f32, @floatFromInt(c.g)) / 255.0,
|
||||
@as(f32, @floatFromInt(c.b)) / 255.0,
|
||||
);
|
||||
};
|
||||
rl.setShaderValue(shader, rl.getShaderLocation(shader, "ambientColor"), &ambient_color, .vec3);
|
||||
rl.setShaderValue(shader, rl.getShaderLocation(shader, "ambient"), &ambient_intensity, .float);
|
||||
|
||||
// Get location for shader parameters that can be modified in real time
|
||||
const loc_metallic_value = rl.getShaderLocation(shader, "metallicValue");
|
||||
const loc_roughness_value = rl.getShaderLocation(shader, "roughnessValue");
|
||||
const loc_emissive_intensity = rl.getShaderLocation(shader, "emissivePower");
|
||||
const loc_emissive_color = rl.getShaderLocation(shader, "emissiveColor");
|
||||
const loc_texture_tiling = rl.getShaderLocation(shader, "tiling");
|
||||
|
||||
// Load old car model using PBR maps and shader
|
||||
// WARNING: We know this model consists of a single model.meshes[0] and
|
||||
// that model.materials[0] is by default assigned to that mesh
|
||||
// There could be more complex models consisting of multiple meshes and
|
||||
// multiple materials defined for those meshes... but always 1 mesh = 1 material
|
||||
const car: rl.Model = try .init("resources/models/old_car_new.glb");
|
||||
defer {
|
||||
car.materials[0].shader = .{ .id = 0, .locs = null };
|
||||
rl.unloadMaterial(car.materials[0]);
|
||||
car.materials[0].maps = null;
|
||||
car.unload();
|
||||
}
|
||||
|
||||
// Assign already setup PBR shader to model.materials[0], used by models.meshes[0]
|
||||
car.materials[0].shader = shader;
|
||||
|
||||
// Setup materials[0].maps default parameters
|
||||
car.materials[0].maps[uMmi(.albedo)].color = .white;
|
||||
car.materials[0].maps[uMmi(.metalness)].value = 1.0;
|
||||
car.materials[0].maps[uMmi(.roughness)].value = 0.0;
|
||||
car.materials[0].maps[uMmi(.occlusion)].value = 1.0;
|
||||
car.materials[0].maps[uMmi(.emission)].color = .init(255, 162, 0, 255);
|
||||
|
||||
// Setup materials[0].maps default textures
|
||||
car.materials[0].maps[uMmi(.albedo)].texture = try .init("resources/textures/old_car_d.png");
|
||||
car.materials[0].maps[uMmi(.metalness)].texture = try .init("resources/textures/old_car_mra.png");
|
||||
car.materials[0].maps[uMmi(.normal)].texture = try .init("resources/textures/old_car_n.png");
|
||||
car.materials[0].maps[uMmi(.emission)].texture = try .init("resources/textures/old_car_e.png");
|
||||
|
||||
// Load floor model mesh and assign material parameters
|
||||
// NOTE: A basic plane shape can be generated instead of being loaded from a model file
|
||||
const floor: rl.Model = try .init("resources/models/plane.glb");
|
||||
defer {
|
||||
floor.materials[0].shader = .{ .id = 0, .locs = null };
|
||||
rl.unloadMaterial(floor.materials[0]);
|
||||
floor.materials[0].maps = null;
|
||||
floor.unload();
|
||||
}
|
||||
//Mesh floorMesh = GenMeshPlane(10, 10, 10, 10);
|
||||
//GenMeshTangents(&floorMesh); // TODO: Review tangents generation
|
||||
//Model floor = LoadModelFromMesh(floorMesh);
|
||||
|
||||
// Assign material shader for our floor model, same PBR shader
|
||||
floor.materials[0].shader = shader;
|
||||
|
||||
floor.materials[0].maps[uMmi(.albedo)].color = .white;
|
||||
floor.materials[0].maps[uMmi(.metalness)].value = 0.8;
|
||||
floor.materials[0].maps[uMmi(.roughness)].value = 0.1;
|
||||
floor.materials[0].maps[uMmi(.occlusion)].value = 1.0;
|
||||
floor.materials[0].maps[uMmi(.emission)].color = .black;
|
||||
|
||||
floor.materials[0].maps[uMmi(.albedo)].texture = try .init("resources/textures/road_a.png");
|
||||
floor.materials[0].maps[uMmi(.metalness)].texture = try .init("resources/textures/road_mra.png");
|
||||
floor.materials[0].maps[uMmi(.normal)].texture = try .init("resources/textures/road_n.png");
|
||||
|
||||
// Models texture tiling parameter can be stored in the Material struct if required (CURRENTLY NOT USED)
|
||||
// NOTE: Material.params[4] are available for generic parameters storage (float)
|
||||
const car_texture_tiling: rl.Vector2 = .init(0.5, 0.5);
|
||||
const floor_texture_tiling: rl.Vector2 = .init(0.5, 0.5);
|
||||
|
||||
// Create some lights
|
||||
var lights: [max_lights]Light = .{
|
||||
.init(.point, .init(-1, 1, -2), .init(0, 0, 0), .yellow, 4, shader),
|
||||
.init(.point, .init(2, 1, 1), .init(0, 0, 0), .green, 3.3, shader),
|
||||
.init(.point, .init(-2, 1, 1), .init(0, 0, 0), .red, 8.3, shader),
|
||||
.init(.point, .init(1, 1, -2), .init(0, 0, 0), .blue, 2, shader),
|
||||
};
|
||||
|
||||
// Setup material texture maps usage in shader
|
||||
// NOTE: By default, the texture maps are always used
|
||||
const usage: i32 = 1;
|
||||
rl.setShaderValue(shader, rl.getShaderLocation(shader, "useTexAlbedo"), &usage, .int);
|
||||
rl.setShaderValue(shader, rl.getShaderLocation(shader, "useTexNormal"), &usage, .int);
|
||||
rl.setShaderValue(shader, rl.getShaderLocation(shader, "useTexMRA"), &usage, .int);
|
||||
rl.setShaderValue(shader, rl.getShaderLocation(shader, "useTexEmissive"), &usage, .int);
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.update(.orbital);
|
||||
|
||||
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
|
||||
const camera_pos: [3]f32 = .{ camera.position.x, camera.position.y, camera.position.z };
|
||||
rl.setShaderValue(shader, shader.locs[uSli(.vector_view)], &camera_pos, .vec3);
|
||||
|
||||
// Check key inputs to enable/disable lights
|
||||
if (rl.isKeyPressed(.one)) {
|
||||
lights[2].enabled = !lights[2].enabled;
|
||||
}
|
||||
if (rl.isKeyPressed(.two)) {
|
||||
lights[1].enabled = !lights[1].enabled;
|
||||
}
|
||||
if (rl.isKeyPressed(.three)) {
|
||||
lights[3].enabled = !lights[3].enabled;
|
||||
}
|
||||
if (rl.isKeyPressed(.four)) {
|
||||
lights[0].enabled = !lights[0].enabled;
|
||||
}
|
||||
|
||||
// Update light values on shader (actually, only enable/disable them)
|
||||
for (&lights) |*l| {
|
||||
l.update(shader);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.black);
|
||||
{
|
||||
rl.beginMode3D(camera);
|
||||
defer rl.endMode3D();
|
||||
|
||||
// Set floor model texture tiling and emissive color parameters on shader
|
||||
rl.setShaderValue(shader, loc_texture_tiling, &floor_texture_tiling, .vec2);
|
||||
const floor_emissive_color: rl.Vector4 = rl.colorNormalize(floor.materials[0].maps[uMmi(.emission)].color);
|
||||
rl.setShaderValue(shader, loc_emissive_color, &floor_emissive_color, .vec4);
|
||||
|
||||
// Set floor metallic and roughness values
|
||||
rl.setShaderValue(shader, loc_metallic_value, &floor.materials[0].maps[uMmi(.metalness)].value, .float);
|
||||
rl.setShaderValue(shader, loc_roughness_value, &floor.materials[0].maps[uMmi(.roughness)].value, .float);
|
||||
|
||||
floor.draw(.init(0, 0, 0), 5, .white); // Draw floor model
|
||||
|
||||
// Set old car model texture tiling, emissive color and emissive intensity parameters on shader
|
||||
rl.setShaderValue(shader, loc_texture_tiling, &car_texture_tiling, .vec2);
|
||||
const car_emissive_color: rl.Vector4 = rl.colorNormalize(car.materials[0].maps[uMmi(.emission)].color);
|
||||
rl.setShaderValue(shader, loc_emissive_color, &car_emissive_color, .vec4);
|
||||
const emissive_intensity: f32 = 0.01;
|
||||
rl.setShaderValue(shader, loc_emissive_intensity, &emissive_intensity, .float);
|
||||
|
||||
// Set old car metallic and roughness values
|
||||
rl.setShaderValue(shader, loc_metallic_value, &car.materials[0].maps[uMmi(.metalness)].value, .float);
|
||||
rl.setShaderValue(shader, loc_roughness_value, &car.materials[0].maps[uMmi(.roughness)].value, .float);
|
||||
|
||||
car.draw(.init(0, 0, 0), 0.25, .white); // Draw car model
|
||||
|
||||
// Draw spheres to show the lights positions
|
||||
for (&lights) |*l| {
|
||||
const light_color: rl.Color = .init(
|
||||
@intFromFloat(l.color[0] * 255),
|
||||
@intFromFloat(l.color[1] * 255),
|
||||
@intFromFloat(l.color[2] * 255),
|
||||
@intFromFloat(l.color[3] * 255),
|
||||
);
|
||||
|
||||
if (l.enabled) {
|
||||
rl.drawSphereEx(l.position, 0.2, 8, 8, light_color);
|
||||
} else {
|
||||
rl.drawSphereWires(l.position, 0.2, 8, 8, rl.colorAlpha(light_color, 0.3));
|
||||
}
|
||||
}
|
||||
}
|
||||
rl.drawText("Toggle lights: [1][2][3][4]", 10, 40, 20, .light_gray);
|
||||
|
||||
rl.drawText("(c) Old Rusty Car model by Renafox (https://skfb.ly/LxRy)",
|
||||
screen_width - 320, screen_height - 20, 10, .light_gray);
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
}
|
||||
}
|
||||
197
examples/shaders/shaders_hybrid_render.zig
Normal file
@ -0,0 +1,197 @@
|
||||
// raylib [shaders] example - Hybrid Rendering
|
||||
//
|
||||
// Example complexity rating: [★★★★] 4/4
|
||||
//
|
||||
// Example originally created with raylib 4.2, last time updated with raylib 4.2
|
||||
//
|
||||
// Example contributed by Buğra Alptekin Sarı (@BugraAlptekinSari) 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 Buğra Alptekin Sarı (@BugraAlptekinSari)
|
||||
|
||||
const rl = @import("raylib");
|
||||
const pi = @import("std").math.pi;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Declare custom Structs
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
const RayLocs = struct {
|
||||
cam_pos: i32,
|
||||
cam_dir: i32,
|
||||
screen_center: i32,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [shaders] example - write depth buffer");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
|
||||
// This Shader calculates pixel depth and color using raymarch
|
||||
const shdr_raymarch: rl.Shader = try rl.loadShader(null, "resources/shaders/glsl330/hybrid_raymarch.fs");
|
||||
defer rl.unloadShader(shdr_raymarch);
|
||||
|
||||
// This Shader is a standard rasterization fragment shader with the addition of depth writing
|
||||
// You are required to write depth for all shaders if one shader does it
|
||||
const shdr_raster: rl.Shader = try rl.loadShader(null, "resources/shaders/glsl330/hybrid_raster.fs");
|
||||
defer rl.unloadShader(shdr_raster);
|
||||
|
||||
// Declare Struct used to store camera locs.
|
||||
const march_locs: RayLocs = .{
|
||||
.cam_pos = rl.getShaderLocation(shdr_raymarch, "camPos"),
|
||||
.cam_dir = rl.getShaderLocation(shdr_raymarch, "camDir"),
|
||||
.screen_center = rl.getShaderLocation(shdr_raymarch, "screenCenter"),
|
||||
};
|
||||
|
||||
// Transfer screenCenter position to shader. Which is used to calculate ray direction.
|
||||
const screen_center: rl.Vector2 = .init(screen_width / 2.0, screen_height / 2.0);
|
||||
rl.setShaderValue(shdr_raymarch, march_locs.screen_center , &screen_center , .vec2);
|
||||
|
||||
// Use Customized function to create writable depth texture buffer
|
||||
const target: rl.RenderTexture2D = try loadRenderTextureDepthTex(screen_width, screen_height);
|
||||
defer unloadRenderTextureDepthTex(target);
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera: rl.Camera = .{
|
||||
.position = .init(0.5, 1, 1.5), // Camera position
|
||||
.target = .init(0, 0.5, 0), // Camera looking at point
|
||||
.up = .init(0, 1, 0), // Camera up vector (rotation towards target)
|
||||
.fovy = 45, // Camera field-of-view Y
|
||||
.projection = .perspective, // Camera projection type
|
||||
};
|
||||
|
||||
// Camera FOV is pre-calculated in the camera Distance.
|
||||
const cam_dist: f32 = 1.0 / @tan(camera.fovy * 0.5 * (pi / 180.0));
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.update(.orbital);
|
||||
|
||||
// Update Camera Postion in the ray march shader.
|
||||
rl.setShaderValue(shdr_raymarch, march_locs.cam_pos, &camera.position, .vec3);
|
||||
|
||||
// Update Camera Looking Vector. Vector length determines FOV.
|
||||
const cam_dir: rl.Vector3 = .scale(.normalize(.subtract(camera.target, camera.position)), cam_dist);
|
||||
rl.setShaderValue(shdr_raymarch, march_locs.cam_dir, &cam_dir, .vec3);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw into our custom render texture (framebuffer)
|
||||
{
|
||||
target.begin();
|
||||
defer target.end();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
// Raymarch Scene
|
||||
rl.gl.rlEnableDepthTest(); //Manually enable Depth Test to handle multiple rendering methods.
|
||||
{
|
||||
shdr_raymarch.activate();
|
||||
defer shdr_raymarch.deactivate();
|
||||
rl.drawRectangleRec(.init(0, 0, screen_width, screen_height), .white);
|
||||
}
|
||||
|
||||
// Rasterize Scene
|
||||
{
|
||||
rl.beginMode3D(camera);
|
||||
defer rl.endMode3D();
|
||||
|
||||
shdr_raster.activate();
|
||||
defer shdr_raster.deactivate();
|
||||
|
||||
rl.drawCubeWiresV(.init(0, 0.5, 1), .init(1, 1, 1), .red);
|
||||
rl.drawCubeV(.init(0, 0.5, 1), .init(1, 1, 1), .purple);
|
||||
rl.drawCubeWiresV(.init(0, 0.5, -1), .init(1, 1, 1), .dark_green);
|
||||
rl.drawCubeV(.init(0, 0.5, -1), .init(1, 1, 1), .yellow);
|
||||
rl.drawGrid(10, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw into screen our custom render texture
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
target.texture.drawRec(.init(0, 0, screen_width, -screen_height), .init(0, 0), .white);
|
||||
rl.drawFPS(10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Define custom functions required for the example
|
||||
//------------------------------------------------------------------------------------
|
||||
// Load custom render texture, create a writable depth texture buffer
|
||||
fn loadRenderTextureDepthTex(width: i32, height: i32) !rl.RenderTexture2D {
|
||||
const id = rl.gl.rlLoadFramebuffer(); // Load an empty framebuffer
|
||||
if (id <= 0) {
|
||||
return error.LoadFrameBufferFail;
|
||||
}
|
||||
|
||||
rl.gl.rlEnableFramebuffer(id);
|
||||
defer rl.gl.rlDisableFramebuffer();
|
||||
|
||||
const pix_format: i32 = @intFromEnum(rl.gl.rlPixelFormat.rl_pixelformat_uncompressed_r8g8b8a8);
|
||||
|
||||
const target: rl.RenderTexture2D = .{
|
||||
.id = id,
|
||||
// Create color texture (default to RGBA)
|
||||
.texture = .{
|
||||
.id = rl.gl.rlLoadTexture(null, width, height, pix_format, 1),
|
||||
.width = width,
|
||||
.height = height,
|
||||
.format = .uncompressed_r8g8b8a8,
|
||||
.mipmaps = 1,
|
||||
},
|
||||
// Create depth texture buffer (instead of raylib default renderbuffer)
|
||||
.depth = .{
|
||||
.id = rl.gl.rlLoadTextureDepth(width, height, false),
|
||||
.width = width,
|
||||
.height = height,
|
||||
.format = .compressed_etc2_rgb, //DEPTH_COMPONENT_24BIT?
|
||||
.mipmaps = 1,
|
||||
}
|
||||
};
|
||||
|
||||
// Attach color texture and depth texture to FBO
|
||||
const channel0: i32 = @intFromEnum(rl.gl.rlFramebufferAttachType.rl_attachment_color_channel0);
|
||||
const depth: i32 = @intFromEnum(rl.gl.rlFramebufferAttachType.rl_attachment_depth);
|
||||
const texture2d: i32 = @intFromEnum(rl.gl.rlFramebufferAttachTextureType.rl_attachment_texture2d);
|
||||
rl.gl.rlFramebufferAttach(target.id, target.texture.id, channel0, texture2d, 0);
|
||||
rl.gl.rlFramebufferAttach(target.id, target.depth.id, depth, texture2d, 0);
|
||||
|
||||
// Check if fbo is complete with attachments (valid)
|
||||
if (rl.gl.rlFramebufferComplete(target.id)) {
|
||||
rl.traceLog(.info, "FBO: [ID %i] Framebuffer object created successfully", .{ target.id });
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
// Unload render texture from GPU memory (VRAM)
|
||||
fn unloadRenderTextureDepthTex(target: rl.RenderTexture2D) void {
|
||||
// Color texture attached to FBO is deleted
|
||||
rl.gl.rlUnloadTexture(target.texture.id);
|
||||
rl.gl.rlUnloadTexture(target.depth.id);
|
||||
|
||||
// NOTE: Depth texture is automatically
|
||||
// queried and deleted before deleting framebuffer
|
||||
rl.gl.rlUnloadFramebuffer(target.id);
|
||||
}
|
||||
@ -15,10 +15,10 @@ pub fn main() anyerror!void {
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [shaders] example - Apply an outline to a texture");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const texture: rl.Texture = rl.Texture.init("resources/textures/fudesumi.png");
|
||||
const texture: rl.Texture = try .init("resources/textures/fudesumi.png");
|
||||
defer rl.unloadTexture(texture);
|
||||
|
||||
const shdrOutline: rl.Shader = rl.loadShader(null, "resources/shaders/glsl330/outline.fs");
|
||||
const shdrOutline: rl.Shader = try rl.loadShader(null, "resources/shaders/glsl330/outline.fs");
|
||||
defer rl.unloadShader(shdrOutline);
|
||||
|
||||
var outlineSize: f32 = 2.0;
|
||||
@ -38,19 +38,19 @@ pub fn main() anyerror!void {
|
||||
shdrOutline,
|
||||
outlineSizeLoc,
|
||||
&outlineSize,
|
||||
rl.ShaderUniformDataType.shader_uniform_float,
|
||||
.float,
|
||||
);
|
||||
rl.setShaderValue(
|
||||
shdrOutline,
|
||||
outlineColorLoc,
|
||||
&outlineColor,
|
||||
rl.ShaderUniformDataType.shader_uniform_vec4,
|
||||
.vec4,
|
||||
);
|
||||
rl.setShaderValue(
|
||||
shdrOutline,
|
||||
textureSizeLoc,
|
||||
&textureSize,
|
||||
rl.ShaderUniformDataType.shader_uniform_vec2,
|
||||
.vec2,
|
||||
);
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
@ -67,7 +67,7 @@ pub fn main() anyerror!void {
|
||||
shdrOutline,
|
||||
outlineSizeLoc,
|
||||
&outlineSize,
|
||||
rl.ShaderUniformDataType.shader_uniform_float,
|
||||
.float,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
@ -76,7 +76,7 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
{
|
||||
rl.beginShaderMode(shdrOutline);
|
||||
@ -85,18 +85,18 @@ pub fn main() anyerror!void {
|
||||
texture.draw(
|
||||
@divFloor(rl.getScreenWidth(), 2) - @divFloor(texture.width, 2),
|
||||
-30,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
}
|
||||
|
||||
rl.drawText("Shader-based\ntexture\noutline", 10, 10, 20, rl.Color.gray);
|
||||
rl.drawText("Shader-based\ntexture\noutline", 10, 10, 20, .gray);
|
||||
|
||||
rl.drawText(
|
||||
rl.textFormat("Outline size: %i px", .{@as(i32, @intFromFloat(outlineSize))}),
|
||||
10,
|
||||
120,
|
||||
20,
|
||||
rl.Color.maroon,
|
||||
.maroon,
|
||||
);
|
||||
|
||||
rl.drawFPS(710, 10);
|
||||
|
||||
58
examples/shapes/basic_shapes.zig
Normal file
@ -0,0 +1,58 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - basic shapes drawing");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var rotation: f32 = 0.0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rotation += 0.2;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("some basic shapes available on raylib", 20, 20, 20, .dark_gray);
|
||||
|
||||
// Circle shapes and lines
|
||||
rl.drawCircle(screenWidth / 5, 120, 35, .dark_blue);
|
||||
rl.drawCircleGradient(screenWidth / 5, 220, 60, .green, .sky_blue);
|
||||
rl.drawCircleLines(screenWidth / 5, 340, 80, .dark_blue);
|
||||
|
||||
// Rectangle shapes and lines
|
||||
rl.drawRectangle(screenWidth / 4 * 2 - 60, 100, 120, 60, .red);
|
||||
rl.drawRectangleGradientH(screenWidth / 4 * 2 - 90, 170, 180, 130, .maroon, .gold);
|
||||
rl.drawRectangleLines(screenWidth / 4 * 2 - 40, 320, 80, 60, .orange); // NOTE: Uses QUADS internally, not lines
|
||||
|
||||
// Triangle shapes and lines
|
||||
rl.drawTriangle(.{ .x = (screenWidth / 4.0 * 3.0), .y = 80.0 }, .{ .x = (screenWidth / 4.0 * 3.0 - 60.0), .y = 150.0 }, .{ .x = (screenWidth / 4.0 * 3.0 + 60.0), .y = 150.0 }, .violet);
|
||||
|
||||
rl.drawTriangleLines(.{ .x = (screenWidth / 4.0 * 3.0), .y = 160.0 }, .{ .x = (screenWidth / 4.0 * 3.0 - 20.0), .y = 230.0 }, .{ .x = (screenWidth / 4.0 * 3.0 + 20.0), .y = 230.0 }, .dark_blue);
|
||||
|
||||
// Polygon shapes and lines
|
||||
rl.drawPoly(.{ .x = (screenWidth / 4.0 * 3), .y = 330 }, 6, 80, rotation, .brown);
|
||||
rl.drawPolyLines(.{ .x = (screenWidth / 4.0 * 3), .y = 330 }, 6, 90, rotation, .brown);
|
||||
rl.drawPolyLinesEx(.{ .x = (screenWidth / 4.0 * 3), .y = 330 }, 6, 85, rotation, 6, .beige);
|
||||
|
||||
// NOTE: We draw all LINES based shapes together to optimize internal drawing,
|
||||
// this way, all LINES are rendered in a single draw pass
|
||||
rl.drawLine(18, 42, screenWidth - 18, 42, .black);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
69
examples/shapes/bouncing_ball.zig
Normal file
@ -0,0 +1,69 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - bouncing ball");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var ballPosition: rl.Vector2 = rl.Vector2{
|
||||
.x = @floatFromInt(@divExact(rl.getScreenWidth(), 2)),
|
||||
.y = @floatFromInt(@divExact(rl.getScreenHeight(), 2)),
|
||||
};
|
||||
var ballSpeed: rl.Vector2 = rl.Vector2{ .x = 5.0, .y = 4.0 };
|
||||
const ballRadius: i32 = 20;
|
||||
|
||||
var pause: bool = false;
|
||||
var framesCounter: i32 = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyPressed(.space)) {
|
||||
pause = !pause;
|
||||
}
|
||||
|
||||
if (!pause) {
|
||||
ballPosition.x += ballSpeed.x;
|
||||
ballPosition.y += ballSpeed.y;
|
||||
|
||||
const ballWidthEdge: f32 = @floatFromInt(rl.getScreenWidth() - ballRadius);
|
||||
if ((ballPosition.x >= ballWidthEdge) or (ballPosition.x <= ballRadius)) {
|
||||
ballSpeed.x = ballSpeed.x * -1.0;
|
||||
}
|
||||
|
||||
const ballHeightEdge: f32 = @floatFromInt(rl.getScreenHeight() - ballRadius);
|
||||
if ((ballPosition.y >= ballHeightEdge) or (ballPosition.y <= ballRadius)) {
|
||||
ballSpeed.y = ballSpeed.y * -1.0;
|
||||
}
|
||||
} else {
|
||||
framesCounter += 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawCircleV(ballPosition, ballRadius, .maroon);
|
||||
rl.drawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, rl.getScreenHeight() - 25, 20, .light_gray);
|
||||
|
||||
// On pause, we draw a blinking message
|
||||
if (pause and @mod(@divFloor(framesCounter, 30), 2) == 0) {
|
||||
rl.drawText("PAUSED", 350, 200, 30, .gray);
|
||||
}
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
114
examples/shapes/collision_area.zig
Normal file
@ -0,0 +1,114 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
fn boxFmt(colliding: bool) rl.Color {
|
||||
if (colliding) return .red;
|
||||
return .black;
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - collision area");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Box A: Movingbox
|
||||
var boxA = rl.Rectangle{ .x = 10, .y = (@as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0) - 50, .width = 200, .height = 100 };
|
||||
var boxASpeedX: f32 = 4;
|
||||
|
||||
// Box B: Mouse moved box
|
||||
var boxB = rl.Rectangle{ .x = (@as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0) - 30, .y = (@as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0) - 30, .width = 60, .height = 60 };
|
||||
|
||||
var boxCollision = rl.Rectangle{ .x = 0, .y = 0, .width = 0, .height = 0 };
|
||||
|
||||
const screenUpperLimit = 40;
|
||||
|
||||
var pause = false;
|
||||
var collision = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Move box if not paused
|
||||
if (!pause) {
|
||||
boxA.x += boxASpeedX;
|
||||
}
|
||||
|
||||
// Bounce box on x screen limits
|
||||
if ((boxA.x + boxA.width) >= @as(f32, @floatFromInt(rl.getScreenWidth())) or (boxA.x <= 0)) {
|
||||
boxASpeedX *= -1;
|
||||
}
|
||||
|
||||
// Update player-controlled-box (box02)
|
||||
boxB.x = @as(f32, @floatFromInt(rl.getMouseX())) - boxB.width / 2;
|
||||
boxB.y = @as(f32, @floatFromInt(rl.getMouseY())) - boxB.height / 2;
|
||||
|
||||
// Make sure Box B does not go out of move area limits
|
||||
if ((boxB.x + boxB.width) >= @as(f32, @floatFromInt(rl.getScreenWidth()))) {
|
||||
boxB.x = @as(f32, @floatFromInt(rl.getScreenWidth())) - boxB.width;
|
||||
} else if (boxB.x <= 0) {
|
||||
boxB.x = 0;
|
||||
}
|
||||
|
||||
if ((boxB.y + boxB.height) >= @as(f32, @floatFromInt(rl.getScreenHeight()))) {
|
||||
boxB.y = @as(f32, @floatFromInt(rl.getScreenHeight())) - boxB.height;
|
||||
} else if (boxB.y <= screenUpperLimit) {
|
||||
boxB.y = screenUpperLimit;
|
||||
}
|
||||
|
||||
// Check boxes collision
|
||||
collision = rl.checkCollisionRecs(boxA, boxB);
|
||||
|
||||
// Get collision rectangle (only on collision)
|
||||
if (collision) {
|
||||
boxCollision = rl.getCollisionRec(boxA, boxB);
|
||||
}
|
||||
|
||||
// Pause Box A movement
|
||||
if (rl.isKeyPressed(.space)) {
|
||||
pause = !pause;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.drawRectangle(0, 0, screenWidth, screenUpperLimit, boxFmt(collision));
|
||||
|
||||
rl.drawRectangleRec(boxA, .gold);
|
||||
rl.drawRectangleRec(boxB, .blue);
|
||||
|
||||
if (collision) {
|
||||
// Draw collision area
|
||||
rl.drawRectangleRec(boxCollision, .lime);
|
||||
|
||||
// Draw collision message
|
||||
rl.drawText(
|
||||
"COLLISION!",
|
||||
@divFloor(rl.getScreenWidth(), @as(i32, 2)) - @divFloor(rl.measureText("COLLISION!", 20), @as(i32, 2)),
|
||||
screenUpperLimit / 2 - 10,
|
||||
20,
|
||||
.black,
|
||||
);
|
||||
|
||||
// Draw collision area
|
||||
rl.drawText(rl.textFormat("Collision Area: %i", .{@as(i32, @intFromFloat(boxCollision.width * boxCollision.height))}), @divFloor(rl.getScreenWidth(), 2) - 100, screenUpperLimit + 10, 20, .black);
|
||||
}
|
||||
|
||||
// Draw help instructions
|
||||
rl.drawText("Press SPACE to PAUSE/RESUME", 20, screenHeight - 35, 20, .light_gray);
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
126
examples/shapes/colors_palette.zig
Normal file
@ -0,0 +1,126 @@
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
|
||||
const maxColorCount = 21; // Number of colors available
|
||||
|
||||
pub fn getAlpha(state: bool) f32 {
|
||||
if (state) {
|
||||
return 0.6;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - colors palette");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const colors = [maxColorCount]rl.Color{
|
||||
.dark_gray,
|
||||
.maroon,
|
||||
.orange,
|
||||
.dark_green,
|
||||
.dark_blue,
|
||||
.dark_purple,
|
||||
.dark_brown,
|
||||
.gray,
|
||||
.red,
|
||||
.gold,
|
||||
.lime,
|
||||
.blue,
|
||||
.violet,
|
||||
.brown,
|
||||
.light_gray,
|
||||
.pink,
|
||||
.yellow,
|
||||
.green,
|
||||
.sky_blue,
|
||||
.purple,
|
||||
.beige,
|
||||
};
|
||||
|
||||
const colorNames = [maxColorCount][:0]const u8{
|
||||
"DARKGRAY",
|
||||
"MAROON",
|
||||
"ORANGE",
|
||||
"DARKGREEN",
|
||||
"DARKBLUE",
|
||||
"DARKPURPLE",
|
||||
"DARKBROWN",
|
||||
"GRAY",
|
||||
"RED",
|
||||
"GOLD",
|
||||
"LIME",
|
||||
"BLUE",
|
||||
"VIOLET",
|
||||
"BROWN",
|
||||
"LIGHTGRAY",
|
||||
"PINK",
|
||||
"YELLOW",
|
||||
"GREEN",
|
||||
"SKYBLUE",
|
||||
"PURPLE",
|
||||
"BEIGE",
|
||||
};
|
||||
|
||||
var colorsRecs = std.mem.zeroes([maxColorCount]rl.Rectangle);
|
||||
|
||||
var i: u8 = 0;
|
||||
while (i < maxColorCount) : (i += 1) {
|
||||
colorsRecs[i].x = 20.0 + 100.0 * @as(f32, @floatFromInt(i % 7)) + 10.0 * @as(f32, @floatFromInt(i % 7));
|
||||
colorsRecs[i].y = 80.0 + 100.0 * @as(f32, @floatFromInt(i / 7)) + 10.0 * @as(f32, @floatFromInt(i / 7));
|
||||
colorsRecs[i].width = 100.0;
|
||||
colorsRecs[i].height = 100.0;
|
||||
}
|
||||
|
||||
var colorState: [maxColorCount]bool = std.mem.zeroes([maxColorCount]bool);
|
||||
|
||||
var mousePoint = rl.Vector2{ .x = 0.0, .y = 0.0 };
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
mousePoint = rl.getMousePosition();
|
||||
|
||||
i = 0;
|
||||
while (i < maxColorCount) : (i += 1) {
|
||||
if (rl.checkCollisionPointRec(mousePoint, colorsRecs[i])) {
|
||||
colorState[i] = true;
|
||||
} else {
|
||||
colorState[i] = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("raylib colors palette", 28, 42, 20, .black);
|
||||
rl.drawText("press SPACE to see all colors", rl.getScreenWidth() - 180, rl.getScreenHeight() - 40, 10, .gray);
|
||||
|
||||
i = 0;
|
||||
while (i < maxColorCount) : (i += 1) {
|
||||
rl.drawRectangleRec(colorsRecs[i], .fade(colors[i], getAlpha(colorState[i])));
|
||||
|
||||
if (rl.isKeyDown(.space) or colorState[i]) {
|
||||
rl.drawRectangle(@intFromFloat(colorsRecs[i].x), @as(i32, @intFromFloat(colorsRecs[i].y)) + @as(i32, @intFromFloat(colorsRecs[i].height)) - 26, @as(i32, @intFromFloat(colorsRecs[i].width)), 20, .black);
|
||||
rl.drawRectangleLinesEx(colorsRecs[i], 6, .fade(.black, 0.3));
|
||||
|
||||
rl.drawText(colorNames[i], @as(i32, @intFromFloat(colorsRecs[i].x)) + @as(i32, @intFromFloat(colorsRecs[i].width)) - rl.measureText(colorNames[i], 10) - 12, @as(i32, @intFromFloat(colorsRecs[i].y)) + @as(i32, @intFromFloat(colorsRecs[i].height)) - 20, 10, colors[i]);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
69
examples/shapes/draw_circle_sector.zig
Normal file
@ -0,0 +1,69 @@
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const rl = @import("raylib");
|
||||
const rgui = @import("raygui");
|
||||
|
||||
fn labelFmt(segments: f32, minSegments: f32) [*c]const u8 {
|
||||
if (segments >= minSegments) return "MANUAL";
|
||||
return "AUTO";
|
||||
}
|
||||
|
||||
fn colorFmt(segments: f32, minSegments: f32) rl.Color {
|
||||
if (segments >= minSegments) return .maroon;
|
||||
return .dark_gray;
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - draw circle sector");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const center = rl.Vector2{ .x = @as(f32, @floatFromInt(rl.getScreenWidth() - 300)) / 2.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 };
|
||||
|
||||
var outerRadius: f32 = 180.0;
|
||||
var startAngle: f32 = 0.0;
|
||||
var endAngle: f32 = 180.0;
|
||||
var segments: f32 = 10.0;
|
||||
var minSegments: f32 = 4;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// NOTE: All variables update happens inside GUI control functions
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawLine(500, 0, 500, rl.getScreenHeight(), .fade(.light_gray, 0.6));
|
||||
rl.drawRectangle(500, 0, rl.getScreenWidth() - 500, rl.getScreenHeight(), .fade(.light_gray, 0.3));
|
||||
|
||||
rl.drawCircleSector(center, outerRadius, startAngle, endAngle, @as(i32, @intFromFloat(segments)), .fade(.maroon, 0.3));
|
||||
rl.drawCircleSectorLines(center, outerRadius, startAngle, endAngle, @as(i32, @intFromFloat(segments)), .fade(.maroon, 0.6));
|
||||
|
||||
// Draw GUI controls
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 40, .width = 120, .height = 20 }, "StartAngle", rl.textFormat("%.2", .{startAngle}), &startAngle, 0, 720);
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 70, .width = 120, .height = 20 }, "EndAngle", rl.textFormat("%.2", .{endAngle}), &endAngle, 0, 720);
|
||||
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 140, .width = 120, .height = 20 }, "Radius", rl.textFormat("%.2", .{outerRadius}), &outerRadius, 0, 200);
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 170, .width = 120, .height = 20 }, "Segments", rl.textFormat("%.2", .{segments}), &segments, 0, 100);
|
||||
|
||||
minSegments = math.trunc(math.ceil((endAngle - startAngle) / 90));
|
||||
rl.drawText(rl.textFormat("MODE: %s", .{labelFmt(segments, minSegments)}), 600, 200, 10, colorFmt(segments, minSegments));
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
73
examples/shapes/draw_rectangle_rounded.zig
Normal file
@ -0,0 +1,73 @@
|
||||
const rl = @import("raylib");
|
||||
const rgui = @import("raygui");
|
||||
|
||||
fn labelFmt(segments: f32) [*c]const u8 {
|
||||
if (segments >= 4) return "MANUAL";
|
||||
return "AUTO";
|
||||
}
|
||||
|
||||
fn colorFmt(segments: f32) rl.Color {
|
||||
if (segments >= 4) return .maroon;
|
||||
return .dark_gray;
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - draw rectangle rounded");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var roundness: f32 = 0.2;
|
||||
var width: f32 = 200.0;
|
||||
var height: f32 = 100.0;
|
||||
var segments: f32 = 0.0;
|
||||
var lineThick: f32 = 1.0;
|
||||
|
||||
var drawRect: bool = false;
|
||||
var drawRoundedRect: bool = true;
|
||||
var drawRoundedLines: bool = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
const rec = rl.Rectangle{ .x = (@as(f32, @floatFromInt(rl.getScreenWidth())) - width - 250) / 2.0, .y = (@as(f32, @floatFromInt(rl.getScreenHeight())) - height) / 2.0, .width = width, .height = height };
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawLine(560, 0, 560, rl.getScreenHeight(), .fade(.light_gray, 0.6));
|
||||
rl.drawRectangle(560, 0, rl.getScreenWidth() - 500, rl.getScreenHeight(), .fade(.light_gray, 0.3));
|
||||
|
||||
if (drawRect) rl.drawRectangleRec(rec, .fade(.gold, 0.6));
|
||||
if (drawRoundedRect) rl.drawRectangleRounded(rec, roundness, @as(i32, @intFromFloat(segments)), .fade(.maroon, 0.2));
|
||||
if (drawRoundedLines) rl.drawRectangleRoundedLinesEx(rec, roundness, @as(i32, @intFromFloat(segments)), lineThick, .fade(.maroon, 0.4));
|
||||
|
||||
// Draw GUI controls
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 640, .y = 40, .width = 105, .height = 20 }, "Width", rl.textFormat("%.2", .{width}), &width, 0, @as(f32, @floatFromInt(rl.getScreenWidth() - 300)));
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 640, .y = 70, .width = 105, .height = 20 }, "Height", rl.textFormat("%.2", .{height}), &height, 0, @as(f32, @floatFromInt(rl.getScreenHeight() - 50)));
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 640, .y = 140, .width = 105, .height = 20 }, "Roundness", rl.textFormat("%.2", .{roundness}), &roundness, 0.0, 1.0);
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 640, .y = 170, .width = 105, .height = 20 }, "Thickness", rl.textFormat("%.2", .{lineThick}), &lineThick, 0, 20);
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 640, .y = 240, .width = 105, .height = 20 }, "Segments", rl.textFormat("%.2", .{segments}), &segments, 0, 60);
|
||||
|
||||
_ = rgui.checkBox(rl.Rectangle{ .x = 640, .y = 320, .width = 20, .height = 20 }, "DrawRoundedRect", &drawRoundedRect);
|
||||
_ = rgui.checkBox(rl.Rectangle{ .x = 640, .y = 350, .width = 20, .height = 20 }, "DrawRoundedLines", &drawRoundedLines);
|
||||
_ = rgui.checkBox(rl.Rectangle{ .x = 640, .y = 380, .width = 20, .height = 20 }, "DrawRect", &drawRect);
|
||||
|
||||
rl.drawText(rl.textFormat("MODE: %s", .{labelFmt(segments)}), 640, 280, 10, colorFmt(segments));
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
83
examples/shapes/draw_ring.zig
Normal file
@ -0,0 +1,83 @@
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const rl = @import("raylib");
|
||||
const rgui = @import("raygui");
|
||||
|
||||
fn labelFmt(segments: f32, minSegments: f32) [*c]const u8 {
|
||||
if (segments >= minSegments) return "MANUAL";
|
||||
return "AUTO";
|
||||
}
|
||||
|
||||
fn colorFmt(segments: f32, minSegments: f32) rl.Color {
|
||||
if (segments >= minSegments) return .maroon;
|
||||
return .dark_gray;
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - draw ring");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const center = rl.Vector2{ .x = @as(f32, @floatFromInt(rl.getScreenWidth() - 300)) / 2.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 };
|
||||
|
||||
var innerRadius: f32 = 80.0;
|
||||
var outerRadius: f32 = 190.0;
|
||||
|
||||
var startAngle: f32 = 0.0;
|
||||
var endAngle: f32 = 360.0;
|
||||
var segments: f32 = 0.0;
|
||||
|
||||
var drawRing = true;
|
||||
var drawRingLines = false;
|
||||
var drawCircleLines = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// NOTE: All variables update happens inside GUI control functions
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawLine(500, 0, 500, rl.getScreenHeight(), .fade(.light_gray, 0.6));
|
||||
rl.drawRectangle(500, 0, rl.getScreenWidth() - 500, rl.getScreenHeight(), .fade(.light_gray, 0.3));
|
||||
|
||||
if (drawRing) rl.drawRing(center, innerRadius, outerRadius, startAngle, endAngle, @intFromFloat(segments), .fade(.maroon, 0.3));
|
||||
if (drawRingLines) rl.drawRingLines(center, innerRadius, outerRadius, startAngle, endAngle, @intFromFloat(segments), .fade(.black, 0.4));
|
||||
if (drawCircleLines) rl.drawCircleSectorLines(center, outerRadius, startAngle, endAngle, @intFromFloat(segments), .fade(.black, 0.4));
|
||||
|
||||
// Draw GUI controls
|
||||
//------------------------------------------------------------------------------
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 40, .width = 120, .height = 20 }, "StartAngle", rl.textFormat("%.2", .{startAngle}), &startAngle, -450, 450);
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 70, .width = 120, .height = 20 }, "EndAngle", rl.textFormat("%.2", .{endAngle}), &endAngle, -450, 450);
|
||||
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 140, .width = 120, .height = 20 }, "InnerRadius", rl.textFormat("%.2", .{innerRadius}), &innerRadius, 0, 100);
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 170, .width = 120, .height = 20 }, "OuterRadius", rl.textFormat("%.2", .{outerRadius}), &outerRadius, 0, 200);
|
||||
|
||||
_ = rgui.sliderBar(rl.Rectangle{ .x = 600, .y = 240, .width = 120, .height = 20 }, "Segments", rl.textFormat("%.2", .{segments}), &segments, 0, 100);
|
||||
|
||||
_ = rgui.checkBox(rl.Rectangle{ .x = 600, .y = 320, .width = 20, .height = 20 }, "Draw Ring", &drawRing);
|
||||
_ = rgui.checkBox(rl.Rectangle{ .x = 600, .y = 350, .width = 20, .height = 20 }, "Draw RingLines", &drawRingLines);
|
||||
_ = rgui.checkBox(rl.Rectangle{ .x = 600, .y = 380, .width = 20, .height = 20 }, "Draw CircleLines", &drawCircleLines);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const minSegments: f32 = math.ceil((endAngle - startAngle) / 90);
|
||||
rl.drawText(rl.textFormat("MODE: %s", .{labelFmt(segments, minSegments)}), 600, 270, 10, colorFmt(segments, minSegments));
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
86
examples/shapes/easings_ball_anim.zig
Normal file
@ -0,0 +1,86 @@
|
||||
const rl = @import("raylib");
|
||||
const reasings = @import("reasings.zig");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [shapes] example - easings ball anim");
|
||||
defer rl.closeWindow(); // Defer closing window and OpenGL context
|
||||
|
||||
// Ball variable value to be animated with easings
|
||||
var ballPositionX: i32 = -100;
|
||||
var ballRadius: f32 = 20;
|
||||
var ballAlpha: f32 = 0;
|
||||
|
||||
var state: i32 = 0;
|
||||
var framesCounter: i32 = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (state) {
|
||||
0 => { // Move ball position X with easing
|
||||
framesCounter += 1;
|
||||
ballPositionX = @intFromFloat(reasings.elasticOut(@floatFromInt(framesCounter), -100, @as(f32, @floatFromInt(screenWidth)) / 2 + 100, 120));
|
||||
|
||||
if (framesCounter >= 120) {
|
||||
framesCounter = 0;
|
||||
state = 1;
|
||||
}
|
||||
},
|
||||
1 => { // Increase ball radius with easing
|
||||
framesCounter += 1;
|
||||
ballRadius = reasings.elasticIn(@floatFromInt(framesCounter), 20, 500, 200);
|
||||
|
||||
if (framesCounter >= 200) {
|
||||
framesCounter = 0;
|
||||
state = 2;
|
||||
}
|
||||
},
|
||||
2 => { // Change ball alpha with easing (background color blending)
|
||||
framesCounter += 1;
|
||||
ballAlpha = reasings.cubicOut(@floatFromInt(framesCounter), 0.0, 1.0, 200);
|
||||
if (framesCounter >= 200) {
|
||||
framesCounter = 0;
|
||||
state = 3;
|
||||
}
|
||||
},
|
||||
3 => { // Reset state to play again
|
||||
if (rl.isKeyPressed(.enter)) {
|
||||
ballPositionX = -100;
|
||||
ballRadius = 20;
|
||||
ballAlpha = 0.0;
|
||||
state = 0;
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.r)) framesCounter = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
if (state >= 2) rl.drawRectangle(0, 0, screenWidth, screenHeight, .green);
|
||||
rl.drawCircle(ballPositionX, 200, ballRadius, .fade(.red, 1.0 - ballAlpha));
|
||||
|
||||
if (state == 3) rl.drawText("PRESS [ENTER] TO PLAY AGAIN!", 240, 200, 20, .black);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
127
examples/shapes/easings_box_anim.zig
Normal file
@ -0,0 +1,127 @@
|
||||
const rl = @import("raylib");
|
||||
const reasing = @import("reasings.zig");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [shapes] example - easings box anim");
|
||||
defer rl.closeWindow();
|
||||
|
||||
// Box variables to be animated with easings
|
||||
var rec: rl.Rectangle = rl.Rectangle{
|
||||
.x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0,
|
||||
.y = -100,
|
||||
.height = 100,
|
||||
.width = 100,
|
||||
};
|
||||
var rotation: f32 = 0.0;
|
||||
var alpha: f32 = 1.0;
|
||||
|
||||
var state: i32 = 0;
|
||||
var framesCounter: i32 = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (state) {
|
||||
// Move box down to center of screen
|
||||
0 => {
|
||||
framesCounter += 1;
|
||||
|
||||
// NOTE: Remember that 3rd parameter of easing function refers to
|
||||
// desired value variation, do not confuse it with expected final value!
|
||||
rec.y = reasing.elasticOut(@floatFromInt(framesCounter), -100, @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 + 100, 120);
|
||||
|
||||
if (framesCounter >= 120) {
|
||||
framesCounter = 0;
|
||||
state = 1;
|
||||
}
|
||||
},
|
||||
// Scale box to an horizontal bar
|
||||
1 => {
|
||||
framesCounter += 1;
|
||||
rec.height = reasing.bounceOut(@floatFromInt(framesCounter), 100, -90, 120);
|
||||
rec.width = reasing.bounceOut(@floatFromInt(framesCounter), 100, @floatFromInt(rl.getScreenWidth()), 120);
|
||||
|
||||
if (framesCounter >= 120) {
|
||||
framesCounter = 0;
|
||||
state = 2;
|
||||
}
|
||||
},
|
||||
// Rotate horizontal bar rectangle
|
||||
2 => {
|
||||
framesCounter += 1;
|
||||
rotation = reasing.quadOut(@floatFromInt(framesCounter), 0.0, 270.0, 240);
|
||||
|
||||
if (framesCounter >= 240) {
|
||||
framesCounter = 0;
|
||||
state = 3;
|
||||
}
|
||||
},
|
||||
// Increase bar size to fill all screen
|
||||
3 => {
|
||||
framesCounter += 1;
|
||||
rec.height = reasing.circOut(@floatFromInt(framesCounter), 10, @floatFromInt(rl.getScreenWidth()), 120);
|
||||
|
||||
if (framesCounter >= 120) {
|
||||
framesCounter = 0;
|
||||
state = 4;
|
||||
}
|
||||
},
|
||||
// Fade out animation
|
||||
4 => {
|
||||
framesCounter += 1;
|
||||
alpha = reasing.sineOut(@floatFromInt(framesCounter), 1.0, -1.0, 160);
|
||||
|
||||
if (framesCounter >= 160) {
|
||||
framesCounter = 0;
|
||||
state = 5;
|
||||
}
|
||||
},
|
||||
5 => {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
// Reset animation at any moment
|
||||
if (rl.isKeyPressed(.space)) {
|
||||
rec = rl.Rectangle{
|
||||
.x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0,
|
||||
.y = -100,
|
||||
.height = 100,
|
||||
.width = 100,
|
||||
};
|
||||
rotation = 0.0;
|
||||
alpha = 1.0;
|
||||
state = 0;
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawRectanglePro(rec, rl.Vector2{
|
||||
.x = rec.width / 2,
|
||||
.y = rec.height / 2,
|
||||
}, rotation, .fade(.black, alpha));
|
||||
|
||||
rl.drawText("PRESS [SPACE] TO RESET BOX ANIMATION!", 10, rl.getScreenHeight() - 25, 20, .light_gray);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
91
examples/shapes/easings_rectangle_array.zig
Normal file
@ -0,0 +1,91 @@
|
||||
const rl = @import("raylib");
|
||||
const reasings = @import("reasings.zig");
|
||||
|
||||
const RECS_WIDTH = 50;
|
||||
const RECS_HEIGHT = 50;
|
||||
const SCREEN_WIDTH = 800;
|
||||
const SCREEN_HEIGHT = 450;
|
||||
|
||||
const MAX_RECS_X = SCREEN_WIDTH / RECS_WIDTH;
|
||||
const MAX_RECS_Y = SCREEN_HEIGHT / RECS_HEIGHT;
|
||||
|
||||
const PLAY_TIME_IN_FRAMES = 240; // At 60 fps = 4 seconds
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
rl.initWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib [shapes] example - easings rectangle array");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var recs: [MAX_RECS_X * MAX_RECS_Y]rl.Rectangle = undefined;
|
||||
|
||||
for (0..MAX_RECS_Y) |y| {
|
||||
for (0..MAX_RECS_X) |x| {
|
||||
recs[y * MAX_RECS_X + x].x = RECS_WIDTH / 2.0 + RECS_WIDTH * @as(f32, @floatFromInt(x));
|
||||
recs[y * MAX_RECS_X + x].y = RECS_HEIGHT / 2.0 + RECS_HEIGHT * @as(f32, @floatFromInt(y));
|
||||
recs[y * MAX_RECS_X + x].width = RECS_WIDTH;
|
||||
recs[y * MAX_RECS_X + x].height = RECS_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
var rotation: f32 = 0.0;
|
||||
var framesCounter: i32 = 0;
|
||||
var state: i32 = 0; // Rectangles animation state: 0-Playing, 1-Finished
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (state == 0) {
|
||||
framesCounter += 1;
|
||||
|
||||
for (&recs) |*rec| {
|
||||
rec.height = reasings.circOut(@floatFromInt(framesCounter), RECS_HEIGHT, -RECS_HEIGHT, PLAY_TIME_IN_FRAMES);
|
||||
rec.width = reasings.circOut(@floatFromInt(framesCounter), RECS_WIDTH, -RECS_WIDTH, PLAY_TIME_IN_FRAMES);
|
||||
|
||||
if (rec.height < 0) rec.height = 0;
|
||||
if (rec.width < 0) rec.width = 0;
|
||||
|
||||
if ((rec.height == 0) and (rec.width == 0)) state = 1; // Finish playing
|
||||
|
||||
rotation = reasings.linearIn(@floatFromInt(framesCounter), 0.0, 360.0, PLAY_TIME_IN_FRAMES);
|
||||
}
|
||||
} else if ((state == 1) and rl.isKeyPressed(.space)) {
|
||||
// When animation has finished, press space to restart
|
||||
framesCounter = 0;
|
||||
|
||||
for (&recs) |*rec| {
|
||||
rec.height = RECS_HEIGHT;
|
||||
rec.width = RECS_WIDTH;
|
||||
}
|
||||
|
||||
state = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
if (state == 0) {
|
||||
for (recs) |rec| {
|
||||
rl.drawRectanglePro(rec, rl.Vector2{
|
||||
.x = rec.width / 2,
|
||||
.y = rec.height / 2,
|
||||
}, rotation, .red);
|
||||
}
|
||||
} else if (state == 1) rl.drawText("PRESS [SPACE] TO PLAY AGAIN!", 240, 200, 20, .gray);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
85
examples/shapes/following_eyes.zig
Normal file
@ -0,0 +1,85 @@
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - following eyes");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const scleraLeftPosition = rl.Vector2{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0 - 100.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 };
|
||||
const scleraRightPosition = rl.Vector2{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0 + 100.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 };
|
||||
const scleraRadius: i32 = 80;
|
||||
|
||||
var irisLeftPosition = rl.Vector2{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0 - 100.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 };
|
||||
var irisRightPosition = rl.Vector2{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0 + 100.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2.0 };
|
||||
const irisRadius: i32 = 24;
|
||||
|
||||
var angle: f32 = 0.0;
|
||||
var dx: f32 = 0.0;
|
||||
var dy: f32 = 0.0;
|
||||
var dxx: f32 = 0.0;
|
||||
var dyy: f32 = 0.0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
irisLeftPosition = rl.getMousePosition();
|
||||
irisRightPosition = rl.getMousePosition();
|
||||
|
||||
// Check not inside the left eye sclera
|
||||
if (!rl.checkCollisionPointCircle(irisLeftPosition, scleraLeftPosition, scleraRadius - irisRadius)) {
|
||||
dx = irisLeftPosition.x - scleraLeftPosition.x;
|
||||
dy = irisLeftPosition.y - scleraLeftPosition.y;
|
||||
|
||||
angle = math.atan2(dy, dx);
|
||||
|
||||
dxx = (scleraRadius - irisRadius) * math.cos(angle);
|
||||
dyy = (scleraRadius - irisRadius) * math.sin(angle);
|
||||
|
||||
irisLeftPosition.x = scleraLeftPosition.x + dxx;
|
||||
irisLeftPosition.y = scleraLeftPosition.y + dyy;
|
||||
}
|
||||
|
||||
// Check not inside the right eye sclera
|
||||
if (!rl.checkCollisionPointCircle(irisRightPosition, scleraRightPosition, scleraRadius - irisRadius)) {
|
||||
dx = irisRightPosition.x - scleraRightPosition.x;
|
||||
dy = irisRightPosition.y - scleraRightPosition.y;
|
||||
|
||||
angle = math.atan2(dy, dx);
|
||||
|
||||
dxx = (scleraRadius - irisRadius) * math.cos(angle);
|
||||
dyy = (scleraRadius - irisRadius) * math.sin(angle);
|
||||
|
||||
irisRightPosition.x = scleraRightPosition.x + dxx;
|
||||
irisRightPosition.y = scleraRightPosition.y + dyy;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.drawCircleV(scleraLeftPosition, scleraRadius, .light_gray);
|
||||
rl.drawCircleV(irisLeftPosition, irisRadius, .brown);
|
||||
rl.drawCircleV(irisLeftPosition, 10, .black);
|
||||
|
||||
rl.drawCircleV(scleraRightPosition, scleraRadius, .light_gray);
|
||||
rl.drawCircleV(irisRightPosition, irisRadius, .dark_green);
|
||||
rl.drawCircleV(irisRightPosition, 10, .black);
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
75
examples/shapes/lines_bezier.zig
Normal file
@ -0,0 +1,75 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
fn collisionFmt(isColliding: bool) f32 {
|
||||
if (isColliding) return 14.0;
|
||||
return 8.0;
|
||||
}
|
||||
|
||||
fn movingFmt(isMoving: bool) rl.Color {
|
||||
if (isMoving) return .red;
|
||||
return .blue;
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
//rl.setConfigFlags(@enumFromInt(rl.ConfigFlags.flag_msaa_4x_hint));
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - cubic-bezier lines");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var startPoint = rl.Vector2{ .x = 30, .y = 30 };
|
||||
var endPoint = rl.Vector2{ .x = screenWidth - 30, .y = screenHeight - 30 };
|
||||
var moveStartPoint = false;
|
||||
var moveEndPoint = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
const mouse: rl.Vector2 = rl.getMousePosition();
|
||||
|
||||
if (rl.checkCollisionPointCircle(mouse, startPoint, 10.0) and rl.isMouseButtonDown(.left)) {
|
||||
moveStartPoint = true;
|
||||
} else if (rl.checkCollisionPointCircle(mouse, endPoint, 10.0) and rl.isMouseButtonDown(.left)) {
|
||||
moveEndPoint = true;
|
||||
}
|
||||
|
||||
if (moveStartPoint) {
|
||||
startPoint = mouse;
|
||||
if (rl.isMouseButtonReleased(.left)) {
|
||||
moveStartPoint = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (moveEndPoint) {
|
||||
endPoint = mouse;
|
||||
if (rl.isMouseButtonReleased(.left)) {
|
||||
moveEndPoint = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("MOVE START-END POINTS WITH MOUSE", 15, 20, 20, .gray);
|
||||
|
||||
// Draw line Cubic Bezier, in-out interpolation (easing), no control points
|
||||
rl.drawLineBezier(startPoint, endPoint, 4.0, .blue);
|
||||
|
||||
// Draw start-end spline circles with some details
|
||||
rl.drawCircleV(startPoint, collisionFmt(rl.checkCollisionPointCircle(mouse, startPoint, 10.0)), movingFmt(moveStartPoint));
|
||||
rl.drawCircleV(endPoint, collisionFmt(rl.checkCollisionPointCircle(mouse, endPoint, 10.0)), movingFmt(moveEndPoint));
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@ -28,13 +28,13 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawRectangle(screenWidth / 2 - 128, screenHeight / 2 - 128, 256, 256, raylib_zig);
|
||||
rl.drawRectangle(screenWidth / 2 - 112, screenHeight / 2 - 112, 224, 224, rl.Color.ray_white);
|
||||
rl.drawRectangle(screenWidth / 2 - 112, screenHeight / 2 - 112, 224, 224, .ray_white);
|
||||
rl.drawText("raylib-zig", screenWidth / 2 - 96, screenHeight / 2 + 57, 41, raylib_zig);
|
||||
|
||||
rl.drawText("this is NOT a texture!", 350, 370, 10, rl.Color.gray);
|
||||
rl.drawText("this is NOT a texture!", 350, 370, 10, .gray);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
128
examples/shapes/logo_raylib_anim.zig
Normal file
@ -0,0 +1,128 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - raylib logo animation");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const logoPositionX = (screenWidth / 2) - 128;
|
||||
const logoPositionY = (screenHeight / 2) - 128;
|
||||
|
||||
var framesCounter: u8 = 0;
|
||||
var lettersCount: u8 = 0;
|
||||
|
||||
var topSideRecWidth: i32 = 16;
|
||||
var leftSideRecHeight: i32 = 16;
|
||||
|
||||
var bottomSideRecWidth: i32 = 16;
|
||||
var rightSideRecHeight: i32 = 16;
|
||||
|
||||
var state: u8 = 0;
|
||||
var alpha: f32 = 1.0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (state == 0) {
|
||||
framesCounter += 1;
|
||||
if (framesCounter == 120) {
|
||||
state = 1;
|
||||
framesCounter = 0;
|
||||
}
|
||||
} else if (state == 1) {
|
||||
topSideRecWidth += 4;
|
||||
leftSideRecHeight += 4;
|
||||
|
||||
if (topSideRecWidth == 256) state = 2;
|
||||
} else if (state == 2) // State 2: Bottom and right bars growing
|
||||
{
|
||||
bottomSideRecWidth += 4;
|
||||
rightSideRecHeight += 4;
|
||||
|
||||
if (bottomSideRecWidth == 256) state = 3;
|
||||
} else if (state == 3) // State 3: Letters appearing (one by one)
|
||||
{
|
||||
framesCounter += 1;
|
||||
|
||||
if (@mod(framesCounter, 12) == 0) // Every 12 frames, one more letter!
|
||||
{
|
||||
lettersCount += 1;
|
||||
framesCounter = 0;
|
||||
}
|
||||
|
||||
if (lettersCount >= 10) // When all letters have appeared, just fade out everything
|
||||
{
|
||||
alpha -= 0.02;
|
||||
|
||||
if (alpha <= 0.0) {
|
||||
alpha = 0.0;
|
||||
state = 4;
|
||||
}
|
||||
}
|
||||
} else if (state == 4) // State 4: Reset and Replay
|
||||
{
|
||||
if (rl.isKeyPressed(.r)) {
|
||||
framesCounter = 0;
|
||||
lettersCount = 0;
|
||||
|
||||
topSideRecWidth = 16;
|
||||
leftSideRecHeight = 16;
|
||||
|
||||
bottomSideRecWidth = 16;
|
||||
rightSideRecHeight = 16;
|
||||
|
||||
alpha = 1.0;
|
||||
state = 0; // Return to State 0
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
if (state == 0) {
|
||||
if (@mod(framesCounter, @as(u8, 15)) == 0) rl.drawRectangle(logoPositionX, logoPositionY, 16, 16, .black);
|
||||
} else if (state == 1) {
|
||||
rl.drawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, .black);
|
||||
rl.drawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, .black);
|
||||
} else if (state == 2) {
|
||||
rl.drawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, .black);
|
||||
rl.drawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, .black);
|
||||
|
||||
rl.drawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, .black);
|
||||
rl.drawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, .black);
|
||||
} else if (state == 3) {
|
||||
rl.drawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, .fade(.black, alpha));
|
||||
rl.drawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, .fade(.black, alpha));
|
||||
|
||||
rl.drawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, .fade(.black, alpha));
|
||||
rl.drawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, .fade(.black, alpha));
|
||||
|
||||
rl.drawRectangle(
|
||||
(@divFloor(rl.getScreenWidth(), @as(i32, 2))) - 112,
|
||||
(@divFloor(rl.getScreenHeight(), @as(i32, 2))) - 112,
|
||||
224,
|
||||
224,
|
||||
.fade(.ray_white, alpha),
|
||||
);
|
||||
|
||||
rl.drawText(rl.textSubtext("raylib", 0, lettersCount), @divFloor(rl.getScreenWidth(), @as(i32, 2)) - 44, @divFloor(rl.getScreenHeight(), @as(i32, 2)) + 48, 50, .fade(.black, alpha));
|
||||
} else if (state == 4) {
|
||||
rl.drawText("[R] REPLAY", 340, 200, 20, .gray);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
192
examples/shapes/reasings.zig
Normal file
@ -0,0 +1,192 @@
|
||||
const math = @import("std").math;
|
||||
|
||||
// Linear Easing functions
|
||||
pub fn linearNone(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (c * t / d + b);
|
||||
}
|
||||
pub fn linearIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (c * t / d + b);
|
||||
}
|
||||
pub fn linearOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (c * t / d + b);
|
||||
}
|
||||
pub fn linearInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (c * t / d + b);
|
||||
}
|
||||
|
||||
pub fn sineIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (-c * math.cos(t / d * (math.pi / 2.0)) + c + b);
|
||||
}
|
||||
pub fn sineOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (c * math.sin(t / d * (math.pi / 2.0)) + b);
|
||||
}
|
||||
pub fn sineInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (-c / 2.0 * (math.cos(math.pi * t / d) - 1.0) + b);
|
||||
}
|
||||
|
||||
// Circular Easing functions
|
||||
pub fn circIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postFix = t / d;
|
||||
return (-c * (math.sqrt(1.0 - postFix * postFix) - 1.0) + b);
|
||||
}
|
||||
pub fn circOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postFix = t / d - 1.0;
|
||||
return (c * math.sqrt(1.0 - postFix * postFix) + b);
|
||||
}
|
||||
pub fn circInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
var postFix = t / d;
|
||||
if ((postFix / 2.0) < 1.0) return (-c / 2.0 * (math.sqrt(1.0 - postFix * postFix) - 1.0) + b);
|
||||
postFix -= 2.0;
|
||||
return (c / 2.0 * (math.sqrt(1.0 - postFix * postFix) + 1.0) + b);
|
||||
}
|
||||
|
||||
// Cubic Easing functions
|
||||
pub fn cubicIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postFix = t / d;
|
||||
return (c * postFix * postFix * postFix + b);
|
||||
}
|
||||
pub fn cubicOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postFix = t / d - 1.0;
|
||||
return (c * (postFix * postFix * postFix + 1.0) + b);
|
||||
}
|
||||
pub fn cubicInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postFix = t / d;
|
||||
if (postFix / 2.0 < 1.0) return (c / 2.0 * postFix * postFix * postFix + b);
|
||||
postFix -= 2.0;
|
||||
return (c / 2.0 * (t * t * t + 2.0) + b);
|
||||
}
|
||||
|
||||
// Quadratic Easing functions
|
||||
pub fn quadIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postfix = t / d;
|
||||
return (c * postfix * postfix + b);
|
||||
}
|
||||
pub fn quadOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const postFix = t / d;
|
||||
return (-c * postFix * (postFix - 2.0) + b);
|
||||
}
|
||||
pub fn quadInOut(t: f32, b: f32, c: f32, d: f32) f32 // Ease: Quadratic In Out
|
||||
{
|
||||
const postFix = t / d;
|
||||
return if (postFix / 2 < 1)
|
||||
(((c / 2) * (postFix * postFix)) + b)
|
||||
else
|
||||
(-c / 2.0 * (((postFix - 1.0) * (postFix - 3.0)) - 1.0) + b);
|
||||
}
|
||||
|
||||
// Exponential Easing functions
|
||||
pub fn expoIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return if (t == 0.0) b else (c * math.pow(f32, 2.0, 10.0 * (t / d - 1.0)) + b);
|
||||
}
|
||||
pub fn expoOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return if (t == d) (b + c) else (c * (-math.pow(f32, 2.0, -10.0 * t / d) + 1.0) + b);
|
||||
}
|
||||
pub fn expoInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
if (t == 0.0) return b;
|
||||
if (t == d) return (b + c);
|
||||
const postFix = t / d;
|
||||
if ((postFix / 2.0) < 1.0) return (c / 2.0 * math.pow(f32, 2.0, 10.0 * (postFix - 1.0)) + b);
|
||||
|
||||
return (c / 2.0 * (-math.pow(f32, 2.0, -10.0 * (postFix - 1.0)) + 2.0) + b);
|
||||
}
|
||||
|
||||
// Back Easing functions
|
||||
pub fn backIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const s = 1.70158;
|
||||
const postFix = t / d;
|
||||
return (c * (postFix) * postFix * ((s + 1.0) * postFix - s) + b);
|
||||
}
|
||||
|
||||
pub fn backOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const s = 1.70158;
|
||||
const postFix = t / d - 1.0;
|
||||
return (c * (postFix * postFix * ((s + 1.0) * postFix + s) + 1.0) + b);
|
||||
}
|
||||
|
||||
pub fn backInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
const s = 1.70158;
|
||||
t /= d;
|
||||
if (t / 2.0 < 1.0) {
|
||||
s *= 1.525;
|
||||
return (c / 2.0 * (t * t * ((s + 1.0) * t - s)) + b);
|
||||
}
|
||||
t -= 2;
|
||||
const postFix = t;
|
||||
s *= 1.525;
|
||||
return (c / 2.0 * ((postFix) * t * ((s + 1.0) * t + s) + 2.0) + b);
|
||||
}
|
||||
|
||||
// Bounce Easing functions
|
||||
|
||||
pub fn bounceOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
var tDivD = t / d;
|
||||
if (tDivD < (1.0 / 2.75)) {
|
||||
return (c * (7.5625 * tDivD * tDivD) + b);
|
||||
} else if (tDivD < (2.0 / 2.75)) {
|
||||
tDivD -= (1.5 / 2.75);
|
||||
return (c * (7.5625 * tDivD * tDivD + 0.75) + b);
|
||||
} else if (tDivD < (2.5 / 2.75)) {
|
||||
tDivD -= (2.25 / 2.75);
|
||||
return (c * (7.5625 * tDivD * tDivD + 0.9375) + b);
|
||||
} else {
|
||||
tDivD -= (2.625 / 2.75);
|
||||
return (c * (7.5625 * tDivD * tDivD + 0.984375) + b);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bounceIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
return (c - bounceOut(d - t, 0.0, c, d) + b);
|
||||
}
|
||||
|
||||
pub fn bounceInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
if (t < d / 2.0) return (bounceIn(t * 2.0, 0.0, c, d) * 0.5 + b);
|
||||
return (bounceOut(t * 2.0 - d, 0.0, c, d) * 0.5 + c * 0.5 + b);
|
||||
}
|
||||
|
||||
// Elastic Easing functions
|
||||
pub fn elasticIn(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
if (t == 0.0) return b;
|
||||
var tDivD = t / d;
|
||||
if (tDivD == 1.0) return (b + c);
|
||||
|
||||
const p = d * 0.3;
|
||||
const a = c;
|
||||
const s = p / 4.0;
|
||||
tDivD -= 1;
|
||||
const postFix = a * math.pow(f32, 2.0, 10.0 * tDivD);
|
||||
|
||||
return (-(postFix * math.sin((tDivD * d - s) * (2.0 * math.pi) / p)) + b);
|
||||
}
|
||||
|
||||
pub fn elasticOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
if (t == 0.0) return b;
|
||||
const tDivD = t / d;
|
||||
if (tDivD == 1.0) return (b + c);
|
||||
|
||||
const p = d * 0.3;
|
||||
const a = c;
|
||||
const s = p / 4.0;
|
||||
|
||||
return (a * math.pow(f32, 2.0, -10.0 * tDivD) * math.sin((tDivD * d - s) * (2.0 * math.pi) / p) + c + b);
|
||||
}
|
||||
|
||||
pub fn elasticInOut(t: f32, b: f32, c: f32, d: f32) f32 {
|
||||
if (t == 0.0) return b;
|
||||
const tDivD = t / d;
|
||||
if (tDivD / 2.0 == 2.0) return (b + c);
|
||||
|
||||
const p = d * (0.3 * 1.5);
|
||||
const a = c;
|
||||
const s = p / 4.0;
|
||||
|
||||
if (tDivD < 1.0) {
|
||||
tDivD -= 1;
|
||||
const postFix = a * math.pow(f32, 2.0, 10.0 * tDivD);
|
||||
return -0.5 * (postFix * math.sin((tDivD * d - s) * (2.0 * math.pi) / p)) + b;
|
||||
}
|
||||
|
||||
tDivD -= 1;
|
||||
const postFix = a * math.pow(f32, 2.0, -10.0 * (tDivD));
|
||||
|
||||
return (postFix * math.sin((tDivD * d - s) * (2.0 * math.pi) / p) * 0.5 + c + b);
|
||||
}
|
||||
83
examples/shapes/rectangle_scaling.zig
Normal file
@ -0,0 +1,83 @@
|
||||
const rl = @import("raylib");
|
||||
|
||||
const mouseScaleMarkSize = 12;
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib-zig [shapes] example - rectangle scaling mouse");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var rec: rl.Rectangle = rl.Rectangle{ .x = 100, .y = 100, .width = 200, .height = 80 };
|
||||
var mousePosition: rl.Vector2 = rl.Vector2{ .x = 0, .y = 0 };
|
||||
|
||||
var mouseScaleReady: bool = false;
|
||||
var mouseScaleMode: bool = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
mousePosition = rl.getMousePosition();
|
||||
|
||||
if (rl.checkCollisionPointRec(mousePosition, rl.Rectangle{ .x = (rec.x + rec.width) - mouseScaleMarkSize, .y = (rec.y + rec.height) - mouseScaleMarkSize, .width = mouseScaleMarkSize, .height = mouseScaleMarkSize })) {
|
||||
mouseScaleReady = true;
|
||||
if (rl.isMouseButtonPressed(.left)) {
|
||||
mouseScaleMode = true;
|
||||
}
|
||||
} else {
|
||||
mouseScaleReady = false;
|
||||
}
|
||||
|
||||
if (mouseScaleMode) {
|
||||
mouseScaleReady = true;
|
||||
|
||||
rec.width = (mousePosition.x - rec.x);
|
||||
rec.height = (mousePosition.y - rec.y);
|
||||
|
||||
// Check minimum rec size
|
||||
if (rec.width < mouseScaleMarkSize) {
|
||||
rec.width = mouseScaleMarkSize;
|
||||
}
|
||||
if (rec.height < mouseScaleMarkSize) {
|
||||
rec.height = mouseScaleMarkSize;
|
||||
}
|
||||
|
||||
// Check maximum rec size
|
||||
if (rec.width > (@as(f32, @floatFromInt(rl.getScreenWidth())) - rec.x)) {
|
||||
rec.width = @as(f32, @floatFromInt(rl.getScreenWidth())) - rec.x;
|
||||
}
|
||||
if (rec.height > (@as(f32, @floatFromInt(rl.getScreenHeight())) - rec.y)) {
|
||||
rec.height = @as(f32, @floatFromInt(rl.getScreenHeight())) - rec.y;
|
||||
}
|
||||
|
||||
if (rl.isMouseButtonReleased(.left)) {
|
||||
mouseScaleMode = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("Scale rectangle dragging from bottom-right corner!", 10, 10, 20, .gray);
|
||||
|
||||
rl.drawRectangleRec(rec, .fade(.green, 0.5));
|
||||
|
||||
if (mouseScaleReady) {
|
||||
rl.drawRectangleLinesEx(rec, 1, .red);
|
||||
rl.drawTriangle(rl.Vector2{ .x = rec.x + rec.width - mouseScaleMarkSize, .y = rec.y + rec.height }, rl.Vector2{ .x = rec.x + rec.width, .y = rec.y + rec.height }, rl.Vector2{ .x = rec.x + rec.width, .y = rec.y + rec.height - mouseScaleMarkSize }, .red);
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
226
examples/shapes/splines_drawing.zig
Normal file
@ -0,0 +1,226 @@
|
||||
const rl = @import("raylib");
|
||||
const rgui = @import("raygui");
|
||||
|
||||
const MAX_SPLINE_POINTS = 32;
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
// Cubic Bezier spline control points
|
||||
// NOTE: Every segment has two control points
|
||||
const ControlPoint = struct {
|
||||
start: rl.Vector2,
|
||||
end: rl.Vector2,
|
||||
};
|
||||
|
||||
// Spline types
|
||||
const SplineType = enum(i32) {
|
||||
linear = 0, // Linear
|
||||
basis = 1, // B-Spline
|
||||
catmullrom = 2, // Catmull-Rom
|
||||
bezier = 3, // Cubic Bezier
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
rl.setConfigFlags(.{ .msaa_4x_hint = true });
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [shapes] example - splines drawing");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
var points: [MAX_SPLINE_POINTS]rl.Vector2 = undefined;
|
||||
points[0] = rl.Vector2{ .x = 50.0, .y = 400.0 };
|
||||
points[1] = rl.Vector2{ .x = 160.0, .y = 220.0 };
|
||||
points[2] = rl.Vector2{ .x = 340.0, .y = 380.0 };
|
||||
points[3] = rl.Vector2{ .x = 520.0, .y = 60.0 };
|
||||
points[4] = rl.Vector2{ .x = 710.0, .y = 260.0 };
|
||||
for (5..MAX_SPLINE_POINTS) |i| {
|
||||
points[i] = rl.Vector2{ .x = 0, .y = 0 };
|
||||
}
|
||||
|
||||
// Array required for spline bezier-cubic,
|
||||
// including control points interleaved with start-end segment points
|
||||
var pointsInterleaved: [3 * (MAX_SPLINE_POINTS - 1) + 1]rl.Vector2 = undefined;
|
||||
for (&pointsInterleaved) |*point| {
|
||||
point.* = rl.Vector2{ .x = 0, .y = 0 };
|
||||
}
|
||||
|
||||
var pointCount: usize = 5;
|
||||
var selectedPoint: ?*rl.Vector2 = null;
|
||||
var focusedPoint: ?*rl.Vector2 = null;
|
||||
var selectedControlPoint: ?*rl.Vector2 = null;
|
||||
var focusedControlPoint: ?*rl.Vector2 = null;
|
||||
|
||||
// Cubic Bezier control points initialization
|
||||
var control: [MAX_SPLINE_POINTS - 1]ControlPoint = undefined;
|
||||
for (&control) |*cp| {
|
||||
cp.* = .{ .end = .{ .x = 0, .y = 0 }, .start = .{ .x = 0, .y = 0 } };
|
||||
}
|
||||
for (0..pointCount) |i| {
|
||||
control[i].start = .{ .x = points[i].x + 50, .y = points[i].y };
|
||||
control[i].end = .{ .x = points[i + 1].x - 50, .y = points[i + 1].y };
|
||||
}
|
||||
|
||||
// Spline config variables
|
||||
var splineThickness: f32 = 8.0;
|
||||
var splineTypeActive = SplineType.linear;
|
||||
var splineTypeEditMode = false;
|
||||
var splineHelpersActive = true;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Spline points creation logic (at the end of spline)
|
||||
if (rl.isMouseButtonPressed(.right) and (pointCount < MAX_SPLINE_POINTS)) {
|
||||
points[pointCount] = rl.getMousePosition();
|
||||
const i = pointCount - 1;
|
||||
control[i].start = rl.Vector2{ .x = points[i].x + 50, .y = points[i].y };
|
||||
control[i].end = rl.Vector2{ .x = points[i + 1].x - 50, .y = points[i + 1].y };
|
||||
pointCount += 1;
|
||||
}
|
||||
|
||||
// Spline point focus and selection logic
|
||||
if (selectedPoint == null and ((splineTypeActive != SplineType.bezier) or selectedControlPoint == null)) {
|
||||
focusedPoint = null;
|
||||
for (0..pointCount) |i| {
|
||||
if (rl.checkCollisionPointCircle(rl.getMousePosition(), points[i], 8.0)) {
|
||||
focusedPoint = &points[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rl.isMouseButtonPressed(.left)) selectedPoint = focusedPoint;
|
||||
}
|
||||
|
||||
// Spline point movement logic
|
||||
if (selectedPoint) |point| {
|
||||
point.* = rl.getMousePosition();
|
||||
if (rl.isMouseButtonReleased(.left)) selectedPoint = null;
|
||||
}
|
||||
|
||||
// Cubic Bezier spline control points logic
|
||||
if ((splineTypeActive == SplineType.bezier) and focusedPoint == null) {
|
||||
// Spline control point focus and selection logic
|
||||
if (selectedControlPoint == null) {
|
||||
focusedControlPoint = null;
|
||||
for (0..pointCount) |i| {
|
||||
if (rl.checkCollisionPointCircle(rl.getMousePosition(), control[i].start, 6.0)) {
|
||||
focusedControlPoint = &control[i].start;
|
||||
break;
|
||||
} else if (rl.checkCollisionPointCircle(rl.getMousePosition(), control[i].end, 6.0)) {
|
||||
focusedControlPoint = &control[i].end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rl.isMouseButtonPressed(.left)) selectedControlPoint = focusedControlPoint;
|
||||
}
|
||||
|
||||
// Spline control point movement logic
|
||||
if (selectedControlPoint) |cp| {
|
||||
cp.* = rl.getMousePosition();
|
||||
if (rl.isMouseButtonReleased(.left)) selectedControlPoint = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Spline selection logic
|
||||
splineTypeActive = switch (rl.getKeyPressed()) {
|
||||
.one => SplineType.linear,
|
||||
.two => SplineType.basis,
|
||||
.three => SplineType.catmullrom,
|
||||
.four => SplineType.basis,
|
||||
else => splineTypeActive,
|
||||
};
|
||||
|
||||
// Clear selection when changing to a spline without control points
|
||||
if (rl.isKeyPressed(.one) or rl.isKeyPressed(.two) or rl.isKeyPressed(.three)) selectedControlPoint = null;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
switch (splineTypeActive) {
|
||||
SplineType.linear => rl.drawSplineLinear(points[0..pointCount], splineThickness, .red),
|
||||
SplineType.basis => rl.drawSplineBasis(points[0..pointCount], splineThickness, .red),
|
||||
SplineType.catmullrom => rl.drawSplineCatmullRom(points[0..pointCount], splineThickness, .red),
|
||||
SplineType.bezier => {
|
||||
// NOTE: Cubic-bezier spline requires the 2 control points of each segnment to be
|
||||
// provided interleaved with the start and end point of every segment
|
||||
for (0..pointCount - 1) |i| {
|
||||
pointsInterleaved[3 * i] = points[i];
|
||||
pointsInterleaved[3 * i + 1] = control[i].start;
|
||||
pointsInterleaved[3 * i + 2] = control[i].end;
|
||||
}
|
||||
|
||||
pointsInterleaved[3 * (pointCount - 1)] = points[pointCount - 1];
|
||||
|
||||
// Draw spline: cubic-bezier (with control points)
|
||||
rl.drawSplineBezierCubic(pointsInterleaved[0 .. 3 * pointCount], splineThickness, .red);
|
||||
|
||||
// Draw spline control points
|
||||
for (0..pointCount - 1) |i| {
|
||||
// Every cubic bezier point have two control points
|
||||
rl.drawCircleV(control[i].start, 6, .gold);
|
||||
rl.drawCircleV(control[i].end, 6, .gold);
|
||||
|
||||
if (focusedControlPoint == &control[i].start) rl.drawCircleV(control[i].start, 8, .green) else if (focusedControlPoint == &control[i].end) rl.drawCircleV(control[i].end, 8, .green);
|
||||
rl.drawLineEx(points[i], control[i].start, 1.0, .light_gray);
|
||||
rl.drawLineEx(points[i + 1], control[i].end, 1.0, .light_gray);
|
||||
|
||||
// Draw spline control lines
|
||||
rl.drawLineV(points[i], control[i].start, .gray);
|
||||
rl.drawLineV(control[i].end, points[i + 1], .gray);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if (splineHelpersActive) {
|
||||
// Draw spline point helpers
|
||||
for (0..pointCount) |i| {
|
||||
const radius: f32 = if (focusedPoint == &points[i]) 12 else 8;
|
||||
const color: rl.Color = if (focusedPoint == &points[i]) .blue else .dark_blue;
|
||||
rl.drawCircleLinesV(points[i], radius, color);
|
||||
if ((splineTypeActive != SplineType.linear) and
|
||||
(splineTypeActive != SplineType.bezier) and
|
||||
(i < pointCount - 1)) rl.drawLineV(points[i], points[i + 1], .gray);
|
||||
|
||||
rl.drawText(rl.textFormat("[%.0f, %.0f]", .{ points[i].x, points[i].y }), @intFromFloat(points[i].x), @intFromFloat(points[i].y + 10), 10, .black);
|
||||
}
|
||||
}
|
||||
|
||||
// Check all possible UI states that require controls lock
|
||||
if (splineTypeEditMode or selectedPoint != null or selectedControlPoint != null) rgui.lock();
|
||||
|
||||
// Draw spline config
|
||||
_ = rgui.label(.{ .x = 12, .y = 62, .width = 140, .height = 24 }, rl.textFormat("Spline thickness: %i", .{@as(i64, @intFromFloat(splineThickness))}));
|
||||
|
||||
_ = rgui.sliderBar(.{ .x = 12, .y = 60 + 24, .width = 140, .height = 16 }, "", "", &splineThickness, 1.0, 40.0);
|
||||
|
||||
_ = rgui.checkBox(.{ .x = 12, .y = 110, .width = 20, .height = 20 }, "Show point helpers", &splineHelpersActive);
|
||||
|
||||
if (splineTypeEditMode) rgui.unlock();
|
||||
|
||||
_ = rgui.label(.{ .x = 12, .y = 10, .width = 140, .height = 24 }, "Spline type:");
|
||||
var active: i32 = @intFromEnum(splineTypeActive);
|
||||
if (rgui.dropdownBox(.{
|
||||
.x = 12,
|
||||
.y = 8 + 24,
|
||||
.width = 140,
|
||||
.height = 28,
|
||||
}, "LINEAR;BSPLINE;CATMULLROM;BEZIER", &active, splineTypeEditMode) > 0) splineTypeEditMode = !splineTypeEditMode;
|
||||
splineTypeActive = @enumFromInt(active);
|
||||
|
||||
rgui.unlock();
|
||||
}
|
||||
}
|
||||
341
examples/shapes/top_down_lights.zig
Normal file
@ -0,0 +1,341 @@
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
// Custom Blend Modes
|
||||
const RLGL_SRC_ALPHA = 0x0302;
|
||||
const RLGL_MIN = 0x8007;
|
||||
const RLGL_MAX = 0x8008;
|
||||
|
||||
const MAX_BOXES = 20;
|
||||
/// MAX_BOXES *3. Each box can cast up to two shadow volumes for the edges it is away from, and one for the box itself
|
||||
const MAX_SHADOWS = MAX_BOXES * 3;
|
||||
const MAX_LIGHTS = 16;
|
||||
|
||||
// Shadow geometry type
|
||||
const ShadowGeometry = struct {
|
||||
vertices: [4]rl.Vector2,
|
||||
};
|
||||
|
||||
// Light info type
|
||||
const LightInfo = struct {
|
||||
/// Is this light slot active?
|
||||
active: bool,
|
||||
/// Does this light need to be updated?
|
||||
dirty: bool,
|
||||
/// Is this light in a valid position?
|
||||
valid: bool,
|
||||
|
||||
/// Light position
|
||||
position: rl.Vector2,
|
||||
/// Alpha mask for the light
|
||||
mask: rl.RenderTexture,
|
||||
/// The distance the light touches
|
||||
outerRadius: f32,
|
||||
/// A cached rectangle of the light bounds to help with culling
|
||||
bounds: rl.Rectangle,
|
||||
|
||||
shadows: [MAX_SHADOWS]ShadowGeometry,
|
||||
shadowCount: usize,
|
||||
};
|
||||
|
||||
var lights: [MAX_LIGHTS]LightInfo = undefined;
|
||||
|
||||
// Move a light and mark it as dirty so that we update it's mask next frame
|
||||
fn MoveLight(slot: usize, x: f32, y: f32) void {
|
||||
lights[slot].dirty = true;
|
||||
lights[slot].position.x = x;
|
||||
lights[slot].position.y = y;
|
||||
|
||||
// update the cached bounds
|
||||
lights[slot].bounds.x = x - lights[slot].outerRadius;
|
||||
lights[slot].bounds.y = y - lights[slot].outerRadius;
|
||||
}
|
||||
|
||||
// Compute a shadow volume for the edge
|
||||
// It takes the edge and projects it back by the light radius and turns it into a quad
|
||||
fn computeShadowVolumeForEdge(slot: usize, sp: rl.Vector2, ep: rl.Vector2) void {
|
||||
if (lights[slot].shadowCount >= MAX_SHADOWS) return;
|
||||
|
||||
const extension = lights[slot].outerRadius * 2;
|
||||
|
||||
const spVector = rl.math.vector2Normalize(rl.math.vector2Subtract(sp, lights[slot].position));
|
||||
const spProjection = rl.math.vector2Add(sp, rl.math.vector2Scale(spVector, extension));
|
||||
|
||||
const epVector = rl.math.vector2Normalize(rl.math.vector2Subtract(ep, lights[slot].position));
|
||||
const epProjection = rl.math.vector2Add(ep, rl.math.vector2Scale(epVector, extension));
|
||||
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[0] = sp;
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[1] = ep;
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[2] = epProjection;
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[3] = spProjection;
|
||||
|
||||
lights[slot].shadowCount += 1;
|
||||
}
|
||||
|
||||
// Draw the light and shadows to the mask for a light
|
||||
fn drawLightMask(slot: usize) void {
|
||||
// Use the light mask
|
||||
rl.beginTextureMode(lights[slot].mask);
|
||||
defer rl.endTextureMode();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
// Force the blend mode to only set the alpha of the destination
|
||||
rl.gl.rlSetBlendFactors(RLGL_SRC_ALPHA, RLGL_SRC_ALPHA, RLGL_MIN);
|
||||
rl.gl.rlSetBlendMode(@intFromEnum(rl.gl.rlBlendMode.rl_blend_custom));
|
||||
// defer going back to normal blend mode
|
||||
defer rl.gl.rlSetBlendMode(@intFromEnum(rl.gl.rlBlendMode.rl_blend_alpha));
|
||||
|
||||
// If we are valid, then draw the light radius to the alpha mask
|
||||
if (lights[slot].valid) rl.drawCircleGradient(@intFromFloat(lights[slot].position.x), @intFromFloat(lights[slot].position.y), lights[slot].outerRadius, rl.colorAlpha(.white, 0), .white);
|
||||
|
||||
rl.gl.rlDrawRenderBatchActive();
|
||||
|
||||
// Cut out the shadows from the light radius by forcing the alpha to maximum
|
||||
rl.gl.rlSetBlendMode(@intFromEnum(rl.gl.rlBlendMode.rl_blend_alpha));
|
||||
rl.gl.rlSetBlendFactors(RLGL_SRC_ALPHA, RLGL_SRC_ALPHA, RLGL_MAX);
|
||||
rl.gl.rlSetBlendMode(@intFromEnum(rl.gl.rlBlendMode.rl_blend_custom));
|
||||
|
||||
// Draw the shadows to the alpha mask
|
||||
for (0..lights[slot].shadowCount) |i| {
|
||||
rl.drawTriangleFan(&lights[slot].shadows[i].vertices, .white);
|
||||
}
|
||||
|
||||
rl.gl.rlDrawRenderBatchActive();
|
||||
}
|
||||
|
||||
// Setup a light
|
||||
fn setupLight(slot: usize, x: f32, y: f32, radius: f32) !void {
|
||||
lights[slot].active = true;
|
||||
lights[slot].valid = false; // The light must prove it is valid
|
||||
lights[slot].mask = try rl.loadRenderTexture(rl.getScreenWidth(), rl.getScreenHeight());
|
||||
lights[slot].outerRadius = radius;
|
||||
|
||||
lights[slot].bounds.width = radius * 2;
|
||||
lights[slot].bounds.height = radius * 2;
|
||||
|
||||
MoveLight(slot, x, y);
|
||||
|
||||
// Force the render texture to have something in it
|
||||
drawLightMask(slot);
|
||||
}
|
||||
|
||||
// See if a light needs to update it's mask
|
||||
// fn UpdateLight(slot: usize, Rectangle* boxes, int count) bool
|
||||
fn updateLight(slot: usize, boxes: []rl.Rectangle) bool {
|
||||
if (!lights[slot].active or !lights[slot].dirty) return false;
|
||||
|
||||
lights[slot].dirty = false;
|
||||
lights[slot].shadowCount = 0;
|
||||
lights[slot].valid = false;
|
||||
|
||||
for (boxes) |box| {
|
||||
// Are we in a box? if so we are not valid
|
||||
if (rl.checkCollisionPointRec(lights[slot].position, box)) return false;
|
||||
|
||||
// If this box is outside our bounds, we can skip it
|
||||
if (!rl.checkCollisionRecs(lights[slot].bounds, box)) continue;
|
||||
|
||||
// Check the edges that are on the same side we are, and cast shadow volumes out from them
|
||||
|
||||
// Top
|
||||
var sp = rl.Vector2{ .x = box.x, .y = box.y };
|
||||
var ep = rl.Vector2{ .x = box.x + box.width, .y = box.y };
|
||||
|
||||
if (lights[slot].position.y > ep.y) computeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// Right
|
||||
sp = ep;
|
||||
ep.y += box.height;
|
||||
if (lights[slot].position.x < ep.x) computeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// Bottom
|
||||
sp = ep;
|
||||
ep.x -= box.width;
|
||||
if (lights[slot].position.y < ep.y) computeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// Left
|
||||
sp = ep;
|
||||
ep.y -= box.height;
|
||||
if (lights[slot].position.x > ep.x) computeShadowVolumeForEdge(slot, sp, ep);
|
||||
|
||||
// The box itself
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[0] = rl.Vector2{ .x = box.x, .y = box.y };
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[1] = rl.Vector2{ .x = box.x, .y = box.y + box.height };
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[2] = rl.Vector2{ .x = box.x + box.width, .y = box.y + box.height };
|
||||
lights[slot].shadows[lights[slot].shadowCount].vertices[3] = rl.Vector2{ .x = box.x + box.width, .y = box.y };
|
||||
lights[slot].shadowCount += 1;
|
||||
}
|
||||
|
||||
lights[slot].valid = true;
|
||||
|
||||
drawLightMask(slot);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set up some boxes
|
||||
fn setupBoxes(boxes: []rl.Rectangle) void {
|
||||
boxes[0] = rl.Rectangle{ .x = 150, .y = 80, .width = 40, .height = 40 };
|
||||
boxes[1] = rl.Rectangle{ .x = 1200, .y = 700, .width = 40, .height = 40 };
|
||||
boxes[2] = rl.Rectangle{ .x = 200, .y = 600, .width = 40, .height = 40 };
|
||||
boxes[3] = rl.Rectangle{ .x = 1000, .y = 50, .width = 40, .height = 40 };
|
||||
boxes[4] = rl.Rectangle{ .x = 500, .y = 350, .width = 40, .height = 40 };
|
||||
|
||||
for (5..boxes.len) |i| {
|
||||
boxes[i] = rl.Rectangle{
|
||||
.x = @floatFromInt(rl.getRandomValue(0, rl.getScreenWidth())),
|
||||
.y = @floatFromInt(rl.getRandomValue(0, rl.getScreenHeight())),
|
||||
.width = @floatFromInt(rl.getRandomValue(10, 100)),
|
||||
.height = @floatFromInt(rl.getRandomValue(10, 100)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [shapes] example - top down lights");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Initialize our 'world' of boxes
|
||||
var boxes: [MAX_BOXES]rl.Rectangle = undefined;
|
||||
setupBoxes(&boxes);
|
||||
|
||||
// Create a checkerboard ground texture
|
||||
const img = rl.genImageChecked(64, 64, 32, 32, .dark_brown, .dark_gray);
|
||||
defer rl.unloadImage(img);
|
||||
const backgroundTexture = try rl.loadTextureFromImage(img);
|
||||
defer rl.unloadTexture(backgroundTexture);
|
||||
|
||||
// Create a global light mask to hold all the blended lights
|
||||
const lightMask = try rl.loadRenderTexture(rl.getScreenWidth(), rl.getScreenHeight());
|
||||
defer rl.unloadRenderTexture(lightMask);
|
||||
|
||||
// Setup initial light
|
||||
try setupLight(0, 600, 400, 300);
|
||||
defer {
|
||||
//deinitialize light
|
||||
for (&lights) |*light| {
|
||||
if (light.active) rl.unloadRenderTexture(light.mask);
|
||||
}
|
||||
}
|
||||
var nextLight: usize = 1;
|
||||
|
||||
var showLines = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Drag light 0
|
||||
if (rl.isMouseButtonDown(.left)) MoveLight(0, rl.getMousePosition().x, rl.getMousePosition().y);
|
||||
|
||||
// Make a new light
|
||||
if (rl.isMouseButtonPressed(.right) and (nextLight < MAX_LIGHTS)) {
|
||||
try setupLight(nextLight, rl.getMousePosition().x, rl.getMousePosition().y, 200);
|
||||
nextLight += 1;
|
||||
}
|
||||
|
||||
// Toggle debug info
|
||||
if (rl.isKeyPressed(.f1)) showLines = !showLines;
|
||||
|
||||
// Update the lights and keep track if any were dirty so we know if we need to update the master light mask
|
||||
var dirtyLights = false;
|
||||
for (0..MAX_LIGHTS) |i| {
|
||||
if (updateLight(i, &boxes)) dirtyLights = true;
|
||||
}
|
||||
|
||||
// Update the light mask
|
||||
if (dirtyLights) {
|
||||
// Build up the light mask
|
||||
rl.beginTextureMode(lightMask);
|
||||
defer rl.endTextureMode();
|
||||
|
||||
rl.clearBackground(.black);
|
||||
|
||||
// Force the blend mode to only set the alpha of the destination
|
||||
rl.gl.rlSetBlendFactors(RLGL_SRC_ALPHA, RLGL_SRC_ALPHA, RLGL_MIN);
|
||||
rl.gl.rlSetBlendMode(@intFromEnum(rl.gl.rlBlendMode.rl_blend_custom));
|
||||
defer rl.gl.rlSetBlendMode(@intFromEnum(rl.gl.rlBlendMode.rl_blend_alpha));
|
||||
|
||||
// Merge in all the light masks
|
||||
for (lights) |light| {
|
||||
if (light.active) rl.drawTextureRec(light.mask.texture, rl.Rectangle{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = @floatFromInt(rl.getScreenWidth()),
|
||||
.height = @floatFromInt(-rl.getScreenHeight()),
|
||||
}, rl.Vector2.zero(), .white);
|
||||
}
|
||||
|
||||
rl.gl.rlDrawRenderBatchActive();
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.black);
|
||||
|
||||
// Draw the tile background
|
||||
rl.drawTextureRec(backgroundTexture, rl.Rectangle{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = @floatFromInt(rl.getScreenWidth()),
|
||||
.height = @floatFromInt(rl.getScreenHeight()),
|
||||
}, rl.Vector2.zero(), .white);
|
||||
|
||||
// Overlay the shadows from all the lights
|
||||
rl.drawTextureRec(lightMask.texture, rl.Rectangle{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = @floatFromInt(rl.getScreenWidth()),
|
||||
.height = @floatFromInt(-rl.getScreenHeight()),
|
||||
}, rl.Vector2.zero(), rl.colorAlpha(.white, if (showLines) 0.75 else 1.0));
|
||||
|
||||
// Draw the lights
|
||||
for (0..MAX_LIGHTS) |i| {
|
||||
if (lights[i].active) rl.drawCircle(@intFromFloat(lights[i].position.x), @intFromFloat(lights[i].position.y), 10, if (i == 0) .yellow else .white);
|
||||
}
|
||||
|
||||
if (showLines) {
|
||||
for (0..lights[0].shadowCount) |s| {
|
||||
rl.drawTriangleFan(&lights[0].shadows[s].vertices, .dark_purple);
|
||||
}
|
||||
|
||||
for (boxes) |box| {
|
||||
if (rl.checkCollisionRecs(box, lights[0].bounds)) rl.drawRectangleRec(box, .purple);
|
||||
|
||||
rl.drawRectangleLines(@intFromFloat(box.x), @intFromFloat(box.y), @intFromFloat(box.width), @intFromFloat(box.height), .dark_blue);
|
||||
}
|
||||
|
||||
rl.drawText("(F1) Hide Shadow Volumes", 10, 50, 10, .green);
|
||||
} else {
|
||||
rl.drawText("(F1) Show Shadow Volumes", 10, 50, 10, .green);
|
||||
}
|
||||
|
||||
rl.drawFPS(screenWidth - 80, 10);
|
||||
rl.drawText("Drag to move light #1", 10, 10, 10, .dark_green);
|
||||
rl.drawText("Right click to add new light", 10, 30, 10, .dark_green);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
166
examples/text/codepoints_loading.zig
Normal file
@ -0,0 +1,166 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zog port of the [text] example - Codepoints loading
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_codepoints_loading.c
|
||||
//!
|
||||
//! Example complexity rating: [★★★☆] 3/4
|
||||
//!
|
||||
//! Example originally created with raylib 4.2, last time updated with raylib 2.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
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! Copyright (c) 2022-2025 Ramon Santamaria (@raysan5)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
/// Text to be displayed, must be UTF-8 (save this code file as UTF-8)
|
||||
/// NOTE: It can contain all the required text for the game,
|
||||
/// this text will be scanned to get all the required codepoints
|
||||
const text = "いろはにほへと ちりぬるを\nわかよたれそ つねならむ\nうゐのおくやま けふこえて\nあさきゆめみし ゑひもせす";
|
||||
|
||||
// Remove codepoint duplicates if requested
|
||||
// static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointResultCount);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - codepoints loading");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Convert each utf-8 character into its
|
||||
// corresponding codepoint in the font file.
|
||||
const codepoints = try rl.loadCodepoints(text);
|
||||
const codepoints_count = codepoints.len;
|
||||
|
||||
//the DebugAllocator provides us with a nice general purpose allocator, great for small projects like this
|
||||
var font: rl.Font = undefined;
|
||||
var codepoints_no_dups: [:0]i32 = undefined;
|
||||
var codepoints_no_dups_count: usize = undefined;
|
||||
{
|
||||
var dba = std.heap.DebugAllocator(.{}){};
|
||||
var alloc = dba.allocator();
|
||||
// Removed duplicate codepoints to generate smaller font atlas
|
||||
codepoints_no_dups = try CodepointRemoveDuplicates(alloc, codepoints);
|
||||
codepoints_no_dups_count = std.mem.len(codepoints_no_dups.ptr);
|
||||
defer alloc.free(codepoints_no_dups);
|
||||
// we can free codepoints at the end of this block, atlas has already been generated
|
||||
rl.unloadCodepoints(codepoints);
|
||||
|
||||
// Load font containing all the provided codepoint glyphs
|
||||
// A texture font atlas is automatically generated
|
||||
// example assumes it is being run from the root of the project
|
||||
font = try rl.loadFontEx("examples/text/resources/DotGothic16-Regular.ttf", 36, codepoints_no_dups);
|
||||
|
||||
// Set bilinear scale filter for better font scaling
|
||||
rl.setTextureFilter(font.texture, .bilinear);
|
||||
rl.setTextLineSpacing(20); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||
}
|
||||
defer rl.unloadFont(font); // Unload font at the end of the program
|
||||
|
||||
var show_font_atlas = false;
|
||||
|
||||
var codepoint_size: i32 = 0;
|
||||
var start: i32 = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyPressed(.space)) show_font_atlas = !show_font_atlas;
|
||||
|
||||
// Testing code: getting next and previous codepoints on provided text
|
||||
if (rl.isKeyPressed(.right)) {
|
||||
// Get next codepoint in string and move pointer
|
||||
const err = rl.getCodepointNext(text[@intCast(start)..text.len], &codepoint_size);
|
||||
if (err == '?') @panic("getCodepointNext failed");
|
||||
if (start + codepoint_size < text.len) {
|
||||
start += codepoint_size;
|
||||
} else {
|
||||
start = text.len;
|
||||
}
|
||||
} else if (rl.isKeyPressed(.left)) {
|
||||
// Get previous codepoint in string and move pointer
|
||||
const err = rl.getCodepointPrevious(text[@intCast(start)..text.len], &codepoint_size);
|
||||
if (err == '?') @panic("getCodepointNext failed");
|
||||
if (start - codepoint_size > 0) {
|
||||
start -= codepoint_size;
|
||||
} else {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawRectangle(0, 0, rl.getScreenWidth(), 70, .black);
|
||||
rl.drawText(rl.textFormat("Total codepoints contained in provided text: %i", .{codepoints_count}), 10, 10, 20, .green);
|
||||
rl.drawText(rl.textFormat("Total codepoints required for font atlas (duplicates excluded): %u", .{codepoints_no_dups_count}), 10, 40, 20, .green);
|
||||
|
||||
if (show_font_atlas) {
|
||||
// Draw generated font texture atlas containing provided codepoints
|
||||
rl.drawTexture(font.texture, 150, 100, .black);
|
||||
rl.drawRectangleLines(150, 100, font.texture.width, font.texture.height, .black);
|
||||
} else {
|
||||
// Draw provided text with loaded font, containing all required codepoint glyphs
|
||||
rl.drawTextEx(font, text, .{ .x = 160, .y = 110 }, 48, 5, .black);
|
||||
}
|
||||
|
||||
rl.drawText("Press SPACE to toggle font atlas view!", 10, rl.getScreenHeight() - 30, 20, .gray);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove codepoint duplicates if requested
|
||||
/// WARNING: This process could be a bit slow if there text to process is very long
|
||||
fn CodepointRemoveDuplicates(allocator: std.mem.Allocator, codepoints: []i32) ![:0]i32 {
|
||||
var no_dups: [:0]i32 = try allocator.allocSentinel(i32, codepoints.len, 0);
|
||||
std.mem.copyForwards(i32, no_dups, codepoints);
|
||||
|
||||
var no_dups_count: usize = no_dups.len;
|
||||
|
||||
// Remove duplicates
|
||||
var i: usize = 0;
|
||||
while (i < no_dups_count) {
|
||||
defer i += 1;
|
||||
var j: usize = i + 1;
|
||||
while (j < no_dups_count) {
|
||||
defer j += 1;
|
||||
const match = no_dups[i] == no_dups[j];
|
||||
if (match) {
|
||||
var k: usize = j;
|
||||
while (k < no_dups_count) {
|
||||
defer k += 1;
|
||||
no_dups[k] = no_dups[k + 1];
|
||||
}
|
||||
no_dups_count -= 1;
|
||||
j -= 1;
|
||||
no_dups[no_dups_count] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The size of codepointsNoDups is the same as original array but
|
||||
// only required positions are filled (codepointsNoDupsCount)
|
||||
return no_dups;
|
||||
}
|
||||
694
examples/text/draw_3d.zig
Normal file
@ -0,0 +1,694 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Draw 3d
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_draw_3d.c
|
||||
//!
|
||||
//! Example complexity rating: [★★★★] 4/4
|
||||
//!
|
||||
//! NOTE: Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set)
|
||||
//! where the texture coodinates of each quad map to the texture coordinates of the glyphs
|
||||
//! inside the font texture.
|
||||
//!
|
||||
//! A more efficient approach, i believe, would be to render the text in a render texture and
|
||||
//! map that texture to a plane and render that, or maybe a shader but my method allows more
|
||||
//! flexibility...for example to change position of each letter individually to make somethink
|
||||
//! like a wavy text effect.
|
||||
//!
|
||||
//! Special thanks to:
|
||||
//! @Nighten for the DrawTextStyle() code https://github.com/NightenDushi/Raylib_DrawTextStyle
|
||||
//! Chris Camacho (codifies - http://bedroomcoders.co.uk/) for the alpha discard shader
|
||||
//!
|
||||
//! Example originally created with raylib 3.5, last time updated with raylib 4.0
|
||||
//!
|
||||
//! Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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 Vlad Adrian (@demizdor)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
const cl = @import("codepoints_loading.zig");
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Globals
|
||||
//--------------------------------------------------------------------------------------
|
||||
const letter_boundry_size = 0.25;
|
||||
const text_max_layers = 32;
|
||||
const letter_boundry_color = rl.Color.violet;
|
||||
|
||||
var show_letter_boundry = false;
|
||||
var show_text_boundry = false;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Data Types definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Configuration structure for waving the text
|
||||
const WaveTextConfig = struct {
|
||||
waveRange: rl.Vector3,
|
||||
waveSpeed: rl.Vector3,
|
||||
waveOffset: rl.Vector3,
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.setConfigFlags(.{ .msaa_4x_hint = true, .vsync_hint = true });
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - draw 2D text in 3D");
|
||||
defer rl.closeWindow();
|
||||
|
||||
var spin = true; // Spin the camera?
|
||||
var multicolor = false; // Multicolor mode
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera: rl.Camera3D = .{
|
||||
.position = .{ .x = -10, .y = 15, .z = -10 },
|
||||
.target = .{ .x = 0, .y = 0, .z = 0 },
|
||||
.up = .{ .x = 0, .y = 1, .z = 0 },
|
||||
.fovy = 45,
|
||||
.projection = .perspective,
|
||||
};
|
||||
var camera_mode = rl.CameraMode.orbital;
|
||||
|
||||
const cube_postition = rl.Vector3{ .x = 0.0, .y = 1.0, .z = 0.0 };
|
||||
const cube_size = rl.Vector3{ .x = 2.0, .y = 2.0, .z = 2.0 };
|
||||
|
||||
// Use the default font
|
||||
|
||||
const default_font = try rl.getFontDefault();
|
||||
defer rl.unloadFont(default_font);
|
||||
var font = try rl.getFontDefault();
|
||||
defer rl.unloadFont(font);
|
||||
var font_size: f32 = 0.8;
|
||||
var fontSpacing: f32 = 0.05;
|
||||
var lineSpacing: f32 = -0.1;
|
||||
|
||||
// var tbox = rl.Vector3{};
|
||||
var layers: usize = 1;
|
||||
var quads: usize = 0;
|
||||
var layerDistance: f32 = 0.01;
|
||||
|
||||
const wcfg = WaveTextConfig{
|
||||
.waveSpeed = .{ .x = 3, .y = 3, .z = 0.5 },
|
||||
.waveOffset = .{ .x = 0.35, .y = 0.35, .z = 0.35 },
|
||||
.waveRange = .{ .x = 0.45, .y = 0.45, .z = 0.45 },
|
||||
};
|
||||
|
||||
var time: f32 = 0.0;
|
||||
|
||||
// Setup a light and dark color
|
||||
var light = rl.Color.maroon;
|
||||
var dark = rl.Color.red;
|
||||
|
||||
// Load the alpha discard shader
|
||||
const alphaDiscard = try rl.loadShader(null, "examples/text/resources/shaders/glsl330/alpha_discard.fs");
|
||||
|
||||
// Array filled with multiple random colors (when multicolor mode is set)
|
||||
var multi: [text_max_layers]rl.Color = undefined;
|
||||
|
||||
// Set the text (using markdown!)
|
||||
var text = [_:0]u8{0} ** 64;
|
||||
var fw = std.Io.Writer.fixed(text[0..]);
|
||||
_ = try fw.writeAll("Hello ~~World~~ In 3D!");
|
||||
|
||||
rl.disableCursor(); // Limit cursor to relative movement inside the window
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.updateCamera(&camera, camera_mode);
|
||||
|
||||
// Handle font files dropped
|
||||
if (rl.isFileDropped()) {
|
||||
const droppedFiles: rl.FilePathList = rl.loadDroppedFiles();
|
||||
defer rl.unloadDroppedFiles(droppedFiles); // Unload filepaths from memory
|
||||
|
||||
// NOTE: We only support first ttf file dropped
|
||||
const path: [:0]const u8 = std.mem.span(droppedFiles.paths[0]);
|
||||
if (rl.isFileExtension(path, ".ttf")) {
|
||||
rl.unloadFont(font);
|
||||
font = try rl.loadFontEx(path, @intFromFloat(font_size), null);
|
||||
} else if (rl.isFileExtension(path, ".fnt")) {
|
||||
rl.unloadFont(font);
|
||||
font = try rl.loadFont(path);
|
||||
font_size = @floatFromInt(font.baseSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Events
|
||||
if (rl.isKeyPressed(.f1)) show_letter_boundry = !show_letter_boundry;
|
||||
if (rl.isKeyPressed(.f2)) show_text_boundry = !show_text_boundry;
|
||||
if (rl.isKeyPressed(.f3)) {
|
||||
// Handle camera change
|
||||
spin = !spin;
|
||||
// we need to reset the camera when changing modes
|
||||
camera = rl.Camera3D{
|
||||
.target = .{ .x = 0.0, .y = 0.0, .z = 0.0 }, // Camera looking at point
|
||||
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 }, // Camera up vector (rotation towards target)
|
||||
.fovy = 45.0, // Camera field-of-view Y
|
||||
.projection = .perspective, // Camera mode type
|
||||
.position = .{ .x = 10.0, .y = 10.0, .z = -10.0 }, // Camera position
|
||||
};
|
||||
camera_mode = .free;
|
||||
|
||||
if (spin) {
|
||||
camera_mode = .orbital;
|
||||
camera.position = .{ .x = -10.0, .y = 15.0, .z = -10.0 }; // Camera position
|
||||
}
|
||||
}
|
||||
|
||||
// Handle clicking the cube
|
||||
if (rl.isMouseButtonPressed(.left)) {
|
||||
const ray = rl.getScreenToWorldRay(rl.getMousePosition(), camera);
|
||||
|
||||
// Check collision between ray and box
|
||||
const collision = rl.getRayCollisionBox(ray, .{ .max = .{ .x = cube_postition.x - cube_size.x / 2, .y = cube_postition.y - cube_size.y / 2, .z = cube_postition.z - cube_size.z / 2 }, .min = .{ .x = cube_postition.x + cube_size.x / 2, .y = cube_postition.y + cube_size.y / 2, .z = cube_postition.z + cube_size.z / 2 } });
|
||||
if (collision.hit) {
|
||||
// Generate new random colors
|
||||
light = generateRandomColor(0.5, 0.78);
|
||||
dark = generateRandomColor(0.4, 0.58);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle text layers changes
|
||||
if (rl.isKeyPressed(.home)) {
|
||||
if (layers > 1) layers -= 1;
|
||||
} else if (rl.isKeyPressed(.end)) {
|
||||
if (layers < text_max_layers) layers += 1;
|
||||
}
|
||||
|
||||
// Handle text changes
|
||||
const key_pressed = rl.getKeyPressed();
|
||||
switch (key_pressed) {
|
||||
.left => font_size -= 0.5,
|
||||
.right => font_size += 0.5,
|
||||
.up => fontSpacing -= 0.1,
|
||||
.down => fontSpacing += 0.1,
|
||||
.page_up => lineSpacing -= 0.1,
|
||||
.page_down => lineSpacing += 0.1,
|
||||
.insert => layerDistance -= 0.001,
|
||||
.delete => layerDistance += 0.001,
|
||||
.tab => {
|
||||
multicolor = !multicolor; // Enable /disable multicolor mode
|
||||
|
||||
if (multicolor) {
|
||||
// Fill color array with random colors
|
||||
for (0..text_max_layers) |i| {
|
||||
multi[i] = generateRandomColor(0.5, 0.8);
|
||||
multi[i].a = @intCast(rl.getRandomValue(0, 255));
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
// Handle text input
|
||||
const ch = rl.getCharPressed();
|
||||
switch (key_pressed) {
|
||||
.backspace => {
|
||||
const len = rl.textLength(&text);
|
||||
if (len > 0) text[len - 1] = 0;
|
||||
},
|
||||
.enter => {
|
||||
const len = rl.textLength(&text);
|
||||
if (len < text.len - 1) {
|
||||
text[len] = '\n';
|
||||
text[len + 1] = 0;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
// append only printable chars
|
||||
const len = rl.textLength(&text);
|
||||
if (len < text.len) {
|
||||
text[len] = @intCast(ch);
|
||||
text[len + 1] = 0;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Measure 3D text so we can center it
|
||||
const tbox = measureTextWave3D(font, &text, font_size, fontSpacing, lineSpacing);
|
||||
|
||||
quads = 0; // Reset quad counter
|
||||
time += rl.getFrameTime(); // Update timer needed by `DrawTextWave3D()`
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
{
|
||||
rl.beginMode3D(camera);
|
||||
defer rl.endMode3D();
|
||||
rl.drawCubeV(cube_postition, cube_size, dark);
|
||||
rl.drawCubeWires(cube_postition, 2.1, 2.1, 2.1, light);
|
||||
|
||||
rl.drawGrid(10, 2.0);
|
||||
|
||||
// Use a shader to handle the depth buffer issue with transparent textures
|
||||
// NOTE: more info at https://bedroomcoders.co.uk/posts/198
|
||||
rl.beginShaderMode(alphaDiscard);
|
||||
defer rl.endShaderMode();
|
||||
|
||||
// Draw the 3D text above the red cube
|
||||
{
|
||||
rl.gl.rlPushMatrix();
|
||||
defer rl.gl.rlPopMatrix();
|
||||
rl.gl.rlRotatef(90.0, 1.0, 0.0, 0.0);
|
||||
rl.gl.rlRotatef(90.0, 0.0, 0.0, -1.0);
|
||||
|
||||
for (0..layers) |i| {
|
||||
var clr = light;
|
||||
if (multicolor) clr = multi[i];
|
||||
drawTextWave3D(font, &text, .{
|
||||
.x = -tbox.x / 2.0,
|
||||
.y = layerDistance * @as(f32, @floatFromInt(i)),
|
||||
.z = -4.5,
|
||||
}, font_size, fontSpacing, lineSpacing, true, wcfg, time, clr);
|
||||
}
|
||||
|
||||
// Draw the text boundry if set
|
||||
if (show_text_boundry) rl.drawCubeWiresV(.{ .x = 0.0, .y = 0.0, .z = -4.5 + tbox.z / 2 }, tbox, dark);
|
||||
}
|
||||
|
||||
// Don't draw the letter boundries for the 3D text below
|
||||
const slb = show_letter_boundry;
|
||||
show_letter_boundry = false;
|
||||
defer show_letter_boundry = slb;
|
||||
|
||||
// Draw 3D options (use default font)
|
||||
//-------------------------------------------------------------------------
|
||||
{
|
||||
rl.gl.rlPushMatrix();
|
||||
defer rl.gl.rlPopMatrix();
|
||||
rl.gl.rlRotatef(180.0, 0.0, 1.0, 0.0);
|
||||
|
||||
// In the C version of this library we use rl.textFormat to format our text. This doesn't play nice Zig's slice strings.
|
||||
// You might be able to make it work but I switched to using the std.fmt interfaces which are more ergonomic in zig anyways.
|
||||
// I use an oversized fixed buffer, but you could use an allocator to get a more robust solution
|
||||
|
||||
var text_buf = [_:0]u8{0} ** 64;
|
||||
|
||||
var opt = try std.fmt.bufPrintZ(&text_buf, "< SIZE: {d} >", .{font_size});
|
||||
var m = rl.measureTextEx(default_font, opt, 0.8, 0.1);
|
||||
var pos = rl.Vector3{ .x = -m.x / 2.0, .y = 0.01, .z = 2.0 };
|
||||
drawText3D(default_font, opt, pos, 0.8, 0.1, 0.0, false, .blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
opt = try std.fmt.bufPrintZ(&text_buf, "< SPACING: {d} >", .{fontSpacing});
|
||||
quads += std.mem.len(opt.ptr);
|
||||
m = rl.measureTextEx(default_font, opt, 0.8, 0.1);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt, pos, 0.8, 0.1, 0.0, false, .blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
opt = try std.fmt.bufPrintZ(&text_buf, "< LINE: {d} >", .{lineSpacing});
|
||||
quads += std.mem.len(opt.ptr);
|
||||
m = rl.measureTextEx(default_font, opt, 0.8, 0.1);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt, pos, 0.8, 0.1, 0.0, false, .blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
opt = try std.fmt.bufPrintZ(&text_buf, "< LBOX: {s} >", .{if (slb) "ON" else "OFF"});
|
||||
quads += std.mem.len(opt.ptr);
|
||||
m = rl.measureTextEx(default_font, opt, 0.8, 0.1);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt, pos, 0.8, 0.1, 0.0, false, .red);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
opt = try std.fmt.bufPrintZ(&text_buf, "< TBOX: {s} >", .{if (show_text_boundry) "ON" else "OFF"});
|
||||
quads += std.mem.len(opt.ptr);
|
||||
m = rl.measureTextEx(default_font, opt, 0.8, 0.1);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt, pos, 0.8, 0.1, 0.0, false, .red);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
opt = try std.fmt.bufPrintZ(&text_buf, "< LAYER DISTANCE: {d} >", .{layerDistance});
|
||||
quads += std.mem.len(opt.ptr);
|
||||
m = rl.measureTextEx(default_font, opt, 0.8, 0.1);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt, pos, 0.8, 0.1, 0.0, false, .dark_purple);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Draw 3D info text (use default font)
|
||||
//-------------------------------------------------------------------------
|
||||
const opt1 = "All the text displayed here is in 3D";
|
||||
quads += opt1.len;
|
||||
var m = rl.measureTextEx(default_font, opt1, 1.0, 0.05);
|
||||
var pos = rl.Vector3{ .x = -m.x / 2.0, .y = 0.01, .z = 2.0 };
|
||||
drawText3D(default_font, opt1, pos, 1.0, 0.05, 0.0, false, .dark_blue);
|
||||
pos.z += 1.5 + m.y;
|
||||
|
||||
const opt2 = "press [Left]/[Right] to change the font size";
|
||||
quads += opt2.len;
|
||||
m = rl.measureTextEx(default_font, opt2, 0.6, 0.05);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt2, pos, 0.6, 0.05, 0.0, false, .dark_blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
const opt3 = "press [Up]/[Down] to change the font spacing";
|
||||
quads += opt3.len;
|
||||
m = rl.measureTextEx(default_font, opt3, 0.6, 0.05);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt3, pos, 0.6, 0.05, 0.0, false, .dark_blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
const opt4 = "press [PgUp]/[PgDown] to change the line spacing";
|
||||
quads += opt4.len;
|
||||
m = rl.measureTextEx(default_font, opt4, 0.6, 0.05);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt4, pos, 0.6, 0.05, 0.0, false, .dark_blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
const opt5 = "press [F1] to toggle the letter boundry";
|
||||
quads += opt5.len;
|
||||
m = rl.measureTextEx(default_font, opt5, 0.6, 0.05);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt5, pos, 0.6, 0.05, 0.0, false, .dark_blue);
|
||||
pos.z += 0.5 + m.y;
|
||||
|
||||
const opt6 = "press [F2] to toggle the text boundry";
|
||||
quads += opt6.len;
|
||||
m = rl.measureTextEx(default_font, opt6, 0.6, 0.05);
|
||||
pos.x = -m.x / 2.0;
|
||||
drawText3D(default_font, opt6, pos, 0.6, 0.05, 0.0, false, .dark_blue);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
// Draw 2D info text & stats
|
||||
//-------------------------------------------------------------------------
|
||||
rl.drawText("Drag & drop a font file to change the font!\nType something, see what happens!\n\nPress [F3] to toggle the camera", 10, 35, 10, .black);
|
||||
|
||||
quads += rl.textLength(&text) * 2 * layers;
|
||||
var buf = [_:0]u8{0} ** 70;
|
||||
const tmp = std.fmt.bufPrintZ(&buf, "{} layer(s) | {s} camera | {} quads ({} verts)", .{
|
||||
layers,
|
||||
if (spin) "ORBITAL" else "FREE",
|
||||
quads,
|
||||
quads * 4,
|
||||
}) catch unreachable;
|
||||
var width = rl.measureText(tmp, 10);
|
||||
rl.drawText(tmp, screen_width - 20 - width, 10, 10, .dark_green);
|
||||
|
||||
const tmp2 = "[Home]/[End] to add/remove 3D text layers";
|
||||
width = rl.measureText(tmp2, 10);
|
||||
rl.drawText(tmp2, screen_width - 20 - width, 25, 10, .dark_gray);
|
||||
|
||||
const tmp3 = "[Insert]/[Delete] to increase/decrease distance between layers";
|
||||
width = rl.measureText(tmp3, 10);
|
||||
rl.drawText(tmp3, screen_width - 20 - width, 40, 10, .dark_gray);
|
||||
|
||||
const tmp4 = "click the [CUBE] for a random color";
|
||||
width = rl.measureText(tmp4, 10);
|
||||
rl.drawText(tmp4, screen_width - 20 - width, 55, 10, .dark_gray);
|
||||
|
||||
const tmp5 = "[Tab] to toggle multicolor mode";
|
||||
width = rl.measureText(tmp5, 10);
|
||||
rl.drawText(tmp5, screen_width - 20 - width, 70, 10, .dark_gray);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
rl.drawFPS(10, 10);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module Functions Definitions
|
||||
//--------------------------------------------------------------------------------------
|
||||
/// Draw codepoint at specified position in 3D space
|
||||
fn drawTextCodepoint3D(font: rl.Font, codepoint: i32, start_position: rl.Vector3, fontSize: f32, backface: bool, tint: rl.Color) void {
|
||||
// Character index position in sprite font
|
||||
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
|
||||
const index: usize = @intCast(rl.getGlyphIndex(font, codepoint));
|
||||
const scale: f32 = fontSize / @as(f32, @floatFromInt(font.baseSize));
|
||||
const glyphPadding: f32 = @floatFromInt(font.glyphPadding);
|
||||
|
||||
// Character destination rectangle on screen
|
||||
// NOTE: We consider charsPadding on drawing
|
||||
const position = rl.Vector3{
|
||||
.x = start_position.x + @as(f32, @floatFromInt(font.glyphs[index].offsetX - font.glyphPadding)) * scale,
|
||||
.y = start_position.y,
|
||||
.z = start_position.z + @as(f32, @floatFromInt(font.glyphs[index].offsetY - font.glyphPadding)) * scale,
|
||||
};
|
||||
|
||||
// Character source rectangle from font texture atlas
|
||||
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
||||
const srcRec = rl.Rectangle{
|
||||
.x = font.recs[index].x - glyphPadding,
|
||||
.y = font.recs[index].y - glyphPadding,
|
||||
.width = font.recs[index].width + 2.0 * glyphPadding,
|
||||
.height = font.recs[index].height + 2.0 * glyphPadding,
|
||||
};
|
||||
|
||||
const width: f32 = (font.recs[index].width + 2.0 * glyphPadding) * scale;
|
||||
const height: f32 = (font.recs[index].height + 2.0 * glyphPadding) * scale;
|
||||
|
||||
if (font.texture.id > 0) {
|
||||
const x = 0.0;
|
||||
const y = 0.0;
|
||||
const z = 0.0;
|
||||
|
||||
// normalized texture coordinates of the glyph inside the font texture (0.0f -> 1.0f)
|
||||
const tx: f32 = srcRec.x / @as(f32, @floatFromInt(font.texture.width));
|
||||
const ty: f32 = srcRec.y / @as(f32, @floatFromInt(font.texture.height));
|
||||
const tw: f32 = (srcRec.x + srcRec.width) / @as(f32, @floatFromInt(font.texture.width));
|
||||
const th: f32 = (srcRec.y + srcRec.height) / @as(f32, @floatFromInt(font.texture.height));
|
||||
|
||||
if (show_letter_boundry) rl.drawCubeWiresV(.{ .x = position.x + width / 2, .y = position.y, .z = position.z + height / 2 }, .{ .x = width, .y = letter_boundry_size, .z = height }, letter_boundry_color);
|
||||
|
||||
//not entirely sure if this has a side effect, its in the original, so I'm not touching it
|
||||
_ = rl.gl.rlCheckRenderBatchLimit(if (backface) 8 else 4);
|
||||
rl.gl.rlSetTexture(font.texture.id);
|
||||
defer rl.gl.rlSetTexture(0);
|
||||
|
||||
rl.gl.rlPushMatrix();
|
||||
defer rl.gl.rlPopMatrix();
|
||||
rl.gl.rlTranslatef(position.x, position.y, position.z);
|
||||
|
||||
rl.gl.rlBegin(rl.gl.rl_quads);
|
||||
defer rl.gl.rlEnd();
|
||||
rl.gl.rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
// Front Face
|
||||
rl.gl.rlNormal3f(0.0, 1.0, 0.0); // Normal Pointing Up
|
||||
rl.gl.rlTexCoord2f(tx, ty);
|
||||
rl.gl.rlVertex3f(x, y, z); // Top Left Of The Texture and Quad
|
||||
rl.gl.rlTexCoord2f(tx, th);
|
||||
rl.gl.rlVertex3f(x, y, z + height); // Bottom Left Of The Texture and Quad
|
||||
rl.gl.rlTexCoord2f(tw, th);
|
||||
rl.gl.rlVertex3f(x + width, y, z + height); // Bottom Right Of The Texture and Quad
|
||||
rl.gl.rlTexCoord2f(tw, ty);
|
||||
rl.gl.rlVertex3f(x + width, y, z); // Top Right Of The Texture and Quad
|
||||
|
||||
if (backface) {
|
||||
// Back Face
|
||||
rl.gl.rlNormal3f(0.0, -1.0, 0.0); // Normal Pointing Down
|
||||
rl.gl.rlTexCoord2f(tx, ty);
|
||||
rl.gl.rlVertex3f(x, y, z); // Top Right Of The Texture and Quad
|
||||
rl.gl.rlTexCoord2f(tw, ty);
|
||||
rl.gl.rlVertex3f(x + width, y, z); // Top Left Of The Texture and Quad
|
||||
rl.gl.rlTexCoord2f(tw, th);
|
||||
rl.gl.rlVertex3f(x + width, y, z + height); // Bottom Left Of The Texture and Quad
|
||||
rl.gl.rlTexCoord2f(tx, th);
|
||||
rl.gl.rlVertex3f(x, y, z + height); // Bottom Right Of The Texture and Quad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a 2D text in 3D space
|
||||
fn drawText3D(font: rl.Font, text: [:0]const u8, position: rl.Vector3, font_size: f32, font_spacing: f32, line_spacing: f32, backface: bool, tint: rl.Color) void {
|
||||
const length = rl.textLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
var text_offset_y: f32 = 0.0; // Offset between lines (on line break '\n')
|
||||
var text_offset_x: f32 = 0.0; // Offset X to next character to draw
|
||||
|
||||
const scale = font_size / @as(f32, @floatFromInt(font.baseSize));
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < length) {
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
var codepoint_byte_count: i32 = 0;
|
||||
const codepoint = rl.getCodepoint(text[i..], &codepoint_byte_count);
|
||||
const index: usize = @intCast(rl.getGlyphIndex(font, codepoint));
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f) codepoint_byte_count = 1;
|
||||
|
||||
if (codepoint == '\n') {
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
text_offset_y += font_size + line_spacing;
|
||||
text_offset_x = 0.0;
|
||||
} else {
|
||||
if ((codepoint != ' ') and (codepoint != '\t')) {
|
||||
drawTextCodepoint3D(font, codepoint, .{
|
||||
.x = position.x + text_offset_x,
|
||||
.y = position.y,
|
||||
.z = position.z + text_offset_y,
|
||||
}, font_size, backface, tint);
|
||||
}
|
||||
|
||||
if (font.glyphs[index].advanceX == 0) {
|
||||
text_offset_x += font.recs[index].width * scale + font_spacing;
|
||||
} else {
|
||||
text_offset_x += @as(f32, @floatFromInt(font.glyphs[index].advanceX)) * scale + font_spacing;
|
||||
}
|
||||
}
|
||||
|
||||
i += @intCast(codepoint_byte_count); // Move text bytes counter to next codepoint
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a 2D text in 3D space and wave the parts that start with `~~` and end with `~~`.
|
||||
/// This is a modified version of the original code by @Nighten found here https://github.com/NightenDushi/Raylib_DrawTextStyle
|
||||
fn drawTextWave3D(font: rl.Font, text: [:0]const u8, position: rl.Vector3, fontSize: f32, fontSpacing: f32, lineSpacing: f32, backface: bool, config: WaveTextConfig, time: f32, tint: rl.Color) void {
|
||||
const length = rl.textLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
var text_offset_x: f32 = 0.0; // Offset X to next character to draw
|
||||
var text_offset_y: f32 = 0.0; // Offset between lines (on line break '\n')
|
||||
|
||||
const scale = fontSize / @as(f32, @floatFromInt(font.baseSize));
|
||||
|
||||
var wave = false;
|
||||
|
||||
var i: usize = 0;
|
||||
var k: usize = 0;
|
||||
while (i < length) : (k += 1) {
|
||||
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
var codepointByteCount: i32 = 0;
|
||||
const codepoint = rl.getCodepoint(text[i..], &codepointByteCount);
|
||||
const index: usize = @intCast(rl.getGlyphIndex(font, codepoint));
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f) codepointByteCount = 1;
|
||||
|
||||
switch (codepoint) {
|
||||
'\n' => {
|
||||
// NOTE: Fixed line spacing of 1.5 line-height
|
||||
// TODO: Support custom line spacing defined by user
|
||||
text_offset_y += fontSize + lineSpacing;
|
||||
text_offset_x = 0.0;
|
||||
k = 0;
|
||||
},
|
||||
'~' => {
|
||||
if (rl.getCodepoint(text[i + 1 ..], &codepointByteCount) == '~') {
|
||||
codepointByteCount += 1;
|
||||
wave = !wave;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
if ((codepoint != ' ') and (codepoint != '\t')) {
|
||||
var pos = position;
|
||||
if (wave) // Apply the wave effect
|
||||
{
|
||||
const kF: f32 = @floatFromInt(k);
|
||||
pos.x += std.math.sin(time * config.waveSpeed.x - kF * config.waveOffset.x) * config.waveRange.x;
|
||||
pos.y += std.math.sin(time * config.waveSpeed.y - kF * config.waveOffset.y) * config.waveRange.y;
|
||||
pos.z += std.math.sin(time * config.waveSpeed.z - kF * config.waveOffset.z) * config.waveRange.z;
|
||||
}
|
||||
|
||||
drawTextCodepoint3D(font, codepoint, .{
|
||||
.x = pos.x + text_offset_x,
|
||||
.y = pos.y,
|
||||
.z = pos.z + text_offset_y,
|
||||
}, fontSize, backface, tint);
|
||||
}
|
||||
|
||||
if (font.glyphs[index].advanceX == 0) {
|
||||
text_offset_x += font.recs[index].width * scale + fontSpacing;
|
||||
} else {
|
||||
text_offset_x += @as(f32, @floatFromInt(font.glyphs[index].advanceX)) * scale + fontSpacing;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
i += @intCast(codepointByteCount); // Move text bytes counter to next codepoint
|
||||
}
|
||||
}
|
||||
|
||||
/// Measure a text in 3D ignoring the `~~` chars.
|
||||
fn measureTextWave3D(font: rl.Font, text: [:0]const u8, fontSize: f32, fontSpacing: f32, lineSpacing: f32) rl.Vector3 {
|
||||
const len = rl.textLength(text);
|
||||
var temp_len: usize = 0; // Used to count longer text line num chars
|
||||
var len_counter: usize = 0;
|
||||
|
||||
var temp_text_width: f32 = 0.0; // Used to count longer text line width
|
||||
|
||||
const scale = fontSize / @as(f32, @floatFromInt(font.baseSize));
|
||||
var text_height = scale;
|
||||
var text_width: f32 = 0.0;
|
||||
|
||||
var letter: i32 = 0; // Current character
|
||||
var index: usize = 0; // Index position in sprite font
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < len) {
|
||||
var next: i32 = 0;
|
||||
letter = rl.getCodepoint(text[i..], &next);
|
||||
index = @intCast(rl.getGlyphIndex(font, letter));
|
||||
|
||||
// NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1
|
||||
if (letter == 0x3f) next = 1;
|
||||
i += @intCast(next);
|
||||
|
||||
if (letter != '\n') {
|
||||
if (letter == '~' and rl.getCodepoint(text[i + 1 ..], &next) == '~') {
|
||||
i += 1;
|
||||
} else {
|
||||
len_counter += 1;
|
||||
if (font.glyphs[index].advanceX != 0) {
|
||||
text_width += @as(f32, @floatFromInt(font.glyphs[index].advanceX)) * scale;
|
||||
} else text_width += (font.recs[index].width + @as(f32, @floatFromInt(font.glyphs[index].offsetX))) * scale;
|
||||
}
|
||||
} else {
|
||||
if (temp_text_width < text_width) temp_text_width = text_width;
|
||||
len_counter = 0;
|
||||
text_width = 0.0;
|
||||
text_height += fontSize + lineSpacing;
|
||||
}
|
||||
|
||||
if (temp_len < len_counter) temp_len = len_counter;
|
||||
}
|
||||
|
||||
if (temp_text_width < text_width) temp_text_width = text_width;
|
||||
|
||||
const vec = rl.Vector3{
|
||||
.x = temp_text_width + (@as(f32, @floatFromInt(temp_len - 1)) * fontSpacing), // Adds chars spacing to measure
|
||||
.y = 0.25,
|
||||
.z = text_height,
|
||||
};
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// Generates a nice color with a random hue
|
||||
fn generateRandomColor(s: f32, v: f32) rl.Color {
|
||||
const Phi: f32 = 0.618033988749895; // Golden ratio conjugate
|
||||
var h: f32 = @floatFromInt(rl.getRandomValue(0, 360));
|
||||
h = std.math.mod(f32, (h + h * Phi), 360.0) catch 0;
|
||||
return rl.colorFromHSV(h, s, v);
|
||||
}
|
||||
143
examples/text/font_filters.zig
Normal file
@ -0,0 +1,143 @@
|
||||
//!*******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Font filters
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_font_filters.c
|
||||
//!
|
||||
//! Example complexity rating: [★★☆☆] 2/4
|
||||
//!
|
||||
//! NOTE: After font loading, font texture atlas filter could be configured for a softer
|
||||
//! display of the font when scaling it to different sizes, that way, it's not required
|
||||
//! to generate multiple fonts at multiple sizes (as long as the scaling is not very different)
|
||||
//!
|
||||
//! Example originally created with raylib 1.3, last time updated with raylib 4.2
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - font filters");
|
||||
defer rl.closeWindow();
|
||||
|
||||
const msg = "Loaded Font";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
// TTF Font loading with custom generation parameters
|
||||
var font = try rl.loadFontEx("examples/text/resources/KAISG.ttf", 96, null);
|
||||
|
||||
// Generate mipmap levels to use trilinear filtering
|
||||
// NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR
|
||||
rl.genTextureMipmaps(&font.texture);
|
||||
|
||||
var font_size: f32 = @floatFromInt(font.baseSize);
|
||||
var fontPosition = rl.Vector2{ .x = 40.0, .y = screen_height / 2.0 - 80.0 };
|
||||
var text_size = rl.Vector2{ .x = 0.0, .y = 0.0 };
|
||||
|
||||
// Setup texture scaling filter
|
||||
rl.setTextureFilter(font.texture, .point);
|
||||
var currentFontFilter: i32 = 0; // TEXTURE_FILTER_POINT
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
font_size += rl.getMouseWheelMove() * 4.0;
|
||||
|
||||
// Choose font texture filter method
|
||||
const key_pressed = rl.getKeyPressed();
|
||||
switch (key_pressed) {
|
||||
.one => {
|
||||
rl.setTextureFilter(font.texture, .point);
|
||||
currentFontFilter = 0;
|
||||
},
|
||||
.two => {
|
||||
rl.setTextureFilter(font.texture, .bilinear);
|
||||
currentFontFilter = 1;
|
||||
},
|
||||
.three => {
|
||||
// NOTE: Trilinear filter won't be noticed on 2D drawing
|
||||
rl.setTextureFilter(font.texture, .trilinear);
|
||||
currentFontFilter = 2;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
text_size = rl.measureTextEx(font, msg, font_size, 0);
|
||||
|
||||
if (rl.isKeyDown(.left)) {
|
||||
fontPosition.x -= 10;
|
||||
} else if (rl.isKeyDown(.right)) {
|
||||
fontPosition.x += 10;
|
||||
}
|
||||
|
||||
// Load a dropped TTF file dynamically (at current fontSize)
|
||||
if (rl.isFileDropped()) {
|
||||
const dropped_files: rl.FilePathList = rl.loadDroppedFiles();
|
||||
defer rl.unloadDroppedFiles(dropped_files); // Unload filepaths from memory
|
||||
|
||||
// NOTE: We only support first ttf file dropped
|
||||
const path: [:0]const u8 = std.mem.span(dropped_files.paths[0]);
|
||||
if (rl.isFileExtension(path, ".ttf")) {
|
||||
rl.unloadFont(font);
|
||||
font = try rl.loadFontEx(path, @intFromFloat(font_size), null);
|
||||
} else if (rl.isFileExtension(path, ".fnt")) {
|
||||
rl.unloadFont(font);
|
||||
font = try rl.loadFont(path);
|
||||
font_size = @floatFromInt(font.baseSize);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("Use mouse wheel to change font size", 20, 20, 10, .gray);
|
||||
rl.drawText("Use KEY_RIGHT and KEY_LEFT to move text", 20, 40, 10, .gray);
|
||||
rl.drawText("Use 1, 2, 3 to change texture filter", 20, 60, 10, .gray);
|
||||
rl.drawText("Drop a new TTF font for dynamic loading", 20, 80, 10, .dark_gray);
|
||||
|
||||
rl.drawTextEx(font, msg, fontPosition, font_size, 0, .black);
|
||||
|
||||
// TODO: It seems texSize measurement is not accurate due to chars offsets...
|
||||
//DrawRectangleLines(fontPosition.x, fontPosition.y, textSize.x, textSize.y, RED);
|
||||
|
||||
rl.drawRectangle(0, screen_height - 80, screen_width, 80, .light_gray);
|
||||
rl.drawText(rl.textFormat("Font size: %02.02f", .{font_size}), 20, screen_height - 50, 10, .dark_gray);
|
||||
rl.drawText(rl.textFormat("Text size: [%02.02f, %02.02f]", .{ text_size.x, text_size.y }), 20, screen_height - 30, 10, .dark_gray);
|
||||
rl.drawText("CURRENT TEXTURE FILTER:", 250, 400, 20, .gray);
|
||||
|
||||
switch (currentFontFilter) {
|
||||
0 => rl.drawText("POINT", 570, 400, 20, .black),
|
||||
1 => rl.drawText("BILINEAR", 570, 400, 20, .black),
|
||||
2 => rl.drawText("TRILINEAR", 570, 400, 20, .black),
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
95
examples/text/font_loading.zig
Normal file
@ -0,0 +1,95 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Font loading
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_font_loading.c
|
||||
//!
|
||||
//! Example complexity rating: [★☆☆☆] 1/4
|
||||
//!
|
||||
//! NOTE: raylib can load fonts from multiple input file formats:
|
||||
//!
|
||||
//! - TTF/OTF > Sprite font atlas is generated on loading, user can configure
|
||||
//! some of the generation parameters (size, characters to include)
|
||||
//! - BMFonts > Angel code font fileformat, sprite font image must be provided
|
||||
//! together with the .fnt file, font generation cna not be configured
|
||||
//! - XNA Spritefont > Sprite font image, following XNA Spritefont conventions,
|
||||
//! Characters in image must follow some spacing and order rules
|
||||
//!
|
||||
//! Example originally created with raylib 1.4, last time updated with raylib 3.0
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - font loading");
|
||||
defer rl.closeWindow();
|
||||
|
||||
// Define characters to draw
|
||||
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
||||
const msg = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
||||
const font_bm = try rl.loadFont("examples/text/resources/pixantiqua.fnt");
|
||||
defer rl.unloadFont(font_bm);
|
||||
|
||||
// TTF font : Font data and atlas are generated directly from TTF
|
||||
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
||||
const font_ttf = try rl.loadFontEx("examples/text/resources/pixantiqua.ttf", 32, null);
|
||||
defer rl.unloadFont(font_ttf);
|
||||
|
||||
rl.setTextLineSpacing(16); // Set line spacing for multiline text (when line breaks are included '\n')
|
||||
|
||||
var use_ttf = false;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyDown(.space)) {
|
||||
use_ttf = true;
|
||||
} else {
|
||||
use_ttf = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("Hold SPACE to use TTF generated font", 20, 20, 20, .light_gray);
|
||||
|
||||
if (!use_ttf) {
|
||||
rl.drawTextEx(font_bm, msg, .{ .x = 20.0, .y = 100.0 }, @floatFromInt(font_bm.baseSize), 2, .maroon);
|
||||
rl.drawText("Using BMFont (Angelcode) imported", 20, rl.getScreenHeight() - 30, 20, .gray);
|
||||
} else {
|
||||
rl.drawTextEx(font_ttf, msg, .{ .x = 20.0, .y = 100.0 }, @floatFromInt(font_ttf.baseSize), 2, .lime);
|
||||
rl.drawText("Using TTF font generated", 20, rl.getScreenHeight() - 30, 20, .gray);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
132
examples/text/font_sdf.zig
Normal file
@ -0,0 +1,132 @@
|
||||
//!*******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Font SDF loading
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_font_sdf.c
|
||||
//!
|
||||
//! Example complexity rating: [★★★☆] 3/4
|
||||
//!
|
||||
//! Example originally created with raylib 1.3, last time updated with raylib 4.0
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const std = @import("std");
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - SDF fonts");
|
||||
defer rl.closeWindow();
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
const msg = "Signed Distance Fields";
|
||||
|
||||
// Loading file to memory
|
||||
const font_default = try rl.loadFontEx("examples/text/resources/anonymous_pro_bold.ttf", 16, null);
|
||||
defer font_default.unload();
|
||||
var font_sdf: rl.Font = font_default;
|
||||
defer font_sdf.unload();
|
||||
{
|
||||
// SDF font generation from TTF font
|
||||
const file_data = try rl.loadFileData("examples/text/resources/anonymous_pro_bold.ttf");
|
||||
defer rl.unloadFileData(file_data); // Free memory from loaded file
|
||||
|
||||
font_sdf = .{
|
||||
.baseSize = 16,
|
||||
.glyphCount = 95,
|
||||
.glyphPadding = 0,
|
||||
.glyphs = @ptrCast(try rl.loadFontData(@ptrCast(file_data), 16, null, .sdf)),
|
||||
.texture = undefined,
|
||||
.recs = undefined,
|
||||
};
|
||||
const atlas_image, const atlas_recs = try rl.genImageFontAtlas(font_sdf.glyphs[0..@intCast(font_sdf.glyphCount)], font_sdf.baseSize, 0, 1);
|
||||
defer atlas_image.unload();
|
||||
font_sdf.texture = try rl.loadTextureFromImage(atlas_image);
|
||||
font_sdf.recs = @ptrCast(atlas_recs);
|
||||
}
|
||||
|
||||
// Load SDF required shader (we use default vertex shader)
|
||||
const shader = try rl.loadShader(null, "examples/text/resources/shaders/glsl330/sdf.fs");
|
||||
defer rl.unloadShader(shader);
|
||||
rl.setTextureFilter(font_sdf.texture, .bilinear); // Required for SDF font
|
||||
|
||||
var font_position = rl.Vector2{ .x = 40, .y = @as(f32, @floatFromInt(screen_height)) / 2.0 - 50 };
|
||||
var text_size = rl.Vector2{ .x = 0.0, .y = 0.0 };
|
||||
var font_size: f32 = 16.0;
|
||||
var current_font: i32 = 0; // 0 - fontDefault, 1 - fontSDF
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
font_size += rl.getMouseWheelMove() * 8.0;
|
||||
|
||||
if (font_size < 6) font_size = 6;
|
||||
|
||||
if (rl.isKeyDown(.space)) {
|
||||
current_font = 1;
|
||||
} else {
|
||||
current_font = 0;
|
||||
}
|
||||
|
||||
if (current_font == 0) {
|
||||
text_size = rl.measureTextEx(font_default, msg, font_size, 0);
|
||||
} else {
|
||||
text_size = rl.measureTextEx(font_sdf, msg, font_size, 0);
|
||||
}
|
||||
|
||||
font_position.x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2 - text_size.x / 2;
|
||||
font_position.y = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2 - text_size.y / 2 + 80;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
if (current_font == 1) {
|
||||
// NOTE: SDF fonts require a custom SDf shader to compute fragment color
|
||||
rl.beginShaderMode(shader); // Activate SDF font shader
|
||||
rl.drawTextEx(font_sdf, msg, font_position, font_size, 0, .black);
|
||||
rl.endShaderMode(); // Activate our default shader for next drawings
|
||||
|
||||
rl.drawTexture(font_sdf.texture, 10, 10, .black);
|
||||
} else {
|
||||
rl.drawTextEx(font_default, msg, font_position, font_size, 0, .black);
|
||||
rl.drawTexture(font_default.texture, 10, 10, .black);
|
||||
}
|
||||
|
||||
if (current_font == 1) {
|
||||
rl.drawText("SDF!", 320, 20, 80, .red);
|
||||
} else {
|
||||
rl.drawText("default font", 315, 40, 30, .gray);
|
||||
}
|
||||
|
||||
rl.drawText("FONT SIZE: 16.0", rl.getScreenWidth() - 240, 20, 20, .dark_gray);
|
||||
rl.drawText(rl.textFormat("RENDER SIZE: %02.02f", .{font_size}), rl.getScreenWidth() - 240, 50, 20, .dark_gray);
|
||||
rl.drawText("Use MOUSE WHEEL to SCALE TEXT!", rl.getScreenWidth() - 240, 90, 10, .dark_gray);
|
||||
rl.drawText("HOLD SPACE to USE SDF FONT VERSION!", 340, rl.getScreenHeight() - 30, 20, .maroon);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
94
examples/text/font_spritefont.zig
Normal file
@ -0,0 +1,94 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Sprite font loading
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_font_spritefont.c
|
||||
//!
|
||||
//! Example complexity rating: [★☆☆☆] 1/4
|
||||
//!
|
||||
//! NOTE: Sprite fonts should be generated following this conventions:
|
||||
//!
|
||||
//! - Characters must be ordered starting with character 32 (Space)
|
||||
//! - Every character must be contained within the same Rectangle height
|
||||
//! - Every character and every line must be separated by the same distance (margin/padding)
|
||||
//! - Rectangles must be defined by a MAGENTA color background
|
||||
//!
|
||||
//! Following those constraints, a font can be provided just by an image,
|
||||
//! this is quite handy to avoid additional font descriptor files (like BMFonts use).
|
||||
//!
|
||||
//! Example originally created with raylib 1.0, last time updated with raylib 1.0
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const rl = @import("raylib");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - sprite font loading");
|
||||
defer rl.closeWindow();
|
||||
|
||||
const msg1 = "THIS IS A custom SPRITE FONT...";
|
||||
const msg2 = "...and this is ANOTHER CUSTOM font...";
|
||||
const msg3 = "...and a THIRD one! GREAT! :D";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
const font1 = try rl.loadFont("examples/text/resources/custom_mecha.png"); // Font loading
|
||||
defer rl.unloadFont(font1);
|
||||
const font2 = try rl.loadFont("examples/text/resources/custom_alagard.png"); // Font loading
|
||||
defer rl.unloadFont(font2);
|
||||
const font3 = try rl.loadFont("examples/text/resources/custom_jupiter_crash.png"); // Font loading
|
||||
defer rl.unloadFont(font3);
|
||||
|
||||
const font_position1 = rl.Vector2{
|
||||
.x = @as(f32, @floatFromInt(screen_width)) / 2.0 - rl.measureTextEx(font1, msg1, @floatFromInt(font1.baseSize), -3).x / 2,
|
||||
.y = @as(f32, @floatFromInt(screen_height)) / 2.0 - @as(f32, @floatFromInt(font1.baseSize)) / 2.0 - 80.0,
|
||||
};
|
||||
|
||||
const font_position2 = rl.Vector2{
|
||||
.x = @as(f32, @floatFromInt(screen_width)) / 2.0 - rl.measureTextEx(font2, msg2, @floatFromInt(font2.baseSize), -2).x / 2,
|
||||
.y = @as(f32, @floatFromInt(screen_height)) / 2.0 - @as(f32, @floatFromInt(font1.baseSize)) / 2.0 - 10.0,
|
||||
};
|
||||
|
||||
const font_position3 = rl.Vector2{
|
||||
.x = @as(f32, @floatFromInt(screen_width)) / 2.0 - rl.measureTextEx(font3, msg3, @floatFromInt(font3.baseSize), 2).x / 2,
|
||||
.y = @as(f32, @floatFromInt(screen_height)) / 2.0 - @as(f32, @floatFromInt(font1.baseSize)) / 2.0 + 50.0,
|
||||
};
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update variables here...
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawTextEx(font1, msg1, font_position1, @floatFromInt(font1.baseSize), -3, .white);
|
||||
rl.drawTextEx(font2, msg2, font_position2, @floatFromInt(font2.baseSize), -2, .white);
|
||||
rl.drawTextEx(font3, msg3, font_position3, @floatFromInt(font3.baseSize), 2, .white);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
49
examples/text/format_text.zig
Normal file
@ -0,0 +1,49 @@
|
||||
// A raylib port of https://github.com/raysan5/raylib/blob/master/examples/text/text_format_text.c
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [text] example - text formatting");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// Set as 'const' for demonstration purposes, but would need to be 'var' once you actually update them to real values.
|
||||
const score: i32 = 100020;
|
||||
const hiscore: i32 = 200450;
|
||||
const lives: i32 = 5;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.white);
|
||||
|
||||
rl.drawText(rl.textFormat("Score: %08i", .{score}), 200, 80, 20, .red);
|
||||
|
||||
rl.drawText(rl.textFormat("HiScore: %08i", .{hiscore}), 200, 120, 20, .green);
|
||||
|
||||
rl.drawText(rl.textFormat("Lives: %02i", .{lives}), 200, 160, 40, .blue);
|
||||
|
||||
rl.drawText(rl.textFormat("Elapsed Time: %02.02f ms", .{rl.getFrameTime() * 1000}), 200, 220, 20, .black);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
126
examples/text/input_box.zig
Normal file
@ -0,0 +1,126 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [raylib-zig port of the [text] example - Input Box
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_input_box.c
|
||||
//!
|
||||
//! Example complexity rating: [★★☆☆] 2/4
|
||||
//!
|
||||
//! Example originally created with raylib 1.7, last time updated with raylib 3.5
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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) 2017-2025 Ramon Santamaria (@raysan5)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const rl = @import("raylib");
|
||||
|
||||
const max_input_chars = 9;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - input box");
|
||||
defer rl.closeWindow();
|
||||
|
||||
var name = [_:0]u8{0} ** max_input_chars;
|
||||
var letter_count: usize = 0;
|
||||
|
||||
const text_box = rl.Rectangle{
|
||||
.x = @as(f32, @floatFromInt(screen_width)) / 2.0 - 100,
|
||||
.y = 180,
|
||||
.width = 255,
|
||||
.height = 50,
|
||||
};
|
||||
var mouse_on_text = false;
|
||||
|
||||
var framesCounter: usize = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
mouse_on_text = rl.checkCollisionPointRec(rl.getMousePosition(), text_box);
|
||||
|
||||
if (mouse_on_text) {
|
||||
// Set the window's cursor to the I-Beam
|
||||
rl.setMouseCursor(.ibeam);
|
||||
|
||||
// Get char pressed (unicode character) on the queue
|
||||
// Check if more characters have been pressed on the same frame
|
||||
var key = rl.getKeyPressed();
|
||||
while (key != .null) : (key = rl.getKeyPressed()) {
|
||||
// NOTE: Only allow keys in range [32..125]
|
||||
const keyInt: c_int = @intFromEnum(key);
|
||||
if ((keyInt >= 32) and (keyInt <= 125) and (letter_count < name.len)) {
|
||||
name[letter_count] = @intCast(keyInt);
|
||||
letter_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rl.isKeyPressed(.backspace)) {
|
||||
if (letter_count <= 1) {
|
||||
letter_count = 0;
|
||||
} else {
|
||||
letter_count -= 1;
|
||||
}
|
||||
name[letter_count] = 0;
|
||||
}
|
||||
} else rl.setMouseCursor(.default);
|
||||
|
||||
if (mouse_on_text) {
|
||||
framesCounter += 1;
|
||||
} else {
|
||||
framesCounter = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawText("PLACE MOUSE OVER INPUT BOX!", 240, 140, 20, .gray);
|
||||
|
||||
rl.drawRectangleRec(text_box, .light_gray);
|
||||
rl.drawRectangleLines(
|
||||
@intFromFloat(text_box.x),
|
||||
@intFromFloat(text_box.y),
|
||||
@intFromFloat(text_box.width),
|
||||
@intFromFloat(text_box.height),
|
||||
if (mouse_on_text) .red else .dark_gray,
|
||||
);
|
||||
|
||||
rl.drawText(&name, @intFromFloat(text_box.x + 5), @intFromFloat(text_box.y + 8), 40, .maroon);
|
||||
|
||||
rl.drawText(rl.textFormat("INPUT CHARS: %i/%i", .{ letter_count, @as(usize, @intCast(max_input_chars)) }), 315, 250, 20, .dark_gray);
|
||||
|
||||
if (mouse_on_text) {
|
||||
if (letter_count < max_input_chars) {
|
||||
// Draw blinking underscore char
|
||||
if (((framesCounter / 20) % 2) == 0) {
|
||||
rl.drawText("_", @as(i32, @intFromFloat(text_box.x)) + 8 + rl.measureText(&name, 40), @intFromFloat(text_box.y + 12), 40, .maroon);
|
||||
}
|
||||
} else {
|
||||
rl.drawText("Press BACKSPACE to delete chars...", 230, 300, 20, .gray);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
89
examples/text/raylib_fonts.zig
Normal file
@ -0,0 +1,89 @@
|
||||
const rl = @import("raylib");
|
||||
const Color = rl.Color;
|
||||
|
||||
const MAX_FONTS = 8;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() !void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
|
||||
var fonts: [MAX_FONTS]rl.Font = undefined;
|
||||
|
||||
fonts[0] = try rl.loadFont("resources/text/fonts/alagard.png");
|
||||
fonts[1] = try rl.loadFont("resources/text/fonts/pixelplay.png");
|
||||
fonts[2] = try rl.loadFont("resources/text/fonts/mecha.png");
|
||||
fonts[3] = try rl.loadFont("resources/text/fonts/setback.png");
|
||||
fonts[4] = try rl.loadFont("resources/text/fonts/romulus.png");
|
||||
fonts[5] = try rl.loadFont("resources/text/fonts/pixantiqua.png");
|
||||
fonts[6] = try rl.loadFont("resources/text/fonts/alpha_beta.png");
|
||||
fonts[7] = try rl.loadFont("resources/text/fonts/jupiter_crash.png");
|
||||
|
||||
// Fonts unloading
|
||||
defer for (fonts) |font| {
|
||||
rl.unloadFont(font);
|
||||
};
|
||||
|
||||
const messages = [MAX_FONTS][:0]const u8{
|
||||
"ALAGARD FONT designed by Hewett Tsoi",
|
||||
"PIXELPLAY FONT designed by Aleksander Shevchuk",
|
||||
"MECHA FONT designed by Captain Falcon",
|
||||
"SETBACK FONT designed by Brian Kent (AEnigma)",
|
||||
"ROMULUS FONT designed by Hewett Tsoi",
|
||||
"PIXANTIQUA FONT designed by Gerhard Grossmann",
|
||||
"ALPHA_BETA FONT designed by Brian Kent (AEnigma)",
|
||||
"JUPITER_CRASH FONT designed by Brian Kent (AEnigma)",
|
||||
};
|
||||
|
||||
const spacings = [_]i32{ 2, 4, 8, 4, 3, 4, 4, 1 };
|
||||
|
||||
var positions: [MAX_FONTS]rl.Vector2 = undefined;
|
||||
for (0..MAX_FONTS) |i| {
|
||||
const font_base_size = @as(f32, @floatFromInt(fonts[i].baseSize));
|
||||
positions[i].x = screenWidth / 2.0 - rl.measureTextEx(fonts[i], messages[i], font_base_size * 2.0, @floatFromInt(spacings[i])).x / 2.0;
|
||||
positions[i].y = 60.0 + font_base_size + 45.0 * @as(f32, @floatFromInt(i));
|
||||
}
|
||||
|
||||
// Small Y position corrections
|
||||
positions[3].y += 8;
|
||||
positions[4].y += 2;
|
||||
positions[7].y -= 8;
|
||||
|
||||
const colors = [MAX_FONTS]Color{ Color.maroon, Color.orange, Color.dark_green, Color.dark_blue, Color.dark_purple, Color.lime, Color.gold, Color.red };
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) { // Detect window close button or ESC key
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
|
||||
rl.clearBackground(Color.white);
|
||||
|
||||
rl.drawText("free fonts included with raylib", 250, 20, 20, Color.dark_gray);
|
||||
rl.drawLine(220, 50, 590, 50, Color.dark_gray);
|
||||
|
||||
for (0..MAX_FONTS) |i| {
|
||||
const font_base_size = @as(f32, @floatFromInt(fonts[i].baseSize));
|
||||
rl.drawTextEx(fonts[i], messages[i], positions[i], font_base_size * 2.0, @floatFromInt(spacings[i]), colors[i]);
|
||||
}
|
||||
|
||||
rl.endDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
282
examples/text/rectangle_bounds.zig
Normal file
@ -0,0 +1,282 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Rectangle bounds
|
||||
//!
|
||||
//! Example complexity rating: [★★★★] 4/4
|
||||
//!
|
||||
//! Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
//!
|
||||
//! Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
|
||||
//!
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
//!
|
||||
//!*******************************************************************************************
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - draw text inside a rectangle");
|
||||
defer rl.closeWindow();
|
||||
|
||||
const text: [:0]const u8 = "Text cannot escape\tthis container\t...word wrap also works when active so here's a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget.";
|
||||
|
||||
var resizing = false;
|
||||
var word_wrap = true;
|
||||
|
||||
var container = rl.Rectangle{
|
||||
.x = 25.0,
|
||||
.y = 25.0,
|
||||
.width = @floatFromInt(screen_width - 50),
|
||||
.height = @floatFromInt(screen_height - 250),
|
||||
};
|
||||
var resizer = rl.Rectangle{
|
||||
.x = container.x + container.width - 17,
|
||||
.y = container.y + container.height - 17,
|
||||
.width = 14,
|
||||
.height = 14,
|
||||
};
|
||||
|
||||
// Minimum width and heigh for the container rectangle
|
||||
const minWidth = 60.0;
|
||||
const minHeight = 60.0;
|
||||
const maxWidth = screen_width - 50.0;
|
||||
const maxHeight = screen_height - 160.0;
|
||||
|
||||
var lastMouse = rl.Vector2{ .x = 0.0, .y = 0.0 }; // Stores last mouse coordinates
|
||||
var border_color = rl.Color.maroon; // Container border color
|
||||
const font = try rl.getFontDefault(); // Get default system font
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rl.isKeyPressed(.space)) word_wrap = !word_wrap;
|
||||
|
||||
const mouse = rl.getMousePosition();
|
||||
|
||||
// Check if the mouse is inside the container and toggle border color
|
||||
if (rl.checkCollisionPointRec(mouse, container)) {
|
||||
border_color = rl.fade(.maroon, 0.4);
|
||||
} else if (!resizing) {
|
||||
border_color = .maroon;
|
||||
}
|
||||
|
||||
// Container resizing logic
|
||||
if (resizing) {
|
||||
if (rl.isMouseButtonReleased(.left)) resizing = false;
|
||||
|
||||
const width = container.width + (mouse.x - lastMouse.x);
|
||||
container.width = if (width > minWidth) if (width < maxWidth) width else maxWidth else minWidth;
|
||||
|
||||
const height = container.height + (mouse.y - lastMouse.y);
|
||||
container.height = if (height > minHeight) if (height < maxHeight) height else maxHeight else minHeight;
|
||||
} else {
|
||||
// Check if we're resizing
|
||||
if (rl.isMouseButtonDown(.left) and rl.checkCollisionPointRec(mouse, resizer)) resizing = true;
|
||||
}
|
||||
|
||||
// Move resizer rectangle properly
|
||||
resizer.x = container.x + container.width - 17;
|
||||
resizer.y = container.y + container.height - 17;
|
||||
|
||||
lastMouse = mouse; // Update mouse
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawRectangleLinesEx(container, 3, border_color); // Draw container border
|
||||
|
||||
// Draw text in container (add some padding)
|
||||
drawTextBoxed(font, text, .{
|
||||
.x = container.x + 4,
|
||||
.y = container.y + 4,
|
||||
.width = container.width - 4,
|
||||
.height = container.height - 4,
|
||||
}, 20.0, 2.0, word_wrap, .gray);
|
||||
|
||||
rl.drawRectangleRec(resizer, border_color); // Draw the resize box
|
||||
|
||||
// Draw bottom info
|
||||
rl.drawRectangle(0, screen_height - 54, screen_width, 54, .gray);
|
||||
rl.drawRectangleRec(.{
|
||||
.x = 382.0,
|
||||
.y = screen_height - 34.0,
|
||||
.width = 12.0,
|
||||
.height = 12.0,
|
||||
}, .maroon);
|
||||
|
||||
rl.drawText("Word Wrap: ", 313, screen_height - 115, 20, .black);
|
||||
if (word_wrap) {
|
||||
rl.drawText("ON", 447, screen_height - 115, 20, .red);
|
||||
} else {
|
||||
rl.drawText("OFF", 447, screen_height - 115, 20, .black);
|
||||
}
|
||||
|
||||
rl.drawText("Press [SPACE] to toggle word wrap", 218, screen_height - 86, 20, .gray);
|
||||
|
||||
rl.drawText("Click hold & drag the to resize the container", 155, screen_height - 38, 20, .ray_white);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module functions definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw text using font inside rectangle limits
|
||||
fn drawTextBoxed(font: rl.Font, text: [:0]const u8, rec: rl.Rectangle, font_size: f32, spacing: f32, word_wrap: bool, tint: rl.Color) void {
|
||||
drawTextBoxedSelectable(font, text, rec, font_size, spacing, word_wrap, tint, 0, 0, .white, .white);
|
||||
}
|
||||
|
||||
// Draw text using font inside rectangle limits with support for text selection
|
||||
fn drawTextBoxedSelectable(font: rl.Font, text: [:0]const u8, rec: rl.Rectangle, font_size: f32, spacing: f32, word_wrap: bool, tint: rl.Color, select_box_start: i32, select_length: i32, select_tint: rl.Color, select_back_tint: rl.Color) void {
|
||||
var select_start = select_box_start;
|
||||
const length = rl.textLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
var text_offset_y: f32 = 0; // Offset between lines (on line break '\n')
|
||||
var text_offset_x: f32 = 0.0; // Offset X to next character to draw
|
||||
|
||||
const scale_factor = font_size / @as(f32, @floatFromInt(font.baseSize)); // Character rectangle scaling factor
|
||||
|
||||
// Word/character wrapping mechanism variables
|
||||
const MeasureState = enum(u8) { measure, draw };
|
||||
var state: MeasureState = if (word_wrap) .measure else .draw;
|
||||
|
||||
var start_line: i32 = -1; // Index where to begin drawing (where a line begins)
|
||||
var end_line: i32 = -1; // Index where to stop drawing (where a line ends)
|
||||
var last_char: i32 = -1; // Holds last value of the character position
|
||||
|
||||
var i: i32 = 0;
|
||||
var k: i32 = 0;
|
||||
while (i < length) : ({
|
||||
i += 1;
|
||||
k += 1;
|
||||
}) {
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
var codepoint_byte_count: i32 = 0;
|
||||
const codepoint = rl.getCodepoint(text[@intCast(i)..], &codepoint_byte_count);
|
||||
const index: usize = @intCast(rl.getGlyphIndex(font, codepoint));
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f) codepoint_byte_count = 1;
|
||||
i += @intCast(codepoint_byte_count - 1);
|
||||
|
||||
var glyph_width: f32 = 0;
|
||||
if (codepoint != '\n') {
|
||||
glyph_width = if (font.glyphs[index].advanceX == 0) font.recs[index].width * scale_factor else @as(f32, @floatFromInt(font.glyphs[index].advanceX)) * scale_factor;
|
||||
|
||||
if (i + 1 < length) glyph_width = glyph_width + spacing;
|
||||
}
|
||||
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
|
||||
// We store this info in startLine and endLine, then we change states, draw the text between those two variables
|
||||
// and change states again and again recursively until the end of the text (or until we get outside of the container).
|
||||
// When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
|
||||
// and begin drawing on the next line before we can get outside the container.
|
||||
if (state == .measure) {
|
||||
// TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
|
||||
// Ref: http://jkorpela.fi/chars/spaces.html
|
||||
if ((codepoint == ' ') or (codepoint == '\t') or (codepoint == '\n')) end_line = @intCast(i);
|
||||
|
||||
if ((text_offset_x + glyph_width) > rec.width) {
|
||||
end_line = if (end_line < 1) @intCast(i) else end_line;
|
||||
if (i == end_line) end_line -= codepoint_byte_count;
|
||||
if ((start_line + codepoint_byte_count) == end_line) end_line = @as(i32, @intCast(i)) - codepoint_byte_count;
|
||||
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
} else if ((i + 1) == length) {
|
||||
end_line = @intCast(i);
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
} else if (codepoint == '\n') {
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
}
|
||||
|
||||
if (state == .draw) {
|
||||
text_offset_x = 0;
|
||||
i = @intCast(start_line);
|
||||
glyph_width = 0;
|
||||
|
||||
// Save character position when we switch states
|
||||
const tmp = last_char;
|
||||
last_char = k - 1;
|
||||
k = tmp;
|
||||
}
|
||||
} else {
|
||||
if (codepoint == '\n') {
|
||||
if (!word_wrap) {
|
||||
const bS: f32 = @floatFromInt(font.baseSize);
|
||||
text_offset_y += (bS + bS / 2) * scale_factor;
|
||||
text_offset_x = 0;
|
||||
}
|
||||
} else {
|
||||
if (!word_wrap and ((text_offset_x + glyph_width) > rec.width)) {
|
||||
const bS: f32 = @floatFromInt(font.baseSize);
|
||||
text_offset_y += (bS + bS / 2) * scale_factor;
|
||||
text_offset_x = 0;
|
||||
}
|
||||
|
||||
// When text overflows rectangle height limit, just stop drawing
|
||||
if ((text_offset_y + @as(f32, @floatFromInt(font.baseSize)) * scale_factor) > rec.height) break;
|
||||
|
||||
// Draw selection background
|
||||
var is_glyph_selected = false;
|
||||
if ((select_start >= 0) and (k >= select_start) and (k < (select_start + select_length))) {
|
||||
rl.drawRectangleRec(.{
|
||||
.x = rec.x + text_offset_x - 1,
|
||||
.y = rec.y + text_offset_y,
|
||||
.width = glyph_width,
|
||||
.height = @as(f32, @floatFromInt(font.baseSize)) * scale_factor,
|
||||
}, select_back_tint);
|
||||
is_glyph_selected = true;
|
||||
}
|
||||
|
||||
// Draw current character glyph
|
||||
if ((codepoint != ' ') and (codepoint != '\t')) {
|
||||
rl.drawTextCodepoint(font, codepoint, .{
|
||||
.x = rec.x + text_offset_x,
|
||||
.y = rec.y + text_offset_y,
|
||||
}, font_size, if (is_glyph_selected) select_tint else tint);
|
||||
}
|
||||
}
|
||||
|
||||
if (word_wrap and (i == end_line)) {
|
||||
const bS: f32 = @floatFromInt(font.baseSize);
|
||||
text_offset_y += (bS + bS / 2) * scale_factor;
|
||||
text_offset_x = 0;
|
||||
start_line = end_line;
|
||||
end_line = -1;
|
||||
glyph_width = 0;
|
||||
select_start += last_char - k;
|
||||
k = last_char;
|
||||
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
}
|
||||
}
|
||||
|
||||
if ((text_offset_x != 0) or (codepoint != ' ')) text_offset_x += glyph_width; // avoid leading spaces
|
||||
}
|
||||
}
|
||||
BIN
examples/text/resources/DotGothic16-Regular.ttf
Normal file
BIN
examples/text/resources/KAISG.ttf
Normal file
20
examples/text/resources/LICENSE.md
Normal file
@ -0,0 +1,20 @@
|
||||
| resource | author | licence | notes |
|
||||
| :----------------------------- | :---------: | :------ | :---- |
|
||||
| fonts/alagard.png | Hewett Tsoi | [Freeware](https://www.dafont.com/es/alagard.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/romulus.png | Hewett Tsoi | [Freeware](https://www.dafont.com/es/romulus.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/alpha_beta.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/alpha-beta.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/setback.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/setback.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/jupiter_crash.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/mecha.png | Captain Falcon | [Freeware](https://www.dafont.com/es/mecha-cf.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/pixelplay.png | Aleksander Shevchuk | [Freeware](https://www.dafont.com/es/pixelplay.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| fonts/pixantiqua.ttf | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| anonymous_pro_bold.ttf | [Mark Simonson](https://fonts.google.com/specimen/Anonymous+Pro) | [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | - |
|
||||
| custom_alagard.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| custom_jupiter_crash.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| custom_mecha.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
|
||||
| dejavu.fnt, dejavu.png | [DejaVu Fonts](https://dejavu-fonts.github.io/) | [Free](https://dejavu-fonts.github.io/License.html) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
|
||||
| KAISG.ttf | [Dieter Steffmann](http://www.steffmann.de/wordpress/) | [Freeware](https://www.1001fonts.com/users/steffmann/) | [Kaiserzeit Gotisch](https://www.dafont.com/es/kaiserzeit-gotisch.font) font |
|
||||
| noto_cjk.fnt, noto_cjk.png | [Google Fonts](https://www.google.com/get/noto/help/cjk/) | [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
|
||||
| pixantiqua.fnt, pixantiqua.png | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
|
||||
| pixantiqua.ttf | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | - |
|
||||
| symbola.fnt, symbola.png | George Douros | [Freeware](https://fontlibrary.org/en/font/symbola) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
|
||||
BIN
examples/text/resources/anonymous_pro_bold.ttf
Normal file
BIN
examples/text/resources/custom_alagard.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
examples/text/resources/custom_jupiter_crash.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
examples/text/resources/custom_mecha.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
1115
examples/text/resources/dejavu.fnt
Normal file
BIN
examples/text/resources/dejavu.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
580
examples/text/resources/noto_cjk.fnt
Normal file
@ -0,0 +1,580 @@
|
||||
info face="Noto Serif CJK JP" size=-16 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2 outline=1
|
||||
common lineHeight=23 base=18 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||
page id=0 file="noto_cjk.png"
|
||||
chars count=576
|
||||
char id=32 x=507 y=185 width=3 height=3 xoffset=-1 yoffset=-1 xadvance=4 page=0 chnl=15
|
||||
char id=33 x=449 y=285 width=5 height=14 xoffset=0 yoffset=5 xadvance=5 page=0 chnl=15
|
||||
char id=34 x=393 y=315 width=8 height=8 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=35 x=285 y=287 width=11 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=36 x=500 y=61 width=10 height=18 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=37 x=52 y=257 width=15 height=15 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=38 x=495 y=268 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=39 x=413 y=315 width=5 height=8 xoffset=-1 yoffset=4 xadvance=3 page=0 chnl=15
|
||||
char id=40 x=339 y=21 width=7 height=19 xoffset=0 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=41 x=330 y=21 width=7 height=19 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=42 x=321 y=317 width=10 height=9 xoffset=-1 yoffset=4 xadvance=8 page=0 chnl=15
|
||||
char id=43 x=26 y=322 width=11 height=11 xoffset=-1 yoffset=7 xadvance=9 page=0 chnl=15
|
||||
char id=44 x=353 y=316 width=6 height=9 xoffset=-1 yoffset=15 xadvance=5 page=0 chnl=15
|
||||
char id=45 x=136 y=334 width=7 height=4 xoffset=-1 yoffset=12 xadvance=5 page=0 chnl=15
|
||||
char id=46 x=109 y=334 width=5 height=5 xoffset=0 yoffset=14 xadvance=5 page=0 chnl=15
|
||||
char id=47 x=500 y=81 width=8 height=18 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=48 x=406 y=286 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=49 x=418 y=286 width=9 height=14 xoffset=0 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=50 x=394 y=286 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=51 x=382 y=286 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=52 x=272 y=287 width=11 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=53 x=370 y=286 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=54 x=358 y=286 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=55 x=346 y=286 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=56 x=334 y=287 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=57 x=322 y=287 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=58 x=502 y=300 width=5 height=11 xoffset=0 yoffset=8 xadvance=5 page=0 chnl=15
|
||||
char id=59 x=190 y=238 width=6 height=16 xoffset=-1 yoffset=8 xadvance=5 page=0 chnl=15
|
||||
char id=60 x=39 y=322 width=11 height=11 xoffset=-1 yoffset=7 xadvance=9 page=0 chnl=15
|
||||
char id=61 x=440 y=315 width=11 height=7 xoffset=-1 yoffset=9 xadvance=9 page=0 chnl=15
|
||||
char id=62 x=78 y=321 width=11 height=11 xoffset=-1 yoffset=7 xadvance=9 page=0 chnl=15
|
||||
char id=63 x=460 y=252 width=7 height=15 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||
char id=64 x=72 y=221 width=16 height=16 xoffset=-1 yoffset=6 xadvance=14 page=0 chnl=15
|
||||
char id=65 x=447 y=269 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=66 x=175 y=289 width=12 height=14 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=67 x=75 y=290 width=13 height=14 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=68 x=415 y=270 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=69 x=119 y=290 width=12 height=14 xoffset=-1 yoffset=5 xadvance=10 page=0 chnl=15
|
||||
char id=70 x=105 y=290 width=12 height=14 xoffset=-1 yoffset=5 xadvance=10 page=0 chnl=15
|
||||
char id=71 x=431 y=269 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=72 x=302 y=271 width=15 height=14 xoffset=-1 yoffset=5 xadvance=14 page=0 chnl=15
|
||||
char id=73 x=439 y=285 width=8 height=14 xoffset=-1 yoffset=5 xadvance=6 page=0 chnl=15
|
||||
char id=74 x=268 y=200 width=9 height=17 xoffset=-2 yoffset=5 xadvance=6 page=0 chnl=15
|
||||
char id=75 x=367 y=270 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=76 x=203 y=289 width=12 height=14 xoffset=-1 yoffset=5 xadvance=10 page=0 chnl=15
|
||||
char id=77 x=158 y=273 width=17 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=78 x=285 y=271 width=15 height=14 xoffset=-1 yoffset=5 xadvance=13 page=0 chnl=15
|
||||
char id=79 x=479 y=269 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=80 x=189 y=289 width=12 height=14 xoffset=-1 yoffset=5 xadvance=10 page=0 chnl=15
|
||||
char id=81 x=209 y=142 width=14 height=18 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=82 x=30 y=291 width=13 height=14 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=83 x=259 y=287 width=11 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=84 x=45 y=291 width=13 height=14 xoffset=-1 yoffset=5 xadvance=10 page=0 chnl=15
|
||||
char id=85 x=335 y=270 width=14 height=14 xoffset=-1 yoffset=5 xadvance=13 page=0 chnl=15
|
||||
char id=86 x=399 y=270 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=87 x=485 y=252 width=19 height=14 xoffset=-1 yoffset=5 xadvance=17 page=0 chnl=15
|
||||
char id=88 x=0 y=291 width=13 height=14 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=89 x=15 y=291 width=13 height=14 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=90 x=217 y=287 width=12 height=14 xoffset=-1 yoffset=5 xadvance=10 page=0 chnl=15
|
||||
char id=91 x=8 y=164 width=6 height=18 xoffset=0 yoffset=4 xadvance=5 page=0 chnl=15
|
||||
char id=92 x=497 y=141 width=8 height=18 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=93 x=0 y=164 width=6 height=18 xoffset=-1 yoffset=4 xadvance=5 page=0 chnl=15
|
||||
char id=94 x=465 y=313 width=9 height=7 xoffset=0 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=95 x=145 y=334 width=11 height=3 xoffset=-1 yoffset=17 xadvance=9 page=0 chnl=15
|
||||
char id=96 x=74 y=335 width=6 height=6 xoffset=0 yoffset=4 xadvance=7 page=0 chnl=15
|
||||
char id=97 x=13 y=322 width=11 height=11 xoffset=-1 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=98 x=398 y=218 width=12 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=99 x=129 y=321 width=10 height=11 xoffset=-1 yoffset=8 xadvance=8 page=0 chnl=15
|
||||
char id=100 x=426 y=217 width=12 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=101 x=117 y=321 width=10 height=11 xoffset=-1 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=102 x=140 y=238 width=10 height=16 xoffset=-1 yoffset=3 xadvance=6 page=0 chnl=15
|
||||
char id=103 x=52 y=239 width=11 height=16 xoffset=-1 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=104 x=440 y=217 width=12 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=105 x=469 y=252 width=7 height=15 xoffset=-1 yoffset=4 xadvance=5 page=0 chnl=15
|
||||
char id=106 x=95 y=0 width=8 height=20 xoffset=-3 yoffset=4 xadvance=5 page=0 chnl=15
|
||||
char id=107 x=412 y=218 width=12 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=108 x=451 y=252 width=7 height=15 xoffset=-1 yoffset=4 xadvance=5 page=0 chnl=15
|
||||
char id=109 x=386 y=302 width=18 height=11 xoffset=-1 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=110 x=488 y=300 width=12 height=11 xoffset=-1 yoffset=8 xadvance=11 page=0 chnl=15
|
||||
char id=111 x=91 y=321 width=11 height=11 xoffset=-1 yoffset=8 xadvance=10 page=0 chnl=15
|
||||
char id=112 x=300 y=218 width=12 height=16 xoffset=-1 yoffset=8 xadvance=10 page=0 chnl=15
|
||||
char id=113 x=286 y=219 width=12 height=16 xoffset=-1 yoffset=8 xadvance=10 page=0 chnl=15
|
||||
char id=114 x=141 y=321 width=10 height=11 xoffset=-1 yoffset=8 xadvance=7 page=0 chnl=15
|
||||
char id=115 x=165 y=320 width=9 height=11 xoffset=-1 yoffset=8 xadvance=8 page=0 chnl=15
|
||||
char id=116 x=429 y=286 width=8 height=14 xoffset=-1 yoffset=5 xadvance=6 page=0 chnl=15
|
||||
char id=117 x=474 y=300 width=12 height=11 xoffset=-1 yoffset=8 xadvance=10 page=0 chnl=15
|
||||
char id=118 x=0 y=322 width=11 height=11 xoffset=-1 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=119 x=424 y=302 width=16 height=11 xoffset=-1 yoffset=8 xadvance=13 page=0 chnl=15
|
||||
char id=120 x=104 y=321 width=11 height=11 xoffset=-1 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=121 x=342 y=218 width=12 height=16 xoffset=-2 yoffset=8 xadvance=9 page=0 chnl=15
|
||||
char id=122 x=153 y=320 width=10 height=11 xoffset=-1 yoffset=8 xadvance=8 page=0 chnl=15
|
||||
char id=123 x=467 y=141 width=8 height=18 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=124 x=111 y=0 width=4 height=20 xoffset=0 yoffset=4 xadvance=4 page=0 chnl=15
|
||||
char id=125 x=457 y=141 width=8 height=18 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=126 x=27 y=335 width=11 height=6 xoffset=-1 yoffset=9 xadvance=9 page=0 chnl=15
|
||||
char id=160 x=507 y=180 width=3 height=3 xoffset=-1 yoffset=-1 xadvance=4 page=0 chnl=15
|
||||
char id=161 x=478 y=252 width=5 height=15 xoffset=0 yoffset=8 xadvance=5 page=0 chnl=15
|
||||
char id=162 x=430 y=252 width=10 height=15 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=163 x=310 y=287 width=10 height=14 xoffset=-1 yoffset=5 xadvance=9 page=0 chnl=15
|
||||
char id=164 x=52 y=322 width=11 height=11 xoffset=-1 yoffset=7 xadvance=9 page=0 chnl=15
|
||||
char id=165 x=201 y=305 width=12 height=13 xoffset=-2 yoffset=6 xadvance=9 page=0 chnl=15
|
||||
char id=166 x=105 y=0 width=4 height=20 xoffset=0 yoffset=4 xadvance=4 page=0 chnl=15
|
||||
char id=167 x=244 y=200 width=10 height=17 xoffset=3 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=168 x=116 y=334 width=9 height=4 xoffset=-1 yoffset=5 xadvance=7 page=0 chnl=15
|
||||
char id=169 x=251 y=271 width=15 height=14 xoffset=-1 yoffset=5 xadvance=13 page=0 chnl=15
|
||||
char id=170 x=383 y=316 width=8 height=8 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=171 x=248 y=317 width=10 height=10 xoffset=-1 yoffset=9 xadvance=8 page=0 chnl=15
|
||||
char id=172 x=427 y=315 width=11 height=7 xoffset=-1 yoffset=10 xadvance=9 page=0 chnl=15
|
||||
char id=173 x=127 y=334 width=7 height=4 xoffset=-1 yoffset=12 xadvance=5 page=0 chnl=15
|
||||
char id=174 x=236 y=317 width=10 height=10 xoffset=-1 yoffset=4 xadvance=8 page=0 chnl=15
|
||||
char id=175 x=158 y=333 width=7 height=3 xoffset=0 yoffset=6 xadvance=7 page=0 chnl=15
|
||||
char id=176 x=486 y=313 width=7 height=7 xoffset=-1 yoffset=5 xadvance=6 page=0 chnl=15
|
||||
char id=177 x=154 y=256 width=15 height=15 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=178 x=270 y=317 width=8 height=10 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||
char id=179 x=260 y=317 width=8 height=10 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||
char id=180 x=58 y=335 width=6 height=6 xoffset=1 yoffset=4 xadvance=7 page=0 chnl=15
|
||||
char id=181 x=26 y=240 width=11 height=16 xoffset=0 yoffset=7 xadvance=10 page=0 chnl=15
|
||||
char id=182 x=216 y=200 width=12 height=17 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=183 x=102 y=334 width=5 height=5 xoffset=0 yoffset=10 xadvance=5 page=0 chnl=15
|
||||
char id=184 x=504 y=313 width=6 height=7 xoffset=0 yoffset=16 xadvance=7 page=0 chnl=15
|
||||
char id=185 x=280 y=317 width=7 height=10 xoffset=0 yoffset=2 xadvance=6 page=0 chnl=15
|
||||
char id=186 x=403 y=315 width=8 height=8 xoffset=-1 yoffset=4 xadvance=6 page=0 chnl=15
|
||||
char id=187 x=224 y=320 width=10 height=10 xoffset=-1 yoffset=9 xadvance=8 page=0 chnl=15
|
||||
char id=188 x=137 y=256 width=15 height=15 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=189 x=375 y=236 width=16 height=15 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=190 x=120 y=256 width=15 height=15 xoffset=0 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=191 x=442 y=252 width=7 height=15 xoffset=0 yoffset=8 xadvance=7 page=0 chnl=15
|
||||
char id=192 x=273 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=12 page=0 chnl=15
|
||||
char id=193 x=353 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=12 page=0 chnl=15
|
||||
char id=194 x=48 y=202 width=14 height=17 xoffset=-1 yoffset=2 xadvance=12 page=0 chnl=15
|
||||
char id=195 x=337 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=12 page=0 chnl=15
|
||||
char id=196 x=0 y=203 width=14 height=17 xoffset=-1 yoffset=2 xadvance=12 page=0 chnl=15
|
||||
char id=197 x=225 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=12 page=0 chnl=15
|
||||
char id=198 x=20 y=275 width=18 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=199 x=400 y=141 width=13 height=18 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=200 x=443 y=141 width=12 height=18 xoffset=-1 yoffset=1 xadvance=10 page=0 chnl=15
|
||||
char id=201 x=498 y=101 width=12 height=18 xoffset=-1 yoffset=1 xadvance=10 page=0 chnl=15
|
||||
char id=202 x=429 y=141 width=12 height=18 xoffset=-1 yoffset=1 xadvance=10 page=0 chnl=15
|
||||
char id=203 x=202 y=200 width=12 height=17 xoffset=-1 yoffset=2 xadvance=10 page=0 chnl=15
|
||||
char id=204 x=502 y=121 width=8 height=18 xoffset=-1 yoffset=1 xadvance=6 page=0 chnl=15
|
||||
char id=205 x=477 y=141 width=8 height=18 xoffset=-1 yoffset=1 xadvance=6 page=0 chnl=15
|
||||
char id=206 x=487 y=141 width=8 height=18 xoffset=-1 yoffset=1 xadvance=6 page=0 chnl=15
|
||||
char id=207 x=279 y=200 width=8 height=17 xoffset=-1 yoffset=2 xadvance=6 page=0 chnl=15
|
||||
char id=208 x=319 y=271 width=14 height=14 xoffset=-1 yoffset=5 xadvance=12 page=0 chnl=15
|
||||
char id=209 x=142 y=143 width=15 height=18 xoffset=-1 yoffset=1 xadvance=13 page=0 chnl=15
|
||||
char id=210 x=305 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=12 page=0 chnl=15
|
||||
char id=211 x=369 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=12 page=0 chnl=15
|
||||
char id=212 x=491 y=180 width=14 height=17 xoffset=-1 yoffset=2 xadvance=12 page=0 chnl=15
|
||||
char id=213 x=475 y=180 width=14 height=17 xoffset=-1 yoffset=2 xadvance=12 page=0 chnl=15
|
||||
char id=214 x=96 y=201 width=14 height=17 xoffset=-1 yoffset=2 xadvance=12 page=0 chnl=15
|
||||
char id=215 x=173 y=305 width=12 height=13 xoffset=2 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=216 x=209 y=219 width=14 height=16 xoffset=-1 yoffset=4 xadvance=12 page=0 chnl=15
|
||||
char id=217 x=241 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=13 page=0 chnl=15
|
||||
char id=218 x=257 y=142 width=14 height=18 xoffset=-1 yoffset=1 xadvance=13 page=0 chnl=15
|
||||
char id=219 x=64 y=202 width=14 height=17 xoffset=-1 yoffset=2 xadvance=13 page=0 chnl=15
|
||||
char id=220 x=16 y=203 width=14 height=17 xoffset=-1 yoffset=2 xadvance=13 page=0 chnl=15
|
||||
char id=221 x=385 y=141 width=13 height=18 xoffset=-1 yoffset=1 xadvance=11 page=0 chnl=15
|
||||
char id=222 x=231 y=287 width=12 height=14 xoffset=-1 yoffset=5 xadvance=11 page=0 chnl=15
|
||||
char id=223 x=299 y=254 width=12 height=15 xoffset=-1 yoffset=4 xadvance=10 page=0 chnl=15
|
||||
char id=224 x=13 y=240 width=11 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=225 x=0 y=240 width=11 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=226 x=493 y=217 width=11 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=227 x=367 y=253 width=11 height=15 xoffset=-1 yoffset=4 xadvance=9 page=0 chnl=15
|
||||
char id=228 x=341 y=253 width=11 height=15 xoffset=-1 yoffset=4 xadvance=9 page=0 chnl=15
|
||||
char id=229 x=480 y=217 width=11 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=230 x=442 y=301 width=15 height=11 xoffset=-1 yoffset=8 xadvance=14 page=0 chnl=15
|
||||
char id=231 x=406 y=253 width=10 height=15 xoffset=-1 yoffset=8 xadvance=8 page=0 chnl=15
|
||||
char id=232 x=116 y=238 width=10 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=233 x=128 y=238 width=10 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=234 x=104 y=239 width=10 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=235 x=418 y=253 width=10 height=15 xoffset=-1 yoffset=4 xadvance=9 page=0 chnl=15
|
||||
char id=236 x=172 y=238 width=7 height=16 xoffset=-1 yoffset=3 xadvance=5 page=0 chnl=15
|
||||
char id=237 x=181 y=238 width=7 height=16 xoffset=-1 yoffset=3 xadvance=5 page=0 chnl=15
|
||||
char id=238 x=163 y=238 width=7 height=16 xoffset=-1 yoffset=3 xadvance=5 page=0 chnl=15
|
||||
char id=239 x=501 y=235 width=9 height=15 xoffset=-2 yoffset=4 xadvance=5 page=0 chnl=15
|
||||
char id=240 x=454 y=217 width=11 height=16 xoffset=-1 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=241 x=327 y=253 width=12 height=15 xoffset=-1 yoffset=4 xadvance=11 page=0 chnl=15
|
||||
char id=242 x=91 y=239 width=11 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=243 x=78 y=239 width=11 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=244 x=65 y=239 width=11 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=245 x=393 y=253 width=11 height=15 xoffset=-1 yoffset=4 xadvance=10 page=0 chnl=15
|
||||
char id=246 x=380 y=253 width=11 height=15 xoffset=-1 yoffset=4 xadvance=10 page=0 chnl=15
|
||||
char id=247 x=233 y=271 width=16 height=14 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=248 x=215 y=305 width=11 height=13 xoffset=-1 yoffset=7 xadvance=10 page=0 chnl=15
|
||||
char id=249 x=384 y=218 width=12 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=250 x=356 y=218 width=12 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=251 x=314 y=218 width=12 height=16 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=252 x=313 y=254 width=12 height=15 xoffset=-1 yoffset=4 xadvance=10 page=0 chnl=15
|
||||
char id=253 x=0 y=0 width=12 height=21 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=15
|
||||
char id=254 x=14 y=0 width=11 height=21 xoffset=-1 yoffset=3 xadvance=10 page=0 chnl=15
|
||||
char id=255 x=81 y=0 width=12 height=20 xoffset=-2 yoffset=4 xadvance=9 page=0 chnl=15
|
||||
char id=8220 x=361 y=316 width=9 height=8 xoffset=-1 yoffset=4 xadvance=7 page=0 chnl=15
|
||||
char id=8222 x=372 y=316 width=9 height=8 xoffset=-1 yoffset=14 xadvance=7 page=0 chnl=15
|
||||
char id=9829 x=18 y=222 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12288 x=507 y=141 width=3 height=3 xoffset=-1 yoffset=-1 xadvance=16 page=0 chnl=15
|
||||
char id=12290 x=476 y=313 width=8 height=7 xoffset=-1 yoffset=14 xadvance=16 page=0 chnl=15
|
||||
char id=12353 x=147 y=289 width=12 height=14 xoffset=2 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12354 x=73 y=183 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12355 x=459 y=300 width=13 height=11 xoffset=1 yoffset=9 xadvance=16 page=0 chnl=15
|
||||
char id=12356 x=483 y=235 width=16 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12357 x=298 y=287 width=10 height=14 xoffset=3 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12358 x=415 y=141 width=12 height=18 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12359 x=187 y=305 width=12 height=13 xoffset=2 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12360 x=409 y=180 width=15 height=17 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12361 x=53 y=307 width=14 height=13 xoffset=1 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12362 x=108 y=220 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12363 x=271 y=181 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12364 x=0 y=184 width=17 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12365 x=32 y=202 width=14 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12366 x=72 y=143 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12367 x=152 y=238 width=9 height=16 xoffset=3 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12368 x=256 y=219 width=13 height=16 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12369 x=375 y=181 width=15 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12370 x=340 y=122 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12371 x=284 y=254 width=13 height=15 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12372 x=426 y=180 width=15 height=17 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12373 x=142 y=201 width=13 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12374 x=57 y=123 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12375 x=443 y=180 width=14 height=17 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12376 x=112 y=201 width=13 height=17 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12377 x=235 y=181 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12378 x=209 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12379 x=309 y=200 width=18 height=16 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12380 x=137 y=163 width=18 height=17 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12381 x=358 y=181 width=15 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12382 x=396 y=161 width=17 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12383 x=217 y=181 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12384 x=277 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12385 x=324 y=181 width=15 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12386 x=430 y=121 width=16 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12387 x=195 y=320 width=13 height=10 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15
|
||||
char id=12388 x=267 y=303 width=17 height=12 xoffset=-1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12389 x=218 y=237 width=18 height=15 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12390 x=411 y=236 width=16 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12391 x=338 y=236 width=17 height=15 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12392 x=370 y=218 width=12 height=16 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12393 x=392 y=181 width=15 height=17 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12394 x=477 y=199 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12395 x=160 y=220 width=15 height=16 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12396 x=447 y=235 width=16 height=15 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12397 x=491 y=161 width=17 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12398 x=465 y=235 width=16 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12399 x=36 y=221 width=16 height=16 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12400 x=479 y=101 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12401 x=247 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12402 x=495 y=199 width=15 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12403 x=36 y=144 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12404 x=253 y=181 width=16 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12405 x=348 y=200 width=17 height=16 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12406 x=289 y=200 width=18 height=16 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12407 x=386 y=200 width=17 height=16 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12408 x=228 y=303 width=18 height=12 xoffset=-1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12409 x=139 y=273 width=17 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12410 x=456 y=285 width=17 height=13 xoffset=-1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12411 x=55 y=183 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12412 x=171 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12413 x=95 y=123 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12414 x=193 y=219 width=14 height=16 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12415 x=405 y=200 width=16 height=16 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12416 x=367 y=200 width=17 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12417 x=90 y=221 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12418 x=328 y=218 width=12 height=16 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12419 x=383 y=270 width=14 height=14 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12420 x=472 y=161 width=17 height=17 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12421 x=159 y=305 width=12 height=13 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12422 x=109 y=182 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12423 x=348 y=302 width=11 height=12 xoffset=3 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12424 x=241 y=219 width=13 height=16 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12425 x=127 y=201 width=13 height=17 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12426 x=500 y=41 width=10 height=18 xoffset=3 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12427 x=188 y=256 width=14 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12428 x=177 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12429 x=177 y=220 width=14 height=16 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12430 x=351 y=270 width=14 height=14 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12431 x=163 y=182 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12432 x=393 y=236 width=16 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12433 x=181 y=181 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12434 x=143 y=220 width=15 height=16 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12435 x=54 y=221 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12436 x=289 y=142 width=14 height=18 xoffset=2 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12437 x=463 y=269 width=14 height=14 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12438 x=101 y=306 width=13 height=13 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12441 x=40 y=335 width=7 height=6 xoffset=-6 yoffset=3 xadvance=0 page=0 chnl=15
|
||||
char id=12442 x=49 y=335 width=7 height=6 xoffset=-5 yoffset=3 xadvance=0 page=0 chnl=15
|
||||
char id=12443 x=495 y=313 width=7 height=7 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12444 x=0 y=335 width=7 height=7 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12445 x=333 y=317 width=8 height=9 xoffset=4 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12446 x=65 y=322 width=11 height=11 xoffset=4 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12447 x=193 y=142 width=14 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12448 x=453 y=314 width=10 height=7 xoffset=3 yoffset=9 xadvance=16 page=0 chnl=15
|
||||
char id=12449 x=334 y=303 width=12 height=12 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
|
||||
char id=12450 x=126 y=220 width=15 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12451 x=374 y=302 width=10 height=12 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12452 x=157 y=201 width=13 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12453 x=161 y=289 width=12 height=14 xoffset=2 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12454 x=459 y=180 width=14 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12455 x=289 y=317 width=14 height=9 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15
|
||||
char id=12456 x=494 y=285 width=16 height=13 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12457 x=116 y=306 width=13 height=13 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12458 x=459 y=199 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12459 x=307 y=181 width=15 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12460 x=453 y=161 width=17 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12461 x=289 y=181 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12462 x=285 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12463 x=80 y=202 width=14 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12464 x=448 y=121 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12465 x=0 y=222 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12466 x=19 y=124 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12467 x=304 y=303 width=14 height=12 xoffset=1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12468 x=429 y=235 width=16 height=15 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12469 x=199 y=181 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12470 x=160 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12471 x=103 y=257 width=15 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12472 x=341 y=181 width=15 height=17 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12473 x=69 y=257 width=15 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12474 x=145 y=182 width=16 height=17 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12475 x=86 y=257 width=15 height=15 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12476 x=278 y=237 width=18 height=15 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12477 x=204 y=254 width=14 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12478 x=322 y=122 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12479 x=321 y=142 width=14 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12480 x=38 y=124 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12481 x=127 y=182 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12482 x=434 y=161 width=17 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12483 x=320 y=303 width=12 height=12 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
|
||||
char id=12484 x=252 y=254 width=14 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12485 x=266 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12486 x=441 y=199 width=16 height=16 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12487 x=228 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12488 x=256 y=200 width=10 height=17 xoffset=4 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12489 x=230 y=200 width=12 height=17 xoffset=3 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12490 x=91 y=182 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12491 x=406 y=302 width=16 height=11 xoffset=0 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12492 x=35 y=258 width=15 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12493 x=484 y=121 width=16 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12494 x=90 y=290 width=13 height=14 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12495 x=176 y=320 width=17 height=10 xoffset=-1 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12496 x=196 y=273 width=17 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12497 x=177 y=273 width=17 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12498 x=60 y=290 width=13 height=14 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12499 x=171 y=256 width=15 height=15 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12500 x=0 y=258 width=16 height=15 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12501 x=236 y=254 width=14 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12502 x=18 y=144 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12503 x=90 y=143 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12504 x=248 y=303 width=17 height=12 xoffset=-1 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12505 x=120 y=273 width=17 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12506 x=475 y=285 width=17 height=13 xoffset=-1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12507 x=357 y=236 width=16 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12508 x=415 y=161 width=17 height=17 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12509 x=37 y=183 width=16 height=17 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12510 x=286 y=303 width=16 height=12 xoffset=0 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12511 x=354 y=253 width=11 height=15 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12512 x=18 y=258 width=15 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12513 x=268 y=254 width=14 height=15 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12514 x=215 y=271 width=16 height=14 xoffset=0 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12515 x=131 y=306 width=12 height=13 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12516 x=423 y=199 width=16 height=16 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12517 x=305 y=317 width=14 height=9 xoffset=1 yoffset=10 xadvance=16 page=0 chnl=15
|
||||
char id=12518 x=0 y=307 width=16 height=13 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12519 x=210 y=320 width=12 height=10 xoffset=2 yoffset=9 xadvance=16 page=0 chnl=15
|
||||
char id=12520 x=85 y=306 width=14 height=13 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12521 x=225 y=219 width=14 height=16 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12522 x=39 y=239 width=11 height=16 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12523 x=0 y=275 width=18 height=14 xoffset=-1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12524 x=36 y=307 width=15 height=13 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12525 x=69 y=306 width=14 height=13 xoffset=1 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12526 x=145 y=305 width=12 height=13 xoffset=2 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12527 x=220 y=254 width=14 height=15 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12528 x=19 y=183 width=16 height=17 xoffset=0 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=12529 x=18 y=307 width=16 height=13 xoffset=0 yoffset=6 xadvance=16 page=0 chnl=15
|
||||
char id=12530 x=271 y=219 width=13 height=16 xoffset=2 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12531 x=268 y=271 width=15 height=14 xoffset=1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12532 x=304 y=122 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12533 x=133 y=289 width=12 height=14 xoffset=2 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12534 x=245 y=287 width=12 height=14 xoffset=2 yoffset=7 xadvance=16 page=0 chnl=15
|
||||
char id=12535 x=190 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12536 x=140 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12537 x=329 y=200 width=17 height=16 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12538 x=54 y=144 width=16 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=12539 x=66 y=335 width=6 height=6 xoffset=5 yoffset=10 xadvance=16 page=0 chnl=15
|
||||
char id=12540 x=9 y=335 width=16 height=6 xoffset=0 yoffset=10 xadvance=16 page=0 chnl=15
|
||||
char id=12541 x=343 y=317 width=8 height=9 xoffset=4 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=12542 x=361 y=302 width=11 height=12 xoffset=4 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=12543 x=172 y=201 width=13 height=17 xoffset=1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=19968 x=82 y=334 width=18 height=5 xoffset=-1 yoffset=8 xadvance=16 page=0 chnl=15
|
||||
char id=19975 x=217 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=19979 x=120 y=103 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=19981 x=100 y=103 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20037 x=80 y=103 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20096 x=60 y=103 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20102 x=394 y=121 width=16 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20107 x=40 y=103 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20108 x=60 y=274 width=18 height=14 xoffset=-1 yoffset=5 xadvance=16 page=0 chnl=15
|
||||
char id=20154 x=20 y=104 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20260 x=0 y=104 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20307 x=480 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20316 x=320 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20320 x=340 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20663 x=320 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20814 x=120 y=63 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20837 x=80 y=63 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20853 x=60 y=63 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20891 x=40 y=63 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20986 x=0 y=144 width=16 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=20999 x=480 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21040 x=460 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21147 x=133 y=123 width=17 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21151 x=440 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21315 x=420 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21507 x=377 y=162 width=17 height=17 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21527 x=152 y=122 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21534 x=400 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=21705 x=380 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=22622 x=360 y=41 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=22825 x=340 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=22833 x=260 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=22836 x=220 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=22909 x=160 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=23376 x=140 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=23398 x=120 y=43 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=23544 x=80 y=43 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=23558 x=60 y=43 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24120 x=40 y=43 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24180 x=117 y=0 width=18 height=19 xoffset=-1 yoffset=2 xadvance=16 page=0 chnl=15
|
||||
char id=24320 x=20 y=44 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24433 x=0 y=44 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24471 x=469 y=21 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24515 x=16 y=164 width=19 height=17 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24605 x=197 y=162 width=18 height=17 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=24651 x=357 y=162 width=18 height=17 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=25105 x=449 y=21 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26080 x=409 y=21 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26082 x=369 y=21 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26085 x=187 y=200 width=13 height=17 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
char id=26131 x=457 y=0 width=17 height=19 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26178 x=0 y=124 width=17 height=18 xoffset=0 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26368 x=440 y=101 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26377 x=420 y=101 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26408 x=400 y=101 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=26543 x=380 y=101 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=27493 x=360 y=101 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=27515 x=340 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=27714 x=320 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=27835 x=300 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=27963 x=280 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=28937 x=260 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=29483 x=240 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=29503 x=220 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=29627 x=200 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=29702 x=157 y=163 width=18 height=17 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=29827 x=180 y=102 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=30002 x=159 y=142 width=15 height=18 xoffset=1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=30045 x=460 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=30693 x=440 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=31119 x=420 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=31169 x=348 y=21 width=19 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=31348 x=400 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32299 x=380 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32368 x=360 y=81 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32705 x=340 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32769 x=257 y=162 width=18 height=17 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32773 x=300 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32780 x=280 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32988 x=260 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=32993 x=240 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=33021 x=220 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=33853 x=200 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=34382 x=180 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=34678 x=160 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=34892 x=140 y=82 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=35265 x=120 y=83 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=35328 x=100 y=83 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36208 x=80 y=83 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36335 x=60 y=83 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36523 x=40 y=83 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36817 x=20 y=84 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36820 x=0 y=84 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36861 x=480 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36941 x=460 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=36965 x=440 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=37326 x=420 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=38590 x=400 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=38750 x=380 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=39034 x=360 y=61 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=39118 x=300 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=39135 x=280 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=39340 x=260 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=39532 x=240 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=39543 x=220 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=40575 x=200 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=40614 x=180 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=16 page=0 chnl=15
|
||||
char id=44040 x=160 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44049 x=357 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44057 x=140 y=62 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44060 x=19 y=23 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44163 x=145 y=21 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44221 x=412 y=121 width=16 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44256 x=238 y=237 width=18 height=15 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=44397 x=237 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44536 x=80 y=274 width=18 height=14 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=44544 x=100 y=63 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=44592 x=282 y=21 width=14 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45033 x=466 y=121 width=16 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45149 x=237 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=45208 x=437 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45209 x=0 y=23 width=17 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45212 x=20 y=64 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45216 x=0 y=64 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45320 x=198 y=21 width=15 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45328 x=176 y=142 width=15 height=18 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45397 x=495 y=0 width=15 height=19 xoffset=0 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=45576 x=297 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=45716 x=317 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=45720 x=337 y=162 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=45768 x=266 y=21 width=14 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=45796 x=27 y=0 width=18 height=20 xoffset=-1 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=46020 x=40 y=275 width=18 height=14 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=46024 x=117 y=163 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=46160 x=320 y=42 width=18 height=18 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=46301 x=300 y=42 width=18 height=18 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=46384 x=257 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=46972 x=197 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=46976 x=280 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47000 x=163 y=21 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47196 x=258 y=237 width=18 height=15 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=47336 x=240 y=42 width=18 height=18 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=47476 x=298 y=237 width=18 height=15 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=47484 x=97 y=163 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=47532 x=65 y=0 width=14 height=20 xoffset=0 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=47560 x=277 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47564 x=200 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47568 x=180 y=42 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47588 x=127 y=21 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47673 x=181 y=21 width=15 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=47784 x=318 y=236 width=18 height=15 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=48148 x=297 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=48152 x=317 y=0 width=18 height=19 xoffset=-1 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=48373 x=217 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49373 x=376 y=121 width=16 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49436 x=73 y=22 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49464 x=55 y=22 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49688 x=377 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49845 x=397 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49884 x=125 y=143 width=15 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=49892 x=358 y=122 width=16 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50420 x=100 y=43 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50500 x=417 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50504 x=114 y=123 width=17 height=18 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50506 x=460 y=101 width=17 height=18 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50508 x=76 y=123 width=17 height=18 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50612 x=215 y=21 width=15 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50631 x=249 y=21 width=15 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50640 x=47 y=0 width=16 height=20 xoffset=-1 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=50728 x=77 y=163 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=50836 x=198 y=237 width=18 height=15 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=50857 x=57 y=164 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=50948 x=37 y=22 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=50976 x=489 y=21 width=18 height=18 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=51012 x=37 y=164 width=18 height=17 xoffset=-1 yoffset=4 xadvance=15 page=0 chnl=15
|
||||
char id=51060 x=298 y=21 width=14 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=51080 x=91 y=22 width=16 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=51088 x=337 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=51228 x=109 y=22 width=16 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=51460 x=429 y=21 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=51648 x=232 y=21 width=15 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=51652 x=108 y=143 width=15 height=18 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=52380 x=476 y=0 width=17 height=19 xoffset=-1 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=52840 x=314 y=21 width=14 height=19 xoffset=0 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=54032 x=389 y=21 width=18 height=18 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=54532 x=100 y=274 width=18 height=14 xoffset=-1 yoffset=5 xadvance=15 page=0 chnl=15
|
||||
char id=54616 x=177 y=0 width=18 height=19 xoffset=-1 yoffset=3 xadvance=15 page=0 chnl=15
|
||||
char id=54620 x=157 y=0 width=18 height=19 xoffset=-1 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=54988 x=137 y=0 width=18 height=19 xoffset=-1 yoffset=2 xadvance=15 page=0 chnl=15
|
||||
char id=65292 x=420 y=315 width=5 height=8 xoffset=0 yoffset=15 xadvance=16 page=0 chnl=15
|
||||
char id=65311 x=467 y=217 width=11 height=16 xoffset=2 yoffset=4 xadvance=16 page=0 chnl=15
|
||||
BIN
examples/text/resources/noto_cjk.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
188
examples/text/resources/pixantiqua.fnt
Normal file
@ -0,0 +1,188 @@
|
||||
info face="PixAntiqua" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=2,2,2,2 spacing=2,2 outline=0
|
||||
common lineHeight=32 base=27 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||
page id=0 file="pixantiqua.png"
|
||||
chars count=184
|
||||
char id=32 x=9 y=304 width=7 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=33 x=391 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=34 x=240 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=35 x=468 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=36 x=152 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=37 x=176 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=38 x=303 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=39 x=495 y=266 width=8 height=36 xoffset=-3 yoffset=-2 xadvance=5 page=0 chnl=15
|
||||
char id=40 x=256 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=199 x=432 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=200 x=126 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=201 x=147 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=202 x=288 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=203 x=189 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=204 x=468 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=205 x=486 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=206 x=0 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=207 x=72 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=208 x=329 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=209 x=277 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=210 x=182 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=211 x=26 y=76 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=41 x=272 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=42 x=288 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=43 x=414 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=44 x=378 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=45 x=414 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=46 x=443 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=47 x=392 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=48 x=485 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=49 x=450 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=50 x=21 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=51 x=42 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=59 x=456 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=60 x=168 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=61 x=309 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=62 x=336 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=63 x=315 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=64 x=364 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=65 x=390 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=66 x=120 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=67 x=144 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=68 x=168 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=69 x=294 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=52 x=488 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=53 x=63 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=54 x=24 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=55 x=48 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=56 x=72 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=57 x=96 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=58 x=404 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=70 x=252 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=71 x=192 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=72 x=78 y=76 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=78 x=78 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=79 x=355 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=80 x=264 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=81 x=381 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=82 x=288 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=83 x=312 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=91 x=144 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=92 x=108 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=93 x=304 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=94 x=34 y=0 width=32 height=36 xoffset=-3 yoffset=-2 xadvance=29 page=0 chnl=15
|
||||
char id=95 x=231 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=96 x=442 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=97 x=408 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=98 x=432 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=99 x=210 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=84 x=336 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=85 x=360 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=86 x=0 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=87 x=68 y=0 width=30 height=36 xoffset=-3 yoffset=-2 xadvance=27 page=0 chnl=15
|
||||
char id=88 x=26 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=89 x=384 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=90 x=84 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=100 x=456 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=101 x=480 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=102 x=54 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=103 x=0 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=104 x=24 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=105 x=469 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=106 x=18 y=266 width=16 height=36 xoffset=-8 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=107 x=48 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=108 x=417 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=109 x=161 y=0 width=27 height=36 xoffset=-3 yoffset=-2 xadvance=24 page=0 chnl=15
|
||||
char id=110 x=72 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=111 x=96 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=117 x=192 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=118 x=216 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=119 x=248 y=0 width=27 height=36 xoffset=-3 yoffset=-2 xadvance=24 page=0 chnl=15
|
||||
char id=120 x=240 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=121 x=264 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=122 x=288 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=123 x=432 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=124 x=365 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=125 x=378 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=126 x=393 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=127 x=132 y=0 width=27 height=36 xoffset=-3 yoffset=-2 xadvance=24 page=0 chnl=15
|
||||
char id=160 x=0 y=304 width=7 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=161 x=352 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=162 x=351 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=163 x=336 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=165 x=360 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=167 x=384 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=169 x=433 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=170 x=224 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=171 x=105 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=172 x=0 y=0 width=32 height=36 xoffset=-3 yoffset=-2 xadvance=29 page=0 chnl=15
|
||||
char id=173 x=494 y=38 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=174 x=52 y=76 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=175 x=52 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=176 x=126 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=177 x=435 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=178 x=320 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=179 x=336 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=181 x=459 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=112 x=120 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=113 x=144 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=114 x=396 y=228 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=115 x=168 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=116 x=36 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=182 x=408 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=183 x=498 y=190 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=185 x=192 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=186 x=208 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=187 x=477 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=191 x=456 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=192 x=407 y=0 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=193 x=234 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=194 x=416 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=195 x=156 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=196 x=130 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=197 x=104 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=198 x=190 y=0 width=27 height=36 xoffset=-3 yoffset=-2 xadvance=24 page=0 chnl=15
|
||||
char id=212 x=0 y=76 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=213 x=338 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=214 x=312 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=215 x=357 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=216 x=286 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=217 x=456 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=218 x=480 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=219 x=0 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=220 x=24 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=221 x=48 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=222 x=260 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=223 x=72 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=224 x=96 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=225 x=120 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=226 x=144 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=227 x=168 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=228 x=192 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=229 x=216 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=230 x=219 y=0 width=27 height=36 xoffset=-3 yoffset=-2 xadvance=24 page=0 chnl=15
|
||||
char id=231 x=372 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=73 x=90 y=266 width=16 height=36 xoffset=-3 yoffset=-2 xadvance=13 page=0 chnl=15
|
||||
char id=74 x=216 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=75 x=240 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=76 x=273 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=77 x=100 y=0 width=30 height=36 xoffset=-3 yoffset=-2 xadvance=27 page=0 chnl=15
|
||||
char id=232 x=312 y=152 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=233 x=240 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=234 x=264 y=190 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=235 x=104 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=236 x=430 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=237 x=482 y=266 width=11 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=238 x=160 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=11 page=0 chnl=15
|
||||
char id=239 x=176 y=266 width=14 height=36 xoffset=-3 yoffset=-2 xadvance=8 page=0 chnl=15
|
||||
char id=240 x=128 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=241 x=200 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=242 x=224 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=243 x=248 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=244 x=272 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=245 x=296 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=246 x=320 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=247 x=330 y=190 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=248 x=208 y=38 width=24 height=36 xoffset=-3 yoffset=-2 xadvance=21 page=0 chnl=15
|
||||
char id=249 x=344 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=250 x=368 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=251 x=416 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=252 x=440 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=253 x=464 y=76 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
char id=254 x=0 y=228 width=19 height=36 xoffset=-3 yoffset=-2 xadvance=16 page=0 chnl=15
|
||||
char id=255 x=0 y=114 width=22 height=36 xoffset=-3 yoffset=-2 xadvance=19 page=0 chnl=15
|
||||
BIN
examples/text/resources/pixantiqua.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
examples/text/resources/pixantiqua.ttf
Normal file
20
examples/text/resources/shaders/glsl100/alpha_discard.fs
Normal file
@ -0,0 +1,20 @@
|
||||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 colDiffuse;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texelColor = texture2D(texture0, fragTexCoord);
|
||||
|
||||
if (texelColor.a == 0.0) discard;
|
||||
|
||||
gl_FragColor = texelColor*fragColor*colDiffuse;
|
||||
}
|
||||
25
examples/text/resources/shaders/glsl100/sdf.fs
Normal file
@ -0,0 +1,25 @@
|
||||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 colDiffuse;
|
||||
|
||||
// NOTE: Add your custom variables here
|
||||
const float smoothing = 1.0/16.0;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Texel color fetching from texture sampler
|
||||
// NOTE: Calculate alpha using signed distance field (SDF)
|
||||
float distance = texture2D(texture0, fragTexCoord).a;
|
||||
float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance);
|
||||
|
||||
// Calculate final fragment color
|
||||
gl_FragColor = vec4(fragColor.rgb, fragColor.a*alpha);
|
||||
}
|
||||
19
examples/text/resources/shaders/glsl330/alpha_discard.fs
Normal file
@ -0,0 +1,19 @@
|
||||
#version 330
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 colDiffuse;
|
||||
|
||||
// Output fragment color
|
||||
out vec4 finalColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||
if (texelColor.a == 0.0) discard;
|
||||
finalColor = texelColor * fragColor * colDiffuse;
|
||||
}
|
||||
26
examples/text/resources/shaders/glsl330/sdf.fs
Normal file
@ -0,0 +1,26 @@
|
||||
#version 330
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 colDiffuse;
|
||||
|
||||
// Output fragment color
|
||||
out vec4 finalColor;
|
||||
|
||||
// NOTE: Add your custom variables here
|
||||
|
||||
void main()
|
||||
{
|
||||
// Texel color fetching from texture sampler
|
||||
// NOTE: Calculate alpha using signed distance field (SDF)
|
||||
float distanceFromOutline = texture(texture0, fragTexCoord).a - 0.5;
|
||||
float distanceChangePerFragment = length(vec2(dFdx(distanceFromOutline), dFdy(distanceFromOutline)));
|
||||
float alpha = smoothstep(-distanceChangePerFragment, distanceChangePerFragment, distanceFromOutline);
|
||||
|
||||
// Calculate final fragment color
|
||||
finalColor = vec4(fragColor.rgb, fragColor.a*alpha);
|
||||
}
|
||||
191
examples/text/resources/symbola.fnt
Normal file
@ -0,0 +1,191 @@
|
||||
info face="Symbola" size=-64 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2 outline=2
|
||||
common lineHeight=81 base=59 scaleW=1024 scaleH=1024 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
|
||||
page id=0 file="symbola.png"
|
||||
chars count=187
|
||||
char id=9749 x=135 y=333 width=63 height=61 xoffset=1 yoffset=9 xadvance=65 page=0 chnl=15
|
||||
char id=9752 x=366 y=396 width=57 height=59 xoffset=0 yoffset=10 xadvance=58 page=0 chnl=15
|
||||
char id=9760 x=257 y=0 width=46 height=68 xoffset=0 yoffset=7 xadvance=47 page=0 chnl=15
|
||||
char id=9785 x=61 y=579 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=9786 x=183 y=578 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=10083 x=984 y=200 width=35 height=50 xoffset=1 yoffset=12 xadvance=37 page=0 chnl=15
|
||||
char id=10084 x=266 y=697 width=58 height=44 xoffset=1 yoffset=15 xadvance=60 page=0 chnl=15
|
||||
char id=127744 x=736 y=266 width=40 height=63 xoffset=4 yoffset=10 xadvance=48 page=0 chnl=15
|
||||
char id=127789 x=401 y=637 width=64 height=56 xoffset=0 yoffset=14 xadvance=64 page=0 chnl=15
|
||||
char id=127790 x=697 y=331 width=62 height=60 xoffset=1 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=127791 x=0 y=699 width=64 height=51 xoffset=0 yoffset=17 xadvance=64 page=0 chnl=15
|
||||
char id=127792 x=456 y=202 width=64 height=63 xoffset=0 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=127798 x=523 y=695 width=58 height=35 xoffset=3 yoffset=27 xadvance=64 page=0 chnl=15
|
||||
char id=127805 x=825 y=330 width=60 height=60 xoffset=0 yoffset=11 xadvance=60 page=0 chnl=15
|
||||
char id=127806 x=259 y=268 width=60 height=63 xoffset=0 yoffset=10 xadvance=60 page=0 chnl=15
|
||||
char id=127807 x=322 y=333 width=59 height=61 xoffset=0 yoffset=10 xadvance=60 page=0 chnl=15
|
||||
char id=127808 x=0 y=269 width=63 height=63 xoffset=0 yoffset=9 xadvance=63 page=0 chnl=15
|
||||
char id=127811 x=305 y=396 width=59 height=59 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=127812 x=696 y=0 width=64 height=66 xoffset=2 yoffset=8 xadvance=68 page=0 chnl=15
|
||||
char id=127813 x=61 y=397 width=58 height=60 xoffset=0 yoffset=11 xadvance=58 page=0 chnl=15
|
||||
char id=127814 x=946 y=265 width=61 height=62 xoffset=0 yoffset=9 xadvance=61 page=0 chnl=15
|
||||
char id=127815 x=584 y=635 width=56 height=56 xoffset=0 yoffset=12 xadvance=56 page=0 chnl=15
|
||||
char id=127827 x=121 y=397 width=58 height=60 xoffset=0 yoffset=10 xadvance=58 page=0 chnl=15
|
||||
char id=127828 x=0 y=334 width=68 height=61 xoffset=0 yoffset=10 xadvance=68 page=0 chnl=15
|
||||
char id=127829 x=68 y=70 width=65 height=65 xoffset=0 yoffset=8 xadvance=65 page=0 chnl=15
|
||||
char id=127830 x=737 y=135 width=59 height=64 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=127831 x=560 y=0 width=66 height=66 xoffset=0 yoffset=8 xadvance=66 page=0 chnl=15
|
||||
char id=127832 x=135 y=70 width=65 height=65 xoffset=0 yoffset=8 xadvance=65 page=0 chnl=15
|
||||
char id=127837 x=630 y=331 width=65 height=60 xoffset=0 yoffset=13 xadvance=65 page=0 chnl=15
|
||||
char id=127838 x=628 y=0 width=66 height=66 xoffset=0 yoffset=8 xadvance=66 page=0 chnl=15
|
||||
char id=127839 x=566 y=267 width=59 height=63 xoffset=0 yoffset=9 xadvance=59 page=0 chnl=15
|
||||
char id=127840 x=562 y=332 width=66 height=60 xoffset=0 yoffset=12 xadvance=66 page=0 chnl=15
|
||||
char id=127841 x=798 y=135 width=57 height=64 xoffset=0 yoffset=9 xadvance=57 page=0 chnl=15
|
||||
char id=127842 x=467 y=637 width=57 height=56 xoffset=0 yoffset=13 xadvance=57 page=0 chnl=15
|
||||
char id=127845 x=213 y=137 width=65 height=64 xoffset=0 yoffset=9 xadvance=65 page=0 chnl=15
|
||||
char id=127846 x=950 y=67 width=34 height=65 xoffset=0 yoffset=8 xadvance=34 page=0 chnl=15
|
||||
char id=127850 x=522 y=202 width=64 height=63 xoffset=0 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=127851 x=544 y=135 width=64 height=64 xoffset=0 yoffset=9 xadvance=65 page=0 chnl=15
|
||||
char id=127855 x=440 y=333 width=49 height=61 xoffset=0 yoffset=10 xadvance=49 page=0 chnl=15
|
||||
char id=127856 x=207 y=638 width=64 height=57 xoffset=0 yoffset=11 xadvance=64 page=0 chnl=15
|
||||
char id=127857 x=710 y=633 width=65 height=55 xoffset=0 yoffset=13 xadvance=66 page=0 chnl=15
|
||||
char id=127858 x=237 y=396 width=66 height=59 xoffset=0 yoffset=12 xadvance=66 page=0 chnl=15
|
||||
char id=127859 x=195 y=268 width=62 height=63 xoffset=1 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=127861 x=77 y=0 width=65 height=68 xoffset=0 yoffset=6 xadvance=65 page=0 chnl=15
|
||||
char id=127862 x=857 y=135 width=57 height=64 xoffset=0 yoffset=9 xadvance=58 page=0 chnl=15
|
||||
char id=127863 x=47 y=203 width=41 height=64 xoffset=0 yoffset=9 xadvance=41 page=0 chnl=15
|
||||
char id=127867 x=833 y=633 width=66 height=54 xoffset=0 yoffset=12 xadvance=66 page=0 chnl=15
|
||||
char id=127868 x=986 y=67 width=25 height=53 xoffset=0 yoffset=12 xadvance=25 page=0 chnl=15
|
||||
char id=127870 x=383 y=333 width=55 height=61 xoffset=1 yoffset=10 xadvance=57 page=0 chnl=15
|
||||
char id=127871 x=530 y=394 width=42 height=59 xoffset=0 yoffset=12 xadvance=42 page=0 chnl=15
|
||||
char id=127874 x=0 y=70 width=66 height=65 xoffset=0 yoffset=8 xadvance=66 page=0 chnl=15
|
||||
char id=128065 x=384 y=696 width=68 height=39 xoffset=-2 yoffset=19 xadvance=64 page=0 chnl=15
|
||||
char id=128068 x=132 y=698 width=57 height=47 xoffset=0 yoffset=15 xadvance=57 page=0 chnl=15
|
||||
char id=128069 x=777 y=633 width=54 height=55 xoffset=0 yoffset=14 xadvance=54 page=0 chnl=15
|
||||
char id=128121 x=478 y=136 width=64 height=64 xoffset=0 yoffset=8 xadvance=64 page=0 chnl=15
|
||||
char id=128122 x=65 y=269 width=63 height=63 xoffset=0 yoffset=9 xadvance=63 page=0 chnl=15
|
||||
char id=128123 x=339 y=637 width=60 height=57 xoffset=2 yoffset=14 xadvance=64 page=0 chnl=15
|
||||
char id=128125 x=505 y=267 width=59 height=63 xoffset=0 yoffset=9 xadvance=60 page=0 chnl=15
|
||||
char id=128126 x=321 y=268 width=60 height=63 xoffset=2 yoffset=7 xadvance=64 page=0 chnl=15
|
||||
char id=128127 x=889 y=67 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128128 x=627 y=266 width=55 height=63 xoffset=0 yoffset=9 xadvance=55 page=0 chnl=15
|
||||
char id=128139 x=574 y=394 width=68 height=58 xoffset=0 yoffset=12 xadvance=68 page=0 chnl=15
|
||||
char id=128140 x=202 y=70 width=65 height=65 xoffset=0 yoffset=8 xadvance=65 page=0 chnl=15
|
||||
char id=128147 x=642 y=634 width=66 height=55 xoffset=0 yoffset=12 xadvance=66 page=0 chnl=15
|
||||
char id=128151 x=588 y=201 width=64 height=63 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=128152 x=280 y=137 width=64 height=64 xoffset=0 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=128153 x=654 y=201 width=64 height=63 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=128155 x=720 y=201 width=64 height=63 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=128156 x=786 y=201 width=64 height=63 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=128157 x=77 y=137 width=67 height=64 xoffset=0 yoffset=9 xadvance=68 page=0 chnl=15
|
||||
char id=128159 x=335 y=69 width=64 height=65 xoffset=0 yoffset=8 xadvance=64 page=0 chnl=15
|
||||
char id=128162 x=130 y=268 width=63 height=63 xoffset=0 yoffset=9 xadvance=63 page=0 chnl=15
|
||||
char id=128163 x=146 y=137 width=65 height=64 xoffset=0 yoffset=9 xadvance=65 page=0 chnl=15
|
||||
char id=128164 x=454 y=695 width=67 height=38 xoffset=0 yoffset=23 xadvance=67 page=0 chnl=15
|
||||
char id=128169 x=916 y=134 width=57 height=64 xoffset=0 yoffset=9 xadvance=58 page=0 chnl=15
|
||||
char id=128420 x=852 y=201 width=64 height=63 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=128512 x=732 y=513 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128514 x=644 y=393 width=63 height=58 xoffset=0 yoffset=12 xadvance=63 page=0 chnl=15
|
||||
char id=128515 x=610 y=514 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128518 x=488 y=517 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128519 x=144 y=0 width=59 height=68 xoffset=0 yoffset=7 xadvance=59 page=0 chnl=15
|
||||
char id=128520 x=584 y=68 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128521 x=427 y=517 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128523 x=61 y=519 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128524 x=0 y=519 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128525 x=915 y=452 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128526 x=854 y=452 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128527 x=793 y=453 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128528 x=732 y=453 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128529 x=671 y=453 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128530 x=488 y=457 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128533 x=122 y=459 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128534 x=854 y=572 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128535 x=305 y=457 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128536 x=122 y=579 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128537 x=366 y=517 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128538 x=244 y=577 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128539 x=305 y=577 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128541 x=366 y=577 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128542 x=427 y=577 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128543 x=488 y=577 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128544 x=549 y=575 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128545 x=671 y=573 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128546 x=732 y=573 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128547 x=793 y=573 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128548 x=427 y=0 width=59 height=67 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128549 x=915 y=572 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128550 x=0 y=639 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128553 x=898 y=392 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128554 x=959 y=391 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128555 x=0 y=459 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128556 x=61 y=459 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128557 x=305 y=0 width=59 height=67 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128558 x=183 y=458 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128559 x=244 y=457 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128560 x=709 y=393 width=61 height=58 xoffset=0 yoffset=12 xadvance=62 page=0 chnl=15
|
||||
char id=128561 x=835 y=392 width=61 height=58 xoffset=0 yoffset=12 xadvance=61 page=0 chnl=15
|
||||
char id=128562 x=366 y=457 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128563 x=427 y=457 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128564 x=90 y=203 width=88 height=63 xoffset=0 yoffset=7 xadvance=59 page=0 chnl=15
|
||||
char id=128565 x=549 y=455 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128566 x=610 y=574 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128567 x=610 y=454 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128568 x=401 y=69 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128569 x=878 y=0 width=67 height=65 xoffset=0 yoffset=8 xadvance=67 page=0 chnl=15
|
||||
char id=128570 x=523 y=68 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128571 x=828 y=68 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128573 x=767 y=68 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128575 x=706 y=68 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128576 x=645 y=68 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=128577 x=122 y=519 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128578 x=183 y=518 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128579 x=244 y=517 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=128580 x=305 y=517 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129296 x=200 y=333 width=59 height=61 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129297 x=366 y=0 width=59 height=67 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=129298 x=383 y=268 width=59 height=63 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129299 x=549 y=515 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129300 x=0 y=0 width=75 height=68 xoffset=0 yoffset=7 xadvance=72 page=0 chnl=15
|
||||
char id=129301 x=671 y=513 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129302 x=181 y=396 width=54 height=60 xoffset=2 yoffset=7 xadvance=59 page=0 chnl=15
|
||||
char id=129303 x=778 y=266 width=98 height=62 xoffset=-1 yoffset=12 xadvance=96 page=0 chnl=15
|
||||
char id=129312 x=0 y=137 width=75 height=64 xoffset=-1 yoffset=9 xadvance=74 page=0 chnl=15
|
||||
char id=129314 x=793 y=513 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129315 x=346 y=136 width=64 height=64 xoffset=-1 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=129316 x=444 y=267 width=59 height=63 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129319 x=488 y=0 width=70 height=66 xoffset=0 yoffset=8 xadvance=70 page=0 chnl=15
|
||||
char id=129320 x=854 y=512 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129321 x=915 y=512 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129322 x=0 y=579 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129323 x=762 y=0 width=59 height=66 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=129324 x=772 y=393 width=61 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129325 x=949 y=329 width=59 height=60 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129326 x=261 y=333 width=59 height=61 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129327 x=462 y=69 width=59 height=65 xoffset=0 yoffset=8 xadvance=59 page=0 chnl=15
|
||||
char id=129346 x=975 y=134 width=46 height=64 xoffset=-1 yoffset=8 xadvance=44 page=0 chnl=15
|
||||
char id=129347 x=675 y=135 width=60 height=64 xoffset=-1 yoffset=9 xadvance=58 page=0 chnl=15
|
||||
char id=129360 x=70 y=334 width=63 height=61 xoffset=-1 yoffset=10 xadvance=61 page=0 chnl=15
|
||||
char id=129361 x=191 y=698 width=73 height=45 xoffset=-1 yoffset=18 xadvance=72 page=0 chnl=15
|
||||
char id=129362 x=253 y=203 width=66 height=63 xoffset=-1 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=129363 x=122 y=639 width=83 height=57 xoffset=-1 yoffset=14 xadvance=82 page=0 chnl=15
|
||||
char id=129364 x=491 y=332 width=69 height=60 xoffset=-1 yoffset=11 xadvance=68 page=0 chnl=15
|
||||
char id=129365 x=412 y=136 width=64 height=64 xoffset=-1 yoffset=8 xadvance=63 page=0 chnl=15
|
||||
char id=129366 x=947 y=0 width=66 height=65 xoffset=-1 yoffset=8 xadvance=65 page=0 chnl=15
|
||||
char id=129367 x=180 y=203 width=71 height=63 xoffset=-1 yoffset=8 xadvance=70 page=0 chnl=15
|
||||
char id=129368 x=878 y=266 width=66 height=62 xoffset=-1 yoffset=9 xadvance=65 page=0 chnl=15
|
||||
char id=129369 x=269 y=70 width=64 height=65 xoffset=-1 yoffset=8 xadvance=63 page=0 chnl=15
|
||||
char id=129370 x=823 y=0 width=53 height=66 xoffset=1 yoffset=8 xadvance=55 page=0 chnl=15
|
||||
char id=129371 x=205 y=0 width=50 height=68 xoffset=1 yoffset=7 xadvance=52 page=0 chnl=15
|
||||
char id=129372 x=389 y=202 width=65 height=63 xoffset=1 yoffset=9 xadvance=67 page=0 chnl=15
|
||||
char id=129373 x=887 y=330 width=60 height=60 xoffset=1 yoffset=10 xadvance=62 page=0 chnl=15
|
||||
char id=129374 x=961 y=632 width=61 height=51 xoffset=1 yoffset=15 xadvance=64 page=0 chnl=15
|
||||
char id=129375 x=526 y=637 width=56 height=56 xoffset=1 yoffset=12 xadvance=58 page=0 chnl=15
|
||||
char id=129377 x=425 y=396 width=53 height=59 xoffset=1 yoffset=10 xadvance=56 page=0 chnl=15
|
||||
char id=129378 x=321 y=203 width=66 height=63 xoffset=-1 yoffset=9 xadvance=64 page=0 chnl=15
|
||||
char id=129379 x=761 y=331 width=62 height=60 xoffset=1 yoffset=12 xadvance=64 page=0 chnl=15
|
||||
char id=129380 x=480 y=396 width=48 height=59 xoffset=4 yoffset=13 xadvance=56 page=0 chnl=15
|
||||
char id=129381 x=0 y=397 width=59 height=60 xoffset=0 yoffset=10 xadvance=59 page=0 chnl=15
|
||||
char id=129382 x=684 y=266 width=50 height=63 xoffset=1 yoffset=10 xadvance=53 page=0 chnl=15
|
||||
char id=129383 x=610 y=135 width=63 height=64 xoffset=1 yoffset=8 xadvance=65 page=0 chnl=15
|
||||
char id=129384 x=901 y=632 width=58 height=53 xoffset=2 yoffset=16 xadvance=63 page=0 chnl=15
|
||||
char id=129385 x=326 y=696 width=56 height=41 xoffset=2 yoffset=19 xadvance=60 page=0 chnl=15
|
||||
char id=129386 x=273 y=637 width=64 height=57 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
char id=129387 x=0 y=203 width=45 height=64 xoffset=4 yoffset=9 xadvance=53 page=0 chnl=15
|
||||
char id=129472 x=66 y=699 width=64 height=49 xoffset=0 yoffset=14 xadvance=64 page=0 chnl=15
|
||||
char id=129488 x=61 y=639 width=59 height=58 xoffset=0 yoffset=12 xadvance=59 page=0 chnl=15
|
||||
char id=129505 x=918 y=200 width=64 height=63 xoffset=0 yoffset=10 xadvance=64 page=0 chnl=15
|
||||
BIN
examples/text/resources/symbola.png
Normal file
|
After Width: | Height: | Size: 239 KiB |
586
examples/text/unicode.zig
Normal file
@ -0,0 +1,586 @@
|
||||
//!******************************************************************************************
|
||||
//!
|
||||
//! raylib-zig port of the [text] example - Unicode
|
||||
//! https://github.com/raysan5/raylib/blob/master/examples/text/text_unicode.c
|
||||
//!
|
||||
//! Example complexity rating: [★★★★] 4/4
|
||||
//!
|
||||
//! Example originally created with raylib 2.5, last time updated with raylib 4.0
|
||||
//!
|
||||
//! Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5)
|
||||
//! Translated to raylib-zig by Timothy Fiss (@TheFissk)
|
||||
//!
|
||||
//! 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 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5)
|
||||
//!
|
||||
//!*******************************************************************************************/
|
||||
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
const emoji_per_width = 8;
|
||||
const emoji_per_height = 4;
|
||||
|
||||
// String containing 180 emoji codepoints separated by a '\0' char
|
||||
const emojiCodepoints = "\xF0\x9F\x8C\x80\x00\xF0\x9F\x98\x80\x00\xF0\x9F\x98\x82\x00\xF0\x9F\xA4\xA3\x00\xF0\x9F\x98\x83\x00\xF0\x9F\x98\x86\x00\xF0\x9F\x98\x89\x00" ++
|
||||
"\xF0\x9F\x98\x8B\x00\xF0\x9F\x98\x8E\x00\xF0\x9F\x98\x8D\x00\xF0\x9F\x98\x98\x00\xF0\x9F\x98\x97\x00\xF0\x9F\x98\x99\x00\xF0\x9F\x98\x9A\x00\xF0\x9F\x99\x82\x00" ++
|
||||
"\xF0\x9F\xA4\x97\x00\xF0\x9F\xA4\xA9\x00\xF0\x9F\xA4\x94\x00\xF0\x9F\xA4\xA8\x00\xF0\x9F\x98\x90\x00\xF0\x9F\x98\x91\x00\xF0\x9F\x98\xB6\x00\xF0\x9F\x99\x84\x00" ++
|
||||
"\xF0\x9F\x98\x8F\x00\xF0\x9F\x98\xA3\x00\xF0\x9F\x98\xA5\x00\xF0\x9F\x98\xAE\x00\xF0\x9F\xA4\x90\x00\xF0\x9F\x98\xAF\x00\xF0\x9F\x98\xAA\x00\xF0\x9F\x98\xAB\x00" ++
|
||||
"\xF0\x9F\x98\xB4\x00\xF0\x9F\x98\x8C\x00\xF0\x9F\x98\x9B\x00\xF0\x9F\x98\x9D\x00\xF0\x9F\xA4\xA4\x00\xF0\x9F\x98\x92\x00\xF0\x9F\x98\x95\x00\xF0\x9F\x99\x83\x00" ++
|
||||
"\xF0\x9F\xA4\x91\x00\xF0\x9F\x98\xB2\x00\xF0\x9F\x99\x81\x00\xF0\x9F\x98\x96\x00\xF0\x9F\x98\x9E\x00\xF0\x9F\x98\x9F\x00\xF0\x9F\x98\xA4\x00\xF0\x9F\x98\xA2\x00" ++
|
||||
"\xF0\x9F\x98\xAD\x00\xF0\x9F\x98\xA6\x00\xF0\x9F\x98\xA9\x00\xF0\x9F\xA4\xAF\x00\xF0\x9F\x98\xAC\x00\xF0\x9F\x98\xB0\x00\xF0\x9F\x98\xB1\x00\xF0\x9F\x98\xB3\x00" ++
|
||||
"\xF0\x9F\xA4\xAA\x00\xF0\x9F\x98\xB5\x00\xF0\x9F\x98\xA1\x00\xF0\x9F\x98\xA0\x00\xF0\x9F\xA4\xAC\x00\xF0\x9F\x98\xB7\x00\xF0\x9F\xA4\x92\x00\xF0\x9F\xA4\x95\x00" ++
|
||||
"\xF0\x9F\xA4\xA2\x00\xF0\x9F\xA4\xAE\x00\xF0\x9F\xA4\xA7\x00\xF0\x9F\x98\x87\x00\xF0\x9F\xA4\xA0\x00\xF0\x9F\xA4\xAB\x00\xF0\x9F\xA4\xAD\x00\xF0\x9F\xA7\x90\x00" ++
|
||||
"\xF0\x9F\xA4\x93\x00\xF0\x9F\x98\x88\x00\xF0\x9F\x91\xBF\x00\xF0\x9F\x91\xB9\x00\xF0\x9F\x91\xBA\x00\xF0\x9F\x92\x80\x00\xF0\x9F\x91\xBB\x00\xF0\x9F\x91\xBD\x00" ++
|
||||
"\xF0\x9F\x91\xBE\x00\xF0\x9F\xA4\x96\x00\xF0\x9F\x92\xA9\x00\xF0\x9F\x98\xBA\x00\xF0\x9F\x98\xB8\x00\xF0\x9F\x98\xB9\x00\xF0\x9F\x98\xBB\x00\xF0\x9F\x98\xBD\x00" ++
|
||||
"\xF0\x9F\x99\x80\x00\xF0\x9F\x98\xBF\x00\xF0\x9F\x8C\xBE\x00\xF0\x9F\x8C\xBF\x00\xF0\x9F\x8D\x80\x00\xF0\x9F\x8D\x83\x00\xF0\x9F\x8D\x87\x00\xF0\x9F\x8D\x93\x00" ++
|
||||
"\xF0\x9F\xA5\x9D\x00\xF0\x9F\x8D\x85\x00\xF0\x9F\xA5\xA5\x00\xF0\x9F\xA5\x91\x00\xF0\x9F\x8D\x86\x00\xF0\x9F\xA5\x94\x00\xF0\x9F\xA5\x95\x00\xF0\x9F\x8C\xBD\x00" ++
|
||||
"\xF0\x9F\x8C\xB6\x00\xF0\x9F\xA5\x92\x00\xF0\x9F\xA5\xA6\x00\xF0\x9F\x8D\x84\x00\xF0\x9F\xA5\x9C\x00\xF0\x9F\x8C\xB0\x00\xF0\x9F\x8D\x9E\x00\xF0\x9F\xA5\x90\x00" ++
|
||||
"\xF0\x9F\xA5\x96\x00\xF0\x9F\xA5\xA8\x00\xF0\x9F\xA5\x9E\x00\xF0\x9F\xA7\x80\x00\xF0\x9F\x8D\x96\x00\xF0\x9F\x8D\x97\x00\xF0\x9F\xA5\xA9\x00\xF0\x9F\xA5\x93\x00" ++
|
||||
"\xF0\x9F\x8D\x94\x00\xF0\x9F\x8D\x9F\x00\xF0\x9F\x8D\x95\x00\xF0\x9F\x8C\xAD\x00\xF0\x9F\xA5\xAA\x00\xF0\x9F\x8C\xAE\x00\xF0\x9F\x8C\xAF\x00\xF0\x9F\xA5\x99\x00" ++
|
||||
"\xF0\x9F\xA5\x9A\x00\xF0\x9F\x8D\xB3\x00\xF0\x9F\xA5\x98\x00\xF0\x9F\x8D\xB2\x00\xF0\x9F\xA5\xA3\x00\xF0\x9F\xA5\x97\x00\xF0\x9F\x8D\xBF\x00\xF0\x9F\xA5\xAB\x00" ++
|
||||
"\xF0\x9F\x8D\xB1\x00\xF0\x9F\x8D\x98\x00\xF0\x9F\x8D\x9D\x00\xF0\x9F\x8D\xA0\x00\xF0\x9F\x8D\xA2\x00\xF0\x9F\x8D\xA5\x00\xF0\x9F\x8D\xA1\x00\xF0\x9F\xA5\x9F\x00" ++
|
||||
"\xF0\x9F\xA5\xA1\x00\xF0\x9F\x8D\xA6\x00\xF0\x9F\x8D\xAA\x00\xF0\x9F\x8E\x82\x00\xF0\x9F\x8D\xB0\x00\xF0\x9F\xA5\xA7\x00\xF0\x9F\x8D\xAB\x00\xF0\x9F\x8D\xAF\x00" ++
|
||||
"\xF0\x9F\x8D\xBC\x00\xF0\x9F\xA5\x9B\x00\xF0\x9F\x8D\xB5\x00\xF0\x9F\x8D\xB6\x00\xF0\x9F\x8D\xBE\x00\xF0\x9F\x8D\xB7\x00\xF0\x9F\x8D\xBB\x00\xF0\x9F\xA5\x82\x00" ++
|
||||
"\xF0\x9F\xA5\x83\x00\xF0\x9F\xA5\xA4\x00\xF0\x9F\xA5\xA2\x00\xF0\x9F\x91\x81\x00\xF0\x9F\x91\x85\x00\xF0\x9F\x91\x84\x00\xF0\x9F\x92\x8B\x00\xF0\x9F\x92\x98\x00" ++
|
||||
"\xF0\x9F\x92\x93\x00\xF0\x9F\x92\x97\x00\xF0\x9F\x92\x99\x00\xF0\x9F\x92\x9B\x00\xF0\x9F\xA7\xA1\x00\xF0\x9F\x92\x9C\x00\xF0\x9F\x96\xA4\x00\xF0\x9F\x92\x9D\x00" ++
|
||||
"\xF0\x9F\x92\x9F\x00\xF0\x9F\x92\x8C\x00\xF0\x9F\x92\xA4\x00\xF0\x9F\x92\xA2\x00\xF0\x9F\x92\xA3\x00";
|
||||
|
||||
const Message = struct {
|
||||
text: [:0]const u8,
|
||||
language: [:0]const u8,
|
||||
};
|
||||
|
||||
/// Array containing all of the emojis messages
|
||||
const messages = [_]Message{
|
||||
.{
|
||||
.text = "\x46\x61\x6C\x73\x63\x68\x65\x73\x20\xC3\x9C\x62\x65\x6E\x20\x76\x6F\x6E\x20\x58\x79\x6C\x6F\x70\x68\x6F\x6E\x6D\x75\x73\x69\x6B\x20\x71\x75\xC3\xA4\x6C\x74\x20\x6A\x65\x64\x65\x6E\x20\x67\x72\xC3\xB6\xC3\x9F\x65\x72\x65\x6E\x20\x5A\x77\x65\x72\x67",
|
||||
.language = "German",
|
||||
},
|
||||
.{
|
||||
.text = "\x42\x65\x69\xC3\x9F\x20\x6E\x69\x63\x68\x74\x20\x69\x6E\x20\x64\x69\x65\x20\x48\x61\x6E\x64\x2C\x20\x64\x69\x65\x20\x64\x69\x63\x68\x20\x66\xC3\xBC\x74\x74\x65\x72\x74\x2E",
|
||||
.language = "German",
|
||||
},
|
||||
.{
|
||||
.text = "\x41\x75\xC3\x9F\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\xC3\x9C\x62\x65\x6C\x20\x65\x72\x66\x6F\x72\x64\x65\x72\x6E\x20\x61\x75\xC3\x9F\x65\x72\x6F\x72\x64\x65\x6E\x74\x6C\x69\x63\x68\x65\x20\x4D\x69\x74\x74\x65\x6C\x2E",
|
||||
.language = "German",
|
||||
},
|
||||
.{
|
||||
.text = "\xD4\xBF\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB4\x20\xD5\xA1\xD5\xBA\xD5\xA1\xD5\xAF\xD5\xAB\x20\xD5\xB8\xD6\x82\xD5\xBF\xD5\xA5\xD5\xAC\x20\xD6\x87\x20\xD5\xAB\xD5\xB6\xD5\xAE\xD5\xAB\x20\xD5\xA1\xD5\xB6\xD5\xB0\xD5\xA1\xD5\xB6\xD5\xA3\xD5\xAB\xD5\xBD\xD5\xBF\x20\xD5\xB9\xD5\xA8\xD5\xB6\xD5\xA5\xD6\x80",
|
||||
.language = "Armenian",
|
||||
},
|
||||
.{
|
||||
.text = "\xD4\xB5\xD6\x80\xD5\xA2\x20\xD5\xB8\xD6\x80\x20\xD5\xAF\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\xD5\xA8\x20\xD5\xA5\xD5\xAF\xD5\xA1\xD6\x82\x20\xD5\xA1\xD5\xB6\xD5\xBF\xD5\xA1\xD5\xBC\x2C\x20\xD5\xAE\xD5\xA1\xD5\xBC\xD5\xA5\xD6\x80\xD5\xA8\x20\xD5\xA1\xD5\xBD\xD5\xA1\xD6\x81\xD5\xAB\xD5\xB6\x2E\x2E\x2E\x20\xC2\xAB\xD4\xBF\xD5\xB8\xD5\xBF\xD5\xA8\x20\xD5\xB4\xD5\xA5\xD6\x80\xD5\xB8\xD5\xB6\xD6\x81\xD5\xAB\xD6\x81\x20\xD5\xA7\x3A\xC2\xBB",
|
||||
.language = "Armenian",
|
||||
},
|
||||
.{
|
||||
.text = "\xD4\xB3\xD5\xA1\xD5\xBC\xD5\xA8\xD5\x9D\x20\xD5\xA3\xD5\xA1\xD6\x80\xD5\xB6\xD5\xA1\xD5\xB6\x2C\x20\xD5\xB1\xD5\xAB\xD6\x82\xD5\xB6\xD5\xA8\xD5\x9D\x20\xD5\xB1\xD5\xB4\xD5\xBC\xD5\xA1\xD5\xB6",
|
||||
.language = "Armenian",
|
||||
},
|
||||
.{
|
||||
.text = "\x4A\x65\xC5\xBC\x75\x20\x6B\x6C\xC4\x85\x74\x77\x2C\x20\x73\x70\xC5\x82\xC3\xB3\x64\xC5\xBA\x20\x46\x69\x6E\x6F\x6D\x20\x63\x7A\xC4\x99\xC5\x9B\xC4\x87\x20\x67\x72\x79\x20\x68\x61\xC5\x84\x62\x21",
|
||||
.language = "Polish",
|
||||
},
|
||||
.{
|
||||
.text = "\x44\x6F\x62\x72\x79\x6D\x69\x20\x63\x68\xC4\x99\x63\x69\x61\x6D\x69\x20\x6A\x65\x73\x74\x20\x70\x69\x65\x6B\xC5\x82\x6F\x20\x77\x79\x62\x72\x75\x6B\x6F\x77\x61\x6E\x65\x2E",
|
||||
.language = "Polish",
|
||||
},
|
||||
.{
|
||||
.text = "\xC3\x8E\xC8\x9B\x69\x20\x6D\x75\x6C\xC8\x9B\x75\x6D\x65\x73\x63\x20\x63\xC4\x83\x20\x61\x69\x20\x61\x6C\x65\x73\x20\x72\x61\x79\x6C\x69\x62\x2E\x0A\xC8\x98\x69\x20\x73\x70\x65\x72\x20\x73\xC4\x83\x20\x61\x69\x20\x6F\x20\x7A\x69\x20\x62\x75\x6E\xC4\x83\x21",
|
||||
.language = "Romanian",
|
||||
},
|
||||
.{
|
||||
.text = "\xD0\xAD\xD1\x85\x2C\x20\xD1\x87\xD1\x83\xD0\xB6\xD0\xB0\xD0\xBA\x2C\x20\xD0\xBE\xD0\xB1\xD1\x89\xD0\xB8\xD0\xB9\x20\xD1\x81\xD1\x8A\xD1\x91\xD0\xBC\x20\xD1\x86\xD0\xB5\xD0\xBD\x20\xD1\x88\xD0\xBB\xD1\x8F\xD0\xBF\x20\x28\xD1\x8E\xD1\x84\xD1\x82\xD1\x8C\x29\x20\xD0\xB2\xD0\xB4\xD1\x80\xD1\x8B\xD0\xB7\xD0\xB3\x21",
|
||||
.language = "Russian",
|
||||
},
|
||||
.{
|
||||
.text = "\xD0\xAF\x20\xD0\xBB\xD1\x8E\xD0\xB1\xD0\xBB\xD1\x8E\x20\x72\x61\x79\x6C\x69\x62\x21",
|
||||
.language = "Russian",
|
||||
},
|
||||
.{
|
||||
.text = "\xD0\x9C\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2C\x20\xD1\x81\xD0\xBA\xD1\x80\xD1\x8B\xD0\xB2\xD0\xB0\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\x20\xD1\x82\xD0\xB0\xD0\xB8\x0A\xD0\x98\x20\xD1\x87\xD1\x83\xD0\xB2\xD1\x81\xD1\x82\xD0\xB2\xD0\xB0\x20\xD0\xB8\x20\xD0\xBC\xD0\xB5\xD1\x87\xD1\x82\xD1\x8B\x20\xD1\x81\xD0\xB2\xD0\xBE\xD0\xB8\x20\xE2\x80\x93\x0A\xD0\x9F\xD1\x83\xD1\x81\xD0\xBA\xD0\xB0\xD0\xB9\x20\xD0\xB2\x20\xD0\xB4\xD1\x83\xD1\x88\xD0\xB5\xD0\xB2\xD0\xBD\xD0\xBE\xD0\xB9\x20\xD0\xB3\xD0\xBB\xD1\x83\xD0\xB1\xD0\xB8\xD0\xBD\xD0\xB5\x0A\xD0\x98\x20\xD0\xB2\xD1\x81\xD1\x85\xD0\xBE\xD0\xB4\xD1\x8F\xD1\x82\x20\xD0\xB8\x20\xD0\xB7\xD0\xB0\xD0\xB9\xD0\xB4\xD1\x83\xD1\x82\x20\xD0\xBE\xD0\xBD\xD0\xB5\x0A\xD0\x9A\xD0\xB0\xD0\xBA\x20\xD0\xB7\xD0\xB2\xD0\xB5\xD0\xB7\xD0\xB4\xD1\x8B\x20\xD1\x8F\xD1\x81\xD0\xBD\xD1\x8B\xD0\xB5\x20\xD0\xB2\x20\xD0\xBD\xD0\xBE\xD1\x87\xD0\xB8\x2D\x0A\xD0\x9B\xD1\x8E\xD0\xB1\xD1\x83\xD0\xB9\xD1\x81\xD1\x8F\x20\xD0\xB8\xD0\xBC\xD0\xB8\x20\xE2\x80\x93\x20\xD0\xB8\x20\xD0\xBC\xD0\xBE\xD0\xBB\xD1\x87\xD0\xB8\x2E",
|
||||
.language = "Russian",
|
||||
},
|
||||
.{
|
||||
.text = "\x56\x6F\x69\x78\x20\x61\x6D\x62\x69\x67\x75\xC3\xAB\x20\x64\xE2\x80\x99\x75\x6E\x20\x63\xC5\x93\x75\x72\x20\x71\x75\x69\x20\x61\x75\x20\x7A\xC3\xA9\x70\x68\x79\x72\x20\x70\x72\xC3\xA9\x66\xC3\xA8\x72\x65\x20\x6C\x65\x73\x20\x6A\x61\x74\x74\x65\x73\x20\x64\x65\x20\x6B\x69\x77\x69",
|
||||
.language = "French",
|
||||
},
|
||||
.{
|
||||
.text = "\x42\x65\x6E\x6A\x61\x6D\xC3\xAD\x6E\x20\x70\x69\x64\x69\xC3\xB3\x20\x75\x6E\x61\x20\x62\x65\x62\x69\x64\x61\x20\x64\x65\x20\x6B\x69\x77\x69\x20\x79\x20\x66\x72\x65\x73\x61\x3B\x20\x4E\x6F\xC3\xA9\x2C\x20\x73\x69\x6E\x20\x76\x65\x72\x67\xC3\xBC\x65\x6E\x7A\x61\x2C\x20\x6C\x61\x20\x6D\xC3\xA1\x73\x20\x65\x78\x71\x75\x69\x73\x69\x74\x61\x20\x63\x68\x61\x6D\x70\x61\xC3\xB1\x61\x20\x64\x65\x6C\x20\x6D\x65\x6E\xC3\xBA\x2E",
|
||||
.language = "Spanish",
|
||||
},
|
||||
.{
|
||||
.text = "\xCE\xA4\xCE\xB1\xCF\x87\xCE\xAF\xCF\x83\xCF\x84\xCE\xB7\x20\xCE\xB1\xCE\xBB\xCF\x8E\xCF\x80\xCE\xB7\xCE\xBE\x20\xCE\xB2\xCE\xB1\xCF\x86\xCE\xAE\xCF\x82\x20\xCF\x88\xCE\xB7\xCE\xBC\xCE\xAD\xCE\xBD\xCE\xB7\x20\xCE\xB3\xCE\xB7\x2C\x20\xCE\xB4\xCF\x81\xCE\xB1\xCF\x83\xCE\xBA\xCE\xB5\xCE\xBB\xCE\xAF\xCE\xB6\xCE\xB5\xCE\xB9\x20\xCF\x85\xCF\x80\xCE\xAD\xCF\x81\x20\xCE\xBD\xCF\x89\xCE\xB8\xCF\x81\xCE\xBF\xCF\x8D\x20\xCE\xBA\xCF\x85\xCE\xBD\xCF\x8C\xCF\x82",
|
||||
.language = "Greek",
|
||||
},
|
||||
.{
|
||||
.text = "\xCE\x97\x20\xCE\xBA\xCE\xB1\xCE\xBB\xCF\x8D\xCF\x84\xCE\xB5\xCF\x81\xCE\xB7\x20\xCE\xAC\xCE\xBC\xCF\x85\xCE\xBD\xCE\xB1\x20\xCE\xB5\xCE\xAF\xCE\xBD\xCE\xB1\xCE\xB9\x20\xCE\xB7\x20\xCE\xB5\xCF\x80\xCE\xAF\xCE\xB8\xCE\xB5\xCF\x83\xCE\xB7\x2E",
|
||||
.language = "Greek",
|
||||
},
|
||||
.{
|
||||
.text = "\xCE\xA7\xCF\x81\xCF\x8C\xCE\xBD\xCE\xB9\xCE\xB1\x20\xCE\xBA\xCE\xB1\xCE\xB9\x20\xCE\xB6\xCE\xB1\xCE\xBC\xCE\xAC\xCE\xBD\xCE\xB9\xCE\xB1\x21",
|
||||
.language = "Greek",
|
||||
},
|
||||
.{
|
||||
.text = "\xCE\xA0\xCF\x8E\xCF\x82\x20\xCF\x84\xCE\xB1\x20\xCF\x80\xCE\xB1\xCF\x82\x20\xCF\x83\xCE\xAE\xCE\xBC\xCE\xB5\xCF\x81\xCE\xB1\x3B",
|
||||
.language = "Greek",
|
||||
},
|
||||
.{
|
||||
.text = "\xE6\x88\x91\xE8\x83\xBD\xE5\x90\x9E\xE4\xB8\x8B\xE7\x8E\xBB\xE7\x92\x83\xE8\x80\x8C\xE4\xB8\x8D\xE4\xBC\xA4\xE8\xBA\xAB\xE4\xBD\x93\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE4\xBD\xA0\xE5\x90\x83\xE4\xBA\x86\xE5\x90\x97\xEF\xBC\x9F",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE4\xB8\x8D\xE4\xBD\x9C\xE4\xB8\x8D\xE6\xAD\xBB\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE6\x9C\x80\xE8\xBF\x91\xE5\xA5\xBD\xE5\x90\x97\xEF\xBC\x9F",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE5\xA1\x9E\xE7\xBF\x81\xE5\xA4\xB1\xE9\xA9\xAC\xEF\xBC\x8C\xE7\x84\x89\xE7\x9F\xA5\xE9\x9D\x9E\xE7\xA6\x8F\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE5\x8D\x83\xE5\x86\x9B\xE6\x98\x93\xE5\xBE\x97\x2C\x20\xE4\xB8\x80\xE5\xB0\x86\xE9\x9A\xBE\xE6\xB1\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE4\xB8\x87\xE4\xBA\x8B\xE5\xBC\x80\xE5\xA4\xB4\xE9\x9A\xBE\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE9\xA3\x8E\xE6\x97\xA0\xE5\xB8\xB8\xE9\xA1\xBA\xEF\xBC\x8C\xE5\x85\xB5\xE6\x97\xA0\xE5\xB8\xB8\xE8\x83\x9C\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE6\xB4\xBB\xE5\x88\xB0\xE8\x80\x81\xEF\xBC\x8C\xE5\xAD\xA6\xE5\x88\xB0\xE8\x80\x81\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE4\xB8\x80\xE8\xA8\x80\xE6\x97\xA2\xE5\x87\xBA\xEF\xBC\x8C\xE9\xA9\xB7\xE9\xA9\xAC\xE9\x9A\xBE\xE8\xBF\xBD\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE8\xB7\xAF\xE9\x81\xA5\xE7\x9F\xA5\xE9\xA9\xAC\xE5\x8A\x9B\xEF\xBC\x8C\xE6\x97\xA5\xE4\xB9\x85\xE8\xA7\x81\xE4\xBA\xBA\xE5\xBF\x83",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE6\x9C\x89\xE7\x90\x86\xE8\xB5\xB0\xE9\x81\x8D\xE5\xA4\xA9\xE4\xB8\x8B\xEF\xBC\x8C\xE6\x97\xA0\xE7\x90\x86\xE5\xAF\xB8\xE6\xAD\xA5\xE9\x9A\xBE\xE8\xA1\x8C\xE3\x80\x82",
|
||||
.language = "Chinese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE7\x8C\xBF\xE3\x82\x82\xE6\x9C\xA8\xE3\x81\x8B\xE3\x82\x89\xE8\x90\xBD\xE3\x81\xA1\xE3\x82\x8B",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE4\xBA\x80\xE3\x81\xAE\xE7\x94\xB2\xE3\x82\x88\xE3\x82\x8A\xE5\xB9\xB4\xE3\x81\xAE\xE5\x8A\x9F",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE3\x81\x86\xE3\x82\x89\xE3\x82\x84\xE3\x81\xBE\xE3\x81\x97\x20\x20\xE6\x80\x9D\xE3\x81\xB2\xE5\x88\x87\xE3\x82\x8B\xE6\x99\x82\x20\x20\xE7\x8C\xAB\xE3\x81\xAE\xE6\x81\x8B",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE8\x99\x8E\xE7\xA9\xB4\xE3\x81\xAB\xE5\x85\xA5\xE3\x82\x89\xE3\x81\x9A\xE3\x82\x93\xE3\x81\xB0\xE8\x99\x8E\xE5\xAD\x90\xE3\x82\x92\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE4\xBA\x8C\xE5\x85\x8E\xE3\x82\x92\xE8\xBF\xBD\xE3\x81\x86\xE8\x80\x85\xE3\x81\xAF\xE4\xB8\x80\xE5\x85\x8E\xE3\x82\x92\xE3\x82\x82\xE5\xBE\x97\xE3\x81\x9A\xE3\x80\x82",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE9\xA6\xAC\xE9\xB9\xBF\xE3\x81\xAF\xE6\xAD\xBB\xE3\x81\xAA\xE3\x81\xAA\xE3\x81\x8D\xE3\x82\x83\xE6\xB2\xBB\xE3\x82\x89\xE3\x81\xAA\xE3\x81\x84\xE3\x80\x82",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE6\x9E\xAF\xE9\x87\x8E\xE8\xB7\xAF\xE3\x81\xAB\xE3\x80\x80\xE5\xBD\xB1\xE3\x81\x8B\xE3\x81\x95\xE3\x81\xAA\xE3\x82\x8A\xE3\x81\xA6\xE3\x80\x80\xE3\x82\x8F\xE3\x81\x8B\xE3\x82\x8C\xE3\x81\x91\xE3\x82\x8A",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xE7\xB9\xB0\xE3\x82\x8A\xE8\xBF\x94\xE3\x81\x97\xE9\xBA\xA6\xE3\x81\xAE\xE7\x95\x9D\xE7\xB8\xAB\xE3\x81\xB5\xE8\x83\xA1\xE8\x9D\xB6\xE5\x93\x89",
|
||||
.language = "Japanese",
|
||||
},
|
||||
.{
|
||||
.text = "\xEC\x95\x84\xEB\x93\x9D\xED\x95\x9C\x20\xEB\xB0\x94\xEB\x8B\xA4\x20\xEC\x9C\x84\xEC\x97\x90\x20\xEA\xB0\x88\xEB\xA7\xA4\xEA\xB8\xB0\x20\xEB\x91\x90\xEC\x97\x87\x20\xEB\x82\xA0\xEC\x95\x84\x20\xEB\x8F\x88\xEB\x8B\xA4\x2E\x0A\xEB\x84\x88\xED\x9B\x8C\xEB\x84\x88\xED\x9B\x8C\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E\x20\xEB\xAA\xA8\xEB\xA5\xB4\xEB\x8A\x94\x20\xEB\x82\x98\xEB\x9D\xBC\x20\xEA\xB8\x80\xEC\x9E\x90\xEB\x8B\xA4\x2E\x0A\xEB\x84\x90\xEB\x94\xB0\xEB\x9E\x80\x20\xED\x95\x98\xEB\x8A\x98\x20\xEB\xB3\xB5\xED\x8C\x90\xEC\x97\x90\x20\xEB\x82\x98\xEB\x8F\x84\x20\xEA\xB0\x99\xEC\x9D\xB4\x20\xEC\x8B\x9C\xEB\xA5\xBC\x20\xEC\x93\xB4\xEB\x8B\xA4\x2E",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEC\xA0\x9C\x20\xEB\x88\x88\xEC\x97\x90\x20\xEC\x95\x88\xEA\xB2\xBD\xEC\x9D\xB4\xEB\x8B\xA4",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEA\xBF\xA9\x20\xEB\xA8\xB9\xEA\xB3\xA0\x20\xEC\x95\x8C\x20\xEB\xA8\xB9\xEB\x8A\x94\xEB\x8B\xA4",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEB\xA1\x9C\xEB\xA7\x88\xEB\x8A\x94\x20\xED\x95\x98\xEB\xA3\xA8\xEC\x95\x84\xEC\xB9\xA8\xEC\x97\x90\x20\xEC\x9D\xB4\xEB\xA3\xA8\xEC\x96\xB4\xEC\xA7\x84\x20\xEA\xB2\x83\xEC\x9D\xB4\x20\xEC\x95\x84\xEB\x8B\x88\xEB\x8B\xA4",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEA\xB3\xA0\xEC\x83\x9D\x20\xEB\x81\x9D\xEC\x97\x90\x20\xEB\x82\x99\xEC\x9D\xB4\x20\xEC\x98\xA8\xEB\x8B\xA4",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEA\xB0\x9C\xEC\xB2\x9C\xEC\x97\x90\xEC\x84\x9C\x20\xEC\x9A\xA9\x20\xEB\x82\x9C\xEB\x8B\xA4",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEC\x95\x88\xEB\x85\x95\xED\x95\x98\xEC\x84\xB8\xEC\x9A\x94\x3F",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xEB\xA7\x8C\xEB\x82\x98\xEC\x84\x9C\x20\xEB\xB0\x98\xEA\xB0\x91\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4",
|
||||
.language = "Korean",
|
||||
},
|
||||
.{
|
||||
.text = "\xED\x95\x9C\xEA\xB5\xAD\xEB\xA7\x90\x20\xED\x95\x98\xEC\x8B\xA4\x20\xEC\xA4\x84\x20\xEC\x95\x84\xEC\x84\xB8\xEC\x9A\x94\x3F",
|
||||
.language = "Korean",
|
||||
},
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Global variables
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Arrays that holds the random emojis
|
||||
const Emoji = struct {
|
||||
index: usize, // Index inside `emojiCodepoints`
|
||||
message: *const Message, // Message index
|
||||
color: rl.Color, // Emoji color
|
||||
};
|
||||
|
||||
var emojis: [emoji_per_height * emoji_per_width]Emoji = undefined;
|
||||
|
||||
var hovered: ?*Emoji = null;
|
||||
var selected_emoji: ?*Emoji = null;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screen_width = 800;
|
||||
const screen_height = 450;
|
||||
|
||||
rl.setConfigFlags(.{ .msaa_4x_hint = true, .vsync_hint = true });
|
||||
rl.initWindow(screen_width, screen_height, "raylib [text] example - unicode");
|
||||
defer rl.closeWindow();
|
||||
|
||||
// Load the font resources
|
||||
// NOTE: fontAsian is for asian languages,
|
||||
// fontEmoji is the emojis and fontDefault is used for everything else
|
||||
const font_default = try rl.loadFont("examples/text/resources/dejavu.fnt");
|
||||
defer rl.unloadFont(font_default);
|
||||
const font_asian = try rl.loadFont("examples/text/resources/noto_cjk.fnt");
|
||||
defer rl.unloadFont(font_asian);
|
||||
const font_emoji = try rl.loadFont("examples/text/resources/symbola.fnt");
|
||||
defer rl.unloadFont(font_emoji);
|
||||
|
||||
var hovered_pos = rl.Vector2{ .x = 0.0, .y = 0.0 };
|
||||
var selected_pos = rl.Vector2{ .x = 0.0, .y = 0.0 };
|
||||
|
||||
// Set a random set of emojis when starting up
|
||||
randomizeEmoji();
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// Add a new set of emojis when SPACE is pressed
|
||||
if (rl.isKeyPressed(.space)) randomizeEmoji();
|
||||
|
||||
// Set the selected emoji
|
||||
if (rl.isMouseButtonPressed(.left) and (hovered != null) and (hovered != selected_emoji)) {
|
||||
selected_emoji = hovered;
|
||||
selected_pos = hovered_pos;
|
||||
}
|
||||
|
||||
const mouse = rl.getMousePosition();
|
||||
var position = rl.Vector2{ .x = 28.8, .y = 10.0 };
|
||||
hovered = null;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
// Draw random emojis in the background
|
||||
//------------------------------------------------------------------------------
|
||||
for (&emojis, 0..) |*emoji, i| {
|
||||
const txt = emojiCodepoints[emoji.index..];
|
||||
const emoji_rect = rl.Rectangle{
|
||||
.x = position.x,
|
||||
.y = position.y,
|
||||
.height = @floatFromInt(font_emoji.baseSize),
|
||||
.width = @floatFromInt(font_emoji.baseSize),
|
||||
};
|
||||
|
||||
if (!rl.checkCollisionPointRec(mouse, emoji_rect)) {
|
||||
rl.drawTextEx(font_emoji, txt, position, @floatFromInt(font_emoji.baseSize), 1.0, if (selected_emoji == emoji) emoji.color else rl.fade(.light_gray, 0.4));
|
||||
} else {
|
||||
rl.drawTextEx(font_emoji, txt, position, @floatFromInt(font_emoji.baseSize), 1.0, emoji.color);
|
||||
hovered = emoji;
|
||||
hovered_pos = position;
|
||||
}
|
||||
|
||||
if ((i != 0) and (i % emoji_per_width == 0)) {
|
||||
position.y += @as(f32, @floatFromInt(font_emoji.baseSize)) + 24.25;
|
||||
position.x = 28.8;
|
||||
} else {
|
||||
position.x += @as(f32, @floatFromInt(font_emoji.baseSize)) + 28.8;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Draw the message when a emoji is selected
|
||||
//------------------------------------------------------------------------------
|
||||
if (selected_emoji) |selected| {
|
||||
const message = selected.message;
|
||||
const horizontal_padding = 20;
|
||||
const vertical_padding = 30;
|
||||
var font = &font_default;
|
||||
|
||||
// Set correct font for asian languages
|
||||
font = if (rl.textIsEqual(message.language, "Chinese") or
|
||||
rl.textIsEqual(message.language, "Korean") or
|
||||
rl.textIsEqual(message.language, "Japanese")) &font_asian else font;
|
||||
|
||||
// Calculate size for the message box (approximate the height and width)
|
||||
var sz = rl.measureTextEx(font.*, message.text, @floatFromInt(font.baseSize), 1.0);
|
||||
if (sz.x > 300) {
|
||||
sz.y *= sz.x / 300;
|
||||
sz.x = 300;
|
||||
} else if (sz.x < 160) {
|
||||
sz.x = 160;
|
||||
}
|
||||
|
||||
var msg_rect = rl.Rectangle{
|
||||
.x = selected_pos.x - 38.8,
|
||||
.y = selected_pos.y,
|
||||
.width = 2 * horizontal_padding + sz.x,
|
||||
.height = 2 * vertical_padding + sz.y,
|
||||
};
|
||||
msg_rect.y -= msg_rect.height;
|
||||
|
||||
// Coordinates for the chat bubble triangle
|
||||
var a = rl.Vector2{ .x = selected_pos.x, .y = msg_rect.y + msg_rect.height };
|
||||
var b = rl.Vector2{ .x = a.x + 8, .y = a.y + 10 };
|
||||
var c = rl.Vector2{ .x = a.x + 10, .y = a.y };
|
||||
|
||||
// Don't go outside the screen
|
||||
if (msg_rect.x < 10) msg_rect.x += 28;
|
||||
if (msg_rect.y < 10) {
|
||||
msg_rect.y = selected_pos.y + 84;
|
||||
a.y = msg_rect.y;
|
||||
c.y = a.y;
|
||||
b.y = a.y - 10;
|
||||
|
||||
// Swap values so we can actually render the triangle :(
|
||||
const tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
if (msg_rect.x + msg_rect.width > screen_width) msg_rect.x -= (msg_rect.x + msg_rect.width) - screen_width + 10;
|
||||
|
||||
// Draw chat bubble
|
||||
rl.drawRectangleRec(msg_rect, selected.color);
|
||||
rl.drawTriangle(a, b, c, selected.color);
|
||||
|
||||
// Draw the main text message
|
||||
const text_rect = rl.Rectangle{
|
||||
.x = msg_rect.x + horizontal_padding / 2,
|
||||
.y = msg_rect.y + vertical_padding / 2,
|
||||
.width = msg_rect.width - horizontal_padding,
|
||||
.height = msg_rect.height,
|
||||
};
|
||||
drawTextBoxed(font.*, message.text, text_rect, @floatFromInt(font.baseSize), 1.0, true, .white);
|
||||
|
||||
// Draw the info text below the main message
|
||||
const size = message.text.len;
|
||||
const length = rl.getCodepointCount(message.text);
|
||||
const info = rl.textFormat("%s %u characters %i bytes", .{ message.language.ptr, length, size });
|
||||
sz = rl.measureTextEx(font_default, info, 10, 1.0);
|
||||
|
||||
rl.drawText(info, @intFromFloat(text_rect.x + text_rect.width - sz.x), @intFromFloat(msg_rect.y + msg_rect.height - sz.y - 2), 10, .ray_white);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Draw the info text
|
||||
rl.drawText("These emojis have something to tell you, click each to find out!", (screen_width - 650) / 2, screen_height - 40, 20, .gray);
|
||||
rl.drawText("Each emoji is a unicode character from a font, not a texture... Press [SPACEBAR] to refresh", (screen_width - 484) / 2, screen_height - 16, 10, .gray);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
// Fills the emoji array with random emoji (only those emojis present in fontEmoji)
|
||||
fn randomizeEmoji() void {
|
||||
hovered = null;
|
||||
selected_emoji = null;
|
||||
const start = rl.getRandomValue(45, 360);
|
||||
|
||||
for (&emojis, 0..) |*emoji, i| {
|
||||
// 0-179 emoji codepoints (from emoji char array) each 4bytes + null char
|
||||
emoji.index = @intCast(rl.getRandomValue(0, 179) * 5);
|
||||
|
||||
// Generate a random color for this emoji
|
||||
const hue: f32 = @floatFromInt(@rem(start * @as(i32, @intCast(i + 1)), 360));
|
||||
emoji.color = rl.fade(rl.colorFromHSV(hue, 0.6, 0.85), 0.8);
|
||||
|
||||
// Set a random message for this emoji
|
||||
emoji.message = &messages[@intCast(rl.getRandomValue(0, messages.len - 1))];
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Module functions definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw text using font inside rectangle limits
|
||||
fn drawTextBoxed(font: rl.Font, text: [:0]const u8, rec: rl.Rectangle, font_size: f32, spacing: f32, word_wrap: bool, tint: rl.Color) void {
|
||||
drawTextBoxedSelectable(font, text, rec, font_size, spacing, word_wrap, tint, 0, 0, .white, .white);
|
||||
}
|
||||
|
||||
// Draw text using font inside rectangle limits with support for text selection
|
||||
fn drawTextBoxedSelectable(font: rl.Font, text: [:0]const u8, rec: rl.Rectangle, font_size: f32, spacing: f32, word_wrap: bool, tint: rl.Color, select_box_start: i32, select_length: i32, select_tint: rl.Color, select_back_tint: rl.Color) void {
|
||||
var select_start = select_box_start;
|
||||
const length = rl.textLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||
|
||||
var text_offset_y: f32 = 0; // Offset between lines (on line break '\n')
|
||||
var text_offset_x: f32 = 0.0; // Offset X to next character to draw
|
||||
|
||||
const scale_factor = font_size / @as(f32, @floatFromInt(font.baseSize)); // Character rectangle scaling factor
|
||||
|
||||
// Word/character wrapping mechanism variables
|
||||
const MeasureState = enum(u8) { measure, draw };
|
||||
var state: MeasureState = if (word_wrap) .measure else .draw;
|
||||
|
||||
var start_line: i32 = -1; // Index where to begin drawing (where a line begins)
|
||||
var end_line: i32 = -1; // Index where to stop drawing (where a line ends)
|
||||
var last_char: i32 = -1; // Holds last value of the character position
|
||||
|
||||
var i: i32 = 0;
|
||||
var k: i32 = 0;
|
||||
while (i < length) : ({
|
||||
i += 1;
|
||||
k += 1;
|
||||
}) {
|
||||
// Get next codepoint from byte string and glyph index in font
|
||||
var codepoint_byte_count: i32 = 0;
|
||||
const codepoint = rl.getCodepoint(text[@intCast(i)..], &codepoint_byte_count);
|
||||
const index: usize = @intCast(rl.getGlyphIndex(font, codepoint));
|
||||
|
||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||
if (codepoint == 0x3f) codepoint_byte_count = 1;
|
||||
i += @intCast(codepoint_byte_count - 1);
|
||||
|
||||
var glyph_width: f32 = 0;
|
||||
if (codepoint != '\n') {
|
||||
glyph_width = if (font.glyphs[index].advanceX == 0) font.recs[index].width * scale_factor else @as(f32, @floatFromInt(font.glyphs[index].advanceX)) * scale_factor;
|
||||
|
||||
if (i + 1 < length) glyph_width = glyph_width + spacing;
|
||||
}
|
||||
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
|
||||
// We store this info in startLine and endLine, then we change states, draw the text between those two variables
|
||||
// and change states again and again recursively until the end of the text (or until we get outside of the container).
|
||||
// When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
|
||||
// and begin drawing on the next line before we can get outside the container.
|
||||
if (state == .measure) {
|
||||
// TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
|
||||
// Ref: http://jkorpela.fi/chars/spaces.html
|
||||
if ((codepoint == ' ') or (codepoint == '\t') or (codepoint == '\n')) end_line = @intCast(i);
|
||||
|
||||
if ((text_offset_x + glyph_width) > rec.width) {
|
||||
end_line = if (end_line < 1) @intCast(i) else end_line;
|
||||
if (i == end_line) end_line -= codepoint_byte_count;
|
||||
if ((start_line + codepoint_byte_count) == end_line) end_line = @as(i32, @intCast(i)) - codepoint_byte_count;
|
||||
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
} else if ((i + 1) == length) {
|
||||
end_line = @intCast(i);
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
} else if (codepoint == '\n') {
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
}
|
||||
|
||||
if (state == .draw) {
|
||||
text_offset_x = 0;
|
||||
i = @intCast(start_line);
|
||||
glyph_width = 0;
|
||||
|
||||
// Save character position when we switch states
|
||||
const tmp = last_char;
|
||||
last_char = k - 1;
|
||||
k = tmp;
|
||||
}
|
||||
} else {
|
||||
if (codepoint == '\n') {
|
||||
if (!word_wrap) {
|
||||
const bS: f32 = @floatFromInt(font.baseSize);
|
||||
text_offset_y += (bS + bS / 2) * scale_factor;
|
||||
text_offset_x = 0;
|
||||
}
|
||||
} else {
|
||||
if (!word_wrap and ((text_offset_x + glyph_width) > rec.width)) {
|
||||
const bS: f32 = @floatFromInt(font.baseSize);
|
||||
text_offset_y += (bS + bS / 2) * scale_factor;
|
||||
text_offset_x = 0;
|
||||
}
|
||||
|
||||
// When text overflows rectangle height limit, just stop drawing
|
||||
if ((text_offset_y + @as(f32, @floatFromInt(font.baseSize)) * scale_factor) > rec.height) break;
|
||||
|
||||
// Draw selection background
|
||||
var is_glyph_selected = false;
|
||||
if ((select_start >= 0) and (k >= select_start) and (k < (select_start + select_length))) {
|
||||
rl.drawRectangleRec(.{
|
||||
.x = rec.x + text_offset_x - 1,
|
||||
.y = rec.y + text_offset_y,
|
||||
.width = glyph_width,
|
||||
.height = @as(f32, @floatFromInt(font.baseSize)) * scale_factor,
|
||||
}, select_back_tint);
|
||||
is_glyph_selected = true;
|
||||
}
|
||||
|
||||
// Draw current character glyph
|
||||
if ((codepoint != ' ') and (codepoint != '\t')) {
|
||||
rl.drawTextCodepoint(font, codepoint, .{
|
||||
.x = rec.x + text_offset_x,
|
||||
.y = rec.y + text_offset_y,
|
||||
}, font_size, if (is_glyph_selected) select_tint else tint);
|
||||
}
|
||||
}
|
||||
|
||||
if (word_wrap and (i == end_line)) {
|
||||
const bS: f32 = @floatFromInt(font.baseSize);
|
||||
text_offset_y += (bS + bS / 2) * scale_factor;
|
||||
text_offset_x = 0;
|
||||
start_line = end_line;
|
||||
end_line = -1;
|
||||
glyph_width = 0;
|
||||
select_start += last_char - k;
|
||||
k = last_char;
|
||||
|
||||
state = if (state == .draw) .measure else .draw;
|
||||
}
|
||||
}
|
||||
|
||||
if ((text_offset_x != 0) or (codepoint != ' ')) text_offset_x += glyph_width; // avoid leading spaces
|
||||
}
|
||||
}
|
||||
46
examples/text/writing_anim.zig
Normal file
@ -0,0 +1,46 @@
|
||||
const rl = @import("raylib");
|
||||
const Color = rl.Color;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
pub fn main() void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rl.initWindow(screenWidth, screenHeight, "raylib [text] example - text writing anim");
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
const message = "This sample illustrates a text writing\nanimation effect! Check it out! ;)";
|
||||
|
||||
var framesCounter: i32 = 0;
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rl.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
framesCounter += if (rl.isKeyDown(.space)) 8 else 1;
|
||||
|
||||
if (rl.isKeyPressed(.enter)) framesCounter = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
|
||||
rl.clearBackground(Color.white);
|
||||
|
||||
rl.drawText(rl.textSubtext(message, 0, @divFloor(framesCounter, 10)), 210, 160, 20, Color.maroon);
|
||||
|
||||
rl.drawText("PRESS [ENTER] to RESTART!", 240, 260, 20, Color.light_gray);
|
||||
rl.drawText("HOLD [SPACE] to SPEED UP!", 239, 300, 20, Color.light_gray);
|
||||
|
||||
rl.endDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@ -17,7 +17,7 @@ pub fn main() anyerror!void {
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
|
||||
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
|
||||
const scarfy: rl.Texture = rl.Texture.init("resources/textures/scarfy.png"); // Texture loading
|
||||
const scarfy = try rl.Texture.init("resources/textures/scarfy.png"); // Texture loading
|
||||
defer rl.unloadTexture(scarfy); // Texture unloading
|
||||
|
||||
const position = rl.Vector2.init(350.0, 280.0);
|
||||
@ -51,9 +51,9 @@ pub fn main() anyerror!void {
|
||||
}
|
||||
|
||||
// Control frames speed
|
||||
if (rl.isKeyPressed(rl.KeyboardKey.key_right)) {
|
||||
if (rl.isKeyPressed(.right)) {
|
||||
framesSpeed += 1;
|
||||
} else if (rl.isKeyPressed(rl.KeyboardKey.key_left)) {
|
||||
} else if (rl.isKeyPressed(.left)) {
|
||||
framesSpeed -= 1;
|
||||
}
|
||||
|
||||
@ -70,37 +70,37 @@ pub fn main() anyerror!void {
|
||||
rl.beginDrawing();
|
||||
defer rl.endDrawing();
|
||||
|
||||
rl.clearBackground(rl.Color.ray_white);
|
||||
rl.clearBackground(.ray_white);
|
||||
|
||||
rl.drawTexture(scarfy, 15, 40, rl.Color.white);
|
||||
rl.drawRectangleLines(15, 40, scarfy.width, scarfy.height, rl.Color.lime);
|
||||
rl.drawTexture(scarfy, 15, 40, .white);
|
||||
rl.drawRectangleLines(15, 40, scarfy.width, scarfy.height, .lime);
|
||||
rl.drawRectangleLines(
|
||||
15 + @as(i32, @intFromFloat(frameRec.x)),
|
||||
40 + @as(i32, @intFromFloat(frameRec.y)),
|
||||
@as(i32, @intFromFloat(frameRec.width)),
|
||||
@as(i32, @intFromFloat(frameRec.height)),
|
||||
rl.Color.red,
|
||||
.red,
|
||||
);
|
||||
|
||||
rl.drawText("FRAME SPEED: ", 165, 210, 10, rl.Color.dark_gray);
|
||||
rl.drawText(rl.textFormat("%02i FPS", .{framesSpeed}), 575, 210, 10, rl.Color.dark_gray);
|
||||
rl.drawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, rl.Color.dark_gray);
|
||||
rl.drawText("FRAME SPEED: ", 165, 210, 10, .dark_gray);
|
||||
rl.drawText(rl.textFormat("%02i FPS", .{framesSpeed}), 575, 210, 10, .dark_gray);
|
||||
rl.drawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, .dark_gray);
|
||||
|
||||
for ([_]u32{0} ** MAX_FRAME_SPEED, 0..) |_, i| {
|
||||
if (i < framesSpeed) {
|
||||
rl.drawRectangle(250 + 21 * @as(i32, @intCast(i)), 205, 20, 20, rl.Color.red);
|
||||
rl.drawRectangle(250 + 21 * @as(i32, @intCast(i)), 205, 20, 20, .red);
|
||||
}
|
||||
rl.drawRectangleLines(250 + 21 * @as(i32, @intCast(i)), 205, 20, 20, rl.Color.maroon);
|
||||
rl.drawRectangleLines(250 + 21 * @as(i32, @intCast(i)), 205, 20, 20, .maroon);
|
||||
}
|
||||
|
||||
scarfy.drawRec(frameRec, position, rl.Color.white); // Draw part of the texture
|
||||
scarfy.drawRec(frameRec, position, .white); // Draw part of the texture
|
||||
|
||||
rl.drawText(
|
||||
"(c) Scarfy sprite by Eiden Marsal",
|
||||
screenWidth - 200,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
rl.Color.gray,
|
||||
.gray,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
@ -20,9 +20,9 @@ pub fn main() anyerror!void {
|
||||
|
||||
// NOTE: Be careful, background width must be equal or bigger than screen width
|
||||
// if not, texture should be draw more than two times for scrolling effect
|
||||
const background = rl.loadTexture("resources/textures/cyberpunk_street_background.png");
|
||||
const midground = rl.loadTexture("resources/textures/cyberpunk_street_midground.png");
|
||||
const foreground = rl.loadTexture("resources/textures/cyberpunk_street_foreground.png");
|
||||
const background = try rl.loadTexture("resources/textures/cyberpunk_street_background.png");
|
||||
const midground = try rl.loadTexture("resources/textures/cyberpunk_street_midground.png");
|
||||
const foreground = try rl.loadTexture("resources/textures/cyberpunk_street_foreground.png");
|
||||
defer rl.unloadTexture(background); // Unload background texture
|
||||
defer rl.unloadTexture(midground); // Unload midground texture
|
||||
defer rl.unloadTexture(foreground); // Unload foreground texture
|
||||
@ -59,49 +59,49 @@ pub fn main() anyerror!void {
|
||||
// NOTE: Texture is scaled twice its size
|
||||
rl.drawTextureEx(
|
||||
background,
|
||||
rl.Vector2.init(scrolling_back, 20.0),
|
||||
.init(scrolling_back, 20.0),
|
||||
0.0,
|
||||
2.0,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
rl.drawTextureEx(
|
||||
background,
|
||||
rl.Vector2.init(@as(f32, @floatFromInt(background.width * 2)) + scrolling_back, 20),
|
||||
.init(@as(f32, @floatFromInt(background.width * 2)) + scrolling_back, 20),
|
||||
0.0,
|
||||
2.0,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
|
||||
// Draw midground image twice
|
||||
rl.drawTextureEx(
|
||||
midground,
|
||||
rl.Vector2.init(scrolling_mid, 20.0),
|
||||
.init(scrolling_mid, 20.0),
|
||||
0.0,
|
||||
2.0,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
rl.drawTextureEx(
|
||||
midground,
|
||||
rl.Vector2.init(@as(f32, @floatFromInt(midground.width * 2)) + scrolling_mid, 20),
|
||||
.init(@as(f32, @floatFromInt(midground.width * 2)) + scrolling_mid, 20),
|
||||
0.0,
|
||||
2.0,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
|
||||
// Draw foreground image twice
|
||||
rl.drawTextureEx(
|
||||
foreground,
|
||||
rl.Vector2.init(scrolling_fore, 70.0),
|
||||
.init(scrolling_fore, 70.0),
|
||||
0.0,
|
||||
2.0,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
rl.drawTextureEx(
|
||||
foreground,
|
||||
rl.Vector2.init(@as(f32, @floatFromInt(foreground.width * 2)) + scrolling_fore, 70),
|
||||
.init(@as(f32, @floatFromInt(foreground.width * 2)) + scrolling_fore, 70),
|
||||
0.0,
|
||||
2.0,
|
||||
rl.Color.white,
|
||||
.white,
|
||||
);
|
||||
|
||||
rl.drawText(
|
||||
@ -109,14 +109,14 @@ pub fn main() anyerror!void {
|
||||
10,
|
||||
10,
|
||||
20,
|
||||
rl.Color.red,
|
||||
.red,
|
||||
);
|
||||
rl.drawText(
|
||||
"(c) Cyberpunk Street Environment by Luis Zuno (@ansimuz)",
|
||||
screen_width - 330,
|
||||
screen_height - 20,
|
||||
10,
|
||||
rl.Color.ray_white,
|
||||
.ray_white,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
67
examples/textures/textures_image_loading.zig
Normal file
@ -0,0 +1,67 @@
|
||||
// raylib-zig (c) Nikolas Wipper 2023
|
||||
//
|
||||
// raylib-zig [textures] example - image loading
|
||||
//
|
||||
// Example licensed under an unmodified zlib/libpng license, which is an
|
||||
// OSI-certified, BSD-like license that allows static linking with closed
|
||||
// source software
|
||||
|
||||
const rl = @import("raylib");
|
||||
const Color = rl.Color;
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Program entry point
|
||||
//--------------------------------------------------------------------------------------
|
||||
pub fn main() anyerror!void {
|
||||
//Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
rl.initWindow(
|
||||
screenWidth,
|
||||
screenHeight,
|
||||
"raylib [textures] example - image loading",
|
||||
);
|
||||
|
||||
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
const image = try rl.loadImage("logo/logo.png"); // Loaded in CPU memory (RAM)
|
||||
const texture = try rl.loadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
|
||||
// Once image has been converted to texture and uploaded to VRAM,
|
||||
// it can be unloaded from RAM
|
||||
rl.unloadImage(image);
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
defer rl.closeWindow(); // Close window and OpenGL context
|
||||
defer rl.unloadTexture(texture); // Texture unloading
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
while (!rl.windowShouldClose()) {
|
||||
// Update
|
||||
//--------------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//--------------------------------------------------------------------------------------
|
||||
rl.beginDrawing();
|
||||
rl.clearBackground(Color.white);
|
||||
rl.drawTexture(
|
||||
texture,
|
||||
screenWidth / 2 - @divFloor(texture.width, 2),
|
||||
screenHeight / 2 - @divFloor(texture.height, 2),
|
||||
Color.white,
|
||||
);
|
||||
rl.drawText(
|
||||
"this IS a texture loaded from an image!",
|
||||
300,
|
||||
370,
|
||||
10,
|
||||
Color.gray,
|
||||
);
|
||||
rl.endDrawing();
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||