1 Commits

Author SHA1 Message Date
Ray
46b9579f0c Update README.md 2026-07-16 15:03:30 +02:00
267 changed files with 30121 additions and 38016 deletions

View File

@ -71,7 +71,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -90,7 +90,7 @@ jobs:
cmake --build . --config $BUILD_TYPE
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
upload: false
@ -99,7 +99,7 @@ jobs:
# Filter out rules with low severity or high false positve rate
# Also filter out warnings in third-party code
- name: Filter out unwanted errors and warnings
uses: advanced-security/filter-sarif@v1.1
uses: advanced-security/filter-sarif@v1
with:
patterns: |
-**:cpp/path-injection
@ -121,7 +121,7 @@ jobs:
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
- name: Upload CodeQL results to code scanning
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ steps.step1.outputs.sarif-output }}
category: "/language:${{matrix.language}}"

View File

@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@master
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v3
uses: microsoft/setup-msbuild@v1
- name: Build Library (MSVC16)
run: |

View File

@ -1,81 +0,0 @@
name: Clang Tidy Lints
on:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: clang-tidy-${{ github.ref }}
cancel-in-progress: true
jobs:
clang-tidy:
name: C lint
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install clang-tidy 19
run: |
sudo apt-get update
sudo apt-get install --yes clang-tidy-19
- name: Run clang-tidy
shell: bash
run: |
checks='-*,
bugprone-assignment-in-if-condition,
bugprone-infinite-loop,
bugprone-misplaced-widening-cast,
bugprone-multiple-statement-macro,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-memset-usage,
readability-duplicate-include,
readability-redundant-casting,
readability-simplify-boolean-expr'
lint_log="$(mktemp)"
filtered_log="$(mktemp)"
lint_pattern='\[(bugprone|readability)-[^]]+\]'
echo "Using clang-tidy:"
clang-tidy-19 --version
echo
echo "Running clang-tidy..."
# Capture everything silently. Do not use tee here.
find src \
-path 'src/external' -prune \
-o -type f -name '*.c' -exec \
clang-tidy-19 \
--quiet \
--checks="$checks" \
--header-filter='.*' \
--exclude-header-filter='(^|.*/)external/.*' \
{} -- \
-std=c11 \
-Isrc \
-isystem src/external \
\; >"$lint_log" 2>&1 || true
# Retain only selected lint warnings, then remove any remaining
# diagnostics whose path passes through an external directory.
grep -E "$lint_pattern" "$lint_log" |
grep -Ev '(^|/)([^/]+/\.\./)*external/' \
>"$filtered_log" || true
if [[ -s "$filtered_log" ]]; then
echo "clang-tidy found the following lint violations:"
echo
cat "$filtered_log"
echo
echo "::error::clang-tidy found lint violations."
exit 1
fi
echo "clang-tidy found no selected lint violations."

View File

@ -1,218 +1,190 @@
# raylib bindings and wrappers
Some people ported raylib to other languages in the form of bindings or wrappers to the library. Here is a list with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list or if it had been updated/archived.
# Recommendations for binding authors.
This is a set of recomendations and guidelines for binding authors, meant to help your binding be as useful as possible to your users.
* Binding should be reasonably up to date with the last release, out of date bindings may be removed from bindings.md
* Binding should expose all of raylib's API. This is to ensure compatibility with all raylib features, and allow your users to do everything in the target language they can do in C raylib.
* raylib.h
* raymath.h
* rcamera.h
* rlgl.h
* rgestures.h
* Bindings should expose the base API in order to match the C examples when possible.
* Bindings that expose additional 'high level' functions to make the binding more native to the host language, should also include the base C style API in addition to those other functions. This is requested in order to make it easier for people to understand the raylib API independent of the language being used.
* Bindings should have clear usage and setup instructions. Examples in the host language are highly recommended. You want your users to be able to get started right away.
* If a binding exists for a language, before making a new one, binding authors should try to work together on maintaining a single binding for a language, this is requested in order to prevent fragmentation and confusion for users.
* Instructions on how to build for web are highly recomeneed if the langauge supports it. This allows your bindings to be used for game jams :)
Some people ported raylib to other languages in the form of bindings or wrappers to the library. Here is a list with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list.
### Language Bindings
| Name | raylib Version | Language | License |
| :--------------------------------------------------------------------------------------: | :--------------: | :---------------------------------------------------------------------: | :------------------: |
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **6.0** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
| [raylib-asm](https://github.com/gAndy50/ASMRay) | **6.0** | [Assembly (x86)](https://en.wikipedia.org/wiki/X86_assembly_language) | Zlib |
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **auto** | [Beef](https://www.beeflang.org) | MIT |
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT |
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **6.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
| [chicken-raylib](https://github.com/meowstr/chicken-raylib) | 5.5 | [CHICKEN Scheme](https://wiki.call-cc.org) | MIT |
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 6.0 | [Crystal](https://crystal-lang.org) | Apache-2.0 |
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
| [raylib_dart](https://pub.dev/packages/raylib_dart) | 6.0 | [Dart](https://dart.dev) | MIT |
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
| [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib |
| [Deno-Raylib](https://github.com/JJLDonley/Deno-Raylib) | **6.0** | [Deno / TS](https://deno.land) | MIT |
| [rayex](https://github.com/shiryel/rayex) | 5.5 | [elixir](https://elixir-lang.org) | Apache-2.0 |
| [raylib-elfscript](https://github.com/ohmtal/raylib-elfscript) | 6.0 | [ElfScript](https://github.com/ohmtal/ElfScript) | MIT |
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 6.0 | [Factor](https://factorcode.org) | BSD |
| [raystar](https://github.com/RobertFlexx/raystar) | **6.0** | [F*](https://www.fstar-lang.org/) | EPL-2.0 |
| [raylib4fb](https://codeberg.org/mudhairless/raylib4fb) | **6.0** | [FreeBASIC](https://www.freebasic.net) | Zlib |
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **6.0** | [Fortran](https://fortran-lang.org) | ISC |
| [raylib-go](https://github.com/gen2brain/raylib-go) | **6.0** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **6.1-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 5.5 | [Haxe](https://haxe.org) | Zlib |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
| [jaylib](https://github.com/electronstudio/jaylib/) | **6.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.2 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 6.0 | [Lua](http://www.lua.org) | ISC |
| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
| [raylib_mojo](https://github.com/willGuimont/raylib_mojo) | **6.0** | [Mojo](https://www.modular.com/mojo) | ZLib |
| [raymojo](https://github.com/RobertFlexx/raymojo) | **6.0** | [Mojo](https://www.modular.com/mojo) | GPLv3 |
| [raymod](https://github.com/RobertFlexx/raymod) | **6.0** | [Modula-2](https://en.wikipedia.org/wiki/Modula-2) / [Modula-3](https://en.wikipedia.org/wiki/Modula-3) | Apache-2.0 |
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | 6.1-dev | [nelua](https://nelua.io) | Zlib |
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 6.1-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
| [node-raylib](https://github.com/RobLoach/node-raylib) | 5.5 | [Node.js](https://nodejs.org/en) | Zlib |
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **6.0** | [Odin](https://odin-lang.org) | Zlib |
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **6.0** | [OCaml](https://ocaml.org) | MIT |
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
| [Rayberon](https://github.com/RobertFlexx/Rayberon) | **6.0** | [Oberon-2](https://en.wikipedia.org/wiki/Oberon-2) | MIT |
| [EuRaylib](https://github.com/gAndy50/EuRaylib6) | **6.0** | [openEuphoria](https://openeuphoria.org/) | Zlib |
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **6.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **6.0** | [Python](https://www.python.org) | EPL-2.0 |
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-py](https://github.com/overdev/raylib-py) | **6.0** | [Python](https://www.python.org) | MIT |
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.5 | [pocketpy](https://pocketpy.dev) | MIT |
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylibr](https://github.com/jeroenjanssens/raylibr) | auto | [R](https://www.r-project.org) | MIT |
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
| [racket-raylib](https://github.com/eutro/racket-raylib) | **6.0** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **6.0** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
| [raylib-solod](https://github.com/solod-dev/raylib) | 6.0 | [Solod](https://solod.dev) | BSD-3-Clause |
| [rayscal](https://github.com/RobertFlexx/rayscal) | **6.0** | [Scala Native](https://scala-native.org) | MIT |
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
| [raylib-v](https://github.com/vlang/raylib) | auto | [V](https://vlang.io) | MIT/Unlicense |
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib |
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** | [Wave](http://wave-lang.dev) | Zlib |
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **6.0** | [Zig](https://ziglang.org) | MIT |
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.6-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **auto** | [Dyalog APL](https://www.dyalog.com/) | MIT |
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **6.0** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
| [Target](https://github.com/FinnDemonCat/Target/tree/main/lib/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
| [mach-raylib](https://github.com/angluca/mach-raylib) | **6.x-dev** | [Mach](https://machlang.org/) | MIT |
| [gcl native raylib module](https://github.com/gnuchanos/GnuchanOS/tree/main/language) | **6.0** | [gclang](https://github.com/gnuchanos/GnuchanOS/tree/main/language) | GPLv3 |
| Name | raylib Version | Language | License |
| :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: |
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT |
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT |
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **6.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
| [chicken-raylib](https://github.com/meowstr/chicken-raylib) | 5.5 | [CHICKEN Scheme](https://wiki.call-cc.org) | MIT |
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 |
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
| [raylib_dart](https://pub.dev/packages/raylib_dart) | 6.0 | [Dart](https://dart.dev) | MIT |
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
| [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib |
| [Deno-Raylib](https://github.com/JJLDonley/Deno-Raylib) | **6.0** | [Deno / TS](https://deno.land) | MIT |
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 |
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD |
| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **6.0** | [FreeBASIC](https://www.freebasic.net) | Zlib |
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
| [raylib-go](https://github.com/gen2brain/raylib-go) | **6.0** | [Go](https://golang.org) | Zlib |
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT |
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
| [jaylib](https://github.com/electronstudio/jaylib/) | **5.5** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** |
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.5** | [nelua](https://nelua.io) | Zlib |
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
| [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) | MIT |
| [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib |
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.5** | [Odin](https://odin-lang.org) | Zlib |
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **6.0** | [OCaml](https://ocaml.org) | MIT |
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **6.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib |
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib |
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 |
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-py](https://github.com/overdev/raylib-py) | 5.5 | [Python](https://www.python.org) | MIT |
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.1-dev | [pocketpy](https://pocketpy.dev) | MIT |
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.5** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
| [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense |
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib |
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib |
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **6.0** | [Zig](https://ziglang.org) | MIT |
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
| [rayjule](https://github.com/SabeDoesThings/rayjule) | **5.5** | [Jule](https://jule.dev/) | MIT |
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT |
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **6.0** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
| [gclang-raylib](https://github.com/gnuchanos/gcLang_Compiler/tree/main/windows_version/raylib_version)| **6.0** | [gclang](https://github.com/gnuchanos/gcLang_Compiler) | AGPL-3.0 |
### Utility Wrappers
### Utility Wrapers
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm.
| Name | raylib Version | Language | License |
| ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: |
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **6.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
| [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
| [DOOR](https://github.com/RealDoigt/DOOR) | 4.0 | [D](https://dlang.org) | MIT |
| [Iris](https://github.com/Marcos-cat/iris) | **5.5** | [Uiua](https://www.uiua.org/) | MIT |
### Older or Unmaintained Language Bindings
These are older raylib bindings that are more than 2 versions old or have not been maintained.
| Name | raylib Version | Language |
| :--------------------------------------------------------------------------------------: | :--------------: | :---------------------------------------------------------------------: |
| [raylib-cppsharp](https://github.com/phxvyper/raylib-cppsharp) | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
| [RaylibFS](https://github.com/dallinbeutler/RaylibFS) | 2.5 | [F#](https://fsharp.org) |
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) |
| [raylib\*d](https://github.com/Sepheus/raylib_d) | 2.5 | [D](https://dlang.org) |
| [bindbc-raylib](https://github.com/o3o/bindbc-raylib) | 3.0 | [D](https://dlang.org) |
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) |
| [go-raylib](https://github.com/chunqian/go-raylib) | 3.5 | [Go](https://golang.org) |
| [raylib-goplus](https://github.com/Lachee/raylib-goplus) | 2.6-dev | [Go](https://golang.org) |
| [ray-go](https://github.com/hecate-tech/ray-go) | 2.6-dev | [Go](https://golang.org) |
| [raylib-luamore](https://github.com/HDPLocust/raylib-luamore) | 3.0 | [Lua](http://www.lua.org) |
| [LuaJIT-Raylib](https://github.com/Bambofy/LuaJIT-Raylib) | 2.6 | [Lua](http://www.lua.org) |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 2.5 | [Lua](http://www.lua.org) |
| [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) | 2.0 | [Lua](http://www.lua.org) |
| [raylib-lua](https://github.com/raysan5/raylib-lua) | 1.7 | [Lua](http://www.lua.org) |
| [raylib-nelua](https://github.com/Andre-LA/raylib-nelua) | 3.0 | [Nelua](https://nelua.io) |
| [raylib-nim](https://github.com/Skrylar/raylib-nim) | 2.0 | [Nim](https://nim-lang.org) |
| [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) | 1.7 | [Nim](https://nim-lang.org) |
| [nim-raylib](https://github.com/tomc1998/nim-raylib) | 3.1-dev | [Nim](https://nim-lang.org) |
| [raylib-Forever](https://github.com/Guevara-chan/Raylib-Forever) | auto | [Nim](https://nim-lang.org) |
| [NimraylibNow!](https://github.com/greenfork/nimraylib_now) | 4.2 | [Nim](https://nim-lang.org) |
| [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) |
| [raylib-haskell](https://github.com/DevJac/raylib-haskell) | 2.0 | [Haskell](https://www.haskell.org) |
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.7 | [Harbour](https://harbour.github.io) |
| [raylib-cr](https://github.com/AregevDev/raylib-cr) | 2.5-dev | [Crystal](https://crystal-lang.org) |
| [raylib.cr](https://github.com/sam0x17/raylib.cr) | 2.0 | [Crystal](https://crystal-lang.org) |
| [cray](https://gitlab.com/Zatherz/cray) | 1.8 | [Crystal](https://crystal-lang.org) |
| [raylib-pas](https://github.com/tazdij/raylib-pas) | 3.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [raylib-pascal](https://github.com/drezgames/raylib-pascal) | 2.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [Graphics-Raylib](https://github.com/athreef/Graphics-Raylib) | 1.4 | [Perl](https://www.perl.org) |
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) |
| [raylib-ruby](https://github.com/a0/raylib-ruby) | 2.6 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) | 2.0 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) | 2.5-dev | [mruby](https://github.com/mruby/mruby) |
| [raylib-java](https://github.com/XoanaIO/raylib-java) | 2.0 | [Java](https://en.wikipedia.org/wiki/Java*(programming_language)) |
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) |
| [clj-raylib](https://github.com/lsevero/clj-raylib) | 3.0 | [Clojure](https://clojure.org) |
| [QuickJS-raylib](https://github.com/sntg-p/QuickJS-raylib) | 3.0 | [QuickJS](https://bellard.org/quickjs) |
| [raylib-duktape](https://github.com/RobLoach/raylib-duktape) | 2.6 | [JavaScript (Duktape)](https://en.wikipedia.org/wiki/JavaScript) |
| [rayjule](https://github.com/SabeDoesThings/rayjule) | **5.5** | [Jule](https://jule.dev/) |
| [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) | 2.6 | [ChaiScript](http://chaiscript.com) |
| [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) | 2.5 | [Squirrel](http://www.squirrel-lang.org) |
| [racket-raylib-2d](https://github.com/arvyy/racket-raylib-2d) | 2.5 | [Racket](https://racket-lang.org) |
| [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) | 2.4-dev | [PHP](https://en.wikipedia.org/wiki/PHP) |
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) |
| [raylib-haxe](https://github.com/ibilon/raylib-haxe) | 2.4 | [Haxe](https://haxe.org) |
| [ringraylib](https://github.com/ringpackages/ringraylib) | 2.6 | [Ring](http://ring-lang.sourceforge.net) |
| [raylib-scm](https://github.com/yashrk/raylib-scm) | 2.5 | [Chicken Scheme](https://www.call-cc.org) |
| [raylib-chibi](https://github.com/VincentToups/raylib-chibi) | 2.5 | [Chibi-Scheme](https://github.com/ashinn/chibi-scheme) |
| [raylib-gambit-scheme](https://github.com/georgjz/raylib-gambit-scheme) | 3.1-dev | [Gambit Scheme](https://github.com/gambit/gambit) |
| [Euraylib](https://github.com/gAndy50/Euraylib) | 3.0 | [Euphoria](https://openeuphoria.org) |
| [raylib-odin](https://github.com/kevinw/raylib-odin) | 3.0 | [Odin](https://odin-lang.org) |
| [vraylib](https://github.com/waotzi/vraylib) | 3.5 | [V](https://vlang.io) |
| [raylib-vala](https://code.guddler.uk/mart/raylibVapi) | 3.0 | [Vala](https://wiki.gnome.org/Projects/Vala) |
| [raylib-jai](https://github.com/kujukuju/raylib-jai) | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) |
| [ray.zig](https://github.com/BitPuffin/zig-raylib-experiments) | 2.5 | [Zig](https://ziglang.org) |
| [raylib-Ada](https://github.com/mimo/raylib-Ada) | 3.0 | [Ada](https://www.adacore.com/about-ada) |
| [raykit](https://github.com/Gamerfiend/raykit) | **???** | [Kit](https://www.kitlang.org) |
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) |
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |
| [raylib-beef](https://github.com/M0n7y5/raylib-beef) | 3.0 | [Beef](https://www.beeflang.org) |
| [raylib-never](https://github.com/never-lang/raylib-never) | 3.0 | [Never](https://github.com/never-lang/never) |
| [raylib.cbl](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib) | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) |
| Name | raylib Version | Language |
| ---------------------------------------------------------------------------------- | :------------: | :---------------------------------------------------------------------: |
| [raylib-cppsharp](https://github.com/phxvyper/raylib-cppsharp) | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
| [RaylibFS](https://github.com/dallinbeutler/RaylibFS) | 2.5 | [F#](https://fsharp.org) |
| [raylib\*d](https://github.com/Sepheus/raylib_d) | 2.5 | [D](https://dlang.org) |
| [bindbc-raylib](https://github.com/o3o/bindbc-raylib) | 3.0 | [D](https://dlang.org) |
| [go-raylib](https://github.com/chunqian/go-raylib) | 3.5 | [Go](https://golang.org) |
| [raylib-goplus](https://github.com/Lachee/raylib-goplus) | 2.6-dev | [Go](https://golang.org) |
| [ray-go](https://github.com/hecate-tech/ray-go) | 2.6-dev | [Go](https://golang.org) |
| [raylib-luamore](https://github.com/HDPLocust/raylib-luamore) | 3.0 | [Lua](http://www.lua.org) |
| [LuaJIT-Raylib](https://github.com/Bambofy/LuaJIT-Raylib) | 2.6 | [Lua](http://www.lua.org) |
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 2.5 | [Lua](http://www.lua.org) |
| [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) | 2.0 | [Lua](http://www.lua.org) |
| [raylib-lua](https://github.com/raysan5/raylib-lua) | 1.7 | [Lua](http://www.lua.org) |
| [raylib-nelua](https://github.com/Andre-LA/raylib-nelua) | 3.0 | [Nelua](https://nelua.io) |
| [raylib-nim](https://github.com/Skrylar/raylib-nim) | 2.0 | [Nim](https://nim-lang.org) |
| [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) | 1.7 | [Nim](https://nim-lang.org) |
| [nim-raylib](https://github.com/tomc1998/nim-raylib) | 3.1-dev | [Nim](https://nim-lang.org) |
| [raylib-Forever](https://github.com/Guevara-chan/Raylib-Forever) | auto | [Nim](https://nim-lang.org) |
| [NimraylibNow!](https://github.com/greenfork/nimraylib_now) | 4.2 | [Nim](https://nim-lang.org) |
| [raylib-haskell](https://github.com/DevJac/raylib-haskell) | 2.0 | [Haskell](https://www.haskell.org) |
| [raylib-cr](https://github.com/AregevDev/raylib-cr) | 2.5-dev | [Crystal](https://crystal-lang.org) |
| [raylib.cr](https://github.com/sam0x17/raylib.cr) | 2.0 | [Crystal](https://crystal-lang.org) |
| [cray](https://gitlab.com/Zatherz/cray) | 1.8 | [Crystal](https://crystal-lang.org) |
| [raylib-pas](https://github.com/tazdij/raylib-pas) | 3.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [raylib-pascal](https://github.com/drezgames/raylib-pascal) | 2.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
| [Graphics-Raylib](https://github.com/athreef/Graphics-Raylib) | 1.4 | [Perl](https://www.perl.org) |
| [raylib-ruby](https://github.com/a0/raylib-ruby) | 2.6 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) | 2.0 | [Ruby](https://www.ruby-lang.org/en) |
| [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) | 2.5-dev | [mruby](https://github.com/mruby/mruby) |
| [raylib-java](https://github.com/XoanaIO/raylib-java) | 2.0 | [Java](https://en.wikipedia.org/wiki/Java*(programming_language)) |
| [clj-raylib](https://github.com/lsevero/clj-raylib) | 3.0 | [Clojure](https://clojure.org) |
| [QuickJS-raylib](https://github.com/sntg-p/QuickJS-raylib) | 3.0 | [QuickJS](https://bellard.org/quickjs) |
| [raylib-duktape](https://github.com/RobLoach/raylib-duktape) | 2.6 | [JavaScript (Duktape)](https://en.wikipedia.org/wiki/JavaScript) |
| [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) | 2.6 | [ChaiScript](http://chaiscript.com) |
| [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) | 2.5 | [Squirrel](http://www.squirrel-lang.org) |
| [racket-raylib-2d](https://github.com/arvyy/racket-raylib-2d) | 2.5 | [Racket](https://racket-lang.org) |
| [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) | 2.4-dev | [PHP](https://en.wikipedia.org/wiki/PHP) |
| [raylib-haxe](https://github.com/ibilon/raylib-haxe) | 2.4 | [Haxe](https://haxe.org) |
| [ringraylib](https://github.com/ringpackages/ringraylib) | 2.6 | [Ring](http://ring-lang.sourceforge.net) |
| [raylib-scm](https://github.com/yashrk/raylib-scm) | 2.5 | [Chicken Scheme](https://www.call-cc.org) |
| [raylib-chibi](https://github.com/VincentToups/raylib-chibi) | 2.5 | [Chibi-Scheme](https://github.com/ashinn/chibi-scheme) |
| [raylib-gambit-scheme](https://github.com/georgjz/raylib-gambit-scheme) | 3.1-dev | [Gambit Scheme](https://github.com/gambit/gambit) |
| [Euraylib](https://github.com/gAndy50/Euraylib) | 3.0 | [Euphoria](https://openeuphoria.org) |
| [raylib-odin](https://github.com/kevinw/raylib-odin) | 3.0 | [Odin](https://odin-lang.org) |
| [vraylib](https://github.com/waotzi/vraylib) | 3.5 | [V](https://vlang.io) |
| [raylib-vala](https://code.guddler.uk/mart/raylibVapi) | 3.0 | [Vala](https://wiki.gnome.org/Projects/Vala) |
| [raylib-jai](https://github.com/kujukuju/raylib-jai) | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) |
| [ray.zig](https://github.com/BitPuffin/zig-raylib-experiments) | 2.5 | [Zig](https://ziglang.org) |
| [raylib-Ada](https://github.com/mimo/raylib-Ada) | 3.0 | [Ada](https://www.adacore.com/about-ada) |
| [raykit](https://github.com/Gamerfiend/raykit) | **???** | [Kit](https://www.kitlang.org) |
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |
| [raylib-beef](https://github.com/M0n7y5/raylib-beef) | 3.0 | [Beef](https://www.beeflang.org) |
| [raylib-never](https://github.com/never-lang/raylib-never) | 3.0 | [Never](https://github.com/never-lang/never) |
| [raylib.cbl](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib) | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) |
Missing some language or wrapper? Feel free to create a new one! :)

302
CHANGELOG
View File

@ -3,308 +3,6 @@ changelog
Current Release: raylib 6.0 (23 April 2026)
-------------------------------------------------------------------------
Release: raylib 6.2 (xx Oct 2026)
-------------------------------------------------------------------------
KEY CHANGES:
- REDESIGNED: Image API for more alignment with Texture API
- REDESIGNED: File API for more standard return result values
- REVIEWED: Shapes lines drawing functions, added new ones and unify behaviour
Detailed changes (until 08-Oct-2026):
[rcore] ADDED: `IsPathDirectory()`, for convenience and more readability at user code by @raysan5
[rcore] ADDED: `IsPathAbsolute()`, check absolute paths by @raysan5
[rcore] ADDED: `IsFileHidden()`, check file hidden (OS-dependant) by @raysan5
[rcore] REVIEWED: `File*()` functions for consistent return result value by @raysan5 -WARNING-
[rcore] REVIEWED: Not updating mouse.previousPosition when `SetMousePosition()` #5962 by @raysan5 -WARNING-
[rcore] REVIEWED: Use `rlgl` provided interface instead of `rlsw` direct access by @raysan5
[rcore] REVIEWED: Set mouse position to (0,0) when mouse leaves window area #5945 by @raysan5
[rcore] REVIEWED: Multiple string boundary handling (#5812) by @zhaob1n
[rcore] REVIEWED: Gamepad lower-bound guard to six sibling functions (#5938) by @mahirhir
[rcore] REVIEWED: Fix logging format for automation event capacity warning (#5986) by @GideonSerf
[rcore] REVIEWED: Fix initial macOS window size (#5967) by @loukamb
[rcore] REVIEWED: Fix clipboard image memory leak (#5968) by @LuisR385
[rcore] REVIEWED: `TakeScreenshot()`, support absolute paths by @raysan5
[rcore] REVIEWED: `OpenURL()`, added some safety checks to mitigate malicious url inputs - ROS: `CLN-002` by @raysan5 -WARNING-
[rcore] REVIEWED: `LoadAutomationEventList()` - ROS: `CLN-005`, `CLN-006` by @raysan5
[rcore] REVIEWED: `GetWindowHandle()`, to be consistent between backends, fix #5885 by @raysan5
[rcore] REVIEWED: `GetWindowPosition()` #5932 by @raysan5
[rcore] REVIEWED: `GetTime()`, small addition for RPI Pico 2 by @raysan5
[rcore] REVIEWED: `GetCurrentMonitor()`, fix for integer overflow in distance calculation (#5842) by @Vasilis-Narain
[rcore] REVIEWED: `FileMove()`, additional security checks by @raysan5
[rcore] REVIEWED: `FileCopy()`, create directory to copy if it does not exist (#5920) by @InviseDivine
[rcore] REVIEWED: `FileMove()`, fix deleting files if `FileCopy()` fails (#5806) by @Lucrecious -WARNING-
[rcore] REVIEWED: `IsPathAbsolute()`, remove `isalpha()` dependency by @raysan5
[rcore] REVIEWED: `ComputeSHA1()`, fix undefined behaviour (#5957) by @TheFissk
[rcore] REVIEWED: `ComputeSHA256()`, wrong hash when message length mod 64 is 56..59 (#6144) by @killerdevildog -WARNING-
[rcore] REVIEWED: `GetPrevDirectoryPath()` behavior to better support side cases (#6073) by @luphi
[rcore] REVIEWED: `GetGamepadAxisCount()`, `GetGamepadName()`, bounds-check gamepad index (#5937) by @szarta
[rcore] REVIEWED: `FileText*()`, make error handling consistent with `Text*()` helpers (#6210) by @Ne0nWinds
[rcore] REVIEWED: `MAX_FILEPATH_LENGTH` to match `MAX_PATH` (#6164) by @randomnumbersandletters
[rcore][GLFW] REVIEWED: `GetClipboardImage()`, fix creating new connection under X11 (#5871) by @steampuker
[rcore][GLFW] REVIEWED: Borderless-windowed mode being always on top (#5868) by @auwsmit
[rcore][GLFW] REVIEWED: Clipboard image memory leak (GLFW, RGFW) (#6103) by @omaribrahimsaad
[rcore][GLFW] REVIEWED: Do not reset mouse position user when user is off window (#6134) by @jestarray
[rcore][GLFW] REVIEWED: `Font` symbol conflict (#6094) by @M374LX
[rcore][RGFW] REVIEWED: Add fullscreen behaviour on size 0 window creation (#5859) by @keks137
[rcore][RGFW] REVIEWED: Fix window Y position reading X in RGFW move callback (#6044) by @latent-9
[rcore][GLFW] REVIEWED: Window centering overflow with unsigned screen size (#6119) by @nfvelten
[rcore][GLFW] REVIEWED: Allow non-fullscreen window being able to be larger than a workable area (#6137) by @JamesMillsDev
[rcore][SDL] REVIEWED: Use precise mouse wheel values (#5830) by @Menduist
[rcore][SDL] REVIEWED: Fix SDL3 wrong joystick functions usage (#5948) by @0xFishbyte
[rcore][SDL] REVIEWED: Accumulate relative mouse motion per frame (#6215) by @snowyukitty
[rcore][SDL] REVIEWED: Fix only the first dropped file being registered (#6190) by @SulimanAbdulrazzaq
[rcore][SDL] REVIEWED: `DROP_EVENT_DATA` definition (#6185) by @Yonokid
[rcore][SDL] REVIEWED: Grow dropFilePaths dynamically when file is dragged ontop of window (#6178) by @jestarray
[rcore][SDL] REVIEWED: Refactor dragdrop file onto window handling and grow dropFilepaths dynamically like glfw (#6178) by @jestarray
[rcore][DRM] REVIEWED: Silence warnings when using GRAPHICS_API_OPENGL_SOFTWARE (#5839) by @NighthowlerStudios
[rcore][DRM] REVIEWED: Segfault on some NVIDIA proprietary drivers (#5960) by @girvel
[rcore][DRM] REVIEWED: Raise MAX_DRM_CACHED_BUFFERS to 4 and warn when the cache fills (#6107) by @jtakakura
[rcore][Web] REVIEWED: Fix for stale mouse position (#5981) by @largenumberhere
[rcore][Web] REVIEWED: Avoid `glfwGetProcAddress()` to reduce code size (#6220) by @vdemcak -WARNING-
[rcore][Win32] ADDED: Support MSAA (#6227) by @Ne0nWinds
[rcore][Win32] ADDED: `IsKeyPressedRepeat()` implementation (#6218) by @Ne0nWinds
[rcore][Win32] ADDED: `GetClipboardImage()` (#6091) by @omaribrahimsaad
[rcore][Win32] REVIEWED: Use `CORE.Input.Keyboard.exitKey` when handling window closing (#5911) by @aceinetx
[rcore][Win32] REVIEWED: Security fixes (#5899) by @M374LX
[rcore][Win32] REVIEWED: Handle conflict with `PlaySoundW()` for wide string builds (#6140) by @JeffM2501
[rcore][Win32] REVIEWED: `SetWindowState()`, prevent infinite loop (#6194) by @Ne0nWinds
[rcore][Win32] REVIEWED: Missing break in WndProc switch statement (#6209) by @Ne0nWinds
[rcore][Win32] REVIEWED: `SetWindowSize()`, allow to change only the width or height (#6232) by @Ne0nWinds
[rcore][Win32] REVIEWED: `CloseWindow()`, clean up window state (#6233) by @Ne0nWinds
[rcore][Win32] REVIEWED: `IsWindowResized()`, return true only when needed (#6186) by @Ne0nWinds
[rcore][Win32] REVIEWED: WGL pixel format not being applied (#6219) by @Ne0nWinds
[rcore][Android] REVIEWED: Restore face-button input on Android gamepads (#5824) by @Tubbles
[rcore][Android] REVIEWED: Relaunch hang after destroy while paused (#6040) by @get-charlie
[rcore][Emscripten] REVIEWED: `GetTime()`, fix time calculation (#6061) by @andzdroid
[rcore][Emscripten] REVIEWED: Handle emscripten keyboard events (#6067) by @andzdroid
[rcore][Emscripten] REVIEWED: Invert emscripten scroll wheel direction (#6104) by @andzdroid
[rcore][Emscripten] REVIEWED: Update emscripten mouse handling (#6070) by @andzdroid
[rlsw] ADDED: Double buffering support and compiler requirements Pico 2 (#5994) by @NighthowlerStudios
[rlsw] ADDED: `GL_SHADING_LANGUAGE_VERSION` for `swGetString()` by @raysan5
[rlsw] REVIEWED: Variant dispatch refactor and render optimizations (#5996) by @Bigfoot71
[rlgl] REVIEWED: `rlGetPixelDataSize()`, fix pixel data size regressions (#5984) by @GideonSerf
[rlgl] REVIEWED: `rlPushMatrix()`, fix matrix stack overflow (#5935) by @szarta
[rlgl] REVIEWED: `rlLoadTexture()`, add power-of-two check for GL_REPEAT wrap mode (#5820) by @noinodev
[rlgl] REVIEWED: Shader attribute/uniform default names can not be overriden #5925 by @raysan5
[rlgl] REVIEWED: Fix DRM/EGL segfault on some NVIDIA proprietary drivers (#5960) by @girvel
[rlgl] REVIEWED: Use `rlGetPixelDataSize()` instead of `GetPixelDataSize()` (#6024) by @leoagomes
[rlgl] REVIEWED: `rlGetActiveFramebuffer()` supported on OpenGL ES 2.0 (#6115) by @JoeStrout
[rlsw] REVIEWED: Replace `SW_TEXTURE_REPEAT_POT_FAST` with `SW_SUPPORT_NPOT_TEXTURE` (#5901) by @Bigfoot71
[rlsw] REVIEWED: Fix triangle and quad spans applying pixels out of bounds (#5849) by @NighthowlerStudios
[rlsw] REVIEWED: Fix swScissor() Y-axis clipping inversion in software renderer (#5976) by @thiagomucci
[rlsw] REVIEWED: Fix persistent alpha blending state (#5964) by @iztanos
[rlsw] REVIEWED: ESP32 optimizations (#5827) by @jensroth-git
[rlsw] REVIEWED: Internal functions declarations (#6028) by @Bigfoot71
[rlsw] REVIEWED: Optimizations for embedded and compiler requirements Pico 2 (#5994) by @NighthowlerStudios
[rlsw] REVIEWED: Rename public compile-time option prefix to `RLSW_` (#6029) by @Bigfoot71
[rlsw] REVIEWED: Variant dispatch refactor and other improvements (#5996) by @Bigfoot71
[rshapes] ADDED: `Draw*LinesEx()` functions (#6072) by @MatthewRoush
[rshapes] RENAMED: `GetSplinePointBezierQuad()` to `GetSplinePointBezierQuadratic()` by @raysan5 -WARNING-
[rshapes] REVIEWED: Reorder drawing functions by number of vertices by @raysan5
[rshapes] REVIEWED: Comments to be more descriptive by @raysan5
[rshapes] REVIEWED: `DrawRectangleRoundedLinesEx()`, not scaling with transform when thick=1 (#5980) by @SamaelHeaven
[rshapes] REVIEWED: `DrawRectangleRoundedLines()` (#5992) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleRounded()`, automatic segments count (#5875) by @anstropleuton
[rshapes] REVIEWED: `DrawRectangleRounded()`, `DrawRectangleRoundedLinesEx()`, fix auto segment rounded-corner math (#5883) by @ghera
[rshapes] REVIEWED: `CheckCollisionLines()`, add NULL check (#5802) by @bielern
[rshapes] REVIEWED: `Draw*LinesEx()`, inconsistencies handling of `thick` parameter (#6035) by @MatthewRoush
[rshapes] REVIEWED: `DrawCircleSector()` (#6045) by @MatthewRoush
[rshapes] REVIEWED: `DrawPolyLinesEx()` (#6004) by @MatthewRoush
[rshapes] REVIEWED: `DrawPolyLinesEx()` line thickness (#6014) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleLinesEx()` (#6027) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleRoundedLines()` (#5992) by @MatthewRoush
[rshapes] REVIEWED: `DrawRectangleRounded*()`, segment auto-calculation threshold (#6159) by @MatthewRoush
[rtextures] ADDED: Support for .pep image fileformat, useful for pixel-art by @raysan5
[rtextures] ADDED: `LoadRenderTextureEx()` with user defined pixel format (#6114) by @JeffM2501
[rtextures] ADDED: `ImageDrawLineStrip()` by @raysan5
[rtextures] ADDED: `DrawTriangleGradient()` by @raysan5
[rtextures] ADDED: `DrawCircleLinesEx()`, simpler naming than `DrawRing()` by @raysan5
[rtextures] ADDED: `ImageDrawCircleGradient()` by @raysan5
[rtextures] ADDED: `ImageDrawImageEx()` by @raysan5
[rtextures] ADDED: `ImageDrawRectanglePro()` by @raysan5
[rtextures] ADDED: `ImageDrawRectangleGradientEx()` by @raysan5
[rtextures] RENAMED: `ImageDrawTriangleEx()` to `ImageDrawTriangleGradient()` by @raysan5 -WARNING-
[rtextures] REDESIGNED: `ImageDraw()`, align with `DrawTexture()` by @raysan5 -WARNING-
[rtextures] REDESIGNED: `ImageDrawRectangleLines()`, consistency with `DrawRectangleLines()` by @raysan5 -WARNING-
[rtextures] REVIEWED: `DrawRectangleLinesEx()`, avoid early-return by @raysan5
[rtextures] REVIEWED: `GetPixelColor()` reading the wrong bits for R5G5B5A1 blue (#6113) by @dylanpulver
[rtextures] REVIEWED: `ImageDrawCircle()`, asymmetry compared with `DrawCircle()` (#6118) by @Risu-swift
[rtextures] REVIEWED: `LoadImageFromTexture()` for wasm by @raysan5
[rtextures] REVIEWED: `ImageFromImage()` - ROS: `CLN-007` by @raysan5
[rtextures] REVIEWED: `ImageFromImage()`, rectangle validation using strict comparisons (#5979) by @CommandPrompt-Wang
[rtextures] REVIEWED: `ImageFromImage()` heap-buffer-overflow on compressed formats (#5991) by @gummyniki
[rtextures] REVIEWED: `ImageToImage()`, reorganize conditionals checks optimization by @raysan5
[rtextures] REVIEWED: `ImageDrawLine()`, rounding and length fix (#5896) by @Kaggen67
[rtextures] REVIEWED: `ImageColorContrast()` parameter type, consistent with other `Image*()` functions by @raysan5 -WARNING-
[rtextures] REVIEWED: `GetPixelDataSize()`, avoid allocations >2GB - ROS: `CLN-013` by @raysan5
[rtextures] REVIEWED: `GetPixelColor()` const by @raysan5
[rtextures] REVIEWED: `ImageDrawImageEx()`, blending on transparent destinations (#6224) by @Kartikey-cs
[rtextures] REVIEWED: `ImageKernelConvolution()`, sampling across rows at image edges and unclamped alpha (#6192) by @4RH1T3CT0R7
[rtext] REVIEWED: BDF loading writing glyphs through a NULL-based pointer (#6198) by @antonsoo
[rtext] REVIEWED: `LoadFontEx()`, `LoadFontFromMemory()`, additional warnings (#5864) by @CrackedPixel
[rtext] REVIEWED: `TextToSnake()`, not considering spaces properly by @raysan5
[rtext] REVIEWED: `TextSubtext()`, fix returning empty string when position is 0 (#5975) by @thiagomucci
[rtext] REVIEWED: `TextReplaceBetween()`, fix buffer overflow (#5936) by @szarta
[rtext] REVIEWED: `TextInsertAlloc()`, overflow by correcting loop bounds (#5982) by @GideonSerf
[rtext] REVIEWED: `TextJoin()`, `TextSubtext()`, `TextInsert*()` - ROS: `CLN-018` by @raysan5
[rtext] REVIEWED: `LoadFontFromImage()`, memory leak (#6100) by @ApexNadir
[rtext] REVIEWED: `TextInsert()`/`TextInsertAlloc()` (#6021) by @SewerynKaminski
[rtext] REVIEWED: `TextSplit()` reading past its buffer on text of 1024 bytes (#6136) by @MaxFreedomPollard
[rtext] REVIEWED: `TextToPascal()`/`TextToCamel()`, truncating text after a separator (#6132) by @MaxFreedomPollard
[rtext] REVIEWED: `TextToPascal()`/`TextToCamel()`, empty strings checks (#6213) by @Ne0nWinds
[rmodels] REDESIGNED: `DrawCapsule()`, `DrawCapsuleWires()`, parameter order by @raysan5 -WARNING-
[rmodels] REVIEWED: Fix glTF skinning when joints have non-joint parent nodes (#5876) by @cseelhoff
[rmodels] REVIEWED: Change `boneCount` field type to `unsigned int` (#5955) by @lauchimoon
[rmodels] REVIEWED: GLTF animation interpolation (#6007) by @lassade
[rmodels] REVIEWED: glTF pose sampled at the end of an animation returning a pose from the start (#6048) by @LeFede
[rmodels] REVIEWED: `LoadOBJ()`, avoid reading past vertex data on out-of-range face indices (#6199) by @antonsoo
[rmodels] REVIEWED: `LoadGLTF()`, use inverse bind matrices for bind pose (#5832) by @fyl2xp1
[rmodels] REVIEWED: `IsModelValid()` #5780 by @raysan5
[rmodels] REVIEWED: `GenMeshTorus()`, improved comments (#5934) by @EugenioBarbieriViale
[rmodels] REVIEWED: `DrawSphereWires()`, code optimization (#6000) by @oscujic
[rmodels] REVIEWED: `DrawSphereWires()`, code optimization (#6000) by @oscujic
[rmodels] REVIEWED: `DrawCapsule()`, `DrawCapsuleWires()`, validate minimum rings (#5909) by @LuisR385
[rmodels] REVIEWED: `UnloadModel()`, fix memory leak (#5907) by @LuisR385
[rmodels] REVIEWED: `UpdateModelAnimation()`, compute bone normal matrices once per bone instead of per vertex (#6191) by @4RH1T3CT0R7 -WARNING-
[raudio] REVIEWED: `UpdateSound()`, missleading parameter name by @raysan5
[raudio] REVIEWED: `UnloadSoundAlias()`, prevent leak (#5857) by @Peter0x44
[raudio] REVIEWED: Remove extra `drflac_free()` call (#5916) by @CrackedPixel
[raudio] REVIEWED: Fix memory leak when loading .wav files (#5963) by @LuisR385
[raudio] REVIEWED: Define missing `UnloadFileData()` on standalone mode (#5787) by @rigidatoms
[raudio] REVIEWED: Update to latest DR libs to fix some warnings in MSVC (#5808) by @JeffM2501
[raudio] REVIEWED: `CloseAudioDevice()`, crash when uninit device before mutex (#6039) by @get-charlie
[raymath] ADDED: Operator overload for (float * Vector) (#5815) by @alphahex99
[raymath] REVIEWED: `MatrixCompose()` to follow raymath conventions (#6133) by @carlost0
[raymath] REVIEWED: `MatrixCompose()`, rotating vectors with already overwritten components (#6187) by @ethanstoner
[raymath] REVIEWED: `MatrixDecompose()`, reading rows instead of columns (#6225) by @ewraj
[raymath] REVIEWED: `QuaternionFromVector3ToVector3()`, returning a zero quaternion for opposite vectors (#6230) by @ewraj
[build] REMOVED: Unmaintained project: 4coder by @raysan5
[build] REMOVED: Unmaintained project: VS2019-Android by @raysan5
[build][Make] REVIEWED: Add `ANDROID_ARCH` check (#5888) by @Fipaan
[build][Make] REVIEWED: Re-enable `GLFW_LINUX_ENABLE_WAYLAND` flag by default #5816 by @raysan5
[build][Make] REVIEWED: examples/Makefile after testing on OSX (#6077) by @WilliamIsMe1
[build][Make] REVIEWED: Detect the recipe shell for proper clean (#6146) by @Peter0x44
[build][Make] REVIEWED: Avoid _GNU_SOURCE on Linux to keep the library linkable with older glibc (#6214) by @Peter0x44 -WARNING-
[build][VS2022] REVIEWED: x64 build compatibility support (#6052) (#6053) by @yoobezxc
[build][CMake] ADDED: Support for Win32 platform + examples (#5855) by @CrackedPixel
[build][CMake] REVIEWED: Fix config.h parsing into cmake options (#5844) by @Peter0x44
[build][CMake] REVIEWED: Add configure-time test for libatomic requirement (#5847) by @Peter0x44
[build][CMake] REVIEWED: Remove `raudio` and `rmodels` modules if disabled (#5878) by @NighthowlerStudios
[build][CMake] REVIEWED: Remove GLFW_BUILD warnings for platform SDL (#5865) by @jestarray
[build][CMake] REVIEWED: Reduce minimum CMake version from 3.25 to 3.22 (#5890) by @RobLoach
[build][CMake] REVIEWED: Fix static link dependencies (#5990) by @meta-legend
[build][CMake] REVIEWED: Fix standalone configuration of examples project (#6079) by @zaveshaa
[build][CMake] REVIEWED: Propagate Cocoa backend frameworks to consumers of static raylib on macOS (#6086) by @zaveshaa
[build][CMake] REVIEWED: Fix install export with vendored SDL (#6173) by @RobLoach
[build][Zig] REVIEWED: Support wasm examples building (#5811) by @shadeops
[build][Zig] REVIEWED: Avoid building examples all the time (#5869) by @jn-jairo
[build][Zig] REVIEWED: Avoid building web examples all the time (#6006) by @jn-jairo
[build][Zig] REVIEWED: Update to raygui 5.0 (#6005) by @jn-jairo
[build][Zig] REVIEWED: Migration to latest 0.17 release (#5951) by @miker2049 -WARNING-
[build][CI] ADDED: Clang tidy linting (disabled by default) (#6163) by @jestarray -WARNING-
[build][CI] REVIEWED: GitHub Actions update to latest actions versions by @raysan5
[build][CI] REVIEWED: `build_examples_windows.yml`, use latest actions versions by @raysan5
[build][CI] REVIEWED: `analyze_codeql.yml`, use latest actions versions by @raysan5
[build][CI] REVIEWED: `setup-emsdk`, use latest actions version by @raysan5
[bindings] ADDED: Recomendations for binding authors (#6141) by @JeffM2501
[bindings] ADDED: gcl native raylib module (#6152) by @gnuchanos
[bindings] ADDED: sola-raylib (6.0) (#5790, #5795) by @brettchalupa
[bindings] ADDED: gclang-raylib (6.0) (#5850) by @gnuchanos
[bindings] ADDED: mach-raylib (#6059) by @Angluca
[bindings] ADDED: solod (#6102) by @nalgeon
[bindings] ADDED: raymojo (#6076) by @RobertFlexx
[bindings] ADDED: raylib_mojo, for Mojo language (#6093) by @willGuimont
[bindings] ADDED: rayscal, for Scala Native (#6019) by @RobertFlexx
[bindings] ADDED: raylib-elfscript, for ElfScript (#6036) by @ohmtal
[bindings] ADDED: raylib component pascal/oberon2 bindings (#6055) by @RobertFlexx
[bindings] ADDED: raylib binding for modula 2 and 3 (#6068) by @RobertFlexx
[bindings] ADDED: raystar (#6075) by @RobertFlexx
[bindings] UPDATED: vala-vapi to raylib 6.0 (#5789) by @edwood-grant
[bindings] UPDATED: raylib_dart to raylib 6.0 (#5917) by @dzylikecode
[bindings] UPDATED: raylib4fb to raylib 6.0 (#5813) by @mudhairless
[bindings] UPDATED: raylib-d to raylib 6.0 (#5799) by @schveiguy
[bindings] UPDATED: raylib-cpp to raylib 6.0 (#5785) by @RobLoach
[bindings] UPDATED: raylib-go to raylib 6.0 (#5866) by @JupiterRider
[bindings] UPDATED: raylib-cpp to raylib 6.0 (#5785) by @RobLoach
[bindings] UPDATED: raylib-zig to raylib 6.0 (#5886) by @coal-rock
[bindings] UPDATED: Deno-Raylib to raylib 6.0 (#5821) by @JJLDonley
[bindings] UPDATED: raylib-cs to raylib 6.0 (#5887) by @rgebee
[bindings] UPDATED: ReiLua to raylib 6.0 (#5959) by @nullstare
[bindings] UPDATED: Raylib-lua to raylib 5.5 (#5884) by @keyle
[bindings] UPDATED: Ray4Laz to raylib 6.0 (#5784) by @GuvaCode
[bindings] UPDATED: EuRaylib to raylib 6.0 (#6034) by @gAndy50
[bindings] UPDATED: raylib-ocaml to raylib 6.0 (#5912) by @tjammer
[bindings] UPDATED: raylib-jai to raylib 6.0 (#5928) by @ahmedqarmout2
[bindings] UPDATED: raylib-c3 to raylib 6.0 (#5819) by @surrealism21
[bindings] UPDATED: raylib-asm to raylib 6.0 (#6033) by @gAndy50
[bindings] UPDATED: fortran-raylib to raylib 6.0 (#6060) by @interkosmos
[bindings] UPDATED: raylib-py to raylib 6.0 (#6095) by @overdev
[bindings] UPDATED: h-raylib to raylib 6.0 (#6142) by @Anut-py
[bindings] UPDATED: Raylib.nelua (#6183) by @AuzFox
[bindings] UPDATED: mach-raylib to raylib 6.x-dev (#6153) by @Angluca
[examples] ADDED: `core_scissor_shape` (#6032) by @davidbuzatto
[examples] ADDED: `shapes_outlines_testbed` (#6072) by @MatthewRoush
[examples] ADDED: `shapes_outlines_thickness` (#6037) by @MatthewRoush
[examples] ADDED: `shapes_polygon_lines` (#6023) by @MatthewRoush
[examples] ADDED: `shapes_drag_puzzle` (#6165) by @gabriel-piangers
[examples] ADDED: `textures_portal_window` (#6082) by @PanicTitan
[examples] ADDED: `models_mesh_uv_painting` (#6084) by @PanicTitan
[examples] ADDED: `models_procedural_decals` (#6083) by @PanicTitan
[examples] ADDED: `shaders_lights_bloom` (#6081) by @PanicTitan
[examples] REVIEWED: Clarify Camera2d.offset and how it works with High DPI scale mode (#6203) by @JeffM2501
[examples] REVIEWED: Inconsistent version metadata (#6171) by @Ne0nWinds
[examples] REVIEWED: Multiple examples, adding missing `Unload*()` (#6151) by @emecdelam
[examples] REVIEWED: `core_smooth_pixelperfect` (#5803) by @rose-mtz
[examples] REVIEWED: `core_directory_files` (#5823) by @MAXDVVV
[examples] REVIEWED: `core_delta_time`, convert frametime to milliseconds before printing (#6201) by @Ne0nWinds
[examples] REVIEWED: `shapes_ball_physics`, move window for ball shake (#5791) by @Sebbl0508
[examples] REVIEWED: `textures_image_drawing` by @raysan5
[examples] REVIEWED: `textures_portal_window` by @raysan5
[examples] REVIEWED: `textures_image_rotate`, unload source image (#6145) by @Hugohong258
[examples] REVIEWED: `textures_image_processing`, fix up arrow wraparound logic (#6217) by @Ne0nWinds
[examples] REVIEWED: `text_codepoints_loading`, out of bounds error in `CodepointRemoveDuplicates()` (#6206) by @Ne0nWinds
[examples] REVIEWED: `models_basic_voxel` by @raysan5
[examples] REVIEWED: `models_animation_blending` by @raysan5
[examples] REVIEWED: `models_mesh_uv_painting` by @raysan5
[examples] REVIEWED: `models_animation_blending`, avoid crash when animations fail to load (#6234) by @akashdeshmukh-git
[examples] REVIEWED: `shaders_*`, `pbr.fs`, using wrong uniform value (#5965) by @raysan5
[examples] REVIEWED: `shaders_lights_bloom` by @raysan5
[examples] REVIEWED: `shaders_shadowmap_rendering` by @raysan5
[examples] REVIEWED: `shaders_mesh_instancing`, release mesh instancing resources on exit (#6207) by @Hugohong258
[examples] REVIEWED: `shaders_lightmap_rendering`, unload lightmap render texture (#6188) by @Hugohong258
[rlparser] ADDED: S-Expression output type (#5943) by @VisenDev
[rlparser] REVIEWED: Path fixes (#5794) by @gigamonster256
[rlparser] REVIEWED: Fix formatting to follow raylib conventions (#6127) by @Nomobyte
[rlparser] REVIEWED: Fix type aliases, added support to type pointers (#6126) by @Nomobyte
[rexm] ADDED: New command: clean (#6124) by @MatthewRoush
[rexm] REVIEWED: Crash when adding a new textures or audio examples (#6089) by @PanicTitan
[rexm] REVIEWED: Leave environment setup up to the user (#6101) by @MatthewRoush
[rexm] REVIEWED: Makefile and change web local testing port number (#6123) by @MatthewRoush
[rexm] REVIEWED: Simplify code, latest w64devkit supports `make` directly, no need for `mingw32-make` by @raysan5
[misc] ADDED: SECURITY.md document by @raysan5
[misc] REVIEWED: Several functions `const` correctness by @raysan5
[misc] REVIEWED: `strncpy()` replaced by `snprintf()` for safety by @raysan5
[misc] REVIEWED: Minimize `long long` usage in all raylib by @raysan5
[misc] REVIEWED: Comments for consistency and spelling by @raysan5
[misc] REVIEWED: Some Rectangle parameters with more descriptive names by @raysan5
[misc] REVIEWED: Shift `__cplusplus` check to a higher level for `bool` type define (#5804) by @lamweilun
[external] ADDED: `rprand_get_value_raw()` to `rprand` library by @raysan5
[external] UPDATED: GLFW to 3.5.1 (#6051) by @M374LX
[external] UPDATED: miniaudio to 0.11.25 (#6050) by @M374LX
[external] UPDATED: `raygui` to latest master (raygui 5.0) by @raysan5
[external] UPDATED: `qoa` with upstream out-of-bounds fixes (#6162) by @thaidn
[external] REVIEWED: `jar_mod_load_file()`, check fread return value (#5840) by @fffaraz
[external] REVIEWED: `tiny_obj_loader` Replace `assert()` by runtime checks - ROS: `CLN-012` by @raysan5
[external] REVIEWED: `fix_win32_compatibility.h`, fix for newer windows SDK versions (#6088) by @JeffM2501
[external] REVIEWED: `vox_loader`, added bounds checks to `Vox_SetVoxel()` and chunk parsing (#6175) by @AvAl4nch
[external] REVIEWED: `vox_loader`, Prevent memory leak when loading voxel models (#6208) by @Ne0nWinds
-------------------------------------------------------------------------
Release: raylib 6.0 (23 April 2026)
-------------------------------------------------------------------------

View File

@ -25,7 +25,7 @@ Functions params | lowerCase | `width`, `height`
Ternary Operator | (condition)? result1 : result2 | `printf("Value is 0: %s", (value == 0)? "yes" : "no");`
Some other conventions to follow:
- **ALWAYS** initialize all defined variables, avoid defining variables in same code line, use multiple lines.
- **ALWAYS** initialize all defined variables.
- **Do not use TABS**, use 4 spaces instead.
- Avoid trailing spaces, please, avoid them
- Comments always start with space + capital letter and never end with a '.', place them **before** the line(s) they refer to
@ -68,14 +68,6 @@ void SomeFunction()
{
// TODO: Do something here!
}
```
- When checking pointers, use full verbose check against `NULL`
```c
if (dataPtr != NULL)
{
RL_FREE(dataPtr);
dataPtr = NULL;
}
```
**If proposing new functions, please try to use a clear naming for function-name and functions-parameters, in case of doubt, open an issue for discussion.**

View File

@ -16,11 +16,12 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
[![GitHub Stars](https://img.shields.io/github/stars/raysan5/raylib?style=flat&label=stars)](https://github.com/raysan5/raylib/stargazers)
[![GitHub commits since tagged version](https://img.shields.io/github/commits-since/raysan5/raylib/6.0)](https://github.com/raysan5/raylib/commits/master)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/raysan5?label=sponsors)](https://github.com/sponsors/raysan5)
[![Packaging Status](https://repology.org/badge/tiny-repos/raylib.svg)](https://repology.org/project/raylib/versions)
[![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE)
[![Discord Members](https://img.shields.io/discord/426912293134270465.svg?label=Discord&logo=discord)](https://discord.gg/raylib)
[![Reddit Static Badge](https://img.shields.io/badge/-r%2Fraylib-red?style=flat&logo=reddit&label=reddit)](https://www.reddit.com/r/raylib/)
[![Youtube Static Badge](https://img.shields.io/badge/YouTube-raylib-red?style=flat&logo=youtube&logoColor=red)](https://www.youtube.com/c/raylib)
[![Youtube Subscribers](https://img.shields.io/youtube/channel/subscribers/UC8WIBkhYb5sBNqXO1mZ7WSQ?style=flat&label=Youtube&logo=youtube)](https://www.youtube.com/c/raylib)
[![Twitch Status](https://img.shields.io/twitch/status/raysan5?style=flat&label=Twitch&logo=twitch)](https://www.twitch.tv/raysan5)
[![Build Windows](https://github.com/raysan5/raylib/actions/workflows/build_windows.yml/badge.svg)](https://github.com/raysan5/raylib/actions/workflows/build_windows.yml)
@ -34,7 +35,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
features
--------
- **NO external dependencies**, all required libraries are [included in raylib](https://github.com/raysan5/raylib/tree/master/src/external)
- **NO external dependencies**, all required libraries are [included into raylib](https://github.com/raysan5/raylib/tree/master/src/external)
- Multiple platforms supported: **Windows, Linux, MacOS, RPI, Android, HTML5... and more!**
- Written in plain C code (C99) using PascalCase/camelCase notation
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
@ -49,21 +50,10 @@ features
- **Powerful math module** for Vector, Matrix and Quaternion operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h)
- Audio loading and playing with streaming support (WAV, QOA, OGG, MP3, FLAC, XM, MOD)
- **VR stereo rendering** support with configurable HMD device parameters
- Huge examples collection with [+200 code examples](https://github.com/raysan5/raylib/tree/master/examples)!
- Huge examples collection with [+140 code examples](https://github.com/raysan5/raylib/tree/master/examples)!
- Bindings to [+70 programming languages](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)!
- **Free and open source**
limitations
-----------
raylib presents some limitations by design for code simplicity. Some forks, alternatives, and samples are available to overcome most of them but it's up to the users to modify the library for their specific needs.
- Single window with single OpenGL context by default, no multi-window support
- Window resize and move stops the rendering loop on platforms supporting a window
- `RenderTextures` are flipped vertically, as provided by OpenGL, it's up to the user to draw them flipped to the screen
- Font rasterization has lower quality than alternatives using `Freetype2`, `HarfBuzz` or `Slug`
- Text drawing does not support RTL, ligatures or emojis
basic example
--------------
This is a basic raylib example, it creates a window and draws the text `"Congrats! You created your first window!"` in the middle of the screen. Check this example [running live on web here](https://www.raylib.com/examples/core/loader.html?name=core_basic_window).
@ -109,7 +99,7 @@ raylib is also available via multiple package managers on multiple OS distributi
- [Working for Web (HTML5)](https://github.com/raysan5/raylib/wiki/Working-for-Web-(HTML5))
- [Working anywhere with CMake](https://github.com/raysan5/raylib/wiki/Working-with-CMake)
*Note that the Wiki is open to edits, if you find some issues while building raylib for your target platform, feel free to edit the Wiki or open an issue related to it.*
*Note that the Wiki is open for edit, if you find some issues while building raylib for your target platform, feel free to edit the Wiki or open an issue related to it.*
#### Setup raylib with multiple IDEs
@ -122,7 +112,7 @@ raylib has been developed on Windows platform using [Notepad++](https://notepad-
learning and docs
------------------
raylib is designed to be learned using [the examples](https://github.com/raysan5/raylib/tree/master/examples) as the main reference. There is no standard API documentation but there is a [**cheatsheet**](https://www.raylib.com/cheatsheet/cheatsheet.html) containing all the functions available in the library with a short description of each one; input parameters and result value names should be intuitive enough to understand how each function works.
raylib is designed to be learned using [the examples](https://github.com/raysan5/raylib/tree/master/examples) as the main reference. There is no standard API documentation but there is a [**cheatsheet**](https://www.raylib.com/cheatsheet/cheatsheet.html) containing all the functions available on the library a short description of each one of them, input parameters and result value names should be intuitive enough to understand how each function works.
Some additional documentation about raylib design can be found in [raylib GitHub Wiki](https://github.com/raysan5/raylib/wiki). Here are the relevant links:

398
build.zig
View File

@ -2,257 +2,85 @@ const std = @import("std");
const builtin = @import("builtin");
pub const emsdk = struct {
const emsdk_version = "4.0.19"; // inline constant used only in activate
var emsdk_dep: ?*std.Build.Dependency = null;
const zemscripten = @import("zemscripten");
// ---------- core types ----------
pub const EmccFlags = std.StringHashMap(void);
pub const EmccSettings = std.StringHashMap([]const u8);
const EmsdkAllocator = enum {
none,
dlmalloc,
emmalloc,
@"emmalloc-debug",
@"emmalloc-memvalidate",
@"emmalloc-verbose",
mimalloc,
};
pub const ResourceFile = struct {
src_path: std.Build.LazyPath,
virtual_path: ?[]const u8 = null,
fn get(self: ResourceFile, b: *std.Build) []const u8 {
return if (self.virtual_path) |vp|
b.fmt("{s}@{s}", .{ self.src_path.getDisplayName(), vp })
else
self.src_path.getDisplayName();
}
};
pub const EmccStepOptions = struct {
optimize: std.builtin.OptimizeMode,
flags: EmccFlags,
settings: EmccSettings,
use_preload_plugins: bool = false,
embed_paths: ?[]const ResourceFile = null,
preload_paths: ?[]const ResourceFile = null,
shell_file_path: ?std.Build.LazyPath = null,
js_library_path: ?std.Build.LazyPath = null,
out_file_name: []const u8,
install_dir: std.Build.InstallDir,
};
// ---------- helpers ----------
pub fn emsdkDep(b: *std.Build) !*std.Build.Dependency {
if (emsdk_dep == null) {
emsdk_dep = try b.dependencyLazy("emsdk", .{});
}
return emsdk_dep.?;
pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath {
return raylib_dep.path("src/shell.html");
}
pub fn path(b: *std.Build, sub_path: []const u8) !std.Build.LazyPath {
return (try emsdkDep(b)).path(sub_path);
}
pub fn emccPath(b: *std.Build) !std.Build.LazyPath {
return try emsdk.path(b, "upstream/emscripten/emcc.py");
}
pub fn emrunPath(b: *std.Build) !std.Build.LazyPath {
return switch (builtin.target.os.tag) {
.windows => try emsdk.path(b, "upstream/emscripten/emrun.bat"),
else => try emsdk.path(b, "upstream/emscripten/emrun"),
};
}
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: struct {
pub const FlagsOptions = struct {
optimize: std.builtin.OptimizeMode,
asyncify: bool = true,
fsanitize: bool = true,
}) EmccFlags {
var flags = EmccFlags.init(allocator);
switch (options.optimize) {
.Debug => {
flags.put("-O0", {}) catch @panic("OOM");
flags.put("-gsource-map", {}) catch @panic("OOM");
if (options.fsanitize)
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
},
.ReleaseSafe => {
flags.put("-O3", {}) catch @panic("OOM");
if (options.fsanitize) {
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
flags.put("-fsanitize-minimal-runtime", {}) catch @panic("OOM");
}
},
.ReleaseFast => flags.put("-O3", {}) catch @panic("OOM"),
.ReleaseSmall => flags.put("-Oz", {}) catch @panic("OOM"),
}
};
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: FlagsOptions) zemscripten.EmccFlags {
var emcc_flags = zemscripten.emccDefaultFlags(allocator, .{
.optimize = options.optimize,
.fsanitize = true,
});
if (options.asyncify)
flags.put("-sASYNCIFY", {}) catch @panic("OOM");
return flags;
emcc_flags.put("-sASYNCIFY", {}) catch unreachable;
return emcc_flags;
}
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: struct {
pub const SettingsOptions = struct {
optimize: std.builtin.OptimizeMode,
es3: bool = false,
glfw3: bool = true,
memory_growth: bool = false,
total_memory: u32 = 134217728,
emsdk_allocator: EmsdkAllocator = .emmalloc,
}) EmccSettings {
var settings = EmccSettings.init(allocator);
switch (options.optimize) {
.Debug, .ReleaseSafe => {
settings.put("SAFE_HEAP", "1") catch @panic("OOM");
settings.put("STACK_OVERFLOW_CHECK", "1") catch @panic("OOM");
settings.put("ASSERTIONS", "1") catch @panic("OOM");
},
else => {},
}
settings.put("MALLOC", @tagName(options.emsdk_allocator)) catch @panic("OOM");
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc,
};
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: SettingsOptions) zemscripten.EmccSettings {
var emcc_settings = zemscripten.emccDefaultSettings(allocator, .{
.optimize = options.optimize,
.emsdk_allocator = options.emsdk_allocator,
});
if (options.es3) {
settings.put("FULL_ES3", "1") catch @panic("OOM");
settings.put("MIN_WEBGL_VERSION", "2") catch @panic("OOM");
settings.put("MAX_WEBGL_VERSION", "2") catch @panic("OOM");
emcc_settings.put("FULL_ES3", "1") catch unreachable;
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable;
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable;
}
if (options.glfw3) {
emcc_settings.put("USE_GLFW", "3") catch unreachable;
}
if (options.glfw3)
settings.put("USE_GLFW", "3") catch @panic("OOM");
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch @panic("OOM");
settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch @panic("OOM");
settings.put("TOTAL_MEMORY", total_memory) catch @panic("OOM");
settings.put("FORCE_FILESYSTEM", "1") catch @panic("OOM");
settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch @panic("OOM");
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable;
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable;
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable;
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
if (options.memory_growth)
settings.put("ALLOW_MEMORY_GROWTH", "1") catch @panic("OOM");
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
return settings;
return emcc_settings;
}
// ---------- step builders ----------
pub fn emccStep(b: *std.Build, src_paths: []const std.Build.LazyPath, compile_steps: []const *std.Build.Step.Compile, options: EmccStepOptions) !*std.Build.Step {
var emcc = b.addRunFile(try emccPath(b));
pub fn emccStep(b: *std.Build, raylib: *std.Build.Step.Compile, wasm: *std.Build.Step.Compile, options: zemscripten.StepOptions) *std.Build.Step {
const activate_emsdk_step = zemscripten.activateEmsdkStep(b);
// flags
{
var it = options.flags.iterator();
while (it.next()) |kv| emcc.addArg(kv.key_ptr.*);
}
const emsdk_dep = b.dependency("emsdk", .{});
raylib.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
wasm.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
// settings
{
var it = options.settings.iterator();
while (it.next()) |kv| {
emcc.addArg(b.fmt("-s{s}={s}", .{ kv.key_ptr.*, kv.value_ptr.* }));
}
}
const emcc_step = zemscripten.emccStep(b, wasm, options);
emcc_step.dependOn(activate_emsdk_step);
// source files & artifact dependencies
for (src_paths) |sp| emcc.addFileArg(sp);
for (compile_steps) |cs| {
emcc.addArtifactArg(cs);
cs.root_module.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
for (cs.root_module.getGraph().modules) |mod| {
for (mod.link_objects.items) |lo| {
if (lo == .other_step) {
const linked = lo.other_step;
if (linked.kind == .lib) emcc.addArtifactArg(linked);
}
}
}
}
emcc.addArg("-o");
const out_file = emcc.addOutputFileArg(options.out_file_name);
// optional args
if (options.use_preload_plugins) emcc.addArg("--use-preload-plugins");
if (options.embed_paths) |eps| for (eps) |ep| {
emcc.addArg("--embed-file");
emcc.addFileArg(ep.src_path);
};
if (options.preload_paths) |pps| for (pps) |pp| {
emcc.addArg("--preload-file");
emcc.addArg(pp.get(b));
};
if (options.shell_file_path) |sfp| {
emcc.addArg("--shell-file");
emcc.addFileArg(sfp);
}
if (options.js_library_path) |jlp| {
emcc.addArg("--js-library");
emcc.addFileArg(jlp);
}
const install = b.addInstallDirectory(.{
.source_dir = out_file.dirname(),
.install_dir = options.install_dir,
.install_subdir = "",
});
install.step.dependOn(&emcc.step);
return &install.step;
return emcc_step;
}
pub fn emrunStep(b: *std.Build, html_path: std.Build.LazyPath, extra_args: []const []const u8) !*std.Build.Step {
var emrun = b.addRunFile(try emrunPath(b));
emrun.addArgs(extra_args);
emrun.addFileArg(html_path);
return &emrun.step;
}
pub fn activateEmsdkStep(b: *std.Build) !*std.Build.Step {
const user = b.step("Activate EMSDK", "Install/Update and prepare emscripten sdk");
const script = switch (builtin.target.os.tag) {
.windows => try emsdk.path(b, "emsdk.bat"),
else => try emsdk.path(b, "emsdk"),
};
var update = b.addRunFile(script);
update.addArg("update");
// chmod / takeown for script
const make_script_exec: ?*std.Build.Step.Run = switch (builtin.target.os.tag) {
.linux, .macos => blk: {
var cmd = b.addSystemCommand(&.{ "chmod", "+x" });
cmd.addFileArg(script);
break :blk cmd;
},
.windows => blk: {
var cmd = b.addSystemCommand(&.{ "takeown", "/f" });
cmd.addFileArg(script);
break :blk cmd;
},
else => null,
};
if (make_script_exec) |mse| update.step.dependOn(&mse.step);
var install = b.addRunFile(script);
install.addArg("install");
install.addArg(emsdk_version);
install.step.dependOn(&update.step);
var activate = b.addRunFile(script);
activate.addArg("activate");
activate.addArg(emsdk_version);
activate.step.dependOn(&install.step);
user.dependOn(&activate.step);
// also ensure emcc/emrun are executable on Unix
if (builtin.target.os.tag == .linux or builtin.target.os.tag == .macos) {
for ([_]std.Build.LazyPath{ try emccPath(b), try emrunPath(b) }) |p| {
var cmd = b.addSystemCommand(&.{ "chmod", "a+x" });
cmd.addFileArg(p);
cmd.step.dependOn(&install.step);
user.dependOn(&cmd.step);
}
}
return user;
pub fn emrunStep(
b: *std.Build,
html_path: []const u8,
extra_args: []const []const u8,
) *std.Build.Step {
return zemscripten.emrunStep(b, html_path, extra_args);
}
};
@ -264,7 +92,7 @@ pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool)
}
fn findWaylandScanner(b: *std.Build) void {
_ = b.findProgram(.{ .names = &.{"wayland-scanner"} }) orelse {
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
std.log.err(
\\ `wayland-scanner` may not be installed on the system.
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
@ -298,20 +126,19 @@ pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
mod.linkSystemLibrary("GL", .{});
}
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) !void {
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void {
// Include xcode_frameworks for cross compilation
const dep = try b.dependencyLazy("xcode_frameworks", .{});
mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib"));
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
mod.addSystemFrameworkPath(dep.path("Frameworks"));
mod.addSystemIncludePath(dep.path("include"));
mod.addLibraryPath(dep.path("lib"));
}
mod.linkFramework("Foundation", .{});
mod.linkFramework("CoreServices", .{});
mod.linkFramework("CoreGraphics", .{});
mod.linkFramework("AppKit", .{});
mod.linkFramework("IOKit", .{});
mod.linkFramework("QuartzCore", .{});
}
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
@ -327,13 +154,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
.root_module = raylib_mod,
});
// On Linux (glibc) avoid _GNU_SOURCE, on glibc >= 2.38 it redirects sscanf(), strtol()...
// to __isoc23_*() symbols, so the generated library fails to link with older glibc versions
if (target.result.os.tag == .linux and !target.result.abi.isAndroid()) {
raylib_mod.addCMacro("_DEFAULT_SOURCE", "");
} else {
raylib_mod.addCMacro("_GNU_SOURCE", "");
}
raylib_mod.addCMacro("_GNU_SOURCE", "");
raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L");
var arena: std.heap.ArenaAllocator = .init(b.allocator);
@ -440,7 +261,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
});
_ = raylib_flags_arr.pop();
try linkMacOS(b, raylib_mod);
linkMacOS(b, raylib_mod);
},
.emscripten => {
switch (opengl_version) {
@ -451,9 +272,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
raylib_mod.addCMacro("PLATFORM_WEB", "");
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
@ -502,7 +321,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
}
},
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
.macos => try linkMacOS(b, raylib_mod),
.macos => linkMacOS(b, raylib_mod),
.emscripten => {
switch (opengl_version) {
.auto => opengl_version = OpenglVersion.gles_2,
@ -511,10 +330,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
}
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
raylib.step.dependOn(activate_emsdk_step);
},
else => @panic("Target is not supported with this platform"),
@ -660,33 +476,33 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
return raylib;
}
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) !void {
const raygui_dep = try b.dependencyLazy("raygui", .{
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void {
if (b.lazyDependency("raygui", .{
.target = target,
.optimize = optimize,
.link_libc = true,
});
})) |raygui_dep| {
var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step);
var gen_step = b.addWriteFiles();
raylib.step.dependOn(&gen_step.step);
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
raylib.root_module.addIncludePath(raygui_dep.path("src"));
raylib.root_module.addIncludePath(b.path("src"));
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
raylib.root_module.addIncludePath(raygui_dep.path("src"));
raylib.root_module.addIncludePath(b.path("src"));
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
const c = b.addTranslateC(.{
.root_source_file = raygui_dep.path("src/raygui.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
c.addIncludePath(b.path("src"));
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
const c = b.addTranslateC(.{
.root_source_file = raygui_dep.path("src/raygui.h"),
.target = target,
.optimize = optimize,
.link_libc = true,
});
c.addIncludePath(b.path("src"));
const c_mod = c.createModule();
c_mod.linkLibrary(raylib);
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
}
}
pub const Options = struct {
@ -807,7 +623,7 @@ pub fn build(b: *std.Build) !void {
translateCMod("rlgl", b, target, optimize, lib);
if (options.raygui) {
try addRaygui(b, target, optimize, lib);
addRaygui(b, target, optimize, lib);
}
const examples = b.step("examples", "build/install all examples");
@ -832,7 +648,7 @@ fn addExamples(
const all = b.step(module, "All " ++ module ++ " examples");
const module_subpath = b.pathJoin(&.{ "examples", module });
var dir = try b.root.openDir(b.graph.io, module_subpath, .{ .iterate = true });
var dir = try b.build_root.handle.openDir(b.graph.io, module_subpath, .{ .iterate = true });
defer dir.close(b.graph.io);
var iter = dir.iterate();
@ -882,7 +698,7 @@ fn addExamples(
exe_mod.addCMacro("PLATFORM_WEB", "");
const wasm = b.addLibrary(.{
.name = b.fmt("{s}.html", .{filename}),
.name = filename,
.root_module = exe_mod,
});
@ -890,40 +706,25 @@ fn addExamples(
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
const SerialResourceFile = struct { src_path: []const u8, virtual_path: []const u8 };
const EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const SerialResourceFile);
const EmccExamplesPreloadSerial = struct { []const u8, []const SerialResourceFile };
const emcc_examples_preloads_serial: []const EmccExamplesPreloadSerial = @import("examples/example_resources.zon");
const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads_serial);
const preload_paths: ?[]emsdk.ResourceFile = blk: {
if (emcc_examples_preloads_map.get(filename)) |resource_files| {
var rfs = try b.allocator.alloc(emsdk.ResourceFile, resource_files.len);
for (resource_files, 0..) |resource_file, rfidx| {
rfs[rfidx] = .{
.src_path = b.path(resource_file.src_path),
.virtual_path = resource_file.virtual_path,
};
}
break :blk rfs;
} else break :blk null;
};
const EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const emsdk.zemscripten.EmccFilePath);
const EmccExamplesPreloadKV = struct { []const u8, []const emsdk.zemscripten.EmccFilePath };
const emcc_examples_preloads: []const EmccExamplesPreloadKV = @import("examples/example_resources.zon");
const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads);
const emcc_step = try emsdk.emccStep(b, &.{}, &.{ raylib, wasm }, .{
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{
.optimize = optimize,
.flags = emcc_flags,
.settings = emcc_settings,
.preload_paths = preload_paths,
.preload_paths = emcc_examples_preloads_map.get(filename) orelse &.{},
.shell_file_path = b.path("src/shell.html"),
.install_dir = install_dir,
.out_file_name = wasm.name,
});
b.getInstallStep().dependOn(emcc_step);
const emrun_step = try emsdk.emrunStep(
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
const emrun_step = emsdk.emrunStep(
b,
b.graph.path(.install_prefix, b.fmt(
"web/{s}/{s}/{s}",
.{ module, filename, wasm.name },
)),
b.getInstallPath(install_dir, html_filename),
&.{},
);
@ -958,7 +759,7 @@ fn waylandGenerate(
comptime waylandDir: []const u8,
comptime source: bool,
) !void {
const dir = try b.root.openDir(b.graph.io, waylandDir, .{ .iterate = true });
const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true });
defer dir.close(b.graph.io);
var iter = dir.iterate();
@ -992,3 +793,4 @@ fn waylandGenerate(
}
}
}

View File

@ -1,7 +1,7 @@
.{
.name = .raylib,
.version = "6.0.0",
.minimum_zig_version = "0.17.0",
.minimum_zig_version = "0.16.0",
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
@ -12,14 +12,17 @@
.lazy = true,
},
.raygui = .{
.url = "git+https://github.com/raysan5/raygui#3f81e2bd02bf08dcd9d350e8e8b3cf58044d6877",
.hash = "N-V-__8AAPPCmABYkTrLoRGTR6whFQP1bvg7p5vpLsKIcn4G",
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
.lazy = true,
},
.emsdk = .{
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
.lazy = true,
},
.zemscripten = .{
.url = "git+https://github.com/zig-gamedev/zemscripten#3fa4b778852226c7346bdcc3c1486e875a9a6d02",
.hash = "zemscripten-0.2.0-dev-sRlDqApRAACspTbAZnuNKWIzfWzSYgYkb2nWAXZ-tqqt",
},
},

View File

@ -1,18 +1,6 @@
# Setup the project and settings
cmake_minimum_required(VERSION 3.22)
project(examples)
# Include raylib's cmake helper functions, so the examples can also be
# configured standalone (`cd examples && cmake .`) and not only as part
# of the raylib project.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
include(AddIfFlagCompiles)
# Default to the Desktop platform when configured standalone.
if (NOT DEFINED PLATFORM)
set(PLATFORM "Desktop" CACHE STRING "Platform to build examples for")
endif ()
# Directories that contain examples
set(example_dirs
audio
@ -201,7 +189,6 @@ foreach (example_source ${example_sources})
target_link_libraries(${example_name} "-framework IOKit")
target_link_libraries(${example_name} "-framework Cocoa")
target_link_libraries(${example_name} "-framework OpenGL")
target_link_libraries(${example_name} "-framework QuartzCore")
endif()
elseif (${PLATFORM} MATCHES "RGFW")

View File

@ -18,7 +18,7 @@
# > PLATFORM_DESKTOP_RGFW (RGFW backend):
# - Windows (Win32, Win64)
# - Linux (X11 desktop mode)
# - macOS/OSX (x64, arm64)
# - macOS/OSX (x64, arm64 (not tested))
# - Others (not tested)
# > PLATFORM_DESKTOP_WIN32 (native Win32):
# - Windows (Win32, Win64)
@ -122,14 +122,6 @@ BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources
# WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3
BUILD_WEB_WEBGL2 ?= FALSE
# Detect the shell used by make: cmd preserves quotes, while sh removes them.
ifndef PLATFORM_SHELL
PLATFORM_SHELL = sh
ifeq ($(shell echo "test"),"test")
PLATFORM_SHELL = cmd
endif
endif
# Determine PLATFORM_OS when required
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW))
# No uname.exe on MinGW!, but OS=Windows_NT on Windows!
@ -322,9 +314,6 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),BSD)
LDFLAGS += -Lsrc -L$(RAYLIB_LIB_PATH)
endif
ifeq ($(PLATFORM_OS),OSX)
LDFLAGS += -L/opt/homebrew/lib -L$(RAYLIB_LIB_PATH)
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
ifeq ($(PLATFORM_OS),WINDOWS)
@ -429,7 +418,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),OSX)
# Libraries for OSX 10.9 desktop compiling
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
endif
ifeq ($(PLATFORM_OS),BSD)
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
@ -507,7 +496,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
# NOTE: Required packages: libegl1-mesa-dev
LDFLAGS += -L../src
LDLIBS = -lraylib -lm
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
@ -600,12 +589,10 @@ SHAPES = \
shapes/shapes_dashed_line \
shapes/shapes_digital_clock \
shapes/shapes_double_pendulum \
shapes/shapes_drag_puzzle \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_easings_testbed \
shapes/shapes_ellipse_collision \
shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \
@ -616,11 +603,8 @@ SHAPES = \
shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \
shapes/shapes_outlines_testbed \
shapes/shapes_outlines_thickness \
shapes/shapes_penrose_tile \
shapes/shapes_pie_chart \
shapes/shapes_polygon_lines \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
shapes/shapes_recursive_tree \
@ -658,7 +642,6 @@ TEXTURES = \
textures/textures_npatch_drawing \
textures/textures_particles_blending \
textures/textures_polygon_drawing \
textures/textures_portal_window \
textures/textures_raw_data \
textures/textures_screen_buffer \
textures/textures_sprite_animation \
@ -710,10 +693,8 @@ MODELS = \
models/models_loading_vox \
models/models_mesh_generation \
models/models_mesh_picking \
models/models_mesh_uv_painting \
models/models_orthographic_projection \
models/models_point_rendering \
models/models_procedural_decals \
models/models_rlgl_solar_system \
models/models_rotating_cube \
models/models_skybox_rendering \
@ -739,7 +720,6 @@ SHADERS = \
shaders/shaders_hybrid_rendering \
shaders/shaders_julia_set \
shaders/shaders_lightmap_rendering \
shaders/shaders_lights_bloom \
shaders/shaders_mandelbrot_set \
shaders/shaders_mesh_instancing \
shaders/shaders_model_shader \
@ -761,7 +741,6 @@ SHADERS = \
shaders/shaders_vertex_displacement
AUDIO = \
audio/audio_amp_envelope \
audio/audio_mixed_processor \
audio/audio_module_playing \
audio/audio_music_stream \
@ -802,11 +781,7 @@ endif
clean:
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),WINDOWS)
ifeq ($(PLATFORM_SHELL),cmd)
del *.o *.exe /s
else
find . -type f '(' -name '*.o' -o -name '*.exe' ')' -exec rm -f {} +
endif
endif
ifeq ($(PLATFORM_OS),BSD)
find . -type f -perm -ugo+x -delete
@ -823,23 +798,19 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
ifeq ($(PLATFORM_OS),WINDOWS)
ifeq ($(PLATFORM_SHELL),cmd)
del *.o *.exe /s
else
find . -type f '(' -name '*.o' -o -name '*.exe' ')' -exec rm -f {} +
endif
del *.o *.exe /s
endif
ifeq ($(PLATFORM_OS),BSD)
find . -type f -perm -ugo+x -delete
rm -fv *.o
find . -type f -perm -ugo+x -delete
rm -fv *.o
endif
ifeq ($(PLATFORM_OS),LINUX)
find . -type f -executable -delete
rm -fv *.o
find . -type f -executable -delete
rm -fv *.o
endif
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
find . -type f -perm +ugo+x -delete
rm -f *.o
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
@ -847,7 +818,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
rm -fv *.o
endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
ifeq ($(PLATFORM_SHELL),cmd)
ifeq ($(PLATFORM_OS),WINDOWS)
del *.wasm *.html *.js *.data
else
rm -f */*.wasm */*.html */*.js */*.data

View File

@ -411,7 +411,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
ifeq ($(PLATFORM_OS),OSX)
# Libraries for OSX 10.9 desktop compiling
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
endif
ifeq ($(PLATFORM_OS),BSD)
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
@ -480,7 +480,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
# NOTE: Required packages: libegl1-mesa-dev
LDFLAGS += -L../src
LDLIBS = -lraylib -lm
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
endif
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
@ -561,12 +561,10 @@ SHAPES = \
shapes/shapes_dashed_line \
shapes/shapes_digital_clock \
shapes/shapes_double_pendulum \
shapes/shapes_drag_puzzle \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_easings_testbed \
shapes/shapes_ellipse_collision \
shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \
@ -577,11 +575,8 @@ SHAPES = \
shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \
shapes/shapes_outlines_testbed \
shapes/shapes_outlines_thickness \
shapes/shapes_penrose_tile \
shapes/shapes_pie_chart \
shapes/shapes_polygon_lines \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
shapes/shapes_recursive_tree \
@ -619,7 +614,6 @@ TEXTURES = \
textures/textures_npatch_drawing \
textures/textures_particles_blending \
textures/textures_polygon_drawing \
textures/textures_portal_window \
textures/textures_raw_data \
textures/textures_screen_buffer \
textures/textures_sprite_animation \
@ -671,10 +665,8 @@ MODELS = \
models/models_loading_vox \
models/models_mesh_generation \
models/models_mesh_picking \
models/models_mesh_uv_painting \
models/models_orthographic_projection \
models/models_point_rendering \
models/models_procedural_decals \
models/models_rlgl_solar_system \
models/models_rotating_cube \
models/models_skybox_rendering \
@ -700,7 +692,6 @@ SHADERS = \
shaders/shaders_hybrid_rendering \
shaders/shaders_julia_set \
shaders/shaders_lightmap_rendering \
shaders/shaders_lights_bloom \
shaders/shaders_mandelbrot_set \
shaders/shaders_mesh_instancing \
shaders/shaders_model_shader \
@ -722,7 +713,6 @@ SHADERS = \
shaders/shaders_vertex_displacement
AUDIO = \
audio/audio_amp_envelope \
audio/audio_mixed_processor \
audio/audio_module_playing \
audio/audio_music_stream \
@ -931,9 +921,6 @@ shapes/shapes_digital_clock: shapes/shapes_digital_clock.c
shapes/shapes_double_pendulum: shapes/shapes_double_pendulum.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_drag_puzzle: shapes/shapes_drag_puzzle.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_easings_ball: shapes/shapes_easings_ball.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -946,9 +933,6 @@ shapes/shapes_easings_rectangles: shapes/shapes_easings_rectangles.c
shapes/shapes_easings_testbed: shapes/shapes_easings_testbed.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_ellipse_collision: shapes/shapes_ellipse_collision.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_following_eyes: shapes/shapes_following_eyes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -979,21 +963,12 @@ shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c
shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_outlines_testbed: shapes/shapes_outlines_testbed.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_outlines_thickness: shapes/shapes_outlines_thickness.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_penrose_tile: shapes/shapes_penrose_tile.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_pie_chart: shapes/shapes_pie_chart.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_polygon_lines: shapes/shapes_polygon_lines.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1123,9 +1098,6 @@ textures/textures_polygon_drawing: textures/textures_polygon_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/cat.png@resources/cat.png
textures/textures_portal_window: textures/textures_portal_window.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
textures/textures_raw_data: textures/textures_raw_data.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/fudesumi.raw@resources/fudesumi.raw
@ -1345,18 +1317,12 @@ models/models_mesh_picking: models/models_mesh_picking.c
--preload-file models/resources/models/obj/turret.obj@resources/models/obj/turret.obj \
--preload-file models/resources/models/obj/turret_diffuse.png@resources/models/obj/turret_diffuse.png
models/models_mesh_uv_painting: models/models_mesh_uv_painting.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_orthographic_projection: models/models_orthographic_projection.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_point_rendering: models/models_point_rendering.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_procedural_decals: models/models_procedural_decals.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
models/models_rlgl_solar_system: models/models_rlgl_solar_system.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -1494,12 +1460,6 @@ shaders/shaders_lightmap_rendering: shaders/shaders_lightmap_rendering.c
--preload-file shaders/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png \
--preload-file shaders/resources/spark_flame.png@resources/spark_flame.png
shaders/shaders_lights_bloom: shaders/shaders_lights_bloom.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/lights_bloom.vs@resources/shaders/glsl100/lights_bloom.vs \
--preload-file shaders/resources/shaders/glsl100/lights_bloom.fs@resources/shaders/glsl100/lights_bloom.fs \
--preload-file shaders/resources/shaders/glsl100/lights_bloom_post.fs@resources/shaders/glsl100/lights_bloom_post.fs
shaders/shaders_mandelbrot_set: shaders/shaders_mandelbrot_set.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/mandelbrot_set.fs@resources/shaders/glsl100/mandelbrot_set.fs
@ -1607,9 +1567,6 @@ shaders/shaders_vertex_displacement: shaders/shaders_vertex_displacement.c
--preload-file shaders/resources/shaders/glsl100/vertex_displacement.fs@resources/shaders/glsl100/vertex_displacement.fs
# Compile AUDIO examples
audio/audio_amp_envelope: audio/audio_amp_envelope.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
audio/audio_mixed_processor: audio/audio_mixed_processor.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3 \

View File

@ -13,13 +13,11 @@ The examples assume you have already built the `raylib` library in `../src`.
The [Zig](https://ziglang.org/) toolchain can compile `C` and `C++` in addition to `Zig`.
You may find it easier to use than other toolchains, especially when it comes to cross-compiling.
Run the following commands from the repository root:
- `zig build examples` to compile all examples
- `zig build` to compile all examples
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
## EXAMPLES COLLECTION [TOTAL: 222]
## EXAMPLES COLLECTION [TOTAL: 212]
### category: core [49]
@ -77,7 +75,7 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_keyboard_testbed](core/core_keyboard_testbed.c) | <img src="core/core_keyboard_testbed.png" alt="core_keyboard_testbed" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_window_web](core/core_window_web.c) | <img src="core/core_window_web.png" alt="core_window_web" width="80"> | ⭐☆☆☆ | 1.3 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
### category: shapes [45]
### category: shapes [40]
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
@ -123,13 +121,8 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) | <img src="shapes/shapes_penrose_tile.png" alt="shapes_penrose_tile" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
| [shapes_hilbert_curve](shapes/shapes_hilbert_curve.c) | <img src="shapes/shapes_hilbert_curve.png" alt="shapes_hilbert_curve" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
| [shapes_easings_testbed](shapes/shapes_easings_testbed.c) | <img src="shapes/shapes_easings_testbed.png" alt="shapes_easings_testbed" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Juan Miguel López](https://github.com/flashback-fx) |
| [shapes_drag_puzzle](shapes/shapes_drag_puzzle.c) | <img src="shapes/shapes_drag_puzzle.png" alt="shapes_drag_puzzle" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Gabriel Piangers](https://github.com/gabriel-piangers) |
| [shapes_ellipse_collision](shapes/shapes_ellipse_collision.c) | <img src="shapes/shapes_ellipse_collision.png" alt="shapes_ellipse_collision" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Ziya](https://github.com/Monjaris) |
| [shapes_outlines_testbed](shapes/shapes_outlines_testbed.c) | <img src="shapes/shapes_outlines_testbed.png" alt="shapes_outlines_testbed" width="80"> | ⭐⭐⭐☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
| [shapes_outlines_thickness](shapes/shapes_outlines_thickness.c) | <img src="shapes/shapes_outlines_thickness.png" alt="shapes_outlines_thickness" width="80"> | ⭐☆☆☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
| [shapes_polygon_lines](shapes/shapes_polygon_lines.c) | <img src="shapes/shapes_polygon_lines.png" alt="shapes_polygon_lines" width="80"> | ⭐⭐☆☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
### category: textures [33]
### category: textures [32]
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
@ -153,7 +146,7 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_sprite_button](textures/textures_sprite_button.c) | <img src="textures/textures_sprite_button.png" alt="textures_sprite_button" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_sprite_explosion](textures/textures_sprite_explosion.c) | <img src="textures/textures_sprite_explosion.png" alt="textures_sprite_explosion" width="80"> | ⭐⭐☆☆ | 2.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_bunnymark](textures/textures_bunnymark.c) | <img src="textures/textures_bunnymark.png" alt="textures_bunnymark" width="80"> | ⭐⭐⭐☆ | 1.6 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 6.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
| [textures_blend_modes](textures/textures_blend_modes.c) | <img src="textures/textures_blend_modes.png" alt="textures_blend_modes" width="80"> | ⭐☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) |
| [textures_tiled_drawing](textures/textures_tiled_drawing.c) | <img src="textures/textures_tiled_drawing.png" alt="textures_tiled_drawing" width="80"> | ⭐⭐⭐☆ | 3.0 | 4.2 | [Vlad Adrian](https://github.com/demizdor) |
| [textures_polygon_drawing](textures/textures_polygon_drawing.c) | <img src="textures/textures_polygon_drawing.png" alt="textures_polygon_drawing" width="80"> | ⭐☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
@ -167,7 +160,6 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
| [textures_cellular_automata](textures/textures_cellular_automata.c) | <img src="textures/textures_cellular_automata.png" alt="textures_cellular_automata" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [textures_framebuffer_rendering](textures/textures_framebuffer_rendering.c) | <img src="textures/textures_framebuffer_rendering.png" alt="textures_framebuffer_rendering" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jack Boakes](https://github.com/jackboakes) |
| [textures_portal_window](textures/textures_portal_window.c) | <img src="textures/textures_portal_window.png" alt="textures_portal_window" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
### category: text [16]
@ -192,7 +184,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
| [text_strings_management](text/text_strings_management.c) | <img src="text/text_strings_management.png" alt="text_strings_management" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
### category: models [32]
### category: models [30]
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
@ -228,10 +220,8 @@ Examples using raylib models functionality, including models loading/generation
| [models_animation_blend_custom](models/models_animation_blend_custom.c) | <img src="models/models_animation_blend_custom.png" alt="models_animation_blend_custom" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [dmitrii-brand](https://github.com/dmitrii-brand) |
| [models_animation_blending](models/models_animation_blending.c) | <img src="models/models_animation_blending.png" alt="models_animation_blending" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
| [models_animation_timing](models/models_animation_timing.c) | <img src="models/models_animation_timing.png" alt="models_animation_timing" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [models_mesh_uv_painting](models/models_mesh_uv_painting.c) | <img src="models/models_mesh_uv_painting.png" alt="models_mesh_uv_painting" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
| [models_procedural_decals](models/models_procedural_decals.c) | <img src="models/models_procedural_decals.png" alt="models_procedural_decals" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
### category: shaders [36]
### category: shaders [35]
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.h) module.
@ -272,9 +262,8 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_game_of_life](shaders/shaders_game_of_life.c) | <img src="shaders/shaders_game_of_life.png" alt="shaders_game_of_life" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
| [shaders_rlgl_compute](shaders/shaders_rlgl_compute.c) | <img src="shaders/shaders_rlgl_compute.png" alt="shaders_rlgl_compute" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
| [shaders_cel_shading](shaders/shaders_cel_shading.c) | <img src="shaders/shaders_cel_shading.png" alt="shaders_cel_shading" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Gleb A](https://github.com/ggrizzly) |
| [shaders_lights_bloom](shaders/shaders_lights_bloom.c) | <img src="shaders/shaders_lights_bloom.png" alt="shaders_lights_bloom" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
### category: audio [11]
### category: audio [10]
Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib.
@ -287,10 +276,9 @@ Examples using raylib audio functionality, including sound/music loading and pla
| [audio_mixed_processor](audio/audio_mixed_processor.c) | <img src="audio/audio_mixed_processor.png" alt="audio_mixed_processor" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
| [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 6.0 | [Le Juez Victor](https://github.com/Bigfoot71) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [IANN](https://github.com/meisei4) |
| [audio_stream_callback](audio/audio_stream_callback.c) | <img src="audio/audio_stream_callback.png" alt="audio_stream_callback" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Dan Hoang](https://github.com/dan-hoang) |
| [audio_amp_envelope](audio/audio_amp_envelope.c) | <img src="audio/audio_amp_envelope.png" alt="audio_amp_envelope" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Arbinda Rizki Muhammad](https://github.com/arbipink) |
Some example missing? As always, contributions are welcome, feel free to send new examples!
Here is an [examples template](examples_template.c) with instructions to start with!

View File

@ -113,7 +113,6 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadMusicStream(music); // Unload music stream buffers from RAM
UnloadSound(sound);
DetachAudioMixedProcessor(ProcessAudio); // Disconnect audio processor

View File

@ -90,7 +90,7 @@ int main(void)
for (int i = 0; i < BUFFER_SIZE; i++)
{
int wavelength = SAMPLE_RATE/sineFrequency;
buffer[i] = sinf(2*PI*sineIndex/wavelength);
buffer[i] = sin(2*PI*sineIndex/wavelength);
sineIndex++;
if (sineIndex >= wavelength)
@ -116,8 +116,8 @@ int main(void)
DrawText("Up/down to change frequency", 10, 10, 20, DARKGRAY);
DrawText("Left/right to pan", 10, 30, 20, DARKGRAY);
int windowStart = (int)((GetTime() - sineStartTime)*SAMPLE_RATE);
int windowSize = SAMPLE_RATE/10;
int windowStart = (GetTime() - sineStartTime)*SAMPLE_RATE;
int windowSize = 0.1f*SAMPLE_RATE;
int wavelength = SAMPLE_RATE/sineFrequency;
// Draw a sine wave with the same frequency as the one being sent to the audio stream
@ -125,8 +125,8 @@ int main(void)
{
int t0 = windowStart + i*windowSize/screenWidth;
int t1 = windowStart + (i + 1)*windowSize/screenWidth;
Vector2 startPos = { (float)i, 250 + 50*sinf(2*PI*t0/wavelength) };
Vector2 endPos = { (float)i + 1, 250 + 50*sinf(2*PI*t1/wavelength) };
Vector2 startPos = { i, 250 + 50*sin(2*PI*t0/wavelength) };
Vector2 endPos = { i + 1, 250 + 50*sin(2*PI*t1/wavelength) };
DrawLineV(startPos, endPos, RED);
}

View File

@ -4,7 +4,7 @@
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.5, last time updated with raylib 6.0
* Example originally created with raylib 5.5, last time updated with raylib 5.5
*
* Example contributed by Le Juez Victor (@Bigfoot71) and reviewed by Ramon Santamaria (@raysan5)
*
@ -116,14 +116,14 @@ static void SetSoundPosition(Camera listener, Sound sound, Vector3 position, flo
// Calculate normalized vectors for spatial positioning
Vector3 normalizedDirection = Vector3Normalize(direction);
Vector3 forward = Vector3Normalize(Vector3Subtract(listener.target, listener.position));
Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, listener.up));
Vector3 right = Vector3Normalize(Vector3CrossProduct(listener.up, forward));
// Reduce volume for sounds behind the listener
float dotProduct = Vector3DotProduct(forward, normalizedDirection);
if (dotProduct < 0.0f) attenuation *= (1.0f + dotProduct*0.5f);
// Set stereo panning based on sound position relative to listener
float pan = Vector3DotProduct(normalizedDirection, right);
float pan = 0.5f + 0.5f*Vector3DotProduct(normalizedDirection, right);
// Apply final sound properties
SetSoundVolume(sound, attenuation);

View File

@ -131,10 +131,10 @@ int main(void)
DrawText("Left/right to change wave type", 10, 30, 20, DARKGRAY);
// Draw the last 10 ms of uploaded audio
for (int i = 0; i < screenWidth - 1; i++)
for (int i = 0; i < screenWidth; i++)
{
Vector2 startPos = {(float)i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
Vector2 endPos = { (float)(i + 1), 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
Vector2 startPos = { i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
Vector2 endPos = { i + 1, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
DrawLineV(startPos, endPos, RED);
}
@ -161,9 +161,9 @@ static void SineCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the sine wave
for (unsigned int i = 0; i < frameCount; i++)
for (int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = sinf(2*PI*waveIndex/wavelength);
((float *)framesOut)[i] = sin(2*PI*waveIndex/wavelength);
waveIndex++;
@ -175,8 +175,8 @@ static void SineCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}
static void SquareCallback(void *framesOut, unsigned int frameCount)
@ -184,9 +184,9 @@ static void SquareCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the square wave
for (unsigned int i = 0; i < frameCount; i++)
for (int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1.0f : -1.0f;
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1 : -1;
waveIndex++;
if (waveIndex >= wavelength)
@ -197,8 +197,8 @@ static void SquareCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}
static void TriangleCallback(void *framesOut, unsigned int frameCount)
@ -206,7 +206,7 @@ static void TriangleCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the triangle wave
for (unsigned int i = 0; i < frameCount; i++)
for (int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = (waveIndex < wavelength/2)? (-1 + 2.0f*waveIndex/(wavelength/2)) : (1 - 2.0f*(waveIndex - wavelength/2)/(wavelength/2));
waveIndex++;
@ -219,8 +219,8 @@ static void TriangleCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}
static void SawtoothCallback(void *framesOut, unsigned int frameCount)
@ -228,7 +228,7 @@ static void SawtoothCallback(void *framesOut, unsigned int frameCount)
int wavelength = SAMPLE_RATE/waveFrequency;
// Synthesize the sawtooth wave
for (unsigned int i = 0; i < frameCount; i++)
for (int i = 0; i < frameCount; i++)
{
((float *)framesOut)[i] = -1 + 2.0f*waveIndex/wavelength;
waveIndex++;
@ -241,6 +241,6 @@ static void SawtoothCallback(void *framesOut, unsigned int frameCount)
}
// Save the synthesized samples for later drawing
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float*)framesOut)[i];
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
}

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,7 @@ int main(void)
Camera2D camera = { 0 };
camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f };
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;

View File

@ -65,8 +65,8 @@ int main(void)
// Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
// Set the offset to where the mouse is
camera.offset = GetMousePosition();
// Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom
@ -86,8 +86,8 @@ int main(void)
// Get the world point that is under the mouse
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
// Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
// Set the offset to where the mouse is
camera.offset = GetMousePosition();
// Set the target to match, so that the camera maps the world space point
// under the cursor to the screen space point under the cursor at any zoom

View File

@ -75,7 +75,7 @@ int main(void)
Camera2D camera = { 0 };
camera.target = player.position;
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;

View File

@ -19,7 +19,6 @@
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define PLAYER_SIZE 40
@ -40,13 +39,13 @@ int main(void)
Camera2D camera1 = { 0 };
camera1.target = (Vector2){ player1.x, player1.y };
camera1.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
camera1.offset = (Vector2){ 200.0f, 200.0f };
camera1.rotation = 0.0f;
camera1.zoom = 1.0f;
Camera2D camera2 = { 0 };
camera2.target = (Vector2){ player2.x, player2.y };
camera2.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
camera2.offset = (Vector2){ 200.0f, 200.0f };
camera2.rotation = 0.0f;
camera2.zoom = 1.0f;

View File

@ -69,7 +69,7 @@ int main(void)
// Define camera
Camera2D camera = { 0 };
camera.target = player.position;
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
@ -117,7 +117,7 @@ int main(void)
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
@ -169,7 +169,7 @@ int main(void)
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}
@ -205,7 +205,7 @@ int main(void)
// Update camera
//----------------------------------------------------------------------------------
camera.target = player.position;
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
// WARNING: On event replay, mouse-wheel internal value is set
@ -267,7 +267,7 @@ int main(void)
player.canJump = false;
camera.target = player.position;
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
}

View File

@ -92,7 +92,7 @@ int main(void)
if (currentFps <= 0) fpsText = TextFormat("FPS: unlimited (%i)", GetFPS());
else fpsText = TextFormat("FPS: %i (target: %i)", GetFPS(), currentFps);
DrawText(fpsText, 10, 10, 20, DARKGRAY);
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()*1000.0f), 10, 30, 20, DARKGRAY);
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()), 10, 30, 20, DARKGRAY);
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, DARKGRAY);
// Draw the text above the circles

View File

@ -88,7 +88,7 @@ int main(void)
DrawCircleV(GetMousePosition(), 20, MAROON);
DrawRectangleRec((Rectangle) { mousePos.x - 25, mousePos.y, 50, 2 }, BLACK);
DrawRectangleRec((Rectangle) { mousePos.x, mousePos.y - 25, 2, 50 }, BLACK);
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), (int)mousePos.x - 44,
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
(mousePos.y > GetScreenHeight() - 60)? (int)mousePos.y - 46 : (int)mousePos.y + 30, 20, BLACK);
EndDrawing();
@ -97,6 +97,9 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
// TODO: Unload all loaded resources at this point
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -50,7 +50,7 @@ int main(void)
// NOTE: The gesture log uses an array (as an inverted circular queue) to store the performed gestures
char gestureLog[GESTURE_LOG_SIZE][12] = { "" };
// NOTE: The index for the inverted circular queue (moving from last to first direction, then looping around)
int gestureLogIndex = 0;
int gestureLogIndex = GESTURE_LOG_SIZE;
int previousGesture = 0;
// Log mode values:

View File

@ -94,7 +94,6 @@ int main(void)
// De-Initialization
//---------------------------------------------------------
UnloadRenderTexture(target);
CloseWindow(); // Close window and OpenGL context
//----------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
#
# This list is used as the main reference by [rexm] tool for examples collection validation and management
#
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2026;"Ramon Santamaria";@raysan5
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5
core;core_delta_time;★☆☆☆;5.5;6.0;2025;2025;"Robin";@RobinsAviary
core;core_input_keys;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_mouse;★☆☆☆;1.0;5.5;2014;2025;"Ramon Santamaria";@raysan5
@ -98,11 +98,6 @@ shapes;shapes_ball_physics;★★☆☆;6.0;6.0;2025;2025;"David Buzatto";@david
shapes;shapes_penrose_tile;★★★★;5.5;6.0;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_hilbert_curve;★★★☆;5.6;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
shapes;shapes_easings_testbed;★★★☆;2.5;2.5;2019;2025;"Juan Miguel López";@flashback-fx
shapes;shapes_drag_puzzle;★☆☆☆;6.0;6.0;2026;2026;"Gabriel Piangers";@gabriel-piangers
shapes;shapes_ellipse_collision;★★☆☆;5.5;5.5;2025;2025;"Ziya";@Monjaris
shapes;shapes_outlines_testbed;★★★☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
shapes;shapes_outlines_thickness;★☆☆☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
shapes;shapes_polygon_lines;★★☆☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
textures;textures_clipboard_image;★☆☆☆;6.0;6.0;2026;2026;"Maicon Santana";@maiconpintoabreu
textures;textures_magnifying_glass;★★★☆;5.6;5.6;2026;2026;"Luke Vaughan";@badram
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
@ -121,7 +116,7 @@ textures;textures_sprite_animation;★★☆☆;1.3;1.3;2014;2025;"Ramon Santama
textures;textures_sprite_button;★★☆☆;2.5;2.5;2019;2025;"Ramon Santamaria";@raysan5
textures;textures_sprite_explosion;★★☆☆;2.5;3.5;2019;2025;"Ramon Santamaria";@raysan5
textures;textures_bunnymark;★★★☆;1.6;2.5;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_mouse_painting;★★★☆;3.0;6.0;2019;2025;"Chris Dill";@MysteriousSpace
textures;textures_mouse_painting;★★★☆;3.0;3.0;2019;2025;"Chris Dill";@MysteriousSpace
textures;textures_blend_modes;★☆☆☆;3.5;3.5;2020;2025;"Karlo Licudine";@accidentalrebel
textures;textures_tiled_drawing;★★★☆;3.0;4.2;2020;2025;"Vlad Adrian";@demizdor
textures;textures_polygon_drawing;★☆☆☆;3.7;3.7;2021;2025;"Chris Camacho";@chriscamacho
@ -135,7 +130,6 @@ textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";
textures;textures_sprite_stacking;★★☆☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
textures;textures_cellular_automata;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
textures;textures_framebuffer_rendering;★★☆☆;5.6;5.6;2026;2026;"Jack Boakes";@jackboakes
textures;textures_portal_window;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5
text;text_font_spritefont;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
@ -182,8 +176,6 @@ models;models_directional_billboard;★★☆☆;6.0;6.0;2025;2025;"Robin";@Robi
models;models_animation_blend_custom;★★★★;5.5;6.0;2026;2026;"dmitrii-brand";@dmitrii-brand
models;models_animation_blending;★★★★;5.5;6.0;2024;2026;"Kirandeep";@Kirandeep-Singh-Khehra
models;models_animation_timing;★★★☆;6.0;6.0;2026;2026;"Ramon Santamaria";@raysan5
models;models_mesh_uv_painting;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
models;models_procedural_decals;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
shaders;shaders_ascii_rendering;★★☆☆;5.5;6.0;2025;2025;"Maicon Santana";@maiconpintoabreu
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
@ -219,7 +211,6 @@ shaders;shaders_depth_rendering;★★★☆;6.0;6.0;2025;2025;"Luís Almeida";@
shaders;shaders_game_of_life;★★★☆;6.0;6.0;2025;2025;"Jordi Santonja";@JordSant
shaders;shaders_rlgl_compute;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
shaders;shaders_cel_shading;★★★☆;6.0;6.0;2026;2026;"Gleb A";@ggrizzly
shaders;shaders_lights_bloom;★★★☆;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
audio;audio_module_playing;★☆☆☆;1.5;3.5;2016;2025;"Ramon Santamaria";@raysan5
audio;audio_music_stream;★☆☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
audio;audio_raw_stream;★★★☆;1.6;6.0;2015;2026;"Ramon Santamaria";@raysan5
@ -227,7 +218,6 @@ audio;audio_sound_loading;★☆☆☆;1.1;3.5;2014;2025;"Ramon Santamaria";@ray
audio;audio_mixed_processor;★★★★;4.2;4.2;2023;2025;"hkc";@hatkidchan
audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@raysan5
audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
audio;audio_sound_positioning;★★☆☆;5.5;6.0;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_spectrum_visualizer;★★★☆;6.0;6.0;2025;2025;"IANN";@meisei4
audio;audio_stream_callback;★★★☆;6.0;6.0;2026;2026;"Dan Hoang";@dan-hoang
audio;audio_amp_envelope;★☆☆☆;6.0;6.0;2026;2026;"Arbinda Rizki Muhammad";@arbipink

View File

@ -212,12 +212,12 @@ static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int f
if (frame1 < 0) frame1 = 0;
// Get bone count (use minimum of all to be safe)
unsigned int boneCount = model->skeleton.boneCount;
int boneCount = model->skeleton.boneCount;
if (anim0->boneCount < boneCount) boneCount = anim0->boneCount;
if (anim1->boneCount < boneCount) boneCount = anim1->boneCount;
// Blend each bone
for (unsigned int boneIndex = 0; boneIndex < boneCount; boneIndex++)
for (int boneIndex = 0; boneIndex < boneCount; boneIndex++)
{
// Determine blend factor for this bone
float boneBlendFactor = blend;

View File

@ -114,7 +114,7 @@ int main(void)
if (IsKeyPressed(KEY_P)) animPause = !animPause;
if (!animPause && (animCount > 0)) // Animations could fail to load
if (!animPause)
{
// Start transition from anim0[] to anim1[]
if (IsKeyPressed(KEY_SPACE) && !animTransition)
@ -252,28 +252,25 @@ int main(void)
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize*2);
GuiLabel((Rectangle){ 0, GetScreenHeight() - 100.0f, (float)GetScreenWidth(), 40 }, "PRESS SPACE to START BLENDING");
GuiLabel((Rectangle){ 0, GetScreenHeight() - 100.0f, GetScreenWidth(), 40 }, "PRESS SPACE to START BLENDING");
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize);
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
if (animCount > 0)
{
// Draw playing timeline with keyframes for anim0[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
GetScreenHeight() - 60, 1, 20, BLUE);
// Draw playing timeline with keyframes for anim0[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
GetScreenHeight() - 60, 1, 20, BLUE);
// Draw playing timeline with keyframes for anim1[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
GetScreenHeight() - 30, 1, 20, BLUE);
}
// Draw playing timeline with keyframes for anim1[]
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
GetScreenHeight() - 30, 1, 20, BLUE);
//---------------------------------------------------------------------------------------------
EndDrawing();

View File

@ -103,7 +103,7 @@ int main(void)
if (collision.hit && (collision.distance < closestDistance))
{
closestDistance = collision.distance;
closestVoxelPosition = (Vector3){ (float)x, (float)y, (float)z };
closestVoxelPosition = (Vector3){ x, y, z };
voxelFound = true;
}
}

View File

@ -64,7 +64,7 @@ int main(void)
int boneSocketIndex[BONE_SOCKETS] = { -1, -1, -1 };
// Search bones for sockets
for (unsigned int i = 0; i < characterModel.skeleton.boneCount; i++)
for (int i = 0; i < characterModel.skeleton.boneCount; i++)
{
if (TextIsEqual(characterModel.skeleton.bones[i].name, "socket_hat"))
{

View File

@ -249,7 +249,7 @@ int main(void)
DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY);
// UI elements
if (GuiButton((Rectangle){ 10, screenHeight - 100.0f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
if (GuiButton((Rectangle){ 10, screenHeight - 1000.f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100.0f, 100, 60 }, "Clear Decals"))
{
@ -267,7 +267,6 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
UnloadModel(placementCube);
UnloadTexture(modelTexture);
// Unload decal models
@ -316,7 +315,7 @@ static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3])
static void FreeMeshBuilder(MeshBuilder *mb)
{
MemFree(mb->vertices);
if (mb->uvs != NULL) MemFree(mb->uvs);
if (mb->uvs) MemFree(mb->uvs);
*mb = (MeshBuilder){ 0 };
}
@ -328,7 +327,7 @@ static Mesh BuildMesh(MeshBuilder *mb)
outMesh.vertexCount = mb->vertexCount;
outMesh.triangleCount = mb->vertexCount/3;
outMesh.vertices = MemAlloc(outMesh.vertexCount*3*sizeof(float));
if (mb->uvs != NULL) outMesh.texcoords = MemAlloc(outMesh.vertexCount*2*sizeof(float));
if (mb->uvs) outMesh.texcoords = MemAlloc(outMesh.vertexCount*2*sizeof(float));
for (int i = 0; i < mb->vertexCount; i++)
{
@ -336,7 +335,7 @@ static Mesh BuildMesh(MeshBuilder *mb)
outMesh.vertices[3*i+1] = mb->vertices[i].y;
outMesh.vertices[3*i+2] = mb->vertices[i].z;
if (mb->uvs != NULL)
if (mb->uvs)
{
outMesh.texcoords[2*i+0] = mb->uvs[i].x;
outMesh.texcoords[2*i+1] = mb->uvs[i].y;

View File

@ -106,3 +106,4 @@ int main(void)
}

View File

@ -21,8 +21,6 @@
#include "raylib.h"
#include <math.h> // Required for: fmaxf(), fminf()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
@ -55,7 +53,6 @@ int main(void)
// Animation playing variables
unsigned int animIndex = 0; // Current animation playing
float animCurrentFrame = 0.0f; // Current animation frame (supporting interpolated frames)
float animSpeed = 1.0f; // How fast the animation plays
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -67,23 +64,10 @@ int main(void)
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
if (IsKeyPressed(KEY_RIGHT))
{
animIndex = (animIndex == animCount - 1)? 0 : animIndex + 1;
animCurrentFrame = 0.0f;
}
if (IsKeyPressed(KEY_LEFT))
{
animIndex = (animIndex == 0)? animCount - 1 : animIndex - 1;
animCurrentFrame = 0.0f;
}
if (IsKeyPressed(KEY_UP)) animSpeed = fminf(5.0f, animSpeed + 0.1f);
if (IsKeyPressed(KEY_DOWN)) animSpeed = fmaxf(0.0f, animSpeed - 0.1f);
animCurrentFrame += animSpeed;
UpdateModelAnimation(model, anims[animIndex], animCurrentFrame);
if (animCurrentFrame >= anims[animIndex].keyframeCount) animCurrentFrame = 0;
// Play animation when spacebar is held down
animCurrentFrame += 1.0f;
UpdateModelAnimation(model, anims[0], animCurrentFrame);
if (animCurrentFrame >= anims[0].keyframeCount) animCurrentFrame = 0;
//----------------------------------------------------------------------------------
// Draw
@ -101,9 +85,6 @@ int main(void)
EndMode3D();
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 10, 20, MAROON);
DrawText(TextFormat("Animation speed: %.2f", animSpeed), 10, 40, 20, MAROON);
DrawText("Use left and right arrow keys to change current animation", 10, screenHeight - 34, 10, BLACK);
DrawText("Use up and down arrow keys to change animation speed", 10, screenHeight - 20, 10, BLACK);
DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY);
EndDrawing();

View File

@ -119,7 +119,7 @@ static void DrawModelSkeleton(ModelSkeleton skeleton, ModelAnimPose pose, float
{
// Loop to (boneCount - 1) because the last one is a special "no bone" bone,
// needed to workaround buggy models without a -1, a cube is always drawn at the origin
for (unsigned int i = 0; i < skeleton.boneCount - 1; i++)
for (int i = 0; i < skeleton.boneCount - 1; i++)
{
// Display the frame-pose skeleton
DrawCube(pose[i].translation, scale*0.05f, scale*0.05f, scale*0.05f, color);

View File

@ -185,9 +185,6 @@ int main(void)
// Unload models data (GPU VRAM)
for (int i = 0; i < MAX_VOX_FILES; i++) UnloadModel(models[i]);
// Unload shader data
UnloadShader(shader);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -1,323 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - mesh uv painting
*
* Example demonstrates painting directly onto a mesh's texture: a ray is cast from the
* mouse into the scene, the hit triangle is found, and the hit point is converted into
* UV space using barycentric interpolation so a brush stroke can be drawn on the texture
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include <math.h> // Required for: fabsf(), floorf()
#include <stddef.h> // Required for: NULL
//--------------------------------------------------------------------------------------
// Global Definitions
//--------------------------------------------------------------------------------------
#define CANVAS_SIZE 512
#define PALETTE_COUNT 8
//--------------------------------------------------------------------------------------
// Types and Structures Definition
//--------------------------------------------------------------------------------------
typedef enum { TOOL_PAINT = 0, TOOL_PICKER } ToolMode;
typedef enum { SHAPE_SPHERE = 0, SHAPE_CUBE, SHAPE_CYLINDER, SHAPE_TORUS } ShapeType;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void ChangeShape(Model *model, BoundingBox *bbox, ShapeType *currentShape, ShapeType newShape, Texture2D canvasTexture);
static bool GetMeshHitUV(Ray ray, Model model, BoundingBox bbox, Vector2 *outUV);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh uv painting");
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 3.5f, 6.5f };
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
// CPU-side canvas plus the GPU texture it gets pushed to after every stroke
Image canvasImage = GenImageColor(CANVAS_SIZE, CANVAS_SIZE, RAYWHITE);
Texture2D canvasTexture = LoadTextureFromImage(canvasImage);
SetTextureFilter(canvasTexture, TEXTURE_FILTER_BILINEAR);
Model model = { 0 };
BoundingBox modelBBox = { 0 };
ShapeType currentShape = SHAPE_SPHERE;
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_SPHERE, canvasTexture);
ToolMode currentTool = TOOL_PAINT;
Color activeColor = RED;
int brushRadius = 12;
Vector2 lastHitUV = { 0 };
bool hasLastHit = false;
Color palette[PALETTE_COUNT] = { RED, ORANGE, GOLD, LIME, SKYBLUE, PURPLE, DARKGRAY, WHITE };
Rectangle uiPanelRec = { 10.0f, 10.0f, 230.0f, 490.0f };
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
Vector2 mousePos = GetMousePosition();
bool isMouseOverUI = CheckCollisionPointRec(mousePos, uiPanelRec);
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
if (!isMouseOverUI && IsMouseButtonDown(MOUSE_BUTTON_LEFT))
{
Ray ray = GetScreenToWorldRay(mousePos, camera);
Vector2 hitUV = { 0 };
if (GetMeshHitUV(ray, model, modelBBox, &hitUV))
{
int px = (int)(hitUV.x * CANVAS_SIZE);
int py = (int)(hitUV.y * CANVAS_SIZE);
if (currentTool == TOOL_PAINT)
{
// Stroke from the last hit to this one, guarding against jumps across a UV seam
if (hasLastHit && (fabsf(hitUV.x - lastHitUV.x) < 0.25f) && (fabsf(hitUV.y - lastHitUV.y) < 0.25f))
{
int lastPx = (int)(lastHitUV.x * CANVAS_SIZE);
int lastPy = (int)(lastHitUV.y * CANVAS_SIZE);
float dist = Vector2Distance((Vector2){ (float)lastPx, (float)lastPy }, (Vector2){ (float)px, (float)py });
int steps = (int)(dist / 2.0f) + 1;
for (int i = 0; i <= steps; i++)
{
float t = (float)i / (float)steps;
ImageDrawCircle(&canvasImage, (int)Lerp((float)lastPx, (float)px, t),
(int)Lerp((float)lastPy, (float)py, t), brushRadius, activeColor);
}
}
else ImageDrawCircle(&canvasImage, px, py, brushRadius, activeColor);
UpdateTexture(canvasTexture, canvasImage.data);
lastHitUV = hitUV;
hasLastHit = true;
}
else
{
activeColor = GetImageColor(canvasImage, px, py);
currentTool = TOOL_PAINT;
hasLastHit = false;
}
}
else hasLastHit = false;
}
else hasLastHit = false;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground((Color){ 30, 32, 40, 255 });
BeginMode3D(camera);
DrawModel(model, Vector3Zero(), 1.0f, WHITE);
DrawGrid(10, 1.0f);
EndMode3D();
// Side panel
DrawRectangleRec(uiPanelRec, Fade(BLACK, 0.8f));
DrawRectangleLinesEx(uiPanelRec, 2.0f, DARKGRAY);
DrawText("MESH UV PAINTER", 25, 22, 20, GOLD);
// Tool selection toggles
bool paintActive = (currentTool == TOOL_PAINT);
bool pickerActive = (currentTool == TOOL_PICKER);
if (GuiToggle((Rectangle){ 25, 55, 95, 32 }, "PAINT", &paintActive)) currentTool = TOOL_PAINT;
if (GuiToggle((Rectangle){ 125, 55, 95, 32 }, "PICKER", &pickerActive)) currentTool = TOOL_PICKER;
// Shape selection toggles
DrawText("Mesh Shape:", 25, 100, 10, LIGHTGRAY);
bool sphereActive = (currentShape == SHAPE_SPHERE);
bool cubeActive = (currentShape == SHAPE_CUBE);
bool cylinderActive = (currentShape == SHAPE_CYLINDER);
bool torusActive = (currentShape == SHAPE_TORUS);
if (GuiToggle((Rectangle){ 25, 120, 95, 28 }, "SPHERE", &sphereActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_SPHERE, canvasTexture);
if (GuiToggle((Rectangle){ 125, 120, 95, 28 }, "CUBE", &cubeActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_CUBE, canvasTexture);
if (GuiToggle((Rectangle){ 25, 153, 95, 28 }, "CYLINDER", &cylinderActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_CYLINDER, canvasTexture);
if (GuiToggle((Rectangle){ 125, 153, 95, 28 }, "TORUS", &torusActive))
ChangeShape(&model, &modelBBox, &currentShape, SHAPE_TORUS, canvasTexture);
// Color display
DrawText("Active Color:", 25, 195, 10, LIGHTGRAY);
DrawRectangle(125, 193, 95, 20, activeColor);
DrawRectangleLines(125, 193, 95, 20, WHITE);
// Color swatches
DrawText("Palette Swatches:", 25, 225, 10, LIGHTGRAY);
for (int i = 0; i < PALETTE_COUNT; i++)
{
Rectangle swatchRec = { 25.0f + (i%4)*48, 245.0f + (i/4)*45, 40.0f, 38.0f };
DrawRectangleRec(swatchRec, palette[i]);
DrawRectangleLinesEx(swatchRec, 1.0f, WHITE);
if (CheckCollisionPointRec(mousePos, swatchRec) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) activeColor = palette[i];
}
// Brush size buttons
DrawText(TextFormat("Brush Size: %dpx", brushRadius), 25, 345, 10, LIGHTGRAY);
if (GuiButton((Rectangle){ 25, 365, 95, 30 }, "SIZE -") && (brushRadius > 2)) brushRadius -= 2;
if (GuiButton((Rectangle){ 125, 365, 95, 30 }, "SIZE +") && (brushRadius < 64)) brushRadius += 2;
// Canvas action buttons
if (GuiButton((Rectangle){ 25, 410, 95, 30 }, "CLEAR"))
{
ImageClearBackground(&canvasImage, RAYWHITE);
UpdateTexture(canvasTexture, canvasImage.data);
}
if (GuiButton((Rectangle){ 125, 410, 95, 30 }, "FILL"))
{
ImageClearBackground(&canvasImage, activeColor);
UpdateTexture(canvasTexture, canvasImage.data);
}
DrawText("Left click: paint / pick color | Right drag: orbit camera", 260, screenHeight - 25, 10, RAYWHITE);
DrawFPS(screenWidth - 90, 15);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model);
UnloadImage(canvasImage);
UnloadTexture(canvasTexture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Unloads the current model and builds a new primitive shape in its place, sharing the
// same canvas texture, and recomputes the transformed bounding box used for ray testing
static void ChangeShape(Model *model, BoundingBox *bbox, ShapeType *currentShape, ShapeType newShape, Texture2D canvasTexture)
{
UnloadModel(*model);
Mesh mesh = { 0 };
switch (newShape)
{
case SHAPE_SPHERE: mesh = GenMeshSphere(1.5f, 32, 32); break;
case SHAPE_CUBE: mesh = GenMeshCube(2.2f, 2.2f, 2.2f); break;
case SHAPE_CYLINDER: mesh = GenMeshCylinder(1.2f, 2.5f, 24); break;
case SHAPE_TORUS: mesh = GenMeshTorus(0.6f, 1.6f, 24, 36); break;
default: mesh = GenMeshSphere(1.5f, 32, 32); break;
}
*model = LoadModelFromMesh(mesh);
// GenMeshCylinder builds upward from y = 0; shift it down to center on the origin
if (newShape == SHAPE_CYLINDER) model->transform = MatrixTranslate(0.0f, -1.25f, 0.0f);
model->materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = canvasTexture;
BoundingBox box = GetMeshBoundingBox(model->meshes[0]);
box.min = Vector3Transform(box.min, model->transform);
box.max = Vector3Transform(box.max, model->transform);
*bbox = box;
*currentShape = newShape;
}
// Raycasts against the model's mesh triangles and returns the UV coordinate of the
// closest hit, interpolated from the hit triangle's vertices with barycentric weights
static bool GetMeshHitUV(Ray ray, Model model, BoundingBox bbox, Vector2 *outUV)
{
if (!GetRayCollisionBox(ray, bbox).hit) return false; // Fast reject
Mesh mesh = model.meshes[0];
float closestDistance = 1e9f;
bool found = false;
Vector2 hitUV = { 0 };
for (int tri = 0; tri < mesh.triangleCount; tri++)
{
int i0, i1, i2;
if (mesh.indices != NULL)
{
i0 = mesh.indices[3*tri + 0];
i1 = mesh.indices[3*tri + 1];
i2 = mesh.indices[3*tri + 2];
}
else { i0 = 3*tri; i1 = 3*tri + 1; i2 = 3*tri + 2; }
Vector3 a = Vector3Transform((Vector3){ mesh.vertices[3*i0], mesh.vertices[3*i0 + 1], mesh.vertices[3*i0 + 2] }, model.transform);
Vector3 b = Vector3Transform((Vector3){ mesh.vertices[3*i1], mesh.vertices[3*i1 + 1], mesh.vertices[3*i1 + 2] }, model.transform);
Vector3 c = Vector3Transform((Vector3){ mesh.vertices[3*i2], mesh.vertices[3*i2 + 1], mesh.vertices[3*i2 + 2] }, model.transform);
RayCollision hit = GetRayCollisionTriangle(ray, a, b, c);
if (hit.hit && (hit.distance < closestDistance))
{
closestDistance = hit.distance;
found = true;
Vector2 uvA = { mesh.texcoords[2*i0], mesh.texcoords[2*i0 + 1] };
Vector2 uvB = { mesh.texcoords[2*i1], mesh.texcoords[2*i1 + 1] };
Vector2 uvC = { mesh.texcoords[2*i2], mesh.texcoords[2*i2 + 1] };
Vector3 w = Vector3Barycenter(hit.point, a, b, c);
hitUV.x = w.x*uvA.x + w.y*uvB.x + w.z*uvC.x;
hitUV.y = w.x*uvA.y + w.y*uvB.y + w.z*uvC.y;
// Wrap into [0, 1] in case of minor floating point drift at UV seams
hitUV.x -= floorf(hitUV.x);
hitUV.y -= floorf(hitUV.y);
}
}
if (found && (outUV != NULL)) *outUV = hitUV;
return found;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@ -1,504 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - procedural decals
*
* Example demonstrates projecting decals onto a 3D mesh surface by transforming the
* mesh's own triangles into the decal's local space and clipping them against a box,
* using only procedurally generated geometry and textures (no external resource files)
*
* NOTE: This is the same clip-space decal projection idea used by models_decals.c
* (in turn based on three.js' DecalGeometry), applied here to a generated mesh and
* generated textures instead of a loaded model, so the example is fully self-contained
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include "raymath.h"
#include <stddef.h> // Required for: NULL
#include <string.h> // Required for: memcpy()
#include <math.h> // Required for: fabsf(), fminf()
//--------------------------------------------------------------------------------------
// Global Definitions
//--------------------------------------------------------------------------------------
#define MAX_DECALS 256
//--------------------------------------------------------------------------------------
// Types and Structures Definition
//--------------------------------------------------------------------------------------
// Growable triangle-soup buffer used while building a clipped decal mesh
typedef struct MeshBuilder {
int vertexCount;
int vertexCapacity;
Vector3 *vertices;
Vector2 *uvs;
} MeshBuilder;
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 v0, Vector3 v1, Vector3 v2);
static void FreeMeshBuilder(MeshBuilder *mb);
static Mesh BuildMesh(MeshBuilder *mb);
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s);
static Mesh GenMeshDecal(Model model, Matrix projection, float decalSize, float decalOffset);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(screenWidth, screenHeight, "raylib [models] example - procedural decals");
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 2.5f, 5.0f };
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
// Target model: a procedurally generated knot with a checkerboard skin
Model model = LoadModelFromMesh(GenMeshTorus(0.8f, 1.8f, 32, 64));
Image checkerImage = GenImageChecked(512, 512, 32, 32, LIGHTGRAY, GRAY);
Texture2D modelTexture = LoadTextureFromImage(checkerImage);
UnloadImage(checkerImage);
SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR);
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture;
BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]);
camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f);
float modelSize = fminf(fminf(fabsf(modelBBox.max.x - modelBBox.min.x),
fabsf(modelBBox.max.y - modelBBox.min.y)), fabsf(modelBBox.max.z - modelBBox.min.z));
float decalSize = modelSize*0.35f;
float decalOffset = 0.01f;
// Translucent cube previewing where the next decal will land
Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize));
placementCube.materials[0].maps[0].color = LIME;
// Decal texture: a procedurally drawn target/bullseye, no image file needed
Image decalImage = GenImageColor(128, 128, BLANK);
ImageDrawCircle(&decalImage, 64, 64, 60, RED);
ImageDrawCircle(&decalImage, 64, 64, 45, WHITE);
ImageDrawCircle(&decalImage, 64, 64, 30, RED);
ImageDrawCircle(&decalImage, 64, 64, 15, YELLOW);
Texture2D decalTexture = LoadTextureFromImage(decalImage);
UnloadImage(decalImage);
SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR);
Material decalMaterial = LoadMaterialDefault();
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture;
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
bool showModel = true;
Model decals[MAX_DECALS] = { 0 };
int decalCount = 0;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Cast a ray from the mouse and keep the closest point it hits on the model
Ray ray = GetScreenToWorldRay(GetMousePosition(), camera);
RayCollision collision = { 0 };
if (GetRayCollisionBox(ray, modelBBox).hit && (decalCount < MAX_DECALS))
{
for (int m = 0; m < model.meshCount; m++)
{
RayCollision meshHit = GetRayCollisionMesh(ray, model.meshes[m], model.transform);
if (meshHit.hit && (!collision.hit || (meshHit.distance < collision.distance))) collision = meshHit;
}
}
// Project a new decal at the hit point, facing along the surface normal
if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS))
{
Vector3 lookTarget = Vector3Add(collision.point, collision.normal);
Matrix splat = MatrixLookAt(collision.point, lookTarget, (Vector3){ 0.0f, 1.0f, 0.0f });
splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*(float)GetRandomValue(-180, 180)));
Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset);
if (decalMesh.vertexCount > 0)
{
decals[decalCount] = LoadModelFromMesh(decalMesh);
decals[decalCount].materials[0].maps[0] = decalMaterial.maps[0];
decalCount++;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
if (showModel) DrawModel(model, Vector3Zero(), 1.0f, WHITE);
for (int i = 0; i < decalCount; i++) DrawModel(decals[i], Vector3Zero(), 1.0f, WHITE);
// Preview cube at the surface point currently under the mouse
if (collision.hit)
{
Vector3 lookTarget = Vector3Add(collision.point, collision.normal);
Matrix splat = MatrixLookAt(collision.point, lookTarget, (Vector3){ 0.0f, 1.0f, 0.0f });
placementCube.transform = MatrixInvert(splat);
DrawModel(placementCube, Vector3Zero(), 1.0f, Fade(WHITE, 0.5f));
}
DrawGrid(10, 1.0f);
EndMode3D();
// Vertex/triangle counts: base model vs total once decal geometry is added
int baseVertices = 0, baseTriangles = 0;
for (int i = 0; i < model.meshCount; i++)
{
baseVertices += model.meshes[i].vertexCount;
baseTriangles += model.meshes[i].triangleCount;
}
int totalVertices = baseVertices, totalTriangles = baseTriangles;
for (int i = 0; i < decalCount; i++)
{
totalVertices += decals[i].meshes[0].vertexCount;
totalTriangles += decals[i].meshes[0].triangleCount;
}
int statX = screenWidth - 280;
DrawText("Vertices", statX + 90, 10, 10, LIME);
DrawText("Triangles", statX + 180, 10, 10, LIME);
DrawText("Base Model", statX, 25, 10, LIME);
DrawText(TextFormat("%d", baseVertices), statX + 90, 25, 10, LIME);
DrawText(TextFormat("%d", baseTriangles), statX + 180, 25, 10, LIME);
DrawText("TOTAL", statX, 40, 10, LIME);
DrawText(TextFormat("%d", totalVertices), statX + 90, 40, 10, LIME);
DrawText(TextFormat("%d", totalTriangles), statX + 180, 40, 10, LIME);
if (GuiButton((Rectangle){ 10, screenHeight - 80.0f, 100, 40 }, showModel ? "Hide Model" : "Show Model"))
showModel = !showModel;
if (GuiButton((Rectangle){ 120, screenHeight - 80.0f, 100, 40 }, "Clear Decals"))
{
for (int i = 0; i < decalCount; i++) UnloadModel(decals[i]);
decalCount = 0;
}
DrawText("Left click: place decal | Right drag: orbit camera", 10, screenHeight - 25, 10, DARKGRAY);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
for (int i = 0; i < decalCount; i++) UnloadModel(decals[i]);
UnloadModel(placementCube);
UnloadTexture(decalTexture);
UnloadTexture(modelTexture);
UnloadModel(model);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Appends a triangle to a growable mesh builder buffer, growing it in fixed-size chunks
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 v0, Vector3 v1, Vector3 v2)
{
if (mb->vertexCapacity <= (mb->vertexCount + 3))
{
int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256;
Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3));
if (mb->vertexCapacity > 0)
{
memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3));
MemFree(mb->vertices);
}
mb->vertices = newVertices;
mb->vertexCapacity = newVertexCapacity;
}
int index = mb->vertexCount;
mb->vertexCount += 3;
mb->vertices[index + 0] = v0;
mb->vertices[index + 1] = v1;
mb->vertices[index + 2] = v2;
}
// Frees a mesh builder's backing buffers
static void FreeMeshBuilder(MeshBuilder *mb)
{
if (mb->vertices != NULL) MemFree(mb->vertices);
if (mb->uvs != NULL) MemFree(mb->uvs);
*mb = (MeshBuilder){ 0 };
}
// Converts a mesh builder's triangle soup into a standard uploaded raylib Mesh
static Mesh BuildMesh(MeshBuilder *mb)
{
Mesh outMesh = { 0 };
outMesh.vertexCount = mb->vertexCount;
outMesh.triangleCount = mb->vertexCount/3;
outMesh.vertices = (float *)MemAlloc(outMesh.vertexCount*3*sizeof(float));
if (mb->uvs != NULL) outMesh.texcoords = (float *)MemAlloc(outMesh.vertexCount*2*sizeof(float));
for (int i = 0; i < mb->vertexCount; i++)
{
outMesh.vertices[3*i + 0] = mb->vertices[i].x;
outMesh.vertices[3*i + 1] = mb->vertices[i].y;
outMesh.vertices[3*i + 2] = mb->vertices[i].z;
if (mb->uvs != NULL)
{
outMesh.texcoords[2*i + 0] = mb->uvs[i].x;
outMesh.texcoords[2*i + 1] = mb->uvs[i].y;
}
}
UploadMesh(&outMesh, false);
return outMesh;
}
// Clips the segment [v0, v1] against the plane p.x = s, returning the intersection point
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s)
{
float d0 = Vector3DotProduct(v0, p) - s;
float d1 = Vector3DotProduct(v1, p) - s;
float t = d0/(d0 - d1);
return Vector3Lerp(v0, v1, t);
}
// Builds a decal mesh: the model's triangles are transformed into the decal's local space
// (so the decal sits at the origin, facing +Z) and clipped against a decalSize-sided box,
// following the same clip-space projection idea used by engines' decal systems (and by
// three.js' DecalGeometry, which the technique is commonly traced back to). What's left
// after clipping becomes the decal's own small mesh, UV-mapped from its local coordinates
static Mesh GenMeshDecal(Model model, Matrix projection, float decalSize, float decalOffset)
{
Matrix invProj = MatrixInvert(projection);
MeshBuilder meshBuilders[2] = { 0 };
int mbIndex = 0;
// Gather triangles that land anywhere near the decal box; this is a loose, cheap
// pre-filter meant to skip most of the model, the precise clip happens below
for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++)
{
Mesh mesh = model.meshes[meshIndex];
for (int tri = 0; tri < mesh.triangleCount; tri++)
{
Vector3 vertices[3] = { 0 };
if (mesh.indices == NULL)
{
for (int v = 0; v < 3; v++)
{
vertices[v] = (Vector3){
mesh.vertices[3*3*tri + 3*v + 0],
mesh.vertices[3*3*tri + 3*v + 1],
mesh.vertices[3*3*tri + 3*v + 2]
};
}
}
else
{
for (int v = 0; v < 3; v++)
{
int idx = mesh.indices[3*tri + v];
vertices[v] = (Vector3){
mesh.vertices[3*idx + 0],
mesh.vertices[3*idx + 1],
mesh.vertices[3*idx + 2]
};
}
}
int insideCount = 0;
for (int i = 0; i < 3; i++)
{
Vector3 v = Vector3Transform(vertices[i], projection);
if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++;
vertices[i] = v;
}
if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices[0], vertices[1], vertices[2]);
}
}
// Clip the surviving triangles against each of the decal box's 6 faces in turn
Vector3 planes[6] = {
{ 1, 0, 0 }, { -1, 0, 0 },
{ 0, 1, 0 }, { 0, -1, 0 },
{ 0, 0, 1 }, { 0, 0, -1 }
};
for (int face = 0; face < 6; face++)
{
mbIndex = 1 - mbIndex;
MeshBuilder *inMesh = &meshBuilders[1 - mbIndex];
MeshBuilder *outMesh = &meshBuilders[mbIndex];
outMesh->vertexCount = 0;
float s = 0.5f*decalSize;
for (int i = 0; i < inMesh->vertexCount; i += 3)
{
Vector3 nV1, nV2, nV3, nV4;
float d1 = Vector3DotProduct(inMesh->vertices[i + 0], planes[face]) - s;
float d2 = Vector3DotProduct(inMesh->vertices[i + 1], planes[face]) - s;
float d3 = Vector3DotProduct(inMesh->vertices[i + 2], planes[face]) - s;
int v1Out = (d1 > 0);
int v2Out = (d2 > 0);
int v3Out = (d3 > 0);
int total = v1Out + v2Out + v3Out;
switch (total)
{
case 0:
// Whole triangle is inside this face, keep it as-is
AddTriangleToMeshBuilder(outMesh, inMesh->vertices[i], inMesh->vertices[i + 1], inMesh->vertices[i + 2]);
break;
case 1:
// One corner is outside; clip it off, turning the triangle into a quad
if (v1Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s);
}
if (v2Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 2];
nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV3, nV2, nV1);
AddTriangleToMeshBuilder(outMesh, nV2, nV3, nV4);
break;
}
if (v3Out)
{
nV1 = inMesh->vertices[i];
nV2 = inMesh->vertices[i + 1];
nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s);
nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s);
}
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
AddTriangleToMeshBuilder(outMesh, nV4, nV3, nV2);
break;
case 2:
// Two corners are outside; only the small corner near the surviving vertex remains
if (!v1Out)
{
nV1 = inMesh->vertices[i];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
}
if (!v2Out)
{
nV1 = inMesh->vertices[i + 1];
nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
}
if (!v3Out)
{
nV1 = inMesh->vertices[i + 2];
nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
}
break;
default:
// All 3 corners are outside this face, the triangle is fully clipped away
break;
}
}
}
MeshBuilder *finalMesh = &meshBuilders[mbIndex];
Mesh decalMesh = { 0 };
if (finalMesh->vertexCount > 0)
{
finalMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*finalMesh->vertexCount);
for (int i = 0; i < finalMesh->vertexCount; i++)
{
// Clipped coordinates run roughly (-decalSize/2 .. decalSize/2); remap to (0..1)
finalMesh->uvs[i].x = (finalMesh->vertices[i].x/decalSize + 0.5f);
finalMesh->uvs[i].y = (finalMesh->vertices[i].y/decalSize + 0.5f);
// Nudge slightly along the normal so the decal doesn't z-fight with the surface
finalMesh->vertices[i].z -= decalOffset;
finalMesh->vertices[i] = Vector3Transform(finalMesh->vertices[i], invProj);
}
decalMesh = BuildMesh(finalMesh);
}
FreeMeshBuilder(&meshBuilders[0]);
FreeMeshBuilder(&meshBuilders[1]);
return decalMesh;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@ -180,8 +180,8 @@ int main(void)
//--------------------------------------------------------------------------------------
UnloadShader(skybox.materials[0].shader);
UnloadTexture(skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture);
UnloadModel(skybox); // Unload skybox model
UnloadShader(shdrCubemap);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -1,153 +0,0 @@
/*******************************************************************************************
*
* raylib [others] example - scissor shapes
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 6.0
*
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2026 David Buzatto (@davidbuzatto)
*
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h"
#include <math.h> // Required for: sinf()
// BeginScissorMode() only clips to an axis-aligned rectangle, since it maps
// directly to glScissor. Clipping to an arbitrary shape (the same idea as
// Graphics2D.setClip(Shape) in Java2D) needs the stencil buffer instead:
// the clip shape is rasterized into the stencil buffer first, then further
// draws are only let through where the stencil was written.
//
// rlgl has no stencil wrapper (see raysan5/raylib discussion #2964), so this
// example calls the handful of OpenGL 1.0 stencil functions directly - they
// don't need glad/extension loading, same as glScissor doesn't.
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#else
#if !defined(APIENTRY)
#if defined(_WIN32)
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
#endif
#if !defined(WINGDIAPI) && defined(_WIN32)
#define WINGDIAPI __declspec(dllimport)
#endif
#include <GL/gl.h>
#endif
// mask is a callback instead of a fixed shape, so the clip region can be any
// combination of Draw* calls (circle, polygon, text, several shapes together)
typedef void (*ScissorMaskDrawFunc)(void *userData);
static void BeginScissorModeShape(ScissorMaskDrawFunc mask, void *userData)
{
rlDrawRenderBatchActive(); // Flush before touching stencil state
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilMask(0xFF);
// Pass 1: rasterize the mask into the stencil buffer only, no color write
rlColorMask(false, false, false, false);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
mask(userData);
rlDrawRenderBatchActive(); // Flush the mask draw
// Pass 2: subsequent draws only survive where the stencil was written
rlColorMask(true, true, true, true);
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
static void EndScissorModeShape(void)
{
rlDrawRenderBatchActive();
glDisable(GL_STENCIL_TEST);
}
// Two example mask shapes, drawn in WHITE (the color is irrelevant here,
// only the stencil write from pass 1 matters)
typedef struct { Vector2 center; float radius; } CircleMask;
static void DrawCircleMask(void *userData)
{
CircleMask *m = (CircleMask *)userData;
DrawCircleV(m->center, m->radius, WHITE);
}
typedef struct { Vector2 center; float radius; int sides; } PolyMask;
static void DrawPolyMask(void *userData)
{
PolyMask *m = (PolyMask *)userData;
DrawPoly(m->center, m->sides, m->radius, 0.0f, WHITE);
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [others] example - scissor shapes");
Vector2 circleCenter = { screenWidth/2.0f - 120, screenHeight/2.0f };
Vector2 hexCenter = { screenWidth/2.0f + 120, screenHeight/2.0f };
float maskRadius = 100.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
circleCenter.y = screenHeight/2.0f + sinf((float)GetTime())*40.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Circle-shaped clip: the full-screen rectangle only shows inside the circle
CircleMask circleMask = { circleCenter, maskRadius };
BeginScissorModeShape(DrawCircleMask, &circleMask);
DrawRectangle(0, 0, screenWidth, screenHeight, BLUE);
EndScissorModeShape();
// Hexagon-shaped clip: same mechanism, a different mask shape
PolyMask hexMask = { hexCenter, maskRadius, 6 };
BeginScissorModeShape(DrawPolyMask, &hexMask);
DrawRectangle(0, 0, screenWidth, screenHeight, ORANGE);
EndScissorModeShape();
DrawText("BeginScissorMode() only clips to a rectangle (glScissor)", 10, 10, 10, DARKGRAY);
DrawText("This clips to arbitrary shapes instead, using the stencil buffer", 10, 25, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -24,7 +24,7 @@
*
* APPLE COMPILATION:
* gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa -framework QuartzCore
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa
* -Wno-deprecated-declarations -std=c99 -DGRAPHICS_API_OPENGL_33
*
*
@ -149,7 +149,7 @@ int main(void)
GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "raylib [others] example - rlgl standalone", NULL, NULL);
if (window == NULL)
if (!window)
{
glfwTerminate();
return 2;

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +0,0 @@
#version 100
precision mediump float;
// Input values from vertex shader
varying vec3 fragPosition;
varying vec3 fragNormal;
varying vec2 fragTexCoord;
// Input uniform values
uniform sampler2D texture0;
uniform vec3 viewPos;
uniform vec3 lightPositions[8];
uniform vec3 lightColors[8];
void main()
{
vec4 texColor = texture2D(texture0, fragTexCoord);
vec3 norm = normalize(fragNormal);
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 ambient = 0.05*texColor.rgb;
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
for (int i = 0; i < 8; i++)
{
vec3 lightDir = normalize(lightPositions[i] - fragPosition);
float dist = length(lightPositions[i] - fragPosition);
float attenuation = 1.0/(1.0 + 0.8*dist + 0.4*dist*dist);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
totalDiffuse += diff*lightColors[i]*attenuation*1.2;
// Blinn-Phong specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
totalSpecular += spec*lightColors[i]*attenuation*0.8;
}
vec3 result = ambient + (totalDiffuse*texColor.rgb) + totalSpecular;
gl_FragColor = vec4(result, texColor.a);
}

View File

@ -1,23 +0,0 @@
#version 100
// Input vertex attributes
attribute vec3 vertexPosition;
attribute vec2 vertexTexCoord;
attribute vec3 vertexNormal;
// Output values to fragment shader
varying vec3 fragPosition;
varying vec3 fragNormal;
varying vec2 fragTexCoord;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
void main()
{
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragNormal = normalize(vec3(matModel*vec4(vertexNormal, 0.0)));
fragTexCoord = vertexTexCoord;
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -1,33 +0,0 @@
#version 100
precision mediump float;
varying vec2 fragTexCoord;
uniform sampler2D texture0;
void main()
{
vec4 color = texture2D(texture0, fragTexCoord);
// High-pass threshold blur: only pixels brighter than 0.75 in any channel contribute
vec4 bloom = vec4(0.0);
vec2 texel = vec2(1.0/1280.0, 1.0/720.0)*2.5;
for (int x = -2; x <= 2; x++)
{
for (int y = -2; y <= 2; y++)
{
vec4 smp = texture2D(texture0, fragTexCoord + vec2(float(x), float(y))*texel);
float brightness = max(smp.r, max(smp.g, smp.b));
if (brightness > 0.75) bloom += smp;
}
}
bloom /= 25.0;
// Combine original with the bloom glow, then Reinhard tone-map back to [0, 1]
vec3 hdr = color.rgb + bloom.rgb*1.2;
vec3 ldr = hdr/(hdr + vec3(1.0));
gl_FragColor = vec4(ldr, color.a);
}

View File

@ -1,44 +0,0 @@
#version 330
// Input values from vertex shader
in vec3 fragPosition;
in vec3 fragNormal;
in vec2 fragTexCoord;
out vec4 finalColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec3 viewPos;
uniform vec3 lightPositions[8];
uniform vec3 lightColors[8];
void main()
{
vec4 texColor = texture(texture0, fragTexCoord);
vec3 norm = normalize(fragNormal);
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 ambient = 0.05*texColor.rgb;
vec3 totalDiffuse = vec3(0.0);
vec3 totalSpecular = vec3(0.0);
for (int i = 0; i < 8; i++)
{
vec3 lightDir = normalize(lightPositions[i] - fragPosition);
float dist = length(lightPositions[i] - fragPosition);
float attenuation = 1.0/(1.0 + 0.8*dist + 0.4*dist*dist);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
totalDiffuse += diff*lightColors[i]*attenuation*1.2;
// Blinn-Phong specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
totalSpecular += spec*lightColors[i]*attenuation*0.8;
}
vec3 result = ambient + (totalDiffuse*texColor.rgb) + totalSpecular;
finalColor = vec4(result, texColor.a);
}

View File

@ -1,23 +0,0 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
// Output values to fragment shader
out vec3 fragPosition;
out vec3 fragNormal;
out vec2 fragTexCoord;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
void main()
{
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
fragNormal = normalize(vec3(matModel*vec4(vertexNormal, 0.0)));
fragTexCoord = vertexTexCoord;
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -1,32 +0,0 @@
#version 330
in vec2 fragTexCoord;
out vec4 finalColor;
uniform sampler2D texture0;
void main()
{
vec4 color = texture(texture0, fragTexCoord);
// High-pass threshold blur: only pixels brighter than 0.75 in any channel contribute
vec4 bloom = vec4(0.0);
vec2 texel = vec2(1.0/1280.0, 1.0/720.0)*2.5;
for (int x = -2; x <= 2; x++)
{
for (int y = -2; y <= 2; y++)
{
vec4 smp = texture(texture0, fragTexCoord + vec2(float(x), float(y))*texel);
float brightness = max(smp.r, max(smp.g, smp.b));
if (brightness > 0.75) bloom += smp;
}
}
bloom /= 25.0;
// Combine original with the bloom glow, then Reinhard tone-map back to [0, 1]
vec3 hdr = color.rgb + bloom.rgb*1.2;
vec3 ldr = hdr/(hdr + vec3(1.0));
finalColor = vec4(ldr, color.a);
}

View File

@ -9,8 +9,6 @@
*
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Gleb A (@ggrizzly) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,

View File

@ -168,7 +168,6 @@ int main(void)
UnloadShader(shader); // Unload shader
UnloadTexture(texture); // Unload texture
UnloadTexture(light); // Unload texture
UnloadRenderTexture(lightmap); // Unload lightmap render texture
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -1,185 +0,0 @@
/*******************************************************************************************
*
* raylib [shaders] example - lights bloom
*
* Example demonstrates forward multi-point lighting (8 point lights, attenuation and
* Blinn-Phong specular) combined with a threshold-based bloom pass and Reinhard tone
* mapping, applied as a full-screen post-process pass
*
* Example complexity rating: [★★★☆] 3/4
*
* Example uses resources/shaders/glsl100 and resources/shaders/glsl330, shared with the
* rest of the shaders examples
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include "rlgl.h"
#include <math.h> // Required for: sinf(), cosf()
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//--------------------------------------------------------------------------------------
// Global Definitions
//--------------------------------------------------------------------------------------
#define MAX_LIGHTS 8
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT);
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - lights bloom");
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 5.0f, 9.0f };
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
// Forward multi-light shader and bloom post-process shader, both loaded from the
// resources folder shared with the rest of the shaders examples. If the GLSL version
// guessed from the PLATFORM_DESKTOP build flag turns out to be wrong for whatever
// raylib was built against, linking fails and silently falls back to the default
// shader - so this retries once with the other version, and either way the result
// is checked explicitly and reported on screen rather than staying silently wrong
Shader lightShader = LoadShader(TextFormat("resources/shaders/glsl%i/lights_bloom.vs", GLSL_VERSION),
TextFormat("resources/shaders/glsl%i/lights_bloom.fs", GLSL_VERSION));
Shader bloomShader = LoadShader(0, TextFormat("resources/shaders/glsl%i/lights_bloom_post.fs", GLSL_VERSION));
// Load models from generated cube mesh and plane
// NOTE: Meshes are automatically unloaded on UnloadModel()
Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f));
Model floor = LoadModelFromMesh(GenMeshPlane(14.0f, 14.0f, 1, 1));
cube.materials[0].shader = lightShader;
floor.materials[0].shader = lightShader;
int lightPosLoc = GetShaderLocation(lightShader, "lightPositions");
int lightColLoc = GetShaderLocation(lightShader, "lightColors");
int viewPosLoc = GetShaderLocation(lightShader, "viewPos");
Vector3 lightPositions[MAX_LIGHTS] = { 0 };
Vector3 lightColors[MAX_LIGHTS] = {
{ 1.0f, 0.2f, 0.2f }, // Red
{ 0.2f, 1.0f, 0.3f }, // Green
{ 0.2f, 0.5f, 1.0f }, // Blue
{ 1.0f, 0.8f, 0.1f }, // Yellow
{ 1.0f, 0.1f, 0.8f }, // Magenta
{ 0.1f, 1.0f, 1.0f }, // Cyan
{ 1.0f, 0.4f, 0.1f }, // Orange
{ 0.7f, 0.2f, 1.0f }, // Purple
};
SetShaderValueV(lightShader, lightColLoc, lightColors, SHADER_UNIFORM_VEC3, MAX_LIGHTS);
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
float time = (float)GetTime();
// Orbital path for each point light, its own radius/height offset by index
for (int i = 0; i < MAX_LIGHTS; i++)
{
float angle = (i/(float)MAX_LIGHTS)*2.0f*PI + time*0.6f;
float radius = 4.2f + sinf(time*1.2f + i)*0.4f;
float height = 1.0f + sinf(time*1.8f + i)*0.6f;
lightPositions[i] = (Vector3){ sinf(angle)*radius, height, cosf(angle)*radius };
}
SetShaderValueV(lightShader, lightPosLoc, lightPositions, SHADER_UNIFORM_VEC3, MAX_LIGHTS);
SetShaderValue(lightShader, viewPosLoc, &camera.position, SHADER_UNIFORM_VEC3);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Render the lit scene to an offscreen texture
BeginTextureMode(target);
ClearBackground((Color){ 12, 12, 18, 255 });
BeginMode3D(camera);
DrawModel(cube, (Vector3){ 0.0f, 1.0f, 0.0f }, 1.0f, GRAY);
DrawModel(floor, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, DARKGRAY);
DrawGrid(10, 1.0f);
// Glowing bulbs mark each light's position
for (int i = 0; i < MAX_LIGHTS; i++)
{
Color bulbColor = (Color){
(unsigned char)(lightColors[i].x*255),
(unsigned char)(lightColors[i].y*255),
(unsigned char)(lightColors[i].z*255),
255 };
DrawSphere(lightPositions[i], 0.15f, bulbColor);
}
EndMode3D();
EndTextureMode();
// Present the offscreen texture through the bloom + tone mapping shader
BeginDrawing();
ClearBackground(BLACK);
Rectangle srcRec = { 0, 0, (float)target.texture.width, (float)-target.texture.height };
BeginShaderMode(bloomShader);
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
DrawTextureRec(target.texture, srcRec, (Vector2){ 0, 0 }, WHITE);
EndShaderMode();
DrawText("BALANCED MULTI-LIGHT + REINHARD TONE MAPPED BLOOM", 20, 20, 20, GREEN);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(cube);
UnloadModel(floor);
UnloadShader(lightShader);
UnloadShader(bloomShader);
UnloadRenderTexture(target);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

View File

@ -139,9 +139,6 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
RL_FREE(transforms); // Free transforms
UnloadMaterial(matInstances); // Also unloads the instancing shader
UnloadMaterial(matDefault); // Unload default material
UnloadMesh(cube); // Unload cube mesh
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -91,8 +91,6 @@ int main(void)
Image whiteImage = GenImageColor(GOL_WIDTH, GOL_WIDTH, WHITE);
Texture whiteTex = LoadTextureFromImage(whiteImage);
UnloadImage(whiteImage);
SetTargetFPS(0); // Set our game to run with an uncapped framerate
//--------------------------------------------------------------------------------------
// Main game loop

View File

@ -68,7 +68,7 @@ int main(void)
SetShaderValue(shadowShader, lightDirLoc, &lightDir, SHADER_UNIFORM_VEC3);
SetShaderValue(shadowShader, lightColLoc, &lightColorNormalized, SHADER_UNIFORM_VEC4);
int ambientLoc = GetShaderLocation(shadowShader, "ambient");
float ambient[4] = { 0.1f, 0.1f, 0.1f, 1.0f };
float ambient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
SetShaderValue(shadowShader, ambientLoc, ambient, SHADER_UNIFORM_VEC4);
int lightVPLoc = GetShaderLocation(shadowShader, "lightVP");
int shadowMapLoc = GetShaderLocation(shadowShader, "shadowMap");
@ -81,7 +81,7 @@ int main(void)
for (int i = 0; i < robot.materialCount; i++) robot.materials[i].shader = shadowShader;
int animCount = 0;
ModelAnimation* anims = LoadModelAnimations("resources/models/robot.glb", &animCount);
ModelAnimation *anims = LoadModelAnimations("resources/models/robot.glb", &animCount);
RenderTexture2D shadowMap = LoadShadowmapRenderTexture(SHADOWMAP_RESOLUTION, SHADOWMAP_RESOLUTION);
@ -111,11 +111,9 @@ int main(void)
//----------------------------------------------------------------------------------
float deltaTime = GetFrameTime();
UpdateCamera(&camera, CAMERA_ORBITAL);
// send the updated camera position to the shader so that it can calculate the correct lighting for the scene
Vector3 cameraPos = camera.position;
SetShaderValue(shadowShader, shadowShader.locs[SHADER_LOC_VECTOR_VIEW], &cameraPos, SHADER_UNIFORM_VEC3);
UpdateCamera(&camera, CAMERA_ORBITAL);
frameCounter++;
frameCounter %= (anims[0].keyframeCount);
@ -162,7 +160,6 @@ int main(void)
EndMode3D();
EndTextureMode();
lightViewProj = MatrixMultiply(lightView, lightProj);
// PASS 02: Draw the scene into main framebuffer, using the generated shadowmap
@ -180,9 +177,6 @@ int main(void)
DrawScene(cube, robot); // Draw the same exact things as we drew in the shadowmap!
EndMode3D();
rlActiveTextureSlot(textureActiveSlot);
rlDisableTexture();
DrawText("Use the arrow keys to rotate the light!", 10, 10, 30, RED);
DrawText("Shadows in raylib using the shadowmapping algorithm!", screenWidth - 280, screenHeight - 20, 10, GRAY);

File diff suppressed because it is too large Load Diff

View File

@ -1,164 +0,0 @@
/*******************************************************************************************
*
* raylib [shapes] example - drag puzzle
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by Gabriel Piangers (@gabriel-piangers) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2026 Gabriel Piangers (@gabriel-piangers)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct {
Vector2 center;
float radius;
} Circle;
typedef struct {
Vector2 v1;
Vector2 v2;
Vector2 v3;
} Triangle;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - drag puzzle");
// Rectangle
Rectangle rec = { screenWidth/2 - 250, screenHeight/2 + 50, 100.0f, 100.0f };
Rectangle recArea = { screenWidth/2 - 60, screenHeight/2 - 110, 110.0f, 110.0f };
bool recPickedUp = false;
// Circle
Circle circ = { screenWidth/2, screenHeight/2 + 100, 50.0f };
Circle circArea = { screenWidth/2 - 195, screenHeight/2 - 55, 55.0f };
bool circPickedUp = false;
// Triangle
Triangle tri = { { 600, 282 }, { 550, 369 }, { 650, 369 } };
Triangle triArea = { { 600, 115 }, { 540, 222 }, { 660, 222 } };
bool triPickedUp = false;
Vector2 mouseOffset = { 0.0f, 0.0f }; // Stores the offset of the mouse relative to the object's pivot point
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
Vector2 mousePosition = GetMousePosition();
bool recPlaced = false;
bool circPlaced = false;
bool triPlaced = false;
// Detect object pickup input
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, rec))
{
recPickedUp = true;
mouseOffset = (Vector2) { rec.x - mousePosition.x, rec.y - mousePosition.y };
}
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointCircle(mousePosition, circ.center, circ.radius))
{
circPickedUp = true;
mouseOffset = (Vector2) { circ.center.x - mousePosition.x, circ.center.y - mousePosition.y };
}
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointTriangle(mousePosition, tri.v1, tri.v2, tri.v3))
{
triPickedUp = true;
mouseOffset = (Vector2) { tri.v1.x - mousePosition.x, tri.v1.y - mousePosition.y }; // Uses v1 as the pivot point
}
// Detect object drop input
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && recPickedUp) recPickedUp = false;
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && circPickedUp) circPickedUp = false;
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && triPickedUp) triPickedUp = false;
// Rectangle update
if (recPickedUp)
{
rec.x = mousePosition.x + mouseOffset.x;
rec.y = mousePosition.y + mouseOffset.y;
}
Rectangle RecCol = GetCollisionRec(recArea, rec);
if (RecCol.width == rec.width && RecCol.height == rec.height) recPlaced = true;
// Circle update
if (circPickedUp)
{
circ.center.x = mousePosition.x + mouseOffset.x;
circ.center.y = mousePosition.y + mouseOffset.y;
}
if (Vector2Distance(circ.center, circArea.center) < circArea.radius - circ.radius) circPlaced = true;
// Triangle update
if (triPickedUp)
{
Vector2 v2Offset = { tri.v2.x - tri.v1.x, tri.v2.y - tri.v1.y };
Vector2 v3Offset = { tri.v3.x - tri.v1.x, tri.v3.y - tri.v1.y };
tri.v1 = (Vector2) { mousePosition.x + mouseOffset.x, mousePosition.y + mouseOffset.y };
tri.v2 = (Vector2) { tri.v1.x + v2Offset.x, tri.v1.y + v2Offset.y };
tri.v3 = (Vector2) { tri.v1.x + v3Offset.x, tri.v1.y + v3Offset.y };
}
if (
CheckCollisionPointTriangle(tri.v1, triArea.v1, triArea.v2, triArea.v3) &&
CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3) &&
CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3)
) triPlaced = true;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectangleLinesEx(recArea, 2.0f, recPlaced ? GREEN : RED);
DrawCircleLinesEx(circArea.center, circArea.radius, 2.0f, circPlaced ? GREEN : RED);
DrawTriangleLinesEx(triArea.v1, triArea.v2, triArea.v3, 2.0f, triPlaced ? GREEN : RED);
// Draws objects that are not picked up first
if (!triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
if (!circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
if (!recPickedUp) DrawRectangleRec(rec, ORANGE);
// Draws the object that is being dragged on top of others
if (triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
if (circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
if (recPickedUp) DrawRectangleRec(rec, ORANGE);
DrawText("Use mouse to drag and drop the objects into the right spot!", 10, 10, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -59,7 +59,7 @@ int main(void)
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ellipse collision");
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses");
SetTargetFPS(60);
Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };

View File

@ -56,7 +56,7 @@ int main(void)
Vector2 mousePos = { 0 };
Vector2 prevMousePos = { 0 };
Vector2 scaleVector = { 1.0f, -1.0f };
Vector2 offset = { GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
Camera2D camera = { 0 };
camera.target = (Vector2){ 0 };

View File

@ -4,9 +4,9 @@
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 5.6, last time updated with raylib 6.0
* Example originally created with raylib 5.6
*
* Example contributed by Balamurugan R (@Bala050814) and reviewed by Ramon Santamaria (@raysan5)
* Example contributed by Balamurugan R (@Bala050814]) 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

View File

@ -1,407 +0,0 @@
/*******************************************************************************************
*
* raylib [shapes] example - outlines testbed
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 6.1, last time updated with raylib 6.1
*
* Example contributed by Matthew Roush (@MatthewRoush) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2026 Matthew Roush (@MatthewRoush)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
#include <stdbool.h>
#define COLOR_FILLED DARKBLUE
#define COLOR_OUTLINE YELLOW
#define SHAPE_SPACING 14.0f
#define SHAPE_SIZE 46.0f
#define BOX_SPACING 10.0f
#define MOUSE_CAMERA_ZOOM_SPEED 0.3f
#define KEYBOARD_CAMERA_MOVE_SPEED 10.0f
#define KEYBOARD_CAMERA_ZOOM_SPEED 0.1f
#define CAMERA_ZOOM_MIN 0.1f
#define CAMERA_ZOOM_MAX 1000.0f
// The shapes are ordered according to their order in this enum, left to right
enum {
ORDER_RECTANGLE = 0,
ORDER_RECTANGLE_ROUNDED,
ORDER_CIRCLE,
ORDER_ELLIPSE,
ORDER_CIRCLE_SECTOR,
ORDER_RING,
ORDER_TRIANGLE,
ORDER_POLYGON,
COUNT_SHAPES
};
// The line style groups are ordered according to their order in this enum, top to bottom
enum {
ORDER_LINES = 0,
ORDER_LINES_EX_WORLD,
ORDER_LINES_EX_SCREEN,
};
#define BOX_WIDTH (SHAPE_SIZE*COUNT_SHAPES + SHAPE_SPACING*(COUNT_SHAPES - 1) + BOX_SPACING*2.0f)
#define BOX_HEIGHT (SHAPE_SIZE + BOX_SPACING*2.0f)
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - outlines testbed");
Camera2D camera = { .zoom = 1 };
// User configurable options while running the program.
float lineOpacity = 130;
float lineThickness = 4.0f;
float rectangleRoundness = 0.4f;
float rectangleSegments = 9;
float ellipseRadiusY = 0.5f;
float circleStartAngle = 20.0f;
float circleEndAngle = 270.0f;
float circleSegments = 36;
float ringInnerRadiusScale = 0.3f;
float polygonSides = 6;
bool disableMouseControl = false;
const Rectangle optionsBackground = { 510, 0, 290, 450 };
const Vector2 zoomPoint = {((float)screenWidth - optionsBackground.width)/2.0f, (float)screenHeight/2.0f};
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(WHITE));
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
const Vector2 mousePosScreen = GetMousePosition();
const Vector2 mouseWheelVec = GetMouseWheelMoveV();
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosScreen, optionsBackground)) disableMouseControl = true;
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) disableMouseControl = false;
if (!disableMouseControl) {
if (mouseWheelVec.y != 0.0f) {
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom *= exp2f(MOUSE_CAMERA_ZOOM_SPEED*mouseWheelVec.y); // Constant zoom rate
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
const Vector2 mouseDelta = GetMouseDelta();
camera.target.x -= mouseDelta.x/camera.zoom;
camera.target.y -= mouseDelta.y/camera.zoom;
const int mouseMaxX = (int)optionsBackground.x;
const int mouseMaxY = screenHeight;
int newX = (int)mousePosScreen.x;
int newY = (int)mousePosScreen.y;
// In C, the '%' operator computes the remainder, we want the modulus
newX = (newX%mouseMaxX + mouseMaxX)%mouseMaxX;
newY = (newY%mouseMaxY + mouseMaxY)%mouseMaxY;
if ((newX != (int)mousePosScreen.x) || (newY != (int)mousePosScreen.y)) SetMousePosition(newX, newY);
}
}
if (IsKeyDown(KEY_A)) camera.target.x -= KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_D)) camera.target.x += KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_W)) camera.target.y -= KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_S)) camera.target.y += KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
if (IsKeyDown(KEY_UP))
{
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom *= exp2f(KEYBOARD_CAMERA_ZOOM_SPEED);
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsKeyDown(KEY_DOWN))
{
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom *= exp2f(-KEYBOARD_CAMERA_ZOOM_SPEED);
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsKeyPressed(KEY_Z))
{
const Vector2 zoomPoint = {((float)screenWidth - optionsBackground.width)/2.0f, (float)screenHeight/2.0f};
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.zoom = 1.0f;
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
}
if (IsKeyPressed(KEY_C)) camera.target = (Vector2){ 0 };
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground((Color){ 50, 50, 55, 255 });
Color colorOutline = COLOR_OUTLINE;
colorOutline.a = (unsigned char)lineOpacity;
BeginMode2D(camera);
const float shapeOffset = BOX_SPACING*2.0f;
const float shapePaddingX = SHAPE_SIZE + SHAPE_SPACING;
const float shapePaddingY = SHAPE_SIZE + SHAPE_SPACING + BOX_SPACING*2.0f;
const float radiusX = SHAPE_SIZE/2.0f;
const float radiusY = radiusX*ellipseRadiusY;
const float ringOuterRadius = SHAPE_SIZE/2.0f;
const float ringInnerRadius = ringOuterRadius*ringInnerRadiusScale;
const Vector2 triangleVertex0Offset = { 0.0f, SHAPE_SIZE*0.8f };
const Vector2 triangleVertex1Offset = { SHAPE_SIZE*0.6f, SHAPE_SIZE };
const Vector2 triangleVertex2Offset = { SHAPE_SIZE, 0.0f };
// ----------------------------------------
// Draw*Lines()
float posY = shapeOffset + shapePaddingY*ORDER_LINES;
// Rectangle
float posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
DrawRectangleLines(posX, posY, SHAPE_SIZE, SHAPE_SIZE, colorOutline);
// Rectangle Rounded
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
DrawRectangleRoundedLines((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, colorOutline);
// Circle
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
DrawCircleLinesV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, colorOutline);
// Ellipse
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
DrawEllipseLinesV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, colorOutline);
// Circle Sector
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawCircleSectorLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, colorOutline);
// Ring
posX = shapeOffset + shapePaddingX*ORDER_RING;
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawRingLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, colorOutline);
// Triangle
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
COLOR_FILLED);
DrawTriangleLines((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
colorOutline);
// Polygon
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
DrawPolyLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, colorOutline);
// Group the shapes
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*Lines()");
// ----------------------------------------
// ----------------------------------------
// Draw*LinesEx() with world space pixel thickness
posY = shapeOffset + shapePaddingY*ORDER_LINES_EX_WORLD;
// Rectangle
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
DrawRectangleLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, lineThickness, colorOutline);
// Rectangle Rounded
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
DrawRectangleRoundedLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, lineThickness, colorOutline);
// Circle
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
DrawCircleLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, lineThickness, colorOutline);
// Ellipse
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
DrawEllipseLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, lineThickness, colorOutline);
// Circle Sector
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawCircleSectorLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, lineThickness, colorOutline);
// Ring
posX = shapeOffset + shapePaddingX*ORDER_RING;
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawRingLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, lineThickness, colorOutline);
// Triangle
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
COLOR_FILLED);
DrawTriangleLinesEx((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
lineThickness, colorOutline);
// Polygon
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
DrawPolyLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, lineThickness, colorOutline);
// Group the shapes
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*LinesEx() with *world space* pixel thickness");
// ----------------------------------------
// ----------------------------------------
// Draw*LinesEx() with screen space pixel thickness
posY = shapeOffset + shapePaddingY*ORDER_LINES_EX_SCREEN;
float constantThickness = lineThickness/camera.zoom;
// Rectangle
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
DrawRectangleLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, constantThickness, colorOutline);
// Rectangle Rounded
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
DrawRectangleRoundedLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, constantThickness, colorOutline);
// Circle
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
DrawCircleLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, constantThickness, colorOutline);
// Ellipse
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
DrawEllipseLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, constantThickness, colorOutline);
// Circle Sector
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawCircleSectorLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, constantThickness, colorOutline);
// Ring
posX = shapeOffset + shapePaddingX*ORDER_RING;
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
DrawRingLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, constantThickness, colorOutline);
// Triangle
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
COLOR_FILLED);
DrawTriangleLinesEx((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
constantThickness, colorOutline);
// Polygon
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
DrawPolyLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, constantThickness, colorOutline);
// Group the shapes
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*LinesEx() with *screen space* pixel thickness");
// ----------------------------------------
EndMode2D();
DrawRectangleRec(optionsBackground, Fade(DARKGRAY, 0.75f));
DrawRectangleRec((Rectangle){ optionsBackground.x, 360, optionsBackground.width, 90 }, Fade(BLACK, 0.4f));
DrawLineEx((Vector2){ optionsBackground.x, 360 }, (Vector2){ optionsBackground.x + optionsBackground.width, 360 }, 1.0f, BLACK);
DrawText("Move with the mouse or WASD keys", (int)optionsBackground.x + 10, 370, 10, ORANGE);
DrawText("Zoom with the mouse or UP and DOWN keys", (int)optionsBackground.x + 10, 390, 10, ORANGE);
DrawText("Press C to reset position", (int)optionsBackground.x + 10, 410, 10, ORANGE);
DrawText("Press Z to reset zoom", (int)optionsBackground.x + 10, 430, 10, ORANGE);
DrawLineEx((Vector2){ optionsBackground.x, optionsBackground.y }, (Vector2){ optionsBackground.x, optionsBackground.y + optionsBackground.height }, 1.0f, BLACK);
GuiSliderBar((Rectangle){ 605, 10, 150, 25 }, "Line Opacity" , TextFormat("%d" , (int)lineOpacity) , &lineOpacity , 0 , 255);
GuiSliderBar((Rectangle){ 605, 45, 150, 25 }, "Thickness" , TextFormat("%.2f", lineThickness) , &lineThickness , -20.0f , 40.0f);
GuiSliderBar((Rectangle){ 605, 80, 150, 25 }, "Rect Roundness" , TextFormat("%.2f", rectangleRoundness) , &rectangleRoundness , -1.0f , 2.0f);
GuiSliderBar((Rectangle){ 605, 115, 150, 25 }, "Rect Segments" , TextFormat("%d" , (int)rectangleSegments), &rectangleSegments , -1 , 100);
GuiSliderBar((Rectangle){ 605, 150, 150, 25 }, "Ellipse Radius Y", TextFormat("%.2f", ellipseRadiusY) , &ellipseRadiusY , 0.0f , 1.25f);
GuiSliderBar((Rectangle){ 605, 185, 150, 25 }, "Start Angle" , TextFormat("%.2f", circleStartAngle) , &circleStartAngle , -360.0f, 360.0f);
GuiSliderBar((Rectangle){ 605, 220, 150, 25 }, "End Angle" , TextFormat("%.2f", circleEndAngle) , &circleEndAngle , -360.0f, 360.0f);
GuiSliderBar((Rectangle){ 605, 255, 150, 25 }, "Circle Segments" , TextFormat("%d" , (int)circleSegments) , &circleSegments , -1 , 100);
GuiSliderBar((Rectangle){ 605, 290, 150, 25 }, "Ring Radius" , TextFormat("%.2f", ringInnerRadiusScale) , &ringInnerRadiusScale, -1.0f , 2.0f);
GuiSliderBar((Rectangle){ 605, 325, 150, 25 }, "Poly Sides" , TextFormat("%d" , (int)polygonSides) , &polygonSides , -1 , 100);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,78 +0,0 @@
/*******************************************************************************************
*
* raylib [shapes] example - outlines thickness
*
* Example complexity rating: [★☆☆☆] 1/4
*
* Example originally created with raylib 6.1, last time updated with raylib 6.1
*
* Example contributed by Matthew Roush (@MatthewRoush) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2026 Matthew Roush (@MatthewRoush)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - outlines thickness");
float thick = 5.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update variables / Implement example logic at this point
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
GuiSliderBar((Rectangle){ 290, 50, 220, 24 }, "Thickness", TextFormat("%.2f", thick), &thick, -30.0f, 30.0f);
DrawRectangle(35, 180, 220, 220, LIGHTGRAY);
DrawRectangleLinesEx((Rectangle){ 35, 180, 220, 220 }, thick, BLUE);
DrawText("DrawRectangleLinesEx()", 35, 160, 10, BLACK);
DrawRectangleRounded((Rectangle){ 290, 180, 220, 220 }, 0.2f, 9, LIGHTGRAY);
DrawRectangleRoundedLinesEx((Rectangle){ 290, 180, 220, 220 }, 0.2f, 9, thick, BLUE);
DrawText("DrawRectangleRoundedLinesEx()", 290, 160, 10, BLACK);
DrawCircle(655, 290, 110, LIGHTGRAY);
DrawCircleLinesEx((Vector2){ 655, 290 }, 110, thick, BLUE);
DrawText("DrawCircleLinesEx()", 545, 160, 10, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -16,13 +16,12 @@
********************************************************************************************/
#include "raylib.h"
#include <math.h>
#include <stdio.h>
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include <math.h>
#include <stdio.h>
#define MAX_PIE_SLICES 10 // Max pie slices
//------------------------------------------------------------------------------------
@ -40,8 +39,12 @@ int main(void)
int sliceCount = 7;
float donutInnerRadius = 25.0f;
float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values
char labels[MAX_PIE_SLICES][32] = { 0 };
bool editingLabel[MAX_PIE_SLICES] = { 0 };
for (int i = 0; i < MAX_PIE_SLICES; i++)
snprintf(labels[i], 32, "Slice %02i", i + 1);
bool showValues = true;
bool showPercentages = false;
bool showDonut = false;
@ -56,7 +59,7 @@ int main(void)
// UI Panel top-left anchor
const Vector2 panelPos = {
(float)screenWidth - panelMargin - panelWidth,
(float)screenWidth - panelMargin - panelWidth,
(float)panelMargin
};
@ -69,7 +72,7 @@ int main(void)
// Pie chart geometry
const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight };
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f };
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f};
const float radius = 205.0f;
// Total value for percentage calculations
@ -90,7 +93,6 @@ int main(void)
// Check for mouse hover over slices
hoveredSlice = -1; // Reset hovered slice
Vector2 mousePos = GetMousePosition();
if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas
{
float dx = mousePos.x - center.x;
@ -174,7 +176,7 @@ int main(void)
if (showDonut) GuiDisable();
GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 },
"Inner Radius", NULL, & donutInnerRadius, 5.0f, radius - 10.0f);
"Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f);
GuiEnable();
GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL);
@ -188,7 +190,8 @@ int main(void)
};
int contentHeight = sliceCount*35;
GuiScrollPanel(scrollPanelBounds, NULL, (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
GuiScrollPanel(scrollPanelBounds, NULL,
(Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
&scrollContentOffset, &view);
const float contentX = view.x + scrollContentOffset.x; // Left of content
@ -205,8 +208,7 @@ int main(void)
DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color);
// Label textbox
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, TextFormat("Slice %02i", i + 1), 32, editingLabel[i]))
editingLabel[i] = !editingLabel[i];
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, labels[i], 32, editingLabel[i])) editingLabel[i] = !editingLabel[i];
GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f);
}

View File

@ -1,118 +0,0 @@
/*******************************************************************************************
*
* raylib [shapes] example - polygon lines
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 6.1, last time updated with raylib 6.1
*
* Example contributed by Matthew Roush (@MatthewRoush) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2026 Matthew Roush (@MatthewRoush)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - polygon lines");
int thick = 2;
float rotation = 0.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_UP)) thick = thick + 1;
if (IsKeyPressed(KEY_DOWN)) thick = thick - 1;
thick = (thick < 1) ? 1 : (thick > 60) ? 60 : thick;
rotation += (360.0f/10.0f)*GetFrameTime();
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText(TextFormat("thick = %d", thick), 10, 280, 20, LIME);
// The square and circle outlines in the top left should match
// The fist pair of outlines are drawn using `DrawRectangleLinesEx()` and `DrawCircleLinesEx()`
// The second pair are drawn using `DrawPolyLinesEx()` with parameters that should visually match the first pair
DrawText("These should look identical!", 10, 10, 20, MAROON);
// Outline pair 1
DrawRectangle(10, 40, 50, 50, LIGHTGRAY);
DrawRectangleLinesEx((Rectangle){ 10, 40, 50, 50 }, (float)thick, RED);
DrawCircle(95, 65, 25, LIGHTGRAY);
DrawCircleLinesEx((Vector2){ 95, 65 }, 25, (float)thick, RED);
DrawText("DrawRectangleLinesEx() and DrawCircleLinesEx()", 130, 60, 10, BLACK);
// Outline pair 2
DrawPoly((Vector2){ 35, 125 }, 4, 35.355f, 45, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 35, 125 }, 4, 35.355f, 45, (float)thick, RED);
DrawPoly((Vector2){ 95, 125 }, 36, 25, 0, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 95, 125 }, 36, 25, 0, (float)thick, RED);
DrawText("DrawPolyLinesEx()", 130, 120, 10, BLACK);
// Some other shapes, all of these outlines should have the same looking thickness
DrawPoly((Vector2){ 290, 220 }, 3, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 290, 220 }, 3, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 430, 220 }, 4, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 430, 220 }, 4, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 570, 220 }, 5, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 570, 220 }, 5, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 710, 220 }, 6, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 710, 220 }, 6, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 290, 360 }, 7, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 290, 360 }, 7, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 430, 360 }, 8, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 430, 360 }, 8, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 570, 360 }, 9, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 570, 360 }, 9, 60, rotation, (float)thick, BLUE);
DrawPoly((Vector2){ 710, 360 }, 10, 60, rotation, LIGHTGRAY);
DrawPolyLinesEx((Vector2){ 710, 360 }, 10, 60, rotation, (float)thick, BLUE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because it is too large Load Diff

View File

@ -442,7 +442,6 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(alphaDiscard);
UnloadFont(font);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -135,7 +135,7 @@ int main(void)
// Module Functions Definition
//------------------------------------------------------------------------------------
// Remove codepoint duplicates if requested
// WARNING: This process could be a bit slow if the text to process is very long
// WARNING: This process could be a bit slow if there text to process is very long
static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointsResultCount)
{
int codepointsNoDupsCount = codepointCount;
@ -149,7 +149,7 @@ static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *
{
if (codepointsNoDups[i] == codepointsNoDups[j])
{
for (int k = j; k < codepointsNoDupsCount - 1; k++) codepointsNoDups[k] = codepointsNoDups[k + 1];
for (int k = j; k < codepointsNoDupsCount; k++) codepointsNoDups[k] = codepointsNoDups[k + 1];
codepointsNoDupsCount--;
j--;

View File

@ -31,7 +31,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [text] example - font filters");
const char *msg = "Loaded Font";
const char msg[50] = "Loaded Font";
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)

View File

@ -38,7 +38,7 @@ int main(void)
// Define characters to draw
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
const char *msg = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm\nnopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒ\nÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö\n÷øùúûüýþÿ";
const char msg[256] = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)

File diff suppressed because it is too large Load Diff

View File

@ -53,7 +53,7 @@ int main(void)
bool paused = false;
SetTargetFPS(0); // Set our game to run with an uncapped framerate
//SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop

View File

@ -50,7 +50,7 @@ int main(void)
if (IsKeyPressed(KEY_R)) // Reset image collection
{
// Unload textures to avoid memory leaks
for (int i = 0; i < currentCollectionIndex; i++) UnloadTexture(collection[i].texture);
for (int i = 0; i < MAX_TEXTURE_COLLECTION; i++) UnloadTexture(collection[i].texture);
currentCollectionIndex = 0;
}
@ -82,8 +82,8 @@ int main(void)
if (IsTextureValid(collection[i].texture))
{
DrawTexturePro(collection[i].texture,
(Rectangle){0,0,(float)collection[i].texture.width, (float)collection[i].texture.height},
(Rectangle){collection[i].position.x,collection[i].position.y, (float)collection[i].texture.width, (float)collection[i].texture.height},
(Rectangle){0,0,collection[i].texture.width, collection[i].texture.height},
(Rectangle){collection[i].position.x,collection[i].position.y,collection[i].texture.width, collection[i].texture.height},
(Vector2){collection[i].texture.width*0.5f, collection[i].texture.height*0.5f},
0.0f, WHITE);
}
@ -98,7 +98,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
for (int i = 0; i < currentCollectionIndex; i++)
for (int i = 0; i < MAX_TEXTURE_COLLECTION;i ++)
{
UnloadTexture(collection[i].texture);
}

View File

@ -115,7 +115,7 @@ int main(void)
EndMode3D();
DrawRectangleLines((int)((subjectTarget.texture.width - captureSize)/2.0f), (int)((subjectTarget.texture.height - captureSize)/2.0f), (int)captureSize, (int)captureSize, GREEN);
DrawRectangleLines((int)((subjectTarget.texture.width - captureSize)/2.0f), (int)((subjectTarget.texture.height - captureSize)/2.0f), captureSize, captureSize, GREEN);
DrawText("Subject View", 10, subjectTarget.texture.height - 30, 20, BLACK);
EndTextureMode();

View File

@ -109,7 +109,7 @@ int main(void)
else if (IsKeyPressed(KEY_UP))
{
currentProcess--;
if (currentProcess < 0) currentProcess = (NUM_PROCESSES - 1);
if (currentProcess < 0) currentProcess = 7;
textureReload = true;
}

View File

@ -44,10 +44,6 @@ int main(void)
textures[1] = LoadTextureFromImage(image90);
textures[2] = LoadTextureFromImage(imageNeg90);
UnloadImage(image45);
UnloadImage(image90);
UnloadImage(imageNeg90);
int currentTexture = 0;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second

View File

@ -29,14 +29,8 @@ int main(void)
Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM)
// When no codepoints are provided, LoadFontEx() loads a default set of codepoints
// This set includes '@', which "KAISG.ttf" doesn't have a glyph for, causing a warning to be logged
// We avoid this by just excluding it from the list of codepoints we load
int codepointCount = 0;
int *codepoints = LoadCodepoints(" !\"#$%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", &codepointCount);
// TTF Font loading with custom generation parameters
Font font = LoadFontEx("resources/KAISG.ttf", 64, codepoints, codepointCount);
UnloadCodepoints(codepoints);
Font font = LoadFontEx("resources/KAISG.ttf", 64, 0, 0);
// Draw over image using custom font
ImageDrawTextEx(&parrots, font, "[Parrots font drawing]", (Vector2){ 20.0f, 20.0f }, (float)font.baseSize, 0.0f, RED);
@ -75,21 +69,7 @@ int main(void)
DrawTextEx(font, "[Parrots font drawing]", (Vector2){ position.x + 20,
position.y + 20 + 280 }, (float)font.baseSize, 0.0f, WHITE);
}
else
{
// Make the font atlas texture fit the screen, so we can see the whole thing
float scale = 1.0f;
float atlasRatio = (float)font.texture.width/(float)font.texture.height;
float screenRatio = (float)screenWidth/(float)screenHeight;
if (atlasRatio >= screenRatio) scale = (float)screenWidth/(float)font.texture.width;
else scale = (float)screenHeight/(float)font.texture.height;
float width = (float)font.texture.width * scale;
float height = (float)font.texture.height * scale;
DrawTextureEx(font.texture, (Vector2){ ((float)screenWidth - width)/2, ((float)screenHeight - height)/2 }, 0, scale, BLACK);
}
else DrawTexture(font.texture, screenWidth/2 - font.texture.width/2, 50, BLACK);
DrawText("PRESS SPACE to SHOW FONT ATLAS USED", 290, 420, 10, DARKGRAY);

View File

@ -16,9 +16,7 @@
********************************************************************************************/
#include "raylib.h"
#include "rlgl.h" // Required for: rlSetBlendFactorsSeparate()
#include "raymath.h" // Required for: Vector2Multiply()
#include "rlgl.h" // for rlSetBlendFactorsSeparate()
//------------------------------------------------------------------------------------
// Program main entry point
@ -47,7 +45,8 @@ int main(void)
// Set magnifying glass zoom
camera.zoom = 2;
// Offset by half the size of the magnifying glass to counteract drawing the texture centered on the mouse position
camera.offset = Vector2Multiply((Vector2){ 128, 128 }, GetWindowScaleDPI());
camera.offset = (Vector2){128, 128};
SetTargetFPS(60);
//--------------------------------------------------------------------------------------

View File

@ -4,7 +4,7 @@
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 3.0, last time updated with raylib 6.0
* Example originally created with raylib 3.0, last time updated with raylib 3.0
*
* Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5)
*
@ -114,7 +114,7 @@ int main(void)
EndTextureMode();
}
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsGestureDetected(GESTURE_DRAG))
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || (GetGestureDetected() == GESTURE_DRAG))
{
// Paint circle into render texture
// NOTE: To avoid discontinuous circles, we could store

View File

@ -1,242 +0,0 @@
/*******************************************************************************************
*
* raylib [textures] example - portal window
*
* Example demonstrates rendering a second scene to a texture and projecting it onto a
* quad to create the illusion of a portal window looking into another place. The second
* scene is rendered with an off-axis ("oblique frustum") projection matched to the
* viewer's actual position relative to the window, so the illusion holds up correctly
* as the player moves and looks around, rather than only looking right from one spot
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 6.0, last time updated with raylib 6.0
*
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2025 PanicTitan (@PanicTitan)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#include "rlgl.h"
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
// Begin portal mode 3D view
static void BeginPortalMode3D(Vector3 eye, Vector3 bottomLeft, Vector3 bottomRight, Vector3 topLeft, float nearPlane, float farPlane);
// End portal 3D mode and returns to default 2D orthographic mode
static void EndPortalMode3D(void);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - portal window");
// Camera to navigate the "real world" (Dimension A)
Camera3D camera = { 0 };
camera.position = (Vector3){ 0.0f, 2.5f, 7.0f };
camera.target = (Vector3){ 0.0f, 1.8f, 0.0f };
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
camera.fovy = 45.0f;
camera.projection = CAMERA_PERSPECTIVE;
// The archway opening, in Dimension A world space (used both to draw the frame and
// as the window rectangle the oblique projection is built from)
Vector3 archBottomLeft = { -1.5f, 0.0f, 0.0f };
Vector3 archBottomRight = { 1.5f, 0.0f, 0.0f };
Vector3 archTopLeft = { -1.5f, 4.0f, 0.0f };
// The archway sits at portalA and looks out onto portalB, far away in world space.
// Every frame, Dimension B gets rendered to a texture using the same relative eye
// and window position, shifted by the offset between the two portals
Vector3 portalA = { 0.0f, 0.0f, 0.0f };
Vector3 portalB = { 0.0f, 0.0f, -60.0f };
RenderTexture2D portalView = LoadRenderTexture(480, 640);
DisableCursor(); // Lock cursor for first-person free camera controls
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_FREE);
float time = (float)GetTime();
// Eye and window corners, shifted into Dimension B so they match the player's
// actual position and viewing angle relative to the archway
Vector3 offset = Vector3Subtract(portalB, portalA);
Vector3 eyeInB = Vector3Add(camera.position, offset);
Vector3 blInB = Vector3Add(archBottomLeft, offset);
Vector3 brInB = Vector3Add(archBottomRight, offset);
Vector3 tlInB = Vector3Add(archTopLeft, offset);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
// Render Dimension B into an offscreen texture, using an oblique projection so
// its perspective lines up with the archway exactly as the real camera sees it
BeginTextureMode(portalView);
ClearBackground((Color){ 10, 5, 20, 255 });
BeginPortalMode3D(eyeInB, blInB, brInB, tlInB, 0.05f, 100.0f);
DrawGrid(30, 0.8f);
// Floating pulsing core sphere
Vector3 corePos = Vector3Add(portalB, (Vector3){ 0.0f, 2.0f + sinf(time * 2.5f) * 0.4f, -4.0f });
DrawSphere(corePos, 1.2f, PURPLE);
DrawSphereWires(corePos, 1.25f, 16, 16, MAGENTA);
// Orbiting cubes
for (int i = 0; i < 4; i++)
{
float angle = time * 1.5f + i * (PI / 2.0f);
Vector3 pos = Vector3Add(portalB, (Vector3){
sinf(angle) * 2.5f,
2.0f + cosf(time * 3.0f + i) * 0.5f,
-4.0f + cosf(angle) * 2.5f });
DrawCube(pos, 0.5f, 0.5f, 0.5f, LIME);
DrawCubeWires(pos, 0.52f, 0.52f, 0.52f, DARKGREEN);
}
EndPortalMode3D();
EndTextureMode();
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawGrid(20, 1.0f);
// Side pillars
DrawCube((Vector3){ -3.5f, 2.0f, 0.0f }, 0.8f, 4.0f, 0.8f, DARKGRAY);
DrawCubeWires((Vector3){ -3.5f, 2.0f, 0.0f }, 0.8f, 4.0f, 0.8f, ORANGE);
DrawCube((Vector3){ 3.5f, 2.0f, 0.0f }, 0.8f, 4.0f, 0.8f, DARKGRAY);
DrawCubeWires((Vector3){ 3.5f, 2.0f, 0.0f }, 0.8f, 4.0f, 0.8f, ORANGE);
// Golden archway frame and solid base
DrawCubeWires((Vector3){ 0.0f, 2.0f, 0.0f }, 3.2f, 4.2f, 0.2f, GOLD);
DrawCube((Vector3){ 0.0f, 0.05f, 0.0f }, 3.4f, 0.1f, 0.6f, MAROON);
// Solid backing wall, only ever seen if looking at the archway from behind
DrawCube((Vector3){ 0.0f, 2.0f, -0.05f }, 3.1f, 4.1f, 0.05f, MAROON);
// The portal opening itself: a plain quad textured with the Dimension B
// render, filling the archway exactly, so nothing "leaks" outside its shape
rlSetTexture(portalView.texture.id);
rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255);
rlNormal3f(0.0f, 0.0f, 1.0f);
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(archBottomLeft.x, archBottomLeft.y, archBottomLeft.z);
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(archBottomRight.x, archBottomRight.y, archBottomRight.z);
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(archBottomRight.x, 4.0f, archBottomRight.z);
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(archTopLeft.x, archTopLeft.y, archTopLeft.z);
rlEnd();
rlSetTexture(0);
EndMode3D();
// HUD overlay
DrawRectangle(15, 15, 520, 100, Fade(BLACK, 0.75f));
DrawRectangleLines(15, 15, 520, 100, GOLD);
DrawText("PORTAL WINDOW", 28, 25, 20, GOLD);
DrawText("Look through the golden arch into Dimension B", 28, 52, 20, RAYWHITE);
DrawText("Controls: Mouse to look | WASD to move", 28, 80, 20, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadRenderTexture(portalView);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Starts a 3D mode using an off-axis ("oblique frustum") projection, built directly from
// an eye point and 3 corners of a rectangular window, instead of a fovy centered straight
// ahead of the camera. This is the standard technique for rendering a scene as seen through
// a window that isn't necessarily faced head-on (also used for multi-monitor and VR
// rendering) - the key difference from a normal Camera3D is that the frustum is allowed
// to be asymmetric, so perspective lines through the window line up correctly from any
// eye position, instead of behaving like a flat image pasted onto the window
static void BeginPortalMode3D(Vector3 eye, Vector3 bottomLeft, Vector3 bottomRight, Vector3 topLeft, float nearPlane, float farPlane)
{
Vector3 right = Vector3Normalize(Vector3Subtract(bottomRight, bottomLeft));
Vector3 up = Vector3Normalize(Vector3Subtract(topLeft, bottomLeft));
Vector3 normal = Vector3Normalize(Vector3CrossProduct(right, up));
// Vectors from the eye to 3 corners of the window, used to project the window onto
// the near plane and read off how far it extends left/right/bottom/top of the eye
Vector3 toBL = Vector3Subtract(bottomLeft, eye);
Vector3 toBR = Vector3Subtract(bottomRight, eye);
Vector3 toTL = Vector3Subtract(topLeft, eye);
float dist = -Vector3DotProduct(toBL, normal);
if (dist < 0.01f) dist = 0.01f; // Keep the eye from crossing the window plane
float scale = nearPlane/dist;
rlDrawRenderBatchActive();
rlMatrixMode(RL_PROJECTION);
rlPushMatrix();
rlSetMatrixProjection(MatrixFrustum(
Vector3DotProduct(right, toBL)*scale, Vector3DotProduct(right, toBR)*scale,
Vector3DotProduct(up, toBL)*scale, Vector3DotProduct(up, toTL)*scale,
nearPlane, farPlane));
// View orientation is fixed to the window's own plane (looking straight through it
// along its normal), NOT aimed at any target - that's what the asymmetric frustum
// above is for, and is what lets the eye move off to one side without distorting
rlMatrixMode(RL_MODELVIEW);
rlLoadIdentity();
rlMultMatrixf(MatrixToFloat(MatrixLookAt(eye, Vector3Subtract(eye, normal), up)));
rlEnableDepthTest();
}
// End portal 3D mode and returns to default 2D orthographic mode
// NOTE: Similar implementation to EndMode3D()
static void EndPortalMode3D(void)
{
rlDrawRenderBatchActive(); // Update and draw internal render batch
rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rlPopMatrix(); // Restore previous matrix (projection) from matrix stack
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
rlLoadIdentity(); // Reset current matrix (modelview)
rlDisableDepthTest(); // Disable DEPTH_TEST for 2D
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -95,7 +95,7 @@ int main(void)
if (!IsMouseButtonDown(MOUSE_LEFT_BUTTON)) curveSelectedPoint = NULL;
// If a point was selected, move it
if (curveSelectedPoint != NULL) *curveSelectedPoint = Vector2Add(*curveSelectedPoint, GetMouseDelta());
if (curveSelectedPoint) *curveSelectedPoint = Vector2Add(*curveSelectedPoint, GetMouseDelta());
// The mouse is down, and nothing was selected, so see if anything was picked
Vector2 mouse = GetMousePosition();

401
projects/4coder/Makefile Normal file
View File

@ -0,0 +1,401 @@
#**************************************************************************************************
#
# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5
#
# Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
#
# This software is provided "as-is", without any express or implied warranty. In no event
# will the authors be held liable for any damages arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose, including commercial
# applications, and to alter it and redistribute it freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not claim that you
# wrote the original software. If you use this software in a product, an acknowledgment
# in the product documentation would be appreciated but is not required.
#
# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
# as being the original software.
#
# 3. This notice may not be removed or altered from any source distribution.
#
#**************************************************************************************************
.PHONY: all clean
# Define required raylib variables
PROJECT_NAME ?= game
RAYLIB_VERSION ?= 4.2.0
RAYLIB_PATH ?= ..\..
# Define default options
# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
PLATFORM ?= PLATFORM_DESKTOP
# Locations of your newly installed library and associated headers. See ../src/Makefile
# On Linux, if you have installed raylib but cannot compile the examples, check that
# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations.
# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED.
# To enable compile-time linking to a special version of libraylib.so, change these variables here.
# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below.
# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime,
# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH.
# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths.
DESTDIR ?= /usr/local
RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib
# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files.
RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include
# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
RAYLIB_LIBTYPE ?= STATIC
# Build mode for project: DEBUG or RELEASE
BUILD_MODE ?= RELEASE
# Use external GLFW library instead of rglfw module
# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3
USE_EXTERNAL_GLFW ?= FALSE
# Use Wayland display server protocol on Linux desktop
# by default it uses X11 windowing system
USE_WAYLAND_DISPLAY ?= FALSE
# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows!
# ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
else
UNAMEOS=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
endif
ifeq ($(UNAMEOS),FreeBSD)
PLATFORM_OS=BSD
endif
ifeq ($(UNAMEOS),OpenBSD)
PLATFORM_OS=BSD
endif
ifeq ($(UNAMEOS),NetBSD)
PLATFORM_OS=BSD
endif
ifeq ($(UNAMEOS),DragonFly)
PLATFORM_OS=BSD
endif
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
UNAMEOS=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
endif
endif
# RAYLIB_PATH adjustment for different platforms.
# If using GNU make, we can get the full path to the top of the tree. Windows? BSD?
# Required for ldconfig or other tools that do not perform path expansion.
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
RAYLIB_PREFIX ?= ..
RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX))
endif
endif
# Default path for raylib on Raspberry Pi, if installed in different path, update it!
# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki.
# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX.
ifeq ($(PLATFORM),PLATFORM_RPI)
RAYLIB_PATH ?= /home/pi/raylib
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# Emscripten required variables
EMSDK_PATH ?= C:/raylib/emsdk
EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten
CLANG_PATH = $(EMSDK_PATH)/upstream/bin
PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit
NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin
export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH)
endif
# Define raylib release directory for compiled library.
# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version
RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src
# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries
# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH
# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux
# without formal installation from ../src/Makefile. It aids portability and is useful if you have
# multiple versions of raylib, have raylib installed to a non-standard location, or want to
# bundle libraylib.so with your game. Change it to your liking.
# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH,
# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH,
# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute.
# To see which libraries a built example is linking to, ldd core/core_basic_window;
# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing.
EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH)
# Define default C compiler: gcc
# NOTE: define g++ compiler if using C++
CC = gcc
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
# OSX default compiler
CC = clang
endif
ifeq ($(PLATFORM_OS),BSD)
# FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
CC = clang
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
# Define RPI cross-compiler
#CC = armv6j-hardfloat-linux-gnueabi-gcc
CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc
endif
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# HTML5 emscripten compiler
# WARNING: To compile to HTML5, code must be redesigned
# to use emscripten.h and emscripten_set_main_loop()
CC = emcc
endif
# Define default make program: Mingw32-make
MAKE = mingw32-make
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),LINUX)
MAKE = make
endif
ifeq ($(PLATFORM_OS),OSX)
MAKE = make
endif
endif
# Define compiler flags:
# -O1 defines optimization level
# -g include debug information on compilation
# -s strip unnecessary data from build
# -Wall turns on most, but not all, compiler warnings
# -std=c99 defines C language mode (standard C from 1999 revision)
# -std=gnu99 defines C language mode (GNU C from 1999 revision)
# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces
ifeq ($(BUILD_MODE),DEBUG)
CFLAGS += -g
endif
# Additional flags for compiler (if desired)
#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# resource file contains windows executable icon and properties
# -Wl,--subsystem,windows hides the console window
CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows
endif
ifeq ($(PLATFORM_OS),LINUX)
ifeq ($(RAYLIB_LIBTYPE),STATIC)
CFLAGS += -D_DEFAULT_SOURCE
endif
ifeq ($(RAYLIB_LIBTYPE),SHARED)
# Explicitly enable runtime link to libraylib.so
CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
CFLAGS += -std=gnu99
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# -Os # size optimization
# -O2 # optimization level 2, if used, also set --memory-init-file 0
# -sUSE_GLFW=3 # Use glfw3 library (context/input management)
# -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
# -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB)
# -sUSE_PTHREADS=1 # multithreading support
# -sWASM=0 # disable Web Assembly, emitted by default
# -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS
# -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data
# -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
# -sMINIFY_HTML=0 # minify generated html from shell.html
# --profiling # include information for code profiling
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
# --preload-file resources # specify a resources folder for data compilation
# --source-map-base # allow debugging in browser with source map
# --shell-file shell.html # define a custom shell .html and output extension
CFLAGS += -Os -sUSE_GLFW=3 -sTOTAL_MEMORY=16777216 --preload-file resources -sMINIFY_HTML=0
ifeq ($(BUILD_MODE), DEBUG)
CFLAGS += -sASSERTIONS=1 --profiling
endif
# Define a custom shell .html and output extension
CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
EXT = .html
endif
# Define include paths for required headers
# NOTE: Several external required libraries (stb and others)
INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external
# Define additional directories containing required header files
ifeq ($(PLATFORM),PLATFORM_RPI)
# RPI required libraries
INCLUDE_PATHS += -I/opt/vc/include
INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux
INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads
endif
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),BSD)
# Consider -L$(RAYLIB_H_INSTALL_PATH)
INCLUDE_PATHS += -I/usr/local/include
endif
ifeq ($(PLATFORM_OS),LINUX)
# Reset everything.
# Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include
INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external
endif
endif
# Define library paths containing required libs.
LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),BSD)
# Consider -L$(RAYLIB_INSTALL_PATH)
LDFLAGS += -L. -Lsrc -L/usr/local/lib
endif
ifeq ($(PLATFORM_OS),LINUX)
# Reset everything.
# Precedence: immediately local, installed version, raysan5 provided libs
LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH)
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
LDFLAGS += -L/opt/vc/lib
endif
# Define any libraries required on linking
# if you want to link libraries (libname.so or libname.a), use the -lname
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
# Libraries for Windows desktop compilation
# NOTE: WinMM library required to set high-res timer resolution
LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
endif
ifeq ($(PLATFORM_OS),LINUX)
# Libraries for Debian GNU/Linux desktop compiling
# NOTE: Required packages: libegl1-mesa-dev
LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
# On X11 requires also below libraries
LDLIBS += -lX11
# NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
#LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
# On Wayland windowing system, additional libraries requires
ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
endif
# Explicit link to libc
ifeq ($(RAYLIB_LIBTYPE),SHARED)
LDLIBS += -lc
endif
endif
ifeq ($(PLATFORM_OS),OSX)
# Libraries for OSX 10.9 desktop compiling
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa
endif
ifeq ($(PLATFORM_OS),BSD)
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
# NOTE: Required packages: mesa-libs
LDLIBS = -lraylib -lGL -lpthread -lm
# On XWindow requires also below libraries
LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
endif
ifeq ($(USE_EXTERNAL_GLFW),TRUE)
# NOTE: It could require additional packages installed: libglfw3-dev
LDLIBS += -lglfw
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
# Libraries for Raspberry Pi compiling
# NOTE: Required packages: libasound2-dev (ALSA)
LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# Libraries for web (HTML5) compiling
LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc
endif
# Define a recursive wildcard function
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
# Define all source files required
SRC_DIR = src
OBJ_DIR = obj
# Define all object files from source files
SRC = $(call rwildcard, *.c, *.h)
#OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
OBJS = main.c
# For Android platform we call a custom Makefile.Android
ifeq ($(PLATFORM),PLATFORM_ANDROID)
MAKEFILE_PARAMS = -f Makefile.Android
export PROJECT_NAME
export SRC_DIR
else
MAKEFILE_PARAMS = $(PROJECT_NAME)
endif
# Default target entry
# NOTE: We call this Makefile target or Makefile.Android target
all:
$(MAKE) $(MAKEFILE_PARAMS)
# Project target defined by PROJECT_NAME
$(PROJECT_NAME): $(OBJS)
$(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
# Compile source files
# NOTE: This pattern will compile every module defined on $(OBJS)
#%.o: %.c
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
# Clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
del *.o *.exe /s
endif
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv
endif
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete
rm -f *.o
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
find . -type f -executable -delete
rm -fv *.o
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done

View File

@ -0,0 +1,300 @@
#**************************************************************************************************
#
# raylib makefile for Android project (APK building)
#
# Copyright (c) 2017 Ramon Santamaria (@raysan5)
#
# This software is provided "as-is", without any express or implied warranty. In no event
# will the authors be held liable for any damages arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose, including commercial
# applications, and to alter it and redistribute it freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not claim that you
# wrote the original software. If you use this software in a product, an acknowledgment
# in the product documentation would be appreciated but is not required.
#
# 2. Altered source versions must be plainly marked as such, and must not be misrepresented
# as being the original software.
#
# 3. This notice may not be removed or altered from any source distribution.
#
#**************************************************************************************************
# Define required raylib variables
PLATFORM ?= PLATFORM_ANDROID
RAYLIB_PATH ?= ..\..
# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version
ANDROID_ARCH ?= ARM
ANDROID_API_VERSION = 21
ifeq ($(ANDROID_ARCH),ARM)
ANDROID_ARCH_NAME = armeabi-v7a
endif
ifeq ($(ANDROID_ARCH),ARM64)
ANDROID_ARCH_NAME = arm64-v8a
endif
# Required path variables
# NOTE: JAVA_HOME must be set to JDK
JAVA_HOME ?= C:/JavaJDK
ANDROID_HOME = C:/android-sdk
ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION)
ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1
ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools
# Android project configuration variables
PROJECT_NAME ?= raylib_game
PROJECT_LIBRARY_NAME ?= main
PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME)
PROJECT_RESOURCES_PATH ?= resources
PROJECT_SOURCE_FILES ?= raylib_game.c
# Some source files are placed in directories, when compiling to some
# output directory other than source, that directory must pre-exist.
# Here we get a list of required folders that need to be created on
# code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors.
PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES)))
# Android app configuration variables
APP_LABEL_NAME ?= rGame
APP_COMPANY_NAME ?= raylib
APP_PRODUCT_NAME ?= rgame
APP_VERSION_CODE ?= 1
APP_VERSION_NAME ?= 1.0
APP_ICON_LDPI ?= $(RAYLIB_PATH)\logo\raylib_36x36.png
APP_ICON_MDPI ?= $(RAYLIB_PATH)\logo\raylib_48x48.png
APP_ICON_HDPI ?= $(RAYLIB_PATH)\logo\raylib_72x72.png
APP_SCREEN_ORIENTATION ?= landscape
APP_KEYSTORE_PASS ?= raylib
# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
RAYLIB_LIBTYPE ?= STATIC
# Library path for libraylib.a/libraylib.so
RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src
# Shared libs must be added to APK if required
# NOTE: Generated NativeLoader.java automatically load those libraries
ifeq ($(RAYLIB_LIBTYPE),SHARED)
PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so
endif
# Compiler and archiver
# NOTE: GCC is being deprecated in Android NDK r16
ifeq ($(ANDROID_ARCH),ARM)
CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang
AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar
endif
ifeq ($(ANDROID_ARCH),ARM64)
CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang
AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar
endif
# Compiler flags for arquitecture
ifeq ($(ANDROID_ARCH),ARM)
CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
endif
ifeq ($(ANDROID_ARCH),ARM64)
CFLAGS = -std=c99 -mfix-cortex-a53-835769
endif
# Compilation functions attributes options
CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC
# Compiler options for the linker
CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes
# Preprocessor macro definitions
CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION)
# Paths containing required header files
INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue
# Linker options
LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a
LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings
# Force linking of library module to define symbol
LDFLAGS += -u ANativeActivity_onCreate
# Library paths containing required libs
LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib
# Define any libraries to link into executable
# if you want to link libraries (libname.so or libname.a), use the -lname
LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl
# Generate target objects list from PROJECT_SOURCE_FILES
OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES))
# Android APK building process... some steps required...
# NOTE: typing 'make' will invoke the default target entry called 'all',
all: create_temp_project_dirs \
copy_project_required_libs \
copy_project_resources \
generate_loader_script \
generate_android_manifest \
generate_apk_keystore \
config_project_package \
compile_project_code \
compile_project_class \
compile_project_class_dex \
create_project_apk_package \
sign_project_apk_package \
zipalign_project_apk_package
# Create required temp directories for APK building
create_temp_project_dirs:
if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH)
if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj
if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src
if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com
if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)
if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME)
if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib
if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)
if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin
if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res
if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi
if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi
if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi
if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values
if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets
if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH)
if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens
$(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir)))
define create_dir
if not exist $(PROJECT_BUILD_PATH)\obj\$(1) mkdir $(PROJECT_BUILD_PATH)\obj\$(1)
endef
# Copy required shared libs for integration into APK
# NOTE: If using shared libs they are loaded by generated NativeLoader.java
copy_project_required_libs:
ifeq ($(RAYLIB_LIBTYPE),SHARED)
copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so
endif
ifeq ($(RAYLIB_LIBTYPE),STATIC)
copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a
endif
# Copy project required resources: strings.xml, icon.png, assets
# NOTE: Required strings.xml is generated and game resources are copied to assets folder
# TODO: Review xcopy usage, it can not be found in some systems!
copy_project_resources:
copy $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)\res\drawable-ldpi\icon.png /Y
copy $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)\res\drawable-mdpi\icon.png /Y
copy $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)\res\drawable-hdpi\icon.png /Y
@echo ^<?xml version="1.0" encoding="utf-8"^?^> > $(PROJECT_BUILD_PATH)/res/values/strings.xml
@echo ^<resources^>^<string name="app_name"^>$(APP_LABEL_NAME)^</string^>^</resources^> >> $(PROJECT_BUILD_PATH)/res/values/strings.xml
if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F
# Generate NativeLoader.java to load required shared libraries
# NOTE: Probably not the bet way to generate this file... but it works.
generate_loader_script:
@echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
@echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
@echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
@echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
ifeq ($(RAYLIB_LIBTYPE),SHARED)
@echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
endif
@echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
@echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
@echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
# Generate AndroidManifest.xml with all the required options
# NOTE: Probably not the bet way to generate this file... but it works.
generate_android_manifest:
@echo ^<?xml version="1.0" encoding="utf-8"^?^> > $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<manifest xmlns:android="http://schemas.android.com/apk/res/android" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<uses-sdk android:minSdkVersion="$(ANDROID_API_VERSION)" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<uses-feature android:glEsVersion="0x00020000" android:required="true" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<application android:allowBackup="false" android:label="@string/app_name" android:icon="@drawable/icon" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<activity android:name="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME).NativeLoader" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<meta-data android:name="android.app.lib_name" android:value="$(PROJECT_LIBRARY_NAME)" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<intent-filter^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<action android:name="android.intent.action.MAIN" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^<category android:name="android.intent.category.LAUNCHER" /^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^</intent-filter^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^</activity^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^</application^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
@echo ^</manifest^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml
# Generate storekey for APK signing: $(PROJECT_NAME).keystore
# NOTE: Configure here your Distinguished Names (-dname) if required!
generate_apk_keystore:
if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA
# Config project package and resource using AndroidManifest.xml and res/values/strings.xml
# NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java
config_project_package:
$(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar
# Compile native_app_glue code as static library: obj/libnative_app_glue.a
compile_native_app_glue:
$(CC) -c $(RAYLIB_PATH)/src/external/android/native_app_glue/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS)
$(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o
# Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so
compile_project_code: $(OBJS)
$(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS)
# Compile all .c files required into object (.o) files
# NOTE: Those files will be linked into a shared library
$(PROJECT_BUILD_PATH)/obj/%.o:%.c
$(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot
# Compile project .java code into .class (Java bytecode)
compile_project_class:
$(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java
# Compile .class files into Dalvik executable bytecode (.dex)
# NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT)
compile_project_class_dex:
$(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj
# Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk
# NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so
# NOTE: Use -A resources to define additional directory in which to find raw asset files
create_project_apk_package:
$(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin
cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS)
# Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk
sign_project_apk_package:
$(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key
# Create zip-aligned APK package: $(PROJECT_NAME).apk
zipalign_project_apk_package:
$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk
# Install $(PROJECT_NAME).apk to default emulator/device
# NOTE: Use -e (emulator) or -d (device) parameters if required
install:
$(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk
# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64)
check_device_abi:
$(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi
# Monitorize output log coming from device, only raylib tag
logcat:
$(ANDROID_PLATFORM_TOOLS)/adb logcat -c
$(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S
# Install and monitorize $(PROJECT_NAME).apk to default emulator/device
deploy:
$(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk
$(ANDROID_PLATFORM_TOOLS)/adb logcat -c
$(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S
#$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W
# Clean everything
clean:
del $(PROJECT_BUILD_PATH)\* /f /s /q
rmdir $(PROJECT_BUILD_PATH) /s /q
@echo Cleaning done

40
projects/4coder/main.c Normal file
View File

@ -0,0 +1,40 @@
#include <math.h>
#include "raylib.h"
int main()
{
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib");
Camera cam;
cam.position = (Vector3){ 0.0f, 10.0f, 8.f };
cam.target = (Vector3){ 0.0f, 0.0f, 0.0f };
cam.up = (Vector3){ 0.0f, 1.f, 0.0f };
cam.fovy = 60.0f;
Vector3 cubePos = { 0.0f, 0.0f, 0.0f };
SetTargetFPS(60);
while (!WindowShouldClose())
{
cam.position.x = sin(GetTime())*10.0f;
cam.position.z = cos(GetTime())*10.0f;
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(cam);
DrawCube(cubePos, 2.f, 2.f, 2.f, RED);
DrawCubeWires(cubePos, 2.f, 2.f, 2.f, MAROON);
DrawGrid(10, 1.f);
EndMode3D();
DrawText("This is a raylib example", 10, 40, 20, DARKGRAY);
DrawFPS(10, 10);
EndDrawing();
}
CloseWindow();
return 0;
}

View File

@ -0,0 +1,54 @@
version(1);
project_name = "raylib-example";
patterns = {
"*.cpp",
"*.c",
"*.h",
"*.bat",
"*.sh",
"*.4coder",
"Makefile",
};
blacklist_patterns = {
".*",
};
load_paths = {
{ { {".", .relative = true, .recursive = true, } }, .os = "win" },
{ { {".", .relative = true, .recursive = true, } }, .os = "linux" },
{ { {".", .relative = true, .recursive = true, } }, .os = "mac" },
};
command_list = {
{ .name = "clean",
.out = "*clean*", .footer_panel = true, .save_dirty_files = false, .cursor_at_end = true,
.cmd = {
{"mingw32-make clean", .os = "win"},
{"make clean", .os = "linux"},
{"make clean", .os = "mac"},
},
},
{ .name = "build",
.out = "*compile*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false,
.cmd = {
{"mingw32-make", .os = "win"},
{"make", .os = "linux"},
{"make", .os = "mac"},
},
},
{ .name = "run",
.out = "*run*", .footer_panel = true, .save_dirty_files = false, .cursor_at_end = true,
.cmd = {
{".\game.exe", .os = "win"},
{"./game", .os = "linux"},
{"./game", .os = "mac"},
},
},
};
fkey_command[3] = "clean";
fkey_command[4] = "build";
fkey_command[5] = "run";

View File

@ -30,7 +30,7 @@ target_link_libraries(${PROJECT_NAME} raylib)
# Web Configurations
if (${PLATFORM} STREQUAL "Web")
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") # Tell Emscripten to build an example.html file.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY -s GL_ENABLE_GET_PROC_ADDRESS=1")
endif()
# Checks if OSX and links appropriate frameworks (Only required on MacOS)
@ -38,5 +38,4 @@ if (APPLE)
target_link_libraries(${PROJECT_NAME} "-framework IOKit")
target_link_libraries(${PROJECT_NAME} "-framework Cocoa")
target_link_libraries(${PROJECT_NAME} "-framework OpenGL")
target_link_libraries(${PROJECT_NAME} "-framework QuartzCore")
endif()

View File

@ -24,7 +24,6 @@
<Add option="-framework IOKit" />
<Add option="-framework CoreAudio" />
<Add option="-framework CoreVideo" />
<Add option="-framework QuartzCore" />
</Linker>
</Target>
<Target title="Release (Mac)">
@ -45,7 +44,6 @@
<Add option="-framework IOKit" />
<Add option="-framework CoreAudio" />
<Add option="-framework CoreVideo" />
<Add option="-framework QuartzCore" />
</Linker>
</Target>
<Target title="Debug (Linux)">

Some files were not shown because too many files have changed in this diff Show More