237 Commits

Author SHA1 Message Date
Ray
6986183858 Merge branch 'master' of https://github.com/raysan5/raylib 2026-01-25 19:06:11 +01:00
Ray
65cddc852e Reviewed comments 2026-01-25 19:06:08 +01:00
afe74c1c70 Refactor int to float missing parse (#5503)
* refactor int to float parse

* Reverting  as requested

---------

Co-authored-by: Maicon <maicon@thinkpad02.exads.com>
2026-01-24 21:53:22 +01:00
70a63f7c62 [web] Fix Emscripten's Closure compiler error: undeclared canvas variable (#5507)
* Fix Emscripten Closure compiler error: undeclared canvas variable

* Fix hardcoded canvas IDs in web targets
2026-01-24 21:21:43 +01:00
Ray
a33ae4a8ef Update raymath.h 2026-01-23 17:11:37 +01:00
b21d7f234b [raymath] QuaternionFromVector3ToVector3(), math is wrong (#5508)
* the math in QuaternionFromVector3ToVector3 is wrong

* fix styling
2026-01-23 17:08:10 +01:00
eda915232d Update miniaudio to v0.11.24 (#5506) 2026-01-23 14:13:17 +01:00
e16467e8b6 Clean up Matrix handling and rl* functions to follow convention (#5505)
- Use named fields in rlTranslatef and rlScalef instead of array literals
- Label implicit row-major to column-major transpose in MatrixToFloatV
- Update rlSetUniformMatrix to use rlMatrixToFloat convention
2026-01-23 13:53:57 +01:00
594f5429b2 [rcore] LoadDirectoryFilesEx(), count files if not recursive (#5496)
* LoadDirectoryFilesEx on not recursive loading count files

* Removed FilePathList.capacity

* Added security check in case of memory leak

* Fix stop loading paths early on recursive loading

* Fix count directories only if filter contains DIRECTORY_FILTER_TAG

* rlparser: update raylib_api.* by CI

* GetDirectoryFileCount() and GetDirectoryFileCountEx() made visible

* rlparser: update raylib_api.* by CI

* Added new file and directories filter tags

* Renamed `fileCount` in `ScanDirectoryFiles()` to `expectedFileCount`

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-23 13:48:26 +01:00
Ray
c610d228a2 Update text_inline_styling.c 2026-01-20 21:01:41 +01:00
Ray
29896a2403 REVIEWED: Some comments (Code Gardening) 2026-01-19 12:40:32 +01:00
Ray
a8c75f2bc5 Update models_first_person_maze.c 2026-01-17 20:15:48 +01:00
Ray
fbed591a6f Reviewed example 2026-01-17 20:15:45 +01:00
9621c3d395 Add QNX EGL2.0 Library configuration (#5499) 2026-01-16 09:42:15 +01:00
10b94b02ad Fix opengl interop single header library not having it's implementation loaded (#5498) 2026-01-15 23:30:13 +01:00
Ray
439448ad7c Update rcore.c 2026-01-15 10:43:08 +01:00
Ray
0df2fe981b REVIEWED: ExportFontAsCode() #5497 2026-01-15 10:42:58 +01:00
a938a7c97a chore: add GetAppDir for wasm returning root VFS (#5495) 2026-01-15 10:08:03 +01:00
026b7e808a fix drm resources leak (#5494) 2026-01-15 10:03:54 +01:00
Ray
4b74312860 Update ROADMAP.md 2026-01-13 20:03:30 +01:00
Ray
4be6815b3b Revert "fix zig build accessing env vars (#5490)"
This reverts commit cfb81e4a00.
2026-01-13 16:27:51 +01:00
Ray
533a17e283 Merge branch 'master' of https://github.com/raysan5/raylib 2026-01-13 16:27:30 +01:00
Ray
132151cf28 Revert "Update build.zig to work with 0.16 (#5487)"
This reverts commit 32e7732061.
2026-01-13 16:27:16 +01:00
cfb81e4a00 fix zig build accessing env vars (#5490) 2026-01-12 22:58:41 +01:00
Ray
644ff28f87 Update shaders_deferred_rendering.c 2026-01-12 13:36:40 +01:00
Ray
28b9411e9d REMOVED: RLGL_RENDER_TEXTURES_HINT, enabled by default and no complaints of anyone having issues #5479 2026-01-12 13:23:27 +01:00
Ray
0c33c603f4 REVIEWED: EXTERNAL_CONFIG_FLAGS usage, check moved to config.h
Due to `utils` module removal, `EXTERNAL_CONFIG_FLAGS` was not working, so the system was redesigned.
This change is independent of #4411
2026-01-12 13:04:38 +01:00
32e7732061 Update build.zig to work with 0.16 (#5487) 2026-01-11 23:43:38 +01:00
d7c38cfbe4 fix rglfw.c path in build.zig for bsd platforms (#5486) 2026-01-11 22:01:14 +01:00
Ray
4badbe2b17 REVIEWED: Variable scope #5485 2026-01-11 21:02:59 +01:00
Ray
51bdaa34fa Update raylib.vcxproj 2026-01-11 16:56:47 +01:00
Ray
483b26ef84 Update rexm.c 2026-01-11 01:04:32 +01:00
Ray
972d6f0775 REXM: Fix raylib building 2026-01-11 00:32:16 +01:00
Ray
d94ea00a97 Update raylib.sln 2026-01-11 00:27:24 +01:00
Ray
f2c8a9c085 Merge branch 'master' of https://github.com/raysan5/raylib 2026-01-10 12:20:37 +01:00
Ray
1606dca0cb Update CMakeLists.txt 2026-01-10 12:20:26 +01:00
21f026a484 rlparser: update raylib_api.* by CI 2026-01-10 11:13:29 +00:00
Ray
dd7a1948f1 WARNING: REDESIGN: REMOVED: utils module, functionality moved to rcore module: logging and file-system #4551
[utils] was created long time ago, when [rcore] contained all the platforms code, the purpose of the file was exposing basic filesystem functionality across modules and also logging mechanism but many things have changed since then and there is no need to keep using this module.

 - Logging system has been move to [rcore] module and macros are exposed through `config.h` to other modules
 - File system functionality has also been centralized in [rcore] module that along the years it was already adding more and more file-system functions, now they are all in the same module
 - Android specific code has been moved to `rcore_android.c`, it had no sense to have specific platform code in `utils`, [rcore] is responsible of all platform code.
2026-01-10 12:13:07 +01:00
Ray
2f6feb74d4 Update raylib.sln 2026-01-10 11:53:46 +01:00
Ray
c7de5c9d4b Updated examples VCXPROJ UUID, not correctly calculated by REXM 2026-01-10 11:53:29 +01:00
Ray
6833305826 REVIEWED: android_fopen() 2026-01-10 10:59:22 +01:00
8de88c71da fix: fall back on dirent filename when all route fails on Android (#5484) 2026-01-10 10:54:54 +01:00
5b0a799769 fix (#5482) 2026-01-09 23:09:06 +01:00
Ray
1284d68721 Update core_highdpi_testbed.png 2026-01-09 20:18:45 +01:00
Ray
a6dd2af9e9 Update rexm.c 2026-01-09 20:06:57 +01:00
Ray
11f7db2dd8 REXM: ADDED: core_keyboard_testbed 2026-01-09 20:06:53 +01:00
Ray
7218b674e5 REXM: Updated: textures_framebuffer_rendering 2026-01-09 20:05:46 +01:00
Ray
cfd5c3f2ab Update examples_list.txt 2026-01-09 20:02:29 +01:00
Ray
b365d23f49 Update examples_list.txt 2026-01-09 19:59:38 +01:00
Ray
4cf844b74e Update raylib.h 2026-01-09 19:55:31 +01:00
Ray
5cc42c1b80 Updated file name 2026-01-09 19:55:26 +01:00
16e6d325b9 [raudio] Fix freeing the wrong memory (#5481) 2026-01-08 22:04:09 +01:00
0bcf79ce28 [#5455] Fix for: Fix window width calculation by adding wOffset (#5480) 2026-01-08 17:26:56 +01:00
Ray
5398b8c9b0 Update rexm.c 2026-01-07 23:09:51 +01:00
Ray
c814625c00 Update models_first_person_maze.c 2026-01-07 22:40:28 +01:00
5e1f5d5b74 examples/models: optimize collision check in first_person_maze (#5478)
Limit collision detection to the player surrounding cells instead of
iterating the full cubicmap each frame.
2026-01-07 22:38:04 +01:00
Ray
229f82699b Reviewed change #5476 2026-01-07 22:36:40 +01:00
c256f146b4 added saving to memory buffer and SaveFileData for binary files (#5476) 2026-01-07 22:32:58 +01:00
Ray
23bc037c37 Revert change, trying to follow DRM implementation but not needed on Android #5477 2026-01-07 22:32:09 +01:00
c78ac65786 Don't require a M3d animation only file to have a mesh. There are valid use cases for animation only files that can be applied to N other meshes. (#5475) 2026-01-06 22:32:42 +01:00
Ray
3678c2d157 REMOVE: TRACELOGD(), hardly ever used 2026-01-05 20:47:25 +01:00
Ray
35fc8ece44 Update models_decals.c 2026-01-03 23:01:37 +01:00
af544c24b9 [rcore] Fix touch position automation event handling (#5470)
* fix touch position automation event handling

* Fix alignment of previousPosition comment in rcore.c
2026-01-03 22:57:22 +01:00
c4b11a30cd Fix DrawMeshInstanced breaking if instanceTransform is unused (#5469) 2026-01-03 22:52:04 +01:00
a44157c2a8 [example] Added textures_frame_buffer_rendering (#5468) 2026-01-03 22:41:52 +01:00
b00cbdaf49 Cleanup warnings in examples (#5467) 2026-01-03 22:38:51 +01:00
f67e70bb47 Fix typecast warnings in rcore (#5466) 2026-01-03 08:59:34 +01:00
Ray
9fe51a6144 Merge branch 'master' of https://github.com/raysan5/raylib 2026-01-02 18:43:37 +01:00
Ray
c92de5f108 REVIEWED: Comments about intrinsics support #5316 2026-01-02 18:43:28 +01:00
942f93db55 fix(build): do not use != assignment in Makefiles (#5464)
GNU Make 3.81 that ships with MacOSX does not understand '!= ...' assignment
so we use ':= $(shell ...)' instead which have the same behavior here.

Additionally, I have changed the use of 'type' to 'command -v'
because assigning the result of 'type' to variable named 'EMMAKE'
does not make much sense. I also reused this variable.

For more detailed information read the linked issue.

Fixes: https://github.com/raysan5/raylib/issues/5460
2026-01-02 18:36:22 +01:00
Ray
ca89934ed5 Update year to 2026 2026-01-02 13:53:20 +01:00
Ray
416af51a93 Update year to 2026 2026-01-02 13:40:15 +01:00
980e4d0ad3 Use the size of the texture as the V scale so repeatable textures work well (#5463) 2026-01-02 13:15:25 +01:00
c9a456e273 Add DenoRaylib550 binding to BINDINGS.md (#5462) 2026-01-02 13:14:25 +01:00
Ray
c07d075a63 REVIEWED: Security checks formatting and comments 2026-01-01 16:54:44 +01:00
5a3391fdce [rtext] Fix multiple security vulnerabilities in font loading (#5433, #5434, #5436) (#5450) 2026-01-01 16:35:12 +01:00
Ray
909f040dc5 Remove trailing spaces 2026-01-01 16:33:34 +01:00
eb4ad50d99 make sure that our up vector really is up in an axis before picking a world plane (#5459) 2025-12-31 23:52:08 +01:00
Ray
95f72b162b REVIEWED: TextReplace(), revert breaking change, needs to be reviewed again... -WIP- 2025-12-31 22:50:17 +01:00
Ray
cac02ab063 REXM: REVIEWED: Add new example to collection list at the end of its category, instead of adding it at the end of the file 2025-12-31 22:48:07 +01:00
Ray
ab1d9b3830 REXM: Check example exists (compilation worked) before trying to run it 2025-12-31 22:47:16 +01:00
Ray
f805e6cae8 REXM: Update Makefile.Web before trying to rebuild new example for web 2025-12-31 22:46:36 +01:00
Ray
83377a3488 Update examples_list.txt 2025-12-31 22:29:12 +01:00
Ray
2377506843 Update rcamera.h 2025-12-31 20:50:27 +01:00
0133a4e6c6 Make CameraMove up and right work with Z up cameras like the other functions do. (#5458) 2025-12-31 20:45:29 +01:00
Ray
c124f2552b REVIEWED: SIMD instrinsics must be explicitly enabled by developer, only SSE supported at the moment #5316 2025-12-31 11:22:26 +01:00
Ray
66755da4c8 REVIEWED: eglGetPlatformDisplay() usage 2025-12-31 11:08:17 +01:00
Ray
02cca28b5f REVIEWED: eglGetPlatformDisplay() usage 2025-12-31 11:08:10 +01:00
25ce6465d5 Added SSE to MatrixMultiply. (#5427) 2025-12-31 10:58:58 +01:00
4af95a3a84 Use eglGetPlatformDisplayEXT on DRM platform for Mali compatibility (#5446) 2025-12-31 10:33:17 +01:00
e534f14419 Fix window width calculation by adding wOffset (#5457) 2025-12-31 09:05:39 +01:00
Ray
9b183e0c5e REXM: Update examples and reports 2025-12-30 23:21:10 +01:00
Ray
8c83dc7d70 Merge branch 'master' of https://github.com/raysan5/raylib 2025-12-30 22:49:45 +01:00
Ray
0c3e10b262 REVIEWED: FileExists(), using macro 2025-12-30 22:49:43 +01:00
4054fc42f3 Remove stdio.h unused header (#5456) 2025-12-30 22:09:20 +01:00
Ray
695f353533 Update Makefile.Web 2025-12-30 22:07:23 +01:00
Ray
f260f5fdd0 Update Makefile 2025-12-30 22:06:18 +01:00
Ray
fa1d4eb7fa Update shapes_hilbert_curve.c 2025-12-30 22:06:05 +01:00
Ray
6e70dece56 Update minshell.html 2025-12-30 22:05:37 +01:00
Ray
ebf2f61425 Delete core_input_keyboard_gamepad_test.c 2025-12-30 22:03:36 +01:00
Ray
6dfaf9fe7e REVIEWED: example shapes_hilbert_curve #5454
Make it more didactic and dynamic, avoid global variables
2025-12-30 21:19:54 +01:00
7523738677 Add hilbert curve example (#5454) 2025-12-30 20:11:37 +01:00
Ray
2b48cf6793 Formating review 2025-12-29 13:06:05 +01:00
1c6f683161 [rcore][drm] Improved touch input handling and multitouch support, closes #4842 (#5447)
* Improved touch input handling and multitouch support in drm platform

* revert

* made some fixes for the touch issue in drm platform

* updated touch input handling by adding multitouch support

* improved how it handles the multitouch

* added cleanup

* Remove touch last update tracking to simplify touch input handling

* improved multitouch support by tracking touch positions and IDs for each slot

* Better touch input handling

* Increase maximum touch points from 8 to 10 and enhance touchscreen prioritization logic

* Refactor touch input handling to use slot index as ID for stability and simplify touch clearing logic

* Improve touch input handling by activating slot 0 based on mouse click or touch events

* touch event handling to use tracking ID for unique touch identification

* Add multitouch detection to PollMouseEvents for improved touch handling

* Fix conditional formatting in PollMouseEvents for clarity

* Refactor conditional statements in PollMouseEvents and InitPlatform for improved readability

* Fix formatting in PollMouseEvents for improved readability
2025-12-29 12:54:30 +01:00
00f42e4199 [rcore] [android] fixed gesture system not reporting GESTURE_NONE (#5452)
in android gesture system is not reporting GESTURE_NONE, specified in the issue https://github.com/raysan5/raylib/issues/5010 so, automatically GESTURE_SWIPE, TAP, DOUBLE_TAP, also will not be reported. in this commit it is fixed.
2025-12-29 12:50:12 +01:00
Ray
58d414bcf8 REVIEWED: InitPlatform(), code simplification 2025-12-29 12:39:40 +01:00
8f8346048c Add chicken scheme to BINDINGS.md (#5449)
* Add chicken scheme to BINDINGS.md

* Fix typo
2025-12-28 23:50:10 +01:00
Ray
eb3cc183cc REVIEWED: FIXED: Windows fullscreen, after breaking it due to X11/Wayland changes 2025-12-28 20:29:01 +01:00
Ray
a334a54eac Update rcore_desktop_glfw.c 2025-12-28 20:09:15 +01:00
Ray
890ca8d687 REVIEWED: GetWindowPosition(), return internal value 2025-12-28 20:04:44 +01:00
Ray
6450a48c75 Update core_highdpi_testbed.c 2025-12-28 20:03:51 +01:00
Ray
8a75439c25 REVIEWED: Fullscreen modes on Linux (X11 over XWayland)
It does not work as expected... :(
2025-12-28 19:51:04 +01:00
Ray
8871d7648d Update core_highdpi_testbed.c 2025-12-28 19:49:38 +01:00
Ray
4176c518c7 Update rcore_desktop_glfw.c 2025-12-28 18:40:44 +01:00
Ray
c0c8ee9dc8 Update rcore_desktop_glfw.c 2025-12-28 18:15:47 +01:00
Ray
11c248aa82 Update rcore_web.c 2025-12-28 16:20:43 +01:00
Ray
2cf8983e18 WARNING: REDESIGNED: Fullscreen modes, use current display resolution
Considering multi-monitor and multi-ppi configurations
Fullscreen-exclusive scales to available display resolution, ignoring content scaling
Windowed-borderless scales to available logical resolution considering HighDPI **if requested**
2025-12-28 16:11:42 +01:00
Ray
297dcc07b8 Update core_highdpi_testbed.c 2025-12-28 16:08:34 +01:00
Ray
8cfb99f275 Minor comment tweaks 2025-12-28 16:08:19 +01:00
Ray
1d8e011eee Update rcore_drm.c 2025-12-28 16:08:08 +01:00
Ray
37bc3f5012 REMOVED: SetupFramebuffer(), most platforms do not need it any more
Kept only for platforms that could potentially need it
2025-12-28 16:07:59 +01:00
Ray
da1a76604f REMOVED: CORE.Window.fullscreen, using available flag instead 2025-12-28 16:05:42 +01:00
Ray
05f5143603 Update README.md 2025-12-27 15:05:18 +01:00
Ray
e4491b40b5 Update README.md 2025-12-27 14:43:46 +01:00
Ray
538bf82037 Update README.md 2025-12-27 14:35:38 +01:00
84dfe6a4cf [rmodels] Fix glTF animation framerate calculation (#4472) (#5445)
- Changed GLTF_ANIMDELAY (17ms, ~58.82fps) to GLTF_FRAMERATE (60.0fps)
- Updated frameCount calculation: (animDuration * 60) instead of (animDuration * 1000 / 17)
- Updated time calculation: j / 60.0f instead of (j * 17) / 1000.0f

This fixes animation frame count misalignment when importing glTF models
exported at standard 60fps. Animations that were 27+ frames shorter than
expected on 1350-frame sequences will now import correctly.
2025-12-27 14:22:24 +01:00
Ray
25a54d87e6 Update rcore_desktop_win32.c 2025-12-26 21:09:53 +01:00
Ray
64bd27bd08 Update rcore_desktop_glfw.c 2025-12-26 20:49:03 +01:00
aee6734cff fix: set correct default axes for gamepads that are not connected (inside rcore_desktop_glfw.c) (#5444)
* fix: set correct default axes for gamepads that are not connected

`glfwGetGamepadState` will set all gamepad state variables to 0.0 if required gamepad is not connected, but `RecordAutomationEvent()` inside rcore.c expects trigger axes to be -1.0f when gamepad is not connected. Since SDL and RGFW return -1.0f in such case, this change is aligning it with them

* updated comment in rcore_desktop_glfw.c
2025-12-26 20:46:09 +01:00
5e14ac5a2e #5387 - Fix keyboard input detected as gamepad on some Android devices (#5439)
* [rcore][android] Fix keyboard input detected as gamepad on some devices (#5387)

* [core] Add keyboard vs gamepad input test example (#5387)
2025-12-26 20:42:32 +01:00
101502103a Fixed FLAG_IS_SET to check if all bits in the flag are set in the value (#5441) 2025-12-24 20:58:40 +01:00
Ray
20dd4641c8 REVIEWED: Potential security concerns while copying unbounded text data between strings
Note that issue has been reported by CodeQL static analysis system
2025-12-24 19:35:06 +01:00
Ray
fc843dc557 Create SECURITY.md 2025-12-24 19:21:43 +01:00
Ray
9103f6e055 ADDED: New platform backend for Web: Emscripten, not dependant on GLFW.js -WIP- 2025-12-24 18:58:20 +01:00
Ray
ced84333a9 Update rl_gputex.h 2025-12-24 18:02:24 +01:00
Ray
05f42aa119 Update core_highdpi_testbed.c 2025-12-24 18:02:04 +01:00
a1e84caa8c RGFW also requires RGBA8 images as window icons, as raylib already reports in raylib.h (#5431) 2025-12-24 09:04:41 +01:00
ddb827fb6f Fixed LoadCodepoints declaring a new local variable shadowing codpoints (#5430) 2025-12-24 08:59:51 +01:00
0a4583ca54 [rl_gputex.h] Possibly fixed the swizzling in rl_load_dds_from_memory() function (#5422)
* Possibly fixed the swizzling bug

* Removed examples, and generation.
2025-12-23 17:10:55 +01:00
6a701b2679 fix android SetWindowState (#5424) 2025-12-23 15:37:08 +01:00
Ray
aa2884bd78 Update rcore_desktop_glfw.c 2025-12-22 22:50:38 +01:00
Ray
f27f2d097f REVIEWED: HighDPI support on macOS (when requested by app)
Tested on two monitors with different DPI configuration, for HigDPI enabled and not, including window resizing (with framebuffer resizing if required). Verified mouse coordinates follow the requested screen size.
2025-12-22 22:48:08 +01:00
Ray
e4baf682ab Update rtext.c 2025-12-22 20:30:11 +01:00
Ray
8516750975 Remove internal function 2025-12-22 20:29:57 +01:00
3212becc91 Update BINDINGS.md (#5421) 2025-12-21 20:15:38 +01:00
Ray
b9446863d7 REXM: RENAMED: core_high_dpi --> core_highdpi_demo 2025-12-20 22:36:44 +01:00
Ray
13f9112d8c Update rcore_desktop_sdl.c 2025-12-19 01:16:34 +01:00
Ray
f16fb065ea Update rcore_template.c 2025-12-19 01:15:34 +01:00
Ray
66392fe0ae REVIEWED: rlGetPixelDataSize(), correct compressed data size calculation per blocks #5416 2025-12-19 00:06:44 +01:00
Ray
720dd22491 REVIEWED: rlLoadTexture(), un complete texture do to issue on mipmap loading #5416 2025-12-18 17:04:58 +01:00
Ray
ca578b8b08 Update raylib.sln 2025-12-18 17:03:53 +01:00
Ray
4b760091da REVIEWED: Window scaling with HighDPI on macOS #5059 2025-12-17 21:23:25 +01:00
Ray
6d562e5e87 REVIEWED: HiggDPI content scaling on changing monitors with different DPI #5335 #5356
Note that high-dpi awareness must be enabled by users and `CORE.Window.render` reports the scaled framebuffer size, while `CORE.Window.screen` reports the logical size.

`ToggleBorderlessWindow()` has also been reviewed to be consistent with scaling, if monitor physical display size is reported as 1920x1080 but there is a content scale of 1.5, then the borderless fullscreen window will be 1280x720, with the 1920x1080 framebuffer
2025-12-17 19:20:18 +01:00
Ray
7553e9d586 REVIEWED: Gamepads on latest SDL2 2.32.8 and SDL3 3.3.6 #5403 2025-12-16 19:36:01 +01:00
Ray
80ad96acc2 Fix #5413 2025-12-16 18:33:07 +01:00
Ray
7a5e8aa3a5 Update rcore_android.c 2025-12-16 18:30:33 +01:00
1c94e94873 [rcore] Implement FLAG_WINDOW_ALWAYS_RUN on Android (#5414) 2025-12-16 18:26:20 +01:00
33adda1983 fixed build errors with zig. now compatible with zig master 0.16.0-dev.1593+c13857e50. still backwards compatible with 0.15.1 (#5415) 2025-12-16 18:24:53 +01:00
Ray
f031b2f4f4 Alignment with other platform backends, avoid unneeded includes 2025-12-16 18:20:02 +01:00
Ray
1c7240a01d Revert "REVIEWED: Alignment with other platforms"
This reverts commit cf0d6fc664.
2025-12-16 18:18:42 +01:00
Ray
cf0d6fc664 REVIEWED: Alignment with other platforms 2025-12-15 20:44:28 +01:00
Ray
615fc36eeb Fix #5406 2025-12-15 18:56:14 +01:00
Ray
cbe31759ab Fix #5405 2025-12-15 18:52:27 +01:00
d74556d35c Modify text_words_alignment.c (#5411) 2025-12-15 18:49:40 +01:00
8d246fdaff Fix EXTERNAL_CONFIG_FLAGS being defined even when no custom config is used when building with zig (#5410) 2025-12-15 00:03:31 +01:00
Ray
a0fd5ab1d9 Update rmodels.c 2025-12-14 19:59:12 +01:00
Ray
9a337f3b3b ADDED: Support software renderer on Web, blitting framebuffer data directly to a 2d canvas
This improvement is just a prove of concept, at this moment `PLATFORM_WEB` is limited in terms of software rendering by `GLFW` that only allows creating a WebGL canvas context with `glfwCreateWindow()`.

We can skip that call but then some GLFW functionality is not available (windowing, inputs). The best solution is replacing GLFW completely by a pure Emscripten implementation for `PLATFORM_WEB`.
2025-12-14 19:52:18 +01:00
Ray
5025009860 REVIEWED: Make sure all variables are initialized on definition, prioritize one line per variable definitions 2025-12-14 19:45:28 +01:00
6f5cabf60c Fix misleading example text. (#5409) 2025-12-14 17:43:54 +01:00
Ray
c96669e123 REVIEWED: Webpage reference comments starting with REF:, more consistent with TODO: and NOTE: comments 2025-12-13 13:03:41 +01:00
Ray
9c04b1de82 REVIEWED: Store canvas name id at platform initialization
Useful to support multiple canvases running different wasm instances in same webpage
2025-12-13 11:58:04 +01:00
Ray
b465b4e2ea RENAMED: Variable names for consistency, textLength (length in bytes) vs textSize (measure in pixels) 2025-12-11 21:41:25 +01:00
Ray
2853b28d6d REVIEWED: Avoid program crash if GPU data is tried to be loaded before InitWindow() #4751
Following raylib design, a warning log message is shown and program can continue execution.
Some early return checks have been added on most  critical functions.
[rtext] Previous implementation checking `isGpuReady` cross-module variable is not needed any more, resulting in a more decoupled code, load failure is managed at rlgl level
2025-12-11 18:21:57 +01:00
8fa5f1fe2c [examples] Fixed shaders_game_of_life for web (#5399)
* [examples] Fixed `shaders_game_of_life` for web

* Fixed image loadig for rexm
2025-12-11 13:38:08 +01:00
6f7cd3a9ab [core] Camera2d comment updates (#5401)
* Make the comments on the camera 2d fields more clear about what space each one is in.

* rlparser: update raylib_api.* by CI

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-12-11 13:37:17 +01:00
ae438e804e rlparser: update raylib_api.* by CI 2025-12-11 12:00:15 +00:00
Ray
2a566544d4 ADDED: Multiply security checks to avoid crashes on wrongly provided string data #4751
- REVIEWED: Checking `NULL` input on functions getting `const char *text`, to avoid crashes
- REVIEWED: `strcpy()` usage, prioritize `strncpy()` with limited copy to buffer size
- REPLACED: `strlen()` by `TextLength()` on [rtext] module
- REVIEWED: Replaced some early returns (but keeping others, for easier code following)
2025-12-11 12:59:55 +01:00
Ray
71a35f661e Update rexm.c 2025-12-11 12:33:05 +01:00
Ray
2d8e346945 Update update_examples.yml 2025-12-10 19:14:28 +01:00
Ray
f3f02b3e17 REXM: examples validation and update 2025-12-10 19:06:41 +01:00
Ray
dad93abcf8 REXM: Ignore some warnings on GCC/Clang 2025-12-10 18:49:52 +01:00
Ray
5e8118daf2 Update shaders_game_of_life.c 2025-12-10 09:46:06 +01:00
Ray
bc2057345b REVIEWED: GetRandomValue(), explained the new approach to get more uniform random values range 2025-12-10 09:30:18 +01:00
f2a900a60d [rcore] Fix modulo bias in GetRandomValue() (#5392)
* Fix modulo bias in GetRandomValue(); implement rejection sampling for uniformity

* Replace do-while with for-loop in GetRandomValue rejection sampling
2025-12-10 09:23:40 +01:00
Ray
3adfde42f7 REVIEWED: rlLoadTeexture(), max mipmap levels to use #5400 2025-12-10 09:21:33 +01:00
Ray
91ac3cc707 FIX: LoadRandomSequence(), using GetRandomValue() #5393 2025-12-09 20:02:38 +01:00
Ray
19a1683641 REXM: Updated examples 2025-12-09 19:25:08 +01:00
be6007be93 fix: sha1 computation on messages longer than 31 bytes (#5397) 2025-12-09 19:18:43 +01:00
efeccfef61 [examples] Add textures_cellular_automata (#5395)
* [examples] Add `textures_cellular_automata`

* Comparison always true. Fixed

* Tabs to spaces
2025-12-09 19:14:16 +01:00
366300aafe [examples] Add shaders_game_of_life (#5394)
* [examples] Add `shaders_game_of_life`

* Declaration hides another variable same name
2025-12-09 19:13:05 +01:00
215ad78d5b Fix build.zig typos (#5390)
* fix small typo

* other small typos
2025-12-09 19:10:22 +01:00
Ray
8115b7e922 Update rmodels.c 2025-12-06 20:40:23 +01:00
fd8830948e fix newer NDK version compiling errors (#5389)
target already gets assigned by the clang macro it points to, overwriting it causes it to target linux instead of android, making it check for usr directories instead of the NDK's directories
2025-12-06 20:01:47 +01:00
Ray
f9899a7182 Reviewed code formating 2025-12-06 20:00:19 +01:00
561cc27403 [rModels] Support 16 bit vec3 values in gltf reader (#5388)
* Support 16 bit vec3 values coming from gltf

* Add support for 8 bit normals
2025-12-06 19:50:59 +01:00
983efae3e4 Expose RGFW to cmake (#5386)
i was wondering why that was missing
2025-12-03 22:55:54 +01:00
95c4efd7a3 Update comment on shapes_penrose_tile.c (#5384) 2025-12-03 16:56:41 +01:00
Ray
68befcc64f Update shapes_penrose_tile.c 2025-12-03 10:00:09 +01:00
b1f8cde329 [examples] Added: text_strings_management (#5379)
* new shapes example - penrose tile

* stack cleanup

* proper use of strnlen, strncat and strncpy

* typo correction

* update screenshot of shapes_penrose_tile example

* new example for strings management

* Improved structure for text_strings_management
2025-12-03 09:44:18 +01:00
Aly
78a81bf407 Fix ToggleBorderlessFullscreen() Not Hiding Taskbar (#5383)
* Use glfwSetWindowMonitor instead of Pos and Size GLFW functions

* Fix window not resetting properly when toggling out of fullscreen, formatting
2025-12-02 22:55:22 +01:00
944567651c replace sprintf with snprintf (#5382) 2025-12-02 22:49:55 +01:00
1bbc8682f4 Fixed some typos and mispellings (#5381)
Specifically "occured" -> "occurred"
2025-12-02 22:48:06 +01:00
Ray
ed5da45203 Update LICENSE.md #5380 2025-12-02 22:46:12 +01:00
Ray
d3addad9a7 REVIEWED: example: shapes_penrose_tile formating 2025-12-02 22:34:48 +01:00
Ray
d13314fe1c Update core_window_flags.c 2025-12-02 22:21:41 +01:00
3ba186f2c1 [examples] Added: shapes_penrose_tile (#5376)
* new shapes example - penrose tile

* stack cleanup

* proper use of strnlen, strncat and strncpy

* typo correction

* update screenshot of shapes_penrose_tile example
2025-12-01 12:57:45 +01:00
4d9df337a7 rlparser: update raylib_api.* by CI 2025-11-30 18:02:52 +00:00
Ray
4724f7cf1b REVIEWED: Comments for UpdateSound() specifying expected data format #5350 2025-11-30 19:02:38 +01:00
Ray
a568506265 REVIEWED: External libraries sdefl and sinfl to address #5367 2025-11-30 18:32:11 +01:00
6a048b7afe corrected visualstudio project (#5375) 2025-11-29 23:22:38 +01:00
Ray
ebce9fa97a Update rcore_memory.c 2025-11-29 20:01:44 +01:00
Ray
78661a4ee0 REXM: ADDED: shapes_ball_physics 2025-11-29 18:23:17 +01:00
Ray
18e1ec504f Updated example 2025-11-29 18:20:06 +01:00
9f567e6ee4 Example for creating balls with simple physics simulation (#5372)
* Example for creating balls with simple physics simulation

The goal of this example is to create several colored balls whose movement is simulated and which respond to the action of being grabbed and dragged using the mouse.

* renaming example

renaming example from physics_bouncing_balls to shapes_ball_physics
2025-11-29 18:11:15 +01:00
e273aaea1e [examples] text_inline_styling: make inline text and background colors respect base alpha (#5373)
* Added source alpha multiplier for text inline styling examples

* Added header description about base alpha multiplier
2025-11-29 18:10:15 +01:00
1ac1309b24 feat: add elle bindings (#5370) 2025-11-27 15:19:22 +01:00
Ray
c991f9e89f Merge branch 'master' of https://github.com/raysan5/raylib 2025-11-25 19:13:12 +01:00
Ray
8f3cabcf76 Update rcore.c 2025-11-25 19:13:08 +01:00
2b051afb29 [examples] shapes_kaleidoscope rewind, forward & reset buttons (#5369)
* [examples] rewind and forward lines drawing

* [examples] reset button

* [examples] update screenshot

* [examples] applied raylib convention
2025-11-25 19:10:56 +01:00
Ray
3d9129e3b4 Update rexm.rc 2025-11-25 12:15:23 +01:00
Ray
80ed6eadb8 REXM: RENAME: audio_fft_spectrum_visualizer -> audio_spectrum_visualizer 2025-11-25 12:15:14 +01:00
Ray
a7ce14ee95 Merge branch 'master' of https://github.com/raysan5/raylib 2025-11-24 15:39:08 +01:00
Ray
47a8b554bc **NEW**: PLATFORM_MEMORY backend
New platform backend for software rendering directly on RAM memory buffer
2025-11-24 15:38:58 +01:00
fc8049a039 rlparser: update raylib_api.* by CI 2025-11-24 14:37:49 +00:00
Ray
bd36610f91 Some formatting 2025-11-24 15:37:28 +01:00
Ray
7e3d6cbfa8 Update rcore.c 2025-11-23 23:16:32 +01:00
Ray
17dc2bb474 Update rcore.c 2025-11-23 22:58:15 +01:00
Ray
aaa893f668 Update rcore.c 2025-11-23 22:58:10 +01:00
Ray
e1b9857b14 Some TODOs and format reviews 2025-11-23 21:40:39 +01:00
Ray
cf5e84c3c4 Update models_skybox_rendering.c 2025-11-23 21:37:35 +01:00
Ray
f1719480e0 Minor format tweaks 2025-11-23 13:21:31 +01:00
Ray
84737a9fc1 Update CONVENTIONS.md 2025-11-22 20:25:42 +01:00
Ray
727a90c5d1 REVIEWED: Formatting to follow raylib conventions 2025-11-22 20:16:33 +01:00
Ray
6c3ef8d9b4 Remove trailing spaces 2025-11-22 20:15:50 +01:00
Ray
97707d7a6b Merge branch 'master' of https://github.com/raysan5/raylib 2025-11-22 20:15:03 +01:00
Ray
12cce1766f Update textures_screen_buffer.c 2025-11-22 20:14:41 +01:00
Ray
dddc94dc7a Update examples_testing_web.md 2025-11-22 20:14:29 +01:00
178 changed files with 15053 additions and 4829 deletions

View File

@ -29,8 +29,9 @@ jobs:
shell: bash shell: bash
- name: Build and run rexm tool (requires GNU Makefile) - name: Build and run rexm tool (requires GNU Makefile)
# "rexm update" validates and updates all required examples in raylib and even raylib.com repos, # "rexm validate" validates examples collection, looking for inconsistencies, it does not rebuild examples
# note that it calls examples/Makefile.Web internally, so it requires [make] tool available # "rexm update" validates and updates all examples with inconsistencies, pushing fixes to raylib and raylib.com repos
# note that rexm calls examples/Makefile.Web internally, so it requires [make] tool available
run: | run: |
sudo apt-get update && sudo apt-get install -y libopengl0 libglu1-mesa libx11-dev libxrandr-dev libxcursor-dev libxi-dev libxinerama-dev libgl1-mesa-dev libglu1-mesa-dev sudo apt-get update && sudo apt-get install -y libopengl0 libglu1-mesa libx11-dev libxrandr-dev libxcursor-dev libxi-dev libxinerama-dev libgl1-mesa-dev libglu1-mesa-dev
cd "${{ github.workspace }}/src" cd "${{ github.workspace }}/src"
@ -47,7 +48,7 @@ jobs:
export REXM_EXAMPLES_COLLECTION_FILE_PATH="${{ github.workspace }}/examples/examples_list.txt" export REXM_EXAMPLES_COLLECTION_FILE_PATH="${{ github.workspace }}/examples/examples_list.txt"
export REXM_EXAMPLES_VS2022_SLN_FILE="${{ github.workspace }}/projects/VS2022/raylib.sln" export REXM_EXAMPLES_VS2022_SLN_FILE="${{ github.workspace }}/projects/VS2022/raylib.sln"
export EMSDK_PATH="${{ github.workspace }}/emsdk-cache/emsdk-main" export EMSDK_PATH="${{ github.workspace }}/emsdk-cache/emsdk-main"
./rexm update ./rexm validate
shell: bash shell: bash
- name: Commit changes to raylib repo (DISABLED) - name: Commit changes to raylib repo (DISABLED)

4
.gitignore vendored
View File

@ -58,6 +58,10 @@ packages/
*.h.pch *.h.pch
./*.obj ./*.obj
# Ignore SDL libs for testing
src/external/SDL2
src/external/SDL3
# Emscripten # Emscripten
emsdk emsdk

View File

@ -21,6 +21,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 | | [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 | | [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 | | [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 | | [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 | | [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 | | [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
@ -28,7 +29,9 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 | | [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 | | [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib | | [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib |
| [DenoRaylib550](https://github.com/JJLDonley/DenoRaylib550) | **5.5** | [Deno](https://deno.land) | MIT |
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [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) | 4.5 | [Factor](https://factorcode.org) | BSD | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD |
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT | | [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 | | [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
@ -75,6 +78,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib | | [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib | | [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) | **???** | | [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
| [ringraylib5](https://github.com/ring-lang/ring/tree/master/extensions/ringraylib5) | **5.0** | [Ring](https://ring-lang.github.io/) | **???** |
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 | | [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT | | [raylib-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-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |

View File

@ -565,7 +565,7 @@ Detailed changes:
[rtext] ADDED: SetTextLineSpacing() to define line breaks text drawing spacing by @raysan5 [rtext] ADDED: SetTextLineSpacing() to define line breaks text drawing spacing by @raysan5
[rtext] RENAMED: LoadFont*() parameter names for consistency and coherence by @raysan5 [rtext] RENAMED: LoadFont*() parameter names for consistency and coherence by @raysan5
[rtext] REVIEWED: GetCodepointCount(), ignore unused return value of GetCodepointNext by @ashn-dot-dev [rtext] REVIEWED: GetCodepointCount(), ignore unused return value of GetCodepointNext by @ashn-dot-dev
[rtext] REVIEWED: TextFormat() warn user if buffer overflow occured (#3399) by @Murlocohol [rtext] REVIEWED: TextFormat() warn user if buffer overflow occurred (#3399) by @Murlocohol
[rtext] REVIEWED: TextFormat(), added "..." for truncation (#3366) by @raysan5 [rtext] REVIEWED: TextFormat(), added "..." for truncation (#3366) by @raysan5
[rtext] REVIEWED: GetGlyphIndex() (#3000) by @raysan5 [rtext] REVIEWED: GetGlyphIndex() (#3000) by @raysan5
[rtext] REVIEWED: GetCodepointNext() to return default value by @chocolate42 [rtext] REVIEWED: GetCodepointNext() to return default value by @chocolate42

View File

@ -6,7 +6,7 @@ if(EMSCRIPTEN)
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default # When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
SET(PLATFORM Web CACHE STRING "Platform to build for.") SET(PLATFORM Web CACHE STRING "Platform to build for.")
endif() endif()
enum_option(PLATFORM "Desktop;Web;Android;Raspberry Pi;DRM;SDL" "Platform to build for.") enum_option(PLATFORM "Desktop;Web;Android;Raspberry Pi;DRM;SDL;RGFW" "Platform to build for.")
enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?") enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")

View File

@ -41,6 +41,7 @@ while (!WindowShouldClose())
} }
// Always use accumulators as `x++` instead of `++x`
for (int i = 0; i < NUM_VALUES; i++) printf("%i", i); for (int i = 0; i < NUM_VALUES; i++) printf("%i", i);
// Be careful with the switch formatting! // Be careful with the switch formatting!

View File

@ -1,4 +1,4 @@
Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
This software is provided "as-is", without any express or implied warranty. In no event 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. will the authors be held liable for any damages arising from the use of this software.

View File

@ -140,7 +140,7 @@ contributors
------------ ------------
<a href="https://github.com/raysan5/raylib/graphs/contributors"> <a href="https://github.com/raysan5/raylib/graphs/contributors">
<img src="https://contrib.rocks/image?repo=raysan5/raylib&max=500&columns=20&anon=1" /> <img src="https://contrib.rocks/image?repo=raysan5/raylib&max=800&columns=24&anon=0" />
</a> </a>
license license

View File

@ -15,13 +15,13 @@ _Current version of raylib is complete and functional but there is always room f
**raylib 5.x** **raylib 5.x**
- [ ] `rcore`: Support additional platforms: iOS, consoles? - [ ] `rcore`: Support additional platforms: iOS, consoles?
- [ ] `rcore_web`: Avoid GLFW dependency, functionality can be directly implemented using emscripten SDK - [x] `rcore_web`: Avoid GLFW dependency, functionality can be directly implemented using emscripten SDK
- [ ] `rlgl`: Review GLSL shaders naming conventions for consistency - [ ] `rlgl`: Review GLSL shaders naming conventions for consistency
- [ ] `textures`: Improve compressed textures support, loading and saving - [ ] `textures`: Improve compressed textures support, loading and saving
- [ ] `rmodels`: Improve 3d objects loading, specially animations (obj, gltf) - [ ] `rmodels`: Improve 3d objects loading, specially animations (obj, gltf)
- [ ] `raudio`: Implement miniaudio high-level provided features - [ ] `raudio`: Implement miniaudio high-level provided features
- [ ] `examples`: Review all examples, add more and better code explanations - [x] `examples`: Review all examples, add more and better code explanations
- [ ] Software renderer backend? Maybe using `Image` provided API - [x] Software renderer backend? Maybe using `Image` provided API
**raylib 4.x** **raylib 4.x**
- [x] Split core module into separate platforms? - [x] Split core module into separate platforms?

18
SECURITY.md Normal file
View File

@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
Most considerations of errors and defects can be handled using the project Issues and/or Discussions.
| Version | Supported |
| ------- | ------------------ |
| 6.0.x | :white_check_mark: |
| < 5.5 | :x: |
## Reporting a Vulnerability
Discovered vulnerability can be directly reported using the project Issues and/or Discussions.
_TODO: Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc._

View File

@ -106,9 +106,9 @@ const config_h_flags = outer: {
if (std.mem.startsWith(u8, line, "//")) continue; if (std.mem.startsWith(u8, line, "//")) continue;
if (std.mem.startsWith(u8, line, "#if")) continue; if (std.mem.startsWith(u8, line, "#if")) continue;
var flag = std.mem.trimLeft(u8, line, " \t"); // Trim whitespace var flag = std.mem.trimStart(u8, line, " \t"); // Trim whitespace
flag = flag["#define ".len - 1 ..]; // Remove #define flag = flag["#define ".len - 1 ..]; // Remove #define
flag = std.mem.trimLeft(u8, flag, " \t"); // Trim whitespace flag = std.mem.trimStart(u8, flag, " \t"); // Trim whitespace
flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space flag = flag[0 .. std.mem.indexOf(u8, flag, " ") orelse continue]; // Flag is only one word, so capture till space
flag = "-D" ++ flag; // Prepend with -D flag = "-D" ++ flag; // Prepend with -D
@ -155,9 +155,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
); );
} }
// Sets a flag indiciating the use of a custom `config.h`
try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
if (options.config.len > 0) { if (options.config.len > 0) {
// Sets a flag indicating the use of a custom `config.h`
try raylib_flags_arr.append(b.allocator, "-DEXTERNAL_CONFIG_FLAGS");
// Splits a space-separated list of config flags into multiple flags // Splits a space-separated list of config flags into multiple flags
// //
// Note: This means certain flags like `-x c++` won't be processed properly. // Note: This means certain flags like `-x c++` won't be processed properly.
@ -187,17 +187,17 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
try raylib_flags_arr.append(b.allocator, flag); try raylib_flags_arr.append(b.allocator, flag);
} }
} else { } else {
// Set default config if no custome config got set // Set default config if no custom config got set
try raylib_flags_arr.appendSlice(b.allocator, &config_h_flags); try raylib_flags_arr.appendSlice(b.allocator, &config_h_flags);
} }
// No GLFW required on PLATFORM_DRM // No GLFW required on PLATFORM_DRM
if (options.platform != .drm) { if (options.platform != .drm) {
raylib.addIncludePath(b.path("src/external/glfw/include")); raylib.root_module.addIncludePath(b.path("src/external/glfw/include"));
} }
var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2); var c_source_files: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 2);
c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c", "src/utils.c" }); c_source_files.appendSliceAssumeCapacity(&.{ "src/rcore.c" });
if (options.rshapes) { if (options.rshapes) {
try c_source_files.append(b.allocator, "src/rshapes.c"); try c_source_files.append(b.allocator, "src/rshapes.c");
@ -224,7 +224,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), ""); raylib.root_module.addCMacro(options.opengl_version.toCMacroStr(), "");
} }
raylib.addIncludePath(b.path("src/platforms")); raylib.root_module.addIncludePath(b.path("src/platforms"));
switch (target.result.os.tag) { switch (target.result.os.tag) {
.windows => { .windows => {
switch (options.platform) { switch (options.platform) {
@ -348,7 +348,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
} }
}, },
.freebsd, .openbsd, .netbsd, .dragonfly => { .freebsd, .openbsd, .netbsd, .dragonfly => {
try c_source_files.append(b.allocator, "rglfw.c"); try c_source_files.append(b.allocator, "src/rglfw.c");
raylib.root_module.linkSystemLibrary("GL", .{}); raylib.root_module.linkSystemLibrary("GL", .{});
raylib.root_module.linkSystemLibrary("rt", .{}); raylib.root_module.linkSystemLibrary("rt", .{});
raylib.root_module.linkSystemLibrary("dl", .{}); raylib.root_module.linkSystemLibrary("dl", .{});
@ -438,7 +438,7 @@ pub const Options = struct {
pub fn getOptions(b: *std.Build) Options { pub fn getOptions(b: *std.Build) Options {
return .{ return .{
.platform = b.option(PlatformBackend, "platform", "Choose the platform backedn for desktop target") orelse defaults.platform, .platform = b.option(PlatformBackend, "platform", "Choose the platform backend for desktop target") orelse defaults.platform,
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio, .raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels, .rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext, .rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,

View File

@ -27,6 +27,12 @@ if (${PLATFORM} MATCHES "Desktop")
add_definitions(-D_CRT_SECURE_NO_WARNINGS) add_definitions(-D_CRT_SECURE_NO_WARNINGS)
find_package(OpenGL QUIET) find_package(OpenGL QUIET)
set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm) set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm)
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "QNX")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
find_library(GLESV2 GLESv2)
find_library(EGL EGL)
set(LIBS_PUBLIC m)
set(LIBS_PRIVATE ${GLESV2} ${EGL} atomic pthread dl)
elseif (UNIX) elseif (UNIX)
find_library(pthread NAMES pthread) find_library(pthread NAMES pthread)
find_package(OpenGL QUIET) find_package(OpenGL QUIET)
@ -141,6 +147,8 @@ elseif ("${PLATFORM}" MATCHES "SDL")
add_compile_definitions(USING_SDL2_PACKAGE) add_compile_definitions(USING_SDL2_PACKAGE)
endif() endif()
endif() endif()
elseif ("${PLATFORM}" MATCHES "RGFW")
set(PLATFORM_CPP "PLATFORM_DESKTOP_RGFW")
endif () endif ()
if (NOT ${OPENGL_VERSION} MATCHES "OFF") if (NOT ${OPENGL_VERSION} MATCHES "OFF")

View File

@ -30,7 +30,7 @@
# > PLATFORM_ANDROID: # > PLATFORM_ANDROID:
# - Android (ARM, ARM64) # - Android (ARM, ARM64)
# #
# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) # Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
# #
# This software is provided "as-is", without any express or implied warranty. In no event # 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. # will the authors be held liable for any damages arising from the use of this software.
@ -205,15 +205,17 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
endif endif
endif endif
ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
MAKE = mingw32-make ifeq ($(PLATFORM_OS),WINDOWS)
MAKE = mingw32-make
endif
endif endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
ifeq ($(OS),Windows_NT) ifeq ($(PLATFORM_OS),WINDOWS)
MAKE = mingw32-make MAKE = mingw32-make
else else
EMMAKE != type emmake EMMAKE := $(shell command -v emmake)
ifneq (, $(EMMAKE)) ifneq (, $(EMMAKE))
MAKE = emmake make MAKE = $(EMMAKE) make
else else
MAKE = mingw32-make MAKE = mingw32-make
endif endif
@ -531,7 +533,7 @@ CORE = \
core/core_delta_time \ core/core_delta_time \
core/core_directory_files \ core/core_directory_files \
core/core_drop_files \ core/core_drop_files \
core/core_high_dpi \ core/core_highdpi_demo \
core/core_highdpi_testbed \ core/core_highdpi_testbed \
core/core_input_actions \ core/core_input_actions \
core/core_input_gamepad \ core/core_input_gamepad \
@ -542,6 +544,7 @@ CORE = \
core/core_input_mouse_wheel \ core/core_input_mouse_wheel \
core/core_input_multitouch \ core/core_input_multitouch \
core/core_input_virtual_controls \ core/core_input_virtual_controls \
core/core_keyboard_testbed \
core/core_monitor_detector \ core/core_monitor_detector \
core/core_random_sequence \ core/core_random_sequence \
core/core_random_values \ core/core_random_values \
@ -560,6 +563,7 @@ CORE = \
core/core_world_screen core/core_world_screen
SHAPES = \ SHAPES = \
shapes/shapes_ball_physics \
shapes/shapes_basic_shapes \ shapes/shapes_basic_shapes \
shapes/shapes_bouncing_ball \ shapes/shapes_bouncing_ball \
shapes/shapes_bullet_hell \ shapes/shapes_bullet_hell \
@ -574,6 +578,7 @@ SHAPES = \
shapes/shapes_easings_box \ shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \ shapes/shapes_easings_rectangles \
shapes/shapes_following_eyes \ shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \ shapes/shapes_kaleidoscope \
shapes/shapes_lines_bezier \ shapes/shapes_lines_bezier \
shapes/shapes_lines_drawing \ shapes/shapes_lines_drawing \
@ -582,6 +587,7 @@ SHAPES = \
shapes/shapes_math_angle_rotation \ shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \ shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \ shapes/shapes_mouse_trail \
shapes/shapes_penrose_tile \
shapes/shapes_pie_chart \ shapes/shapes_pie_chart \
shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \ shapes/shapes_rectangle_scaling \
@ -601,7 +607,9 @@ TEXTURES = \
textures/textures_background_scrolling \ textures/textures_background_scrolling \
textures/textures_blend_modes \ textures/textures_blend_modes \
textures/textures_bunnymark \ textures/textures_bunnymark \
textures/textures_cellular_automata \
textures/textures_fog_of_war \ textures/textures_fog_of_war \
textures/textures_framebuffer_rendering \
textures/textures_gif_player \ textures/textures_gif_player \
textures/textures_image_channel \ textures/textures_image_channel \
textures/textures_image_drawing \ textures/textures_image_drawing \
@ -639,6 +647,7 @@ TEXT = \
text/text_input_box \ text/text_input_box \
text/text_rectangle_bounds \ text/text_rectangle_bounds \
text/text_sprite_fonts \ text/text_sprite_fonts \
text/text_strings_management \
text/text_unicode_emojis \ text/text_unicode_emojis \
text/text_unicode_ranges \ text/text_unicode_ranges \
text/text_words_alignment \ text/text_words_alignment \
@ -684,6 +693,7 @@ SHADERS = \
shaders/shaders_depth_writing \ shaders/shaders_depth_writing \
shaders/shaders_eratosthenes_sieve \ shaders/shaders_eratosthenes_sieve \
shaders/shaders_fog_rendering \ shaders/shaders_fog_rendering \
shaders/shaders_game_of_life \
shaders/shaders_hot_reloading \ shaders/shaders_hot_reloading \
shaders/shaders_hybrid_rendering \ shaders/shaders_hybrid_rendering \
shaders/shaders_julia_set \ shaders/shaders_julia_set \
@ -708,7 +718,6 @@ SHADERS = \
shaders/shaders_vertex_displacement shaders/shaders_vertex_displacement
AUDIO = \ AUDIO = \
audio/audio_fft_spectrum_visualizer \
audio/audio_mixed_processor \ audio/audio_mixed_processor \
audio/audio_module_playing \ audio/audio_module_playing \
audio/audio_music_stream \ audio/audio_music_stream \
@ -716,6 +725,7 @@ AUDIO = \
audio/audio_sound_loading \ audio/audio_sound_loading \
audio/audio_sound_multi \ audio/audio_sound_multi \
audio/audio_sound_positioning \ audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
audio/audio_stream_effects audio/audio_stream_effects
OTHERS = \ OTHERS = \

View File

@ -130,7 +130,7 @@ ifeq ($(ANDROID_ARCH),ARM)
CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
endif endif
ifeq ($(ANDROID_ARCH),ARM64) ifeq ($(ANDROID_ARCH),ARM64)
CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 CFLAGS = -std=c99 -mfix-cortex-a53-835769
endif endif
# Compilation functions attributes options # Compilation functions attributes options
CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC

View File

@ -30,7 +30,7 @@
# > PLATFORM_ANDROID: # > PLATFORM_ANDROID:
# - Android (ARM, ARM64) # - Android (ARM, ARM64)
# #
# Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) # Copyright (c) 2013-2026 Ramon Santamaria (@raysan5)
# #
# This software is provided "as-is", without any express or implied warranty. In no event # 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. # will the authors be held liable for any damages arising from the use of this software.
@ -208,12 +208,12 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
MAKE = mingw32-make MAKE = mingw32-make
endif endif
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
ifeq ($(OS),Windows_NT) ifeq ($(PLATFORM_OS),WINDOWS)
MAKE = mingw32-make MAKE = mingw32-make
else else
EMMAKE != type emmake EMMAKE := $(shell command -v emmake)
ifneq (, $(EMMAKE)) ifneq (, $(EMMAKE))
MAKE = emmake make MAKE = $(EMMAKE) make
else else
MAKE = mingw32-make MAKE = mingw32-make
endif endif
@ -519,7 +519,7 @@ CORE = \
core/core_delta_time \ core/core_delta_time \
core/core_directory_files \ core/core_directory_files \
core/core_drop_files \ core/core_drop_files \
core/core_high_dpi \ core/core_highdpi_demo \
core/core_highdpi_testbed \ core/core_highdpi_testbed \
core/core_input_actions \ core/core_input_actions \
core/core_input_gamepad \ core/core_input_gamepad \
@ -530,6 +530,7 @@ CORE = \
core/core_input_mouse_wheel \ core/core_input_mouse_wheel \
core/core_input_multitouch \ core/core_input_multitouch \
core/core_input_virtual_controls \ core/core_input_virtual_controls \
core/core_keyboard_testbed \
core/core_monitor_detector \ core/core_monitor_detector \
core/core_random_sequence \ core/core_random_sequence \
core/core_random_values \ core/core_random_values \
@ -548,6 +549,7 @@ CORE = \
core/core_world_screen core/core_world_screen
SHAPES = \ SHAPES = \
shapes/shapes_ball_physics \
shapes/shapes_basic_shapes \ shapes/shapes_basic_shapes \
shapes/shapes_bouncing_ball \ shapes/shapes_bouncing_ball \
shapes/shapes_bullet_hell \ shapes/shapes_bullet_hell \
@ -562,6 +564,7 @@ SHAPES = \
shapes/shapes_easings_box \ shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \ shapes/shapes_easings_rectangles \
shapes/shapes_following_eyes \ shapes/shapes_following_eyes \
shapes/shapes_hilbert_curve \
shapes/shapes_kaleidoscope \ shapes/shapes_kaleidoscope \
shapes/shapes_lines_bezier \ shapes/shapes_lines_bezier \
shapes/shapes_lines_drawing \ shapes/shapes_lines_drawing \
@ -570,6 +573,7 @@ SHAPES = \
shapes/shapes_math_angle_rotation \ shapes/shapes_math_angle_rotation \
shapes/shapes_math_sine_cosine \ shapes/shapes_math_sine_cosine \
shapes/shapes_mouse_trail \ shapes/shapes_mouse_trail \
shapes/shapes_penrose_tile \
shapes/shapes_pie_chart \ shapes/shapes_pie_chart \
shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \ shapes/shapes_rectangle_scaling \
@ -589,7 +593,9 @@ TEXTURES = \
textures/textures_background_scrolling \ textures/textures_background_scrolling \
textures/textures_blend_modes \ textures/textures_blend_modes \
textures/textures_bunnymark \ textures/textures_bunnymark \
textures/textures_cellular_automata \
textures/textures_fog_of_war \ textures/textures_fog_of_war \
textures/textures_framebuffer_rendering \
textures/textures_gif_player \ textures/textures_gif_player \
textures/textures_image_channel \ textures/textures_image_channel \
textures/textures_image_drawing \ textures/textures_image_drawing \
@ -627,6 +633,7 @@ TEXT = \
text/text_input_box \ text/text_input_box \
text/text_rectangle_bounds \ text/text_rectangle_bounds \
text/text_sprite_fonts \ text/text_sprite_fonts \
text/text_strings_management \
text/text_unicode_emojis \ text/text_unicode_emojis \
text/text_unicode_ranges \ text/text_unicode_ranges \
text/text_words_alignment \ text/text_words_alignment \
@ -672,6 +679,7 @@ SHADERS = \
shaders/shaders_depth_writing \ shaders/shaders_depth_writing \
shaders/shaders_eratosthenes_sieve \ shaders/shaders_eratosthenes_sieve \
shaders/shaders_fog_rendering \ shaders/shaders_fog_rendering \
shaders/shaders_game_of_life \
shaders/shaders_hot_reloading \ shaders/shaders_hot_reloading \
shaders/shaders_hybrid_rendering \ shaders/shaders_hybrid_rendering \
shaders/shaders_julia_set \ shaders/shaders_julia_set \
@ -696,7 +704,6 @@ SHADERS = \
shaders/shaders_vertex_displacement shaders/shaders_vertex_displacement
AUDIO = \ AUDIO = \
audio/audio_fft_spectrum_visualizer \
audio/audio_mixed_processor \ audio/audio_mixed_processor \
audio/audio_module_playing \ audio/audio_module_playing \
audio/audio_music_stream \ audio/audio_music_stream \
@ -704,6 +711,7 @@ AUDIO = \
audio/audio_sound_loading \ audio/audio_sound_loading \
audio/audio_sound_multi \ audio/audio_sound_multi \
audio/audio_sound_positioning \ audio/audio_sound_positioning \
audio/audio_spectrum_visualizer \
audio/audio_stream_effects audio/audio_stream_effects
# Default target entry # Default target entry
@ -778,7 +786,7 @@ core/core_directory_files: core/core_directory_files.c
core/core_drop_files: core/core_drop_files.c core/core_drop_files: core/core_drop_files.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_high_dpi: core/core_high_dpi.c core/core_highdpi_demo: core/core_highdpi_demo.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_highdpi_testbed: core/core_highdpi_testbed.c core/core_highdpi_testbed: core/core_highdpi_testbed.c
@ -813,6 +821,9 @@ core/core_input_multitouch: core/core_input_multitouch.c
core/core_input_virtual_controls: core/core_input_virtual_controls.c core/core_input_virtual_controls: core/core_input_virtual_controls.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_keyboard_testbed: core/core_keyboard_testbed.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_monitor_detector: core/core_monitor_detector.c core/core_monitor_detector: core/core_monitor_detector.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -864,6 +875,9 @@ core/core_world_screen: core/core_world_screen.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
# Compile SHAPES examples # Compile SHAPES examples
shapes/shapes_ball_physics: shapes/shapes_ball_physics.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_basic_shapes: shapes/shapes_basic_shapes.c shapes/shapes_basic_shapes: shapes/shapes_basic_shapes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -906,6 +920,9 @@ shapes/shapes_easings_rectangles: shapes/shapes_easings_rectangles.c
shapes/shapes_following_eyes: shapes/shapes_following_eyes.c shapes/shapes_following_eyes: shapes/shapes_following_eyes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_hilbert_curve: shapes/shapes_hilbert_curve.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
shapes/shapes_kaleidoscope: shapes/shapes_kaleidoscope.c shapes/shapes_kaleidoscope: shapes/shapes_kaleidoscope.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -930,6 +947,9 @@ shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c
shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(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 shapes/shapes_pie_chart: shapes/shapes_pie_chart.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@ -988,9 +1008,15 @@ textures/textures_bunnymark: textures/textures_bunnymark.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/raybunny.png@resources/raybunny.png --preload-file textures/resources/raybunny.png@resources/raybunny.png
textures/textures_cellular_automata: textures/textures_cellular_automata.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
textures/textures_fog_of_war: textures/textures_fog_of_war.c textures/textures_fog_of_war: textures/textures_fog_of_war.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
textures/textures_framebuffer_rendering: textures/textures_framebuffer_rendering.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
textures/textures_gif_player: textures/textures_gif_player.c textures/textures_gif_player: textures/textures_gif_player.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file textures/resources/scarfy_run.gif@resources/scarfy_run.gif --preload-file textures/resources/scarfy_run.gif@resources/scarfy_run.gif
@ -1139,6 +1165,9 @@ text/text_sprite_fonts: text/text_sprite_fonts.c
--preload-file text/resources/sprite_fonts/alpha_beta.png@resources/sprite_fonts/alpha_beta.png \ --preload-file text/resources/sprite_fonts/alpha_beta.png@resources/sprite_fonts/alpha_beta.png \
--preload-file text/resources/sprite_fonts/jupiter_crash.png@resources/sprite_fonts/jupiter_crash.png --preload-file text/resources/sprite_fonts/jupiter_crash.png@resources/sprite_fonts/jupiter_crash.png
text/text_strings_management: text/text_strings_management.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
text/text_unicode_emojis: text/text_unicode_emojis.c text/text_unicode_emojis: text/text_unicode_emojis.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file text/resources/dejavu.fnt@resources/dejavu.fnt \ --preload-file text/resources/dejavu.fnt@resources/dejavu.fnt \
@ -1347,6 +1376,19 @@ shaders/shaders_fog_rendering: shaders/shaders_fog_rendering.c
--preload-file shaders/resources/shaders/glsl100/lighting.vs@resources/shaders/glsl100/lighting.vs \ --preload-file shaders/resources/shaders/glsl100/lighting.vs@resources/shaders/glsl100/lighting.vs \
--preload-file shaders/resources/shaders/glsl100/fog.fs@resources/shaders/glsl100/fog.fs --preload-file shaders/resources/shaders/glsl100/fog.fs@resources/shaders/glsl100/fog.fs
shaders/shaders_game_of_life: shaders/shaders_game_of_life.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/game_of_life.fs@resources/shaders/glsl100/game_of_life.fs \
--preload-file shaders/resources/game_of_life/r_pentomino.png@resources/game_of_life/r_pentomino.png \
--preload-file shaders/resources/game_of_life/glider.png@resources/game_of_life/glider.png \
--preload-file shaders/resources/game_of_life/acorn.png@resources/game_of_life/acorn.png \
--preload-file shaders/resources/game_of_life/spaceships.png@resources/game_of_life/spaceships.png \
--preload-file shaders/resources/game_of_life/still_lifes.png@resources/game_of_life/still_lifes.png \
--preload-file shaders/resources/game_of_life/oscillators.png@resources/game_of_life/oscillators.png \
--preload-file shaders/resources/game_of_life/puffer_train.png@resources/game_of_life/puffer_train.png \
--preload-file shaders/resources/game_of_life/glider_gun.png@resources/game_of_life/glider_gun.png \
--preload-file shaders/resources/game_of_life/breeder.png@resources/game_of_life/breeder.png
shaders/shaders_hot_reloading: shaders/shaders_hot_reloading.c shaders/shaders_hot_reloading: shaders/shaders_hot_reloading.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/reload.fs@resources/shaders/glsl100/reload.fs --preload-file shaders/resources/shaders/glsl100/reload.fs@resources/shaders/glsl100/reload.fs
@ -1471,10 +1513,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 --preload-file shaders/resources/shaders/glsl100/vertex_displacement.fs@resources/shaders/glsl100/vertex_displacement.fs
# Compile AUDIO examples # Compile AUDIO examples
audio/audio_fft_spectrum_visualizer: audio/audio_fft_spectrum_visualizer.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3
audio/audio_mixed_processor: audio/audio_mixed_processor.c audio/audio_mixed_processor: audio/audio_mixed_processor.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3 \ --preload-file audio/resources/country.mp3@resources/country.mp3 \
@ -1503,6 +1541,11 @@ audio/audio_sound_positioning: audio/audio_sound_positioning.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/coin.wav@resources/coin.wav --preload-file audio/resources/coin.wav@resources/coin.wav
audio/audio_spectrum_visualizer: audio/audio_spectrum_visualizer.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/shaders/glsl100/fft.fs@resources/shaders/glsl100/fft.fs \
--preload-file audio/resources/country.mp3@resources/country.mp3
audio/audio_stream_effects: audio/audio_stream_effects.c audio/audio_stream_effects: audio/audio_stream_effects.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file audio/resources/country.mp3@resources/country.mp3 --preload-file audio/resources/country.mp3@resources/country.mp3

View File

@ -17,9 +17,9 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `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`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
## EXAMPLES COLLECTION [TOTAL: 200] ## EXAMPLES COLLECTION [TOTAL: 208]
### category: core [47] ### category: core [48]
Examples using raylib [core](../src/rcore.c) module platform functionality: window creation, inputs, drawing modes and system functionality. Examples using raylib [core](../src/rcore.c) module platform functionality: window creation, inputs, drawing modes and system functionality.
@ -61,7 +61,7 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) | | [core_smooth_pixelperfect](core/core_smooth_pixelperfect.c) | <img src="core/core_smooth_pixelperfect.png" alt="core_smooth_pixelperfect" width="80"> | ⭐⭐⭐☆ | 3.7 | 4.0 | [Giancamillo Alessandroni](https://github.com/NotManyIdeasDev) |
| [core_random_sequence](core/core_random_sequence.c) | <img src="core/core_random_sequence.png" alt="core_random_sequence" width="80"> | ⭐☆☆☆ | 5.0 | 5.0 | [Dalton Overmyer](https://github.com/REDl3east) | | [core_random_sequence](core/core_random_sequence.c) | <img src="core/core_random_sequence.png" alt="core_random_sequence" width="80"> | ⭐☆☆☆ | 5.0 | 5.0 | [Dalton Overmyer](https://github.com/REDl3east) |
| [core_automation_events](core/core_automation_events.c) | <img src="core/core_automation_events.png" alt="core_automation_events" width="80"> | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | | [core_automation_events](core/core_automation_events.c) | <img src="core/core_automation_events.png" alt="core_automation_events" width="80"> | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_high_dpi](core/core_high_dpi.c) | <img src="core/core_high_dpi.png" alt="core_high_dpi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) | | [core_highdpi_demo](core/core_highdpi_demo.c) | <img src="core/core_highdpi_demo.png" alt="core_highdpi_demo" width="80"> | ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
| [core_render_texture](core/core_render_texture.c) | <img src="core/core_render_texture.png" alt="core_render_texture" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_render_texture](core/core_render_texture.c) | <img src="core/core_render_texture.png" alt="core_render_texture" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_undo_redo](core/core_undo_redo.c) | <img src="core/core_undo_redo.png" alt="core_undo_redo" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_viewport_scaling](core/core_viewport_scaling.c) | <img src="core/core_viewport_scaling.png" alt="core_viewport_scaling" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) | | [core_viewport_scaling](core/core_viewport_scaling.c) | <img src="core/core_viewport_scaling.png" alt="core_viewport_scaling" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
@ -69,11 +69,12 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
| [core_directory_files](core/core_directory_files.c) | <img src="core/core_directory_files.png" alt="core_directory_files" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [core_directory_files](core/core_directory_files.c) | <img src="core/core_directory_files.png" alt="core_directory_files" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
| [core_highdpi_testbed](core/core_highdpi_testbed.c) | <img src="core/core_highdpi_testbed.png" alt="core_highdpi_testbed" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_highdpi_testbed](core/core_highdpi_testbed.c) | <img src="core/core_highdpi_testbed.png" alt="core_highdpi_testbed" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_screen_recording](core/core_screen_recording.c) | <img src="core/core_screen_recording.png" alt="core_screen_recording" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_screen_recording](core/core_screen_recording.c) | <img src="core/core_screen_recording.png" alt="core_screen_recording" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_clipboard_text](core/core_clipboard_text.c) | <img src="core/core_clipboard_text.png" alt="core_clipboard_text" width="80"> | ⭐☆☆ | 5.6-dev | 5.6-dev | [Ananth S](https://github.com/Ananth1839) | | [core_clipboard_text](core/core_clipboard_text.c) | <img src="core/core_clipboard_text.png" alt="core_clipboard_text" width="80"> | ⭐☆☆ | 5.6-dev | 5.6-dev | [Ananth S](https://github.com/Ananth1839) |
| [core_text_file_loading](core/core_text_file_loading.c) | <img src="core/core_text_file_loading.png" alt="core_text_file_loading" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) | | [core_text_file_loading](core/core_text_file_loading.c) | <img src="core/core_text_file_loading.png" alt="core_text_file_loading" width="80"> | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) |
| [core_compute_hash](core/core_compute_hash.c) | <img src="core/core_compute_hash.png" alt="core_compute_hash" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_compute_hash](core/core_compute_hash.c) | <img src="core/core_compute_hash.png" alt="core_compute_hash" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_keyboard_testbed](core/core_keyboard_testbed.c) | <img src="core/core_keyboard_testbed.png" alt="core_keyboard_testbed" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
### category: shapes [36] ### category: shapes [39]
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
@ -115,8 +116,11 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) | <img src="shapes/shapes_math_angle_rotation.png" alt="shapes_math_angle_rotation" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6 | [Kris](https://github.com/krispy-snacc) | | [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) | <img src="shapes/shapes_math_angle_rotation.png" alt="shapes_math_angle_rotation" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6 | [Kris](https://github.com/krispy-snacc) |
| [shapes_rlgl_color_wheel](shapes/shapes_rlgl_color_wheel.c) | <img src="shapes/shapes_rlgl_color_wheel.png" alt="shapes_rlgl_color_wheel" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | | [shapes_rlgl_color_wheel](shapes/shapes_rlgl_color_wheel.c) | <img src="shapes/shapes_rlgl_color_wheel.png" alt="shapes_rlgl_color_wheel" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
| [shapes_rlgl_triangle](shapes/shapes_rlgl_triangle.c) | <img src="shapes/shapes_rlgl_triangle.png" alt="shapes_rlgl_triangle" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | | [shapes_rlgl_triangle](shapes/shapes_rlgl_triangle.c) | <img src="shapes/shapes_rlgl_triangle.png" alt="shapes_rlgl_triangle" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
| [shapes_ball_physics](shapes/shapes_ball_physics.c) | <img src="shapes/shapes_ball_physics.png" alt="shapes_ball_physics" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) | <img src="shapes/shapes_penrose_tile.png" alt="shapes_penrose_tile" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 5.6-dev | [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) |
### category: textures [28] ### category: textures [30]
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module. Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
@ -150,8 +154,10 @@ Examples using raylib textures functionality, including image/textures loading/g
| [textures_screen_buffer](textures/textures_screen_buffer.c) | <img src="textures/textures_screen_buffer.png" alt="textures_screen_buffer" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) | | [textures_screen_buffer](textures/textures_screen_buffer.c) | <img src="textures/textures_screen_buffer.png" alt="textures_screen_buffer" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Agnis Aldiņš](https://github.com/nezvers) |
| [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) | | [textures_textured_curve](textures/textures_textured_curve.c) | <img src="textures/textures_textured_curve.png" alt="textures_textured_curve" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) |
| [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 5.6-dev | 6.0 | [Robin](https://github.com/RobinsAviary) | | [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 5.6-dev | 6.0 | [Robin](https://github.com/RobinsAviary) |
| [textures_cellular_automata](textures/textures_cellular_automata.c) | <img src="textures/textures_cellular_automata.png" alt="textures_cellular_automata" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
| [textures_framebuffer_rendering](textures/textures_framebuffer_rendering.c) | <img src="textures/textures_framebuffer_rendering.png" alt="textures_framebuffer_rendering" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jack Boakes](https://github.com/jackboakes) |
### category: text [15] ### category: text [16]
Examples using raylib text functionality, including sprite fonts loading/generation and text drawing, provided by raylib [text](../src/rtext.c) module. Examples using raylib text functionality, including sprite fonts loading/generation and text drawing, provided by raylib [text](../src/rtext.c) module.
@ -172,6 +178,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_codepoints_loading](text/text_codepoints_loading.c) | <img src="text/text_codepoints_loading.png" alt="text_codepoints_loading" width="80"> | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | | [text_codepoints_loading](text/text_codepoints_loading.c) | <img src="text/text_codepoints_loading.png" alt="text_codepoints_loading" width="80"> | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
| [text_inline_styling](text/text_inline_styling.c) | <img src="text/text_inline_styling.png" alt="text_inline_styling" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) | | [text_inline_styling](text/text_inline_styling.c) | <img src="text/text_inline_styling.png" alt="text_inline_styling" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) |
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [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"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [David Buzatto](https://github.com/davidbuzatto) |
### category: models [27] ### category: models [27]
@ -207,7 +214,7 @@ Examples using raylib models functionality, including models loading/generation
| [models_decals](models/models_decals.c) | <img src="models/models_decals.png" alt="models_decals" width="80"> | ⭐⭐⭐⭐️ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [models_decals](models/models_decals.c) | <img src="models/models_decals.png" alt="models_decals" width="80"> | ⭐⭐⭐⭐️ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) |
| [models_directional_billboard](models/models_directional_billboard.c) | <img src="models/models_directional_billboard.png" alt="models_directional_billboard" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) | | [models_directional_billboard](models/models_directional_billboard.c) | <img src="models/models_directional_billboard.png" alt="models_directional_billboard" width="80"> | ⭐⭐☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) |
### category: shaders [32] ### category: shaders [33]
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.c) module. 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.c) module.
@ -245,6 +252,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete
| [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | <img src="shaders/shaders_lightmap_rendering.png" alt="shaders_lightmap_rendering" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) | | [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | <img src="shaders/shaders_lightmap_rendering.png" alt="shaders_lightmap_rendering" width="80"> | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) |
| [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) | | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | <img src="shaders/shaders_rounded_rectangle.png" alt="shaders_rounded_rectangle" width="80"> | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) |
| [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | <img src="shaders/shaders_depth_rendering.png" alt="shaders_depth_rendering" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) | | [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | <img src="shaders/shaders_depth_rendering.png" alt="shaders_depth_rendering" width="80"> | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) |
| [shaders_game_of_life](shaders/shaders_game_of_life.c) | <img src="shaders/shaders_game_of_life.png" alt="shaders_game_of_life" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
### category: audio [9] ### category: audio [9]
@ -260,7 +268,7 @@ Examples using raylib audio functionality, including sound/music loading and pla
| [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_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_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) | | [audio_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_fft_spectrum_visualizer](audio/audio_fft_spectrum_visualizer.c) | <img src="audio/audio_fft_spectrum_visualizer.png" alt="audio_fft_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 5.6-dev | [IANN](https://github.com/meisei4) | | [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 5.6-dev | [IANN](https://github.com/meisei4) |
### category: others [6] ### category: others [6]
@ -276,4 +284,4 @@ Examples showing raylib misc functionality that does not fit in other categories
| [web_basic_window](others/web_basic_window.c) | <img src="others/web_basic_window.png" alt="web_basic_window" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [web_basic_window](others/web_basic_window.c) | <img src="others/web_basic_window.png" alt="web_basic_window" width="80"> | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
Some example missing? As always, contributions are welcome, feel free to send new examples! 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! Here is an [examples template](examples_template.c) with instructions to start with!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -35,10 +35,10 @@ int main(void)
float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f] float timePlayed = 0.0f; // Time played normalized [0.0f..1.0f]
bool pause = false; // Music playing paused bool pause = false; // Music playing paused
float pan = 0.0f; // Default audio pan center [-1.0f..1.0f] float pan = 0.0f; // Default audio pan center [-1.0f..1.0f]
SetMusicPan(music, pan); SetMusicPan(music, pan);
float volume = 0.8f; // Default audio volume [0.0f..1.0f] float volume = 0.8f; // Default audio volume [0.0f..1.0f]
SetMusicVolume(music, volume); SetMusicVolume(music, volume);
@ -67,29 +67,29 @@ int main(void)
if (pause) PauseMusicStream(music); if (pause) PauseMusicStream(music);
else ResumeMusicStream(music); else ResumeMusicStream(music);
} }
// Set audio pan // Set audio pan
if (IsKeyDown(KEY_LEFT)) if (IsKeyDown(KEY_LEFT))
{ {
pan -= 0.05f; pan -= 0.05f;
if (pan < -1.0f) pan = -1.0f; if (pan < -1.0f) pan = -1.0f;
SetMusicPan(music, pan); SetMusicPan(music, pan);
} }
else if (IsKeyDown(KEY_RIGHT)) else if (IsKeyDown(KEY_RIGHT))
{ {
pan += 0.05f; pan += 0.05f;
if (pan > 1.0f) pan = 1.0f; if (pan > 1.0f) pan = 1.0f;
SetMusicPan(music, pan); SetMusicPan(music, pan);
} }
// Set audio volume // Set audio volume
if (IsKeyDown(KEY_DOWN)) if (IsKeyDown(KEY_DOWN))
{ {
volume -= 0.05f; volume -= 0.05f;
if (volume < 0.0f) volume = 0.0f; if (volume < 0.0f) volume = 0.0f;
SetMusicVolume(music, volume); SetMusicVolume(music, volume);
} }
else if (IsKeyDown(KEY_UP)) else if (IsKeyDown(KEY_UP))
{ {
volume += 0.05f; volume += 0.05f;
if (volume > 1.0f) volume = 1.0f; if (volume > 1.0f) volume = 1.0f;
@ -109,11 +109,11 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY); DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY);
DrawText("LEFT-RIGHT for PAN CONTROL", 320, 74, 10, DARKBLUE); DrawText("LEFT-RIGHT for PAN CONTROL", 320, 74, 10, DARKBLUE);
DrawRectangle(300, 100, 200, 12, LIGHTGRAY); DrawRectangle(300, 100, 200, 12, LIGHTGRAY);
DrawRectangleLines(300, 100, 200, 12, GRAY); DrawRectangleLines(300, 100, 200, 12, GRAY);
DrawRectangle(300 + (pan + 1.0)/2.0f*200 - 5, 92, 10, 28, DARKGRAY); DrawRectangle((int)(300 + (pan + 1.0f)/2.0f*200 - 5), 92, 10, 28, DARKGRAY);
DrawRectangle(200, 200, 400, 12, LIGHTGRAY); DrawRectangle(200, 200, 400, 12, LIGHTGRAY);
DrawRectangle(200, 200, (int)(timePlayed*400.0f), 12, MAROON); DrawRectangle(200, 200, (int)(timePlayed*400.0f), 12, MAROON);
@ -121,11 +121,11 @@ int main(void)
DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY); DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY);
DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY); DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY);
DrawText("UP-DOWN for VOLUME CONTROL", 320, 334, 10, DARKGREEN); DrawText("UP-DOWN for VOLUME CONTROL", 320, 334, 10, DARKGREEN);
DrawRectangle(300, 360, 200, 12, LIGHTGRAY); DrawRectangle(300, 360, 200, 12, LIGHTGRAY);
DrawRectangleLines(300, 360, 200, 12, GRAY); DrawRectangleLines(300, 360, 200, 12, GRAY);
DrawRectangle(300 + volume*200 - 5, 352, 10, 28, DARKGRAY); DrawRectangle((int)(300 + volume*200 - 5), 352, 10, 28, DARKGRAY);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -166,7 +166,7 @@ int main(void)
memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short)); memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short));
// Update cursors and loop audio // Update cursors and loop audio
readCursor = (readCursor + writeLength) % waveLength; readCursor = (readCursor + writeLength)%waveLength;
writeCursor += writeLength; writeCursor += writeLength;
} }

View File

@ -95,7 +95,7 @@ int main(void)
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************************* /*******************************************************************************************
* *
* raylib [audio] example - fft spectrum visualizer * raylib [audio] example - spectrum visualizer
* *
* Example complexity rating: [] 3/4 * Example complexity rating: [] 3/4
* *
@ -78,7 +78,7 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [audio] example - fft spectrum visualizer"); InitWindow(screenWidth, screenHeight, "raylib [audio] example - spectrum visualizer");
Image fftImage = GenImageColor(BUFFER_SIZE, TEXTURE_HEIGHT, WHITE); Image fftImage = GenImageColor(BUFFER_SIZE, TEXTURE_HEIGHT, WHITE);
Texture2D fftTexture = LoadTextureFromImage(fftImage); Texture2D fftTexture = LoadTextureFromImage(fftImage);
@ -115,7 +115,7 @@ int main(void)
.tapbackPos = 0.01f .tapbackPos = 0.01f
}; };
size_t wavCursor = 0; int wavCursor = 0;
const short *wavPCM16 = wav.data; const short *wavPCM16 = wav.data;
short chunkSamples[AUDIO_STREAM_RING_BUFFER_SIZE] = { 0 }; short chunkSamples[AUDIO_STREAM_RING_BUFFER_SIZE] = { 0 };
@ -148,7 +148,7 @@ int main(void)
CaptureFrame(&fft, audioSamples); CaptureFrame(&fft, audioSamples);
RenderFrame(&fft, &fftImage); RenderFrame(&fft, &fftImage);
UpdateTexture(fftTexture, fftImage.data); UpdateTexture(fftTexture, fftImage.data);
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------
// Draw // Draw
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -269,7 +269,7 @@ static void CaptureFrame(FFTData *fftData, const float *audioSamples)
fftData->lastFftTime = GetTime(); fftData->lastFftTime = GetTime();
memcpy(fftData->fftHistory[fftData->historyPos], smoothedSpectrum, sizeof(smoothedSpectrum)); memcpy(fftData->fftHistory[fftData->historyPos], smoothedSpectrum, sizeof(smoothedSpectrum));
fftData->historyPos = (fftData->historyPos + 1) % fftData->fftHistoryLen; fftData->historyPos = (fftData->historyPos + 1)%fftData->fftHistoryLen;
} }
static void RenderFrame(const FFTData *fftData, Image *fftImage) static void RenderFrame(const FFTData *fftData, Image *fftImage)
@ -277,12 +277,9 @@ static void RenderFrame(const FFTData *fftData, Image *fftImage)
double framesSinceTapback = floor(fftData->tapbackPos/WINDOW_TIME); double framesSinceTapback = floor(fftData->tapbackPos/WINDOW_TIME);
framesSinceTapback = Clamp(framesSinceTapback, 0.0, fftData->fftHistoryLen - 1); framesSinceTapback = Clamp(framesSinceTapback, 0.0, fftData->fftHistoryLen - 1);
int historyPosition = (fftData->historyPos - 1 - (int)framesSinceTapback) % fftData->fftHistoryLen; int historyPosition = (fftData->historyPos - 1 - (int)framesSinceTapback)%fftData->fftHistoryLen;
if (historyPosition < 0) if (historyPosition < 0) historyPosition += fftData->fftHistoryLen;
historyPosition += fftData->fftHistoryLen;
const float *amplitude = fftData->fftHistory[historyPosition]; const float *amplitude = fftData->fftHistory[historyPosition];
for (int bin = 0; bin < BUFFER_SIZE; bin++) { for (int bin = 0; bin < BUFFER_SIZE; bin++) ImageDrawPixel(fftImage, bin, FFT_ROW, ColorFromNormalized((Vector4){ amplitude[bin], UNUSED_CHANNEL, UNUSED_CHANNEL, UNUSED_CHANNEL }));
ImageDrawPixel(fftImage, bin, FFT_ROW, ColorFromNormalized((Vector4){ amplitude[bin], UNUSED_CHANNEL, UNUSED_CHANNEL, UNUSED_CHANNEL }));
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -125,8 +125,8 @@ int main(void)
DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f)); DrawRectangle( 10, 10, 250, 113, Fade(SKYBLUE, 0.5f));
DrawRectangleLines( 10, 10, 250, 113, BLUE); DrawRectangleLines( 10, 10, 250, 113, BLUE);
DrawText("Free 2d camera controls:", 20, 20, 10, BLACK); DrawText("Free 2D camera controls:", 20, 20, 10, BLACK);
DrawText("- Right/Left to move Offset", 40, 40, 10, DARKGRAY); DrawText("- Right/Left to move player", 40, 40, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY); DrawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DARKGRAY);
DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY); DrawText("- A / S to Rotate", 40, 80, 10, DARKGRAY);
DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY); DrawText("- R to reset Zoom and Rotation", 40, 100, 10, DARKGRAY);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -226,10 +226,10 @@ void UpdateCameraCenterInsideMap(Camera2D *camera, Player *player, EnvItem *envI
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera); Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera);
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera); Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera);
if (max.x < width) camera->offset.x = width - (max.x - width/2); if (max.x < width) camera->offset.x = width - (max.x - (float)width/2);
if (max.y < height) camera->offset.y = height - (max.y - height/2); if (max.y < height) camera->offset.y = height - (max.y - (float)height/2);
if (min.x > 0) camera->offset.x = width/2 - min.x; if (min.x > 0) camera->offset.x = (float)width/2 - min.x;
if (min.y > 0) camera->offset.y = height/2 - min.y; if (min.y > 0) camera->offset.y = (float)height/2 - min.y;
} }
void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height) void UpdateCameraCenterSmoothFollow(Camera2D *camera, Player *player, EnvItem *envItems, int envItemsLength, float delta, int width, int height)

View File

@ -225,10 +225,10 @@ int main(void)
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, camera); Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, camera);
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, camera); Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, camera);
if (max.x < screenWidth) camera.offset.x = screenWidth - (max.x - screenWidth/2); if (max.x < screenWidth) camera.offset.x = screenWidth - (max.x - (float)screenWidth/2);
if (max.y < screenHeight) camera.offset.y = screenHeight - (max.y - screenHeight/2); if (max.y < screenHeight) camera.offset.y = screenHeight - (max.y - (float)screenHeight/2);
if (min.x > 0) camera.offset.x = screenWidth/2 - min.x; if (min.x > 0) camera.offset.x = (float)screenWidth/2 - min.x;
if (min.y > 0) camera.offset.y = screenHeight/2 - min.y; if (min.y > 0) camera.offset.y = (float)screenHeight/2 - min.y;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Events management // Events management

View File

@ -2,6 +2,8 @@
* *
* raylib [core] example - clipboard text * raylib [core] example - clipboard text
* *
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
* *
* Example contributed by Ananth S (@Ananth1839) and reviewed by Ramon Santamaria (@raysan5) * Example contributed by Ananth S (@Ananth1839) and reviewed by Ramon Santamaria (@raysan5)

View File

@ -1,6 +1,6 @@
/******************************************************************************************* /*******************************************************************************************
* *
* raylib [core] example - high dpi * raylib [core] example - highdpi demo
* *
* Example complexity rating: [] 2/4 * Example complexity rating: [] 2/4
* *
@ -33,7 +33,7 @@ int main(void)
const int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_WINDOW_HIGHDPI | FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - high dpi"); InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi demo");
SetWindowMinSize(450, 450); SetWindowMinSize(450, 450);
int logicalGridDescY = 120; int logicalGridDescY = 120;

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -27,9 +27,15 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI);
InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed"); InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed");
// TODO: Load resources / Initialize variables at this point Vector2 scaleDpi = GetWindowScaleDPI();
Vector2 mousePos = GetMousePosition();
int currentMonitor = GetCurrentMonitor();
Vector2 windowPos = GetWindowPosition();
int gridSpacing = 40; // Grid spacing in pixels
SetTargetFPS(60); SetTargetFPS(60);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -39,7 +45,13 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// TODO: Update variables / Implement example logic at this point mousePos = GetMousePosition();
currentMonitor = GetCurrentMonitor();
scaleDpi = GetWindowScaleDPI();
windowPos = GetWindowPosition();
if (IsKeyPressed(KEY_SPACE)) ToggleBorderlessWindowed();
if (IsKeyPressed(KEY_F)) ToggleFullscreen();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -48,11 +60,36 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
// TODO: Draw everything that requires to be drawn at this point // Draw grid
for (int h = 0; h < GetScreenHeight()/gridSpacing + 1; h++)
{
DrawText(TextFormat("%02i", h*gridSpacing), 4, h*gridSpacing - 4, 10, GRAY);
DrawLine(24, h*gridSpacing, GetScreenWidth(), h*gridSpacing, LIGHTGRAY);
}
for (int v = 0; v < GetScreenWidth()/gridSpacing + 1; v++)
{
DrawText(TextFormat("%02i", v*gridSpacing), v*gridSpacing - 10, 4, 10, GRAY);
DrawLine(v*gridSpacing, 20, v*gridSpacing, GetScreenHeight(), LIGHTGRAY);
}
DrawLineEx((Vector2){ 0, 0 }, (Vector2){ screenWidth, screenHeight }, 2.0f, RED); // Draw UI info
DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED); DrawText(TextFormat("CURRENT MONITOR: %i/%i (%ix%i)", currentMonitor + 1, GetMonitorCount(),
DrawText("example base code template", 260, 400, 20, LIGHTGRAY); GetMonitorWidth(currentMonitor), GetMonitorHeight(currentMonitor)), 50, 50, 20, DARKGRAY);
DrawText(TextFormat("WINDOW POSITION: %ix%i", (int)windowPos.x, (int)windowPos.y), 50, 90, 20, DARKGRAY);
DrawText(TextFormat("SCREEN SIZE: %ix%i", GetScreenWidth(), GetScreenHeight()), 50, 130, 20, DARKGRAY);
DrawText(TextFormat("RENDER SIZE: %ix%i", GetRenderWidth(), GetRenderHeight()), 50, 170, 20, DARKGRAY);
DrawText(TextFormat("SCALE FACTOR: %.1fx%.1f", scaleDpi.x, scaleDpi.y), 50, 210, 20, GRAY);
// Draw reference rectangles, top-left and bottom-right corners
DrawRectangle(0, 0, 30, 60, RED);
DrawRectangle(GetScreenWidth() - 30, GetScreenHeight() - 60, 30, 60, BLUE);
// Draw mouse position
DrawCircleV(GetMousePosition(), 20, MAROON);
DrawRectangle(mousePos.x - 25, mousePos.y, 50, 2, BLACK);
DrawRectangle(mousePos.x, mousePos.y - 25, 2, 50, BLACK);
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
(mousePos.y > GetScreenHeight() - 60)? mousePos.y - 46 : mousePos.y + 30, 20, BLACK);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -67,7 +67,7 @@ int main(void)
if (IsKeyPressed(KEY_RIGHT)) gamepad++; if (IsKeyPressed(KEY_RIGHT)) gamepad++;
Vector2 mousePosition = GetMousePosition(); Vector2 mousePosition = GetMousePosition();
vibrateButton = (Rectangle){ 10, 70 + 20*GetGamepadAxisCount(gamepad) + 20, 75, 24 }; vibrateButton = (Rectangle){ 10, 70.0f + 20*GetGamepadAxisCount(gamepad) + 20, 75, 24 };
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, vibrateButton)) SetGamepadVibration(gamepad, 1.0, 1.0, 1.0); if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, vibrateButton)) SetGamepadVibration(gamepad, 1.0, 1.0, 1.0);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -262,7 +262,7 @@ int main(void)
// Draw vibrate button // Draw vibrate button
DrawRectangleRec(vibrateButton, SKYBLUE); DrawRectangleRec(vibrateButton, SKYBLUE);
DrawText("VIBRATE", vibrateButton.x + 14, vibrateButton.y + 1, 10, DARKGRAY); DrawText("VIBRATE", (int)(vibrateButton.x + 14), (int)(vibrateButton.y + 1), 10, DARKGRAY);
if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED); if (GetGamepadButtonPressed() != GAMEPAD_BUTTON_UNKNOWN) DrawText(TextFormat("DETECTED BUTTON: %i", GetGamepadButtonPressed()), 10, 430, 10, RED);
else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY); else DrawText("DETECTED BUTTON: NONE", 10, 430, 10, GRAY);

View File

@ -202,7 +202,7 @@ int main(void)
DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK); DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK);
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle) // Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY)); for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1)%GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY));
Color logButton1Color, logButton2Color; Color logButton1Color, logButton2Color;
switch (logMode) switch (logMode)
{ {

View File

@ -46,7 +46,7 @@ int main(void)
// Clamp touch points available ( set the maximum touch points allowed ) // Clamp touch points available ( set the maximum touch points allowed )
if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS; if (tCount > MAX_TOUCH_POINTS) tCount = MAX_TOUCH_POINTS;
// Get touch points positions // Get touch points positions
for (int i = 0; i < tCount; ++i) touchPositions[i] = GetTouchPosition(i); for (int i = 0; i < tCount; i++) touchPositions[i] = GetTouchPosition(i);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -55,7 +55,7 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
for (int i = 0; i < tCount; ++i) for (int i = 0; i < tCount; i++)
{ {
// Make sure point is not (0, 0) as this means there is no touch for it // Make sure point is not (0, 0) as this means there is no touch for it
if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0)) if ((touchPositions[i].x > 0) && (touchPositions[i].y > 0))

View File

@ -0,0 +1,333 @@
/*******************************************************************************************
*
* raylib [core] example - keyboard testbed
*
* Example complexity rating: [★★☆☆] 2/4
*
* NOTE: raylib defined keys refer to ENG-US Keyboard layout,
* mapping to other layouts is up to the user
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* 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 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define KEY_REC_SPACING 4 // Space in pixels between key rectangles
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static const char *GetKeyText(int key);
static void GuiKeyboardKey(Rectangle bounds, int key);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard testbed");
SetExitKey(KEY_NULL); // Avoid exit on KEY_ESCAPE
// Keyboard line 01
int line01KeyWidths[15] = { 0 };
for (int i = 0; i < 15; i++) line01KeyWidths[i] = 45;
line01KeyWidths[13] = 62; // PRINTSCREEN
int line01Keys[15] = {
KEY_ESCAPE, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11,
KEY_F12, KEY_PRINT_SCREEN, KEY_PAUSE
};
// Keyboard line 02
int line02KeyWidths[15] = { 0 };
for (int i = 0; i < 15; i++) line02KeyWidths[i] = 45;
line02KeyWidths[0] = 25; // GRAVE
line02KeyWidths[13] = 82; // BACKSPACE
int line02Keys[15] = {
KEY_GRAVE, KEY_ONE, KEY_TWO, KEY_THREE, KEY_FOUR,
KEY_FIVE, KEY_SIX, KEY_SEVEN, KEY_EIGHT, KEY_NINE,
KEY_ZERO, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_DELETE };
// Keyboard line 03
int line03KeyWidths[15] = { 0 };
for (int i = 0; i < 15; i++) line03KeyWidths[i] = 45;
line03KeyWidths[0] = 50; // TAB
line03KeyWidths[13] = 57; // BACKSLASH
int line03Keys[15] = {
KEY_TAB, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y,
KEY_U, KEY_I, KEY_O, KEY_P, KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET, KEY_BACKSLASH, KEY_INSERT
};
// Keyboard line 04
int line04KeyWidths[14] = { 0 };
for (int i = 0; i < 14; i++) line04KeyWidths[i] = 45;
line04KeyWidths[0] = 68; // CAPS
line04KeyWidths[12] = 88; // ENTER
int line04Keys[14] = {
KEY_CAPS_LOCK, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G,
KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
KEY_APOSTROPHE, KEY_ENTER, KEY_PAGE_UP
};
// Keyboard line 05
int line05KeyWidths[14] = { 0 };
for (int i = 0; i < 14; i++) line05KeyWidths[i] = 45;
line05KeyWidths[0] = 80; // LSHIFT
line05KeyWidths[11] = 76; // RSHIFT
int line05Keys[14] = {
KEY_LEFT_SHIFT, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B,
KEY_N, KEY_M, KEY_COMMA, KEY_PERIOD, /*KEY_MINUS*/
KEY_SLASH, KEY_RIGHT_SHIFT, KEY_UP, KEY_PAGE_DOWN
};
// Keyboard line 06
int line06KeyWidths[11] = { 0 };
for (int i = 0; i < 11; i++) line06KeyWidths[i] = 45;
line06KeyWidths[0] = 80; // LCTRL
line06KeyWidths[3] = 208; // SPACE
line06KeyWidths[7] = 60; // RCTRL
int line06Keys[11] = {
KEY_LEFT_CONTROL, KEY_LEFT_SUPER, KEY_LEFT_ALT,
KEY_SPACE, KEY_RIGHT_ALT, 162, KEY_NULL,
KEY_RIGHT_CONTROL, KEY_LEFT, KEY_DOWN, KEY_RIGHT
};
Vector2 keyboardOffset = { 26, 80 };
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
int key = GetKeyPressed(); // Get pressed keycode
if (key > 0) TraceLog(LOG_INFO, "KEYBOARD TESTBED: KEY PRESSED: %d", key);
int ch = GetCharPressed(); // Get pressed char for text input, using OS mapping
if (ch > 0) TraceLog(LOG_INFO, "KEYBOARD TESTBED: CHAR PRESSED: %c (%d)", ch, ch);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("KEYBOARD LAYOUT: ENG-US", 26, 38, 20, LIGHTGRAY);
// Keyboard line 01 - 15 keys
// ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, IMP, CLOSE
for (int i = 0, recOffsetX = 0; i < 15; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y, line01KeyWidths[i], 30 }, line01Keys[i]);
recOffsetX += line01KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 02 - 15 keys
// `, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, -, =, BACKSPACE, DEL
for (int i = 0, recOffsetX = 0; i < 15; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + KEY_REC_SPACING, line02KeyWidths[i], 38 }, line02Keys[i]);
recOffsetX += line02KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 03 - 15 keys
// TAB, Q, W, E, R, T, Y, U, I, O, P, [, ], \, INS
for (int i = 0, recOffsetX = 0; i < 15; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38 + KEY_REC_SPACING*2, line03KeyWidths[i], 38 }, line03Keys[i]);
recOffsetX += line03KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 04 - 14 keys
// MAYUS, A, S, D, F, G, H, J, K, L, ;, ', ENTER, REPAG
for (int i = 0, recOffsetX = 0; i < 14; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38*2 + KEY_REC_SPACING*3, line04KeyWidths[i], 38 }, line04Keys[i]);
recOffsetX += line04KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 05 - 14 keys
// LSHIFT, Z, X, C, V, B, N, M, ,, ., /, RSHIFT, UP, AVPAG
for (int i = 0, recOffsetX = 0; i < 14; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38*3 + KEY_REC_SPACING*4, line05KeyWidths[i], 38 }, line05Keys[i]);
recOffsetX += line05KeyWidths[i] + KEY_REC_SPACING;
}
// Keyboard line 06 - 11 keys
// LCTRL, WIN, LALT, SPACE, ALTGR, \, FN, RCTRL, LEFT, DOWN, RIGHT
for (int i = 0, recOffsetX = 0; i < 11; i++)
{
GuiKeyboardKey((Rectangle){ keyboardOffset.x + recOffsetX, keyboardOffset.y + 30 + 38*4 + KEY_REC_SPACING*5, line06KeyWidths[i], 38 }, line06Keys[i]);
recOffsetX += line06KeyWidths[i] + KEY_REC_SPACING;
}
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Get keyboard keycode as text (US keyboard)
// NOTE: Mapping for other keyboard layouts can be done here
static const char *GetKeyText(int key)
{
switch (key)
{
case KEY_APOSTROPHE : return "'"; // Key: '
case KEY_COMMA : return ","; // Key: ,
case KEY_MINUS : return "-"; // Key: -
case KEY_PERIOD : return "."; // Key: .
case KEY_SLASH : return "/"; // Key: /
case KEY_ZERO : return "0"; // Key: 0
case KEY_ONE : return "1"; // Key: 1
case KEY_TWO : return "2"; // Key: 2
case KEY_THREE : return "3"; // Key: 3
case KEY_FOUR : return "4"; // Key: 4
case KEY_FIVE : return "5"; // Key: 5
case KEY_SIX : return "6"; // Key: 6
case KEY_SEVEN : return "7"; // Key: 7
case KEY_EIGHT : return "8"; // Key: 8
case KEY_NINE : return "9"; // Key: 9
case KEY_SEMICOLON : return ";"; // Key: ;
case KEY_EQUAL : return "="; // Key: =
case KEY_A : return "A"; // Key: A | a
case KEY_B : return "B"; // Key: B | b
case KEY_C : return "C"; // Key: C | c
case KEY_D : return "D"; // Key: D | d
case KEY_E : return "E"; // Key: E | e
case KEY_F : return "F"; // Key: F | f
case KEY_G : return "G"; // Key: G | g
case KEY_H : return "H"; // Key: H | h
case KEY_I : return "I"; // Key: I | i
case KEY_J : return "J"; // Key: J | j
case KEY_K : return "K"; // Key: K | k
case KEY_L : return "L"; // Key: L | l
case KEY_M : return "M"; // Key: M | m
case KEY_N : return "N"; // Key: N | n
case KEY_O : return "O"; // Key: O | o
case KEY_P : return "P"; // Key: P | p
case KEY_Q : return "Q"; // Key: Q | q
case KEY_R : return "R"; // Key: R | r
case KEY_S : return "S"; // Key: S | s
case KEY_T : return "T"; // Key: T | t
case KEY_U : return "U"; // Key: U | u
case KEY_V : return "V"; // Key: V | v
case KEY_W : return "W"; // Key: W | w
case KEY_X : return "X"; // Key: X | x
case KEY_Y : return "Y"; // Key: Y | y
case KEY_Z : return "Z"; // Key: Z | z
case KEY_LEFT_BRACKET : return "["; // Key: [
case KEY_BACKSLASH : return "\\"; // Key: '\'
case KEY_RIGHT_BRACKET : return "]"; // Key: ]
case KEY_GRAVE : return "`"; // Key: `
case KEY_SPACE : return "SPACE"; // Key: Space
case KEY_ESCAPE : return "ESC"; // Key: Esc
case KEY_ENTER : return "ENTER"; // Key: Enter
case KEY_TAB : return "TAB"; // Key: Tab
case KEY_BACKSPACE : return "BACK"; // Key: Backspace
case KEY_INSERT : return "INS"; // Key: Ins
case KEY_DELETE : return "DEL"; // Key: Del
case KEY_RIGHT : return "RIGHT"; // Key: Cursor right
case KEY_LEFT : return "LEFT"; // Key: Cursor left
case KEY_DOWN : return "DOWN"; // Key: Cursor down
case KEY_UP : return "UP"; // Key: Cursor up
case KEY_PAGE_UP : return "PGUP"; // Key: Page up
case KEY_PAGE_DOWN : return "PGDOWN"; // Key: Page down
case KEY_HOME : return "HOME"; // Key: Home
case KEY_END : return "END"; // Key: End
case KEY_CAPS_LOCK : return "CAPS"; // Key: Caps lock
case KEY_SCROLL_LOCK : return "LOCK"; // Key: Scroll down
case KEY_NUM_LOCK : return "NUMLOCK"; // Key: Num lock
case KEY_PRINT_SCREEN : return "PRINTSCR"; // Key: Print screen
case KEY_PAUSE : return "PAUSE"; // Key: Pause
case KEY_F1 : return "F1"; // Key: F1
case KEY_F2 : return "F2"; // Key: F2
case KEY_F3 : return "F3"; // Key: F3
case KEY_F4 : return "F4"; // Key: F4
case KEY_F5 : return "F5"; // Key: F5
case KEY_F6 : return "F6"; // Key: F6
case KEY_F7 : return "F7"; // Key: F7
case KEY_F8 : return "F8"; // Key: F8
case KEY_F9 : return "F9"; // Key: F9
case KEY_F10 : return "F10"; // Key: F10
case KEY_F11 : return "F11"; // Key: F11
case KEY_F12 : return "F12"; // Key: F12
case KEY_LEFT_SHIFT : return "LSHIFT"; // Key: Shift left
case KEY_LEFT_CONTROL : return "LCTRL"; // Key: Control left
case KEY_LEFT_ALT : return "LALT"; // Key: Alt left
case KEY_LEFT_SUPER : return "WIN"; // Key: Super left
case KEY_RIGHT_SHIFT : return "RSHIFT"; // Key: Shift right
case KEY_RIGHT_CONTROL : return "RCTRL"; // Key: Control right
case KEY_RIGHT_ALT : return "ALTGR"; // Key: Alt right
case KEY_RIGHT_SUPER : return "RSUPER"; // Key: Super right
case KEY_KB_MENU : return "KBMENU"; // Key: KB menu
case KEY_KP_0 : return "KP0"; // Key: Keypad 0
case KEY_KP_1 : return "KP1"; // Key: Keypad 1
case KEY_KP_2 : return "KP2"; // Key: Keypad 2
case KEY_KP_3 : return "KP3"; // Key: Keypad 3
case KEY_KP_4 : return "KP4"; // Key: Keypad 4
case KEY_KP_5 : return "KP5"; // Key: Keypad 5
case KEY_KP_6 : return "KP6"; // Key: Keypad 6
case KEY_KP_7 : return "KP7"; // Key: Keypad 7
case KEY_KP_8 : return "KP8"; // Key: Keypad 8
case KEY_KP_9 : return "KP9"; // Key: Keypad 9
case KEY_KP_DECIMAL : return "KPDEC"; // Key: Keypad .
case KEY_KP_DIVIDE : return "KPDIV"; // Key: Keypad /
case KEY_KP_MULTIPLY : return "KPMUL"; // Key: Keypad *
case KEY_KP_SUBTRACT : return "KPSUB"; // Key: Keypad -
case KEY_KP_ADD : return "KPADD"; // Key: Keypad +
case KEY_KP_ENTER : return "KPENTER"; // Key: Keypad Enter
case KEY_KP_EQUAL : return "KPEQU"; // Key: Keypad =
default: return "";
}
}
// Draw keyboard key
static void GuiKeyboardKey(Rectangle bounds, int key)
{
if (key == KEY_NULL) DrawRectangleLinesEx(bounds, 2.0f, LIGHTGRAY);
else
{
if (IsKeyDown(key))
{
DrawRectangleLinesEx(bounds, 2.0f, MAROON);
DrawText(GetKeyText(key), bounds.x + 4, bounds.y + 4, 10, MAROON);
}
else
{
DrawRectangleLinesEx(bounds, 2.0f, DARKGRAY);
DrawText(GetKeyText(key), bounds.x + 4, bounds.y + 4, 10, DARKGRAY);
}
}
if (CheckCollisionPointRec(GetMousePosition(), bounds))
{
DrawRectangleRec(bounds, Fade(RED, 0.2f));
DrawRectangleLinesEx(bounds, 3.0f, RED);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -142,7 +142,7 @@ int main(void)
Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 }; Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 };
// Draw window position based on monitors // Draw window position based on monitors
DrawRectangleV(windowPosition, (Vector2){screenWidth * monitorScale, screenHeight * monitorScale}, Fade(GREEN, 0.5)); DrawRectangleV(windowPosition, (Vector2){screenWidth*monitorScale, screenHeight*monitorScale}, Fade(GREEN, 0.5));
} }
else DrawRectangleLinesEx(rec, 5, GRAY); else DrawRectangleLinesEx(rec, 5, GRAY);
} }

View File

@ -187,7 +187,7 @@ int main(void)
if (lastUndoIndex > firstUndoIndex) if (lastUndoIndex > firstUndoIndex)
{ {
for (int i = firstUndoIndex; i < currentUndoIndex; i++) for (int i = firstUndoIndex; i < currentUndoIndex; i++)
DrawRectangleRec((Rectangle){gridPosition.x + states[i].cell.x * GRID_CELL_SIZE, gridPosition.y + states[i].cell.y * GRID_CELL_SIZE, DrawRectangleRec((Rectangle){gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY); GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY);
} }
else if (firstUndoIndex > lastUndoIndex) else if (firstUndoIndex > lastUndoIndex)
@ -195,7 +195,7 @@ int main(void)
if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex)) if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex))
{ {
for (int i = firstUndoIndex; i < currentUndoIndex; i++) for (int i = firstUndoIndex; i < currentUndoIndex; i++)
DrawRectangleRec((Rectangle) { gridPosition.x + states[i].cell.x * GRID_CELL_SIZE, gridPosition.y + states[i].cell.y * GRID_CELL_SIZE, DrawRectangleRec((Rectangle) { gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE,
GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY); GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY);
} }
else else

View File

@ -17,11 +17,9 @@
#include "raylib.h" #include "raylib.h"
// For itteration purposes and teaching example #define RESOLUTION_COUNT 4 // For iteration purposes and teaching example
#define RESOLUTION_COUNT 4
enum ViewportType typedef enum {
{
// Only upscale, useful for pixel art // Only upscale, useful for pixel art
KEEP_ASPECT_INTEGER, KEEP_ASPECT_INTEGER,
KEEP_HEIGHT_INTEGER, KEEP_HEIGHT_INTEGER,
@ -32,24 +30,28 @@ enum ViewportType
KEEP_WIDTH, KEEP_WIDTH,
// For itteration purposes and as a teaching example // For itteration purposes and as a teaching example
VIEWPORT_TYPE_COUNT, VIEWPORT_TYPE_COUNT,
} ViewportType;
// For displaying on GUI
const char *ViewportTypeNames[VIEWPORT_TYPE_COUNT] = {
"KEEP_ASPECT_INTEGER",
"KEEP_HEIGHT_INTEGER",
"KEEP_WIDTH_INTEGER",
"KEEP_ASPECT",
"KEEP_HEIGHT",
"KEEP_WIDTH",
}; };
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Module Functions Declaration // Module Functions Declaration
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect); static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect); static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect); static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect); static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect); static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect); static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect);
static void ResizeRenderSize(ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target);
static void ResizeRenderSize(enum ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target);
// Example how to calculate position on RenderTexture // Example how to calculate position on RenderTexture
static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect); static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect);
@ -61,91 +63,89 @@ int main(void)
{ {
// Initialization // Initialization
//--------------------------------------------------------- //---------------------------------------------------------
// Preset resolutions that could be created by subdividing screen resolution
Vector2 resolutionList[RESOLUTION_COUNT] = {
(Vector2){64, 64},
(Vector2){256, 240},
(Vector2){320, 180},
// 4K doesn't work with integer scaling but included for example purposes with non-integer scaling
(Vector2){3840, 2160},
};
int resolutionIndex = 0;
int screenWidth = 800; int screenWidth = 800;
int screenHeight = 450; int screenHeight = 450;
int gameWidth = 64;
int gameHeight = 64;
RenderTexture2D target = (RenderTexture2D){0};
Rectangle sourceRect = (Rectangle){0};
Rectangle destRect = (Rectangle){0};
// For displaying on GUI
const char *ViewportTypeNames[VIEWPORT_TYPE_COUNT] = {
"KEEP_ASPECT_INTEGER",
"KEEP_HEIGHT_INTEGER",
"KEEP_WIDTH_INTEGER",
"KEEP_ASPECT",
"KEEP_HEIGHT",
"KEEP_WIDTH",
};
enum ViewportType viewportType = KEEP_ASPECT_INTEGER;
SetConfigFlags(FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(screenWidth, screenHeight, "raylib [core] example - viewport scaling"); InitWindow(screenWidth, screenHeight, "raylib [core] example - viewport scaling");
// Preset resolutions that could be created by subdividing screen resolution
Vector2 resolutionList[RESOLUTION_COUNT] = {
(Vector2){ 64, 64 },
(Vector2){ 256, 240 },
(Vector2){ 320, 180 },
// 4K doesn't work with integer scaling but included for example purposes with non-integer scaling
(Vector2){ 3840, 2160 },
};
int resolutionIndex = 0;
int gameWidth = 64;
int gameHeight = 64;
RenderTexture2D target = (RenderTexture2D){ 0 };
Rectangle sourceRect = (Rectangle){ 0 };
Rectangle destRect = (Rectangle){ 0 };
ViewportType viewportType = KEEP_ASPECT_INTEGER;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target); ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
// Button rectangles
Rectangle decreaseResolutionButton = (Rectangle){ 200, 30, 10, 10 };
Rectangle increaseResolutionButton = (Rectangle){ 215, 30, 10, 10 };
Rectangle decreaseTypeButton = (Rectangle){ 200, 45, 10, 10 };
Rectangle increaseTypeButton = (Rectangle){ 215, 45, 10, 10 };
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------- //----------------------------------------------------------
// Button rectangles
Rectangle decreaseResolutionButton = (Rectangle){200, 30, 10, 10};
Rectangle increaseResolutionButton = (Rectangle){215, 30, 10, 10};
Rectangle decreaseTypeButton = (Rectangle){200, 45, 10, 10};
Rectangle increaseTypeButton = (Rectangle){215, 45, 10, 10};
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
// Update // Update
//----------------------------------------------------- //----------------------------------------------------------------------------------
if (IsWindowResized()){ if (IsWindowResized()) ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
}
Vector2 mousePosition = GetMousePosition(); Vector2 mousePosition = GetMousePosition();
bool mousePressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT); bool mousePressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
// Check buttons and rescale // Check buttons and rescale
if (CheckCollisionPointRec(mousePosition, decreaseResolutionButton) && mousePressed){ if (CheckCollisionPointRec(mousePosition, decreaseResolutionButton) && mousePressed)
resolutionIndex = (resolutionIndex + RESOLUTION_COUNT - 1) % RESOLUTION_COUNT; {
gameWidth = resolutionList[resolutionIndex].x; resolutionIndex = (resolutionIndex + RESOLUTION_COUNT - 1)%RESOLUTION_COUNT;
gameHeight = resolutionList[resolutionIndex].y; gameWidth = (int)resolutionList[resolutionIndex].x;
gameHeight = (int)resolutionList[resolutionIndex].y;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target); ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
} }
if (CheckCollisionPointRec(mousePosition, increaseResolutionButton) && mousePressed){
resolutionIndex = (resolutionIndex + 1) % RESOLUTION_COUNT; if (CheckCollisionPointRec(mousePosition, increaseResolutionButton) && mousePressed)
gameWidth = resolutionList[resolutionIndex].x; {
gameHeight = resolutionList[resolutionIndex].y; resolutionIndex = (resolutionIndex + 1)%RESOLUTION_COUNT;
gameWidth = (int)resolutionList[resolutionIndex].x;
gameHeight = (int)resolutionList[resolutionIndex].y;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target); ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
} }
if (CheckCollisionPointRec(mousePosition, decreaseTypeButton) && mousePressed){
viewportType = (viewportType + VIEWPORT_TYPE_COUNT - 1) % VIEWPORT_TYPE_COUNT; if (CheckCollisionPointRec(mousePosition, decreaseTypeButton) && mousePressed)
{
viewportType = (viewportType + VIEWPORT_TYPE_COUNT - 1)%VIEWPORT_TYPE_COUNT;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target); ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
} }
if (CheckCollisionPointRec(mousePosition, increaseTypeButton) && mousePressed){
viewportType = (viewportType + 1) % VIEWPORT_TYPE_COUNT; if (CheckCollisionPointRec(mousePosition, increaseTypeButton) && mousePressed)
{
viewportType = (viewportType + 1)%VIEWPORT_TYPE_COUNT;
ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target); ResizeRenderSize(viewportType, &screenWidth, &screenHeight, gameWidth, gameHeight, &sourceRect, &destRect, &target);
} }
Vector2 textureMousePosition = Screen2RenderTexturePosition(mousePosition, &sourceRect, &destRect); Vector2 textureMousePosition = Screen2RenderTexturePosition(mousePosition, &sourceRect, &destRect);
//----------------------------------------------------------------------------------
// Draw // Draw
//----------------------------------------------------- //----------------------------------------------------------------------------------
// Draw our scene to the render texture // Draw our scene to the render texture
BeginTextureMode(target); BeginTextureMode(target);
ClearBackground(WHITE); ClearBackground(WHITE);
DrawCircle(textureMousePosition.x, textureMousePosition.y, 20.f, LIME); DrawCircleV(textureMousePosition, 20.0f, LIME);
EndTextureMode(); EndTextureMode();
// Draw render texture to main framebuffer // Draw render texture to main framebuffer
@ -153,29 +153,22 @@ int main(void)
ClearBackground(BLACK); ClearBackground(BLACK);
// Draw our render texture with rotation applied // Draw our render texture with rotation applied
const Vector2 ORIGIN_POSITION = (Vector2){ 0.0f, 0.0f }; DrawTexturePro(target.texture, sourceRect, destRect, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
const float ROTATION = 0.f;
DrawTexturePro(target.texture, sourceRect, destRect, ORIGIN_POSITION, ROTATION, WHITE);
// Draw Native resolution (GUI or anything) // Draw Native resolution (GUI or anything)
// Draw info box // Draw info box
Rectangle infoRect = (Rectangle){5, 5, 330, 105}; Rectangle infoRect = (Rectangle){5, 5, 330, 105};
DrawRectangleRec(infoRect, Fade(LIGHTGRAY, 0.7f)); DrawRectangleRec(infoRect, Fade(LIGHTGRAY, 0.7f));
DrawRectangleLines(infoRect.x, infoRect.y, infoRect.width, infoRect.height, BLUE); DrawRectangleLinesEx(infoRect, 1, BLUE);
DrawText(TextFormat("Window Resolution: %d x %d", screenWidth, screenHeight), 15, 15, 10, BLACK); DrawText(TextFormat("Window Resolution: %d x %d", screenWidth, screenHeight), 15, 15, 10, BLACK);
DrawText(TextFormat("Game Resolution: %d x %d", gameWidth, gameHeight), 15, 30, 10, BLACK); DrawText(TextFormat("Game Resolution: %d x %d", gameWidth, gameHeight), 15, 30, 10, BLACK);
DrawText(TextFormat("Type: %s", ViewportTypeNames[viewportType]), 15, 45, 10, BLACK); DrawText(TextFormat("Type: %s", ViewportTypeNames[viewportType]), 15, 45, 10, BLACK);
Vector2 scaleRatio = (Vector2){destRect.width / sourceRect.width, destRect.height / -sourceRect.height}; Vector2 scaleRatio = (Vector2){destRect.width/sourceRect.width, -destRect.height/sourceRect.height};
if (scaleRatio.x < 0.001f || scaleRatio.y < 0.001f) if (scaleRatio.x < 0.001f || scaleRatio.y < 0.001f) DrawText(TextFormat("Scale ratio: INVALID"), 15, 60, 10, BLACK);
{ else DrawText(TextFormat("Scale ratio: %.2f x %.2f", scaleRatio.x, scaleRatio.y), 15, 60, 10, BLACK);
DrawText(TextFormat("Scale ratio: INVALID"), 15, 60, 10, BLACK);
}
else
{
DrawText(TextFormat("Scale ratio: %.2f x %.2f", scaleRatio.x, scaleRatio.y), 15, 60, 10, BLACK);
}
DrawText(TextFormat("Source size: %.2f x %.2f", sourceRect.width, -sourceRect.height), 15, 75, 10, BLACK); DrawText(TextFormat("Source size: %.2f x %.2f", sourceRect.width, -sourceRect.height), 15, 75, 10, BLACK);
DrawText(TextFormat("Destination size: %.2f x %.2f", destRect.width, destRect.height), 15, 90, 10, BLACK); DrawText(TextFormat("Destination size: %.2f x %.2f", destRect.width, destRect.height), 15, 90, 10, BLACK);
@ -190,13 +183,13 @@ int main(void)
DrawText(">", increaseResolutionButton.x + 3, increaseResolutionButton.y + 1, 10, BLACK); DrawText(">", increaseResolutionButton.x + 3, increaseResolutionButton.y + 1, 10, BLACK);
EndDrawing(); EndDrawing();
//----------------------------------------------------- //----------------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization
//--------------------------------------------------------- //----------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//---------------------------------------------------------- //----------------------------------------------------------------------------------
return 0; return 0;
} }
@ -206,54 +199,54 @@ int main(void)
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect) static void KeepAspectCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{ {
sourceRect->x = 0.f; sourceRect->x = 0.0f;
sourceRect->y = (float)gameHeight; sourceRect->y = (float)gameHeight;
sourceRect->width = (float)gameWidth; sourceRect->width = (float)gameWidth;
sourceRect->height = (float)-gameHeight; sourceRect->height = (float)-gameHeight;
const int ratio_x = (screenWidth/gameWidth); const int ratio_x = (screenWidth/gameWidth);
const int ratio_y = (screenHeight/gameHeight); const int ratio_y = (screenHeight/gameHeight);
const float resizeRatio = (float)(ratio_x < ratio_y ? ratio_x : ratio_y); const float resizeRatio = (float)((ratio_x < ratio_y)? ratio_x : ratio_y);
destRect->x = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5); destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5); destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth * resizeRatio); destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(gameHeight * resizeRatio); destRect->height = (float)(int)(gameHeight*resizeRatio);
} }
static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect) static void KeepHeightCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{ {
const float resizeRatio = (float)(screenHeight/gameHeight); const float resizeRatio = (float)screenHeight/gameHeight;
sourceRect->x = 0.f; sourceRect->x = 0.0f;
sourceRect->y = 0.f; sourceRect->y = 0.0f;
sourceRect->width = (float)(int)(screenWidth / resizeRatio); sourceRect->width = (float)(int)(screenWidth/resizeRatio);
sourceRect->height = (float)-gameHeight; sourceRect->height = (float)-gameHeight;
destRect->x = (float)(int)((screenWidth - (sourceRect->width * resizeRatio)) * 0.5); destRect->x = (float)(int)((screenWidth - (sourceRect->width*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5); destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(sourceRect->width * resizeRatio); destRect->width = (float)(int)(sourceRect->width*resizeRatio);
destRect->height = (float)(int)(gameHeight * resizeRatio); destRect->height = (float)(int)(gameHeight*resizeRatio);
} }
static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect) static void KeepWidthCenteredInteger(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{ {
const float resizeRatio = (float)(screenWidth/gameWidth); const float resizeRatio = (float)screenWidth/gameWidth;
sourceRect->x = 0.f; sourceRect->x = 0.0f;
sourceRect->y = 0.f; sourceRect->y = 0.0f;
sourceRect->width = (float)gameWidth; sourceRect->width = (float)gameWidth;
sourceRect->height = (float)(int)(screenHeight / resizeRatio); sourceRect->height = (float)(int)(screenHeight/resizeRatio);
destRect->x = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5); destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (sourceRect->height * resizeRatio)) * 0.5); destRect->y = (float)(int)((screenHeight - (sourceRect->height*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth * resizeRatio); destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(sourceRect->height * resizeRatio); destRect->height = (float)(int)(sourceRect->height*resizeRatio);
sourceRect->height *= -1.f; sourceRect->height *= -1.0f;
} }
static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect) static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{ {
sourceRect->x = 0.f; sourceRect->x = 0.0f;
sourceRect->y = (float)gameHeight; sourceRect->y = (float)gameHeight;
sourceRect->width = (float)gameWidth; sourceRect->width = (float)gameWidth;
sourceRect->height = (float)-gameHeight; sourceRect->height = (float)-gameHeight;
@ -262,81 +255,58 @@ static void KeepAspectCentered(int screenWidth, int screenHeight, int gameWidth,
const float ratio_y = ((float)screenHeight/(float)gameHeight); const float ratio_y = ((float)screenHeight/(float)gameHeight);
const float resizeRatio = (ratio_x < ratio_y ? ratio_x : ratio_y); const float resizeRatio = (ratio_x < ratio_y ? ratio_x : ratio_y);
destRect->x = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5); destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5); destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth * resizeRatio); destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(gameHeight * resizeRatio); destRect->height = (float)(int)(gameHeight*resizeRatio);
} }
static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect) static void KeepHeightCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{ {
const float resizeRatio = ((float)screenHeight/(float)gameHeight); const float resizeRatio = ((float)screenHeight/(float)gameHeight);
sourceRect->x = 0.f; sourceRect->x = 0.0f;
sourceRect->y = 0.f; sourceRect->y = 0.0f;
sourceRect->width = (float)(int)((float)screenWidth / resizeRatio); sourceRect->width = (float)(int)((float)screenWidth/resizeRatio);
sourceRect->height = (float)-gameHeight; sourceRect->height = (float)-gameHeight;
destRect->x = (float)(int)((screenWidth - (sourceRect->width * resizeRatio)) * 0.5); destRect->x = (float)(int)((screenWidth - (sourceRect->width*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (gameHeight * resizeRatio)) * 0.5); destRect->y = (float)(int)((screenHeight - (gameHeight*resizeRatio))*0.5f);
destRect->width = (float)(int)(sourceRect->width * resizeRatio); destRect->width = (float)(int)(sourceRect->width*resizeRatio);
destRect->height = (float)(int)(gameHeight * resizeRatio); destRect->height = (float)(int)(gameHeight*resizeRatio);
} }
static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect) static void KeepWidthCentered(int screenWidth, int screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect)
{ {
const float resizeRatio = ((float)screenWidth/(float)gameWidth); const float resizeRatio = ((float)screenWidth/(float)gameWidth);
sourceRect->x = 0.f; sourceRect->x = 0.0f;
sourceRect->y = 0.f; sourceRect->y = 0.0f;
sourceRect->width = (float)gameWidth; sourceRect->width = (float)gameWidth;
sourceRect->height = (float)(int)((float)screenHeight / resizeRatio); sourceRect->height = (float)(int)((float)screenHeight/resizeRatio);
destRect->x = (float)(int)((screenWidth - (gameWidth * resizeRatio)) * 0.5); destRect->x = (float)(int)((screenWidth - (gameWidth*resizeRatio))*0.5f);
destRect->y = (float)(int)((screenHeight - (sourceRect->height * resizeRatio)) * 0.5); destRect->y = (float)(int)((screenHeight - (sourceRect->height*resizeRatio))*0.5f);
destRect->width = (float)(int)(gameWidth * resizeRatio); destRect->width = (float)(int)(gameWidth*resizeRatio);
destRect->height = (float)(int)(sourceRect->height * resizeRatio); destRect->height = (float)(int)(sourceRect->height*resizeRatio);
sourceRect->height *= -1.f; sourceRect->height *= -1.f;
} }
static void ResizeRenderSize(enum ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target) static void ResizeRenderSize(ViewportType viewportType, int *screenWidth, int *screenHeight, int gameWidth, int gameHeight, Rectangle *sourceRect, Rectangle *destRect, RenderTexture2D *target)
{ {
*screenWidth = GetScreenWidth(); *screenWidth = GetScreenWidth();
*screenHeight = GetScreenHeight(); *screenHeight = GetScreenHeight();
switch(viewportType) switch(viewportType)
{ {
case KEEP_ASPECT_INTEGER: case KEEP_ASPECT_INTEGER: KeepAspectCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
{ case KEEP_HEIGHT_INTEGER: KeepHeightCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
KeepAspectCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); case KEEP_WIDTH_INTEGER: KeepWidthCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
break; case KEEP_ASPECT: KeepAspectCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
} case KEEP_HEIGHT: KeepHeightCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
case KEEP_HEIGHT_INTEGER: case KEEP_WIDTH: KeepWidthCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect); break;
{ default: break;
KeepHeightCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect);
break;
}
case KEEP_WIDTH_INTEGER:
{
KeepWidthCenteredInteger(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect);
break;
}
case KEEP_ASPECT:
{
KeepAspectCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect);
break;
}
case KEEP_HEIGHT:
{
KeepHeightCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect);
break;
}
case KEEP_WIDTH:
{
KeepWidthCentered(*screenWidth, *screenHeight, gameWidth, gameHeight, sourceRect, destRect);
break;
}
default: {}
} }
UnloadRenderTexture(*target); UnloadRenderTexture(*target);
*target = LoadRenderTexture(sourceRect->width, -sourceRect->height); *target = LoadRenderTexture(sourceRect->width, -sourceRect->height);
} }
@ -345,7 +315,7 @@ static void ResizeRenderSize(enum ViewportType viewportType, int *screenWidth, i
static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect) static Vector2 Screen2RenderTexturePosition(Vector2 point, Rectangle *textureRect, Rectangle *scaledRect)
{ {
Vector2 relativePosition = {point.x - scaledRect->x, point.y - scaledRect->y}; Vector2 relativePosition = {point.x - scaledRect->x, point.y - scaledRect->y};
Vector2 ratio = {textureRect->width / scaledRect->width, -textureRect->height / scaledRect->height}; Vector2 ratio = {textureRect->width/scaledRect->width, -textureRect->height/scaledRect->height};
return (Vector2){relativePosition.x * ratio.x, relativePosition.y * ratio.x}; return (Vector2){relativePosition.x*ratio.x, relativePosition.y*ratio.x};
} }

View File

@ -43,7 +43,7 @@ int main(void)
*/ */
// Set configuration flags for window creation // Set configuration flags for window creation
//SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI); //SetConfigFlags(FLAG_VSYNC_HINT | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI);// | FLAG_WINDOW_TRANSPARENT);
InitWindow(screenWidth, screenHeight, "raylib [core] example - window flags"); InitWindow(screenWidth, screenHeight, "raylib [core] example - window flags");
Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }; Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
@ -97,7 +97,8 @@ int main(void)
if (IsWindowState(FLAG_WINDOW_MINIMIZED)) if (IsWindowState(FLAG_WINDOW_MINIMIZED))
{ {
framesCounter++; framesCounter++;
if (framesCounter >= 240) { if (framesCounter >= 240)
{
RestoreWindow(); // Restore window after 3 seconds RestoreWindow(); // Restore window after 3 seconds
framesCounter = 0; framesCounter = 0;
} }

View File

@ -1,11 +1,13 @@
# #
# raylib examples list used to generate/update collection # raylib examples list with available .c example files
# examples must be provided as: <example_category>;<example_name>;<example_stars>;<raylib_created_version>;<raylib_last_update_version>;<year_created>;<year_reviewed>;"<example_author_name>";<author_github_user> #
# WARNING: List is not ordered by example name but by the display order on web,
# so it can not be automatically generated scanning available .c code files, only updated
# new examples are added at the end of each category; it's up to the user to reorder them as desired
#
# examples data is listed as: <example_category>;<example_name>;<example_stars>;<raylib_created_version>;<raylib_last_update_version>;<year_created>;<year_reviewed>;"<example_author_name>";<author_github_user>
# #
# This list is used as the main reference by [rexm] tool for examples collection validation and management # This list is used as the main reference by [rexm] tool for examples collection validation and management
# New examples must be added to this list and any possible rename must be made on this list first
#
# WARNING: List is not ordered by example name but by the display order on web
# #
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5 core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5
core;core_delta_time;★☆☆☆;5.5;5.6-dev;2025;2025;"Robin";@RobinsAviary core;core_delta_time;★☆☆☆;5.5;5.6-dev;2025;2025;"Robin";@RobinsAviary
@ -43,7 +45,7 @@ core;core_custom_frame_control;★★★★;4.0;4.0;2021;2025;"Ramon Santamaria"
core;core_smooth_pixelperfect;★★★☆;3.7;4.0;2021;2025;"Giancamillo Alessandroni";@NotManyIdeasDev core;core_smooth_pixelperfect;★★★☆;3.7;4.0;2021;2025;"Giancamillo Alessandroni";@NotManyIdeasDev
core;core_random_sequence;★☆☆☆;5.0;5.0;2023;2025;"Dalton Overmyer";@REDl3east core;core_random_sequence;★☆☆☆;5.0;5.0;2023;2025;"Dalton Overmyer";@REDl3east
core;core_automation_events;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@raysan5 core;core_automation_events;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
core;core_high_dpi;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997 core;core_highdpi_demo;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997
core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5 core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5
core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers core;core_viewport_scaling;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
@ -51,9 +53,10 @@ core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoo
core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal
core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_screen_recording;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_screen_recording;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_clipboard_text;★☆☆;5.6-dev;5.6-dev;2025;2025;"Ananth S";@Ananth1839 core;core_clipboard_text;★☆☆;5.6-dev;5.6-dev;2025;2025;"Ananth S";@Ananth1839
core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04 core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04
core;core_compute_hash;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_compute_hash;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_keyboard_testbed;★★☆☆;5.6;5.6;2026;2026;"Ramon Santamaria";@raysan5
shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower
@ -90,6 +93,9 @@ shapes;shapes_lines_drawing;★☆☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAv
shapes;shapes_math_angle_rotation;★☆☆☆;5.6-dev;5.6;2025;2025;"Kris";@krispy-snacc shapes;shapes_math_angle_rotation;★☆☆☆;5.6-dev;5.6;2025;2025;"Kris";@krispy-snacc
shapes;shapes_rlgl_color_wheel;★★★☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary shapes;shapes_rlgl_color_wheel;★★★☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary
shapes;shapes_rlgl_triangle;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary shapes;shapes_rlgl_triangle;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary
shapes;shapes_ball_physics;★★☆☆;5.6-dev;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_penrose_tile;★★★★;5.5;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
shapes;shapes_hilbert_curve;★★★☆;5.6;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5
@ -118,6 +124,8 @@ textures;textures_image_rotate;★★☆☆;1.0;1.0;2014;2025;"Ramon Santamaria"
textures;textures_screen_buffer;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers textures;textures_screen_buffer;★★☆☆;5.5;5.5;2025;2025;"Agnis Aldiņš";@nezvers
textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";@JeffM2501 textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";@JeffM2501
textures;textures_sprite_stacking;★★☆☆;5.6-dev;6.0;2025;2025;"Robin";@RobinsAviary textures;textures_sprite_stacking;★★☆☆;5.6-dev;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
text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5 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_spritefont;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5 text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
@ -133,6 +141,7 @@ text;text_3d_drawing;★★★★;3.5;4.0;2021;2025;"Vlad Adrian";@demizdor
text;text_codepoints_loading;★★★☆;4.2;4.2;2022;2025;"Ramon Santamaria";@raysan5 text;text_codepoints_loading;★★★☆;4.2;4.2;2022;2025;"Ramon Santamaria";@raysan5
text;text_inline_styling;★★★☆;5.6-dev;5.6-dev;2025;2025;"Wagner Barongello";@SultansOfCode text;text_inline_styling;★★★☆;5.6-dev;5.6-dev;2025;2025;"Wagner Barongello";@SultansOfCode
text;text_words_alignment;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates text;text_words_alignment;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates
text;text_strings_management;★★★☆;5.6-dev;5.6-dev;2025;2025;"David Buzatto";@davidbuzatto
models;models_animation_playing;★★☆☆;2.5;3.5;2019;2025;"Culacant";@culacant models;models_animation_playing;★★☆☆;2.5;3.5;2019;2025;"Culacant";@culacant
models;models_billboard_rendering;★★★☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5 models;models_billboard_rendering;★★★☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5
models;models_box_collisions;★☆☆☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5 models;models_box_collisions;★☆☆☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5
@ -192,6 +201,7 @@ shaders;shaders_basic_pbr;★★★★;5.0;5.5;2023;2025;"Afan OLOVCIC";@_DevDad
shaders;shaders_lightmap_rendering;★★★☆;4.5;4.5;2019;2025;"Jussi Viitala";@nullstare shaders;shaders_lightmap_rendering;★★★☆;4.5;4.5;2019;2025;"Jussi Viitala";@nullstare
shaders;shaders_rounded_rectangle;★★★☆;5.5;5.5;2025;2025;"Anstro Pleuton";@anstropleuton shaders;shaders_rounded_rectangle;★★★☆;5.5;5.5;2025;2025;"Anstro Pleuton";@anstropleuton
shaders;shaders_depth_rendering;★★★☆;5.6-dev;5.6-dev;2025;2025;"Luís Almeida";@luis605 shaders;shaders_depth_rendering;★★★☆;5.6-dev;5.6-dev;2025;2025;"Luís Almeida";@luis605
shaders;shaders_game_of_life;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
audio;audio_module_playing;★☆☆☆;1.5;3.5;2016;2025;"Ramon Santamaria";@raysan5 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_music_stream;★☆☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
audio;audio_raw_stream;★★★☆;1.6;4.2;2015;2025;"Ramon Santamaria";@raysan5 audio;audio_raw_stream;★★★☆;1.6;4.2;2015;2025;"Ramon Santamaria";@raysan5
@ -200,7 +210,7 @@ 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_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_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71 audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
audio;audio_fft_spectrum_visualizer;★★★☆;6.0;5.6-dev;2025;2025;"IANN";@meisei4 audio;audio_spectrum_visualizer;★★★☆;6.0;5.6-dev;2025;2025;"IANN";@meisei4
others;rlgl_standalone;★★★★;1.6;4.0;2014;2025;"Ramon Santamaria";@raysan5 others;rlgl_standalone;★★★★;1.6;4.0;2014;2025;"Ramon Santamaria";@raysan5
others;rlgl_compute_shader;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41 others;rlgl_compute_shader;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flashback-fx others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flashback-fx

View File

@ -45,7 +45,7 @@ static void FreeMeshBuilder(MeshBuilder *mb);
static Mesh BuildMesh(MeshBuilder *mb); static Mesh BuildMesh(MeshBuilder *mb);
static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset); static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset);
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s); static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s);
#define FreeDecalMeshData() GenMeshDecal((Model){ .meshCount = -1.0f }, (Matrix){ 0 }, 0.0f, 0.0f) static void FreeDecalMeshData(void) { GenMeshDecal((Model){ .meshCount = -1 }, (Matrix){ 0 }, 0.0f, 0.0f); }
static bool GuiButton(Rectangle rec, const char *label); static bool GuiButton(Rectangle rec, const char *label);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
@ -198,12 +198,12 @@ int main(void)
EndMode3D(); EndMode3D();
float yPos = 10; float yPos = 10;
float x0 = GetScreenWidth() - 300; float x0 = GetScreenWidth() - 300.0f;
float x1 = x0 + 100; float x1 = x0 + 100;
float x2 = x1 + 100; float x2 = x1 + 100;
DrawText("Vertices", x1, yPos, 10, LIME); DrawText("Vertices", (int)x1, (int)yPos, 10, LIME);
DrawText("Triangles", x2, yPos, 10, LIME); DrawText("Triangles", (int)x2, (int)yPos, 10, LIME);
yPos += 15; yPos += 15;
int vertexCount = 0; int vertexCount = 0;
@ -215,24 +215,24 @@ int main(void)
triangleCount += model.meshes[i].triangleCount; triangleCount += model.meshes[i].triangleCount;
} }
DrawText("Main model", x0, yPos, 10, LIME); DrawText("Main model", (int)x0, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); DrawText(TextFormat("%d", vertexCount), (int)x1, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); DrawText(TextFormat("%d", triangleCount), (int)x2, (int)yPos, 10, LIME);
yPos += 15; yPos += 15;
for (int i = 0; i < decalCount; i++) for (int i = 0; i < decalCount; i++)
{ {
if (i == 20) if (i == 20)
{ {
DrawText("...", x0, yPos, 10, LIME); DrawText("...", (int)x0, (int)yPos, 10, LIME);
yPos += 15; yPos += 15;
} }
if (i < 20) if (i < 20)
{ {
DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); DrawText(TextFormat("Decal #%d", i+1), (int)x0, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), (int)x1, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), (int)x2, (int)yPos, 10, LIME);
yPos += 15; yPos += 15;
} }
@ -240,18 +240,18 @@ int main(void)
triangleCount += decalModels[i].meshes[0].triangleCount; triangleCount += decalModels[i].meshes[0].triangleCount;
} }
DrawText("TOTAL", x0, yPos, 10, LIME); DrawText("TOTAL", (int)x0, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); DrawText(TextFormat("%d", vertexCount), (int)x1, (int)yPos, 10, LIME);
DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); DrawText(TextFormat("%d", triangleCount), (int)x2, (int)yPos, 10, LIME);
yPos += 15; yPos += 15;
DrawText("Hold RMB to move camera", 10, 430, 10, GRAY); DrawText("Hold RMB to move camera", 10, 430, 10, GRAY);
DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY); DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY);
// UI elements // UI elements
if (GuiButton((Rectangle){ 10, screenHeight - 100, 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, 100, 60 }, "Clear Decals")) if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100.0f, 100, 60 }, "Clear Decals"))
{ {
// Clear decals, unload all decal models // Clear decals, unload all decal models
for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]); for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]);
@ -596,8 +596,8 @@ static bool GuiButton(Rectangle rec, const char *label)
DrawRectangleRec(rec, bgColor); DrawRectangleRec(rec, bgColor);
DrawRectangleLinesEx(rec, 2.0f, DARKGRAY); DrawRectangleLinesEx(rec, 2.0f, DARKGRAY);
float fontSize = 10.0f; int fontSize = 10;
float textWidth = MeasureText(label, fontSize); int textWidth = MeasureText(label, fontSize);
DrawText(label, (int)(rec.x + rec.width*0.5f - textWidth*0.5f), (int)(rec.y + rec.height*0.5f - fontSize*0.5f), fontSize, DARKGRAY); DrawText(label, (int)(rec.x + rec.width*0.5f - textWidth*0.5f), (int)(rec.y + rec.height*0.5f - fontSize*0.5f), fontSize, DARKGRAY);

View File

@ -80,18 +80,23 @@ int main(void)
if (playerCellY < 0) playerCellY = 0; if (playerCellY < 0) playerCellY = 0;
else if (playerCellY >= cubicmap.height) playerCellY = cubicmap.height - 1; else if (playerCellY >= cubicmap.height) playerCellY = cubicmap.height - 1;
// Check map collisions using image data and player position // Check map collisions using image data and player position against surrounding cells only
// TODO: Improvement: Just check player surrounding cells for collision for (int y = playerCellY - 1; y <= playerCellY + 1; y++)
for (int y = 0; y < cubicmap.height; y++)
{ {
for (int x = 0; x < cubicmap.width; x++) // Avoid map accessing out of bounds
if ((y >= 0) && (y < cubicmap.height))
{ {
if ((mapPixels[y*cubicmap.width + x].r == 255) && // Collision: white pixel, only check R channel for (int x = playerCellX - 1; x <= playerCellX + 1; x++)
(CheckCollisionCircleRec(playerPos, playerRadius,
(Rectangle){ mapPosition.x - 0.5f + x*1.0f, mapPosition.z - 0.5f + y*1.0f, 1.0f, 1.0f })))
{ {
// Collision detected, reset camera position // NOTE: Collision: Only checking R channel for white pixel
camera.position = oldCamPos; if (((x >= 0) && (x < cubicmap.width)) &&
(mapPixels[y*cubicmap.width + x].r == 255) &&
(CheckCollisionCircleRec(playerPos, playerRadius,
(Rectangle){ mapPosition.x - 0.5f + x*1.0f, mapPosition.z - 0.5f + y*1.0f, 1.0f, 1.0f })))
{
// Collision detected, reset camera position
camera.position = oldCamPos;
}
} }
} }
} }

View File

@ -138,7 +138,7 @@ int main(void)
GetMouseWheelMove()*-2.0f); // Move to target (zoom) GetMouseWheelMove()*-2.0f); // Move to target (zoom)
// Cycle between models on mouse click // Cycle between models on mouse click
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) currentModel = (currentModel + 1) % MAX_VOX_FILES; if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) currentModel = (currentModel + 1)%MAX_VOX_FILES;
// Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f }) // Update the shader with the camera view vector (points towards { 0.0f, 0.0f, 0.0f })
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };

View File

@ -148,25 +148,25 @@ void DrawSphereBasic(Color color)
{ {
for (int j = 0; j < slices; j++) for (int j = 0; j < slices; j++)
{ {
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*sinf(DEG2RAD*(j*360.0f/slices)),
sinf(DEG2RAD*(270+(180/(rings + 1))*i)), sinf(DEG2RAD*(270+(180.0f/(rings + 1))*i)),
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*cosf(DEG2RAD*(j*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360.0f/slices)),
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*sinf(DEG2RAD*(j*360.0f/slices)),
sinf(DEG2RAD*(270+(180/(rings + 1))*i)), sinf(DEG2RAD*(270+(180.0f/(rings + 1))*i)),
cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); cosf(DEG2RAD*(270+(180.0f/(rings + 1))*i))*cosf(DEG2RAD*(j*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
sinf(DEG2RAD*(270+(180/(rings + 1))*(i))), sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i))),
cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), rlVertex3f(cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360.0f/slices)),
sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), sinf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1))),
cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); cosf(DEG2RAD*(270+(180.0f/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360.0f/slices)));
} }
} }
rlEnd(); rlEnd();

View File

@ -54,7 +54,8 @@ int main(void)
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
Model skybox = LoadModelFromMesh(cube); Model skybox = LoadModelFromMesh(cube);
// Set this to true to use an HDR Texture, Note that raylib must be built with HDR Support for this to work SUPPORT_FILEFORMAT_HDR // Set this to true to use an HDR Texture
// NOTE: raylib must be built with HDR Support for this to work: SUPPORT_FILEFORMAT_HDR
bool useHDR = false; bool useHDR = false;
// Load skybox shader and set required locations // Load skybox shader and set required locations
@ -63,8 +64,8 @@ int main(void)
TextFormat("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION)); TextFormat("resources/shaders/glsl%i/skybox.fs", GLSL_VERSION));
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MATERIAL_MAP_CUBEMAP }, SHADER_UNIFORM_INT); SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "environmentMap"), (int[1]){ MATERIAL_MAP_CUBEMAP }, SHADER_UNIFORM_INT);
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "doGamma"), (int[1]) { useHDR ? 1 : 0 }, SHADER_UNIFORM_INT); SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "doGamma"), (int[1]){ useHDR? 1 : 0 }, SHADER_UNIFORM_INT);
SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "vflipped"), (int[1]){ useHDR ? 1 : 0 }, SHADER_UNIFORM_INT); SetShaderValue(skybox.materials[0].shader, GetShaderLocation(skybox.materials[0].shader, "vflipped"), (int[1]){ useHDR? 1 : 0 }, SHADER_UNIFORM_INT);
// Load cubemap shader and setup required shader locations // Load cubemap shader and setup required shader locations
Shader shdrCubemap = LoadShader(TextFormat("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION), Shader shdrCubemap = LoadShader(TextFormat("resources/shaders/glsl%i/cubemap.vs", GLSL_VERSION),
@ -91,9 +92,11 @@ int main(void)
} }
else else
{ {
Image img = LoadImage("resources/skybox.png"); // TODO: WARNING: On PLATFORM_WEB it requires a big amount of memory to process input image
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT); // CUBEMAP_LAYOUT_PANORAMA // and generate the required cubemap image to be passed to rlLoadTextureCubemap()
UnloadImage(img); Image image = LoadImage("resources/skybox.png");
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(image);
} }
DisableCursor(); // Limit cursor to relative movement inside the window DisableCursor(); // Limit cursor to relative movement inside the window
@ -132,9 +135,9 @@ int main(void)
} }
else else
{ {
Image img = LoadImage(droppedFiles.paths[0]); Image image = LoadImage(droppedFiles.paths[0]);
skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(img, CUBEMAP_LAYOUT_AUTO_DETECT); skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = LoadTextureCubemap(image, CUBEMAP_LAYOUT_AUTO_DETECT);
UnloadImage(img); UnloadImage(image);
} }
TextCopy(skyboxFileName, droppedFiles.paths[0]); TextCopy(skyboxFileName, droppedFiles.paths[0]);

View File

@ -85,9 +85,9 @@ int main(void)
// Calculate the cube position // Calculate the cube position
Vector3 cubePos = { Vector3 cubePos = {
(float)(x - numBlocks/2)*(scale*3.0f) + scatter, (float)(x - (float)numBlocks/2)*(scale*3.0f) + scatter,
(float)(y - numBlocks/2)*(scale*2.0f) + scatter, (float)(y - (float)numBlocks/2)*(scale*2.0f) + scatter,
(float)(z - numBlocks/2)*(scale*3.0f) + scatter (float)(z - (float)numBlocks/2)*(scale*3.0f) + scatter
}; };
// Pick a color with a hue depending on cube position for the rainbow color effect // Pick a color with a hue depending on cube position for the rainbow color effect

View File

@ -30,6 +30,7 @@
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
#define GLAD_GLES2_IMPLEMENTATION
#include "glad_gles2.h" // Required for: OpenGL functionality #include "glad_gles2.h" // Required for: OpenGL functionality
#define glGenVertexArrays glGenVertexArraysOES #define glGenVertexArrays glGenVertexArraysOES
#define glBindVertexArray glBindVertexArrayOES #define glBindVertexArray glBindVertexArrayOES

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

View File

@ -0,0 +1,44 @@
#version 100
precision highp float;
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Input size in pixels of the textures
uniform vec2 resolution;
void main()
{
// Size of one pixel in texture coordinates (from 0.0 to 1.0)
float x = 1.0/resolution.x;
float y = 1.0/resolution.y;
// Status of the current cell (1 = alive, 0 = dead)
int origValue = (texture2D(texture0, fragTexCoord).r < 0.1)? 1 : 0;
// Sum of alive neighbors
int sumValue = (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Top-left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Top
sumValue += (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Top-right
sumValue += (texture2D(texture0, vec2(fragTexCoord.x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Right
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Bottom-left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Bottom
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Bottom-right
// Game of life rules:
// Current cell remains alive when 2 or 3 neighbors are alive, dies otherwise
// Current cell goes from dead to alive when exactly 3 neighbors are alive
if ((origValue == 1 && sumValue == 2) || sumValue == 3)
gl_FragColor = vec4(0.0, 0.0, 0.0, 255.0); // Alive: draw the pixel black
else
gl_FragColor = fragColor; // Dead: draw the pixel with the background color, RAYWHITE
}

View File

@ -0,0 +1,42 @@
#version 120
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Input size in pixels of the textures
uniform vec2 resolution;
void main()
{
// Size of one pixel in texture coordinates (from 0.0 to 1.0)
float x = 1.0/resolution.x;
float y = 1.0/resolution.y;
// Status of the current cell (1 = alive, 0 = dead)
int origValue = (texture2D(texture0, fragTexCoord).r < 0.1)? 1 : 0;
// Sum of alive neighbors
int sumValue = (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Top-left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Top
sumValue += (texture2D(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Top-right
sumValue += (texture2D(texture0, vec2(fragTexCoord.x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Right
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Bottom-left
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Bottom
sumValue += (texture2D(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Bottom-right
// Game of life rules:
// Current cell remains alive when 2 or 3 neighbors are alive, dies otherwise
// Current cell goes from dead to alive when exactly 3 neighbors are alive
if (((origValue == 1) && (sumValue == 2)) || sumValue == 3)
gl_FragColor = vec4(0.0, 0.0, 0.0, 255.0); // Alive: draw the pixel black
else
gl_FragColor = fragColor; // Dead: draw the pixel with the background color, RAYWHITE
}

View File

@ -0,0 +1,45 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Output fragment color
out vec4 finalColor;
// Input size in pixels of the textures
uniform vec2 resolution;
void main()
{
// Size of one pixel in texture coordinates (from 0.0 to 1.0)
float x = 1.0/resolution.x;
float y = 1.0/resolution.y;
// Status of the current cell (1 = alive, 0 = dead)
int origValue = (texture(texture0, fragTexCoord).r < 0.1)? 1 : 0;
// Sum of alive neighbors
int sumValue = (texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Top-left
sumValue += (texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Top
sumValue += (texture(texture0, vec2(fragTexCoord.x - x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Top-right
sumValue += (texture(texture0, vec2(fragTexCoord.x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Left
sumValue += (texture(texture0, vec2(fragTexCoord.x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Right
sumValue += (texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y - y)).r < 0.1)? 1 : 0; // Bottom-left
sumValue += (texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y )).r < 0.1)? 1 : 0; // Bottom
sumValue += (texture(texture0, vec2(fragTexCoord.x + x, fragTexCoord.y + y)).r < 0.1)? 1 : 0; // Bottom-right
// Game of life rules:
// Current cell remains alive when 2 or 3 neighbors are alive, dies otherwise
// Current cell goes from dead to alive when exactly 3 neighbors are alive
if (((origValue == 1) && (sumValue == 2)) || sumValue == 3)
finalColor = vec4(0.0, 0.0, 0.0, 255.0); // Alive: draw the pixel black
else
finalColor = fragColor; // Dead: draw the pixel with the background color, RAYWHITE
}

View File

@ -254,9 +254,9 @@ int main(void)
{ {
Color lightColor = (Color){ Color lightColor = (Color){
(unsigned char)(lights[i].color[0]*255), (unsigned char)(lights[i].color[0]*255),
(unsigned char)(lights[i].color[1] * 255), (unsigned char)(lights[i].color[1]*255),
(unsigned char)(lights[i].color[2] * 255), (unsigned char)(lights[i].color[2]*255),
(unsigned char)(lights[i].color[3] * 255) }; (unsigned char)(lights[i].color[3]*255) };
if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lightColor); if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lightColor);
else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f)); else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f));

View File

@ -138,7 +138,7 @@ int main(void)
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
for (int i = 0; i < MAX_TEXTURES; ++i) UnloadTexture(texture[i]); for (int i = 0; i < MAX_TEXTURES; i++) UnloadTexture(texture[i]);
UnloadShader(shdrColorCorrection); UnloadShader(shdrColorCorrection);
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context

View File

@ -40,13 +40,13 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// GBuffer data // GBuffer data
typedef struct GBuffer { typedef struct GBuffer {
unsigned int framebuffer; unsigned int framebufferId;
unsigned int positionTexture; unsigned int positionTextureId;
unsigned int normalTexture; unsigned int normalTextureId;
unsigned int albedoSpecTexture; unsigned int albedoSpecTextureId;
unsigned int depthRenderbuffer; unsigned int depthRenderbufferId;
} GBuffer; } GBuffer;
// Deferred mode passes // Deferred mode passes
@ -90,15 +90,10 @@ int main(void)
// Initialize the G-buffer // Initialize the G-buffer
GBuffer gBuffer = { 0 }; GBuffer gBuffer = { 0 };
gBuffer.framebuffer = rlLoadFramebuffer(); gBuffer.framebufferId = rlLoadFramebuffer();
if (gBuffer.framebufferId == 0) TraceLog(LOG_WARNING, "Failed to create framebufferId");
if (!gBuffer.framebuffer) rlEnableFramebuffer(gBuffer.framebufferId);
{
TraceLog(LOG_WARNING, "Failed to create framebuffer");
exit(1);
}
rlEnableFramebuffer(gBuffer.framebuffer);
// NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture // NOTE: Vertex positions are stored in a texture for simplicity. A better approach would use a depth texture
// (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position, // (instead of a detph renderbuffer) to reconstruct world positions in the final render shader via clip-space position,
@ -107,46 +102,42 @@ int main(void)
// 16-bit precision ensures OpenGL ES 3 compatibility, though it may lack precision for real scenarios // 16-bit precision ensures OpenGL ES 3 compatibility, though it may lack precision for real scenarios
// But as mentioned above, the positions could be reconstructed instead of stored. If not targeting OpenGL ES // But as mentioned above, the positions could be reconstructed instead of stored. If not targeting OpenGL ES
// and you wish to maintain this approach, consider using `RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32` // and you wish to maintain this approach, consider using `RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32`
gBuffer.positionTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1); gBuffer.positionTextureId = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// Similarly, 16-bit precision is used for normals ensures OpenGL ES 3 compatibility // Similarly, 16-bit precision is used for normals ensures OpenGL ES 3 compatibility
// This is generally sufficient, but a 16-bit fixed-point format offer a better uniform precision in all orientations // This is generally sufficient, but a 16-bit fixed-point format offer a better uniform precision in all orientations
gBuffer.normalTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1); gBuffer.normalTextureId = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16, 1);
// Albedo (diffuse color) and specular strength can be combined into one texture // Albedo (diffuse color) and specular strength can be combined into one texture
// The color in RGB, and the specular strength in the alpha channel // The color in RGB, and the specular strength in the alpha channel
gBuffer.albedoSpecTexture = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1); gBuffer.albedoSpecTextureId = rlLoadTexture(NULL, screenWidth, screenHeight, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
// Activate the draw buffers for our framebuffer // Activate the draw buffers for our framebufferId
rlActiveDrawBuffers(3); rlActiveDrawBuffers(3);
// Now we attach our textures to the framebuffer // Now we attach our textures to the framebufferId
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.positionTexture, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.positionTextureId, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.normalTexture, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.normalTextureId, RL_ATTACHMENT_COLOR_CHANNEL1, RL_ATTACHMENT_TEXTURE2D, 0);
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.albedoSpecTexture, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.albedoSpecTextureId, RL_ATTACHMENT_COLOR_CHANNEL2, RL_ATTACHMENT_TEXTURE2D, 0);
// Finally we attach the depth buffer // Finally we attach the depth buffer
gBuffer.depthRenderbuffer = rlLoadTextureDepth(screenWidth, screenHeight, true); gBuffer.depthRenderbufferId = rlLoadTextureDepth(screenWidth, screenHeight, true);
rlFramebufferAttach(gBuffer.framebuffer, gBuffer.depthRenderbuffer, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); rlFramebufferAttach(gBuffer.framebufferId, gBuffer.depthRenderbufferId, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0);
// Make sure our framebuffer is complete // Make sure our framebufferId is complete
// NOTE: rlFramebufferComplete() automatically unbinds the framebuffer, so we don't have // NOTE: rlFramebufferComplete() automatically unbinds the framebufferId, so we don't have to rlDisableFramebuffer() here
// to rlDisableFramebuffer() here if (!rlFramebufferComplete(gBuffer.framebufferId)) TraceLog(LOG_WARNING, "Framebuffer is not complete");
if (!rlFramebufferComplete(gBuffer.framebuffer))
{
TraceLog(LOG_WARNING, "Framebuffer is not complete");
}
// Now we initialize the sampler2D uniform's in the deferred shader // Now we initialize the sampler2D uniform's in the deferred shader
// We do this by setting the uniform's values to the texture units that // We do this by setting the uniform's values to the texture units that
// we later bind our g-buffer textures to // we later bind our g-buffer textures to
rlEnableShader(deferredShader.id); rlEnableShader(deferredShader.id);
int texUnitPosition = 0; int texUnitPosition = 0;
int texUnitNormal = 1; int texUnitNormal = 1;
int texUnitAlbedoSpec = 2; int texUnitAlbedoSpec = 2;
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gPosition"), &texUnitPosition, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gPosition"), &texUnitPosition, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gNormal"), &texUnitNormal, RL_SHADER_UNIFORM_SAMPLER2D);
SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D); SetShaderValue(deferredShader, rlGetLocationUniform(deferredShader.id, "gAlbedoSpec"), &texUnitAlbedoSpec, RL_SHADER_UNIFORM_SAMPLER2D);
rlDisableShader(); rlDisableShader();
// Assign out lighting shader to model // Assign out lighting shader to model
@ -176,7 +167,7 @@ int main(void)
cubeRotations[i] = (float)(rand()%360); cubeRotations[i] = (float)(rand()%360);
} }
DeferredMode mode = DEFERRED_SHADING; int mode = DEFERRED_SHADING;
rlEnableDepthTest(); rlEnableDepthTest();
@ -215,17 +206,16 @@ int main(void)
BeginDrawing(); BeginDrawing();
// Draw to the geometry buffer by first activating it // Draw to the geometry buffer by first activating it
rlEnableFramebuffer(gBuffer.framebuffer); rlEnableFramebuffer(gBuffer.framebufferId);
rlClearColor(0, 0, 0, 0); rlClearColor(0, 0, 0, 0);
rlClearScreenBuffers(); // Clear color and depth buffer rlClearScreenBuffers(); // Clear color and depth buffer
rlDisableColorBlend(); rlDisableColorBlend();
BeginMode3D(camera); BeginMode3D(camera);
// NOTE: We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader` // NOTE: We have to use rlEnableShader here. `BeginShaderMode` or thus `rlSetShader`
// will not work, as they won't immediately load the shader program // will not work, as they won't immediately load the shader program
rlEnableShader(gbufferShader.id); rlEnableShader(gbufferShader.id);
// When drawing a model here, make sure that the material's shaders // When drawing a model here, make sure that the material's shaders are set to the gbuffer shader!
// are set to the gbuffer shader!
DrawModel(model, Vector3Zero(), 1.0f, WHITE); DrawModel(model, Vector3Zero(), 1.0f, WHITE);
DrawModel(cube, (Vector3) { 0.0, 1.0f, 0.0 }, 1.0f, WHITE); DrawModel(cube, (Vector3) { 0.0, 1.0f, 0.0 }, 1.0f, WHITE);
@ -234,12 +224,12 @@ int main(void)
Vector3 position = cubePositions[i]; Vector3 position = cubePositions[i];
DrawModelEx(cube, position, (Vector3) { 1, 1, 1 }, cubeRotations[i], (Vector3) { CUBE_SCALE, CUBE_SCALE, CUBE_SCALE }, WHITE); DrawModelEx(cube, position, (Vector3) { 1, 1, 1 }, cubeRotations[i], (Vector3) { CUBE_SCALE, CUBE_SCALE, CUBE_SCALE }, WHITE);
} }
rlDisableShader(); rlDisableShader();
EndMode3D(); EndMode3D();
rlEnableColorBlend(); rlEnableColorBlend();
// Go back to the default framebuffer (0) and draw our deferred shading // Go back to the default framebufferId (0) and draw our deferred shading
rlDisableFramebuffer(); rlDisableFramebuffer();
rlClearScreenBuffers(); // Clear color & depth buffer rlClearScreenBuffers(); // Clear color & depth buffer
@ -254,21 +244,21 @@ int main(void)
// We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`, // We are binding them to locations that we earlier set in sampler2D uniforms `gPosition`, `gNormal`,
// and `gAlbedoSpec` // and `gAlbedoSpec`
rlActiveTextureSlot(texUnitPosition); rlActiveTextureSlot(texUnitPosition);
rlEnableTexture(gBuffer.positionTexture); rlEnableTexture(gBuffer.positionTextureId);
rlActiveTextureSlot(texUnitNormal); rlActiveTextureSlot(texUnitNormal);
rlEnableTexture(gBuffer.normalTexture); rlEnableTexture(gBuffer.normalTextureId);
rlActiveTextureSlot(texUnitAlbedoSpec); rlActiveTextureSlot(texUnitAlbedoSpec);
rlEnableTexture(gBuffer.albedoSpecTexture); rlEnableTexture(gBuffer.albedoSpecTextureId);
// Finally, we draw a fullscreen quad to our default framebuffer // Finally, we draw a fullscreen quad to our default framebufferId
// This will now be shaded using our deferred shader // This will now be shaded using our deferred shader
rlLoadDrawQuad(); rlLoadDrawQuad();
rlDisableShader(); rlDisableShader();
rlEnableColorBlend(); rlEnableColorBlend();
EndMode3D(); EndMode3D();
// As a last step, we now copy over the depth buffer from our g-buffer to the default framebuffer // As a last step, we now copy over the depth buffer from our g-buffer to the default framebufferId
rlBindFramebuffer(RL_READ_FRAMEBUFFER, gBuffer.framebuffer); rlBindFramebuffer(RL_READ_FRAMEBUFFER, gBuffer.framebufferId);
rlBindFramebuffer(RL_DRAW_FRAMEBUFFER, 0); rlBindFramebuffer(RL_DRAW_FRAMEBUFFER, 0);
rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT rlBlitFramebuffer(0, 0, screenWidth, screenHeight, 0, 0, screenWidth, screenHeight, 0x00000100); // GL_DEPTH_BUFFER_BIT
rlDisableFramebuffer(); rlDisableFramebuffer();
@ -290,7 +280,7 @@ int main(void)
case DEFERRED_POSITION: case DEFERRED_POSITION:
{ {
DrawTextureRec((Texture2D){ DrawTextureRec((Texture2D){
.id = gBuffer.positionTexture, .id = gBuffer.positionTextureId,
.width = screenWidth, .width = screenWidth,
.height = screenHeight, .height = screenHeight,
}, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE);
@ -300,7 +290,7 @@ int main(void)
case DEFERRED_NORMAL: case DEFERRED_NORMAL:
{ {
DrawTextureRec((Texture2D){ DrawTextureRec((Texture2D){
.id = gBuffer.normalTexture, .id = gBuffer.normalTextureId,
.width = screenWidth, .width = screenWidth,
.height = screenHeight, .height = screenHeight,
}, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE);
@ -310,7 +300,7 @@ int main(void)
case DEFERRED_ALBEDO: case DEFERRED_ALBEDO:
{ {
DrawTextureRec((Texture2D){ DrawTextureRec((Texture2D){
.id = gBuffer.albedoSpecTexture, .id = gBuffer.albedoSpecTextureId,
.width = screenWidth, .width = screenWidth,
.height = screenHeight, .height = screenHeight,
}, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE); }, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, Vector2Zero(), RAYWHITE);
@ -331,18 +321,20 @@ int main(void)
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
UnloadModel(model); // Unload the models // Unload the models
UnloadModel(model);
UnloadModel(cube); UnloadModel(cube);
UnloadShader(deferredShader); // Unload shaders // Unload shaders
UnloadShader(deferredShader);
UnloadShader(gbufferShader); UnloadShader(gbufferShader);
// Unload geometry buffer and all attached textures // Unload geometry buffer and all attached textures
rlUnloadFramebuffer(gBuffer.framebuffer); rlUnloadFramebuffer(gBuffer.framebufferId);
rlUnloadTexture(gBuffer.positionTexture); rlUnloadTexture(gBuffer.positionTextureId);
rlUnloadTexture(gBuffer.normalTexture); rlUnloadTexture(gBuffer.normalTextureId);
rlUnloadTexture(gBuffer.albedoSpecTexture); rlUnloadTexture(gBuffer.albedoSpecTextureId);
rlUnloadTexture(gBuffer.depthRenderbuffer); rlUnloadTexture(gBuffer.depthRenderbufferId);
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -0,0 +1,353 @@
/*******************************************************************************************
*
* raylib [shaders] example - game of life
*
* Example complexity rating: [★★★☆] 3/4
*
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* Example contributed by Jordi Santonja (@JordSant) 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 Jordi Santonja (@JordSant)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h" // Required for GUI controls
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Interaction mode
typedef enum {
MODE_RUN = 0,
MODE_PAUSE,
MODE_DRAW,
} InteractionMode;
// Struct to store example preset patterns
typedef struct {
char *name;
Vector2 position;
} PresetPattern;
//----------------------------------------------------------------------------------
// Functions declaration
//----------------------------------------------------------------------------------
void FreeImageToDraw(Image **imageToDraw);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - game of life");
const int menuWidth = 100;
const int windowWidth = screenWidth - menuWidth;
const int windowHeight = screenHeight;
const int worldWidth = 2048;
const int worldHeight = 2048;
const int randomTiles = 8; // Random preset: divide the world to compute random points in each tile
const Rectangle worldRectSource = { 0, 0, (float)worldWidth, (float)-worldHeight };
const Rectangle worldRectDest = { 0, 0, (float)worldWidth, (float)worldHeight };
const Rectangle textureOnScreen = { 0, 0, (float)windowWidth, (float)windowHeight };
const PresetPattern presetPatterns[] = {
{ "Glider", { 0.5f, 0.5f } }, { "R-pentomino", { 0.5f, 0.5f } }, { "Acorn", { 0.5f,0.5f } },
{ "Spaceships", { 0.1f, 0.5f } }, { "Still lifes", { 0.5f, 0.5f } }, { "Oscillators", { 0.5f, 0.5f } },
{ "Puffer train", { 0.1f, 0.5f } }, { "Glider Gun", { 0.2f, 0.2f } }, { "Breeder", { 0.1f, 0.5f } },
{ "Random", { 0.5f, 0.5f } }
};
const int numberOfPresets = sizeof(presetPatterns)/sizeof(presetPatterns[0]);
int zoom = 1;
float offsetX = (worldWidth - windowWidth)/2.0f; // Centered on window
float offsetY = (worldHeight - windowHeight)/2.0f; // Centered on window
int framesPerStep = 1;
int frame = 0;
int preset = -1; // No button pressed for preset
int mode = MODE_RUN; // Starting mode: running
bool buttonZoomIn = false; // Button states: false not pressed
bool buttonZomOut = false;
bool buttonFaster = false;
bool buttonSlower = false;
// Load shader
Shader shdrGameOfLife = LoadShader(0, TextFormat("resources/shaders/glsl%i/game_of_life.fs", GLSL_VERSION));
// Set shader uniform size of the world
int resolutionLoc = GetShaderLocation(shdrGameOfLife, "resolution");
const float resolution[2] = { (float)worldWidth, (float)worldHeight };
SetShaderValue(shdrGameOfLife, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
// Define two textures: the current world and the previous world
RenderTexture2D world1 = LoadRenderTexture(worldWidth, worldHeight);
RenderTexture2D world2 = LoadRenderTexture(worldWidth, worldHeight);
BeginTextureMode(world2);
ClearBackground(RAYWHITE);
EndTextureMode();
Image startPattern = LoadImage("resources/game_of_life/r_pentomino.png");
UpdateTextureRec(world2.texture, (Rectangle){ worldWidth/2.0f, worldHeight/2.0f, (float)(startPattern.width), (float)(startPattern.height) }, startPattern.data);
UnloadImage(startPattern);
// Pointers to the two textures, to be swapped
RenderTexture2D *currentWorld = &world2;
RenderTexture2D *previousWorld = &world1;
// Image to be used in DRAW mode, to be changed with mouse input
Image *imageToDraw = NULL;
SetTargetFPS(60); // Set at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
frame++;
// Change zoom: both by buttons or by mouse wheel
float mouseWheelMove = GetMouseWheelMove();
if (buttonZoomIn || (buttonZomOut && (zoom > 1)) || (mouseWheelMove != 0.0f))
{
FreeImageToDraw(&imageToDraw); // Zoom change: free the image to draw to be recreated again
const float centerX = offsetX + (windowWidth/2.0f)/zoom;
const float centerY = offsetY + (windowHeight/2.0f)/zoom;
if (buttonZoomIn || (mouseWheelMove > 0.0f)) zoom *= 2;
if ((buttonZomOut || (mouseWheelMove < 0.0f)) && (zoom > 1)) zoom /= 2;
offsetX = centerX - (windowWidth/2.0f)/zoom;
offsetY = centerY - (windowHeight/2.0f)/zoom;
}
// Change speed: number of frames per step
if (buttonFaster && framesPerStep > 1) framesPerStep--;
if (buttonSlower) framesPerStep++;
// Mouse management
if ((mode == MODE_RUN) || (mode == MODE_PAUSE))
{
FreeImageToDraw(&imageToDraw); // Free the image to draw: no longer needed in these modes
// Pan with mouse left button
static Vector2 previousMousePosition = { 0.0f, 0.0f };
const Vector2 mousePosition = GetMousePosition();
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && (mousePosition.x < windowWidth))
{
offsetX -= (mousePosition.x - previousMousePosition.x)/zoom;
offsetY -= (mousePosition.y - previousMousePosition.y)/zoom;
}
previousMousePosition = mousePosition;
}
else // MODE_DRAW
{
const float offsetDecimalX = offsetX - floorf(offsetX);
const float offsetDecimalY = offsetY - floorf(offsetY);
int sizeInWorldX = (int)(ceilf((float)(windowWidth + offsetDecimalX*zoom)/zoom));
int sizeInWorldY = (int)(ceilf((float)(windowHeight + offsetDecimalY*zoom)/zoom));
if (offsetX + sizeInWorldX >= worldWidth) sizeInWorldX = worldWidth - (int)floorf(offsetX);
if (offsetY + sizeInWorldY >= worldHeight) sizeInWorldY = worldHeight - (int)floorf(offsetY);
// Create image to draw if not created yet
if (imageToDraw == NULL)
{
RenderTexture2D worldOnScreen = LoadRenderTexture(sizeInWorldX, sizeInWorldY);
BeginTextureMode(worldOnScreen);
DrawTexturePro(currentWorld->texture, (Rectangle) { floorf(offsetX), floorf(offsetY), (float)(sizeInWorldX), -(float)(sizeInWorldY) },
(Rectangle) { 0, 0, (float)(sizeInWorldX), (float)(sizeInWorldY) }, (Vector2) { 0, 0 }, 0.0f, WHITE);
EndTextureMode();
imageToDraw = (Image*)RL_MALLOC(sizeof(Image));
*imageToDraw = LoadImageFromTexture(worldOnScreen.texture);
UnloadRenderTexture(worldOnScreen);
}
const Vector2 mousePosition = GetMousePosition();
static int firstColor = -1;
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && (mousePosition.x < windowWidth))
{
int mouseX = (int)(mousePosition.x + offsetDecimalX*zoom)/zoom;
int mouseY = (int)(mousePosition.y + offsetDecimalY*zoom)/zoom;
if (mouseX >= sizeInWorldX) mouseX = sizeInWorldX - 1;
if (mouseY >= sizeInWorldY) mouseY = sizeInWorldY - 1;
if (firstColor == -1) firstColor = (GetImageColor(*imageToDraw, mouseX, mouseY).r < 5)? 0 : 1;
const int prevColor = (GetImageColor(*imageToDraw, mouseX, mouseY).r < 5)? 0 : 1;
ImageDrawPixel(imageToDraw, mouseX, mouseY, (firstColor) ? BLACK : RAYWHITE);
if (prevColor != firstColor) UpdateTextureRec(currentWorld->texture, (Rectangle){ floorf(offsetX), floorf(offsetY), (float)(sizeInWorldX), (float)(sizeInWorldY) }, imageToDraw->data);
}
else firstColor = -1;
}
// Load selected preset
if (preset >= 0)
{
Image pattern;
if (preset < numberOfPresets - 1) // Preset with pattern image lo load
{
switch (preset)
{
case 0: pattern = LoadImage("resources/game_of_life/glider.png"); break;
case 1: pattern = LoadImage("resources/game_of_life/r_pentomino.png"); break;
case 2: pattern = LoadImage("resources/game_of_life/acorn.png"); break;
case 3: pattern = LoadImage("resources/game_of_life/spaceships.png"); break;
case 4: pattern = LoadImage("resources/game_of_life/still_lifes.png"); break;
case 5: pattern = LoadImage("resources/game_of_life/oscillators.png"); break;
case 6: pattern = LoadImage("resources/game_of_life/puffer_train.png"); break;
case 7: pattern = LoadImage("resources/game_of_life/glider_gun.png"); break;
case 8: pattern = LoadImage("resources/game_of_life/breeder.png"); break;
}
BeginTextureMode(*currentWorld);
ClearBackground(RAYWHITE);
EndTextureMode();
UpdateTextureRec(currentWorld->texture, (Rectangle){ worldWidth*presetPatterns[preset].position.x - pattern.width/2.0f,
worldHeight*presetPatterns[preset].position.y - pattern.height/2.0f,
(float)(pattern.width), (float)(pattern.height) }, pattern.data);
}
else // Last preset: Random values
{
pattern = GenImageColor(worldWidth/randomTiles, worldHeight/randomTiles, RAYWHITE);
for (int i = 0; i < randomTiles; i++)
{
for (int j = 0; j < randomTiles; j++)
{
ImageClearBackground(&pattern, RAYWHITE);
for (int x = 0; x < pattern.width; x++)
{
for (int y = 0; y < pattern.height; y++)
{
if (GetRandomValue(0, 100) < 15) ImageDrawPixel(&pattern, x, y, BLACK);
}
}
UpdateTextureRec(currentWorld->texture,
(Rectangle){ (float)(pattern.width*i), (float)(pattern.height*j),
(float)(pattern.width), (float)(pattern.height) }, pattern.data);
}
}
}
UnloadImage(pattern);
mode = MODE_PAUSE;
offsetX = worldWidth*presetPatterns[preset].position.x - (float)windowWidth/zoom/2.0f;
offsetY = worldHeight*presetPatterns[preset].position.y - (float)windowHeight/zoom/2.0f;
}
// Check window draw inside world limits
if (offsetX < 0) offsetX = 0;
if (offsetY < 0) offsetY = 0;
if (offsetX > worldWidth - (float)(windowWidth)/zoom) offsetX = worldWidth - (float)(windowWidth)/zoom;
if (offsetY > worldHeight - (float)(windowHeight)/zoom) offsetY = worldHeight - (float)(windowHeight)/zoom;
// Rectangles for drawing texture portion to screen
const Rectangle textureSourceToScreen = { offsetX, offsetY, (float)windowWidth/zoom, (float)windowHeight/zoom };
//----------------------------------------------------------------------------------
// Draw to texture
//----------------------------------------------------------------------------------
if ((mode == MODE_RUN) && ((frame%framesPerStep) == 0))
{
// Swap worlds
RenderTexture2D *tempWorld = currentWorld;
currentWorld = previousWorld;
previousWorld = tempWorld;
// Draw to texture
BeginTextureMode(*currentWorld);
BeginShaderMode(shdrGameOfLife);
DrawTexturePro(previousWorld->texture, worldRectSource, worldRectDest, (Vector2){ 0, 0 }, 0.0f, RAYWHITE);
EndShaderMode();
EndTextureMode();
}
//----------------------------------------------------------------------------------
// Draw to screen
//----------------------------------------------------------------------------------
BeginDrawing();
DrawTexturePro(currentWorld->texture, textureSourceToScreen, textureOnScreen, (Vector2){ 0, 0 }, 0.0f, WHITE);
DrawLine(windowWidth, 0, windowWidth, screenHeight, (Color){ 218, 218, 218, 255 });
DrawRectangle(windowWidth, 0, screenWidth - windowWidth, screenHeight, (Color){ 232, 232, 232, 255 });
DrawText("Conway's", 704, 4, 20, DARKBLUE);
DrawText(" game of", 704, 19, 20, DARKBLUE);
DrawText(" life", 708, 34, 20, DARKBLUE);
DrawText("in raylib", 757, 42, 6, BLACK);
DrawText("Presets", 710, 58, 8, GRAY);
preset = -1;
for (int i = 0; i < numberOfPresets; i++)
if (GuiButton((Rectangle){ 710.0f, 70.0f + 18*i, 80.0f, 16.0f }, presetPatterns[i].name)) preset = i;
GuiToggleGroup((Rectangle){ 710, 258, 80, 16 }, "Run\nPause\nDraw", &mode);
DrawText(TextFormat("Zoom: %ix", zoom), 710, 316, 8, GRAY);
buttonZoomIn = GuiButton((Rectangle){ 710, 328, 80, 16 }, "Zoom in");
buttonZomOut = GuiButton((Rectangle){ 710, 346, 80, 16 }, "Zoom out");
DrawText(TextFormat("Speed: %i frame%s", framesPerStep, (framesPerStep > 1)? "s" : ""), 710, 370, 8, GRAY);
buttonFaster = GuiButton((Rectangle){ 710, 382, 80, 16 }, "Faster");
buttonSlower = GuiButton((Rectangle){ 710, 400, 80, 16 }, "Slower");
DrawFPS(712, 426);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shdrGameOfLife);
UnloadRenderTexture(world1);
UnloadRenderTexture(world2);
FreeImageToDraw(&imageToDraw);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Functions definition
//----------------------------------------------------------------------------------
void FreeImageToDraw(Image **imageToDraw)
{
if (*imageToDraw != NULL)
{
UnloadImage(**imageToDraw);
RL_FREE(*imageToDraw);
*imageToDraw = NULL;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -138,7 +138,7 @@ int main(void)
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawTextureRec(target.texture, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, (Vector2) { 0, 0 }, WHITE); DrawTextureRec(target.texture, (Rectangle) { 0, 0, (float)screenWidth, (float)-screenHeight }, (Vector2) { 0, 0 }, WHITE);
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -0,0 +1,221 @@
/*******************************************************************************************
*
* raylib [shapes] example - ball physics
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* 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) 2025 David Buzatto (@davidbuzatto)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h>
#include <math.h>
#define MAX_BALLS 5000 // Maximum quantity of balls
typedef struct Ball {
Vector2 pos; // Position
Vector2 vel; // Velocity
Vector2 ppos; // Previous position
float radius;
float friction;
float elasticity;
Color color;
bool grabbed;
} Ball;
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ball physics");
Ball balls[MAX_BALLS] = {{
.pos = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f },
.vel = { 200, 200 },
.ppos = { 0 },
.radius = 40,
.friction = 0.99f,
.elasticity = 0.9f,
.color = BLUE,
.grabbed = false
}};
int ballCount = 1;
Ball *grabbedBall = NULL; // A pointer to the current ball that is grabbed
Vector2 pressOffset = {0}; // Mouse press offset relative to the ball that grabbedd
float gravity = 100; // World gravity
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
float delta = GetFrameTime();
Vector2 mousePos = GetMousePosition();
// Checks if a ball was grabbed
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
for (int i = ballCount - 1; i >= 0; i--)
{
Ball *ball = &balls[i];
pressOffset.x = mousePos.x - ball->pos.x;
pressOffset.y = mousePos.y - ball->pos.y;
// If the distance between the ball position and the mouse press position
// is less than or equal to the ball radius, the event occurred inside the ball
if (hypot(pressOffset.x, pressOffset.y) <= ball->radius)
{
ball->grabbed = true;
grabbedBall = ball;
break;
}
}
}
// Releases any ball the was grabbed
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
{
if (grabbedBall != NULL)
{
grabbedBall->grabbed = false;
grabbedBall = NULL;
}
}
// Creates a new ball
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) || (IsKeyDown(KEY_LEFT_CONTROL) && IsMouseButtonDown(MOUSE_BUTTON_RIGHT)))
{
if (ballCount < MAX_BALLS)
{
balls[ballCount++] = (Ball){
.pos = mousePos,
.vel = { (float)GetRandomValue(-300, 300), (float)GetRandomValue(-300, 300) },
.ppos = { 0 },
.radius = 20.0f + (float)GetRandomValue(0, 30),
.friction = 0.99f,
.elasticity = 0.9f,
.color = { GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 },
.grabbed = false
};
}
}
// Shake balls
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
{
for (int i = 0; i < ballCount; i++)
{
if (!balls[i].grabbed) balls[i].vel = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) };
}
}
// Changes gravity
gravity += GetMouseWheelMove()*5;
// Updates each ball state
for (int i = 0; i < ballCount; i++)
{
Ball *ball = &balls[i];
// The ball is not grabbed
if (!ball->grabbed)
{
// Ball repositioning using the velocity
ball->pos.x += ball->vel.x * delta;
ball->pos.y += ball->vel.y * delta;
// Does the ball hit the screen right boundary?
if ((ball->pos.x + ball->radius) >= screenWidth)
{
ball->pos.x = screenWidth - ball->radius; // Ball repositioning
ball->vel.x = -ball->vel.x*ball->elasticity; // Elasticity makes the ball lose 10% of its velocity on hit
}
// Does the ball hit the screen left boundary?
else if ((ball->pos.x - ball->radius) <= 0)
{
ball->pos.x = ball->radius;
ball->vel.x = -ball->vel.x*ball->elasticity;
}
// The same for y axis
if ((ball->pos.y + ball->radius) >= screenHeight)
{
ball->pos.y = screenHeight - ball->radius;
ball->vel.y = -ball->vel.y*ball->elasticity;
}
else if ((ball->pos.y - ball->radius) <= 0)
{
ball->pos.y = ball->radius;
ball->vel.y = -ball->vel.y*ball->elasticity;
}
// Friction makes the ball lose 1% of its velocity each frame
ball->vel.x = ball->vel.x*ball->friction;
// Gravity affects only the y axis
ball->vel.y = ball->vel.y*ball->friction + gravity;
}
else
{
// Ball repositioning using the mouse position
ball->pos.x = mousePos.x - pressOffset.x;
ball->pos.y = mousePos.y - pressOffset.y;
// While the ball is grabbed, recalculates its velocity
ball->vel.x = (ball->pos.x - ball->ppos.x)/delta;
ball->vel.y = (ball->pos.y - ball->ppos.y)/delta;
ball->ppos = ball->pos;
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < ballCount; i++)
{
DrawCircleV(balls[i].pos, balls[i].radius, balls[i].color);
DrawCircleLinesV(balls[i].pos, balls[i].radius, BLACK);
}
DrawText("grab a ball by pressing with the mouse and throw it by releasing", 10, 10, 10, DARKGRAY);
DrawText("right click to create new balls (keep left control pressed to create a lot)", 10, 30, 10, DARKGRAY);
DrawText("use mouse wheel to change gravity", 10, 50, 10, DARKGRAY);
DrawText("middle click to shake", 10, 70, 10, DARKGRAY);
DrawText(TextFormat("BALL COUNT: %d", ballCount), 10, GetScreenHeight() - 70, 20, BLACK);
DrawText(TextFormat("GRAVITY: %.2f", gravity), 10, GetScreenHeight() - 40, 20, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -107,7 +107,7 @@ int main(void)
float bulletDirection = baseDirection + (degreesPerRow*row); float bulletDirection = baseDirection + (degreesPerRow*row);
// Bullet speed * bullet direction, this will determine how much pixels will be incremented/decremented // Bullet speed*bullet direction, this will determine how much pixels will be incremented/decremented
// from the bullet position every frame. Since the bullets doesn't change its direction and speed, // from the bullet position every frame. Since the bullets doesn't change its direction and speed,
// only need to calculate it at the spawning time // only need to calculate it at the spawning time
// 0 degrees = right, 90 degrees = down, 180 degrees = left and 270 degrees = up, basically clockwise // 0 degrees = right, 90 degrees = down, 180 degrees = left and 270 degrees = up, basically clockwise

View File

@ -14,9 +14,6 @@
* Copyright (c) 2025 JP Mortiboys (@themushroompirates) * Copyright (c) 2025 JP Mortiboys (@themushroompirates)
* *
********************************************************************************************/ ********************************************************************************************/
#if defined(WIN32)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "raylib.h" #include "raylib.h"
@ -63,24 +60,16 @@ int main(void)
/* 8 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR }, /* 8 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR },
/* 9 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR }, /* 9 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR },
}; };
// Time for the hands to move to the new position (in seconds); this must be <1s // Time for the hands to move to the new position (in seconds); this must be <1s
const float handsMoveDuration = .5f; const float handsMoveDuration = 0.5f;
// We store the previous seconds value so we can see if the time has changed
int prevSeconds = -1; int prevSeconds = -1;
// This represents the real position where the hands are right now
Vector2 currentAngles[6][24] = { 0 }; Vector2 currentAngles[6][24] = { 0 };
// This is the position where the hands were moving from
Vector2 srcAngles[6][24] = { 0 }; Vector2 srcAngles[6][24] = { 0 };
// This is the position where the hands are moving to
Vector2 dstAngles[6][24] = { 0 }; Vector2 dstAngles[6][24] = { 0 };
// Current animation timer
float handsMoveTimer = 0.0f; float handsMoveTimer = 0.0f;
// 12 or 24 hour mode
int hourMode = 24; int hourMode = 24;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second SetTargetFPS(60); // Set our game to run at 60 frames-per-second
@ -91,7 +80,6 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Get the current time // Get the current time
time_t rawtime; time_t rawtime;
struct tm *timeinfo; struct tm *timeinfo;
@ -99,30 +87,26 @@ int main(void)
time(&rawtime); time(&rawtime);
timeinfo = localtime(&rawtime); timeinfo = localtime(&rawtime);
if (timeinfo->tm_sec != prevSeconds) { if (timeinfo->tm_sec != prevSeconds)
{
// The time has changed, so we need to move the hands to the new positions // The time has changed, so we need to move the hands to the new positions
prevSeconds = timeinfo->tm_sec; prevSeconds = timeinfo->tm_sec;
// Format the current time so we can access the individual digits // Format the current time so we can access the individual digits
const char *clockDigits = TextFormat("%02d%02d%02d", timeinfo->tm_hour % hourMode, timeinfo->tm_min, timeinfo->tm_sec); const char *clockDigits = TextFormat("%02d%02d%02d", timeinfo->tm_hour%hourMode, timeinfo->tm_min, timeinfo->tm_sec);
// Fetch where we want all the hands to be // Fetch where we want all the hands to be
for (int digit = 0; digit < 6; digit++) { for (int digit = 0; digit < 6; digit++)
for (int cell = 0; cell < 24; cell++) { {
for (int cell = 0; cell < 24; cell++)
{
srcAngles[digit][cell] = currentAngles[digit][cell]; srcAngles[digit][cell] = currentAngles[digit][cell];
dstAngles[digit][cell] = digitAngles[ clockDigits[digit] - '0' ][cell]; dstAngles[digit][cell] = digitAngles[clockDigits[digit] - '0'][cell];
// Quick exception for 12h mode // Quick exception for 12h mode
if (digit == 0 && hourMode == 12 && clockDigits[0] == '0') { if ((digit == 0) && (hourMode == 12) && (clockDigits[0] == '0')) dstAngles[digit][cell] = ZZ;
dstAngles[digit][cell] = ZZ; if (srcAngles[digit][cell].x > dstAngles[digit][cell].x) srcAngles[digit][cell].x -= 360.0f;
} if (srcAngles[digit][cell].y > dstAngles[digit][cell].y) srcAngles[digit][cell].y -= 360.0f;
if (srcAngles[digit][cell].x > dstAngles[digit][cell].x) {
srcAngles[digit][cell].x -= 360.0f;
}
if (srcAngles[digit][cell].y > dstAngles[digit][cell].y) {
srcAngles[digit][cell].y -= 360.0f;
}
} }
} }
@ -131,37 +115,29 @@ int main(void)
} }
// Now let's animate all the hands if we need to // Now let's animate all the hands if we need to
if (handsMoveTimer < handsMoveDuration) { if (handsMoveTimer < handsMoveDuration)
{
// Increase the timer but don't go above the maximum // Increase the timer but don't go above the maximum
handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration); handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration);
// Calculate the % completion of the animation // Calculate the%completion of the animation
float t = handsMoveTimer / handsMoveDuration; float t = handsMoveTimer/handsMoveDuration;
// A little cheeky smoothstep // A little cheeky smoothstep
t = t * t * (3.0f - 2.0f * t); t = t*t*(3.0f - 2.0f*t);
for (int digit = 0; digit < 6; digit++) { for (int digit = 0; digit < 6; digit++)
for (int cell = 0; cell < 24; cell++) { {
for (int cell = 0; cell < 24; cell++)
{
currentAngles[digit][cell].x = Lerp(srcAngles[digit][cell].x, dstAngles[digit][cell].x, t); currentAngles[digit][cell].x = Lerp(srcAngles[digit][cell].x, dstAngles[digit][cell].x, t);
currentAngles[digit][cell].y = Lerp(srcAngles[digit][cell].y, dstAngles[digit][cell].y, t); currentAngles[digit][cell].y = Lerp(srcAngles[digit][cell].y, dstAngles[digit][cell].y, t);
} }
} }
if (handsMoveTimer == handsMoveDuration) {
// The animation has now finished
}
} }
// Handle input // Handle input
if (IsKeyPressed(KEY_SPACE)) hourMode = 36 - hourMode; // Toggle between 12 and 24 hour mode with space
// Toggle between 12 and 24 hour mode with space
if (IsKeyPressed(KEY_SPACE)) {
hourMode = 36 - hourMode;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -174,19 +150,22 @@ int main(void)
float xOffset = 4.0f; float xOffset = 4.0f;
for (int digit = 0; digit < 6; digit++) { for (int digit = 0; digit < 6; digit++)
{
for (int row = 0; row < 6; row++) { for (int row = 0; row < 6; row++)
for (int col = 0; col < 4; col++) { {
for (int col = 0; col < 4; col++)
{
Vector2 centre = (Vector2){ Vector2 centre = (Vector2){
xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f, xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f,
100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f 100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize*0.5f
}; };
DrawRing(centre, clockFaceSize * 0.5f - 2.0f, clockFaceSize * 0.5f, 0, 360, 24, DARKGRAY);
DrawRing(centre, clockFaceSize*0.5f - 2.0f, clockFaceSize*0.5f, 0, 360, 24, DARKGRAY);
// Big hand // Big hand
DrawRectanglePro( DrawRectanglePro(
(Rectangle){centre.x, centre.y, clockFaceSize*.5f+4.0f, 4.0f}, (Rectangle){centre.x, centre.y, clockFaceSize*0.5f+4.0f, 4.0f},
(Vector2){ 2.0f, 2.0f }, (Vector2){ 2.0f, 2.0f },
currentAngles[digit][row*4+col].x, currentAngles[digit][row*4+col].x,
handsColor handsColor
@ -194,7 +173,7 @@ int main(void)
// Little hand // Little hand
DrawRectanglePro( DrawRectanglePro(
(Rectangle){centre.x, centre.y, clockFaceSize*.5f+2.0f, 4.0f}, (Rectangle){centre.x, centre.y, clockFaceSize*0.5f+2.0f, 4.0f},
(Vector2){ 2.0f, 2.0f }, (Vector2){ 2.0f, 2.0f },
currentAngles[digit][row*4+col].y, currentAngles[digit][row*4+col].y,
handsColor handsColor
@ -202,27 +181,23 @@ int main(void)
} }
} }
xOffset += (clockFaceSize+clockFaceSpacing) * 4; xOffset += (clockFaceSize+clockFaceSpacing)*4;
if (digit % 2 == 1) { if (digit%2 == 1)
{
DrawRing((Vector2){xOffset + 4.0f, 160.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor); DrawRing((Vector2){xOffset + 4.0f, 160.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
DrawRing((Vector2){xOffset + 4.0f, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor); DrawRing((Vector2){xOffset + 4.0f, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor);
xOffset += sectionSpacing; xOffset += sectionSpacing;
} }
} }
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------

View File

@ -45,7 +45,7 @@ int main(void)
for (int i = 0; i < MAX_COLORS_COUNT; i++) for (int i = 0; i < MAX_COLORS_COUNT; i++)
{ {
colorsRecs[i].x = 20.0f + 100.0f *(i%7) + 10.0f *(i%7); colorsRecs[i].x = 20.0f + 100.0f *(i%7) + 10.0f *(i%7);
colorsRecs[i].y = 80.0f + 100.0f *(i/7) + 10.0f *(i/7); colorsRecs[i].y = 80.0f + 100.0f *((float)i/7) + 10.0f *((float)i/7);
colorsRecs[i].width = 100.0f; colorsRecs[i].width = 100.0f;
colorsRecs[i].height = 100.0f; colorsRecs[i].height = 100.0f;
} }

View File

@ -311,7 +311,7 @@ static void DrawDisplaySegment(Vector2 center, int length, int thick, bool verti
(Vector2){ center.x + thick/2.0f, center.y - length/2.0f }, // Point 3 (Vector2){ center.x + thick/2.0f, center.y - length/2.0f }, // Point 3
(Vector2){ center.x - thick/2.0f, center.y + length/2.0f }, // Point 4 (Vector2){ center.x - thick/2.0f, center.y + length/2.0f }, // Point 4
(Vector2){ center.x + thick/2.0f, center.y + length/2.0f }, // Point 5 (Vector2){ center.x + thick/2.0f, center.y + length/2.0f }, // Point 5
(Vector2){ center.x, center.y + length/2 + thick/2.0f }, // Point 6 (Vector2){ center.x, center.y + (float)length/2 + thick/2.0f }, // Point 6
}; };
DrawTriangleStrip(segmentPointsV, 6, color); DrawTriangleStrip(segmentPointsV, 6, color);

View File

@ -42,15 +42,15 @@ int main(void)
SetConfigFlags(FLAG_WINDOW_HIGHDPI); SetConfigFlags(FLAG_WINDOW_HIGHDPI);
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - double pendulum"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - double pendulum");
// Simulation Paramters // Simulation Parameters
float l1 = 15.0f, m1 = 0.2f, theta1 = DEG2RAD*170, w1 = 0; float l1 = 15.0f, m1 = 0.2f, theta1 = DEG2RAD*170, w1 = 0;
float l2 = 15.0f, m2 = 0.1f, theta2 = DEG2RAD*0, w2 = 0; float l2 = 15.0f, m2 = 0.1f, theta2 = DEG2RAD*0, w2 = 0;
float lengthScaler = 0.1f; float lengthScaler = 0.1f;
float totalM = m1 + m2; float totalM = m1 + m2;
Vector2 previousPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2); Vector2 previousPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
previousPosition.x += (screenWidth/2); previousPosition.x += ((float)screenWidth/2);
previousPosition.y += (screenHeight/2 - 100); previousPosition.y += ((float)screenHeight/2 - 100);
// Scale length // Scale length
float L1 = l1*lengthScaler; float L1 = l1*lengthScaler;
@ -76,7 +76,7 @@ int main(void)
float step = dt/SIMULATION_STEPS, step2 = step*step; float step = dt/SIMULATION_STEPS, step2 = step*step;
// Update Physics - larger steps = better approximation // Update Physics - larger steps = better approximation
for (int i = 0; i < SIMULATION_STEPS; ++i) for (int i = 0; i < SIMULATION_STEPS; i++)
{ {
float delta = theta1 - theta2; float delta = theta1 - theta2;
float sinD = sinf(delta), cosD = cosf(delta), cos2D = cosf(2*delta); float sinD = sinf(delta), cosD = cosf(delta), cos2D = cosf(2*delta);
@ -105,8 +105,8 @@ int main(void)
// Calculate position // Calculate position
Vector2 currentPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2); Vector2 currentPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2);
currentPosition.x += screenWidth/2; currentPosition.x += (float)screenWidth/2;
currentPosition.y += screenHeight/2 - 100; currentPosition.y += (float)screenHeight/2 - 100;
// Draw to render texture // Draw to render texture
BeginTextureMode(target); BeginTextureMode(target);

View File

@ -0,0 +1,196 @@
/*******************************************************************************************
*
* raylib [shapes] example - hilbert curve
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* Example contributed by Hamza RAHAL (@hmz-rhl) 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 Hamza RAHAL (@hmz-rhl)
*
********************************************************************************************/
#include "raylib.h"
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include <stdlib.h> // Required for: calloc(), free()
//------------------------------------------------------------------------------------
// Module Functions Declaration
//------------------------------------------------------------------------------------
static Vector2 *LoadHilbertPath(int order, float size, int *strokeCount);
static void UnloadHilbertPath(Vector2 *hilbertPath);
static Vector2 ComputeHilbertStep(int order, int index);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - hilbert curve");
int order = 2;
float size = GetScreenHeight();
int strokeCount = 0;
Vector2 *hilbertPath = LoadHilbertPath(order, size, &strokeCount);
int prevOrder = order;
int prevSize = (int)size; // NOTE: Size from slider is float but for comparison we use int
int counter = 0;
float thick = 2.0f;
bool animate = true;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
//--------------------------------------------------------------------------------------
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// Check if order or size have changed to regenerate
// NOTE: Size from slider is float but for comparison we use int
if ((prevOrder != order) || (prevSize != (int)size))
{
UnloadHilbertPath(hilbertPath);
hilbertPath = LoadHilbertPath(order, size, &strokeCount);
if (animate) counter = 0;
else counter = strokeCount;
prevOrder = order;
prevSize = size;
}
//----------------------------------------------------------------------------------
// Draw
//--------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (counter < strokeCount)
{
// Draw Hilbert path animation, one stroke every frame
for (int i = 1; i <= counter; i++)
{
DrawLineEx(hilbertPath[i], hilbertPath[i - 1], thick, ColorFromHSV(((float)i/strokeCount)*360.0f, 1.0f, 1.0f));
}
counter += 1;
}
else
{
// Draw full Hilbert path
for (int i = 1; i < strokeCount; i++)
{
DrawLineEx(hilbertPath[i], hilbertPath[i - 1], thick, ColorFromHSV(((float)i/strokeCount)*360.0f, 1.0f, 1.0f));
}
}
// Draw UI using raygui
GuiCheckBox((Rectangle){ 450, 50, 20, 20 }, "ANIMATE GENERATION ON CHANGE", &animate);
GuiSpinner((Rectangle){ 585, 100, 180, 30 }, "HILBERT CURVE ORDER: ", &order, 2, 8, false);
GuiSlider((Rectangle){ 524, 150, 240, 24 }, "THICKNESS: ", NULL, &thick, 1.0f, 10.0f);
GuiSlider((Rectangle){ 524, 190, 240, 24 }, "TOTAL SIZE: ", NULL, &size, 10.0f, GetScreenHeight()*1.5f);
EndDrawing();
//--------------------------------------------------------------------------
}
//--------------------------------------------------------------------------------------
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadHilbertPath(hilbertPath);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------
// Module Functions Definition
//------------------------------------------------------------------------------------
// Load the whole Hilbert Path (including each U and their link)
static Vector2 *LoadHilbertPath(int order, float size, int *strokeCount)
{
int N = 1 << order;
float len = size/N;
*strokeCount = N*N;
Vector2 *hilbertPath = (Vector2 *)RL_CALLOC(*strokeCount, sizeof(Vector2));
for (int i = 0; i < *strokeCount; i++)
{
hilbertPath[i] = ComputeHilbertStep(order, i);
hilbertPath[i].x = hilbertPath[i].x*len + len/2.0f;
hilbertPath[i].y = hilbertPath[i].y*len + len/2.0f;
}
return hilbertPath;
}
// Unload Hilbert path data
static void UnloadHilbertPath(Vector2 *hilbertPath)
{
RL_FREE(hilbertPath);
}
// Compute Hilbert path U positions
static Vector2 ComputeHilbertStep(int order, int index)
{
// Hilbert points base pattern
static const Vector2 hilbertPoints[4] = {
[0] = { .x = 0, .y = 0 },
[1] = { .x = 0, .y = 1 },
[2] = { .x = 1, .y = 1 },
[3] = { .x = 1, .y = 0 },
};
int hilbertIndex = index&3;
Vector2 vect = hilbertPoints[hilbertIndex];
float temp = 0.0f;
int len = 0;
for (int j = 1; j < order; j++)
{
index = index >> 2;
hilbertIndex = index&3;
len = 1 << j;
switch (hilbertIndex)
{
case 0:
{
temp = vect.x;
vect.x = vect.y;
vect.y = temp;
} break;
case 2: vect.x += len;
case 1: vect.y += len; break;
case 3:
{
temp = len - 1 - vect.x;
vect.x = 2*len - 1 - vect.y;
vect.y = temp;
} break;
default: break;
}
}
return vect;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -16,7 +16,10 @@
********************************************************************************************/ ********************************************************************************************/
#include "raylib.h" #include "raylib.h"
#include <string.h>
#define RAYGUI_IMPLEMENTATION
#include "raygui.h"
#include "raymath.h" #include "raymath.h"
#define MAX_DRAW_LINES 8192 #define MAX_DRAW_LINES 8192
@ -47,6 +50,9 @@ int main(void)
int symmetry = 6; int symmetry = 6;
float angle = 360.0f/(float)symmetry; float angle = 360.0f/(float)symmetry;
float thickness = 3.0f; float thickness = 3.0f;
Rectangle resetButtonRec = { screenWidth - 55.0f, 5.0f, 50, 25 };
Rectangle backButtonRec = { screenWidth - 55.0f, screenHeight - 30.0f, 25, 25 };
Rectangle nextButtonRec = { screenWidth - 30.0f, screenHeight - 30.0f, 25, 25 };
Vector2 mousePos = { 0 }; Vector2 mousePos = { 0 };
Vector2 prevMousePos = { 0 }; Vector2 prevMousePos = { 0 };
Vector2 scaleVector = { 1.0f, -1.0f }; Vector2 scaleVector = { 1.0f, -1.0f };
@ -58,7 +64,11 @@ int main(void)
camera.rotation = 0.0f; camera.rotation = 0.0f;
camera.zoom = 1.0f; camera.zoom = 1.0f;
int lineCounter = 0; int currentLineCounter = 0;
int totalLineCounter = 0;
int resetButtonClicked = false;
int backButtonClicked = false;
int nextButtonClicked = false;
SetTargetFPS(20); SetTargetFPS(20);
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -74,24 +84,47 @@ int main(void)
Vector2 lineStart = Vector2Subtract(mousePos, offset); Vector2 lineStart = Vector2Subtract(mousePos, offset);
Vector2 lineEnd = Vector2Subtract(prevMousePos, offset); Vector2 lineEnd = Vector2Subtract(prevMousePos, offset);
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) if (
IsMouseButtonDown(MOUSE_LEFT_BUTTON)
&& (CheckCollisionPointRec(mousePos, resetButtonRec) == false)
&& (CheckCollisionPointRec(mousePos, backButtonRec) == false)
&& (CheckCollisionPointRec(mousePos, nextButtonRec) == false)
)
{ {
for (int s = 0; (s < symmetry) && (lineCounter < (MAX_DRAW_LINES - 1)); s++) for (int s = 0; (s < symmetry) && (totalLineCounter < (MAX_DRAW_LINES - 1)); s++)
{ {
lineStart = Vector2Rotate(lineStart, angle*DEG2RAD); lineStart = Vector2Rotate(lineStart, angle*DEG2RAD);
lineEnd = Vector2Rotate(lineEnd, angle*DEG2RAD); lineEnd = Vector2Rotate(lineEnd, angle*DEG2RAD);
// Store mouse line // Store mouse line
lines[lineCounter].start = lineStart; lines[totalLineCounter].start = lineStart;
lines[lineCounter].end = lineEnd; lines[totalLineCounter].end = lineEnd;
// Store reflective line // Store reflective line
lines[lineCounter + 1].start = Vector2Multiply(lineStart, scaleVector); lines[totalLineCounter + 1].start = Vector2Multiply(lineStart, scaleVector);
lines[lineCounter + 1].end = Vector2Multiply(lineEnd, scaleVector); lines[totalLineCounter + 1].end = Vector2Multiply(lineEnd, scaleVector);
lineCounter += 2; totalLineCounter += 2;
currentLineCounter = totalLineCounter;
} }
} }
if (resetButtonClicked)
{
memset(&lines, 0, sizeof(Line)*MAX_DRAW_LINES);
currentLineCounter = 0;
totalLineCounter = 0;
}
if (backButtonClicked && (currentLineCounter > 0))
{
currentLineCounter -= 1;
}
if (nextButtonClicked && (currentLineCounter < MAX_DRAW_LINES) && ((currentLineCounter + 1) <= totalLineCounter))
{
currentLineCounter += 1;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -99,19 +132,31 @@ int main(void)
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
BeginMode2D(camera); BeginMode2D(camera);
for (int s = 0; s < symmetry; s++) for (int s = 0; s < symmetry; s++)
{ {
for (int i = 0; i < lineCounter; i += 2) for (int i = 0; i < currentLineCounter; i += 2)
{ {
DrawLineEx(lines[i].start, lines[i].end, thickness, BLACK); DrawLineEx(lines[i].start, lines[i].end, thickness, BLACK);
DrawLineEx(lines[i + 1].start, lines[i + 1].end, thickness, BLACK); DrawLineEx(lines[i + 1].start, lines[i + 1].end, thickness, BLACK);
} }
} }
EndMode2D(); EndMode2D();
DrawText(TextFormat("LINES: %i/%i", lineCounter, MAX_DRAW_LINES), 10, screenHeight - 30, 20, MAROON); if ((currentLineCounter - 1) < 0) GuiDisable();
backButtonClicked = GuiButton(backButtonRec, "<");
GuiEnable();
if ((currentLineCounter + 1) > totalLineCounter) GuiDisable();
nextButtonClicked = GuiButton(nextButtonRec, ">");
GuiEnable();
resetButtonClicked = GuiButton(resetButtonRec, "Reset");
DrawText(TextFormat("LINES: %i/%i", currentLineCounter, MAX_DRAW_LINES), 10, screenHeight - 30, 20, MAROON);
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -31,7 +31,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math angle rotation"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math angle rotation");
SetTargetFPS(60); SetTargetFPS(60);
Vector2 center = { screenWidth / 2.0f, screenHeight / 2.0f }; Vector2 center = { screenWidth/2.0f, screenHeight/2.0f };
const float lineLength = 150.0f; const float lineLength = 150.0f;
// Predefined angles for fixed lines // Predefined angles for fixed lines
@ -60,9 +60,9 @@ int main(void)
// Draw fixed-angle lines with colorful gradient // Draw fixed-angle lines with colorful gradient
for (int i = 0; i < numAngles; i++) for (int i = 0; i < numAngles; i++)
{ {
float rad = angles[i] * DEG2RAD; float rad = angles[i]*DEG2RAD;
Vector2 end = { center.x + cosf(rad) * lineLength, Vector2 end = { center.x + cosf(rad)*lineLength,
center.y + sinf(rad) * lineLength }; center.y + sinf(rad)*lineLength };
// Gradient color from green → cyan → blue → magenta // Gradient color from green → cyan → blue → magenta
Color col; Color col;
@ -78,15 +78,15 @@ int main(void)
DrawLineEx(center, end, 5.0f, col); DrawLineEx(center, end, 5.0f, col);
// Draw angle label slightly offset along the line // Draw angle label slightly offset along the line
Vector2 textPos = { center.x + cosf(rad) * (lineLength + 20), Vector2 textPos = { center.x + cosf(rad)*(lineLength + 20),
center.y + sinf(rad) * (lineLength + 20) }; center.y + sinf(rad)*(lineLength + 20) };
DrawText(TextFormat("%d°", angles[i]), (int)textPos.x, (int)textPos.y, 20, col); DrawText(TextFormat("%d°", angles[i]), (int)textPos.x, (int)textPos.y, 20, col);
} }
// Draw animated rotating line with changing color // Draw animated rotating line with changing color
float animRad = totalAngle * DEG2RAD; float animRad = totalAngle*DEG2RAD;
Vector2 animEnd = { center.x + cosf(animRad) * lineLength, Vector2 animEnd = { center.x + cosf(animRad)*lineLength,
center.y + sinf(animRad) * lineLength }; center.y + sinf(animRad)*lineLength };
// Cycle through HSV colors for animated line // Cycle through HSV colors for animated line
Color animCol = ColorFromHSV(fmodf(totalAngle, 360.0f), 0.8f, 0.9f); Color animCol = ColorFromHSV(fmodf(totalAngle, 360.0f), 0.8f, 0.9f);

View File

@ -40,8 +40,8 @@ int main(void)
Vector2 sinePoints[WAVE_POINTS]; Vector2 sinePoints[WAVE_POINTS];
Vector2 cosPoints[WAVE_POINTS]; Vector2 cosPoints[WAVE_POINTS];
Vector2 center = { (screenWidth/2.0f) - 30.f, screenHeight/2.0f }; Vector2 center = { (screenWidth/2.0f) - 30.0f, screenHeight/2.0f };
Rectangle start = { 20.f, screenHeight - 120.f , 200.0f, 100.0f}; Rectangle start = { 20.0f, screenHeight - 120.f , 200.0f, 100.0f};
float radius = 130.0f; float radius = 130.0f;
float angle = 0.0f; float angle = 0.0f;
bool pause = false; bool pause = false;
@ -98,7 +98,7 @@ int main(void)
// Base circle and axes // Base circle and axes
DrawCircleLinesV(center, radius, GRAY); DrawCircleLinesV(center, radius, GRAY);
DrawLineEx((Vector2){ center.x, limitMin.y }, (Vector2){ center.x, limitMax.y }, 1.0f, GRAY); DrawLineEx((Vector2){ center.x, limitMin.y }, (Vector2){ center.x, limitMax.y }, 1.0f, GRAY);
DrawLineEx((Vector2){ limitMin.x, center.y }, (Vector2){ limitMax.x, center.y }, 1.f, GRAY); DrawLineEx((Vector2){ limitMin.x, center.y }, (Vector2){ limitMax.x, center.y }, 1.0f, GRAY);
// Wave graph axes // Wave graph axes
DrawLineEx((Vector2){ start.x , start.y }, (Vector2){ start.x , start.y + start.height }, 2.0f, GRAY); DrawLineEx((Vector2){ start.x , start.y }, (Vector2){ start.x , start.y + start.height }, 2.0f, GRAY);
@ -135,19 +135,19 @@ int main(void)
DrawText(TextFormat("Cotangent %.2f", cotangent), 640, 250, 6, ORANGE); DrawText(TextFormat("Cotangent %.2f", cotangent), 640, 250, 6, ORANGE);
// Complementary angle (beige) // Complementary angle (beige)
DrawCircleSectorLines(center, radius*0.6f , -angle, -90.f , 36.0f, BEIGE); DrawCircleSectorLines(center, radius*0.6f , -angle, -90.0f , 36.0f, BEIGE);
DrawText(TextFormat("Complementary %0.f°",complementary), 640, 150, 6, BEIGE); DrawText(TextFormat("Complementary %0.f°",complementary), 640, 150, 6, BEIGE);
// Supplementary angle (darkblue) // Supplementary angle (darkblue)
DrawCircleSectorLines(center, radius*0.5f , -angle, -180.f , 36.0f, DARKBLUE); DrawCircleSectorLines(center, radius*0.5f , -angle, -180.0f , 36.0f, DARKBLUE);
DrawText(TextFormat("Supplementary %0.f°",supplementary), 640, 130, 6, DARKBLUE); DrawText(TextFormat("Supplementary %0.f°",supplementary), 640, 130, 6, DARKBLUE);
// Explementary angle (pink) // Explementary angle (pink)
DrawCircleSectorLines(center, radius*0.4f , -angle, -360.f , 36.0f, PINK); DrawCircleSectorLines(center, radius*0.4f , -angle, -360.0f , 36.0f, PINK);
DrawText(TextFormat("Explementary %0.f°",explementary), 640, 170, 6, PINK); DrawText(TextFormat("Explementary %0.f°",explementary), 640, 170, 6, PINK);
// Current angle - arc (lime), radius (black), endpoint (black) // Current angle - arc (lime), radius (black), endpoint (black)
DrawCircleSectorLines(center, radius*0.7f , -angle, 0.f, 36.0f, LIME); DrawCircleSectorLines(center, radius*0.7f , -angle, 0.0f, 36.0f, LIME);
DrawLineEx((Vector2){ center.x , center.y }, point, 2.0f, BLACK); DrawLineEx((Vector2){ center.x , center.y }, point, 2.0f, BLACK);
DrawCircleV(point, 4.0f, BLACK); DrawCircleV(point, 4.0f, BLACK);
@ -156,11 +156,12 @@ int main(void)
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(GRAY)); GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(GRAY));
GuiToggle((Rectangle){ 640, 70, 120, 20}, TextFormat("Pause"), &pause); GuiToggle((Rectangle){ 640, 70, 120, 20}, TextFormat("Pause"), &pause);
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(LIME)); GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(LIME));
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f°", angle), &angle, 0.0f, 360.f); GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f°", angle), &angle, 0.0f, 360.0f);
// Angle values panel // Angle values panel
GuiGroupBox((Rectangle){ 620, 110, 140, 170}, "Angle Values"); GuiGroupBox((Rectangle){ 620, 110, 140, 170}, "Angle Values");
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();

View File

@ -71,7 +71,7 @@ int main(void)
if ((trailPositions[i].x != 0.0f) || (trailPositions[i].y != 0.0f)) if ((trailPositions[i].x != 0.0f) || (trailPositions[i].y != 0.0f))
{ {
// Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old) // Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old)
float ratio = (float)(MAX_TRAIL_LENGTH - i) / MAX_TRAIL_LENGTH; float ratio = (float)(MAX_TRAIL_LENGTH - i)/MAX_TRAIL_LENGTH;
// Fade effect: oldest positions are more transparent // Fade effect: oldest positions are more transparent
// Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio // Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio

View File

@ -0,0 +1,271 @@
/*******************************************************************************************
*
* raylib [shapes] example - penrose tile
*
* Example complexity rating: [★★★★] 4/4
*
* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
* Based on: https://processing.org/examples/penrosetile.html
*
* 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) 2025 David Buzatto (@davidbuzatto)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define STR_MAX_SIZE 10000
#define TURTLE_STACK_MAX_SIZE 50
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct TurtleState {
Vector2 origin;
double angle;
} TurtleState;
typedef struct PenroseLSystem {
int steps;
char *production;
const char *ruleW;
const char *ruleX;
const char *ruleY;
const char *ruleZ;
float drawLength;
float theta;
} PenroseLSystem;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static TurtleState turtleStack[TURTLE_STACK_MAX_SIZE];
static int turtleTop = -1;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static void PushTurtleState(TurtleState state);
static TurtleState PopTurtleState(void);
static PenroseLSystem CreatePenroseLSystem(float drawLength);
static void BuildProductionStep(PenroseLSystem *ls);
static void DrawPenroseLSystem(PenroseLSystem *ls);
//------------------------------------------------------------------------------------
// 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 [shapes] example - penrose tile");
float drawLength = 460.0f;
int minGenerations = 0;
int maxGenerations = 4;
int generations = 0;
// Initializee new penrose tile
PenroseLSystem ls = CreatePenroseLSystem(drawLength*(generations/(float)maxGenerations));
for (int i = 0; i < generations; i++) BuildProductionStep(&ls);
SetTargetFPS(120); // Set our game to run at 120 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
bool rebuild = false;
if (IsKeyPressed(KEY_UP))
{
if (generations < maxGenerations)
{
generations++;
rebuild = true;
}
}
else if (IsKeyPressed(KEY_DOWN))
{
if (generations > minGenerations)
{
generations--;
if (generations > 0) rebuild = true;
}
}
if (rebuild)
{
RL_FREE(ls.production); // Free previous production for re-creation
ls = CreatePenroseLSystem(drawLength*(generations/(float)maxGenerations));
for (int i = 0; i < generations; i++) BuildProductionStep(&ls);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground( RAYWHITE );
if (generations > 0) DrawPenroseLSystem(&ls);
DrawText("penrose l-system", 10, 10, 20, DARKGRAY);
DrawText("press up or down to change generations", 10, 30, 20, DARKGRAY);
DrawText(TextFormat("generations: %d", generations), 10, 50, 20, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Push turtle state for next step
static void PushTurtleState(TurtleState state)
{
if (turtleTop < (TURTLE_STACK_MAX_SIZE - 1)) turtleStack[++turtleTop] = state;
else TraceLog(LOG_WARNING, "TURTLE STACK OVERFLOW!");
}
// Pop turtle state step
static TurtleState PopTurtleState(void)
{
if (turtleTop >= 0) return turtleStack[turtleTop--];
else TraceLog(LOG_WARNING, "TURTLE STACK UNDERFLOW!");
return (TurtleState){ 0 };
}
// Create a new penrose tile structure
static PenroseLSystem CreatePenroseLSystem(float drawLength)
{
// TODO: Review constant values assignment on recreation?
PenroseLSystem ls = {
.steps = 0,
.ruleW = "YF++ZF4-XF[-YF4-WF]++",
.ruleX = "+YF--ZF[3-WF--XF]+",
.ruleY = "-WF++XF[+++YF++ZF]-",
.ruleZ = "--YF++++WF[+ZF++++XF]--XF",
.drawLength = drawLength,
.theta = 36.0f // Degrees
};
ls.production = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
ls.production[0] = '\0';
strncpy(ls.production, "[X]++[X]++[X]++[X]++[X]", STR_MAX_SIZE);
return ls;
}
// Build next penrose step
static void BuildProductionStep(PenroseLSystem *ls)
{
char *newProduction = (char *)RL_MALLOC(sizeof(char)*STR_MAX_SIZE);
newProduction[0] = '\0';
int productionLength = (int)strnlen(ls->production, STR_MAX_SIZE);
for (int i = 0; i < productionLength; i++)
{
char step = ls->production[i];
int remainingSpace = STR_MAX_SIZE - (int)strnlen(newProduction, STR_MAX_SIZE) - 1;
switch (step)
{
case 'W': strncat(newProduction, ls->ruleW, remainingSpace); break;
case 'X': strncat(newProduction, ls->ruleX, remainingSpace); break;
case 'Y': strncat(newProduction, ls->ruleY, remainingSpace); break;
case 'Z': strncat(newProduction, ls->ruleZ, remainingSpace); break;
default:
{
if (step != 'F')
{
int t = (int)strnlen(newProduction, STR_MAX_SIZE);
newProduction[t] = step;
newProduction[t + 1] = '\0';
}
} break;
}
}
ls->drawLength *= 0.5f;
strncpy(ls->production, newProduction, STR_MAX_SIZE);
RL_FREE(newProduction);
}
// Draw penrose tile lines
static void DrawPenroseLSystem(PenroseLSystem *ls)
{
Vector2 screenCenter = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
TurtleState turtle = {
.origin = { 0 },
.angle = -90.0f
};
int repeats = 1;
int productionLength = (int)strnlen(ls->production, STR_MAX_SIZE);
ls->steps += 12;
if (ls->steps > productionLength) ls->steps = productionLength;
for (int i = 0; i < ls->steps; i++)
{
char step = ls->production[i];
if (step == 'F')
{
for (int j = 0; j < repeats; j++)
{
Vector2 startPosWorld = turtle.origin;
float radAngle = DEG2RAD*turtle.angle;
turtle.origin.x += ls->drawLength*cosf(radAngle);
turtle.origin.y += ls->drawLength*sinf(radAngle);
Vector2 startPosScreen = { startPosWorld.x + screenCenter.x, startPosWorld.y + screenCenter.y };
Vector2 endPosScreen = { turtle.origin.x + screenCenter.x, turtle.origin.y + screenCenter.y };
DrawLineEx(startPosScreen, endPosScreen, 2, Fade(BLACK, 0.2f));
}
repeats = 1;
}
else if (step == '+')
{
for (int j = 0; j < repeats; j++) turtle.angle += ls->theta;
repeats = 1;
}
else if (step == '-')
{
for (int j = 0; j < repeats; j++) turtle.angle += -ls->theta;
repeats = 1;
}
else if (step == '[') PushTurtleState(turtle);
else if (step == ']') turtle = PopTurtleState();
else if ((step >= 48) && (step <= 57)) repeats = (int) step - 48;
}
turtleTop = -1;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -184,7 +184,7 @@ static void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, fl
} }
// End one even segments // End one even segments
if ( segments % 2) if ( segments%2)
{ {
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
rlVertex2f(center.x, center.y); rlVertex2f(center.x, center.y);

View File

@ -112,7 +112,7 @@ int main(void)
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180); GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180);
GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f); GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f);
GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f); GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f);
GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.f); GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.0f);
GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8); GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8);
GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier); GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -122,11 +122,11 @@ int main(void)
} }
float distance = Vector2Distance(center, circlePosition)/pointScale; float distance = Vector2Distance(center, circlePosition)/pointScale;
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f) / 2.0f); float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
if (distance > 1.0f) if (distance > 1.0f)
{ {
circlePosition = Vector2Add((Vector2){ sinf(angle*(PI * 2.0f)) * pointScale, -cosf(angle*(PI*2.0f))*pointScale }, center); circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI*2.0f))*pointScale }, center);
} }
} }
@ -152,21 +152,15 @@ int main(void)
// If the slider or the wheel was clicked, update the current color // If the slider or the wheel was clicked, update the current color
if (settingColor || sliderClicked) if (settingColor || sliderClicked)
{ {
if (settingColor) { if (settingColor) circlePosition = GetMousePosition();
circlePosition = GetMousePosition();
}
float distance = Vector2Distance(center, circlePosition) / pointScale; float distance = Vector2Distance(center, circlePosition)/pointScale;
float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f); float angle = ((Vector2Angle((Vector2){ 0.0f, -pointScale }, Vector2Subtract(center, circlePosition))/PI + 1.0f)/2.0f);
if (settingColor && distance > 1.0f) { if (settingColor && distance > 1.0f) circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI* 2.0f))*pointScale }, center);
circlePosition = Vector2Add((Vector2){ sinf(angle*(PI*2.0f))*pointScale, -cosf(angle*(PI* 2.0f))*pointScale }, center);
}
float angle360 = angle*360.0f; float angle360 = angle*360.0f;
float valueActual = Clamp(distance, 0.0f, 1.0f); float valueActual = Clamp(distance, 0.0f, 1.0f);
color = ColorLerp((Color){ (int)(value*255.0f), (int)(value*255.0f), (int)(value*255.0f), 255 }, ColorFromHSV(angle360, Clamp(distance, 0.0f, 1.0f), 1.0f), valueActual); color = ColorLerp((Color){ (int)(value*255.0f), (int)(value*255.0f), (int)(value*255.0f), 255 }, ColorFromHSV(angle360, Clamp(distance, 0.0f, 1.0f), 1.0f), valueActual);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -95,7 +95,7 @@ int main(void)
} }
else else
{ {
for (int i = 0; i <= emissionRate; ++i) EmitParticle(&circularBuffer, emitterPosition, currentType); for (int i = 0; i <= emissionRate; i++) EmitParticle(&circularBuffer, emitterPosition, currentType);
} }
// Update the parameters of each particle // Update the parameters of each particle

View File

@ -34,7 +34,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip"); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip");
Vector2 points[122] = { 0 }; Vector2 points[122] = { 0 };
Vector2 center = { (screenWidth/2.0f) - 125.f, screenHeight/2.0f }; Vector2 center = { (screenWidth/2.0f) - 125.0f, screenHeight/2.0f };
float segments = 6.0f; float segments = 6.0f;
float insideRadius = 100.0f; float insideRadius = 100.0f;
float outsideRadius = 150.0f; float outsideRadius = 150.0f;
@ -92,7 +92,7 @@ int main(void)
// Draw GUI controls // Draw GUI controls
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Segments", TextFormat("%.0f", segments), &segments, 6.0f, 60.f); GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Segments", TextFormat("%.0f", segments), &segments, 6.0f, 60.0f);
GuiCheckBox((Rectangle){ 640, 70, 20, 20 }, "Outline", &outline); GuiCheckBox((Rectangle){ 640, 70, 20, 20 }, "Outline", &outline);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -8,13 +8,15 @@
| fonts/mecha.png | Captain Falcon | [Freeware](https://www.dafont.com/es/mecha-cf.font) | Atlas created by [@raysan5](https://github.com/raysan5) | | fonts/mecha.png | Captain Falcon | [Freeware](https://www.dafont.com/es/mecha-cf.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
| fonts/pixelplay.png | Aleksander Shevchuk | [Freeware](https://www.dafont.com/es/pixelplay.font) | Atlas created by [@raysan5](https://github.com/raysan5) | | fonts/pixelplay.png | Aleksander Shevchuk | [Freeware](https://www.dafont.com/es/pixelplay.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
| fonts/pixantiqua.ttf | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | Atlas created by [@raysan5](https://github.com/raysan5) | | fonts/pixantiqua.ttf | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
| anonymous_pro_bold.ttf | [Mark Simonson](https://fonts.google.com/specimen/Anonymous+Pro) | [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | - | | anonymous_pro_bold.ttf | [Mark Simonson](https://fonts.google.com/specimen/Anonymous+Pro) | [SIL Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | - |
| custom_alagard.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) | | custom_alagard.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
| custom_jupiter_crash.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) | | custom_jupiter_crash.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
| custom_mecha.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) | | custom_mecha.png | [Brian Kent (AEnigma)](https://www.dafont.com/es/aenigma.d188) | [Freeware](https://www.dafont.com/es/jupiter-crash.font) | Atlas created by [@raysan5](https://github.com/raysan5) |
| dejavu.fnt, dejavu.png | [DejaVu Fonts](https://dejavu-fonts.github.io/) | [Free](https://dejavu-fonts.github.io/License.html) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) | | dejavu.fnt, dejavu.png | [DejaVu Fonts](https://dejavu-fonts.github.io/) | [Free](https://dejavu-fonts.github.io/License.html) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
| KAISG.ttf | [Dieter Steffmann](http://www.steffmann.de/wordpress/) | [Freeware](https://www.1001fonts.com/users/steffmann/) | [Kaiserzeit Gotisch](https://www.dafont.com/es/kaiserzeit-gotisch.font) font | | KAISG.ttf | [Dieter Steffmann](http://www.steffmann.de/wordpress/) | [Freeware](https://www.1001fonts.com/users/steffmann/) | [Kaiserzeit Gotisch](https://www.dafont.com/es/kaiserzeit-gotisch.font) font |
| noto_cjk.fnt, noto_cjk.png | [Google Fonts](https://www.google.com/get/noto/help/cjk/) | [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) | | noto_cjk.fnt, noto_cjk.png | [Google Fonts](https://www.google.com/get/noto/help/cjk/) | [SIL Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
| pixantiqua.fnt, pixantiqua.png | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) | | pixantiqua.fnt, pixantiqua.png | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
| pixantiqua.ttf | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | - | | pixantiqua.ttf | Gerhard Großmann | [Freeware](https://www.dafont.com/es/pixantiqua.font) | - |
| symbola.fnt, symbola.png | George Douros | [Freeware](https://fontlibrary.org/en/font/symbola) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) | | symbola.fnt, symbola.png | George Douros | [Freeware](https://fontlibrary.org/en/font/symbola) | Atlas made with [BMFont](https://www.angelcode.com/products/bmfont/) by [@raysan5](https://github.com/raysan5) |
| DotGothic16-Regular.ttf | [The DotGothic16 Project Authors](https://github.com/fontworks-fonts/DotGothic16) | [Open Font License](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL) | - |
| NotoSansTC-Regular.ttf | [Adobe](http://www.adobe.com/) | [SIL Open Font License](https://openfontlicense.org/documents/OFL.txt) | - |

View File

@ -231,7 +231,7 @@ int main(void)
if (multicolor) if (multicolor)
{ {
// Fill color array with random colors // Fill color array with random colors
for (int i = 0; i < TEXT_MAX_LAYERS; ++i) for (int i = 0; i < TEXT_MAX_LAYERS; i++)
{ {
multi[i] = GenerateRandomColor(0.5f, 0.8f); multi[i] = GenerateRandomColor(0.5f, 0.8f);
multi[i].a = GetRandomValue(0, 255); multi[i].a = GetRandomValue(0, 255);
@ -296,7 +296,7 @@ int main(void)
rlRotatef(90.0f, 1.0f, 0.0f, 0.0f); rlRotatef(90.0f, 1.0f, 0.0f, 0.0f);
rlRotatef(90.0f, 0.0f, 0.0f, -1.0f); rlRotatef(90.0f, 0.0f, 0.0f, -1.0f);
for (int i = 0; i < layers; ++i) for (int i = 0; i < layers; i++)
{ {
Color clr = light; Color clr = light;
if (multicolor) clr = multi[i]; if (multicolor) clr = multi[i];

View File

@ -97,8 +97,8 @@ int main(void)
if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0); if (currentFont == 0) textSize = MeasureTextEx(fontDefault, msg, fontSize, 0);
else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0); else textSize = MeasureTextEx(fontSDF, msg, fontSize, 0);
fontPosition.x = GetScreenWidth()/2 - textSize.x/2; fontPosition.x = (float)GetScreenWidth()/2 - textSize.x/2;
fontPosition.y = GetScreenHeight()/2 - textSize.y/2 + 80; fontPosition.y = (float)GetScreenHeight()/2 - textSize.y/2 + 80;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw

View File

@ -70,6 +70,8 @@ int main(void)
// - Define foreground color: [cRRGGBBAA] // - Define foreground color: [cRRGGBBAA]
// - Define background color: [bRRGGBBAA] // - Define background color: [bRRGGBBAA]
// - Reset formating: [r] // - Reset formating: [r]
// Colors defined with [cRRGGBBAA] or [bRRGGBBAA] are multiplied by the base color alpha
// This allows global transparency control while keeping per-section styling (ex. text fade effects)
// Example: [bAA00AAFF][cFF0000FF]red text on gray background[r] normal text // Example: [bAA00AAFF][cFF0000FF]red text on gray background[r] normal text
DrawTextStyled(GetFontDefault(), "This changes the [cFF0000FF]foreground color[r] of provided text!!!", DrawTextStyled(GetFontDefault(), "This changes the [cFF0000FF]foreground color[r] of provided text!!!",
@ -81,12 +83,15 @@ int main(void)
DrawTextStyled(GetFontDefault(), "This changes the [c00ff00ff][bff0000ff]foreground and background colors[r]!!!", DrawTextStyled(GetFontDefault(), "This changes the [c00ff00ff][bff0000ff]foreground and background colors[r]!!!",
(Vector2){ 100, 160 }, 20.0f, 2.0f, BLACK); (Vector2){ 100, 160 }, 20.0f, 2.0f, BLACK);
DrawTextStyled(GetFontDefault(), "This changes the [c00ff00ff]alpha[r] relative [cffffffff][b000000ff]from source[r] [cff000088]color[r]!!!",
(Vector2){ 100, 200 }, 20.0f, 2.0f, (Color){ 0, 0, 0, 100 });
// Get pointer to formated text // Get pointer to formated text
const char *text = TextFormat("Let's be [c%02x%02x%02xFF]CREATIVE[r] !!!", colRandom.r, colRandom.g, colRandom.b); const char *text = TextFormat("Let's be [c%02x%02x%02xFF]CREATIVE[r] !!!", colRandom.r, colRandom.g, colRandom.b);
DrawTextStyled(GetFontDefault(), text, (Vector2){ 100, 220 }, 40.0f, 2.0f, BLACK); DrawTextStyled(GetFontDefault(), text, (Vector2){ 100, 240 }, 40.0f, 2.0f, BLACK);
textSize = MeasureTextStyled(GetFontDefault(), text, 40.0f, 2.0f); textSize = MeasureTextStyled(GetFontDefault(), text, 40.0f, 2.0f);
DrawRectangleLines(100, 220, (int)textSize.x, (int)textSize.y, GREEN); DrawRectangleLines(100, 240, (int)textSize.x, (int)textSize.y, GREEN);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -105,6 +110,7 @@ int main(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw text using inline styling // Draw text using inline styling
// PARAM: color is the default text color, background color is BLANK by default // PARAM: color is the default text color, background color is BLANK by default
// NOTE: Using input color as the base alpha multiplied to inline styles
static void DrawTextStyled(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color color) static void DrawTextStyled(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color color)
{ {
// Text inline styling strategy used: [ ] delimiters for format // Text inline styling strategy used: [ ] delimiters for format
@ -171,8 +177,16 @@ static void DrawTextStyled(Font font, const char *text, Vector2 position, float
// Convert hex color text into actual Color // Convert hex color text into actual Color
unsigned int colHexValue = strtoul(colHexText, NULL, 16); unsigned int colHexValue = strtoul(colHexText, NULL, 16);
if (text[i - 1] == 'c') colFront = GetColor(colHexValue); if (text[i - 1] == 'c')
else if (text[i - 1] == 'b') colBack = GetColor(colHexValue); {
colFront = GetColor(colHexValue);
//colFront.a *= (unsigned char)(colFront.a*(float)color.a/255.0f); // TODO: Review
}
else if (text[i - 1] == 'b')
{
colBack = GetColor(colHexValue);
//colBack.a *= (unsigned char)(colFront.a*(float)color.a/255.0f);
}
i += (colHexCount + 1); // Skip color value retrieved and ']' i += (colHexCount + 1); // Skip color value retrieved and ']'
continue; // Do not draw characters continue; // Do not draw characters
@ -186,7 +200,7 @@ static void DrawTextStyled(Font font, const char *text, Vector2 position, float
else increaseX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing); else increaseX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
// Draw background rectangle color (if required) // Draw background rectangle color (if required)
if (colBack.a > 0) DrawRectangleRec((Rectangle) { position.x + textOffsetX, position.y + textOffsetY - backRecPadding, increaseX, fontSize + 2 * backRecPadding }, colBack); if (colBack.a > 0) DrawRectangleRec((Rectangle) { position.x + textOffsetX, position.y + textOffsetY - backRecPadding, increaseX, fontSize + 2*backRecPadding }, colBack);
if ((codepoint != ' ') && (codepoint != '\t')) if ((codepoint != ' ') && (codepoint != '\t'))
{ {

View File

@ -226,7 +226,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
{ {
if (!wordWrap) if (!wordWrap)
{ {
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
textOffsetX = 0; textOffsetX = 0;
} }
} }
@ -234,7 +234,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
{ {
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
{ {
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
textOffsetX = 0; textOffsetX = 0;
} }
@ -258,7 +258,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
if (wordWrap && (i == endLine)) if (wordWrap && (i == endLine))
{ {
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
textOffsetX = 0; textOffsetX = 0;
startLine = endLine; startLine = endLine;
endLine = -1; endLine = -1;

View File

@ -0,0 +1,400 @@
/*******************************************************************************************
*
* raylib [text] example - strings management
*
* Example complexity rating: [★★★☆] 3/4
*
* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
*
* 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) 2025 David Buzatto (@davidbuzatto)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h>
#define MAX_TEXT_LENGTH 100
#define MAX_TEXT_PARTICLES 100
#define FONT_SIZE 30
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct TextParticle {
char text[MAX_TEXT_LENGTH];
Rectangle rect; // Boundary
Vector2 vel; // Velocity
Vector2 ppos; // Previous position
float padding;
float borderWidth;
float friction;
float elasticity;
Color color;
bool grabbed;
} TextParticle;
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
void PrepareFirstTextParticle(const char* text, TextParticle *tps, int *particleCount);
TextParticle CreateTextParticle(const char *text, float x, float y, Color color);
void SliceTextParticle(TextParticle *tp, int particlePos, int sliceLength, TextParticle *tps, int *particleCount);
void SliceTextParticleByChar(TextParticle *tp, char charToSlice, TextParticle *tps, int *particleCount);
void ShatterTextParticle(TextParticle *tp, int particlePos, TextParticle *tps, int *particleCount);
void GlueTextParticles(TextParticle *grabbed, TextParticle *target, TextParticle *tps, int *particleCount);
void RealocateTextParticles(TextParticle *tps, int particlePos, int *particleCount);
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - strings management");
TextParticle textParticles[MAX_TEXT_PARTICLES] = { 0 };
int particleCount = 0;
TextParticle *grabbedTextParticle = NULL;
Vector2 pressOffset = {0};
PrepareFirstTextParticle("raylib => fun videogames programming!", textParticles, &particleCount);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
float delta = GetFrameTime();
Vector2 mousePos = GetMousePosition();
// Checks if a text particle was grabbed
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
{
for (int i = particleCount - 1; i >= 0; i--)
{
TextParticle *tp = &textParticles[i];
pressOffset.x = mousePos.x - tp->rect.x;
pressOffset.y = mousePos.y - tp->rect.y;
if (CheckCollisionPointRec(mousePos, tp->rect))
{
tp->grabbed = true;
grabbedTextParticle = tp;
break;
}
}
}
// Releases any text particle the was grabbed
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
{
if (grabbedTextParticle != NULL)
{
grabbedTextParticle->grabbed = false;
grabbedTextParticle = NULL;
}
}
// Slice os shatter a text particle
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT))
{
for (int i = particleCount - 1; i >= 0; i--)
{
TextParticle *tp = &textParticles[i];
if (CheckCollisionPointRec(mousePos, tp->rect))
{
if (IsKeyDown(KEY_LEFT_SHIFT))
{
ShatterTextParticle(tp, i, textParticles, &particleCount);
}
else
{
SliceTextParticle(tp, i, TextLength(tp->text)/2, textParticles, &particleCount);
}
break;
}
}
}
// Shake text particles
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
{
for (int i = 0; i < particleCount; i++)
{
if (!textParticles[i].grabbed) textParticles[i].vel = (Vector2){ (float)GetRandomValue(-2000, 2000), (float)GetRandomValue(-2000, 2000) };
}
}
// Reset using TextTo* functions
if (IsKeyPressed(KEY_ONE)) PrepareFirstTextParticle("raylib => fun videogames programming!", textParticles, &particleCount);
if (IsKeyPressed(KEY_TWO)) PrepareFirstTextParticle(TextToUpper("raylib => fun videogames programming!"), textParticles, &particleCount);
if (IsKeyPressed(KEY_THREE)) PrepareFirstTextParticle(TextToLower("raylib => fun videogames programming!"), textParticles, &particleCount);
if (IsKeyPressed(KEY_FOUR)) PrepareFirstTextParticle(TextToPascal("raylib_fun_videogames_programming"), textParticles, &particleCount);
if (IsKeyPressed(KEY_FIVE)) PrepareFirstTextParticle(TextToSnake("RaylibFunVideogamesProgramming"), textParticles, &particleCount);
if (IsKeyPressed(KEY_SIX)) PrepareFirstTextParticle(TextToCamel("raylib_fun_videogames_programming"), textParticles, &particleCount);
// Slice by char pressed only when we have one text particle
char charPressed = GetCharPressed();
if ((charPressed >= 'A') && (charPressed <= 'z') && (particleCount == 1))
{
SliceTextParticleByChar(&textParticles[0], charPressed, textParticles, &particleCount);
}
// Updates each text particle state
for (int i = 0; i < particleCount; i++)
{
TextParticle *tp = &textParticles[i];
// The text particle is not grabbed
if (!tp->grabbed)
{
// text particle repositioning using the velocity
tp->rect.x += tp->vel.x * delta;
tp->rect.y += tp->vel.y * delta;
// Does the text particle hit the screen right boundary?
if ((tp->rect.x + tp->rect.width) >= screenWidth)
{
tp->rect.x = screenWidth - tp->rect.width; // Text particle repositioning
tp->vel.x = -tp->vel.x*tp->elasticity; // Elasticity makes the text particle lose 10% of its velocity on hit
}
// Does the text particle hit the screen left boundary?
else if (tp->rect.x <= 0)
{
tp->rect.x = 0.0f;
tp->vel.x = -tp->vel.x*tp->elasticity;
}
// The same for y axis
if ((tp->rect.y + tp->rect.height) >= screenHeight)
{
tp->rect.y = screenHeight - tp->rect.height;
tp->vel.y = -tp->vel.y*tp->elasticity;
}
else if (tp->rect.y <= 0)
{
tp->rect.y = 0.0f;
tp->vel.y = -tp->vel.y*tp->elasticity;
}
// Friction makes the text particle lose 1% of its velocity each frame
tp->vel.x = tp->vel.x*tp->friction;
tp->vel.y = tp->vel.y*tp->friction;
}
else
{
// Text particle repositioning using the mouse position
tp->rect.x = mousePos.x - pressOffset.x;
tp->rect.y = mousePos.y - pressOffset.y;
// While the text particle is grabbed, recalculates its velocity
tp->vel.x = (tp->rect.x - tp->ppos.x)/delta;
tp->vel.y = (tp->rect.y - tp->ppos.y)/delta;
tp->ppos.x = tp->rect.x;
tp->ppos.y = tp->rect.y;
// Glue text particles when dragging and pressing left ctrl
if (IsKeyDown(KEY_LEFT_CONTROL))
{
for (int i = 0; i < particleCount; i++)
{
if (&textParticles[i] != grabbedTextParticle && grabbedTextParticle->grabbed)
{
if (CheckCollisionRecs(grabbedTextParticle->rect, textParticles[i].rect))
{
GlueTextParticles(grabbedTextParticle, &textParticles[i], textParticles, &particleCount);
grabbedTextParticle = &textParticles[particleCount-1];
}
}
}
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
for (int i = 0; i < particleCount; i++)
{
TextParticle *tp = &textParticles[i];
DrawRectangleRec((Rectangle) { tp->rect.x - tp->borderWidth, tp->rect.y - tp->borderWidth, tp->rect.width + tp->borderWidth * 2, tp->rect.height + tp->borderWidth * 2 }, BLACK);
DrawRectangleRec(tp->rect, tp->color);
DrawText(tp->text, (int)(tp->rect.x+tp->padding), (int)(tp->rect.y+tp->padding), FONT_SIZE, BLACK);
}
DrawText("grab a text particle by pressing with the mouse and throw it by releasing", 10, 10, 10, DARKGRAY);
DrawText("slice a text particle by pressing it with the mouse right button", 10, 30, 10, DARKGRAY);
DrawText("shatter a text particle keeping left shift pressed and pressing it with the mouse right button", 10, 50, 10, DARKGRAY);
DrawText("glue text particles by grabbing than and keeping left control pressed", 10, 70, 10, DARKGRAY);
DrawText("1 to 6 to reset", 10, 90, 10, DARKGRAY);
DrawText("when you have only one text particle, you can slice it by pressing a char", 10, 110, 10, DARKGRAY);
DrawText(TextFormat("TEXT PARTICLE COUNT: %d", particleCount), 10, GetScreenHeight() - 30, 20, BLACK);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
void PrepareFirstTextParticle(const char* text, TextParticle *tps, int *particleCount)
{
tps[0] = CreateTextParticle(
text,
GetScreenWidth()/2.0f,
GetScreenHeight()/2.0f,
RAYWHITE
);
*particleCount = 1;
}
TextParticle CreateTextParticle(const char *text, float x, float y, Color color)
{
TextParticle tp = {
.text = "",
.rect = { x, y, 30, 30 },
.vel = { (float)GetRandomValue(-200, 200), (float)GetRandomValue(-200, 200) },
.ppos = { 0 },
.padding = 5.0f,
.borderWidth = 5.0f,
.friction = 0.99f,
.elasticity = 0.9f,
.color = color,
.grabbed = false
};
TextCopy(tp.text, text);
tp.rect.width = MeasureText(tp.text, FONT_SIZE)+tp.padding*2;
tp.rect.height = FONT_SIZE+tp.padding*2;
return tp;
}
void SliceTextParticle(TextParticle *tp, int particlePos, int sliceLength, TextParticle *tps, int *particleCount)
{
int length = TextLength(tp->text);
if((length > 1) && ((*particleCount+length) < MAX_TEXT_PARTICLES))
{
for (int i = 0; i < length; i += sliceLength)
{
const char *text = sliceLength == 1 ? TextFormat("%c", tp->text[i]) : TextSubtext(tp->text, i, sliceLength);
tps[(*particleCount)++] = CreateTextParticle(
text,
tp->rect.x + i * tp->rect.width/length,
tp->rect.y,
(Color) { GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }
);
}
RealocateTextParticles(tps, particlePos, particleCount);
}
}
void SliceTextParticleByChar(TextParticle *tp, char charToSlice, TextParticle *tps, int *particleCount)
{
int tokenCount = 0;
char **tokens = TextSplit(tp->text, charToSlice, &tokenCount);
if (tokenCount > 1)
{
int textLength = TextLength(tp->text);
for (int i = 0; i < textLength; i++)
{
if (tp->text[i] == charToSlice)
{
tps[(*particleCount)++] = CreateTextParticle(
TextFormat("%c", charToSlice),
tp->rect.x,
tp->rect.y,
(Color) { GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }
);
}
}
for (int i = 0; i < tokenCount; i++)
{
int tokenLength = TextLength(tokens[i]);
tps[(*particleCount)++] = CreateTextParticle(
TextFormat("%s", tokens[i]),
tp->rect.x + i * tp->rect.width/tokenLength,
tp->rect.y,
(Color) { GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }
);
}
if (tokenCount)
{
RealocateTextParticles(tps, 0, particleCount);
}
}
}
void ShatterTextParticle(TextParticle *tp, int particlePos, TextParticle *tps, int *particleCount)
{
SliceTextParticle(tp, particlePos, 1, tps, particleCount);
}
void GlueTextParticles(TextParticle *grabbed, TextParticle *target, TextParticle *tps, int *particleCount)
{
int p1 = -1;
int p2 = -1;
for (int i = 0; i < *particleCount; i++)
{
if (&tps[i] == grabbed) p1 = i;
if (&tps[i] == target) p2 = i;
}
if ((p1 != -1) && (p2 != -1))
{
TextParticle tp = CreateTextParticle(
TextFormat( "%s%s", grabbed->text, target->text),
grabbed->rect.x,
grabbed->rect.y,
RAYWHITE
);
tp.grabbed = true;
tps[(*particleCount)++] = tp;
grabbed->grabbed = false;
if (p1 < p2)
{
RealocateTextParticles(tps, p2, particleCount);
RealocateTextParticles(tps, p1, particleCount);
}
else
{
RealocateTextParticles(tps, p1, particleCount);
RealocateTextParticles(tps, p2, particleCount);
}
}
}
void RealocateTextParticles(TextParticle *tps, int particlePos, int *particleCount)
{
for (int i = particlePos+1; i < *particleCount; i++)
{
tps[i-1] = tps[i];
}
(*particleCount)--;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -210,7 +210,7 @@ int main(void)
// Draw random emojis in the background // Draw random emojis in the background
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
for (int i = 0; i < SIZEOF(emoji); ++i) for (int i = 0; i < SIZEOF(emoji); i++)
{ {
const char *txt = &emojiCodepoints[emoji[i].index]; const char *txt = &emojiCodepoints[emoji[i].index];
Rectangle emojiRect = { position.x, position.y, (float)fontEmoji.baseSize, (float)fontEmoji.baseSize }; Rectangle emojiRect = { position.x, position.y, (float)fontEmoji.baseSize, (float)fontEmoji.baseSize };
@ -277,7 +277,7 @@ int main(void)
DrawTriangle(a, b, c, emoji[selected].color); DrawTriangle(a, b, c, emoji[selected].color);
// Draw the main text message // Draw the main text message
Rectangle textRect = { msgRect.x + horizontalPadding/2, msgRect.y + verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height }; Rectangle textRect = { msgRect.x + (float)horizontalPadding/2, msgRect.y + (float)verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height };
DrawTextBoxed(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE); DrawTextBoxed(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE);
// Draw the info text below the main message // Draw the info text below the main message
@ -316,7 +316,7 @@ static void RandomizeEmoji(void)
hovered = selected = -1; hovered = selected = -1;
int start = GetRandomValue(45, 360); int start = GetRandomValue(45, 360);
for (int i = 0; i < SIZEOF(emoji); ++i) for (int i = 0; i < SIZEOF(emoji); i++)
{ {
// 0-179 emoji codepoints (from emoji char array) each 4bytes + null char // 0-179 emoji codepoints (from emoji char array) each 4bytes + null char
emoji[i].index = GetRandomValue(0, 179)*5; emoji[i].index = GetRandomValue(0, 179)*5;
@ -421,7 +421,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
{ {
if (!wordWrap) if (!wordWrap)
{ {
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
textOffsetX = 0; textOffsetX = 0;
} }
} }
@ -429,7 +429,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
{ {
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width)) if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
{ {
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
textOffsetX = 0; textOffsetX = 0;
} }
@ -453,7 +453,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
if (wordWrap && (i == endLine)) if (wordWrap && (i == endLine))
{ {
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor; textOffsetY += (font.baseSize + (float)font.baseSize/2)*scaleFactor;
textOffsetX = 0; textOffsetX = 0;
startLine = endLine; startLine = endLine;
endLine = -1; endLine = -1;

View File

@ -41,7 +41,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [text] example - words alignment"); InitWindow(screenWidth, screenHeight, "raylib [text] example - words alignment");
// Define the rectangle we will draw the text in // Define the rectangle we will draw the text in
Rectangle textContainerRect = (Rectangle){ screenWidth/2-screenWidth/4, screenHeight/2-screenHeight/3, screenWidth/2, screenHeight*2/3 }; Rectangle textContainerRect = (Rectangle){ (float)screenWidth/2-(float)screenWidth/4, (float)screenHeight/2-(float)screenHeight/3, (float)screenWidth/2, (float)screenHeight*2/3 };
// Some text to display the current alignment // Some text to display the current alignment
const char *textAlignNameH[] = { "Left", "Centre", "Right" }; const char *textAlignNameH[] = { "Left", "Centre", "Right" };
@ -58,7 +58,7 @@ int main(void)
// And of course the font... // And of course the font...
Font font = GetFontDefault(); Font font = GetFontDefault();
// Intialize the alignment variables // Initialize the alignment variables
TextAlignment hAlign = TEXT_ALIGN_CENTRE; TextAlignment hAlign = TEXT_ALIGN_CENTRE;
TextAlignment vAlign = TEXT_ALIGN_MIDDLE; TextAlignment vAlign = TEXT_ALIGN_MIDDLE;
@ -70,27 +70,31 @@ int main(void)
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_LEFT))
if (IsKeyPressed(KEY_LEFT)) { {
hAlign = hAlign - 1; if (hAlign > 0) hAlign = hAlign - 1;
if (hAlign < 0) hAlign = 0;
} }
if (IsKeyPressed(KEY_RIGHT)) {
if (IsKeyPressed(KEY_RIGHT))
{
hAlign = hAlign + 1; hAlign = hAlign + 1;
if (hAlign > 2) hAlign = 2; if (hAlign > 2) hAlign = 2;
} }
if (IsKeyPressed(KEY_UP)) {
vAlign = vAlign - 1; if (IsKeyPressed(KEY_UP))
if (vAlign < 0) vAlign = 0; {
if (vAlign > 0) vAlign = vAlign - 1;
} }
if (IsKeyPressed(KEY_DOWN)) {
if (IsKeyPressed(KEY_DOWN))
{
vAlign = vAlign + 1; vAlign = vAlign + 1;
if (vAlign > 2) vAlign = 2; if (vAlign > 2) vAlign = 2;
} }
// One word per second // One word per second
wordIndex = (int)GetTime() % wordCount; if (wordCount > 0) wordIndex = (int)GetTime()%wordCount;
else wordIndex = 0;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw // Draw
@ -108,9 +112,9 @@ int main(void)
Vector2 textSize = MeasureTextEx(font, words[wordIndex], fontSize, fontSize*.1f); Vector2 textSize = MeasureTextEx(font, words[wordIndex], fontSize, fontSize*.1f);
// Calculate the top-left text position based on the rectangle and alignment // Calculate the top-left text position based on the rectangle and alignment
Vector2 textPos = (Vector2) { Vector2 textPos = (Vector2){
textContainerRect.x + Lerp(0.0f, textContainerRect.width - textSize.x, ((float)hAlign) * 0.5f), textContainerRect.x + Lerp(0.0f, textContainerRect.width - textSize.x, ((float)hAlign)*0.5f),
textContainerRect.y + Lerp(0.0f, textContainerRect.height - textSize.y, ((float)vAlign) * 0.5f) textContainerRect.y + Lerp(0.0f, textContainerRect.height - textSize.y, ((float)vAlign)*0.5f)
}; };
// Draw the text // Draw the text
@ -127,4 +131,4 @@ int main(void)
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
return 0; return 0;
} }

View File

@ -83,10 +83,10 @@ int main(void)
bunnies[i].position.x += bunnies[i].speed.x; bunnies[i].position.x += bunnies[i].speed.x;
bunnies[i].position.y += bunnies[i].speed.y; bunnies[i].position.y += bunnies[i].speed.y;
if (((bunnies[i].position.x + texBunny.width/2) > GetScreenWidth()) || if (((bunnies[i].position.x + (float)texBunny.width/2) > GetScreenWidth()) ||
((bunnies[i].position.x + texBunny.width/2) < 0)) bunnies[i].speed.x *= -1; ((bunnies[i].position.x + (float)texBunny.width/2) < 0)) bunnies[i].speed.x *= -1;
if (((bunnies[i].position.y + texBunny.height/2) > GetScreenHeight()) || if (((bunnies[i].position.y + (float)texBunny.height/2) > GetScreenHeight()) ||
((bunnies[i].position.y + texBunny.height/2 - 40) < 0)) bunnies[i].speed.y *= -1; ((bunnies[i].position.y + (float)texBunny.height/2 - 40) < 0)) bunnies[i].speed.y *= -1;
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View File

@ -0,0 +1,212 @@
/*******************************************************************************************
*
* raylib [textures] example - cellular automata
*
* Example complexity rating: [★★☆☆] 2/4
*
* Example originally created with raylib 5.6, last time updated with raylib 5.6
*
* Example contributed by Jordi Santonja (@JordSant) 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 Jordi Santonja (@JordSant)
*
********************************************************************************************/
#include "raylib.h"
// Initialization constants
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
const int imageWidth = 800;
const int imageHeight = 800/2;
// Rule button sizes and positions
const int drawRuleStartX = 585;
const int drawRuleStartY = 10;
const int drawRuleSpacing = 15;
const int drawRuleGroupSpacing = 50;
const int drawRuleSize = 14;
const int drawRuleInnerSize = 10;
// Preset button sizes
const int presetsSizeX = 42;
const int presetsSizeY = 22;
const int linesUpdatedPerFrame = 4;
//----------------------------------------------------------------------------------
// Functions
//----------------------------------------------------------------------------------
void ComputeLine(Image *image, int line, int rule)
{
// Compute next line pixels. Boundaries are not computed, always 0
for (int i = 1; i < imageWidth - 1; i++)
{
// Get, from the previous line, the 3 pixels states as a binary value
const int prevValue = ((GetImageColor(*image, i - 1, line - 1).r < 5)? 4 : 0) + // Left pixel
((GetImageColor(*image, i, line - 1).r < 5)? 2 : 0) + // Center pixel
((GetImageColor(*image, i + 1, line - 1).r < 5)? 1 : 0); // Right pixel
// Get next value from rule bitmask
const bool currValue = (rule & (1 << prevValue));
// Update pixel color
ImageDrawPixel(image, i, line, (currValue)? BLACK : RAYWHITE);
}
}
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "raylib [textures] example - cellular automata");
// Image that contains the cellular automaton
Image image = GenImageColor(imageWidth, imageHeight, RAYWHITE);
// The top central pixel set as black
ImageDrawPixel(&image, imageWidth/2, 0, BLACK);
Texture2D texture = LoadTextureFromImage(image);
// Some interesting rules
const int presetValues[] = { 18, 30, 60, 86, 102, 124, 126, 150, 182, 225 };
const int presetsCount = sizeof(presetValues)/sizeof(presetValues[0]);
// Variables
int rule = 30; // Starting rule
int line = 1; // Line to compute, starting from line 1. One point in line 0 is already set
SetTargetFPS(60);
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// Handle mouse
const Vector2 mouse = GetMousePosition();
int mouseInCell = -1; // -1: outside any button; 0-7: rule cells; 8+: preset cells
// Check mouse on rule cells
for (int i = 0; i < 8; i++)
{
const int cellX = drawRuleStartX - drawRuleGroupSpacing*i + drawRuleSpacing;
const int cellY = drawRuleStartY + drawRuleSpacing;
if ((mouse.x >= cellX) && (mouse.x <= cellX + drawRuleSize) &&
(mouse.y >= cellY) && (mouse.y <= cellY + drawRuleSize))
{
mouseInCell = i; // 0-7: rule cells
break;
}
}
// Check mouse on preset cells
if (mouseInCell < 0)
{
for (int i = 0; i < presetsCount; i++)
{
const int cellX = 4 + (presetsSizeX + 2)*(i/2);
const int cellY = 2 + (presetsSizeY + 2)*(i%2);
if ((mouse.x >= cellX) && (mouse.x <= cellX + presetsSizeX) &&
(mouse.y >= cellY) && (mouse.y <= cellY + presetsSizeY))
{
mouseInCell = i + 8; // 8+: preset cells
break;
}
}
}
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (mouseInCell >= 0))
{
// Rule changed both by selecting a preset or toggling a bit
if (mouseInCell < 8)
rule ^= (1 << mouseInCell);
else
rule = presetValues[mouseInCell - 8];
// Reset image
ImageClearBackground(&image, RAYWHITE);
ImageDrawPixel(&image, imageWidth/2, 0, BLACK);
line = 1;
}
// Compute next lines
//----------------------------------------------------------------------------------
if (line < imageHeight)
{
for (int i = 0; (i < linesUpdatedPerFrame) && (line + i < imageHeight); i++)
ComputeLine(&image, line + i, rule);
line += linesUpdatedPerFrame;
UpdateTexture(texture, image.data);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
// Draw cellular automaton texture
DrawTexture(texture, 0, screenHeight - imageHeight, WHITE);
// Draw preset values
for (int i = 0; i < presetsCount; i++)
{
DrawText(TextFormat("%i", presetValues[i]), 8 + (presetsSizeX + 2)*(i/2), 4 + (presetsSizeY + 2)*(i%2), 20, GRAY);
DrawRectangleLines(4 + (presetsSizeX + 2)*(i/2), 2 + (presetsSizeY + 2)*(i%2), presetsSizeX, presetsSizeY, BLUE);
// If the mouse is on this preset, highlight it
if (mouseInCell == i + 8)
DrawRectangleLinesEx((Rectangle) { 2 + (presetsSizeX + 2.0f)*((float)i/2),
(presetsSizeY + 2.0f)*(i%2),
presetsSizeX + 4.0f, presetsSizeY + 4.0f }, 3, RED);
}
// Draw rule bits
for (int i = 0; i < 8; i++)
{
// The three input bits
for (int j = 0; j < 3; j++)
{
DrawRectangleLines(drawRuleStartX - drawRuleGroupSpacing*i + drawRuleSpacing*j, drawRuleStartY, drawRuleSize, drawRuleSize, GRAY);
if (i & (4 >> j))
DrawRectangle(drawRuleStartX + 2 - drawRuleGroupSpacing*i + drawRuleSpacing*j, drawRuleStartY + 2, drawRuleInnerSize, drawRuleInnerSize, BLACK);
}
// The output bit
DrawRectangleLines(drawRuleStartX - drawRuleGroupSpacing*i + drawRuleSpacing, drawRuleStartY + drawRuleSpacing, drawRuleSize, drawRuleSize, BLUE);
if (rule & (1 << i))
DrawRectangle(drawRuleStartX + 2 - drawRuleGroupSpacing*i + drawRuleSpacing, drawRuleStartY + 2 + drawRuleSpacing, drawRuleInnerSize, drawRuleInnerSize, BLACK);
// If the mouse is on this rule bit, highlight it
if (mouseInCell == i)
DrawRectangleLinesEx((Rectangle){ drawRuleStartX - drawRuleGroupSpacing*i + drawRuleSpacing - 2.0f,
drawRuleStartY + drawRuleSpacing - 2.0f,
drawRuleSize + 4.0f, drawRuleSize + 4.0f }, 3, RED);
}
DrawText(TextFormat("RULE: %i", rule), drawRuleStartX + drawRuleSpacing*4, drawRuleStartY + 1, 30, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadImage(image);
UnloadTexture(texture);
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -93,8 +93,8 @@ int main(void)
for (unsigned int i = 0; i < map.tilesX*map.tilesY; i++) if (map.tileFog[i] == 1) map.tileFog[i] = 2; for (unsigned int i = 0; i < map.tilesX*map.tilesY; i++) if (map.tileFog[i] == 1) map.tileFog[i] = 2;
// Get current tile position from player pixel position // Get current tile position from player pixel position
playerTileX = (int)((playerPosition.x + MAP_TILE_SIZE/2)/MAP_TILE_SIZE); playerTileX = (int)((playerPosition.x + (float)MAP_TILE_SIZE/2)/MAP_TILE_SIZE);
playerTileY = (int)((playerPosition.y + MAP_TILE_SIZE/2)/MAP_TILE_SIZE); playerTileY = (int)((playerPosition.y + (float)MAP_TILE_SIZE/2)/MAP_TILE_SIZE);
// Check visibility and update fog // Check visibility and update fog
// NOTE: We check tilemap limits to avoid processing tiles out-of-array-bounds (it could crash program) // NOTE: We check tilemap limits to avoid processing tiles out-of-array-bounds (it could crash program)

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