├── .gitignore ├── .gitattributes ├── resources └── grass.png ├── CONTRIBUTING.md ├── src ├── game_mouse.h ├── world │ ├── worldmodel.h │ ├── perlin.h │ ├── worldgeneration.h │ ├── worldgeneration.c │ ├── perlin.c │ └── worldmodel.c ├── game_camera.h ├── player.h ├── game_mouse.c ├── game_camera.c ├── main.c └── player.c ├── .vscode ├── settings.json ├── tasks.json ├── c_cpp_properties.json └── launch.json ├── main.code-workspace ├── README.md ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── Makefile └── Makefile.Android /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | **/.DS_Store 3 | 4 | cmake-build-debug 5 | .idea -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /resources/grass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietmichal/raycraft/HEAD/resources/grass.png -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | The project is open for contributions. 2 | 3 | The rules will be expanded as the project grows. 4 | -------------------------------------------------------------------------------- /src/game_mouse.h: -------------------------------------------------------------------------------- 1 | #ifndef RAYCRAFT_GAME_MOUSE_H 2 | #define RAYCRAFT_GAME_MOUSE_H 3 | 4 | #include "raylib.h" 5 | 6 | void UpdateMouseMovement(); 7 | Vector2 GetMouseMovement(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/*.o": true, 9 | "**/*.exe": true, 10 | } 11 | } -------------------------------------------------------------------------------- /src/world/worldmodel.h: -------------------------------------------------------------------------------- 1 | // raycraft (c) Nikolas Wipper 2020 2 | 3 | #ifndef RAYCRAFT_WORLDMODEL_H 4 | #define RAYCRAFT_WORLDMODEL_H 5 | 6 | #include 7 | 8 | Model GetWorldModel(int *world); 9 | 10 | #endif //RAYCRAFT_WORLDMODEL_H 11 | -------------------------------------------------------------------------------- /main.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "files.associations": { 9 | "raylib.h": "c", 10 | "math.h": "c", 11 | "blocks.h": "c", 12 | "stdio.h": "c", 13 | "*.m": "c", 14 | "camera.h": "c", 15 | "gamecamera.h": "c", 16 | "raymath.h": "c", 17 | "game_camera.h": "c" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/game_camera.h: -------------------------------------------------------------------------------- 1 | #ifndef RAYCRAFT_CAMERA_H 2 | #define RAYCRAFT_CAMERA_H 3 | 4 | #include "raylib.h" 5 | #include "player.h" 6 | 7 | typedef struct GameCamera 8 | { 9 | struct Camera3D camera; 10 | Vector3 rotation; 11 | } GameCamera; 12 | 13 | 14 | GameCamera *CreateGameCamera(); 15 | void UpdateGameCamera(GameCamera *gameCamera, Player *player); 16 | 17 | #endif -------------------------------------------------------------------------------- /src/world/perlin.h: -------------------------------------------------------------------------------- 1 | // raycraft (c) Nikolas Wipper 2020 2 | 3 | #ifndef RAYCRAFT_PERLIN_H 4 | #define RAYCRAFT_PERLIN_H 5 | 6 | int noise2(int x, int y); 7 | float lin_inter(float x, float y, float s); 8 | float smooth_inter(float x, float y, float s); 9 | float noise2d(float x, float y); 10 | float perlin2d(float x, float y, float freq, int depth); 11 | 12 | #endif //RAYCRAFT_PERLIN_H 13 | -------------------------------------------------------------------------------- /src/world/worldgeneration.h: -------------------------------------------------------------------------------- 1 | // raycraft (c) Nikolas Wipper 2020 2 | 3 | #ifndef RAYCRAFT_WORLDGENERATION_H 4 | #define RAYCRAFT_WORLDGENERATION_H 5 | 6 | #define WORLD_MAX_X 100 7 | #define WORLD_MAX_Z 100 8 | #define WORLD_MAX_Y 16 9 | 10 | #include 11 | #include 12 | 13 | int GetWorldCube(int *world, int x, int y, int z); 14 | void SetWorldCube(int *world, int x, int y, int z, int value); 15 | int *GenerateWorld(); 16 | 17 | #endif //RAYCRAFT_WORLDGENERATION_H 18 | -------------------------------------------------------------------------------- /src/player.h: -------------------------------------------------------------------------------- 1 | #ifndef RAYCRAFT_PLAYER_H 2 | #define RAYCRAFT_PLAYER_H 3 | 4 | #define FORWARD_KEY KEY_W 5 | #define BACKWARD_KEY KEY_S 6 | #define LEFT_KEY KEY_A 7 | #define RIGHT_KEY KEY_D 8 | 9 | #include "raylib.h" 10 | 11 | typedef struct Player { 12 | Vector3 position; 13 | Vector3 size; 14 | Vector3 velocity; 15 | float yaw; 16 | float friction; // Note: keep it in the player for simplicity's sake 17 | } Player; 18 | 19 | Player *CreatePlayer(Vector3 position); 20 | void UpdatePlayer(Player* player, int *world); 21 | 22 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raycraft 2 | 3 | by Michał Pietraszko ([Follow him on twitter](https://twitter.com/pietmichal)) 4 | 5 | Minecraft-clone made using [raylib](https://github.com/raysan5/raylib). 6 | 7 | Work in progress. 8 | 9 | ## Game todo 10 | 11 | - gravity + collision 12 | - Destroying blocks 13 | - Placing blocks 14 | 15 | ## Repo todos 16 | 17 | - How to download, compile and run guide. 18 | - Automated releases with executable in it. 19 | - Github actions to deploy wasm build to teh internets. 20 | - Automate nicely looking contributors list generation 21 | 22 | ## Contributors 23 | 24 | - [G3bE](https://github.com/G3bE) 25 | 26 | :shipit: 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /src/game_mouse.c: -------------------------------------------------------------------------------- 1 | #include "raylib.h" 2 | #include "raymath.h" 3 | #include "game_mouse.h" 4 | 5 | #define SMOOTHNESS 0.001f 6 | #define SENSITIVITY 2.0f 7 | 8 | // Note: Can we get away without using globals? 9 | static Vector2 previousMousePosition = (Vector2){0}; 10 | static Vector2 mouseMovement = (Vector2){0}; 11 | 12 | // Important: Call ONCE at the beginning of every frame! 13 | void UpdateMouseMovement() 14 | { 15 | Vector2 currentMousePosition = GetMousePosition(); 16 | mouseMovement = Vector2MultiplyV( 17 | Vector2Subtract(currentMousePosition, previousMousePosition), 18 | (Vector2){SMOOTHNESS * SENSITIVITY, SMOOTHNESS * SENSITIVITY}); 19 | previousMousePosition = currentMousePosition; 20 | } 21 | 22 | Vector2 GetMouseMovement() 23 | { 24 | return mouseMovement; 25 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 pietmichal 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 | -------------------------------------------------------------------------------- /src/world/worldgeneration.c: -------------------------------------------------------------------------------- 1 | #include "worldgeneration.h" 2 | 3 | #include "perlin.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int GetWorldCube(int *world, int x, int y, int z) 10 | { 11 | if (x < WORLD_MAX_X && x >= 0 && 12 | y < WORLD_MAX_Y && y >= 0 && 13 | z < WORLD_MAX_Z && z >= 0) 14 | return world[(y * WORLD_MAX_X * WORLD_MAX_Z) + (z * WORLD_MAX_X) + x]; 15 | return 0; 16 | } 17 | 18 | void SetWorldCube(int *world, int x, int y, int z, int value) 19 | { 20 | if (x < WORLD_MAX_X && x >= 0 && 21 | y < WORLD_MAX_Y && y >= 0 && 22 | z < WORLD_MAX_Z && z >= 0) 23 | world[(y * WORLD_MAX_X * WORLD_MAX_Z) + (z * WORLD_MAX_X) + x] = value; 24 | } 25 | 26 | int *GenerateWorld() 27 | { 28 | int *world = RL_MALLOC(WORLD_MAX_X * WORLD_MAX_Y * WORLD_MAX_Z * sizeof(int)); 29 | 30 | for (int x = 0; x < WORLD_MAX_X; x++) 31 | { 32 | for (int y = 0; y < WORLD_MAX_Y; y++) 33 | { 34 | for (int z = 0; z < WORLD_MAX_Z; z++) 35 | { 36 | int maxY = round(WORLD_MAX_Y * perlin2d(x, z, 0.06f, WORLD_MAX_Y)); 37 | if (y <= maxY) 38 | { 39 | SetWorldCube(world, x, y, z, 1); 40 | } 41 | else 42 | { 43 | SetWorldCube(world, x, y, z, 0); 44 | } 45 | } 46 | } 47 | } 48 | 49 | return world; 50 | } 51 | -------------------------------------------------------------------------------- /src/game_camera.c: -------------------------------------------------------------------------------- 1 | #include "raylib.h" 2 | #include "raymath.h" 3 | #include "stdlib.h" 4 | #include "game_camera.h" 5 | #include "player.h" 6 | #include "game_mouse.h" 7 | 8 | GameCamera *CreateGameCamera() 9 | { 10 | GameCamera *gameCamera = RL_MALLOC(sizeof(GameCamera)); 11 | 12 | gameCamera->camera.position = (Vector3){0}; 13 | gameCamera->camera.target = (Vector3){0}; 14 | gameCamera->camera.up = (Vector3){0.0f, 1.0f, 0.0f}; 15 | gameCamera->camera.fovy = 60.0f; 16 | gameCamera->camera.type = CAMERA_PERSPECTIVE; 17 | gameCamera->rotation = (Vector3){0}; 18 | 19 | return gameCamera; 20 | } 21 | 22 | void UpdateGameCamera(GameCamera *gameCamera, Player *player) 23 | { 24 | gameCamera->camera.position.x = player->position.x; 25 | 26 | // Note: place camera on top of player's head. 27 | gameCamera->camera.position.y = player->position.y + (player->size.y/2); 28 | gameCamera->camera.position.z = player->position.z; 29 | 30 | // todo: limit camera rotation 31 | gameCamera->rotation.y -= GetMouseMovement().y; 32 | 33 | Matrix translation = MatrixTranslate(0, 0, 1); 34 | 35 | // Note: y rotation is bound to a camera, x rotation is bound to the player 36 | Matrix rotation = MatrixRotateXYZ((Vector3){PI * 2 - gameCamera->rotation.y, PI * 2 - player->yaw, 0}); 37 | Matrix transform = MatrixMultiply(translation, rotation); 38 | 39 | gameCamera->camera.target.x = gameCamera->camera.position.x - transform.m12; 40 | gameCamera->camera.target.y = gameCamera->camera.position.y - transform.m13; 41 | gameCamera->camera.target.z = gameCamera->camera.position.z - transform.m14; 42 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "build debug", 8 | "type": "process", 9 | "command": "make", 10 | "args": [ 11 | "PLATFORM=PLATFORM_DESKTOP", 12 | "BUILD_MODE=DEBUG" 13 | ], 14 | "windows": { 15 | "command": "C:/raylib/mingw/bin/mingw32-make.exe", 16 | "args": [ 17 | "RAYLIB_PATH=C:/raylib/raylib", 18 | "PROJECT_NAME=game", 19 | ], 20 | }, 21 | "osx": { 22 | "args": [ 23 | "RAYLIB_PATH=/raylib" 24 | ], 25 | }, 26 | "group": { 27 | "kind": "build", 28 | "isDefault": true 29 | }, 30 | "problemMatcher": [ 31 | "$gcc" 32 | ] 33 | }, 34 | { 35 | "label": "build release", 36 | "type": "process", 37 | "command": "make", 38 | "args": [ 39 | "PLATFORM=PLATFORM_DESKTOP", 40 | ], 41 | "windows": { 42 | "command": "C:/raylib/mingw/bin/mingw32-make.exe", 43 | "args": [ 44 | "RAYLIB_PATH=C:/raylib/raylib", 45 | "PROJECT_NAME=game", 46 | ], 47 | }, 48 | "osx": { 49 | "args": [ 50 | "RAYLIB_PATH=/raylib", 51 | ], 52 | }, 53 | "group": "build", 54 | "problemMatcher": [ 55 | "$gcc" 56 | ] 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Win32", 5 | "includePath": [ 6 | "C:/raylib/raylib/src/**", 7 | "${workspaceFolder}/**" 8 | ], 9 | "defines": [ 10 | "_DEBUG", 11 | "UNICODE", 12 | "_UNICODE", 13 | "GRAPHICS_API_OPENGL_33", 14 | "PLATFORM_DESKTOP" 15 | ], 16 | "compilerPath": "C:/raylib/mingw/bin/gcc.exe", 17 | "cStandard": "c99", 18 | "cppStandard": "c++14", 19 | "intelliSenseMode": "gcc-x64" 20 | }, 21 | { 22 | "name": "Mac", 23 | "includePath": [ 24 | "/src/**", 25 | "${workspaceFolder}/**" 26 | ], 27 | "defines": [ 28 | "_DEBUG", 29 | "UNICODE", 30 | "_UNICODE", 31 | "GRAPHICS_API_OPENGL_33", 32 | "PLATFORM_DESKTOP" 33 | ], 34 | "macFrameworkPath": [ 35 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks" 36 | ], 37 | "compilerPath": "/usr/bin/clang", 38 | "cStandard": "c11", 39 | "cppStandard": "c++14", 40 | "intelliSenseMode": "clang-x64" 41 | }, 42 | { 43 | "name": "Linux", 44 | "includePath": [ 45 | "/src/**", 46 | "${workspaceFolder}/**" 47 | ], 48 | "defines": [ 49 | "_DEBUG", 50 | "UNICODE", 51 | "_UNICODE", 52 | "GRAPHICS_API_OPENGL_33", 53 | "PLATFORM_DESKTOP" 54 | ], 55 | "compilerPath": "usr/bin/clang", 56 | "cStandard": "c11", 57 | "cppStandard": "c++14", 58 | "intelliSenseMode": "clang-x64" 59 | 60 | } 61 | ], 62 | "version": 4 63 | } 64 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Debug", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${workspaceFolder}/game", 12 | "args": [], 13 | "stopAtEntry": false, 14 | "cwd": "${workspaceFolder}", 15 | "environment": [], 16 | "externalConsole": false, 17 | "MIMode": "gdb", 18 | "setupCommands": [ 19 | { 20 | "description": "Enable pretty-printing for gdb", 21 | "text": "-enable-pretty-printing", 22 | "ignoreFailures": false 23 | } 24 | ], 25 | "windows": { 26 | "miDebuggerPath": "C:/raylib/mingw/bin/gdb.exe", 27 | }, 28 | "osx": { 29 | "MIMode": "lldb" 30 | }, 31 | "linux": { 32 | "miDebuggerPath": "/usr/bin/gdb", 33 | }, 34 | "preLaunchTask": "build debug" 35 | }, 36 | { 37 | "name": "Run", 38 | "type": "cppdbg", 39 | "request": "launch", 40 | "args": [], 41 | "stopAtEntry": false, 42 | "cwd": "${workspaceFolder}", 43 | "environment": [], 44 | "externalConsole": false, 45 | "program": "${workspaceFolder}/game", 46 | "MIMode": "gdb", 47 | "windows": { 48 | "program": "${workspaceFolder}/game.exe", 49 | "miDebuggerPath": "C:/raylib/mingw/bin/gdb.exe" 50 | }, 51 | "osx": { 52 | "MIMode": "lldb" 53 | }, 54 | "linux": { 55 | "miDebuggerPath": "/usr/bin/gdb" 56 | }, 57 | "preLaunchTask": "build release", 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "world/worldgeneration.h" 2 | #include "world/worldmodel.h" 3 | #include "game_mouse.h" 4 | #include "game_camera.h" 5 | #include "player.h" 6 | #include "raymath.h" 7 | 8 | int main(void) 9 | { 10 | const int screenWidth = 1920 / 2; 11 | const int screenHeight = 1080 / 2; 12 | 13 | InitWindow(screenWidth, screenHeight, "Raycraft"); 14 | 15 | // SetTargetFPS(60); 16 | 17 | int *world = GenerateWorld(); 18 | Model worldModel = GetWorldModel(world); 19 | 20 | GameCamera *gameCamera = CreateGameCamera(); 21 | Player *player = CreatePlayer((Vector3){0, 20.0f, 0}); 22 | 23 | DisableCursor(); 24 | 25 | while (!WindowShouldClose()) 26 | { 27 | 28 | UpdateMouseMovement(); 29 | 30 | BeginDrawing(); 31 | { 32 | ClearBackground(SKYBLUE); 33 | 34 | BeginMode3D(gameCamera->camera); 35 | { 36 | 37 | UpdatePlayer(player, world); 38 | UpdateGameCamera(gameCamera, player); 39 | // Clouds 40 | DrawCube((Vector3){600.0f, 200.0f, 600.0f}, 100.0f, 10.0f, 37.0f, WHITE); 41 | DrawCube((Vector3){250.0f, 200.0f, 150.0f}, 49.0f, 10.0f, 40.0f, WHITE); 42 | DrawCube((Vector3){900.0f, 200.0f, 130.0f}, 60.0f, 10.0f, 300.0f, WHITE); 43 | DrawCube((Vector3){200.0f, 200.0f, -50.0f}, 30.0f, 10.0f, 37.0f, WHITE); 44 | DrawCube((Vector3){1000.0f, 200.0f, 200.0f}, 30.0f, 10.0f, 37.0f, WHITE); 45 | DrawCube((Vector3){50.0f, 200.0f, 30.0f}, 30.0f, 10.0f, 37.0f, WHITE); 46 | // World 47 | DrawModel(worldModel, (Vector3){0, 0, 0}, 1.0f, WHITE); 48 | // Player 49 | DrawCubeWiresV(player->position, player->size, RED); 50 | } 51 | EndMode3D(); 52 | 53 | // DrawText(FormatText("x: %f\ny: %f\nz: %f", player->position.x, player->position.y, player->position.z), 10, 10, 16, WHITE); 54 | 55 | float x = player->position.x; 56 | float y = player->position.y; 57 | float z = player->position.z; 58 | 59 | // Translate player position to world position 60 | // Assumption: cube size is always 1.0f! 61 | 62 | Vector3 playerWorldPosition = (Vector3){round(x), round(y), round(z)}; 63 | 64 | DrawText(FormatText("x: %f\ny: %f\nz: %f", playerWorldPosition.x, playerWorldPosition.y, playerWorldPosition.z), 10, 10, 16, WHITE); 65 | 66 | DrawFPS(1920 / 2 - 90, 10); 67 | } 68 | EndDrawing(); 69 | } 70 | 71 | CloseWindow(); 72 | 73 | return 0; 74 | } -------------------------------------------------------------------------------- /src/world/perlin.c: -------------------------------------------------------------------------------- 1 | #include "perlin.h" 2 | 3 | static int SEED = 1337; 4 | 5 | static int hash[] = {208, 34, 231, 213, 32, 248, 233, 56, 161, 78, 24, 140, 71, 48, 140, 254, 245, 255, 247, 247, 40, 6 | 185, 248, 251, 245, 28, 124, 204, 204, 76, 36, 1, 107, 28, 234, 163, 202, 224, 245, 128, 167, 204, 7 | 9, 92, 217, 54, 239, 174, 173, 102, 193, 189, 190, 121, 100, 108, 167, 44, 43, 77, 180, 204, 8, 81, 8 | 70, 223, 11, 38, 24, 254, 210, 210, 177, 32, 81, 195, 243, 125, 8, 169, 112, 32, 97, 53, 195, 13, 9 | 203, 9, 47, 104, 125, 117, 114, 124, 165, 203, 181, 235, 193, 206, 70, 180, 174, 0, 167, 181, 41, 10 | 164, 30, 116, 127, 198, 245, 146, 87, 224, 149, 206, 57, 4, 192, 210, 65, 210, 129, 240, 178, 105, 11 | 228, 108, 245, 148, 140, 40, 35, 195, 38, 58, 65, 207, 215, 253, 65, 85, 208, 76, 62, 3, 237, 55, 89, 12 | 232, 50, 217, 64, 244, 157, 199, 121, 252, 90, 17, 212, 203, 149, 152, 140, 187, 234, 177, 73, 174, 13 | 193, 100, 192, 143, 97, 53, 145, 135, 19, 103, 13, 90, 135, 151, 199, 91, 239, 247, 33, 39, 145, 14 | 101, 120, 99, 3, 186, 86, 99, 41, 237, 203, 111, 79, 220, 135, 158, 42, 30, 154, 120, 67, 87, 167, 15 | 135, 176, 183, 191, 253, 115, 184, 21, 233, 58, 129, 233, 142, 39, 128, 211, 118, 137, 139, 255, 16 | 114, 20, 218, 113, 154, 27, 127, 246, 250, 1, 8, 198, 250, 209, 92, 222, 173, 21, 88, 102, 219}; 17 | 18 | int noise2(int x, int y) 19 | { 20 | int tmp = hash[(y + SEED) % 256]; 21 | return hash[(tmp + x) % 256]; 22 | } 23 | 24 | float lin_inter(float x, float y, float s) 25 | { 26 | return x + s * (y - x); 27 | } 28 | 29 | float smooth_inter(float x, float y, float s) 30 | { 31 | return lin_inter(x, y, s * s * (3 - 2 * s)); 32 | } 33 | 34 | float noise2d(float x, float y) 35 | { 36 | int x_int = x; 37 | int y_int = y; 38 | float x_frac = x - x_int; 39 | float y_frac = y - y_int; 40 | int s = noise2(x_int, y_int); 41 | int t = noise2(x_int + 1, y_int); 42 | int u = noise2(x_int, y_int + 1); 43 | int v = noise2(x_int + 1, y_int + 1); 44 | float low = smooth_inter(s, t, x_frac); 45 | float high = smooth_inter(u, v, x_frac); 46 | return smooth_inter(low, high, y_frac); 47 | } 48 | 49 | float perlin2d(float x, float y, float freq, int depth) 50 | { 51 | float xa = x * freq; 52 | float ya = y * freq; 53 | float amp = 1.0; 54 | float fin = 0; 55 | float div = 0.0; 56 | 57 | int i; 58 | for (i = 0; i < depth; i++) 59 | { 60 | div += 256 * amp; 61 | fin += noise2d(xa, ya) * amp; 62 | amp /= 2; 63 | xa *= 2; 64 | ya *= 2; 65 | } 66 | 67 | return fin / div; 68 | } -------------------------------------------------------------------------------- /src/player.c: -------------------------------------------------------------------------------- 1 | #include "player.h" 2 | #include "raylib.h" 3 | #include "stdlib.h" 4 | #include "math.h" 5 | #include "world/worldgeneration.h" 6 | #include "game_mouse.h" 7 | #include "raymath.h" 8 | #include 9 | 10 | Player *CreatePlayer(Vector3 position) 11 | { 12 | Player *player = RL_MALLOC(sizeof(Player)); 13 | 14 | player->position = position; 15 | player->yaw = 0.0f; 16 | player->size = (Vector3){1.0f, 1.0f, 1.0f}; 17 | player->velocity = (Vector3){0}; 18 | player->friction = 10.0f; 19 | 20 | return player; 21 | } 22 | 23 | static void HandlePlayerMovement(Player *player) 24 | { 25 | player->yaw -= GetMouseMovement().x; 26 | player->velocity = Vector3Zero(); 27 | 28 | if (IsKeyDown(FORWARD_KEY)) 29 | { 30 | player->velocity.x = 3; 31 | } 32 | 33 | if (IsKeyDown(BACKWARD_KEY)) 34 | { 35 | player->velocity.x = -3; 36 | } 37 | 38 | if (IsKeyDown(RIGHT_KEY)) 39 | { 40 | player->velocity.z = 3; 41 | } 42 | 43 | if (IsKeyDown(LEFT_KEY)) 44 | { 45 | player->velocity.z = -3; 46 | } 47 | 48 | player->velocity.y = -3; 49 | } 50 | 51 | static void HandlePlayerWorldCollision(Player *player, int *world) 52 | { 53 | // Get player position 54 | 55 | float x = player->position.x; 56 | float y = player->position.y; 57 | float z = player->position.z; 58 | Vector3 size = player->size; 59 | 60 | // Translate player position to world position 61 | // Assumption: cube size is always 1.0f! 62 | 63 | Vector3 playerWorldPosition = (Vector3){round(x), round(y), round(z)}; 64 | 65 | DrawBoundingBox((BoundingBox){ 66 | (Vector3){playerWorldPosition.x - 0.5f, playerWorldPosition.y - 0.5f, playerWorldPosition.z - 0.5f}, 67 | (Vector3){playerWorldPosition.x + 0.5f, playerWorldPosition.y + 0.5f, playerWorldPosition.z + 0.5f}, 68 | }, 69 | GREEN); 70 | 71 | // Get cubes around player 72 | 73 | BoundingBox cubes[6 * 6 * 6]; 74 | 75 | int iter = 0; 76 | 77 | for (int x = -2; x <= 3; x++) 78 | { 79 | for (int y = -2; y <= 3; y++) 80 | { 81 | for (int z = -2; z <= 3; z++) 82 | { 83 | int cubeX = (int)playerWorldPosition.x + x; 84 | int cubeY = (int)playerWorldPosition.y + y; 85 | int cubeZ = (int)playerWorldPosition.z + z; 86 | int worldCube = GetWorldCube(world, cubeX, cubeY, cubeZ); 87 | if (worldCube == 1) 88 | { 89 | cubes[iter] = (BoundingBox){ 90 | (Vector3){cubeX - 0.5f, cubeY - 0.5f, cubeZ - 0.5f}, 91 | (Vector3){cubeX + 0.5f, cubeY + 0.5f, cubeZ + 0.5f}, 92 | }; 93 | } 94 | else 95 | { 96 | // fixme: How do I express that cube doesn't exist? 97 | cubes[iter] = (BoundingBox){ 98 | (Vector3){0, 0, 0}, 99 | (Vector3){1, 1, 1}, 100 | }; 101 | } 102 | iter++; 103 | } 104 | } 105 | } 106 | 107 | for (int i = 0; i < 6 * 6 * 6; i++) 108 | { 109 | DrawBoundingBox(cubes[i], BLUE); 110 | } 111 | 112 | // Naive: move, if collides, rollback 113 | 114 | float newX = player->position.x - ((player->velocity.x * sinf(player->yaw) - player->velocity.z * cosf(player->yaw)) * GetFrameTime()); 115 | float newY = player->position.y + (player->velocity.y * GetFrameTime()); 116 | float newZ = player->position.z - ((player->velocity.x * cosf(player->yaw) + player->velocity.z * sinf(player->yaw)) * GetFrameTime()); 117 | 118 | player->position.x = newX; 119 | player->position.z = newZ; 120 | 121 | // Translate new player position and size to box 122 | 123 | BoundingBox playerBox = (BoundingBox){ 124 | (Vector3){newX - size.x / 2, newY - size.y / 2, newZ - size.z / 2}, 125 | (Vector3){newX + size.x / 2, newY + size.y / 2, newZ + size.z / 2}}; 126 | 127 | bool isColliding = false; 128 | for (int i = 0; i < 6 * 6 * 6; i++) 129 | { 130 | // fixme: detect that cube doesn't exist 131 | isColliding = CheckCollisionBoxes(playerBox, cubes[i]); 132 | if (isColliding) 133 | { 134 | DrawBoundingBox(cubes[i], PINK); 135 | break; 136 | } 137 | } 138 | 139 | if (!isColliding) 140 | { 141 | player->position.y = newY; 142 | } 143 | 144 | // todo: one axis move, if it collides, rollback, repeat until out of axis 145 | 146 | // Even less naive: instead of rolling back, move to the intersection point 147 | } 148 | 149 | void UpdatePlayer(Player *player, int *world) 150 | { 151 | HandlePlayerMovement(player); 152 | HandlePlayerWorldCollision(player, world); 153 | } -------------------------------------------------------------------------------- /src/world/worldmodel.c: -------------------------------------------------------------------------------- 1 | #include "worldmodel.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include "worldgeneration.h" 7 | 8 | #define MAX_MESH_VBO 7 9 | 10 | static float texcoordsRef[] = { 11 | // face 1 12 | 0.5f, 1.0f, 13 | 0.25f, 1.0f, 14 | 0.25f, 0.0f, 15 | 16 | 0.25f, 0.0f, 17 | 0.5f, 0.0f, 18 | 0.5f, 1.0f, 19 | 20 | 21 | // face 2 22 | 0.25f, 1.0f, 23 | 0.25f, 0.0f, 24 | 0.5f, 0.0f, 25 | 26 | 0.5f, 0.0f, 27 | 0.5f, 1.0f, 28 | 0.25f, 1.0f, 29 | 30 | // face 3 (top) 31 | 0.0f, 0.0f, 32 | 0.25f, 0.0f, 33 | 0.25f, 1.0f, 34 | 35 | 0.25f, 1.0f, 36 | 0.0f, 1.0f, 37 | 0.0f, 0.0f, 38 | 39 | // face 4 (bottom) 40 | 0.0f, 0.0f, 41 | 0.25f, 0.0f, 42 | 0.25f, 1.0f, 43 | 44 | 0.25f, 1.0f, 45 | 0.0f, 1.0f, 46 | 0.0f, 0.0f, 47 | 48 | // face 5 49 | 0.25f, 1.0f, 50 | 0.25f, 0.0f, 51 | 0.5f, 0.0f, 52 | 53 | 0.5f, 0.0f, 54 | 0.5f, 1.0f, 55 | 0.25f, 1.0f, 56 | 57 | // face 6 58 | 0.5f, 1.0f, 59 | 0.25f, 1.0f, 60 | 0.25f, 0.0f, 61 | 62 | 0.25f, 0.0f, 63 | 0.5f, 0.0f, 64 | 0.5f, 1.0f, 65 | }; 66 | 67 | static float normalsRef[] = { 68 | // face 1 69 | 0.0f, 0.0f, 1.0f, 70 | 0.0f, 0.0f, 1.0f, 71 | 0.0f, 0.0f, 1.0f, 72 | 73 | 0.0f, 0.0f, 1.0f, 74 | 0.0f, 0.0f, 1.0f, 75 | 0.0f, 0.0f, 1.0f, 76 | 77 | // face 2 78 | 0.0f, 0.0f, -1.0f, 79 | 0.0f, 0.0f, -1.0f, 80 | 0.0f, 0.0f, -1.0f, 81 | 82 | 0.0f, 0.0f, -1.0f, 83 | 0.0f, 0.0f, -1.0f, 84 | 0.0f, 0.0f, -1.0f, 85 | 86 | // face 3 87 | 0.0f, 1.0f, 0.0f, 88 | 0.0f, 1.0f, 0.0f, 89 | 0.0f, 1.0f, 0.0f, 90 | 91 | 0.0f, 1.0f, 0.0f, 92 | 0.0f, 1.0f, 0.0f, 93 | 0.0f, 1.0f, 0.0f, 94 | 95 | // face 4 96 | 0.0f, -1.0f, 0.0f, 97 | 0.0f, -1.0f, 0.0f, 98 | 0.0f, -1.0f, 0.0f, 99 | 100 | 0.0f, -1.0f, 0.0f, 101 | 0.0f, -1.0f, 0.0f, 102 | 0.0f, -1.0f, 0.0f, 103 | 104 | // face 5 105 | 1.0f, 0.0f, 0.0f, 106 | 1.0f, 0.0f, 0.0f, 107 | 1.0f, 0.0f, 0.0f, 108 | 109 | 1.0f, 0.0f, 0.0f, 110 | 1.0f, 0.0f, 0.0f, 111 | 1.0f, 0.0f, 0.0f, 112 | 113 | // face 6 114 | -1.0f, 0.0f, 0.0f, 115 | -1.0f, 0.0f, 0.0f, 116 | -1.0f, 0.0f, 0.0f, 117 | 118 | -1.0f, 0.0f, 0.0f, 119 | -1.0f, 0.0f, 0.0f, 120 | -1.0f, 0.0f, 0.0f}; 121 | 122 | // note: Yes, the implementation of the world model is dirty. 123 | // todo: reimplement as chunks 124 | 125 | static float *GetCubeVertices(float x, float y, float z) 126 | { 127 | // not using indices 128 | float width = 1.0f; 129 | float height = 1.0f; 130 | float length = 1.0f; 131 | float *cubeVertices = malloc(36 * 3 * sizeof(float)); 132 | float ref[] = { 133 | // face 1 134 | -width / 2 + x, -height / 2 + y, length / 2 + z, 135 | width / 2 + x, -height / 2 + y, length / 2 + z, 136 | width / 2 + x, height / 2 + y, length / 2 + z, 137 | 138 | width / 2 + x, height / 2 + y, length / 2 + z, 139 | -width / 2 + x, height / 2 + y, length / 2 + z, 140 | -width / 2 + x, -height / 2 + y, length / 2 + z, 141 | 142 | // face 2 143 | -width / 2 + x, -height / 2 + y, -length / 2 + z, 144 | -width / 2 + x, height / 2 + y, -length / 2 + z, 145 | width / 2 + x, height / 2 + y, -length / 2 + z, 146 | 147 | width / 2 + x, height / 2 + y, -length / 2 + z, 148 | width / 2 + x, -height / 2 + y, -length / 2 + z, 149 | -width / 2 + x, -height / 2 + y, -length / 2 + z, 150 | 151 | // face 3 152 | -width / 2 + x, height / 2 + y, -length / 2 + z, 153 | -width / 2 + x, height / 2 + y, length / 2 + z, 154 | width / 2 + x, height / 2 + y, length / 2 + z, 155 | 156 | width / 2 + x, height / 2 + y, length / 2 + z, 157 | width / 2 + x, height / 2 + y, -length / 2 + z, 158 | -width / 2 + x, height / 2 + y, -length / 2 + z, 159 | 160 | // face 4 161 | -width / 2 + x, -height / 2 + y, -length / 2 + z, 162 | width / 2 + x, -height / 2 + y, -length / 2 + z, 163 | width / 2 + x, -height / 2 + y, length / 2 + z, 164 | 165 | width / 2 + x, -height / 2 + y, length / 2 + z, 166 | -width / 2 + x, -height / 2 + y, length / 2 + z, 167 | -width / 2 + x, -height / 2 + y, -length / 2 + z, 168 | 169 | // face 5 170 | width / 2 + x, -height / 2 + y, -length / 2 + z, 171 | width / 2 + x, height / 2 + y, -length / 2 + z, 172 | width / 2 + x, height / 2 + y, length / 2 + z, 173 | 174 | width / 2 + x, height / 2 + y, length / 2 + z, 175 | width / 2 + x, -height / 2 + y, length / 2 + z, 176 | width / 2 + x, -height / 2 + y, -length / 2 + z, 177 | 178 | // face 6 179 | -width / 2 + x, -height / 2 + y, -length / 2 + z, 180 | -width / 2 + x, -height / 2 + y, length / 2 + z, 181 | -width / 2 + x, height / 2 + y, length / 2 + z, 182 | 183 | -width / 2 + x, height / 2 + y, length / 2 + z, 184 | -width / 2 + x, height / 2 + y, -length / 2 + z, 185 | -width / 2 + x, -height / 2 + y, -length / 2 + z}; 186 | 187 | for (int i = 0; i < 36 * 3; i++) 188 | { 189 | cubeVertices[i] = ref[i]; 190 | } 191 | 192 | return cubeVertices; 193 | } 194 | 195 | Model GetWorldModel(int *world) 196 | { 197 | Mesh mesh = {0}; 198 | mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int)); 199 | 200 | float *vertices = RL_MALLOC(36 * 3 * WORLD_MAX_X * WORLD_MAX_Y * WORLD_MAX_Z * sizeof(float)); 201 | float *texcoords = RL_MALLOC(36 * 2 * WORLD_MAX_X * WORLD_MAX_Y * WORLD_MAX_Z * sizeof(float)); 202 | float *normals = RL_MALLOC(36 * 3 * WORLD_MAX_X * WORLD_MAX_Y * WORLD_MAX_Z * sizeof(float)); 203 | 204 | int verticesCount = 0; 205 | int texcoordsCount = 0; 206 | int normalsCount = 0; 207 | 208 | for (int x = 0; x < WORLD_MAX_X; x++) 209 | { 210 | for (int y = 0; y < WORLD_MAX_Y; y++) 211 | { 212 | for (int z = 0; z < WORLD_MAX_Z; z++) 213 | { 214 | bool blockExists = GetWorldCube(world, x, y, z) == 1; 215 | if (blockExists) 216 | { 217 | float *blockVertices = GetCubeVertices(x, y, z); 218 | for (int v = 0; v < 36 * 3; v++) 219 | { 220 | vertices[verticesCount + v] = blockVertices[v]; 221 | } 222 | for (int t = 0; t < 36 * 2; t++) 223 | { 224 | texcoords[texcoordsCount + t] = texcoordsRef[t]; 225 | } 226 | for (int n = 0; n < 36 * 3; n++) 227 | { 228 | normals[normalsCount + n] = normalsRef[n]; 229 | } 230 | verticesCount += 36 * 3; 231 | texcoordsCount += 36 * 2; 232 | normalsCount += 36 * 3; 233 | } 234 | } 235 | } 236 | } 237 | 238 | mesh.vertices = (float *)RL_MALLOC(verticesCount * sizeof(float)); 239 | memcpy(mesh.vertices, vertices, verticesCount * sizeof(float)); 240 | 241 | mesh.texcoords = (float *)RL_MALLOC(texcoordsCount * sizeof(float)); 242 | memcpy(mesh.texcoords, texcoords, texcoordsCount * sizeof(float)); 243 | 244 | mesh.normals = (float *)RL_MALLOC(normalsCount * sizeof(float)); 245 | memcpy(mesh.normals, normals, normalsCount * sizeof(float)); 246 | 247 | mesh.vertexCount = verticesCount / 3; // fixme: Why divide by 3 ??? 248 | mesh.triangleCount = (verticesCount / 3) / 2; // fixme: Why divide by 3 and 2 ??? 249 | 250 | RL_FREE(vertices); 251 | RL_FREE(texcoords); 252 | RL_FREE(normals); 253 | 254 | rlLoadMesh(&mesh, false); 255 | 256 | Model worldModel = LoadModelFromMesh(mesh); 257 | 258 | worldModel.materials[0].maps[MAP_DIFFUSE].texture = LoadTexture("resources/grass.png"); 259 | 260 | return worldModel; 261 | } 262 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #************************************************************************************************** 2 | # 3 | # raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5 4 | # 5 | # Copyright (c) 2013-2019 Ramon Santamaria (@raysan5) 6 | # 7 | # This software is provided "as-is", without any express or implied warranty. In no event 8 | # will the authors be held liable for any damages arising from the use of this software. 9 | # 10 | # Permission is granted to anyone to use this software for any purpose, including commercial 11 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 12 | # 13 | # 1. The origin of this software must not be misrepresented; you must not claim that you 14 | # wrote the original software. If you use this software in a product, an acknowledgment 15 | # in the product documentation would be appreciated but is not required. 16 | # 17 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented 18 | # as being the original software. 19 | # 20 | # 3. This notice may not be removed or altered from any source distribution. 21 | # 22 | #************************************************************************************************** 23 | 24 | .PHONY: all clean 25 | 26 | # Define required raylib variables 27 | PROJECT_NAME ?= game 28 | RAYLIB_VERSION ?= 2.5.0 29 | RAYLIB_API_VERSION ?= 251 30 | RAYLIB_PATH ?= ..\.. 31 | 32 | # Define compiler path on Windows 33 | COMPILER_PATH ?= C:/raylib/mingw/bin 34 | 35 | # Define default options 36 | # One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB 37 | PLATFORM ?= PLATFORM_DESKTOP 38 | 39 | # Locations of your newly installed library and associated headers. See ../src/Makefile 40 | # On Linux, if you have installed raylib but cannot compile the examples, check that 41 | # the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. 42 | # To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. 43 | # To enable compile-time linking to a special version of libraylib.so, change these variables here. 44 | # To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. 45 | # If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, 46 | # the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. 47 | # RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. 48 | DESTDIR ?= /usr/local 49 | RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib 50 | # RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. 51 | RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include 52 | 53 | # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) 54 | RAYLIB_LIBTYPE ?= STATIC 55 | 56 | # Build mode for project: DEBUG or RELEASE 57 | BUILD_MODE ?= RELEASE 58 | 59 | # Use external GLFW library instead of rglfw module 60 | # TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 61 | USE_EXTERNAL_GLFW ?= FALSE 62 | 63 | # Use Wayland display server protocol on Linux desktop 64 | # by default it uses X11 windowing system 65 | USE_WAYLAND_DISPLAY ?= FALSE 66 | 67 | # Determine PLATFORM_OS in case PLATFORM_DESKTOP selected 68 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 69 | # No uname.exe on MinGW!, but OS=Windows_NT on Windows! 70 | # ifeq ($(UNAME),Msys) -> Windows 71 | ifeq ($(OS),Windows_NT) 72 | PLATFORM_OS=WINDOWS 73 | export PATH := $(COMPILER_PATH):$(PATH) 74 | else 75 | UNAMEOS=$(shell uname) 76 | ifeq ($(UNAMEOS),Linux) 77 | PLATFORM_OS=LINUX 78 | endif 79 | ifeq ($(UNAMEOS),FreeBSD) 80 | PLATFORM_OS=BSD 81 | endif 82 | ifeq ($(UNAMEOS),OpenBSD) 83 | PLATFORM_OS=BSD 84 | endif 85 | ifeq ($(UNAMEOS),NetBSD) 86 | PLATFORM_OS=BSD 87 | endif 88 | ifeq ($(UNAMEOS),DragonFly) 89 | PLATFORM_OS=BSD 90 | endif 91 | ifeq ($(UNAMEOS),Darwin) 92 | PLATFORM_OS=OSX 93 | endif 94 | endif 95 | endif 96 | ifeq ($(PLATFORM),PLATFORM_RPI) 97 | UNAMEOS=$(shell uname) 98 | ifeq ($(UNAMEOS),Linux) 99 | PLATFORM_OS=LINUX 100 | endif 101 | endif 102 | 103 | # RAYLIB_PATH adjustment for different platforms. 104 | # If using GNU make, we can get the full path to the top of the tree. Windows? BSD? 105 | # Required for ldconfig or other tools that do not perform path expansion. 106 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 107 | ifeq ($(PLATFORM_OS),LINUX) 108 | RAYLIB_PREFIX ?= .. 109 | RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) 110 | endif 111 | endif 112 | # Default path for raylib on Raspberry Pi, if installed in different path, update it! 113 | # This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. 114 | # TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. 115 | ifeq ($(PLATFORM),PLATFORM_RPI) 116 | RAYLIB_PATH ?= /home/pi/raylib 117 | endif 118 | 119 | ifeq ($(PLATFORM),PLATFORM_WEB) 120 | # Emscripten required variables 121 | EMSDK_PATH ?= C:/emsdk 122 | EMSCRIPTEN_VERSION ?= 1.38.31 123 | CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit 124 | PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64 125 | NODE_VERSION = 8.9.1_64bit 126 | export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH) 127 | EMSCRIPTEN = $(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION) 128 | endif 129 | 130 | # Define raylib release directory for compiled library. 131 | # RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version 132 | RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src 133 | 134 | # EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries 135 | # into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH 136 | # so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux 137 | # without formal installation from ../src/Makefile. It aids portability and is useful if you have 138 | # multiple versions of raylib, have raylib installed to a non-standard location, or want to 139 | # bundle libraylib.so with your game. Change it to your liking. 140 | # NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, 141 | # The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, 142 | # Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) 143 | # To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. 144 | # To see which libraries a built example is linking to, ldd core/core_basic_window; 145 | # Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. 146 | EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) 147 | 148 | # Define default C compiler: gcc 149 | # NOTE: define g++ compiler if using C++ 150 | CC = gcc 151 | 152 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 153 | ifeq ($(PLATFORM_OS),OSX) 154 | # OSX default compiler 155 | CC = clang 156 | endif 157 | ifeq ($(PLATFORM_OS),BSD) 158 | # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler 159 | CC = clang 160 | endif 161 | endif 162 | ifeq ($(PLATFORM),PLATFORM_RPI) 163 | ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) 164 | # Define RPI cross-compiler 165 | #CC = armv6j-hardfloat-linux-gnueabi-gcc 166 | CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc 167 | endif 168 | endif 169 | ifeq ($(PLATFORM),PLATFORM_WEB) 170 | # HTML5 emscripten compiler 171 | # WARNING: To compile to HTML5, code must be redesigned 172 | # to use emscripten.h and emscripten_set_main_loop() 173 | CC = emcc 174 | endif 175 | 176 | # Define default make program: Mingw32-make 177 | MAKE = mingw32-make 178 | 179 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 180 | ifeq ($(PLATFORM_OS),LINUX) 181 | MAKE = make 182 | endif 183 | endif 184 | 185 | # Define compiler flags: 186 | # -O0 defines optimization level (no optimization, better for debugging) 187 | # -O1 defines optimization level 188 | # -g include debug information on compilation 189 | # -s strip unnecessary data from build -> do not use in debug builds 190 | # -Wall turns on most, but not all, compiler warnings 191 | # -std=c99 defines C language mode (standard C from 1999 revision) 192 | # -std=gnu99 defines C language mode (GNU C from 1999 revision) 193 | # -Wno-missing-braces ignore invalid warning (GCC bug 53119) 194 | # -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec 195 | CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces 196 | 197 | ifeq ($(BUILD_MODE),DEBUG) 198 | CFLAGS += -g -O0 199 | else 200 | CFLAGS += -s -O1 201 | endif 202 | 203 | # Additional flags for compiler (if desired) 204 | #CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes 205 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 206 | ifeq ($(PLATFORM_OS),WINDOWS) 207 | # resource file contains windows executable icon and properties 208 | # -Wl,--subsystem,windows hides the console window 209 | CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows 210 | endif 211 | ifeq ($(PLATFORM_OS),LINUX) 212 | ifeq ($(RAYLIB_LIBTYPE),STATIC) 213 | CFLAGS += -D_DEFAULT_SOURCE 214 | endif 215 | ifeq ($(RAYLIB_LIBTYPE),SHARED) 216 | # Explicitly enable runtime link to libraylib.so 217 | CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) 218 | endif 219 | endif 220 | endif 221 | ifeq ($(PLATFORM),PLATFORM_RPI) 222 | CFLAGS += -std=gnu99 223 | endif 224 | ifeq ($(PLATFORM),PLATFORM_WEB) 225 | # -Os # size optimization 226 | # -O2 # optimization level 2, if used, also set --memory-init-file 0 227 | # -s USE_GLFW=3 # Use glfw3 library (context/input management) 228 | # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! 229 | # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) 230 | # -s USE_PTHREADS=1 # multithreading support 231 | # -s WASM=0 # disable Web Assembly, emitted by default 232 | # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow) 233 | # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter 234 | # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data 235 | # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) 236 | # --profiling # include information for code profiling 237 | # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) 238 | # --preload-file resources # specify a resources folder for data compilation 239 | CFLAGS += -Os -s USE_GLFW=3 -s TOTAL_MEMORY=16777216 --preload-file resources 240 | ifeq ($(BUILD_MODE), DEBUG) 241 | CFLAGS += -s ASSERTIONS=1 --profiling 242 | endif 243 | 244 | # Define a custom shell .html and output extension 245 | CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html 246 | EXT = .html 247 | endif 248 | 249 | # Define include paths for required headers 250 | # NOTE: Several external required libraries (stb and others) 251 | INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external 252 | 253 | # Define additional directories containing required header files 254 | ifeq ($(PLATFORM),PLATFORM_RPI) 255 | # RPI required libraries 256 | INCLUDE_PATHS += -I/opt/vc/include 257 | INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux 258 | INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads 259 | endif 260 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 261 | ifeq ($(PLATFORM_OS),BSD) 262 | # Consider -L$(RAYLIB_H_INSTALL_PATH) 263 | INCLUDE_PATHS += -I/usr/local/include 264 | endif 265 | ifeq ($(PLATFORM_OS),LINUX) 266 | # Reset everything. 267 | # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include 268 | INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external 269 | endif 270 | endif 271 | 272 | # Define library paths containing required libs. 273 | LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src 274 | 275 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 276 | ifeq ($(PLATFORM_OS),BSD) 277 | # Consider -L$(RAYLIB_INSTALL_PATH) 278 | LDFLAGS += -L. -Lsrc -L/usr/local/lib 279 | endif 280 | ifeq ($(PLATFORM_OS),LINUX) 281 | # Reset everything. 282 | # Precedence: immediately local, installed version, raysan5 provided libs 283 | LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) 284 | endif 285 | endif 286 | 287 | ifeq ($(PLATFORM),PLATFORM_RPI) 288 | LDFLAGS += -L/opt/vc/lib 289 | endif 290 | 291 | # Define any libraries required on linking 292 | # if you want to link libraries (libname.so or libname.a), use the -lname 293 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 294 | ifeq ($(PLATFORM_OS),WINDOWS) 295 | # Libraries for Windows desktop compilation 296 | # NOTE: WinMM library required to set high-res timer resolution 297 | LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm 298 | # Required for physac examples 299 | #LDLIBS += -static -lpthread 300 | endif 301 | ifeq ($(PLATFORM_OS),LINUX) 302 | # Libraries for Debian GNU/Linux desktop compiling 303 | # NOTE: Required packages: libegl1-mesa-dev 304 | LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt 305 | 306 | # On X11 requires also below libraries 307 | LDLIBS += -lX11 308 | # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them 309 | #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor 310 | 311 | # On Wayland windowing system, additional libraries requires 312 | ifeq ($(USE_WAYLAND_DISPLAY),TRUE) 313 | LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon 314 | endif 315 | # Explicit link to libc 316 | ifeq ($(RAYLIB_LIBTYPE),SHARED) 317 | LDLIBS += -lc 318 | endif 319 | endif 320 | ifeq ($(PLATFORM_OS),OSX) 321 | # Libraries for OSX 10.9 desktop compiling 322 | # NOTE: Required packages: libopenal-dev libegl1-mesa-dev 323 | LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa 324 | endif 325 | ifeq ($(PLATFORM_OS),BSD) 326 | # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling 327 | # NOTE: Required packages: mesa-libs 328 | LDLIBS = -lraylib -lGL -lpthread -lm 329 | 330 | # On XWindow requires also below libraries 331 | LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor 332 | endif 333 | ifeq ($(USE_EXTERNAL_GLFW),TRUE) 334 | # NOTE: It could require additional packages installed: libglfw3-dev 335 | LDLIBS += -lglfw 336 | endif 337 | endif 338 | ifeq ($(PLATFORM),PLATFORM_RPI) 339 | # Libraries for Raspberry Pi compiling 340 | # NOTE: Required packages: libasound2-dev (ALSA) 341 | LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl 342 | endif 343 | ifeq ($(PLATFORM),PLATFORM_WEB) 344 | # Libraries for web (HTML5) compiling 345 | LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc 346 | endif 347 | 348 | # Define a recursive wildcard function 349 | rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) 350 | 351 | # Define all source files required 352 | SRC_DIR = src 353 | OBJ_DIR = obj 354 | 355 | # Define all object files from source files 356 | SRC = $(call rwildcard, *.c, *.h) 357 | #OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) 358 | OBJS = $(call rwildcard, src,*.c) 359 | 360 | # For Android platform we call a custom Makefile.Android 361 | ifeq ($(PLATFORM),PLATFORM_ANDROID) 362 | MAKEFILE_PARAMS = -f Makefile.Android 363 | export PROJECT_NAME 364 | export SRC_DIR 365 | else 366 | MAKEFILE_PARAMS = $(PROJECT_NAME) 367 | endif 368 | 369 | # Default target entry 370 | # NOTE: We call this Makefile target or Makefile.Android target 371 | all: 372 | $(MAKE) $(MAKEFILE_PARAMS) 373 | 374 | # Project target defined by PROJECT_NAME 375 | $(PROJECT_NAME): $(OBJS) 376 | $(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) 377 | 378 | # Compile source files 379 | # NOTE: This pattern will compile every module defined on $(OBJS) 380 | #%.o: %.c 381 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c 382 | $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) 383 | 384 | # Clean everything 385 | clean: 386 | ifeq ($(PLATFORM),PLATFORM_DESKTOP) 387 | ifeq ($(PLATFORM_OS),WINDOWS) 388 | del *.o *.exe /s 389 | endif 390 | ifeq ($(PLATFORM_OS),LINUX) 391 | find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv 392 | endif 393 | ifeq ($(PLATFORM_OS),OSX) 394 | find . -type f -perm +ugo+x -delete 395 | rm -f *.o 396 | endif 397 | endif 398 | ifeq ($(PLATFORM),PLATFORM_RPI) 399 | find . -type f -executable -delete 400 | rm -fv *.o 401 | endif 402 | ifeq ($(PLATFORM),PLATFORM_WEB) 403 | del *.o *.html *.js 404 | endif 405 | @echo Cleaning done 406 | 407 | -------------------------------------------------------------------------------- /Makefile.Android: -------------------------------------------------------------------------------- 1 | #************************************************************************************************** 2 | # 3 | # raylib makefile for Android project (APK building) 4 | # 5 | # Copyright (c) 2017 Ramon Santamaria (@raysan5) 6 | # 7 | # This software is provided "as-is", without any express or implied warranty. In no event 8 | # will the authors be held liable for any damages arising from the use of this software. 9 | # 10 | # Permission is granted to anyone to use this software for any purpose, including commercial 11 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 12 | # 13 | # 1. The origin of this software must not be misrepresented; you must not claim that you 14 | # wrote the original software. If you use this software in a product, an acknowledgment 15 | # in the product documentation would be appreciated but is not required. 16 | # 17 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented 18 | # as being the original software. 19 | # 20 | # 3. This notice may not be removed or altered from any source distribution. 21 | # 22 | #************************************************************************************************** 23 | 24 | # Define required raylib variables 25 | PLATFORM ?= PLATFORM_ANDROID 26 | RAYLIB_PATH ?= ..\.. 27 | 28 | # Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version 29 | ANDROID_ARCH ?= ARM 30 | ANDROID_API_VERSION = 21 31 | ifeq ($(ANDROID_ARCH),ARM) 32 | ANDROID_ARCH_NAME = armeabi-v7a 33 | endif 34 | ifeq ($(ANDROID_ARCH),ARM64) 35 | ANDROID_ARCH_NAME = arm64-v8a 36 | endif 37 | 38 | # Required path variables 39 | # NOTE: JAVA_HOME must be set to JDK 40 | JAVA_HOME ?= C:/JavaJDK 41 | ANDROID_HOME = C:/android-sdk 42 | ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) 43 | ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 44 | ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools 45 | 46 | # Android project configuration variables 47 | PROJECT_NAME ?= raylib_game 48 | PROJECT_LIBRARY_NAME ?= main 49 | PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) 50 | PROJECT_RESOURCES_PATH ?= resources 51 | PROJECT_SOURCE_FILES ?= raylib_game.c 52 | 53 | # Some source files are placed in directories, when compiling to some 54 | # output directory other than source, that directory must pre-exist. 55 | # Here we get a list of required folders that need to be created on 56 | # code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors. 57 | PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES))) 58 | 59 | # Android app configuration variables 60 | APP_LABEL_NAME ?= rGame 61 | APP_COMPANY_NAME ?= raylib 62 | APP_PRODUCT_NAME ?= rgame 63 | APP_VERSION_CODE ?= 1 64 | APP_VERSION_NAME ?= 1.0 65 | APP_ICON_LDPI ?= $(RAYLIB_PATH)\logo\raylib_36x36.png 66 | APP_ICON_MDPI ?= $(RAYLIB_PATH)\logo\raylib_48x48.png 67 | APP_ICON_HDPI ?= $(RAYLIB_PATH)\logo\raylib_72x72.png 68 | APP_SCREEN_ORIENTATION ?= landscape 69 | APP_KEYSTORE_PASS ?= raylib 70 | 71 | # Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) 72 | RAYLIB_LIBTYPE ?= STATIC 73 | 74 | # Library path for libraylib.a/libraylib.so 75 | RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src 76 | 77 | # Shared libs must be added to APK if required 78 | # NOTE: Generated NativeLoader.java automatically load those libraries 79 | ifeq ($(RAYLIB_LIBTYPE),SHARED) 80 | PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so 81 | endif 82 | 83 | # Compiler and archiver 84 | # NOTE: GCC is being deprecated in Android NDK r16 85 | ifeq ($(ANDROID_ARCH),ARM) 86 | CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang 87 | AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar 88 | endif 89 | ifeq ($(ANDROID_ARCH),ARM64) 90 | CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang 91 | AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar 92 | endif 93 | 94 | # Compiler flags for arquitecture 95 | ifeq ($(ANDROID_ARCH),ARM) 96 | CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 97 | endif 98 | ifeq ($(ANDROID_ARCH),ARM64) 99 | CFLAGS = -std=c99 -target aarch64 -mfix-cortex-a53-835769 100 | endif 101 | # Compilation functions attributes options 102 | CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC 103 | # Compiler options for the linker 104 | CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes 105 | # Preprocessor macro definitions 106 | CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) 107 | 108 | # Paths containing required header files 109 | INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue 110 | 111 | # Linker options 112 | LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a 113 | LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings 114 | # Force linking of library module to define symbol 115 | LDFLAGS += -u ANativeActivity_onCreate 116 | # Library paths containing required libs 117 | LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib 118 | 119 | # Define any libraries to link into executable 120 | # if you want to link libraries (libname.so or libname.a), use the -lname 121 | LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl 122 | 123 | # Generate target objects list from PROJECT_SOURCE_FILES 124 | OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) 125 | 126 | # Android APK building process... some steps required... 127 | # NOTE: typing 'make' will invoke the default target entry called 'all', 128 | all: create_temp_project_dirs \ 129 | copy_project_required_libs \ 130 | copy_project_resources \ 131 | generate_loader_script \ 132 | generate_android_manifest \ 133 | generate_apk_keystore \ 134 | config_project_package \ 135 | compile_project_code \ 136 | compile_project_class \ 137 | compile_project_class_dex \ 138 | create_project_apk_package \ 139 | sign_project_apk_package \ 140 | zipalign_project_apk_package 141 | 142 | # Create required temp directories for APK building 143 | create_temp_project_dirs: 144 | if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH) 145 | if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj 146 | if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src 147 | if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com 148 | if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) 149 | if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) 150 | if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib 151 | if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) 152 | if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin 153 | if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res 154 | if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi 155 | if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi 156 | if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi 157 | if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values 158 | if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets 159 | if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) 160 | if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens 161 | $(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir))) 162 | 163 | define create_dir 164 | if not exist $(PROJECT_BUILD_PATH)\obj\$(1) mkdir $(PROJECT_BUILD_PATH)\obj\$(1) 165 | endef 166 | 167 | # Copy required shared libs for integration into APK 168 | # NOTE: If using shared libs they are loaded by generated NativeLoader.java 169 | copy_project_required_libs: 170 | ifeq ($(RAYLIB_LIBTYPE),SHARED) 171 | copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so 172 | endif 173 | ifeq ($(RAYLIB_LIBTYPE),STATIC) 174 | copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a 175 | endif 176 | 177 | # Copy project required resources: strings.xml, icon.png, assets 178 | # NOTE: Required strings.xml is generated and game resources are copied to assets folder 179 | # TODO: Review xcopy usage, it can not be found in some systems! 180 | copy_project_resources: 181 | copy $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)\res\drawable-ldpi\icon.png /Y 182 | copy $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)\res\drawable-mdpi\icon.png /Y 183 | copy $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)\res\drawable-hdpi\icon.png /Y 184 | @echo ^ > $(PROJECT_BUILD_PATH)/res/values/strings.xml 185 | @echo ^^$(APP_LABEL_NAME)^^ >> $(PROJECT_BUILD_PATH)/res/values/strings.xml 186 | if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F 187 | 188 | # Generate NativeLoader.java to load required shared libraries 189 | # NOTE: Probably not the bet way to generate this file... but it works. 190 | generate_loader_script: 191 | @echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 192 | @echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 193 | @echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 194 | @echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 195 | ifeq ($(RAYLIB_LIBTYPE),SHARED) 196 | @echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 197 | endif 198 | @echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 199 | @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 200 | @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 201 | 202 | # Generate AndroidManifest.xml with all the required options 203 | # NOTE: Probably not the bet way to generate this file... but it works. 204 | generate_android_manifest: 205 | @echo ^ > $(PROJECT_BUILD_PATH)/AndroidManifest.xml 206 | @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 207 | @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 208 | @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 209 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 210 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 211 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 212 | @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 213 | @echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 214 | @echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 215 | @echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 216 | @echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 217 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 218 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 219 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 220 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 221 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 222 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 223 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 224 | @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml 225 | 226 | # Generate storekey for APK signing: $(PROJECT_NAME).keystore 227 | # NOTE: Configure here your Distinguished Names (-dname) if required! 228 | generate_apk_keystore: 229 | if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA 230 | 231 | # Config project package and resource using AndroidManifest.xml and res/values/strings.xml 232 | # NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java 233 | config_project_package: 234 | $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar 235 | 236 | # Compile native_app_glue code as static library: obj/libnative_app_glue.a 237 | compile_native_app_glue: 238 | $(CC) -c $(RAYLIB_PATH)/src/external/android/native_app_glue/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS) 239 | $(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o 240 | 241 | # Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so 242 | compile_project_code: $(OBJS) 243 | $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) 244 | 245 | # Compile all .c files required into object (.o) files 246 | # NOTE: Those files will be linked into a shared library 247 | $(PROJECT_BUILD_PATH)/obj/%.o:%.c 248 | $(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot 249 | 250 | # Compile project .java code into .class (Java bytecode) 251 | compile_project_class: 252 | $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java 253 | 254 | # Compile .class files into Dalvik executable bytecode (.dex) 255 | # NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) 256 | compile_project_class_dex: 257 | $(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj 258 | 259 | # Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk 260 | # NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so 261 | # NOTE: Use -A resources to define additional directory in which to find raw asset files 262 | create_project_apk_package: 263 | $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin 264 | cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) 265 | 266 | # Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk 267 | sign_project_apk_package: 268 | $(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key 269 | 270 | # Create zip-aligned APK package: $(PROJECT_NAME).apk 271 | zipalign_project_apk_package: 272 | $(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk 273 | 274 | # Install $(PROJECT_NAME).apk to default emulator/device 275 | # NOTE: Use -e (emulator) or -d (device) parameters if required 276 | install: 277 | $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk 278 | 279 | # Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) 280 | check_device_abi: 281 | $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi 282 | 283 | # Monitorize output log coming from device, only raylib tag 284 | logcat: 285 | $(ANDROID_PLATFORM_TOOLS)/adb logcat -c 286 | $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S 287 | 288 | # Install and monitorize $(PROJECT_NAME).apk to default emulator/device 289 | deploy: 290 | $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk 291 | $(ANDROID_PLATFORM_TOOLS)/adb logcat -c 292 | $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S 293 | 294 | #$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W 295 | 296 | # Clean everything 297 | clean: 298 | del $(PROJECT_BUILD_PATH)\* /f /s /q 299 | rmdir $(PROJECT_BUILD_PATH) /s /q 300 | @echo Cleaning done 301 | --------------------------------------------------------------------------------