├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── LICENSE ├── audio ├── mixed_processor.nim ├── music_stream.nim ├── raw_stream.nim ├── resources │ ├── country.mp3 │ └── sound.wav └── sound_multi.nim ├── config.nims ├── core ├── automation_event.nim ├── basic_window.nim ├── basic_window_web.nim ├── basic_window_web.nims ├── camera2d.nim ├── custom_frame_control.nim ├── custom_frame_control.nims ├── custom_logging.nim ├── drop_files.nim ├── input_gamepad.nim ├── input_gestures.nim ├── loading_thread.nim ├── mouse_zoom.nim ├── platformer.nim ├── public │ └── .gitkeep ├── resources │ ├── ps3.png │ └── xbox.png ├── screen_management.nim ├── shell_minimal.html ├── storage_values.nim └── window_letterbox.nim ├── games ├── config.nims ├── floppy.nim ├── minshell.html └── public │ └── .gitkeep ├── media ├── astar.png ├── bst.png ├── crown.png ├── nqueens.png ├── perceptron.png ├── rogue.png ├── shaderart.png └── target9.png ├── models ├── flowers_oop.nim ├── heightmap.nim ├── mesh_generation.nim ├── orthographic_projection.nim ├── resources │ ├── heightmap.png │ ├── models │ │ ├── plane.obj │ │ └── plane_diffuse.png │ └── skybox.png └── yaw_pitch_roll.nim ├── others ├── embedded_files_loading.nim ├── raymath_vector_angle.nim ├── resources │ ├── audio_data.nim │ ├── image_data.nim │ └── shaders │ │ └── glsl430 │ │ ├── gol.glsl │ │ ├── gol_render.glsl │ │ └── gol_transfert.glsl ├── rlgl_compute_shader.nim └── rlgl_compute_shader.nims ├── personal ├── astar.nim ├── bst.nim ├── crown.nim ├── kernel_perceptron.nim ├── map14.txt ├── map7.txt ├── maploader.nim ├── nqueens.nim ├── particles.nim ├── perceptron.nim ├── resources │ ├── License.txt │ ├── lambdarogue.png │ ├── shaders │ │ └── retro_crt.fs │ ├── super_mario_bros.png │ └── wQ.png ├── retro_crt.nim ├── rogue.nim ├── shaderart.nim └── target9.nim ├── raylib_examples.nimble ├── readme.md ├── shaders ├── basic_pbr.nim ├── palette_switch.nim ├── resources │ ├── models │ │ ├── old_car_new.glb │ │ └── plane.glb │ ├── old_car_d.png │ ├── old_car_e.png │ ├── old_car_mra.png │ ├── old_car_n.png │ ├── road_a.png │ ├── road_mra.png │ ├── road_n.png │ ├── shaders │ │ ├── glsl100 │ │ │ ├── palette_switch.fs │ │ │ ├── pbr.fs │ │ │ └── wave.fs │ │ ├── glsl120 │ │ │ ├── pbr.fs │ │ │ └── pbr.vs │ │ └── glsl330 │ │ │ ├── palette_switch.fs │ │ │ ├── pbr.fs │ │ │ ├── pbr.vs │ │ │ └── wave.fs │ └── space.png └── texture_waves.nim ├── shapes ├── basic_shapes.nim ├── collision_area.nim ├── easings_ball_anim.nim ├── easings_rectangle_array.nim └── top_down_lights.nim ├── text ├── font_loading.nim ├── font_sdf.nim ├── resources │ ├── anonymous_pro_bold.ttf │ ├── dejavu.fnt │ ├── dejavu.png │ ├── noto_cjk.fnt │ ├── noto_cjk.png │ ├── pixantiqua.fnt │ ├── pixantiqua.png │ ├── pixantiqua.ttf │ ├── shaders │ │ ├── glsl100 │ │ │ └── sdf.fs │ │ └── glsl330 │ │ │ └── sdf.fs │ ├── symbola.fnt │ └── symbola.png └── unicode.nim └── textures ├── background_scrolling.nim ├── bunnymark.nim ├── image_kernel.nim ├── image_processing.nim ├── mouse_painting.nim ├── raw_data.nim ├── rectangle.nim ├── resources ├── boom.wav ├── button.png ├── buttonfx.wav ├── cat.png ├── cyberpunk_street_background.png ├── cyberpunk_street_foreground.png ├── cyberpunk_street_midground.png ├── explosion.png ├── fudesumi.raw ├── parrots.png ├── road.png ├── scarfy.png └── wabbit_alpha.png ├── sprite_button.nim ├── sprite_explosion.nim ├── srcrec_dstrec.nim └── textured_curve.nim /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Nim CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | test-linux: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: jiro4989/setup-nim-action@v2 15 | with: 16 | nim-version: 'stable' 17 | repo-token: ${{ secrets.GITHUB_TOKEN }} 18 | - name: Install dependencies 19 | run: | 20 | sudo apt install libasound2-dev libx11-dev libxrandr-dev libxi-dev libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxinerama-dev libwayland-dev libxkbcommon-dev libwayland-bin 21 | - name: Run tests 22 | run: nimble test -Y 23 | 24 | # test-windows: 25 | # runs-on: windows-latest 26 | # steps: 27 | # - uses: actions/checkout@v4 28 | # - uses: jiro4989/setup-nim-action@v2 29 | # with: 30 | # nim-version: 'stable' 31 | # repo-token: ${{ secrets.GITHUB_TOKEN }} 32 | # - name: Run tests 33 | # run: nimble test -Y 34 | # 35 | # test-macos: 36 | # runs-on: macos-latest 37 | # steps: 38 | # - uses: actions/checkout@v4 39 | # - uses: jiro4989/setup-nim-action@v2 40 | # with: 41 | # nim-version: 'stable' 42 | # repo-token: ${{ secrets.GITHUB_TOKEN }} 43 | # - name: Run tests 44 | # run: nimble test -Y 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2024 Antonis Geralis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /audio/mixed_processor.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [audio] example - Mixed audio processing 4 | # 5 | # Example originally created with raylib 4.2, last time updated with raylib 4.2 6 | # 7 | # Example contributed by hkc (@hatkidchan) and reviewed by Ramon Santamaria (@raysan5) 8 | # 9 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 10 | # BSD-like license that allows static linking with closed source software 11 | # 12 | # Copyright (c) 2023 hkc (@hatkidchan) 13 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2023 14 | # 15 | # **************************************************************************************** 16 | 17 | import raylib, std/[strformat, math] 18 | 19 | const 20 | screenWidth = 800 21 | screenHeight = 450 22 | 23 | var 24 | exponent: float32 = 1.0 # Audio exponentiation value 25 | averageVolume: array[400, float32] # Average volume history 26 | 27 | # ---------------------------------------------------------------------------------------- 28 | # Audio processing function 29 | # ---------------------------------------------------------------------------------------- 30 | 31 | proc processAudio(buffer: pointer; frames: uint32) {.cdecl.} = 32 | var samples = cast[ptr UncheckedArray[float32]](buffer) # Samples internally stored as s 33 | var average: float32 = 0 # Temporary average volume 34 | for frame in 0 ..< frames.int: 35 | template left: untyped = samples[frame*2 + 0] 36 | template right: untyped = samples[frame*2 + 1] 37 | left = pow(abs(left), exponent)*(if (left < 0): -1 else: 1) 38 | right = pow(abs(right), exponent)*(if (right < 0): -1 else: 1) 39 | average += abs(left) / frames.float32 # accumulating average volume 40 | average += abs(right) / frames.float32 41 | # Moving history to the left 42 | for i in 0 ..< averageVolume.high: 43 | averageVolume[i] = averageVolume[i + 1] 44 | averageVolume[^1] = average # Adding last average value 45 | 46 | # ---------------------------------------------------------------------------------------- 47 | # Program main entry point 48 | # ---------------------------------------------------------------------------------------- 49 | 50 | proc main = 51 | # Initialization 52 | # -------------------------------------------------------------------------------------- 53 | initWindow(screenWidth, screenHeight, "raylib [audio] example - processing mixed output") 54 | defer: closeWindow() # Close window and OpenGL context 55 | 56 | initAudioDevice() # Initialize audio device 57 | defer: closeAudioDevice() # Close audio device (music streaming is automatically stopped) 58 | 59 | attachAudioMixedProcessor(processAudio) 60 | let music = loadMusicStream("resources/country.mp3") 61 | let sound = loadSound("resources/coin.wav") 62 | playMusicStream(music) 63 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 64 | # -------------------------------------------------------------------------------------- 65 | # Main game loop 66 | while not windowShouldClose(): # Detect window close button or ESC key 67 | # Update 68 | # ------------------------------------------------------------------------------------ 69 | updateMusicStream(music) # Update music buffer with new stream data 70 | 71 | # Modify processing variables 72 | # ------------------------------------------------------------------------------------ 73 | if isKeyPressed(Left): exponent -= 0.05'f32 74 | if isKeyPressed(Right): exponent += 0.05'f32 75 | 76 | if exponent <= 0.5'f32: exponent = 0.5'f32 77 | if exponent >= 3.0'f32: exponent = 3.0'f32 78 | 79 | if isKeyPressed(Space): playSound(sound) 80 | # ------------------------------------------------------------------------------------ 81 | # Draw 82 | # ------------------------------------------------------------------------------------ 83 | beginDrawing() 84 | clearBackground(RayWhite) 85 | drawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LightGray) 86 | drawText(&"EXPONENT = {exponent:.2f}", 215, 180, 20, LightGray) 87 | drawRectangle(199, 199, 402, 34, LightGray) 88 | for i in 0 ..< 400: 89 | drawLine(201 + i.int32, int32(232 - averageVolume[i]*32), 201 + i.int32, 232, Maroon) 90 | drawRectangleLines(199, 199, 402, 34, Gray) 91 | drawText("PRESS SPACE TO PLAY OTHER SOUND", 200, 250, 20, LightGray) 92 | drawText("USE LEFT AND RIGHT ARROWS TO ALTER DISTORTION", 140, 280, 20, LightGray) 93 | endDrawing() 94 | # ------------------------------------------------------------------------------------ 95 | # De-Initialization 96 | # -------------------------------------------------------------------------------------- 97 | detachAudioMixedProcessor(processAudio) # Disconnect audio processor 98 | # -------------------------------------------------------------------------------------- 99 | 100 | main() 101 | -------------------------------------------------------------------------------- /audio/music_stream.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [audio] example - Music playing (streaming) 4 | # 5 | # This example has been created using raylib 1.3 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2015 Ramon Santamaria (@raysan5) 9 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 10 | # 11 | # **************************************************************************************** 12 | 13 | import raylib 14 | 15 | const 16 | screenWidth = 800 17 | screenHeight = 450 18 | 19 | proc main = 20 | # Initialization 21 | # -------------------------------------------------------------------------------------- 22 | initWindow(screenWidth, screenHeight, "raylib [audio] example - music playing (streaming)") 23 | defer: closeWindow() # Close window and OpenGL context 24 | 25 | initAudioDevice() # Initialize audio device 26 | defer: closeAudioDevice() # Close audio device (music streaming is automatically stopped) 27 | 28 | let music = loadMusicStream("resources/country.mp3") 29 | # 1 second delay (device sampleRate*channels) 30 | playMusicStream(music) 31 | 32 | var timePlayed: float32 = 0 # Time played normalized [0.0f..1.0f] 33 | var pause = false # Music playing paused 34 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 35 | # -------------------------------------------------------------------------------------- 36 | # Main game loop 37 | while not windowShouldClose(): # Detect window close button or ESC key 38 | # Update 39 | # ------------------------------------------------------------------------------------ 40 | updateMusicStream(music) # Update music buffer with new stream data 41 | 42 | # Restart music playing (stop and play) 43 | if isKeyPressed(Space): 44 | stopMusicStream(music) 45 | playMusicStream(music) 46 | 47 | # Pause/Resume music playing 48 | if isKeyPressed(P): 49 | pause = not pause 50 | if pause: pauseMusicStream(music) 51 | else: resumeMusicStream(music) 52 | 53 | # Get normalized time played for current music stream 54 | timePlayed = getMusicTimePlayed(music)/getMusicTimeLength(music) 55 | if timePlayed > 1: timePlayed = 1 # Make sure time played is no longer than music 56 | # ------------------------------------------------------------------------------------ 57 | # Draw 58 | # ------------------------------------------------------------------------------------ 59 | beginDrawing() 60 | clearBackground(RayWhite) 61 | drawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LightGray) 62 | drawRectangle(200, 200, 400, 12, LightGray) 63 | drawRectangle(200, 200, int32(timePlayed*400), 12, Maroon) 64 | drawRectangleLines(200, 200, 400, 12, Gray) 65 | drawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LightGray) 66 | drawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LightGray) 67 | endDrawing() 68 | # ------------------------------------------------------------------------------------ 69 | 70 | main() 71 | -------------------------------------------------------------------------------- /audio/resources/country.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/audio/resources/country.mp3 -------------------------------------------------------------------------------- /audio/resources/sound.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/audio/resources/sound.wav -------------------------------------------------------------------------------- /audio/sound_multi.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [audio] example - Playing sound multiple times 4 | # 5 | # Example originally created with raylib 4.6 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2023 Jeffery Myers (@JeffM2501) 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib 15 | 16 | const 17 | screenWidth = 800 18 | screenHeight = 450 19 | 20 | MaxSounds = 10 21 | 22 | var 23 | sound: Sound 24 | soundArray: array[MaxSounds, SoundAlias] 25 | currentSound: int32 = 0 26 | 27 | # ---------------------------------------------------------------------------------------- 28 | # Program main entry point 29 | # ---------------------------------------------------------------------------------------- 30 | 31 | proc main = 32 | # Initialization 33 | # -------------------------------------------------------------------------------------- 34 | initWindow(screenWidth, screenHeight, 35 | "raylib [audio] example - playing sound multiple times") 36 | defer: closeWindow() # Close window and OpenGL context 37 | 38 | initAudioDevice() # Initialize audio device 39 | defer: closeAudioDevice() # Close audio device (music streaming is automatically stopped) 40 | 41 | # load the sound list 42 | sound = loadSound("resources/sound.wav") 43 | # Load WAV audio file into the first slot as the 'source' sound 44 | # this sound owns the sample data 45 | for i in 0 ..< MaxSounds: 46 | soundArray[i] = loadSoundAlias(sound) 47 | # Load an alias of the sound into slots 1-9. These do not own the sound data, but can be played 48 | currentSound = 0 # Set the sound list to the start 49 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 50 | # -------------------------------------------------------------------------------------- 51 | # Main game loop 52 | while not windowShouldClose(): # Detect window close button or ESC key 53 | # Update 54 | # ------------------------------------------------------------------------------------ 55 | if isKeyPressed(Space): 56 | playSound(Sound(soundArray[currentSound])) 57 | # play the next open sound slot 58 | inc(currentSound) 59 | # increment the sound slot 60 | if currentSound >= MaxSounds: 61 | currentSound = 0 62 | beginDrawing() 63 | clearBackground(RayWhite) 64 | drawText("Press SPACE to PLAY a WAV sound!", 200, 180, 20, LightGray) 65 | endDrawing() 66 | # ------------------------------------------------------------------------------------ 67 | 68 | main() 69 | -------------------------------------------------------------------------------- /config.nims: -------------------------------------------------------------------------------- 1 | when not defined(emscripten): 2 | --define:GraphicsApiOpenGl33 3 | --experimental:overloadableEnums 4 | -------------------------------------------------------------------------------- /core/basic_window.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - Basic window 4 | # 5 | # Welcome to raylib! 6 | # 7 | # To test examples, just press F6 and execute raylib_compile_execute script 8 | # Note that compiled executable is placed in the same folder as .c file 9 | # 10 | # You can find all basic examples on C:\raylib\raylib\examples folder or 11 | # raylib official webpage: www.raylib.com 12 | # 13 | # Enjoy using raylib. :) 14 | # 15 | # Example originally created with raylib 1.0, last time updated with raylib 1.0 16 | # 17 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 18 | # BSD-like license that allows static linking with closed source software 19 | # 20 | # Copyright (c) 2013-2023 Ramon Santamaria (@raysan5) 21 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 22 | # 23 | # **************************************************************************************** 24 | 25 | import raylib 26 | 27 | # ---------------------------------------------------------------------------------------- 28 | # Global Variables Definition 29 | # ---------------------------------------------------------------------------------------- 30 | 31 | const 32 | screenWidth = 800 33 | screenHeight = 450 34 | 35 | # ---------------------------------------------------------------------------------------- 36 | # Program main entry point 37 | # ---------------------------------------------------------------------------------------- 38 | 39 | proc main = 40 | # Initialization 41 | # -------------------------------------------------------------------------------------- 42 | initWindow(screenWidth, screenHeight, "raylib [core] example - basic window") 43 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 44 | # -------------------------------------------------------------------------------------- 45 | # Main game loop 46 | while not windowShouldClose(): # Detect window close button or ESC key 47 | # Update 48 | # ------------------------------------------------------------------------------------ 49 | # TODO: Update your variables here 50 | # ------------------------------------------------------------------------------------ 51 | # Draw 52 | # ------------------------------------------------------------------------------------ 53 | beginDrawing() 54 | clearBackground(RayWhite) 55 | drawText("Congrats! You created your first window!", 190, 200, 20, LightGray) 56 | endDrawing() 57 | # ------------------------------------------------------------------------------------ 58 | # De-Initialization 59 | # -------------------------------------------------------------------------------------- 60 | closeWindow() # Close window and OpenGL context 61 | # -------------------------------------------------------------------------------------- 62 | 63 | main() 64 | -------------------------------------------------------------------------------- /core/basic_window_web.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - Basic window (adapted for HTML5 platform) 4 | # 5 | # NOTE: This example is prepared to compile to WebAssembly, as shown in the 6 | # basic_window_web.nims file. Compile with the -d:emscripten flag. 7 | # To run the example on the Web, run nimhttpd from the public directory and visit 8 | # the address printed to stdout. As you will notice, code structure is slightly 9 | # diferent to the other examples... 10 | # 11 | # NOTE: For multithreading support you need to pass the following extra arguments to nimhttpd: 12 | # -H:"Cross-Origin-Opener-Policy: same-origin" -H:"Cross-Origin-Embedder-Policy: require-corp" 13 | # 14 | # Example originally created with raylib 1.3, last time updated with raylib 1.3 15 | # 16 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 17 | # BSD-like license that allows static linking with closed source software 18 | # 19 | # Copyright (c) 2015-2022 Ramon Santamaria (@raysan5) 20 | # 21 | # **************************************************************************************** 22 | 23 | import raylib 24 | 25 | # ---------------------------------------------------------------------------------------- 26 | # Global Variables Definition 27 | # ---------------------------------------------------------------------------------------- 28 | 29 | const 30 | screenWidth = 800 31 | screenHeight = 450 32 | 33 | # ---------------------------------------------------------------------------------------- 34 | # Module functions Definition 35 | # ---------------------------------------------------------------------------------------- 36 | 37 | proc updateDrawFrame {.cdecl.} = 38 | # Update 39 | # -------------------------------------------------------------------------------------- 40 | # TODO: Update your variables here 41 | # -------------------------------------------------------------------------------------- 42 | # Draw 43 | # -------------------------------------------------------------------------------------- 44 | beginDrawing() 45 | clearBackground(RayWhite) 46 | drawText("Congrats! You created your first window!", 190, 200, 20, LightGray) 47 | endDrawing() 48 | # -------------------------------------------------------------------------------------- 49 | 50 | # ---------------------------------------------------------------------------------------- 51 | # Program main entry point 52 | # ---------------------------------------------------------------------------------------- 53 | 54 | proc main = 55 | # Initialization 56 | # -------------------------------------------------------------------------------------- 57 | initWindow(screenWidth, screenHeight, "raylib [core] example - basic window") 58 | when defined(emscripten): 59 | emscriptenSetMainLoop(updateDrawFrame, 0, 1) 60 | else: 61 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 62 | # ------------------------------------------------------------------------------------ 63 | # Main game loop 64 | while not windowShouldClose(): # Detect window close button or ESC key 65 | updateDrawFrame() 66 | # De-Initialization 67 | # -------------------------------------------------------------------------------------- 68 | closeWindow() # Close window and OpenGL context 69 | # -------------------------------------------------------------------------------------- 70 | 71 | main() 72 | -------------------------------------------------------------------------------- /core/basic_window_web.nims: -------------------------------------------------------------------------------- 1 | when defined(emscripten): 2 | --define:GraphicsApiOpenGlEs2 3 | # --define:NaylibWebResources 4 | # switch("define", "NaylibWebResourcesPath=resources") 5 | # switch("define", "NaylibWebPthreadPoolSize=2") 6 | # --define:NaylibWebAsyncify 7 | --os:linux 8 | --cpu:wasm32 9 | --cc:clang 10 | when buildOS == "windows": 11 | --clang.exe:emcc.bat 12 | --clang.linkerexe:emcc.bat 13 | --clang.cpp.exe:emcc.bat 14 | --clang.cpp.linkerexe:emcc.bat 15 | else: 16 | --clang.exe:emcc 17 | --clang.linkerexe:emcc 18 | --clang.cpp.exe:emcc 19 | --clang.cpp.linkerexe:emcc 20 | # --mm:orc 21 | --threads:on 22 | --panics:on 23 | --define:noSignalHandler 24 | --passL:"-o public/index.html" 25 | # Use raylib/src/shell.html or raylib/src/minshell.html 26 | --passL:"--shell-file shell_minimal.html" 27 | -------------------------------------------------------------------------------- /core/camera2d.nim: -------------------------------------------------------------------------------- 1 | # *************************************************************************************** 2 | # 3 | # raylib [core] example - 2d camera 4 | # 5 | # This example has been created using raylib 1.5 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2016 Ramon Santamaria (@raysan5) 9 | # Converted in 2020 by bones527 10 | # Adapted in 2021 by greenfork 11 | # Modified by Antonis Geralis (@planetis-m) in 2022 12 | # 13 | # *************************************************************************************** 14 | 15 | import raylib, std/[lenientops, random] 16 | 17 | const 18 | MaxBuildings = 100 19 | 20 | screenWidth = 800 21 | screenHeight = 450 22 | 23 | proc main = 24 | initWindow(screenWidth, screenHeight, "Camera 2D") 25 | 26 | var 27 | player = Rectangle(x: 400, y: 280, width: 40, height: 40) 28 | buildings: array[MaxBuildings, Rectangle] 29 | buildColors: array[MaxBuildings, Color] 30 | spacing: int32 = 0 31 | 32 | for i in 0 ..< MaxBuildings: 33 | buildings[i] = Rectangle( 34 | x: -6000'f32 + spacing, 35 | y: screenHeight - 130 - buildings[i].height, 36 | width: rand(50..200).float32, 37 | height: rand(100..800).float32 38 | ) 39 | 40 | spacing += buildings[i].width.int32 41 | 42 | buildColors[i] = Color( 43 | r: rand(200'u8..240'u8), 44 | g: rand(200'u8..240'u8), 45 | b: rand(200'u8..240'u8), 46 | a: 255 47 | ) 48 | var camera = Camera2D( 49 | target: Vector2(x: player.x + 20, y: player.y + 20), 50 | offset: Vector2(x: screenWidth/2'f32, y: screenHeight/2'f32), 51 | rotation: 0, 52 | zoom: 1, 53 | ) 54 | 55 | setTargetFPS(60) 56 | while not windowShouldClose(): 57 | # Update 58 | # ----------------------------------------------------------------------------------- 59 | # Player movement 60 | if isKeyDown(Right): player.x += 2 61 | elif isKeyDown(Left): player.x -= 2 62 | # Camera target follows player 63 | camera.target = Vector2(x: player.x + 20, y: player.y + 20) 64 | # Camera rotation controls 65 | if isKeyDown(A): camera.rotation -= 1 66 | elif isKeyDown(S): camera.rotation += 1 67 | # Limit camera rotation to 80 degrees (-40 to 40) 68 | if camera.rotation > 40: camera.rotation = 40 69 | elif camera.rotation < -40: camera.rotation = -40 70 | # Camera zoom controls 71 | camera.zoom += getMouseWheelMove()*0.05'f32 72 | if camera.zoom > 3: camera.zoom = 3 73 | elif camera.zoom < 0.1'f32: camera.zoom = 0.1'f32 74 | # Camera reset (zoom and rotation) 75 | if isKeyPressed(R): 76 | camera.zoom = 1 77 | camera.rotation = 0 78 | # Draw 79 | # ----------------------------------------------------------------------------------- 80 | beginDrawing() 81 | clearBackground(RayWhite) 82 | beginMode2D(camera) 83 | drawRectangle(-6000, 320, 13000, 8000, DarkGray) 84 | for i in 0 ..< MaxBuildings: 85 | drawRectangle(buildings[i], buildColors[i]) 86 | drawRectangle(player, Red) 87 | drawLine(camera.target.x.int32, -screenHeight * 10, camera.target.x.int32, 88 | screenHeight * 10, Green) 89 | drawLine(-screenWidth * 10, camera.target.y.int32, screenWidth * 10, 90 | camera.target.y.int32, Green) 91 | endMode2D() 92 | drawText("SCREEN AREA", 640, 10, 20, Red) 93 | drawRectangle(0, 0, screenWidth, 5, Red) 94 | drawRectangle(0, 5, 5, screenHeight - 10, Red) 95 | drawRectangle(screenWidth - 5, 5, 5, screenHeight - 10, Red) 96 | drawRectangle(0, screenHeight - 5, screenWidth, 5, Red) 97 | drawRectangle(10, 10, 250, 113, fade(SkyBlue, 0.5)) 98 | drawRectangleLines(10, 10, 250, 113, Blue) 99 | drawText("Free 2d camera controls:", 20, 20, 10, Black) 100 | drawText("- Right/Left to move Offset", 40, 40, 10, DarkGray) 101 | drawText("- Mouse Wheel to Zoom in-out", 40, 60, 10, DarkGray) 102 | drawText("- A / S to Rotate", 40, 80, 10, DarkGray) 103 | drawText("- R to reset Zoom and Rotation", 40, 100, 10, DarkGray) 104 | endDrawing() 105 | # De-Initialization 106 | # ------------------------------------------------------------------------------------- 107 | closeWindow() # Close window and OpenGL context 108 | 109 | main() 110 | -------------------------------------------------------------------------------- /core/custom_frame_control.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - custom frame control 4 | # 5 | # WARNING: This is an example for advance users willing to have full control over 6 | # the frame processes. By default, endDrawing() calls the following processes: 7 | # 1. Draw remaining batch data: drawRenderBatchActive() 8 | # 2. swapScreenBuffer() 9 | # 3. Frame time control: waitTime() 10 | # 4. pollInputEvents() 11 | # 12 | # To avoid steps 2, 3 and 4, define NaylibSupportCustomFrameControl can be enabled in 13 | # config.nims. This way those steps are up to the user. 14 | # 15 | # Note that enabling this flag invalidates some functions: 16 | # - getFrameTime() 17 | # - setTargetFPS() 18 | # - getFPS() 19 | # 20 | # This example has been created using raylib 3.8 (www.raylib.com) 21 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 22 | # 23 | # Copyright (c) 2021 Ramon Santamaria (@raysan5) 24 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 25 | # 26 | # **************************************************************************************** 27 | 28 | import raylib, std/[lenientops, strformat] 29 | 30 | const 31 | screenWidth = 800 32 | screenHeight = 450 33 | 34 | proc main = 35 | initWindow(screenWidth, screenHeight, "raylib [core] example - custom frame control") 36 | # Custom timming variables 37 | var previousTime = getTime() # Previous time measure 38 | var currentTime = 0.0 # Current time measure 39 | var updateDrawTime = 0.0 # Update + Draw time 40 | var waitTime = 0.0 # Wait time (if target fps required) 41 | var deltaTime: float32 = 0 # Frame time (Update + Draw + Wait time) 42 | var timeCounter: float32 = 0 # Accumulative time counter (seconds) 43 | var position: float32 = 0 # Circle position 44 | var pause = false # Pause control flag 45 | var targetFPS: int32 = 60 # Our initial target fps 46 | # -------------------------------------------------------------------------------------- 47 | # Main game loop 48 | while not windowShouldClose(): # Detect window close button or ESC key 49 | # Update 50 | # ------------------------------------------------------------------------------------ 51 | pollInputEvents() # Poll input events (SUPPORT_CUSTOM_FRAME_CONTROL) 52 | if isKeyPressed(Space): 53 | pause = not pause 54 | if isKeyPressed(Up): 55 | inc(targetFPS, 20) 56 | elif isKeyPressed(Down): 57 | dec(targetFPS, 20) 58 | if targetFPS < 0: 59 | targetFPS = 0 60 | if not pause: 61 | position += 200 * deltaTime # We move at 200 pixels per second 62 | if position >= getScreenWidth(): 63 | position = 0 64 | timeCounter += deltaTime # We count time (seconds) 65 | # ------------------------------------------------------------------------------------ 66 | # Draw 67 | # ------------------------------------------------------------------------------------ 68 | beginDrawing() 69 | clearBackground(RayWhite) 70 | for i in 0 ..< getScreenWidth() div 200: 71 | drawRectangle(200 * i, 0, 1, getScreenHeight(), SkyBlue) 72 | drawCircle(position.int32, getScreenHeight() div 2 - 25, 50, Red) 73 | drawText(&"{timeCounter * 1000'f32:03.0f} ms", position.int32 - 40, 74 | getScreenHeight() div 2 - 100, 20, Maroon) 75 | drawText(&"PosX: {position:03.0f}", position.int32 - 50, 76 | getScreenHeight() div 2 + 40, 20, Black) 77 | drawText("Circle is moving at a constant 200 pixels/sec,\nindependently of the frame rate.", 78 | 10, 10, 20, DarkGray) 79 | drawText("PRESS SPACE to PAUSE MOVEMENT", 10, getScreenHeight() - 60, 20, Gray) 80 | drawText("PRESS UP | DOWN to CHANGE TARGET FPS", 10, getScreenHeight() - 30, 20, Gray) 81 | drawText(&"TARGET FPS: {targetFPS}", getScreenWidth() - 220, 10, 20, Lime) 82 | drawText(&"CURRENT FPS: {int32(1'f32 / deltaTime)}", getScreenWidth() - 220, 40, 20, Green) 83 | endDrawing() 84 | # NOTE: In case raylib is configured to SUPPORT_CUSTOM_FRAME_CONTROL, 85 | # Events polling, screen buffer swap and frame time control must be managed by the user 86 | swapScreenBuffer() 87 | # Flip the back buffer to screen (front buffer) 88 | currentTime = getTime() 89 | updateDrawTime = currentTime - previousTime 90 | if targetFPS > 0: 91 | waitTime = (1'f32/targetFPS) - updateDrawTime 92 | if waitTime > 0: 93 | waitTime(waitTime) 94 | currentTime = getTime() 95 | deltaTime = float32(currentTime - previousTime) 96 | else: 97 | deltaTime = updateDrawTime 98 | # Framerate could be variable 99 | previousTime = currentTime 100 | # De-Initialization 101 | # -------------------------------------------------------------------------------------- 102 | closeWindow() # Close window and OpenGL context 103 | 104 | main() 105 | -------------------------------------------------------------------------------- /core/custom_frame_control.nims: -------------------------------------------------------------------------------- 1 | --define:NaylibSupportCustomFrameControl 2 | -------------------------------------------------------------------------------- /core/custom_logging.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - Custom logging 4 | # 5 | # This example has been created using raylib 2.1 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Example contributed by Pablo Marcos Oltra (@pamarcos) and reviewed by Ramon Santamaria (@raysan5) 9 | # 10 | # Copyright (c) 2018 Pablo Marcos Oltra (@pamarcos) and Ramon Santamaria (@raysan5) 11 | # Converted in 2021 by greenfork 12 | # Modified by Antonis Geralis (@planetis-m) in 2022 13 | # 14 | # **************************************************************************************** 15 | 16 | import raylib, std/[times, strformat] 17 | 18 | const 19 | screenWidth = 800 20 | screenHeight = 450 21 | 22 | proc logCustom(msgType: TraceLogLevel; text: string) = 23 | # Custom logging funtion 24 | var header = newStringOfCap(36) 25 | let timeStr = now().format("yyyy-MM-dd hh:mm:ss") 26 | header.add &"[{timeStr}] " 27 | header.add: 28 | case msgType 29 | of Info: "[INFO]: " 30 | of Error: "[ERROR]: " 31 | of Warning: "[WARN]: " 32 | of Debug: "[DEBUG]: " 33 | else: "" 34 | echo(header, text) 35 | 36 | proc main = 37 | # Initialization 38 | # -------------------------------------------------------------------------------------- 39 | # First thing we do is setting our custom logger to ensure everything raylib logs 40 | # will use our own logger instead of its internal one 41 | setTraceLogCallback(logCustom) 42 | initWindow(screenWidth, screenHeight, "raylib [core] example - custom logging") 43 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 44 | # -------------------------------------------------------------------------------------- 45 | # Main game loop 46 | while not windowShouldClose(): # Detect window close button or ESC key 47 | # Update 48 | # ------------------------------------------------------------------------------------ 49 | # TODO: Update your variables here 50 | # ------------------------------------------------------------------------------------ 51 | # Draw 52 | # ------------------------------------------------------------------------------------ 53 | beginDrawing() 54 | clearBackground(RayWhite) 55 | drawText("Check out the console output to see the custom logger in action!", 60, 200, 20, LightGray) 56 | endDrawing() 57 | # De-Initialization 58 | # -------------------------------------------------------------------------------------- 59 | closeWindow() # Close window and OpenGL context 60 | # -------------------------------------------------------------------------------------- 61 | 62 | main() 63 | -------------------------------------------------------------------------------- /core/drop_files.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - Windows drop files 4 | # 5 | # This example only works on platforms that support drag & drop (Windows, Linux, OSX, Html5?) 6 | # 7 | # This example has been created using raylib 1.3 (www.raylib.com) 8 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 9 | # 10 | # Copyright (c) 2015 Ramon Santamaria (@raysan5) 11 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 12 | # 13 | # **************************************************************************************** 14 | 15 | import raylib 16 | 17 | const 18 | screenWidth = 800 19 | screenHeight = 450 20 | 21 | proc main = 22 | # Initialization 23 | # -------------------------------------------------------------------------------------- 24 | initWindow(screenWidth, screenHeight, "raylib [core] example - drop files") 25 | 26 | var droppedFiles: seq[string] = @[] 27 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 28 | # -------------------------------------------------------------------------------------- 29 | # Main game loop 30 | while not windowShouldClose(): # Detect window close button or ESC key 31 | # Update 32 | # ------------------------------------------------------------------------------------ 33 | if isFileDropped(): 34 | droppedFiles = getDroppedFiles() 35 | # ------------------------------------------------------------------------------------ 36 | # Draw 37 | # ------------------------------------------------------------------------------------ 38 | beginDrawing() 39 | clearBackground(RayWhite) 40 | if droppedFiles.len == 0: 41 | drawText("Drop your files to this window!", 100, 40, 20, DarkGray) 42 | else: 43 | drawText("Dropped files:", 100, 40, 20, DarkGray) 44 | for i in 0..droppedFiles.high: 45 | if i mod 2 == 0: 46 | drawRectangle(0, 85 + 40*i.int32, screenWidth, 40, fade(LightGray, 0.5)) 47 | else: 48 | drawRectangle(0, 85 + 40*i.int32, screenWidth, 40, fade(LightGray, 0.3)) 49 | drawText(droppedFiles[i], 120, 100 + 40*i.int32, 10, Gray) 50 | drawText("Drop new files...", 100, 110 + 40*droppedFiles.len.int32, 20, DarkGray) 51 | endDrawing() 52 | # De-Initialization 53 | # -------------------------------------------------------------------------------------- 54 | closeWindow() # Close window and OpenGL context 55 | # -------------------------------------------------------------------------------------- 56 | 57 | main() 58 | -------------------------------------------------------------------------------- /core/input_gestures.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - Input Gesture Detection 4 | # 5 | # This example has been created using raylib 1.4 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2016 Ramon Santamaria (@raysan5) 9 | # Converted in 2021 by greenfork 10 | # Modified by Antonis Geralis (@planetis-m) in 2022 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib 15 | 16 | const 17 | screenWidth = 800 18 | screenHeight = 450 19 | 20 | MaxGestureStrings = 20 21 | 22 | proc main = 23 | # Initialization 24 | # -------------------------------------------------------------------------------------- 25 | initWindow(screenWidth, screenHeight, "raylib [core] example - input gestures") 26 | var touchArea = Rectangle(x: 220, y: 10, width: screenWidth - 230, height: screenHeight - 20) 27 | var gesturesCount = 0 28 | var gestureStrings: array[MaxGestureStrings, string] 29 | var currentGesture: Gesture = None 30 | var lastGesture: Gesture = None 31 | # setGesturesEnabled(flags(Tap, Drag)) # Enable only some gestures to be detected 32 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 33 | # Main game loop 34 | # -------------------------------------------------------------------------------------- 35 | while not windowShouldClose(): # Detect window close button or ESC key 36 | # Update 37 | # ------------------------------------------------------------------------------------ 38 | lastGesture = currentGesture 39 | currentGesture = getGestureDetected() 40 | let touchPosition = getTouchPosition(0) 41 | 42 | if checkCollisionPointRec(touchPosition, touchArea) and currentGesture != None: 43 | if currentGesture != lastGesture: 44 | # Store gesture string 45 | case currentGesture 46 | of Tap: 47 | gestureStrings[gesturesCount] = "GESTURE TAP" 48 | of Doubletap: 49 | gestureStrings[gesturesCount] = "GESTURE DOUBLETAP" 50 | of Hold: 51 | gestureStrings[gesturesCount] = "GESTURE HOLD" 52 | of Drag: 53 | gestureStrings[gesturesCount] = "GESTURE DRAG" 54 | of SwipeRight: 55 | gestureStrings[gesturesCount] = "GESTURE SWIPE RIGHT" 56 | of SwipeLeft: 57 | gestureStrings[gesturesCount] = "GESTURE SWIPE LEFT" 58 | of SwipeUp: 59 | gestureStrings[gesturesCount] = "GESTURE SWIPE UP" 60 | of SwipeDown: 61 | gestureStrings[gesturesCount] = "GESTURE SWIPE DOWN" 62 | of PinchIn: 63 | gestureStrings[gesturesCount] = "GESTURE PINCH IN" 64 | of PinchOut: 65 | gestureStrings[gesturesCount] = "GESTURE PINCH OUT" 66 | else: 67 | discard 68 | inc gesturesCount 69 | # Reset gestures strings 70 | if gesturesCount >= MaxGestureStrings: 71 | # for i in 0.. 120: 55 | currentScreen = Title 56 | of Title: 57 | # TODO: Update TITLE screen variables here! 58 | # Press enter to change to GAMEPLAY screen 59 | if isKeyPressed(Enter) or isGestureDetected(Tap): 60 | currentScreen = Gameplay 61 | of Gameplay: 62 | # TODO: Update GAMEPLAY screen variables here! 63 | # Press enter to change to ENDING screen 64 | if isKeyPressed(Enter) or isGestureDetected(Tap): 65 | currentScreen = Ending 66 | of Ending: 67 | # TODO: Update ENDING screen variables here! 68 | # Press enter to return to TITLE screen 69 | if isKeyPressed(Enter) or isGestureDetected(Tap): 70 | currentScreen = Title 71 | # ------------------------------------------------------------------------------------ 72 | # Draw 73 | # ------------------------------------------------------------------------------------ 74 | beginDrawing() 75 | clearBackground(RayWhite) 76 | case currentScreen 77 | of Logo: 78 | # TODO: Draw LOGO screen here! 79 | drawText("LOGO SCREEN", 20, 20, 40, LightGray) 80 | drawText("WAIT for 2 SECONDS...", 290, 220, 20, Gray) 81 | of Title: 82 | # TODO: Draw TITLE screen here! 83 | drawRectangle(0, 0, screenWidth, screenHeight, Green) 84 | drawText("TITLE SCREEN", 20, 20, 40, DarkGreen) 85 | drawText("PRESS ENTER or TAP to JUMP to GAMEPLAY SCREEN", 120, 220, 20, DarkGreen) 86 | of Gameplay: 87 | # TODO: Draw GAMEPLAY screen here! 88 | drawRectangle(0, 0, screenWidth, screenHeight, Purple) 89 | drawText("GAMEPLAY SCREEN", 20, 20, 40, Maroon) 90 | drawText("PRESS ENTER or TAP to JUMP to ENDING SCREEN", 130, 220, 20, Maroon) 91 | of Ending: 92 | # TODO: Draw ENDING screen here! 93 | drawRectangle(0, 0, screenWidth, screenHeight, Blue) 94 | drawText("ENDING SCREEN", 20, 20, 40, DarkBlue) 95 | drawText("PRESS ENTER or TAP to RETURN to TITLE SCREEN", 120, 220, 20, DarkBlue) 96 | endDrawing() 97 | # ------------------------------------------------------------------------------------ 98 | 99 | main() 100 | -------------------------------------------------------------------------------- /core/storage_values.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [textures] example - Texture loading and drawing a part defined by a rectangle 4 | # 5 | # This example has been created using raylib 1.3 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2015 Ramon Santamaria (@raysan5) 9 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 10 | # 11 | # **************************************************************************************** 12 | 13 | import raylib, std/[random, strformat] 14 | 15 | const 16 | screenWidth = 800 17 | screenHeight = 450 18 | 19 | StorageDataFile = "storage.data" # Storage file 20 | 21 | type 22 | StorageData = enum 23 | # NOTE: Storage positions must start with 0, directly related to file memory layout 24 | Score = 0, Hiscore 25 | 26 | proc saveStorageValue(position: StorageData, value: int32) = 27 | # Save integer value to storage file (to defined position) 28 | # NOTE: Storage positions is directly related to file memory layout (4 bytes each integer) 29 | var fileData = readFile(StorageDataFile) 30 | if fileData.len <= position.ord*4: 31 | if fileData.len == 0: 32 | traceLog(Info, &"FILEIO: [{StorageDataFile}] File created successfully") 33 | # Increase data size up to position and store value 34 | fileData.setLen((position.ord + 1)*4) 35 | let dataPtr = cast[ptr UncheckedArray[int32]](addr fileData[0]) 36 | dataPtr[position.ord] = value 37 | writeFile(StorageDataFile, fileData) 38 | traceLog(Info, &"FILEIO: [{StorageDataFile}] Saved storage value: {value}") 39 | 40 | proc loadStorageValue(position: StorageData): int32 = 41 | # Load integer value from storage file (from defined position) 42 | # NOTE: If requested position could not be found, value 0 is returned 43 | result = 0 44 | let fileData = readFile(StorageDataFile) 45 | if fileData.len < position.ord*4: 46 | traceLog(Warning, &"FILEIO: [{StorageDataFile}] Failed to find storage position: {position}") 47 | else: 48 | let dataPtr = cast[ptr UncheckedArray[int32]](addr fileData[0]) 49 | result = dataPtr[position.ord] 50 | traceLog(Info, &"FILEIO: [{StorageDataFile}] Loaded storage value: {result}") 51 | 52 | proc main = 53 | # Initialization 54 | # -------------------------------------------------------------------------------------- 55 | initWindow(screenWidth, screenHeight, "raylib [core] example - storage save/load values") 56 | 57 | var score: int32 = 0 58 | var hiscore: int32 = 0 59 | var framesCounter = 0 60 | 61 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 62 | # -------------------------------------------------------------------------------------- 63 | # Main game loop 64 | while not windowShouldClose(): # Detect window close button or ESC key 65 | # Update 66 | # ------------------------------------------------------------------------------------ 67 | if isKeyPressed(R): 68 | score = rand(1000'i32..2000'i32) 69 | hiscore = rand(2000'i32..4000'i32) 70 | if isKeyPressed(Enter): 71 | saveStorageValue(Score, score) 72 | saveStorageValue(Hiscore, hiscore) 73 | elif isKeyPressed(Space): 74 | # NOTE: If requested position could not be found, value 0 is returned 75 | score = loadStorageValue(Score) 76 | hiscore = loadStorageValue(Hiscore) 77 | 78 | inc framesCounter 79 | # ------------------------------------------------------------------------------------ 80 | # Draw 81 | # ------------------------------------------------------------------------------------ 82 | beginDrawing() 83 | clearBackground(RayWhite) 84 | drawText(&"SCORE: {score}", 280, 130, 40, Maroon) 85 | drawText(&"HI-SCORE: {hiscore}", 210, 200, 50, Black) 86 | 87 | drawText(&"frames: {framesCounter}", 10, 10, 20, Lime) 88 | 89 | drawText("Press R to generate random numbers", 220, 40, 20, LightGray) 90 | drawText("Press ENTER to SAVE values", 250, 310, 20, LightGray) 91 | drawText("Press SPACE to LOAD values", 252, 350, 20, LightGray) 92 | endDrawing() 93 | # ------------------------------------------------------------------------------------ 94 | 95 | main() 96 | -------------------------------------------------------------------------------- /core/window_letterbox.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [core] example - window scale letterbox (and virtual mouse) 4 | # 5 | # Example originally created with raylib 2.5, last time updated with raylib 4.0 6 | # 7 | # Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5) 8 | # 9 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 10 | # BSD-like license that allows static linking with closed source software 11 | # 12 | # Copyright (c) 2019-2022 Anata (@anatagawa) and Ramon Santamaria (@raysan5) 13 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 14 | # 15 | # **************************************************************************************** 16 | 17 | import raylib, raymath, std/[random, strformat, lenientops] 18 | 19 | const 20 | windowWidth = 800 21 | windowHeight = 450 22 | 23 | gameScreenWidth = 640 24 | gameScreenHeight = 480 25 | 26 | # ---------------------------------------------------------------------------------------- 27 | # Program main entry point 28 | # ---------------------------------------------------------------------------------------- 29 | 30 | proc main = 31 | # Enable config flags for resizable window and vertical synchro 32 | setConfigFlags(flags(WindowResizable, VsyncHint)) 33 | initWindow(windowWidth, windowHeight, "raylib [core] example - window scale letterbox") 34 | defer: closeWindow() # Close window and OpenGL context 35 | setWindowMinSize(320, 240) 36 | 37 | # Render texture initialization, used to hold the rendering result so we can easily resize it 38 | let target = loadRenderTexture(gameScreenWidth, gameScreenHeight) 39 | setTextureFilter(target.texture, Bilinear) # Texture scale filter to use 40 | 41 | var colors: array[10, Color] 42 | for i in 0..colors.high: 43 | colors[i] = Color( 44 | r: rand(100'u8..250'u8), 45 | g: rand(50'u8..150'u8), 46 | b: rand(10'u8..100'u8), 47 | a: 255 48 | ) 49 | 50 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 51 | # -------------------------------------------------------------------------------------- 52 | # Main game loop 53 | while not windowShouldClose(): # Detect window close button or ESC key 54 | # Update 55 | # ------------------------------------------------------------------------------------ 56 | # Compute required framebuffer scaling 57 | let scale = min(getScreenWidth().float32/gameScreenWidth, getScreenHeight().float32/gameScreenHeight) 58 | 59 | if isKeyPressed(Space): 60 | # Recalculate random colors for the bars 61 | for i in 0..colors.high: 62 | colors[i] = Color( 63 | r: rand(100'u8..250'u8), 64 | g: rand(50'u8..150'u8), 65 | b: rand(10'u8..100'u8), 66 | a: 255 67 | ) 68 | 69 | let mouse = getMousePosition() 70 | var virtualMouse = Vector2( 71 | x: clamp((mouse.x - (getScreenWidth() - (gameScreenWidth*scale))*0.5'f32)/scale, 0, gameScreenWidth), 72 | y: clamp((mouse.y - (getScreenHeight() - (gameScreenHeight*scale))*0.5'f32)/scale, 0, gameScreenHeight) 73 | ) 74 | 75 | # Apply the same transformation as the virtual mouse to the real mouse (i.e. to work with raygui) 76 | # setMouseOffset(-(getScreenWidth() - (gameScreenWidth*scale))*0.5'f32, -(getScreenHeight() - (gameScreenHeight*scale))*0.5'f32) 77 | # setMouseScale(1/scale, 1/scale) 78 | # ------------------------------------------------------------------------------------ 79 | # Draw 80 | # ------------------------------------------------------------------------------------ 81 | # Draw everything in the render texture, note this will not be rendered on screen, yet 82 | beginTextureMode(target) 83 | clearBackground(RayWhite) # Clear render texture background color 84 | for i in 0..colors.high: 85 | drawRectangle(0, (gameScreenHeight div 10)*i.int32, gameScreenWidth, gameScreenHeight div 10, 86 | colors[i]) 87 | drawText("If executed inside a window,\nyou can resize the window,\nand see the screen scaling!", 88 | 10, 25, 20, White) 89 | drawText(&"Default Mouse: [{mouse.x.int32}, {mouse.y.int32}]", 350, 25, 20, Green) 90 | drawText(&"Virtual Mouse: [{virtualMouse.x.int32}, {virtualMouse.y.int32}]", 350, 55, 20, Yellow) 91 | endTextureMode() 92 | 93 | beginDrawing() 94 | clearBackground(Black) # Clear screen background 95 | # Draw render texture to screen, properly scaled 96 | drawTexture(target.texture, 97 | Rectangle( 98 | x: 0, 99 | y: 0, 100 | width: target.texture.width.float32, 101 | height: -target.texture.height.float32 102 | ), 103 | Rectangle( 104 | x: (getScreenWidth() - (gameScreenWidth*scale))*0.5'f32, 105 | y: (getScreenHeight() - (gameScreenHeight*scale))*0.5'f32, 106 | width: gameScreenWidth*scale, 107 | height: gameScreenHeight*scale 108 | ), 109 | Vector2(x: 0, y: 0), 0, White) 110 | endDrawing() 111 | # ------------------------------------------------------------------------------------ 112 | 113 | main() 114 | -------------------------------------------------------------------------------- /games/config.nims: -------------------------------------------------------------------------------- 1 | when defined(emscripten): 2 | --define:GraphicsApiOpenGlEs2 3 | # --define:NaylibWebResources 4 | --os:linux 5 | --cpu:wasm32 6 | --cc:clang 7 | when defined(windows): 8 | --clang.exe:emcc.bat 9 | --clang.linkerexe:emcc.bat 10 | --clang.cpp.exe:emcc.bat 11 | --clang.cpp.linkerexe:emcc.bat 12 | else: 13 | --clang.exe:emcc 14 | --clang.linkerexe:emcc 15 | --clang.cpp.exe:emcc 16 | --clang.cpp.linkerexe:emcc 17 | # --mm:orc 18 | --threads:off 19 | --panics:on 20 | --define:noSignalHandler 21 | switch("passL", "-o public/" & projectName() & ".html") 22 | # Use raylib/src/shell.html or raylib/src/minshell.html 23 | --passL:"--shell-file minshell.html" 24 | -------------------------------------------------------------------------------- /games/minshell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | raylib web game 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 44 | 45 | 63 | 64 | 65 | 66 |

67 | 87 | {{{ SCRIPT }}} 88 | 89 | 90 | -------------------------------------------------------------------------------- /games/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/games/public/.gitkeep -------------------------------------------------------------------------------- /media/astar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/astar.png -------------------------------------------------------------------------------- /media/bst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/bst.png -------------------------------------------------------------------------------- /media/crown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/crown.png -------------------------------------------------------------------------------- /media/nqueens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/nqueens.png -------------------------------------------------------------------------------- /media/perceptron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/perceptron.png -------------------------------------------------------------------------------- /media/rogue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/rogue.png -------------------------------------------------------------------------------- /media/shaderart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/shaderart.png -------------------------------------------------------------------------------- /media/target9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/media/target9.png -------------------------------------------------------------------------------- /models/heightmap.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [models] example - Heightmap loading and drawing 4 | # 5 | # Example originally created with raylib 1.8, last time updated with raylib 3.5 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2015-2022 Ramon Santamaria (@raysan5) 11 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 12 | # 13 | # **************************************************************************************** 14 | 15 | import raylib 16 | 17 | const 18 | screenWidth = 800 19 | screenHeight = 450 20 | 21 | # ---------------------------------------------------------------------------------------- 22 | # Program main entry point 23 | # ---------------------------------------------------------------------------------------- 24 | 25 | proc main = 26 | # Initialization 27 | # -------------------------------------------------------------------------------------- 28 | initWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing") 29 | defer: closeWindow() # Close window and OpenGL context 30 | 31 | # Define our custom camera to look into our 3d world 32 | var camera = Camera( 33 | position: Vector3(x: 18, y: 18, z: 18), # Camera position 34 | target: Vector3(x: 0, y: 0, z: 0), # Camera looking at point 35 | up: Vector3(x: 0, y: 1, z: 0), # Camera up vector (rotation towards target) 36 | fovy: 45, # Camera field-of-view Y 37 | projection: Perspective # Camera projection type 38 | ) 39 | 40 | var image = loadImage("resources/heightmap.png") # Load heightmap image (RAM) 41 | let texture = loadTextureFromImage(image) # Convert image to texture (VRAM) 42 | let mesh = genMeshHeightmap(image, Vector3(x: 16, y: 8, z: 16)) # Generate heightmap mesh (RAM and VRAM) 43 | var model = loadModelFromMesh(mesh) # Load model from generated mesh 44 | model.materials[0].maps[MaterialMapIndex.Diffuse].texture = texture # Set map diffuse texture 45 | 46 | let mapPosition = Vector3(x: -8, y: 0, z: -8) # Define model position 47 | reset(image) # Unload heightmap image from RAM, already uploaded to VRAM 48 | 49 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 50 | # -------------------------------------------------------------------------------------- 51 | # Main game loop 52 | while not windowShouldClose(): # Detect window close button or ESC key 53 | # Update 54 | # ------------------------------------------------------------------------------------ 55 | updateCamera(camera, Orbital) # Set an orbital camera mode 56 | # ------------------------------------------------------------------------------------ 57 | # Draw 58 | # ------------------------------------------------------------------------------------ 59 | beginDrawing() 60 | clearBackground(RayWhite) 61 | 62 | beginMode3D(camera) 63 | drawModel(model, mapPosition, 1, Red) 64 | drawGrid(20, 1) 65 | endMode3D() 66 | 67 | drawTexture(texture, screenWidth - texture.width - 20, 20, White) 68 | drawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, Green) 69 | drawFPS(10, 10) 70 | endDrawing() 71 | # ------------------------------------------------------------------------------------ 72 | 73 | main() 74 | -------------------------------------------------------------------------------- /models/orthographic_projection.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [models] example - Show the difference between perspective and orthographic projection 4 | # 5 | # Example originally created with raylib 2.0, last time updated with raylib 3.7 6 | # 7 | # Example contributed by Max Danielsson (@autious) and reviewed by Ramon Santamaria (@raysan5) 8 | # 9 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 10 | # BSD-like license that allows static linking with closed source software 11 | # 12 | # Copyright (c) 2018-2023 Max Danielsson (@autious) and Ramon Santamaria (@raysan5) 13 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2023 14 | # 15 | # **************************************************************************************** 16 | 17 | import raylib 18 | 19 | const 20 | FovyPerspective: float32 = 45.0 21 | WidthOrthographic: float32 = 10.0 22 | 23 | # ---------------------------------------------------------------------------------------- 24 | # Program main entry point 25 | # ---------------------------------------------------------------------------------------- 26 | 27 | const 28 | screenWidth = 800 29 | screenHeight = 450 30 | 31 | proc main = 32 | # Initialization 33 | # -------------------------------------------------------------------------------------- 34 | initWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes") 35 | # Define the camera to look into our 3d world 36 | var camera = Camera( 37 | position: Vector3(x: 0, y: 10, z: 10), 38 | target: Vector3(x: 0, y: 0, z: 0), 39 | up: Vector3(x: 0, y: 1, z: 0), 40 | fovy: FovyPerspective, 41 | projection: Perspective 42 | ) 43 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 44 | # -------------------------------------------------------------------------------------- 45 | # Main game loop 46 | while not windowShouldClose(): # Detect window close button or ESC key 47 | # Update 48 | # ------------------------------------------------------------------------------------ 49 | if isKeyPressed(Space): 50 | case camera.projection 51 | of Perspective: 52 | camera.fovy = WidthOrthographic 53 | camera.projection = Orthographic 54 | else: 55 | camera.fovy = FovyPerspective 56 | camera.projection = Perspective 57 | # ------------------------------------------------------------------------------------ 58 | # Draw 59 | # ------------------------------------------------------------------------------------ 60 | drawing(): 61 | clearBackground(RayWhite) 62 | mode3D(camera): 63 | drawCube(Vector3(x: -4, y: 0, z: 2), 2, 5, 2, Red) 64 | drawCubeWires(Vector3(x: -4, y: 0, z: 2), 2, 5, 2, Gold) 65 | drawCubeWires(Vector3(x: -4, y: 0, z: -2), 3, 6, 2, Maroon) 66 | drawSphere(Vector3(x: -1, y: 0, z: -2), 1, Green) 67 | drawSphereWires(Vector3(x: 1, y: 0, z: 2), 2, 16, 16, Lime) 68 | drawCylinder(Vector3(x: 4, y: 0, z: -2), 1, 2, 3, 4, SkyBlue) 69 | drawCylinderWires(Vector3(x: 4, y: 0, z: -2), 1, 2, 3, 4, DarkBlue) 70 | drawCylinderWires(Vector3(x: 4.5, y: -1, z: 2), 1, 1, 2, 6, Brown) 71 | drawCylinder(Vector3(x: 1, y: 0, z: -4), 0, 1.5, 3, 8, Gold) 72 | drawCylinderWires(Vector3(x: 1, y: 0, z: -4), 0, 1.5, 3, 8, Pink) 73 | drawGrid(10, 1) # Draw a grid 74 | 75 | drawText("Press Spacebar to switch camera type", 10, getScreenHeight() - 30, 20, DarkGray) 76 | case camera.projection 77 | of Orthographic: 78 | drawText("ORTHOGRAPHIC", 10, 40, 20, Black) 79 | of Perspective: 80 | drawText("PERSPECTIVE", 10, 40, 20, Black) 81 | drawFPS(10, 10) 82 | # ---------------------------------------------------------------------------------- 83 | # De-Initialization 84 | # -------------------------------------------------------------------------------------- 85 | closeWindow() # Close window and OpenGL context 86 | # -------------------------------------------------------------------------------------- 87 | 88 | main() 89 | -------------------------------------------------------------------------------- /models/resources/heightmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/models/resources/heightmap.png -------------------------------------------------------------------------------- /models/resources/models/plane_diffuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/models/resources/models/plane_diffuse.png -------------------------------------------------------------------------------- /models/resources/skybox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/models/resources/skybox.png -------------------------------------------------------------------------------- /models/yaw_pitch_roll.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [models] example - Plane rotations (yaw, pitch, roll) 4 | # 5 | # This example has been created using raylib 1.8 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Example contributed by Berni (@Berni8k) and reviewed by Ramon Santamaria (@raysan5) 9 | # 10 | # Copyright (c) 2017-2021 Berni (@Berni8k) and Ramon Santamaria (@raysan5) 11 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 12 | # 13 | # **************************************************************************************** 14 | 15 | import raylib, raymath, std/math 16 | 17 | const 18 | screenWidth = 800 19 | screenHeight = 450 20 | 21 | proc main = 22 | #setConfigFlags(flags(Msaa4xHint, WindowHighdpi)) 23 | initWindow(screenWidth, screenHeight, 24 | "raylib [models] example - plane rotations (yaw, pitch, roll)") 25 | defer: closeWindow() # Close window and OpenGL context 26 | 27 | let camera = Camera( 28 | position: Vector3(x: 0, y: 50, z: -120), # Camera position perspective 29 | target: Vector3(x: 0, y: 0, z: 0), # Camera looking at point 30 | up: Vector3(x: 0, y: 1, z: 0), # Camera up vector (rotation towards target) 31 | fovy: 30, # Camera field-of-view Y 32 | projection: Perspective # Camera type 33 | ) 34 | 35 | var model = loadModel("resources/models/plane.obj") # Load model 36 | let texture = loadTexture("resources/models/plane_diffuse.png") # Load model texture 37 | model.materials[0].maps[MaterialMapIndex.Diffuse].texture = texture # Set map diffuse texture 38 | 39 | var 40 | pitch: float32 = 0 41 | roll: float32 = 0 42 | yaw: float32 = 0 43 | 44 | setTargetFPS(60) 45 | # Main game loop 46 | # -------------------------------------------------------------------------------------- 47 | while not windowShouldClose(): # Detect window close button or ESC key 48 | # Update 49 | # ------------------------------------------------------------------------------------ 50 | # Plane pitch (x-axis) controls 51 | if isKeyDown(Down): pitch += 0.6'f32 52 | elif isKeyDown(Up): pitch -= 0.6'f32 53 | else: 54 | if pitch > 0.3'f32: pitch -= 0.3'f32 55 | elif pitch < -0.3'f32: pitch += 0.3'f32 56 | 57 | # Plane yaw (y-axis) controls 58 | if isKeyDown(S): yaw -= 1'f32 59 | elif isKeyDown(A): yaw += 1'f32 60 | else: 61 | if yaw > 0'f32: yaw -= 0.5'f32 62 | elif yaw < 0'f32: yaw += 0.5'f32 63 | 64 | # Plane roll (z-axis) controls 65 | if isKeyDown(Left): roll -= 1'f32 66 | elif isKeyDown(Right): roll += 1'f32 67 | else: 68 | if roll > 0'f32: roll -= 0.5'f32 69 | elif roll < 0'f32: roll += 0.5'f32 70 | 71 | # Tranformation matrix for rotations 72 | model.transform = rotateXYZ(Vector3(x: pitch.degToRad, y: yaw.degToRad, z: roll.degToRad)) 73 | # ------------------------------------------------------------------------------------ 74 | # Draw 75 | # ------------------------------------------------------------------------------------ 76 | beginDrawing() 77 | clearBackground(RayWhite) 78 | 79 | # Draw 3D model (recomended to draw 3D always before 2D) 80 | beginMode3D(camera) 81 | drawModel(model, Vector3(x: 0, y: -8, z: 0), 1, White) # Draw 3d model with texture 82 | drawGrid(10, 10) 83 | endMode3D() 84 | 85 | # Draw controls info 86 | drawRectangle(30, 370, 260, 70, fade(Green, 0.5)) 87 | drawRectangleLines(30, 370, 260, 70, fade(DarkGreen, 0.5)) 88 | drawText("Pitch controlled with: KEY_UP / KEY_DOWN", 40, 380, 10, DarkGray) 89 | drawText("Roll controlled with: KEY_LEFT / KEY_RIGHT", 40, 400, 10, DarkGray) 90 | drawText("Yaw controlled with: KEY_A / KEY_S", 40, 420, 10, DarkGray) 91 | 92 | drawText("(c) WWI Plane Model created by GiaHanLam", screenWidth - 240, screenHeight - 20, 10, DarkGray) 93 | endDrawing() 94 | # ------------------------------------------------------------------------------------ 95 | 96 | main() 97 | -------------------------------------------------------------------------------- /others/embedded_files_loading.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [others] example - Weak files loading (Wave and Image) 4 | # 5 | # Example originally created with raylib 3.0, last time updated with raylib 2.5 6 | # 7 | # Example contributed by Kristian Holmgren (@defutura) and reviewed by Ramon Santamaria (@raysan5) 8 | # 9 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 10 | # BSD-like license that allows static linking with closed source software 11 | # 12 | # Copyright (c) 2020-2022 Kristian Holmgren (@defutura) and Ramon Santamaria (@raysan5) 13 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 14 | # 15 | # **************************************************************************************** 16 | 17 | import raylib 18 | include resources/[audio_data, image_data] 19 | 20 | const 21 | screenWidth = 800 22 | screenHeight = 450 23 | 24 | proc main = 25 | # Initialization 26 | # -------------------------------------------------------------------------------------- 27 | initWindow(screenWidth, screenHeight, "raylib [others] example - Weak files loading") 28 | defer: closeWindow() # Close window and OpenGL context 29 | initAudioDevice() # Initialize audio device 30 | defer: closeAudioDevice() # Close audio device 31 | 32 | # Loaded in CPU memory (RAM) from source file (audio_data.nim) 33 | # Same as: let wave = loadWave("sound.wav") 34 | let wave = toWeakWave(AudioData, AudioFrameCount, AudioSampleRate, AudioSampleSize, AudioChannels) 35 | 36 | # Wave converted to Sound to be played 37 | let sound = loadSoundFromWave(wave.Wave) # Convert proc argument to Wave 38 | 39 | # With a Wave loaded from file, after Sound is loaded, we can unload Wave 40 | # but in our case, Wave is embedded in executable, in program .data segment 41 | # we can not (and should not) try to free that private memory region 42 | #reset(wave) # Do not unload wave data! 43 | 44 | # Loaded in CPU memory (RAM) from source file (image_data.nim) 45 | # Same as: let image = loadImage("raylib_logo.png") 46 | let image = toWeakImage(ImageData, ImageWidth, ImageHeight, ImageFormat) 47 | # Image converted to Texture (VRAM) to be drawn 48 | let texture = loadTextureFromImage(image.Image) # Convert proc argument to Image 49 | 50 | # With an Image loaded from file, after Texture is loaded, we can unload Image 51 | # but in our case, Image is embedded in executable, in program .data segment 52 | # we can not (and should not) try to free that private memory region 53 | #reset(image) # Do not unload image data! 54 | 55 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 56 | # -------------------------------------------------------------------------------------- 57 | # Main game loop 58 | while not windowShouldClose(): # Detect window close button or ESC key 59 | # Update 60 | # ------------------------------------------------------------------------------------ 61 | if isKeyPressed(Space): playSound(sound) # Play sound 62 | # ------------------------------------------------------------------------------------ 63 | # Draw 64 | # ------------------------------------------------------------------------------------ 65 | beginDrawing() 66 | clearBackground(RayWhite) 67 | drawTexture(texture, screenWidth div 2 - texture.width div 2, 40, White) 68 | drawText("raylib logo and sound loaded from header files", 150, 320, 20, LightGray) 69 | drawText("Press SPACE to PLAY the sound!", 220, 370, 20, LightGray) 70 | endDrawing() 71 | # ------------------------------------------------------------------------------------ 72 | 73 | main() 74 | -------------------------------------------------------------------------------- /others/raymath_vector_angle.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shapes] example - Vector Angle 4 | # 5 | # Example originally created with raylib 1.0, last time updated with raylib 4.2 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2023 Ramon Santamaria (@raysan5) 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib, raymath, std/[math, strformat] 15 | 16 | const 17 | screenWidth = 800 18 | screenHeight = 450 19 | 20 | type 21 | AngleMode = enum 22 | Angle, LineAngle 23 | 24 | proc `not`(x: AngleMode): AngleMode = AngleMode(not x.bool) 25 | 26 | # ---------------------------------------------------------------------------------------- 27 | # Program main entry point 28 | # ---------------------------------------------------------------------------------------- 29 | 30 | proc main = 31 | # Initialization 32 | # -------------------------------------------------------------------------------------- 33 | initWindow(screenWidth, screenHeight, "raylib [math] example - vector angle") 34 | var v0 = Vector2(x: screenWidth div 2, y: screenHeight div 2) 35 | var v1 = Vector2(x: 100, y: 80) 36 | var v2 = Vector2() # Updated with mouse position 37 | var angle: float32 = 0 # Angle in degrees 38 | var angleMode: AngleMode = Angle 39 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 40 | # -------------------------------------------------------------------------------------- 41 | # Main game loop 42 | while not windowShouldClose(): # Detect window close button or ESC key 43 | # Update 44 | # ------------------------------------------------------------------------------------ 45 | var startAngle: float32 = 0 46 | case angleMode 47 | of Angle: 48 | startAngle = -lineAngle(v0, v1).radToDeg 49 | of LineAngle: 50 | startAngle = 0 51 | v2 = getMousePosition() 52 | if isKeyPressed(Space): 53 | angleMode = not angleMode 54 | case angleMode 55 | of Angle: 56 | if isMouseButtonDown(Right): 57 | v1 = getMousePosition() 58 | # Calculate angle between two vectors, considering a common origin (v0) 59 | angle = angle(normalize(v1 - v0), normalize(v2 - v0)).radToDeg 60 | of LineAngle: 61 | # Calculate angle defined by a two vectors line, in reference to horizontal line 62 | angle = lineAngle(v0, v2).radToDeg 63 | # ------------------------------------------------------------------------------------ 64 | # Draw 65 | # ------------------------------------------------------------------------------------ 66 | beginDrawing() 67 | clearBackground(White) 68 | case angleMode 69 | of Angle: 70 | drawText("MODE: Angle between V1 and V2", 10, 10, 20, Black) 71 | drawLine(v0, v1, 2, Black) 72 | drawLine(v0, v2, 2, Red) 73 | drawCircleSector(v0, 40, startAngle, startAngle + angle, 32, fade(Green, 0.6)) 74 | of LineAngle: 75 | drawText("MODE: Angle formed by line V1 to V2", 10, 10, 20, Black) 76 | drawLine(0, screenHeight div 2, screenWidth, screenHeight div 2, LightGray) 77 | drawLine(v0, v2, 2, Red) 78 | drawCircleSector(v0, 40, startAngle, startAngle - angle, 32, fade(Green, 0.6)) 79 | drawText("v0", v0.x.int32, v0.y.int32, 10, DarkGray) 80 | # If the line from v0 to v1 would overlap the text, move it's position up 10 81 | if angleMode == Angle: 82 | if (v0 - v1).y >= 0: 83 | drawText("v1", v1.x.int32, int32(v1.y - 10), 10, DarkGray) 84 | else: 85 | drawText("v1", v1.x.int32, v1.y.int32, 10, DarkGray) 86 | # If angle mode 1, use v1 to emphasize the horizontal line 87 | if angleMode == LineAngle: 88 | drawText("v1", int32(v0.x + 40), v0.y.int32, 10, DarkGray) 89 | # position adjusted by -10 so it isn't hidden by cursor 90 | drawText("v2", int32(v2.x - 10), int32(v2.y - 10), 10, DarkGray) 91 | drawText("Press SPACE to change MODE", 460, 10, 20, DarkGray) 92 | drawText(&"ANGLE: {angle:2.2f}", 10, 70, 20, Lime) 93 | endDrawing() 94 | # ------------------------------------------------------------------------------------ 95 | # De-Initialization 96 | # -------------------------------------------------------------------------------------- 97 | closeWindow() # Close window and OpenGL context 98 | # -------------------------------------------------------------------------------------- 99 | 100 | main() 101 | -------------------------------------------------------------------------------- /others/resources/shaders/glsl430/gol.glsl: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | // Game of Life logic shader 4 | 5 | #define GOL_WIDTH 768 6 | 7 | layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; 8 | 9 | layout(std430, binding = 1) readonly restrict buffer golLayout { 10 | uint golBuffer[]; // golBuffer[x, y] = golBuffer[x + gl_NumWorkGroups.x * y] 11 | }; 12 | 13 | layout(std430, binding = 2) writeonly restrict buffer golLayout2 { 14 | uint golBufferDest[]; // golBufferDest[x, y] = golBufferDest[x + gl_NumWorkGroups.x * y] 15 | }; 16 | 17 | #define fetchGol(x, y) ((((x) < 0) || ((y) < 0) || ((x) > GOL_WIDTH) || ((y) > GOL_WIDTH)) \ 18 | ? (0) \ 19 | : golBuffer[(x) + GOL_WIDTH * (y)]) 20 | 21 | #define setGol(x, y, value) golBufferDest[(x) + GOL_WIDTH*(y)] = value 22 | 23 | void main() 24 | { 25 | uint neighbourCount = 0; 26 | uint x = gl_GlobalInvocationID.x; 27 | uint y = gl_GlobalInvocationID.y; 28 | 29 | neighbourCount += fetchGol(x - 1, y - 1); // Top left 30 | neighbourCount += fetchGol(x, y - 1); // Top middle 31 | neighbourCount += fetchGol(x + 1, y - 1); // Top right 32 | neighbourCount += fetchGol(x - 1, y); // Left 33 | neighbourCount += fetchGol(x + 1, y); // Right 34 | neighbourCount += fetchGol(x - 1, y + 1); // Bottom left 35 | neighbourCount += fetchGol(x, y + 1); // Bottom middle 36 | neighbourCount += fetchGol(x + 1, y + 1); // Bottom right 37 | 38 | if (neighbourCount == 3) setGol(x, y, 1); 39 | else if (neighbourCount == 2) setGol(x, y, fetchGol(x, y)); 40 | else setGol(x, y, 0); 41 | } 42 | -------------------------------------------------------------------------------- /others/resources/shaders/glsl430/gol_render.glsl: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | // Game of Life rendering shader 4 | // Just renders the content of the ssbo at binding 1 to screen 5 | 6 | #define GOL_WIDTH 768 7 | 8 | // Input vertex attributes (from vertex shader) 9 | in vec2 fragTexCoord; 10 | 11 | // Output fragment color 12 | out vec4 finalColor; 13 | 14 | // Input game of life grid. 15 | layout(std430, binding = 1) readonly buffer golLayout 16 | { 17 | uint golBuffer[]; 18 | }; 19 | 20 | // Output resolution 21 | uniform vec2 resolution; 22 | 23 | void main() 24 | { 25 | ivec2 coords = ivec2(fragTexCoord*resolution); 26 | 27 | if ((golBuffer[coords.x + coords.y*uvec2(resolution).x]) == 1) finalColor = vec4(1.0); 28 | else finalColor = vec4(0.0, 0.0, 0.0, 1.0); 29 | } 30 | -------------------------------------------------------------------------------- /others/resources/shaders/glsl430/gol_transfert.glsl: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | // Game of life transfert shader 4 | 5 | #define GOL_WIDTH 768 6 | 7 | // Game Of Life Update Command 8 | // NOTE: matches the structure defined on main program 9 | struct GolUpdateCmd { 10 | uint x; // x coordinate of the gol command 11 | uint y; // y coordinate of the gol command 12 | uint w; // width of the filled zone 13 | uint enabled; // whether to enable or disable zone 14 | }; 15 | 16 | // Local compute unit size 17 | layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 18 | 19 | // Output game of life grid buffer 20 | layout(std430, binding = 1) buffer golBufferLayout 21 | { 22 | uint golBuffer[]; // golBuffer[x, y] = golBuffer[x + GOL_WIDTH * y] 23 | }; 24 | 25 | // Command buffer 26 | layout(std430, binding = 3) readonly restrict buffer golUpdateLayout 27 | { 28 | uint count; 29 | GolUpdateCmd commands[]; 30 | }; 31 | 32 | #define isInside(x, y) (((x) >= 0) && ((y) >= 0) && ((x) < GOL_WIDTH) && ((y) < GOL_WIDTH)) 33 | #define getBufferIndex(x, y) ((x) + GOL_WIDTH * (y)) 34 | 35 | void main() 36 | { 37 | uint cmdIndex = gl_GlobalInvocationID.x; 38 | GolUpdateCmd cmd = commands[cmdIndex]; 39 | 40 | for (uint x = cmd.x; x < (cmd.x + cmd.w); x++) 41 | { 42 | for (uint y = cmd.y; y < (cmd.y + cmd.w); y++) 43 | { 44 | if (isInside(x, y)) 45 | { 46 | if (cmd.enabled != 0) atomicOr(golBuffer[getBufferIndex(x, y)], 1); 47 | else atomicAnd(golBuffer[getBufferIndex(x, y)], 0); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /others/rlgl_compute_shader.nims: -------------------------------------------------------------------------------- 1 | --define:GraphicsApiOpenGl43 2 | -------------------------------------------------------------------------------- /personal/bst.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # naylib example - binary search tree 4 | # 5 | # Example originally created with naylib 5.1 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2024 Antonis Geralis (@planetis-m) 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib, std/[random, lenientops] 15 | 16 | const 17 | screenWidth = 800 18 | screenHeight = 450 19 | 20 | type 21 | Node = ref object 22 | key: int 23 | left, right: Node 24 | 25 | proc insertNode(root: Node, key: int): Node = 26 | # Insert a new node into the binary search tree 27 | if root == nil: 28 | return Node(key: key) 29 | if key < root.key: 30 | root.left = insertNode(root.left, key) 31 | else: 32 | root.right = insertNode(root.right, key) 33 | return root 34 | 35 | proc drawNode(node: Node, x, y, radius, depth, horizontal, vertical: int32) = 36 | # Draw a node and its children on the screen 37 | if node != nil: 38 | # Draw the node as a circle 39 | drawCircle(x, y, radius.float32, Black) 40 | drawCircle(x, y, radius - 2'f32, White) 41 | # Draw the key as a text inside the circle 42 | let keyStr = $node.key 43 | let keyWidth = measureText(keyStr, 20) 44 | drawText(keyStr, x - keyWidth div 2, y - 10, 20, Black) 45 | # Draw the children with a smaller radius and a line to the parent 46 | if node.left != nil: 47 | # Calculate the coordinates of the center of the left child 48 | let leftX = x - horizontal div (depth + 1) 49 | let leftY = y + vertical 50 | drawLine(x, y + radius, leftX, leftY - radius, Black) 51 | drawNode(node.left, leftX, leftY, radius, depth + 1, horizontal, vertical - 10) 52 | if node.right != nil: 53 | # Calculate the coordinates of the center of the right child 54 | let rightX = x + horizontal div (depth + 1) 55 | let rightY = y + vertical 56 | drawLine(x, y + radius, rightX, rightY - radius, Black) 57 | drawNode(node.right, rightX, rightY, radius, depth + 1, horizontal, vertical - 10) 58 | 59 | # ---------------------------------------------------------------------------------------- 60 | # Program main entry point 61 | # ---------------------------------------------------------------------------------------- 62 | 63 | proc main = 64 | # Initialization 65 | # -------------------------------------------------------------------------------------- 66 | # Set up the raylib window 67 | setConfigFlags(flags(Msaa4xHint)) 68 | initWindow(screenWidth, screenHeight, "raylib example - binary search tree") 69 | randomize() 70 | # Create the binary search tree and insert some nodes 71 | var root: Node = nil 72 | for i in 0 ..< 10: 73 | let key = rand(10..99) # Generate a random key between 10 and 99 74 | root = insertNode(root, key) # Insert the key into the BST 75 | setTargetFPS(60) 76 | # -------------------------------------------------------------------------------------- 77 | # Main game loop 78 | while not windowShouldClose(): 79 | # Update 80 | # ------------------------------------------------------------------------------------ 81 | # Check if the user presses the space key 82 | if isKeyPressed(Space): 83 | # Insert a new random key into the BST 84 | let key = rand(10..99) 85 | root = insertNode(root, key) 86 | # ------------------------------------------------------------------------------------ 87 | # Draw 88 | # ------------------------------------------------------------------------------------ 89 | beginDrawing() 90 | clearBackground(RayWhite) 91 | drawText("Press SPACE to insert a new node", 10, 10, 20, DarkGray) 92 | # Draw the binary search tree 93 | drawNode(root, screenWidth div 2, 40, 20, 1, screenWidth div 4, 80) 94 | endDrawing() 95 | # ------------------------------------------------------------------------------------ 96 | # De-Initialization 97 | # -------------------------------------------------------------------------------------- 98 | closeWindow() # Close window and OpenGL context 99 | 100 | main() 101 | -------------------------------------------------------------------------------- /personal/crown.nim: -------------------------------------------------------------------------------- 1 | # Developed in 2021 by greenfork 2 | # Reviewed in 2023 by planetis-m 3 | # Reviewed in 2025 by ILiekCarot 4 | 5 | import std/math, raylib 6 | 7 | # Let's draw a Nim crown! 8 | const 9 | nimFg = getColor(0xffc200ff'u32) 10 | nimBg = getColor(0x17181fff'u32) 11 | 12 | crownSides = 8 # Low-polygon version 13 | centerAngle: float32 = TAU/crownSides # Angle from the center of a circle 14 | lowerRadius: float32 = 2 # Lower crown circle 15 | upperRadius = lowerRadius*1.4'f32 # Upper crown circle 16 | mainHeight = lowerRadius*0.8'f32 # Height without teeth 17 | toothHeight = mainHeight*1.3'f32 # Height with teeth 18 | toothSkew: float32 = 1.2 # Little angle for teeth 19 | 20 | proc main = 21 | var 22 | lowerPoints, upperPoints: array[crownSides, Vector2] 23 | 24 | # Get evenly spaced points on the lower and upper circles, 25 | # use Nim's math module for that 26 | for i in 0.. 0: 35 | let parts = line.split(',').mapIt(it.strip) 36 | if currentSection in {TMap..TWalls}: 37 | expectPartsLen(mapWidth) 38 | case currentSection 39 | of Colors: 40 | expectPartsLen(3) 41 | colors.add Color( 42 | r: parts[0].parseInt().uint8, 43 | g: parts[1].parseInt().uint8, 44 | b: parts[2].parseInt().uint8, 45 | a: 255 46 | ) 47 | of RaceColors: 48 | expectPartsLen(2) 49 | case parts[0] 50 | of "Elf": elfColor = colors[parts[1].parseInt()] 51 | of "Goblin": goblinColor = colors[parts[1].parseInt()] 52 | of MapDimensions: 53 | expectPartsLen(2) 54 | case parts[0] 55 | of "Width": mapWidth = parts[1].parseInt() 56 | of "Height": mapHeight = parts[1].parseInt() 57 | of TMap: 58 | map.add(parts.mapIt(it.parseInt().int16)) 59 | of TEntities: 60 | entities.add(parts.mapIt(it.parseInt().int16)) 61 | of TBgColors: 62 | bgColors.add(parts.mapIt(colors[it.parseInt()])) 63 | of TFgColors: 64 | fgColors.add(parts.mapIt(colors[it.parseInt()])) 65 | of TWalls: 66 | walls.add(parts.mapIt(it.parseInt().bool)) 67 | # Validate dimensions 68 | let totalCells = mapWidth * mapHeight 69 | assert map.len == totalCells 70 | assert entities.len == totalCells 71 | assert bgColors.len == totalCells 72 | assert fgColors.len == totalCells 73 | assert walls.len == totalCells 74 | # Return game data 75 | (elfColor, goblinColor, mapWidth, mapHeight, map, 76 | entities, bgColors, fgColors, walls) 77 | -------------------------------------------------------------------------------- /personal/nqueens.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib example - 8 queens puzzle 4 | # 5 | # Example originally created with naylib 1.8 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2022 Antonis Geralis (@planetis-m) 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib, reasings, std/strformat 15 | 16 | const 17 | screenSize = 600 18 | N = 8 19 | SquareSize = 75 20 | AnimationFrames = 20 21 | 22 | type 23 | QueensArr = array[N, int32] 24 | Queens = object 25 | queenInRow: QueensArr # column number of queen in each row 26 | colFree: array[N, bool] 27 | upwardFree: array[N*2 - 1, bool] 28 | downwardFree: array[N*2 - 1, bool] 29 | 30 | proc initQueens(): Queens = 31 | # The Queens object is set up as an empty configuration on a chessboard with N 32 | # cells in each row and column. 33 | result = Queens() 34 | for i in 0..= N: 61 | solutions.add x.queenInRow 62 | else: 63 | for col in 0..= solutions.len: index = 0 102 | framesCounter = 0 103 | if framesCounter <= AnimationFrames: 104 | inc framesCounter 105 | # ------------------------------------------------------------------------------------ 106 | # Draw 107 | # ------------------------------------------------------------------------------------ 108 | drawing(): 109 | # Draw the chess board 110 | for row in 0.. 0: index - 1 else: solutions.high][row] 118 | let newCol = solutions[index][row] 119 | animateQueenPlacement(queenPiece, row.int32, oldCol, newCol, framesCounter) 120 | drawText(&"Solution {index+1}", 420, 10, 30, Black) 121 | drawText("Press ENTER to continue", 15, 570, 20, Black) 122 | # ---------------------------------------------------------------------------------- 123 | 124 | main() 125 | -------------------------------------------------------------------------------- /personal/particles.nim: -------------------------------------------------------------------------------- 1 | import raylib, raymath, rmem, std/[random, math] 2 | 3 | const 4 | screenWidth = 800 5 | screenHeight = 450 6 | 7 | MaxParticles = 1000 8 | ParticlesPerClick = 10 # Number of particles to spawn per click 9 | 10 | type 11 | Particle = object 12 | position: Vector2 13 | velocity: Vector2 14 | color: Color 15 | size: float32 16 | 17 | ParticleSystem = object 18 | buffer: pointer 19 | pool: ObjPool[Particle] 20 | activeParticles: array[MaxParticles, ptr Particle] 21 | activeCount: int32 22 | 23 | proc `=destroy`(x: ParticleSystem) = 24 | # x.pool.freeAll() 25 | dealloc(x.buffer) 26 | 27 | proc createParticleSystem(): ParticleSystem = 28 | result = ParticleSystem(activeCount: 0) 29 | let memSize = sizeof(Particle)*MaxParticles 30 | result.buffer = alloc(memSize) 31 | result.pool = createObjPool[Particle](result.buffer, memSize) 32 | 33 | proc updateParticle(particle: ptr Particle): bool = 34 | particle.position += particle.velocity 35 | particle.size -= 0.1 36 | result = particle.size > 0 37 | 38 | proc drawParticle(particle: ptr Particle) = 39 | drawCircle(particle.position, particle.size, particle.color) 40 | 41 | proc spawnParticles(system: var ParticleSystem, position: Vector2, count: int32) = 42 | for _ in 0 ..< count: 43 | if system.activeCount >= MaxParticles: 44 | break 45 | let newParticle = system.pool.alloc() 46 | if newParticle == nil: 47 | break 48 | let angle = rand(0.0..2*PI) 49 | let speed = rand(1.0..3.0) 50 | newParticle[] = Particle( 51 | position: position, 52 | velocity: Vector2(x: cos(angle) * speed, y: sin(angle) * speed), 53 | color: Color(r: uint8(rand(128..255)), g: uint8(rand(128..255)), b: uint8(rand(128..255)), a: 255), 54 | size: rand(5.0..20.0) 55 | ) 56 | system.activeParticles[system.activeCount] = newParticle 57 | inc system.activeCount 58 | 59 | proc updateParticleSystem(system: var ParticleSystem) = 60 | var i = 0 61 | while i < system.activeCount: 62 | if updateParticle(system.activeParticles[i]): 63 | inc i 64 | else: 65 | system.pool.free(system.activeParticles[i]) 66 | system.activeParticles[i] = system.activeParticles[system.activeCount - 1] 67 | dec system.activeCount 68 | 69 | proc drawParticleSystem(system: ParticleSystem) = 70 | for i in 0 ..< system.activeCount: 71 | drawParticle(system.activeParticles[i]) 72 | 73 | proc main() = 74 | var particleSystem = createParticleSystem() 75 | 76 | initWindow(screenWidth, screenHeight, "Raylib Nim rmem Example") 77 | setTargetFPS(60) 78 | 79 | while not windowShouldClose(): 80 | if isMouseButtonPressed(Left): 81 | let clickPosition = getMousePosition() 82 | spawnParticles(particleSystem, clickPosition, ParticlesPerClick) 83 | 84 | updateParticleSystem(particleSystem) 85 | 86 | drawing(): 87 | clearBackground(RayWhite) 88 | drawParticleSystem(particleSystem) 89 | drawText("Active Particles: " & $particleSystem.activeCount, 10, 10, 20, Black) 90 | 91 | closeWindow() 92 | 93 | main() 94 | -------------------------------------------------------------------------------- /personal/perceptron.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # naylib example - raylib perceptron 4 | # 5 | # The example is inspired by Chapter 10 of The Nature of Code 6 | # by Daniel Shiffman (http://natureofcode.com/book/chapter-10-neural-networks/). 7 | # 8 | # Example originally created with naylib 5.1 9 | # 10 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 11 | # BSD-like license that allows static linking with closed source software 12 | # 13 | # Copyright (c) 2024 Antonis Geralis (@planetis-m) 14 | # 15 | # **************************************************************************************** 16 | 17 | import raylib, rlgl, std/random 18 | 19 | const 20 | screenWidth = 800 21 | screenHeight = 450 22 | 23 | NumPoints = 2000 24 | 25 | type 26 | Perceptron = object 27 | weights: array[3, float32] # The perceptron has three inputs (including bias) 28 | lr: float32 # The learning rate 29 | 30 | proc initPerceptron(lr: float32): Perceptron = 31 | # Initialize the perceptron with random weights and a given learning rate 32 | result = Perceptron(lr: lr) 33 | for i in 0 ..< 3: 34 | result.weights[i] = rand(-1'f32..1'f32) 35 | 36 | proc feedForward(p: Perceptron, input: array[3, float32]): int32 = 37 | # Feedforward the input and get the output (1 or -1) 38 | var sum = 0'f32 39 | for i in 0 ..< 3: 40 | sum += input[i] * p.weights[i] 41 | result = if sum >= 0: 1 else: -1 42 | 43 | proc train(p: var Perceptron, input: array[3, float32], desired: int32) = 44 | # Train the perceptron with one input and the desired output 45 | let guess = p.feedForward(input) 46 | let error = desired - guess 47 | for i in 0 ..< 3: 48 | p.weights[i] += error.float32*input[i]*p.lr 49 | 50 | func f(x: float32): float32 = 51 | # The formula for a line 52 | 0.5'f32*x + 1 53 | 54 | # ---------------------------------------------------------------------------------------- 55 | # Program main entry point 56 | # ---------------------------------------------------------------------------------------- 57 | 58 | proc main = 59 | # Initialization 60 | # -------------------------------------------------------------------------------------- 61 | # Set up the raylib window 62 | setConfigFlags(flags(Msaa4xHint)) 63 | initWindow(screenWidth, screenHeight, "raylib example - perceptron") 64 | let camera = Camera2D(zoom: 1) 65 | randomize() 66 | var perceptron = initPerceptron(0.0001) # The perceptron with a learning rate of 0.0001 67 | var training: array[NumPoints, array[3, float32]] # An array for training data 68 | var count: int32 = 0 # A counter to track training data points one by one 69 | # Make 2,000 training data points 70 | for i in 0 ..< NumPoints: 71 | let x = rand(-screenWidth/2'f32..screenWidth/2'f32) 72 | let y = rand(-screenHeight/2'f32..screenHeight/2'f32) 73 | training[i] = [x, y, 1] 74 | setTargetFPS(25) # Set our game to run at 25 frames-per-second 75 | # -------------------------------------------------------------------------------------- 76 | # Main game loop 77 | while not windowShouldClose(): # Detect window close button or ESC key 78 | # Update 79 | # ------------------------------------------------------------------------------------ 80 | # Get the current (x, y) of the training data 81 | let (x, y) = (training[count][0], training[count][1]) 82 | # What is the desired output? 83 | let desired: int32 = if y > f(x): 1 else: -1 84 | # Train the perceptron 85 | perceptron.train(training[count], desired) 86 | # For animation, train one point at a time 87 | count = (count + 1) mod NumPoints 88 | # ------------------------------------------------------------------------------------ 89 | # Draw 90 | # ------------------------------------------------------------------------------------ 91 | drawing(): 92 | clearBackground(RayWhite) 93 | # Reorient the canvas to match a traditional Cartesian plane 94 | mode2D(camera): 95 | # Cull the front-facing triangles to flip the y-axis of the camera 96 | setCullFace(FaceFront) 97 | # Save the current transformation matrix on a stack 98 | pushMatrix() 99 | # Translate the origin to the center of the screen 100 | translatef(screenWidth/2'f32, screenHeight/2'f32, 0) 101 | # Flip the y-axis by scaling it by -1.0 102 | scalef(1, -1, 1) 103 | # Draw the line 104 | drawLine(Vector2(x: -screenWidth/2'f32, y: f(-screenWidth/2'f32)), 105 | Vector2(x: screenWidth/2'f32, y: f(screenWidth/2'f32)), 2, Black) 106 | # Draw all the points and color according to the output of the perceptron 107 | for dataPoint in training.items: 108 | let guess = perceptron.feedForward(dataPoint) 109 | let (x, y) = (dataPoint[0].int32, dataPoint[1].int32) 110 | drawCircle(x, y, 6, DarkGray) 111 | drawCircle(x, y, 4, if guess > 0: LightGray else: White) 112 | popMatrix() 113 | # ------------------------------------------------------------------------------------ 114 | # De-Initialization 115 | # -------------------------------------------------------------------------------------- 116 | closeWindow() # Close window and OpenGL context 117 | 118 | main() 119 | -------------------------------------------------------------------------------- /personal/resources/License.txt: -------------------------------------------------------------------------------- 1 | Lambda Rogue Tileset can be used in both non-commercial and commercial projects of any kind, excluding those relating to or containing non-fungible tokens ("NFT") or blockchain-related projects. It may not be used in conjunction with artificial intelligence or machine learning projects. You can modify it to suit your needs. You may not redistribute, or resell it, even if modified. Credit is not necessary, but very much appreciated. -------------------------------------------------------------------------------- /personal/resources/lambdarogue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/personal/resources/lambdarogue.png -------------------------------------------------------------------------------- /personal/resources/shaders/retro_crt.fs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes (from vertex shader) 4 | in vec2 fragTexCoord; 5 | in vec4 fragColor; 6 | 7 | // Input uniform values 8 | uniform sampler2D texture0; 9 | uniform vec2 size; 10 | uniform float seconds; 11 | 12 | // Output fragment color 13 | out vec4 finalColor; 14 | 15 | // NOTE: values should be passed from code 16 | const float vignetteOpacity = 1.0; 17 | const float scanLineOpacity = 0.5; 18 | const float curvature = 10.0; 19 | const float distortion = 0.1; 20 | const float gammaInput = 2.4; 21 | const float gammaOutput = 2.2; 22 | const float brightness = 1.5; 23 | 24 | vec2 curveRemapUV() { 25 | vec2 uv = fragTexCoord*2.0-1.0; 26 | vec2 offset = abs(uv.yx)/curvature; 27 | uv = uv + uv*offset*offset; 28 | uv = uv*0.5 + 0.5; 29 | return uv; 30 | } 31 | 32 | vec3 vignetteIntensity(vec2 uv, vec2 resolution, float opacity) { 33 | float intensity = uv.x*uv.y*(1.0 - uv.x)*(1.0 - uv.y); 34 | return vec3(clamp(pow(resolution.x*intensity, opacity), 0.0, 1.0)); 35 | } 36 | 37 | vec3 scanLineIntensity(float uv, float resolution, float opacity) { 38 | float intensity = sin(uv*resolution*2.0); 39 | intensity = ((0.5*intensity) + 0.5)*0.9 + 0.1; 40 | return vec3(pow(intensity, opacity)); 41 | } 42 | 43 | vec3 distortIntensity(vec2 uv, float time) { 44 | vec2 rg = sin(uv*10.0 + time)*distortion + 1.0; 45 | float b = sin((uv.x + uv.y)*10.0 + time)*distortion + 1.0; 46 | return vec3(rg, b); 47 | } 48 | 49 | void main() { 50 | vec2 uv = curveRemapUV(); 51 | vec3 baseColor = texture(texture0, uv).rgb; 52 | baseColor *= vignetteIntensity(uv, size, vignetteOpacity); 53 | // baseColor *= distortIntensity(uv, seconds); 54 | baseColor = pow(baseColor, vec3(gammaInput)); // gamma correction 55 | baseColor *= scanLineIntensity(uv.x, size.x, scanLineOpacity); 56 | baseColor *= scanLineIntensity(uv.y, size.y, scanLineOpacity); 57 | baseColor = pow(baseColor, vec3(1.0/gammaOutput)); // gamma correction 58 | baseColor *= vec3(brightness); 59 | 60 | if (uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0) { 61 | finalColor = vec4(0.0, 0.0, 0.0, 1.0); 62 | } else { 63 | finalColor = vec4(baseColor, 1.0); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /personal/resources/super_mario_bros.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/personal/resources/super_mario_bros.png -------------------------------------------------------------------------------- /personal/resources/wQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/personal/resources/wQ.png -------------------------------------------------------------------------------- /personal/retro_crt.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib example - Retro CRT Shader 4 | # https://babylonjs.medium.com/retro-crt-shader-a-post-processing-effect-study-1cb3f783afbc 5 | # 6 | # Example originally created with naylib 5.2 7 | # 8 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 9 | # BSD-like license that allows static linking with closed source software 10 | # 11 | # Copyright (c) 2024 Antonis Geralis (@planetis-m) 12 | # 13 | # **************************************************************************************** 14 | 15 | import raylib 16 | 17 | const 18 | screenWidth = 800 19 | screenHeight = 450 20 | 21 | const 22 | shaderCode = """ 23 | #version 330 24 | 25 | // Input vertex attributes (from vertex shader) 26 | in vec2 fragTexCoord; 27 | in vec4 fragColor; 28 | 29 | // Input uniform values 30 | uniform sampler2D texture0; 31 | uniform vec2 size; 32 | uniform float seconds; 33 | 34 | // Output fragment color 35 | out vec4 finalColor; 36 | 37 | // NOTE: values should be passed from code 38 | const float vignetteOpacity = 1.0; 39 | const float scanLineOpacity = 0.5; 40 | const float curvature = 10.0; 41 | const float distortion = 0.1; 42 | const float gammaInput = 2.4; 43 | const float gammaOutput = 2.2; 44 | const float brightness = 1.5; 45 | 46 | vec2 curveRemapUV() { 47 | vec2 uv = fragTexCoord*2.0-1.0; 48 | vec2 offset = abs(uv.yx)/curvature; 49 | uv = uv + uv*offset*offset; 50 | uv = uv*0.5 + 0.5; 51 | return uv; 52 | } 53 | 54 | vec3 vignetteIntensity(vec2 uv, vec2 resolution, float opacity) { 55 | float intensity = uv.x*uv.y*(1.0 - uv.x)*(1.0 - uv.y); 56 | return vec3(clamp(pow(resolution.x*intensity, opacity), 0.0, 1.0)); 57 | } 58 | 59 | vec3 scanLineIntensity(float uv, float resolution, float opacity) { 60 | float intensity = sin(uv*resolution*2.0); 61 | intensity = ((0.5*intensity) + 0.5)*0.9 + 0.1; 62 | return vec3(pow(intensity, opacity)); 63 | } 64 | 65 | vec3 distortIntensity(vec2 uv, float time) { 66 | vec2 rg = sin(uv*10.0 + time)*distortion + 1.0; 67 | float b = sin((uv.x + uv.y)*10.0 + time)*distortion + 1.0; 68 | return vec3(rg, b); 69 | } 70 | 71 | void main() { 72 | vec2 uv = curveRemapUV(); 73 | vec3 baseColor = texture(texture0, uv).rgb; 74 | baseColor *= vignetteIntensity(uv, size, vignetteOpacity); 75 | baseColor *= distortIntensity(uv, seconds); 76 | baseColor = pow(baseColor, vec3(gammaInput)); // gamma correction 77 | baseColor *= scanLineIntensity(uv.x, size.x, scanLineOpacity); 78 | baseColor *= scanLineIntensity(uv.y, size.y, scanLineOpacity); 79 | baseColor = pow(baseColor, vec3(1.0/gammaOutput)); // gamma correction 80 | baseColor *= vec3(brightness); 81 | 82 | if (uv.x < 0.0 || uv.y < 0.0 || uv.x > 1.0 || uv.y > 1.0) { 83 | finalColor = vec4(0.0, 0.0, 0.0, 1.0); 84 | } else { 85 | finalColor = vec4(baseColor, 1.0); 86 | } 87 | } 88 | """ 89 | 90 | proc main = 91 | # Initialization 92 | # -------------------------------------------------------------------------------------- 93 | initWindow(screenWidth, screenHeight, "raylib [shaders] example - Retro CRT Shader") 94 | defer: closeWindow() # Close window and OpenGL context 95 | 96 | # Load texture to apply shaders 97 | let texture = loadTexture("resources/super_mario_bros.png") 98 | # Load the CRT shader 99 | let shader = loadShaderFromMemory("", shaderCode) 100 | # Set shader uniforms 101 | let screenSize = [getScreenWidth().float32, getScreenHeight().float32] 102 | setShaderValue(shader, getShaderLocation(shader, "size"), screenSize) 103 | let secondsLoc = getShaderLocation(shader, "seconds") 104 | 105 | var seconds: float32 = 0 106 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 107 | # Main game loop 108 | # -------------------------------------------------------------------------------------- 109 | while not windowShouldClose(): # Detect window close button or ESC key 110 | # Update 111 | # ------------------------------------------------------------------------------------ 112 | seconds += getFrameTime() 113 | setShaderValue(shader, secondsLoc, seconds) 114 | # ------------------------------------------------------------------------------------ 115 | # Draw 116 | # ------------------------------------------------------------------------------------ 117 | beginDrawing() 118 | clearBackground(RayWhite) 119 | # Begin shader mode 120 | beginShaderMode(shader) 121 | drawTexture(texture, 0, 0, White) 122 | endShaderMode() 123 | endDrawing() 124 | # ------------------------------------------------------------------------------------ 125 | 126 | main() 127 | -------------------------------------------------------------------------------- /personal/shaderart.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib example - An introduction to Shader Art Coding (https://youtu.be/f4s1h2YETNY) 4 | # 5 | # Example originally created with naylib 5.2 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2024 Antonis Geralis (@planetis-m) 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib 15 | 16 | const 17 | screenWidth = 600 18 | screenHeight = 600 19 | 20 | const 21 | shaderCode = """ 22 | #version 330 23 | 24 | // Input vertex attributes (from vertex shader) 25 | in vec2 fragTexCoord; 26 | in vec4 fragColor; 27 | 28 | // Output fragment color 29 | out vec4 finalColor; 30 | 31 | // Custom variables 32 | uniform float seconds; 33 | uniform vec2 size; 34 | 35 | // NOTE: Render size values should be passed from code 36 | const float renderWidth = 600; 37 | const float renderHeight = 600; 38 | 39 | vec3 palette(float t) { 40 | vec3 a = vec3(0.5, 0.5, 0.5); 41 | vec3 b = vec3(0.5, 0.5, 0.5); 42 | vec3 c = vec3(1.0, 1.0, 1.0); 43 | vec3 d = vec3(0.263, 0.416, 0.557); 44 | return a + b*cos(6.28318*(c*t + d)); 45 | } 46 | 47 | void main() { 48 | vec2 uv = fragTexCoord*2.0 - 1.0; 49 | uv.x *= renderWidth/renderHeight; 50 | vec2 uv0 = uv; 51 | vec3 tmpColor = vec3(0.0); 52 | for (float i = 0.0; i < 4.0; i++) { 53 | uv = fract(uv*1.5) - 0.5; 54 | float d = length(uv)*exp(-length(uv0)); 55 | vec3 col = palette(length(uv0) + i*0.4 + seconds*0.4); 56 | d = sin(d*8.0 + seconds)/8.0; 57 | d = abs(d); 58 | d = pow(0.01/d, 1.2); 59 | tmpColor += col*d; 60 | } 61 | finalColor = vec4(tmpColor, 1.0); 62 | } 63 | """ 64 | 65 | proc main = 66 | # Initialization 67 | # -------------------------------------------------------------------------------------- 68 | initWindow(screenWidth, screenHeight, "raylib [shaders] example - Shader Art Coding") 69 | defer: closeWindow() # Close window and OpenGL context 70 | # Create a RenderTexture2D to be used for render to texture 71 | let target = loadRenderTexture(getScreenWidth(), getScreenHeight()) 72 | # Load shader and setup location points and values 73 | let shader = loadShaderFromMemory("", shaderCode) 74 | let secondsLoc = getShaderLocation(shader, "seconds") 75 | 76 | var seconds: float32 = 0 77 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 78 | # Main game loop 79 | # -------------------------------------------------------------------------------------- 80 | while not windowShouldClose(): # Detect window close button or ESC key 81 | # Update 82 | # ------------------------------------------------------------------------------------ 83 | seconds += getFrameTime() 84 | setShaderValue(shader, secondsLoc, seconds) 85 | # ------------------------------------------------------------------------------------ 86 | # Draw 87 | # ------------------------------------------------------------------------------------ 88 | # Using a render texture to draw 89 | beginTextureMode(target) # Enable drawing to texture 90 | clearBackground(Black) # Clear the render texture 91 | # Draw a rectangle in shader mode to be used as shader canvas 92 | drawRectangle(0, 0, getScreenWidth(), getScreenHeight(), Black) 93 | endTextureMode() 94 | beginDrawing() 95 | clearBackground(Black) 96 | # Begin shader mode 97 | beginShaderMode(shader) 98 | drawTexture(target.texture, Vector2(x: 0, y: 0), White) 99 | endShaderMode() 100 | endDrawing() 101 | # ------------------------------------------------------------------------------------ 102 | 103 | main() 104 | -------------------------------------------------------------------------------- /raylib_examples.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | version = "1.2.3" 3 | author = "Antonis Geralis" 4 | description = "Raylib examples" 5 | license = "Public Domain" 6 | 7 | # Dependencies 8 | requires "naylib" 9 | 10 | # Tasks 11 | import std/[os, strutils] 12 | 13 | task test, "Runs the test suite": 14 | for dir in ["audio", "core", "games", "models", "others", 15 | "personal", "shaders", "shapes", "text", "textures"]: 16 | for f in listFiles(thisDir().quoteShell / dir): 17 | if f.endsWith("maploader.nim"): continue # skip import 18 | if f.endsWith(".nim"): 19 | echo "Compiling example: ", f 20 | exec "nim c -d:release --verbosity:0 --hints:off " & quoteShell(f) 21 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # raylib-examples ported to Nim 2 | 3 | This repository contains [raylib](https://www.raylib.com/) examples ported to the [Nim programming language](https://nim-lang.org/). It also includes unique examples built with [naylib](https://github.com/planetis-m/naylib) from the start. 4 | 5 | ## Unique naylib Examples 6 | 7 | ### A* (IDA*) Path Finding 8 | **File:** [astar.nim](personal/astar.nim) 9 | 10 | This example demonstrates the IDA* (Iterative Deepening A*) path finding algorithm. It's an efficient way to find the shortest path between two points in a graph or grid. 11 | 12 | ![A* Path Finding](media/astar.png) 13 | 14 | ### Binary Search Tree 15 | **File:** [bst.nim](personal/bst.nim) 16 | 17 | An implementation and visualization of a binary search tree data structure. This example helps in understanding tree traversal and basic operations on a BST. 18 | 19 | ![Binary Search Tree](media/bst.png) 20 | 21 | ### Nim Crown 22 | **File:** [crown.nim](personal/crown.nim) 23 | 24 | A creative example that draws a crown using raylib's drawing functions, paying homage to the Nim programming language. 25 | 26 | ![Nim Crown](media/crown.png) 27 | 28 | ### 8 Queens Puzzle 29 | **File:** [nqueens.nim](personal/nqueens.nim) 30 | 31 | This classic chess puzzle challenges you to place eight queens on a chessboard so that no two queens threaten each other. The example provides a solver and visualization. 32 | 33 | ![8 Queens Puzzle](media/nqueens.png) 34 | 35 | ### Raylib Perceptron 36 | **File:** [perceptron.nim](personal/perceptron.nim) 37 | 38 | An implementation of a simple perceptron, demonstrating basic concepts of neural networks and machine learning using raylib for visualization. 39 | 40 | ![Raylib Perceptron](media/perceptron.png) 41 | 42 | ### Rogue (Advent of Code Solution) 43 | **File:** [rogue.nim](personal/rogue.nim) 44 | 45 | This example is a solution to the "Beverage Bandits" problem from Advent of Code 2018, Day 15. It implements a rogue-like game simulation. 46 | 47 | ![Rogue](media/rogue.png) 48 | 49 | [Problem Link](https://adventofcode.com/2018/day/15) 50 | 51 | ### Shader Art Coding 52 | **File:** [shaderart.nim](personal/shaderart.nim) 53 | 54 | An introduction to Shader Art Coding, based on the YouTube tutorial by @[kishimisu](https://github.com/kishimisu). This example demonstrates how to create interesting visual effects using shaders. 55 | 56 | ![Shader Art](media/shaderart.png) 57 | 58 | [Tutorial Video](https://youtu.be/f4s1h2YETNY) 59 | 60 | ### Target 9 Puzzle Game 61 | **File:** [target9.nim](personal/target9.nim) 62 | 63 | A puzzle game where the objective is to change all digits on a 3x3 grid to 9 by incrementing the values in selected rows and columns. 64 | 65 | ![Target 9](media/target9.png) 66 | 67 | ## Contributing 68 | 69 | We welcome contributions to this repository! If you have created an interesting 70 | example using raylib/naylib and Nim, feel free to submit it. Please ensure your 71 | code is well-commented and follows the existing style guidelines. 72 | 73 | ## License 74 | 75 | This project is licensed under the [MIT License](LICENSE). 76 | 77 | --- 78 | 79 | Happy coding with raylib and Nim! 80 | -------------------------------------------------------------------------------- /shaders/palette_switch.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shaders] example - Color palette switch 4 | # 5 | # NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, 6 | # OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. 7 | # 8 | # NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example 9 | # on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders 10 | # raylib comes with shaders ready for both versions, check raylib/shaders install folder 11 | # 12 | # This example has been created using raylib 2.3 (www.raylib.com) 13 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 14 | # 15 | # Example contributed by Marco Lizza (@MarcoLizza) and reviewed by Ramon Santamaria (@raysan5) 16 | # 17 | # Copyright (c) 2019 Marco Lizza (@MarcoLizza) and Ramon Santamaria (@raysan5) 18 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 19 | # 20 | # **************************************************************************************** 21 | 22 | import raylib, std/strformat 23 | 24 | when defined(GraphicsApiOpenGl33): 25 | const 26 | glslVersion = 330 27 | else: 28 | const 29 | glslVersion = 100 30 | 31 | const 32 | screenWidth = 800 33 | screenHeight = 450 34 | 35 | const 36 | MaxPalettes = 3 37 | ColorsPerPalette = 8 38 | ValuesPerColor = 3 39 | 40 | palettes: array[MaxPalettes, array[ColorsPerPalette, array[ValuesPerColor, int32]]] = [ 41 | [[0, 0, 0], 42 | [255, 0, 0], 43 | [0, 255, 0], 44 | [0, 0, 255], 45 | [0, 255, 255], 46 | [255, 0, 255], 47 | [255, 255, 0], 48 | [255, 255, 255]], # 3-BIT RGB 49 | [[4, 12, 6], 50 | [17, 35, 24], 51 | [30, 58, 41], 52 | [48, 93, 66], 53 | [77, 128, 97], 54 | [137, 162, 87], 55 | [190, 220, 127], 56 | [238, 255, 204]], # AMMO-8 (GameBoy-like) 57 | [[21, 25, 26], 58 | [138, 76, 88], 59 | [217, 98, 117], 60 | [230, 184, 193], 61 | [69, 107, 115], 62 | [75, 151, 166], 63 | [165, 189, 194], 64 | [255, 245, 247]] # RKBV (2-strip film) 65 | ] 66 | 67 | paletteText = [ 68 | "3-BIT RGB", 69 | "AMMO-8 (GameBoy-like)", 70 | "RKBV (2-strip film)" 71 | ] 72 | 73 | proc main = 74 | # Initialization 75 | # -------------------------------------------------------------------------------------- 76 | initWindow(screenWidth, screenHeight, "raylib [shaders] example - color palette switch") 77 | defer: closeWindow() # Close window and OpenGL context 78 | # Load shader to be used on some parts drawing 79 | # NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version 80 | # NOTE 2: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader 81 | let shader = loadShader("", &"resources/shaders/glsl{glslVersion}/palette_switch.fs") 82 | # Get variable (uniform) location on the shader to connect with the program 83 | # NOTE: If uniform variable could not be found in the shader, function returns -1 84 | let paletteLoc = getShaderLocation(shader, "palette") 85 | var currentPalette = 0 86 | const lineHeight = screenHeight div ColorsPerPalette 87 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 88 | # Main game loop 89 | # -------------------------------------------------------------------------------------- 90 | while not windowShouldClose(): # Detect window close button or ESC key 91 | # Update 92 | # ------------------------------------------------------------------------------------ 93 | if isKeyPressed(Right): inc currentPalette 94 | elif isKeyPressed(Left): dec currentPalette 95 | 96 | if currentPalette >= MaxPalettes: currentPalette = 0 97 | elif currentPalette < 0: currentPalette = MaxPalettes - 1 98 | # Send new value to the shader to be used on drawing. 99 | # NOTE: We are sending RGB triplets w/o the alpha channel 100 | setShaderValueV(shader, paletteLoc, palettes[currentPalette]) 101 | # Draw 102 | # ------------------------------------------------------------------------------------ 103 | beginDrawing() 104 | clearBackground(RayWhite) 105 | beginShaderMode(shader) 106 | for i in 0..", 10, 10, 30, DarkBlue) 113 | drawText("CURRENT PALETTE:", 60, 15, 20, RayWhite) 114 | drawText(paletteText[currentPalette], 300, 15, 20, Red) 115 | drawFPS(700, 15) 116 | endDrawing() 117 | # ------------------------------------------------------------------------------------ 118 | 119 | main() 120 | -------------------------------------------------------------------------------- /shaders/resources/models/old_car_new.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/models/old_car_new.glb -------------------------------------------------------------------------------- /shaders/resources/models/plane.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/models/plane.glb -------------------------------------------------------------------------------- /shaders/resources/old_car_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/old_car_d.png -------------------------------------------------------------------------------- /shaders/resources/old_car_e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/old_car_e.png -------------------------------------------------------------------------------- /shaders/resources/old_car_mra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/old_car_mra.png -------------------------------------------------------------------------------- /shaders/resources/old_car_n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/old_car_n.png -------------------------------------------------------------------------------- /shaders/resources/road_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/road_a.png -------------------------------------------------------------------------------- /shaders/resources/road_mra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/road_mra.png -------------------------------------------------------------------------------- /shaders/resources/road_n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/road_n.png -------------------------------------------------------------------------------- /shaders/resources/shaders/glsl100/palette_switch.fs: -------------------------------------------------------------------------------- 1 | #version 100 2 | 3 | precision mediump float; 4 | 5 | const int colors = 8; 6 | 7 | // Input vertex attributes (from vertex shader) 8 | varying vec2 fragTexCoord; 9 | varying vec4 fragColor; 10 | 11 | // Input uniform values 12 | uniform sampler2D texture0; 13 | uniform ivec3 palette[colors]; 14 | 15 | void main() 16 | { 17 | // Texel color fetching from texture sampler 18 | vec4 texelColor = texture2D(texture0, fragTexCoord)*fragColor; 19 | 20 | // Convert the (normalized) texel color RED component (GB would work, too) 21 | // to the palette index by scaling up from [0, 1] to [0, 255]. 22 | int index = int(texelColor.r*255.0); 23 | 24 | ivec3 color = ivec3(0); 25 | 26 | // NOTE: On GLSL 100 we are not allowed to index a uniform array by a variable value, 27 | // a constantmust be used, so this logic... 28 | if (index == 0) color = palette[0]; 29 | else if (index == 1) color = palette[1]; 30 | else if (index == 2) color = palette[2]; 31 | else if (index == 3) color = palette[3]; 32 | else if (index == 4) color = palette[4]; 33 | else if (index == 5) color = palette[5]; 34 | else if (index == 6) color = palette[6]; 35 | else if (index == 7) color = palette[7]; 36 | 37 | // Calculate final fragment color. Note that the palette color components 38 | // are defined in the range [0, 255] and need to be normalized to [0, 1] 39 | // for OpenGL to work. 40 | gl_FragColor = vec4(float(color.x)/255.0, float(color.y)/255.0, float(color.z)/255.0, texelColor.a); 41 | } 42 | -------------------------------------------------------------------------------- /shaders/resources/shaders/glsl100/wave.fs: -------------------------------------------------------------------------------- 1 | #version 100 2 | 3 | precision mediump float; 4 | 5 | // Input vertex attributes (from vertex shader) 6 | varying vec2 fragTexCoord; 7 | varying vec4 fragColor; 8 | 9 | // Input uniform values 10 | uniform sampler2D texture0; 11 | uniform vec4 colDiffuse; 12 | 13 | uniform float secondes; 14 | 15 | uniform vec2 size; 16 | 17 | uniform float freqX; 18 | uniform float freqY; 19 | uniform float ampX; 20 | uniform float ampY; 21 | uniform float speedX; 22 | uniform float speedY; 23 | 24 | void main() { 25 | float pixelWidth = 1.0 / size.x; 26 | float pixelHeight = 1.0 / size.y; 27 | float aspect = pixelHeight / pixelWidth; 28 | float boxLeft = 0.0; 29 | float boxTop = 0.0; 30 | 31 | vec2 p = fragTexCoord; 32 | p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth; 33 | p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight; 34 | 35 | gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor; 36 | } 37 | -------------------------------------------------------------------------------- /shaders/resources/shaders/glsl120/pbr.vs: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | // Input vertex attributes 4 | attribute vec3 vertexPosition; 5 | attribute vec2 vertexTexCoord; 6 | attribute vec3 vertexNormal; 7 | attribute vec3 vertexTangent; 8 | attribute vec4 vertexColor; 9 | 10 | // Input uniform values 11 | uniform mat4 mvp; 12 | uniform mat4 matModel; 13 | uniform mat4 matNormal; 14 | uniform vec3 lightPos; 15 | uniform vec4 difColor; 16 | 17 | // Output vertex attributes (to fragment shader) 18 | varying vec3 fragPosition; 19 | varying vec2 fragTexCoord; 20 | varying vec4 fragColor; 21 | varying vec3 fragNormal; 22 | varying mat3 TBN; 23 | 24 | const float normalOffset = 0.1; 25 | 26 | // https://github.com/glslify/glsl-inverse 27 | mat3 inverse(mat3 m) 28 | { 29 | float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; 30 | float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; 31 | float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; 32 | 33 | float b01 = a22*a11 - a12*a21; 34 | float b11 = -a22*a10 + a12*a20; 35 | float b21 = a21*a10 - a11*a20; 36 | 37 | float det = a00*b01 + a01*b11 + a02*b21; 38 | 39 | return mat3(b01, (-a22*a01 + a02*a21), (a12*a01 - a02*a11), 40 | b11, (a22*a00 - a02*a20), (-a12*a00 + a02*a10), 41 | b21, (-a21*a00 + a01*a20), (a11*a00 - a01*a10))/det; 42 | } 43 | 44 | // https://github.com/glslify/glsl-transpose 45 | mat3 transpose(mat3 m) 46 | { 47 | return mat3(m[0][0], m[1][0], m[2][0], 48 | m[0][1], m[1][1], m[2][1], 49 | m[0][2], m[1][2], m[2][2]); 50 | } 51 | 52 | void main() 53 | { 54 | 55 | // calc binormal from vertex normal and tangent 56 | vec3 vertexBinormal = cross(vertexNormal, vertexTangent); 57 | // calc fragment normal based on normal transformations 58 | mat3 normalMatrix = transpose(inverse(mat3(matModel))); 59 | // calc fragment position based on model transformations 60 | 61 | fragPosition = vec3(matModel*vec4(vertexPosition, 1.0)); 62 | 63 | fragTexCoord = vertexTexCoord*2.0; 64 | 65 | fragNormal = normalize(normalMatrix*vertexNormal); 66 | vec3 fragTangent = normalize(normalMatrix*vertexTangent); 67 | fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); 68 | vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); 69 | fragBinormal = cross(fragNormal, fragTangent); 70 | 71 | TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal)); 72 | 73 | // Calculate final vertex position 74 | gl_Position = mvp * vec4(vertexPosition, 1.0); 75 | } -------------------------------------------------------------------------------- /shaders/resources/shaders/glsl330/palette_switch.fs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | const int colors = 8; 4 | 5 | // Input fragment attributes (from fragment shader) 6 | in vec2 fragTexCoord; 7 | in vec4 fragColor; 8 | 9 | // Input uniform values 10 | uniform sampler2D texture0; 11 | uniform ivec3 palette[colors]; 12 | 13 | // Output fragment color 14 | out vec4 finalColor; 15 | 16 | void main() 17 | { 18 | // Texel color fetching from texture sampler 19 | vec4 texelColor = texture(texture0, fragTexCoord)*fragColor; 20 | 21 | // Convert the (normalized) texel color RED component (GB would work, too) 22 | // to the palette index by scaling up from [0, 1] to [0, 255]. 23 | int index = int(texelColor.r*255.0); 24 | ivec3 color = palette[index]; 25 | 26 | // Calculate final fragment color. Note that the palette color components 27 | // are defined in the range [0, 255] and need to be normalized to [0, 1] 28 | // for OpenGL to work. 29 | finalColor = vec4(color/255.0, texelColor.a); 30 | } 31 | -------------------------------------------------------------------------------- /shaders/resources/shaders/glsl330/pbr.vs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes 4 | in vec3 vertexPosition; 5 | in vec2 vertexTexCoord; 6 | in vec3 vertexNormal; 7 | in vec3 vertexTangent; 8 | in vec4 vertexColor; 9 | 10 | // Input uniform values 11 | uniform mat4 mvp; 12 | uniform mat4 matModel; 13 | uniform mat4 matNormal; 14 | uniform vec3 lightPos; 15 | uniform vec4 difColor; 16 | 17 | // Output vertex attributes (to fragment shader) 18 | out vec3 fragPosition; 19 | out vec2 fragTexCoord; 20 | out vec4 fragColor; 21 | out vec3 fragNormal; 22 | out mat3 TBN; 23 | 24 | const float normalOffset = 0.1; 25 | 26 | void main() 27 | { 28 | // Compute binormal from vertex normal and tangent 29 | vec3 vertexBinormal = cross(vertexNormal, vertexTangent); 30 | 31 | // Compute fragment normal based on normal transformations 32 | mat3 normalMatrix = transpose(inverse(mat3(matModel))); 33 | 34 | // Compute fragment position based on model transformations 35 | fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f)); 36 | 37 | fragTexCoord = vertexTexCoord*2.0; 38 | fragNormal = normalize(normalMatrix*vertexNormal); 39 | vec3 fragTangent = normalize(normalMatrix*vertexTangent); 40 | fragTangent = normalize(fragTangent - dot(fragTangent, fragNormal)*fragNormal); 41 | vec3 fragBinormal = normalize(normalMatrix*vertexBinormal); 42 | fragBinormal = cross(fragNormal, fragTangent); 43 | 44 | TBN = transpose(mat3(fragTangent, fragBinormal, fragNormal)); 45 | 46 | // Calculate final vertex position 47 | gl_Position = mvp*vec4(vertexPosition, 1.0); 48 | } -------------------------------------------------------------------------------- /shaders/resources/shaders/glsl330/wave.fs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes (from vertex shader) 4 | in vec2 fragTexCoord; 5 | in vec4 fragColor; 6 | 7 | // Input uniform values 8 | uniform sampler2D texture0; 9 | uniform vec4 colDiffuse; 10 | 11 | // Output fragment color 12 | out vec4 finalColor; 13 | 14 | uniform float secondes; 15 | 16 | uniform vec2 size; 17 | 18 | uniform float freqX; 19 | uniform float freqY; 20 | uniform float ampX; 21 | uniform float ampY; 22 | uniform float speedX; 23 | uniform float speedY; 24 | 25 | void main() { 26 | float pixelWidth = 1.0 / size.x; 27 | float pixelHeight = 1.0 / size.y; 28 | float aspect = pixelHeight / pixelWidth; 29 | float boxLeft = 0.0; 30 | float boxTop = 0.0; 31 | 32 | vec2 p = fragTexCoord; 33 | p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth; 34 | p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight; 35 | 36 | finalColor = texture(texture0, p)*colDiffuse*fragColor; 37 | } 38 | -------------------------------------------------------------------------------- /shaders/resources/space.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/shaders/resources/space.png -------------------------------------------------------------------------------- /shaders/texture_waves.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shaders] example - Texture Waves 4 | # 5 | # NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, 6 | # OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version. 7 | # 8 | # NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example 9 | # on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders 10 | # raylib comes with shaders ready for both versions, check raylib/shaders install folder 11 | # 12 | # This example has been created using raylib 2.5 (www.raylib.com) 13 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 14 | # 15 | # Example contributed by Anata (@anatagawa) and reviewed by Ramon Santamaria (@raysan5) 16 | # 17 | # Copyright (c) 2019 Anata (@anatagawa) and Ramon Santamaria (@raysan5) 18 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 19 | # 20 | # **************************************************************************************** 21 | 22 | import raylib, std/strformat 23 | 24 | const 25 | screenWidth = 800 26 | screenHeight = 450 27 | 28 | when defined(GraphicsApiOpenGl33): 29 | const 30 | glslVersion = 330 31 | else: 32 | const 33 | glslVersion = 100 34 | 35 | proc main = 36 | # Initialization 37 | # -------------------------------------------------------------------------------------- 38 | initWindow(screenWidth, screenHeight, "raylib [shaders] example - texture waves") 39 | defer: closeWindow() # Close window and OpenGL context 40 | 41 | # Load texture to apply shaders 42 | let texture = loadTexture("resources/space.png") 43 | 44 | # Load shader and setup location points and values 45 | let shader = loadShader("", &"resources/shaders/glsl{glslVersion}/wave.fs") 46 | let secondsLoc = getShaderLocation(shader, "secondes") 47 | let freqXLoc = getShaderLocation(shader, "freqX") 48 | let freqYLoc = getShaderLocation(shader, "freqY") 49 | let ampXLoc = getShaderLocation(shader, "ampX") 50 | let ampYLoc = getShaderLocation(shader, "ampY") 51 | let speedXLoc = getShaderLocation(shader, "speedX") 52 | let speedYLoc = getShaderLocation(shader, "speedY") 53 | 54 | # Shader uniform values that can be updated at any time 55 | let freqX: float32 = 25 56 | let freqY: float32 = 25 57 | let ampX: float32 = 5 58 | let ampY: float32 = 5 59 | let speedX: float32 = 8 60 | let speedY: float32 = 8 61 | 62 | let screenSize = [getScreenWidth().float32, getScreenHeight().float32] 63 | setShaderValue(shader, getShaderLocation(shader, "size"), screenSize) 64 | setShaderValue(shader, freqXLoc, freqX) 65 | setShaderValue(shader, freqYLoc, freqY) 66 | setShaderValue(shader, ampXLoc, ampX) 67 | setShaderValue(shader, ampYLoc, ampY) 68 | setShaderValue(shader, speedXLoc, speedX) 69 | setShaderValue(shader, speedYLoc, speedY) 70 | 71 | var seconds: float32 = 0 72 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 73 | # Main game loop 74 | # -------------------------------------------------------------------------------------- 75 | while not windowShouldClose(): # Detect window close button or ESC key 76 | # Update 77 | # ------------------------------------------------------------------------------------ 78 | seconds += getFrameTime() 79 | setShaderValue(shader, secondsLoc, seconds) 80 | # ------------------------------------------------------------------------------------ 81 | # Draw 82 | # ------------------------------------------------------------------------------------ 83 | beginDrawing() 84 | clearBackground(RayWhite) 85 | beginShaderMode(shader) 86 | drawTexture(texture, 0, 0, White) 87 | drawTexture(texture, texture.width, 0, White) 88 | endShaderMode() 89 | endDrawing() 90 | # ------------------------------------------------------------------------------------ 91 | 92 | main() 93 | -------------------------------------------------------------------------------- /shapes/basic_shapes.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shapes] example - Draw basic shapes 2d (rectangle, circle, line...) 4 | # 5 | # This example has been created using raylib 1.0 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2014 Ramon Santamaria (@raysan5) 9 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 10 | # 11 | # **************************************************************************************** 12 | 13 | import raylib 14 | 15 | const 16 | screenWidth = 800 17 | screenHeight = 450 18 | 19 | proc main = 20 | initWindow(screenWidth, screenHeight, "raylib [shapes] example - basic shapes drawing") 21 | setTargetFPS(60) 22 | # Main game loop 23 | # -------------------------------------------------------------------------------------- 24 | while not windowShouldClose(): # Detect window close button or ESC key 25 | # Draw 26 | # ------------------------------------------------------------------------------------ 27 | beginDrawing() 28 | clearBackground(RayWhite) 29 | drawText("some basic shapes available on raylib", 20, 20, 20, DarkGray) 30 | 31 | # Circle shapes and lines 32 | drawCircle(screenWidth div 5, 120, 35, DarkBlue) 33 | drawCircleGradient(screenWidth div 5, 220, 60, Green, SkyBlue) 34 | drawCircleLines(screenWidth div 5, 340, 80, DarkBlue) 35 | 36 | # Rectangle shapes and lines 37 | drawRectangle(screenWidth div 4 * 2 - 60, 100, 120, 60, Red) 38 | drawRectangleGradientH(screenWidth div 4 * 2 - 90, 170, 180, 130, Maroon, Gold) 39 | drawRectangleLines(screenWidth div 4 * 2 - 40, 320, 80, 60, Orange) # NOTE: Uses QUADS internally, not lines 40 | 41 | # Triangle shapes and lines 42 | drawTriangle(Vector2(x: screenWidth/4'f32 * 3, y: 80), 43 | Vector2(x: screenWidth/4'f32 * 3 - 60, y: 150), 44 | Vector2(x: screenWidth/4'f32 * 3 + 60, y: 150), Violet) 45 | 46 | drawTriangleLines(Vector2(x: screenWidth/4'f32 * 3, y: 160), 47 | Vector2(x: screenWidth/4'f32 * 3 - 20, y: 230), 48 | Vector2(x: screenWidth/4'f32 * 3 + 20, y: 230), DarkBlue) 49 | 50 | # Polygon shapes and lines 51 | drawPoly(Vector2(x: screenWidth/4'f32 * 3, y: 320), 6, 80, 0, Brown) 52 | drawPolyLines(Vector2(x: screenWidth/4'f32 * 3, y: 320), 6, 80, 0, 6, Beige) 53 | 54 | # NOTE: We draw all LINES based shapes together to optimize internal drawing, 55 | # this way, all LINES are rendered in a single draw pass 56 | drawLine(18, 42, screenWidth - 18'i32, 42, Black) 57 | endDrawing() 58 | # ------------------------------------------------------------------------------------ 59 | # De-Initialization 60 | # -------------------------------------------------------------------------------------- 61 | closeWindow() # Close window and OpenGL context 62 | # -------------------------------------------------------------------------------------- 63 | 64 | main() 65 | -------------------------------------------------------------------------------- /shapes/collision_area.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shapes] example - collision area 4 | # 5 | # This example has been created using raylib 2.5 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2013-2019 Ramon Santamaria (@raysan5) 9 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 10 | # 11 | # **************************************************************************************** 12 | 13 | import raylib, std/[lenientops, strutils] 14 | 15 | const 16 | screenWidth = 800 17 | screenHeight = 450 18 | 19 | proc main = 20 | # Initialization 21 | # -------------------------------------------------------------------------------------- 22 | initWindow(screenWidth, screenHeight, "raylib [shapes] example - collision area") 23 | # Box A: Moving box 24 | var boxA = Rectangle( 25 | x: 10, 26 | y: getScreenHeight()/2'f32 - 50, 27 | width: 200, 28 | height: 100 29 | ) 30 | var boxASpeedX: int32 = 4 31 | # Box B: Mouse moved box 32 | var boxB = Rectangle( 33 | x: getScreenWidth()/2'f32 - 30, 34 | y: getScreenHeight()/2'f32 - 30, 35 | width: 60, 36 | height: 60 37 | ) 38 | var boxCollision: Rectangle # Collision rectangle 39 | var screenUpperLimit: int32 = 40 # Top menu limits 40 | var pause = false # Movement pause 41 | var collision = false # Collision detection 42 | 43 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 44 | # Main game loop 45 | # -------------------------------------------------------------------------------------- 46 | while not windowShouldClose(): # Detect window close button or ESC key 47 | # Update 48 | # ------------------------------------------------------------------------------------ 49 | # Move box if not paused 50 | if not pause: 51 | boxA.x += boxASpeedX.float32 52 | if boxA.x + boxA.width >= getScreenWidth() or boxA.x <= 0: 53 | boxASpeedX = boxASpeedX * -1 54 | boxB.x = getMouseX() - boxB.width/2'f32 55 | boxB.y = getMouseY() - boxB.height/2'f32 56 | # Make sure Box B does not go out of move area limits 57 | if boxB.x + boxB.width >= getScreenWidth(): 58 | boxB.x = getScreenWidth() - boxB.width 59 | elif boxB.x <= 0: 60 | boxB.x = 0 61 | if boxB.y + boxB.height >= getScreenHeight(): 62 | boxB.y = getScreenHeight() - boxB.height 63 | elif boxB.y <= screenUpperLimit: # Check boxes collision 64 | boxB.y = screenUpperLimit.float32 65 | collision = checkCollisionRecs(boxA, boxB) 66 | # Get collision rectangle (only on collision) 67 | if collision: 68 | boxCollision = getCollisionRec(boxA, boxB) 69 | if isKeyPressed(Space): 70 | pause = not pause 71 | # ------------------------------------------------------------------------------------ 72 | # Draw 73 | # ------------------------------------------------------------------------------------ 74 | beginDrawing() 75 | clearBackground(White) 76 | drawRectangle(0, 0, screenWidth, screenUpperLimit, if collision: Red else: Black) 77 | drawRectangle(boxA, Gold) 78 | drawRectangle(boxB, Blue) 79 | if collision: 80 | # Draw collision area 81 | drawRectangle(boxCollision, Lime) 82 | # Draw collision message 83 | drawText("COLLISION!", getScreenWidth() div 2 - measureText("COLLISION!", 20) div 2, 84 | screenUpperLimit div 2 - 10, 20, Black) 85 | # Draw collision area 86 | drawText(format("Collision Area: $#", boxCollision.width.int32*boxCollision.height.int32), 87 | getScreenWidth() div 2 - 100, screenUpperLimit + 10, 20, Black) 88 | drawFPS(10, 10) 89 | endDrawing() 90 | # ------------------------------------------------------------------------------------ 91 | # De-Initialization 92 | # -------------------------------------------------------------------------------------- 93 | closeWindow() # Close window and OpenGL context 94 | # -------------------------------------------------------------------------------------- 95 | 96 | main() 97 | -------------------------------------------------------------------------------- /shapes/easings_ball_anim.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shapes] example - easings ball anim 4 | # 5 | # Example originally created with raylib 2.5, last time updated with raylib 2.5 6 | # 7 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 8 | # BSD-like license that allows static linking with closed source software 9 | # 10 | # Copyright (c) 2014-2022 Ramon Santamaria (@raysan5) 11 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 12 | # 13 | # **************************************************************************************** 14 | 15 | import raylib, reasings 16 | 17 | const 18 | screenWidth = 800 19 | screenHeight = 450 20 | 21 | type 22 | State = enum 23 | BounceX, BounceZ, FadeOut, Reset 24 | 25 | # ---------------------------------------------------------------------------------------- 26 | # Program main entry point 27 | # ---------------------------------------------------------------------------------------- 28 | 29 | proc main = 30 | # Initialization 31 | # -------------------------------------------------------------------------------------- 32 | initWindow(screenWidth, screenHeight, "raylib [shapes] example - easings ball anim") 33 | # Ball variable value to be animated with easings 34 | var ballPositionX: int32 = -100 35 | var ballRadius: int32 = 20 36 | var ballAlpha: float32 = 0.0 37 | var state = BounceX 38 | var framesCounter: int32 = 0 39 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 40 | # -------------------------------------------------------------------------------------- 41 | # Main game loop 42 | while not windowShouldClose(): # Detect window close button or ESC key 43 | # Update 44 | # ------------------------------------------------------------------------------------ 45 | case state 46 | of BounceX: 47 | inc(framesCounter) 48 | ballPositionX = elasticOut(framesCounter.float32, -100, screenWidth / 2 + 100, 120).int32 49 | if framesCounter >= 120: 50 | framesCounter = 0 51 | state = BounceZ 52 | of BounceZ: # Increase ball radius with easing 53 | inc(framesCounter) 54 | ballRadius = elasticIn(framesCounter.float32, 20, 500, 200).int32 55 | if framesCounter >= 200: 56 | framesCounter = 0 57 | state = FadeOut 58 | of FadeOut: # Change ball alpha with easing (background color blending) 59 | inc(framesCounter) 60 | ballAlpha = cubicOut(framesCounter.float32, 0, 1, 200) 61 | if framesCounter >= 200: 62 | framesCounter = 0 63 | state = Reset 64 | of Reset: # Reset state to play again 65 | if isKeyPressed(Enter): 66 | # Reset required variables to play again 67 | ballPositionX = -100 68 | ballRadius = 20 69 | ballAlpha = 0 70 | state = BounceX 71 | if isKeyPressed(R): 72 | framesCounter = 0 73 | # ------------------------------------------------------------------------------------ 74 | # Draw 75 | # ------------------------------------------------------------------------------------ 76 | beginDrawing() 77 | clearBackground(RayWhite) 78 | if state >= FadeOut: 79 | drawRectangle(0, 0, screenWidth, screenHeight, Green) 80 | drawCircle(ballPositionX, 200, ballRadius.float32, fade(Red, 1 - ballAlpha)) 81 | if state == Reset: 82 | drawText("PRESS [ENTER] TO PLAY AGAIN!", 240, 200, 20, Black) 83 | endDrawing() 84 | # ------------------------------------------------------------------------------------ 85 | # De-Initialization 86 | # -------------------------------------------------------------------------------------- 87 | closeWindow() # Close window and OpenGL context 88 | # -------------------------------------------------------------------------------------- 89 | 90 | main() 91 | -------------------------------------------------------------------------------- /shapes/easings_rectangle_array.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [shapes] example - easings rectangle array 4 | # 5 | # NOTE: This example requires 'easings.h' library, provided on raylib/src. Just copy 6 | # the library to same directory as example or make sure it's available on include path. 7 | # 8 | # Example originally created with raylib 2.0, last time updated with raylib 2.5 9 | # 10 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 11 | # BSD-like license that allows static linking with closed source software 12 | # 13 | # Copyright (c) 2014-2022 Ramon Santamaria (@raysan5) 14 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 15 | # 16 | # **************************************************************************************** 17 | 18 | import raylib, reasings, std/lenientops 19 | 20 | const 21 | screenWidth = 800 22 | screenHeight = 450 23 | 24 | const 25 | RecsWidth = 50 26 | RecsHeight = 50 27 | MaxRecsX = 800 div RecsWidth 28 | MaxRecsY = 450 div RecsHeight 29 | PlayTimeInFrames = 240 # At 60 fps = 4 seconds 30 | 31 | type 32 | State = enum 33 | Playing, Finished 34 | 35 | # ---------------------------------------------------------------------------------------- 36 | # Program main entry point 37 | # ---------------------------------------------------------------------------------------- 38 | 39 | proc main = 40 | # Initialization 41 | # -------------------------------------------------------------------------------------- 42 | initWindow(screenWidth, screenHeight, "raylib [shapes] example - easings rectangle array") 43 | 44 | var recs: array[MaxRecsX*MaxRecsY, Rectangle] 45 | for y in 0 ..< MaxRecsY: 46 | for x in 0 ..< MaxRecsX: 47 | recs[y*MaxRecsX + x] = Rectangle( 48 | x: RecsWidth/2'f32 + RecsWidth*x, 49 | y: RecsHeight/2'f32 + RecsHeight*y, 50 | width: RecsWidth, 51 | height: RecsHeight 52 | ) 53 | 54 | var rotation: float32 = 0 55 | var framesCounter: int32 = 0 56 | var state = Playing # Rectangles animation state: 0-Playing, 1-Finished 57 | 58 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 59 | # -------------------------------------------------------------------------------------- 60 | # Main game loop 61 | while not windowShouldClose(): # Detect window close button or ESC key 62 | # Update 63 | # ------------------------------------------------------------------------------------ 64 | if state == Playing: 65 | inc(framesCounter) 66 | for i in 0 ..< MaxRecsX*MaxRecsY: 67 | recs[i].height = circOut(framesCounter.float32, RecsHeight, -RecsHeight, PlayTimeInFrames) 68 | recs[i].width = circOut(framesCounter.float32, RecsWidth, -RecsWidth, PlayTimeInFrames) 69 | if recs[i].height < 0: 70 | recs[i].height = 0 71 | if recs[i].width < 0: 72 | recs[i].width = 0 73 | if recs[i].height == 0 and recs[i].width == 0: 74 | state = Finished 75 | rotation = linearIn(framesCounter.float32, 0, 360, PlayTimeInFrames) 76 | elif state == Finished and isKeyPressed(Space): 77 | # When animation has finished, press space to restart 78 | framesCounter = 0 79 | for i in 0 ..< MaxRecsX*MaxRecsY: 80 | recs[i].height = RecsHeight 81 | recs[i].width = RecsWidth 82 | state = Playing 83 | # ------------------------------------------------------------------------------------ 84 | # Draw 85 | # ------------------------------------------------------------------------------------ 86 | beginDrawing() 87 | clearBackground(RayWhite) 88 | if state == Playing: 89 | for i in 0 ..< MaxRecsX*MaxRecsY: 90 | drawRectangle(recs[i], Vector2(x: recs[i].width/2, y: recs[i].height/2), rotation, Red) 91 | elif state == Finished: 92 | drawText("PRESS [SPACE] TO PLAY AGAIN!", 240, 200, 20, Gray) 93 | endDrawing() 94 | # ------------------------------------------------------------------------------------ 95 | # De-Initialization 96 | # -------------------------------------------------------------------------------------- 97 | closeWindow() 98 | # Close window and OpenGL context 99 | # -------------------------------------------------------------------------------------- 100 | 101 | main() 102 | -------------------------------------------------------------------------------- /text/font_loading.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [text] example - Font loading 4 | # 5 | # NOTE: raylib can load fonts from multiple input file formats: 6 | # 7 | # - TTF/OTF > Sprite font atlas is generated on loading, user can configure 8 | # some of the generation parameters (size, characters to include) 9 | # - BMFonts > Angel code font fileformat, sprite font image must be provided 10 | # together with the .fnt file, font generation cna not be configured 11 | # - XNA Spritefont > Sprite font image, following XNA Spritefont conventions, 12 | # Characters in image must follow some spacing and order rules 13 | # 14 | # Example originally created with raylib 1.4, last time updated with raylib 3.0 15 | # 16 | # Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, 17 | # BSD-like license that allows static linking with closed source software 18 | # 19 | # Copyright (c) 2016-2024 Ramon Santamaria (@raysan5) 20 | # 21 | # **************************************************************************************** 22 | 23 | import raylib 24 | 25 | const 26 | screenWidth = 800 27 | screenHeight = 450 28 | msg = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ" # Define characters to draw 29 | 30 | # ---------------------------------------------------------------------------------------- 31 | # Program main entry point 32 | # ---------------------------------------------------------------------------------------- 33 | 34 | proc main() = 35 | # Initialization 36 | # ------------------------------------------------------------------------------------- 37 | initWindow(screenWidth, screenHeight, "raylib [text] example - font loading") 38 | defer: closeWindow() # Ensure window closure on proc exit 39 | 40 | # Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) 41 | let 42 | # BMFont (AngelCode) : Font data and image atlas have been generated using external program 43 | fontBm = loadFont("resources/pixantiqua.fnt") 44 | # TTF font : Font data and atlas are generated directly from TTF 45 | # NOTE: We define a font base size of 32 pixels tall and up-to 250 characters 46 | fontTtf = loadFont("resources/pixantiqua.ttf", 32, 250) 47 | 48 | setTextLineSpacing(16) # Set line spacing for multiline text (when line breaks are included '\n') 49 | var useTtf = false 50 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 51 | # Main game loop 52 | # ------------------------------------------------------------------------------------- 53 | while not windowShouldClose(): # Detect window close button or ESC key 54 | # Update 55 | # ----------------------------------------------------------------------------------- 56 | if isKeyDown(Space): 57 | useTtf = true 58 | else: 59 | useTtf = false 60 | # Draw 61 | # ----------------------------------------------------------------------------------- 62 | beginDrawing() 63 | clearBackground(RayWhite) 64 | 65 | drawText("Hold SPACE to use TTF generated font", 20, 20, 20, LightGray) 66 | 67 | if not useTtf: 68 | drawText(fontBm, msg, Vector2(x: 20, y: 100), fontBm.baseSize.float32, 2, Maroon) 69 | drawText("Using BMFont (Angelcode) imported", 20, getScreenHeight() - 30, 20, Gray) 70 | else: 71 | drawText(fontTtf, msg, Vector2(x: 20, y: 100), fontTtf.baseSize.float32, 2, Lime) 72 | drawText("Using TTF font generated", 20, getScreenHeight() - 30, 20, Gray) 73 | 74 | endDrawing() 75 | 76 | main() 77 | -------------------------------------------------------------------------------- /text/font_sdf.nim: -------------------------------------------------------------------------------- 1 | # *************************************************************************************** 2 | # 3 | # raylib [text] example - TTF loading and usage 4 | # 5 | # This example has been created using raylib 1.3.0 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2015 Ramon Santamaria (@raysan5) 9 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 10 | # 11 | # *************************************************************************************** 12 | 13 | import raylib, std/[strformat, lenientops] 14 | 15 | when defined(GraphicsApiOpenGl33): 16 | const 17 | glslVersion = 330 18 | else: 19 | const 20 | glslVersion = 100 21 | 22 | const 23 | screenWidth = 800 24 | screenHeight = 450 25 | 26 | Message = "Signed Distance Fields" 27 | 28 | template toBytes(x: string): untyped = 29 | toOpenArrayByte(x, 0, x.high) 30 | 31 | proc main = 32 | # Initialization 33 | # ------------------------------------------------------------------------------------- 34 | initWindow(screenWidth, screenHeight, "raylib [text] example - SDF fonts") 35 | defer: closeWindow() # Close window and OpenGL context 36 | # NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required) 37 | # Loading file to memory 38 | let fileData = readFile("resources/anonymous_pro_bold.ttf") 39 | # Default font generation from TTF font 40 | # Loading font data from memory data 41 | # Parameters > font size: 16, no glyphs array provided (0), glyphs count: 95 (autogenerate chars array) 42 | let glyphsDefault = loadFontData(fileData.toBytes, 16, 95, Default) 43 | # Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 4 px, pack method: 0 (default) 44 | let fontDefault = loadFontFromData(glyphsDefault, 16, 4, 0) 45 | # SDF font generation from TTF font 46 | # Parameters > font size: 16, no glyphs array provided (0), glyphs count: 0 (defaults to 95) 47 | let glyphsSdf = loadFontData(fileData.toBytes, 16, 0, Sdf) 48 | # Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 0 px, pack method: 1 (Skyline algorythm) 49 | let fontSdf = loadFontFromData(glyphsSdf, 16, 0, 1) 50 | # Load SDF required shader (we use default vertex shader) 51 | var shader = loadShader("", &"resources/shaders/glsl{glslVersion}/sdf.fs") 52 | setTextureFilter(fontSdf.texture, Bilinear) # Required for SDF font 53 | var fontPosition = Vector2(x: 40, y: screenHeight/2'f32 - 50) 54 | var textSize = Vector2(x: 0, y: 0) 55 | var fontSize: float32 = 16 56 | var currentFont = 0 # 0 - fontDefault, 1 - fontSdf 57 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 58 | # Main game loop 59 | # ------------------------------------------------------------------------------------- 60 | while not windowShouldClose(): # Detect window close button or ESC key 61 | # Update 62 | # ----------------------------------------------------------------------------------- 63 | fontSize += getMouseWheelMove()*8 64 | if fontSize < 6: 65 | fontSize = 6 66 | if isKeyDown(Space): 67 | currentFont = 1 68 | else: 69 | currentFont = 0 70 | if currentFont == 0: 71 | textSize = measureText(fontDefault, Message, fontSize, 0) 72 | else: 73 | textSize = measureText(fontSdf, Message, fontSize, 0) 74 | fontPosition.x = getScreenWidth()/2'f32 - textSize.x/2'f32 75 | fontPosition.y = getScreenHeight()/2'f32 - textSize.y/2'f32 + 80 76 | # Draw 77 | # ----------------------------------------------------------------------------------- 78 | beginDrawing() 79 | clearBackground(RayWhite) 80 | if currentFont == 1: 81 | # NOTE: SDF fonts require a custom SDf shader to compute fragment color 82 | beginShaderMode(shader) # Activate SDF font shader 83 | drawText(fontSdf, Message, fontPosition, fontSize, 0, Black) 84 | endShaderMode() # Activate our default shader for next drawings 85 | drawTexture(fontSdf.texture, 10, 10, Black) 86 | else: 87 | drawText(fontDefault, Message, fontPosition, fontSize, 0, Black) 88 | drawTexture(fontDefault.texture, 10, 10, Black) 89 | if currentFont == 1: 90 | drawText("SDF!", 320, 20, 80, Red) 91 | else: 92 | drawText("default font", 315, 40, 30, Gray) 93 | drawText("FONT SIZE: 16.0", getScreenWidth() - 240, 20, 20, DarkGray) 94 | drawText(&"RENDER SIZE: {fontSize}:02f", getScreenWidth() - 240, 50, 20, DarkGray) 95 | drawText("Use MOUSE WHEEL to SCALE TEXT!", getScreenWidth() - 240, 90, 10, DarkGray) 96 | drawText("HOLD SPACE to USE SDF FONT VERSION!", 340, getScreenHeight() - 30, 20, Maroon) 97 | endDrawing() 98 | 99 | main() 100 | -------------------------------------------------------------------------------- /text/resources/anonymous_pro_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/text/resources/anonymous_pro_bold.ttf -------------------------------------------------------------------------------- /text/resources/dejavu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/text/resources/dejavu.png -------------------------------------------------------------------------------- /text/resources/noto_cjk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/text/resources/noto_cjk.png -------------------------------------------------------------------------------- /text/resources/pixantiqua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/text/resources/pixantiqua.png -------------------------------------------------------------------------------- /text/resources/pixantiqua.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/text/resources/pixantiqua.ttf -------------------------------------------------------------------------------- /text/resources/shaders/glsl100/sdf.fs: -------------------------------------------------------------------------------- 1 | #version 100 2 | 3 | precision mediump float; 4 | 5 | // Input vertex attributes (from vertex shader) 6 | varying vec2 fragTexCoord; 7 | varying vec4 fragColor; 8 | 9 | // Input uniform values 10 | uniform sampler2D texture0; 11 | uniform vec4 colDiffuse; 12 | 13 | // NOTE: Add here your custom variables 14 | const float smoothing = 1.0/16.0; 15 | 16 | void main() 17 | { 18 | // Texel color fetching from texture sampler 19 | // NOTE: Calculate alpha using signed distance field (SDF) 20 | float distance = texture2D(texture0, fragTexCoord).a; 21 | float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, distance); 22 | 23 | // Calculate final fragment color 24 | gl_FragColor = vec4(fragColor.rgb, fragColor.a*alpha); 25 | } 26 | -------------------------------------------------------------------------------- /text/resources/shaders/glsl330/sdf.fs: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | // Input vertex attributes (from vertex shader) 4 | in vec2 fragTexCoord; 5 | in vec4 fragColor; 6 | 7 | // Input uniform values 8 | uniform sampler2D texture0; 9 | uniform vec4 colDiffuse; 10 | 11 | // Output fragment color 12 | out vec4 finalColor; 13 | 14 | // NOTE: Add here your custom variables 15 | 16 | void main() 17 | { 18 | // Texel color fetching from texture sampler 19 | // NOTE: Calculate alpha using signed distance field (SDF) 20 | float distanceFromOutline = texture(texture0, fragTexCoord).a - 0.5; 21 | float distanceChangePerFragment = length(vec2(dFdx(distanceFromOutline), dFdy(distanceFromOutline))); 22 | float alpha = smoothstep(-distanceChangePerFragment, distanceChangePerFragment, distanceFromOutline); 23 | 24 | // Calculate final fragment color 25 | finalColor = vec4(fragColor.rgb, fragColor.a*alpha); 26 | } 27 | -------------------------------------------------------------------------------- /text/resources/symbola.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planetis-m/raylib-examples/b32a2b24dcbbab2207a273d06bb2cce6ac77160d/text/resources/symbola.png -------------------------------------------------------------------------------- /textures/background_scrolling.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [textures] example - Background scrolling 4 | # 5 | # This example has been created using raylib 2.0 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2019 Ramon Santamaria (@raysan5) 9 | # Converted in 2021 by greenfork 10 | # Modified by Antonis Geralis (@planetis-m) in 2022 11 | # 12 | # **************************************************************************************** 13 | 14 | import std/lenientops, raylib 15 | 16 | const 17 | screenWidth = 800 18 | screenHeight = 450 19 | 20 | proc main = 21 | # Initialization 22 | # -------------------------------------------------------------------------------------- 23 | initWindow(screenWidth, screenHeight, "raylib [textures] example - background scrolling") 24 | defer: closeWindow() # Close window and OpenGL context 25 | 26 | # NOTE: Be careful, background width must be equal or bigger than screen width 27 | # if not, texture should be draw more than two times for scrolling effect 28 | let background = loadTexture("resources/cyberpunk_street_background.png") 29 | let midground = loadTexture("resources/cyberpunk_street_midground.png") 30 | let foreground = loadTexture("resources/cyberpunk_street_foreground.png") 31 | 32 | var scrollingBack: float32 = 0 33 | var scrollingMid: float32 = 0 34 | var scrollingFore: float32 = 0 35 | 36 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 37 | # -------------------------------------------------------------------------------------- 38 | # Main game loop 39 | while not windowShouldClose(): # Detect window close button or ESC key 40 | # Update 41 | # ------------------------------------------------------------------------------------ 42 | scrollingBack -= 0.1 43 | scrollingMid -= 0.5 44 | scrollingFore -= 1.0 45 | 46 | # NOTE: Texture is scaled twice its size, so it sould be considered on scrolling 47 | if scrollingBack <= -background.width * 2'f32: 48 | scrollingBack = 0 49 | if scrollingMid <= -midground.width * 2'f32: 50 | scrollingMid = 0 51 | if scrollingFore <= -foreground.width * 2'f32: 52 | scrollingFore = 0 53 | 54 | beginDrawing() 55 | clearBackground(getColor(0x052c46ff)) 56 | # Draw background image twice 57 | # NOTE: Texture is scaled twice its size 58 | drawTexture(background, Vector2(x: scrollingBack, y: 20), 0, 2, White) 59 | drawTexture(background, Vector2(x: background.width * 2 + scrollingBack, y: 20), 0, 2, White) 60 | # Draw midground image twice 61 | drawTexture(midground, Vector2(x: scrollingMid, y: 20), 0, 2, White) 62 | drawTexture(midground, Vector2(x: midground.width * 2 + scrollingMid, y: 20), 0, 2, White) 63 | # Draw foreground image twice 64 | drawTexture(foreground, Vector2(x: scrollingFore, y: 70), 0, 2, White) 65 | drawTexture(foreground, Vector2(x: foreground.width * 2 + scrollingFore, y: 70), 0, 2, White) 66 | drawText("BACKGROUND SCROLLING & PARALLAX", 10, 10, 20, Red) 67 | drawText("(c) Cyberpunk Street Environment by Luis Zuno (@ansimuz)", 68 | screenWidth - 330, screenHeight - 20, 10, RayWhite) 69 | endDrawing() 70 | # ------------------------------------------------------------------------------------ 71 | 72 | main() 73 | -------------------------------------------------------------------------------- /textures/bunnymark.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [textures] example - Bunnymark 4 | # 5 | # This example has been created using raylib 1.6 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2014-2019 Ramon Santamaria (@raysan5) 9 | # Converted in 2021 by greenfork 10 | # Modified by Antonis Geralis (@planetis-m) in 2022 11 | # 12 | # **************************************************************************************** 13 | 14 | import raylib, std/[lenientops, random, strformat] 15 | 16 | const 17 | screenHeight = 450 18 | screenWidth = 800 19 | 20 | MaxBunnies = 50_000 # 50K bunnies limit 21 | # This is the maximum amount of elements (quads) per batch 22 | # NOTE: This value is defined in [rlgl] module and can be changed there 23 | MaxBatchElements = 8192 24 | 25 | type 26 | Bunny = object 27 | position: Vector2 28 | speed: Vector2 29 | color: Color 30 | 31 | proc main = 32 | # Initialization 33 | # -------------------------------------------------------------------------------------- 34 | initWindow(screenWidth, screenHeight, "raylib [textures] example - bunnymark") 35 | defer: closeWindow() # Close window and OpenGL context 36 | 37 | # Load bunny texture 38 | let texBunny = loadTexture("resources/wabbit_alpha.png") 39 | var bunnies = newSeq[Bunny](MaxBunnies) # Bunnies seq 40 | 41 | var bunniesCount = 0 # Bunnies counter 42 | setTargetFPS(60) # Set our game to run at 60 frames-per-second 43 | # Main game loop 44 | # -------------------------------------------------------------------------------------- 45 | while not windowShouldClose(): # Detect window close button or ESC key 46 | # Update 47 | # ------------------------------------------------------------------------------------ 48 | if isMouseButtonDown(Left): 49 | # Create more bunnies 50 | for i in 0..<100: 51 | if bunniesCount < MaxBunnies: 52 | bunnies[bunniesCount] = Bunny( 53 | position: getMousePosition(), 54 | speed: Vector2( 55 | x: rand(-250..250)/60'f32, 56 | y: rand(-250..250)/60'f32 57 | ), 58 | color: Color( 59 | r: rand(50'u8..240'u8), 60 | g: rand(80'u8..240'u8), 61 | b: rand(100'u8..240'u8), 62 | a: 255 63 | ) 64 | ) 65 | inc bunniesCount 66 | for i in 0.. getScreenWidth() or 71 | bunnies[i].position.x + texBunny.width/2'f32 < 0: 72 | bunnies[i].speed.x *= -1 73 | if bunnies[i].position.y + texBunny.height/2'f32 > getScreenHeight() or 74 | bunnies[i].position.y + texBunny.height/2'f32 - 40 < 0: 75 | bunnies[i].speed.y *= -1 76 | # ------------------------------------------------------------------------------------ 77 | # Draw 78 | # ------------------------------------------------------------------------------------ 79 | beginDrawing() 80 | clearBackground(RayWhite) 81 | for i in 0..= 60 div framesSpeed: 45 | framesCounter = 0 46 | inc currentFrame 47 | if currentFrame > 5: 48 | currentFrame = 0 49 | frameRec.x = currentFrame*(scarfy.width/6'f32) 50 | if isKeyPressed(Right): 51 | inc framesSpeed 52 | elif isKeyPressed(Left): 53 | dec framesSpeed 54 | if framesSpeed > MaxFrameSpeed: 55 | framesSpeed = MaxFrameSpeed 56 | elif framesSpeed < MinFrameSpeed: 57 | framesSpeed = MinFrameSpeed 58 | # ------------------------------------------------------------------------------------ 59 | # Draw 60 | # ------------------------------------------------------------------------------------ 61 | beginDrawing() 62 | clearBackground(RayWhite) 63 | drawTexture(scarfy, 15, 40, White) 64 | drawRectangleLines(15, 40, scarfy.width, scarfy.height, Lime) 65 | drawRectangleLines(15 + frameRec.x.int32, 40 + frameRec.y.int32, frameRec.width.int32, 66 | frameRec.height.int32, Red) 67 | drawText("FRAME SPEED: ", 165, 210, 10, DarkGray) 68 | drawText(format("$# FPS", framesSpeed), 575, 210, 10, DarkGray) 69 | drawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, DarkGray) 70 | for i in 0.. 2: 62 | inc(currentFrame) 63 | if currentFrame >= FramesPerLine: 64 | currentFrame = 0 65 | inc(currentLine) 66 | if currentLine >= Lines: 67 | currentLine = 0 68 | active = false 69 | framesCounter = 0 70 | frameRec.x = frameWidth*currentFrame 71 | frameRec.y = frameHeight*currentLine 72 | # ------------------------------------------------------------------------------------ 73 | # Draw 74 | # ------------------------------------------------------------------------------------ 75 | beginDrawing() 76 | clearBackground(RayWhite) 77 | # Draw explosion required frame rectangle 78 | if active: 79 | drawTexture(explosion, frameRec, position, White) 80 | endDrawing() 81 | # ------------------------------------------------------------------------------------ 82 | 83 | main() 84 | -------------------------------------------------------------------------------- /textures/srcrec_dstrec.nim: -------------------------------------------------------------------------------- 1 | # **************************************************************************************** 2 | # 3 | # raylib [textures] example - Texture source and destination rectangles 4 | # 5 | # This example has been created using raylib 1.3 (www.raylib.com) 6 | # raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 7 | # 8 | # Copyright (c) 2015 Ramon Santamaria (@raysan5) 9 | # Converted to Nim by Antonis Geralis (@planetis-m) in 2022 10 | # 11 | # **************************************************************************************** 12 | 13 | import raylib, std/lenientops 14 | 15 | const 16 | screenWidth = 800 17 | screenHeight = 450 18 | 19 | proc main = 20 | initWindow(screenWidth, screenHeight, 21 | "raylib [textures] examples - texture source and destination rectangles") 22 | defer: closeWindow() # Close window and OpenGL context 23 | 24 | # NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) 25 | let scarfy = loadTexture("resources/scarfy.png") # Texture loading 26 | let frameWidth = scarfy.width div 6 27 | let frameHeight = scarfy.height 28 | # Source rectangle (part of the texture to use for drawing) 29 | let sourceRec = Rectangle(x: 0, y: 0, width: frameWidth.float32, height: frameHeight.float32) 30 | # Destination rectangle (screen rectangle where drawing part of texture) 31 | let destRec = Rectangle( 32 | x: screenWidth/2'f32, 33 | y: screenHeight/2'f32, 34 | width: frameWidth*2'f32, 35 | height: frameHeight*2'f32 36 | ) 37 | # Origin of the texture (rotation/scale point), it's relative to destination rectangle size 38 | let origin = Vector2(x: frameWidth.float32, y: frameHeight.float32) 39 | var rotation: int32 = 0 40 | 41 | setTargetFPS(60) 42 | # Main game loop 43 | # -------------------------------------------------------------------------------------- 44 | while not windowShouldClose(): # Detect window close button or ESC key 45 | # Update 46 | # ------------------------------------------------------------------------------------ 47 | inc(rotation) 48 | # ------------------------------------------------------------------------------------ 49 | # Draw 50 | # ------------------------------------------------------------------------------------ 51 | beginDrawing() 52 | clearBackground(RayWhite) 53 | # NOTE: Using DrawTexturePro() we can easily rotate and scale the part of the texture we draw 54 | # sourceRec defines the part of the texture we use for drawing 55 | # destRec defines the rectangle where our texture part will fit (scaling it to fit) 56 | # origin defines the point of the texture used as reference for rotation and scaling 57 | # rotation defines the texture rotation (using origin as rotation point) 58 | drawTexture(scarfy, sourceRec, destRec, origin, rotation.float32, White) 59 | drawLine(destRec.x.int32, 0, destRec.x.int32, screenHeight, Gray) 60 | drawLine(0, destRec.y.int32, screenWidth, destRec.y.int32, Gray) 61 | drawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, Gray) 62 | endDrawing() 63 | # ------------------------------------------------------------------------------------ 64 | 65 | main() 66 | --------------------------------------------------------------------------------