Initial commit

This commit is contained in:
2025-12-11 07:09:08 -06:00
committed by GitHub
commit 9a78a8706d
9 changed files with 448 additions and 0 deletions

2
.clangd Normal file
View File

@@ -0,0 +1,2 @@
CompileFlags:
CompilationDatabase: "./build"

View File

@@ -0,0 +1,151 @@
name: CMake on multiple platforms
on:
push:
tags:
- "v*"
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
c_compiler: cl
cpp_compiler: cl
platform: Windows
artifact_name: windows
build_type: Release
- os: ubuntu-latest
c_compiler: gcc
cpp_compiler: g++
platform: Linux
artifact_name: linux
build_type: Release
- os: macos-latest
c_compiler: clang
cpp_compiler: clang++
platform: MacOS
artifact_name: macos
build_type: Release
- os: ubuntu-latest
c_compiler: emcc
cpp_compiler: em++
platform: Web
artifact_name: web
build_type: Release
steps:
- uses: actions/checkout@v4
- name: Set reusable strings
id: strings
shell: bash
run: |
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
- name: Install Linux Dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y libasound2-dev mesa-common-dev libx11-dev libxrandr-dev libxi-dev xorg-dev libgl1-mesa-dev libglu1-mesa-dev vim-common
- name: Install MacOS Dependencies
if: runner.os == 'macOS'
run: |
brew install cmake
xcode-select --install || true
- name: Install Windows Dependencies
if: runner.os == 'Windows'
run: choco install vim -y
shell: pwsh
- name: Cache CMake files
uses: actions/cache@v4
with:
path: |
~/.cmake
${{ github.workspace }}/build/_deps
key: ${{ runner.os }}-cmake-${{ matrix.c_compiler }}-${{ hashFiles('**/CMakeLists.txt', '**/*.cmake') }}
restore-keys: |
${{ runner.os }}-cmake-${{ matrix.c_compiler }}-
${{ runner.os }}-cmake-
- name: Setup Emscripten
if: matrix.c_compiler == 'emcc'
uses: mymindstorm/setup-emsdk@v14
with:
version: latest
- name: Setup Web Build Environment
if: matrix.c_compiler == 'emcc'
run: |
mkdir -p ${{ steps.strings.outputs.build-output-dir }}/assets
# cp -r assets/* ${{ steps.strings.outputs.build-output-dir }}/assets/
- name: Configure CMake
run: >
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
${{ matrix.c_compiler == 'emcc' && '-DPLATFORM=Web' || '' }}
-S ${{ github.workspace }}
- name: Build
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
- name: Test
working-directory: ${{ steps.strings.outputs.build-output-dir }}
run: ctest --build-config ${{ matrix.build_type }}
- name: Create Release ZIP (Windows)
if: matrix.platform == 'Windows'
run: |
cd build/${{ matrix.build_type }}
Compress-Archive -Path *.exe -DestinationPath ../../${{ matrix.artifact_name }}.zip
shell: pwsh
- name: Create Release ZIP (Web)
if: matrix.platform == 'Web'
run: |
cd build
zip -r ../${{ matrix.artifact_name }}.zip *.html *.js *.data *.wasm 2>/dev/null || true
shell: bash
- name: Create Release ZIP (Linux/macOS)
if: matrix.platform == 'Linux' || matrix.platform == 'MacOS'
run: |
mkdir -p release_files
cd build
# Copy executable files (excluding libraries and build artifacts)
for file in *; do
if [ -f "$file" ] && [ -x "$file" ]; then
case "$file" in
*.so|*.a|*.dylib|*.sh) ;;
*) cp "$file" ../release_files/ ;;
esac
fi
done
cd ../release_files
if [ -n "$(ls -A 2>/dev/null)" ]; then
zip ../${{ matrix.artifact_name }}.zip *
fi
shell: bash
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}
path: ${{ matrix.artifact_name }}.zip

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
build/*
build-web/*
data/*
.cache/*

105
CMakeLists.txt Normal file
View File

@@ -0,0 +1,105 @@
cmake_minimum_required(VERSION 3.11) # FetchContent is available in 3.11+
project(game C CXX)
# Generate compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Dependencies
set(RAYLIB_VERSION 5.5)
find_package(raylib ${RAYLIB_VERSION} QUIET) # QUIET or REQUIRED
if(NOT raylib_FOUND) # If there's none, fetch and build raylib
include(FetchContent)
FetchContent_Declare(
raylib
DOWNLOAD_EXTRACT_TIMESTAMP OFF
URL https://github.com/raysan5/raylib/archive/refs/tags/${RAYLIB_VERSION}.tar.gz
)
FetchContent_GetProperties(raylib)
if(NOT raylib_POPULATED) # Have we downloaded raylib yet?
set(FETCHCONTENT_QUIET NO)
FetchContent_MakeAvailable(raylib)
endif()
endif()
set(RAYLIB_CPP_VERSION "v5.5.0")
find_package(raylib_cpp QUIET) # QUIET or REQUIRED
if(NOT raylib_cpp_FOUND) # If there's none, fetch and build raylib
include(FetchContent)
FetchContent_Declare(
raylib_cpp
DOWNLOAD_EXTRACT_TIMESTAMP OFF
URL https://github.com/RobLoach/raylib-cpp/archive/refs/tags/${RAYLIB_CPP_VERSION}.tar.gz
)
FetchContent_GetProperties(raylib_cpp)
if(NOT raylib_cpp_POPULATED) # Have we downloaded raylib yet?
set(FETCHCONTENT_QUIET NO)
FetchContent_MakeAvailable(raylib_cpp)
endif()
endif()
# Our Project
add_executable(${PROJECT_NAME})
# Generate header files from assets using xxd
file(GLOB_RECURSE ASSET_FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/*)
set(DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
set(GENERATED_HEADERS "")
foreach(ASSET_FILE ${ASSET_FILES})
file(RELATIVE_PATH REL_PATH
${CMAKE_CURRENT_SOURCE_DIR}/assets
${ASSET_FILE}
)
get_filename_component(FILE_NAME ${ASSET_FILE} NAME)
get_filename_component(SUB_DIR ${REL_PATH} DIRECTORY)
set(OUTPUT_DIR ${DATA_DIR}/${SUB_DIR})
file(MAKE_DIRECTORY ${OUTPUT_DIR})
set(OUTPUT_FILE ${OUTPUT_DIR}/${FILE_NAME}.h)
get_filename_component(ASSET_DIR ${ASSET_FILE} DIRECTORY)
add_custom_command(
OUTPUT ${OUTPUT_FILE}
COMMAND xxd -i ${FILE_NAME} ${OUTPUT_FILE}
DEPENDS ${ASSET_FILE}
WORKING_DIRECTORY ${ASSET_DIR}
COMMENT "Embedding ${REL_PATH}"
VERBATIM
)
list(APPEND GENERATED_HEADERS ${OUTPUT_FILE})
endforeach()
# Add source files
file(GLOB_RECURSE PROJECTSOURCES "src/*.c" "src/*.cpp")
target_sources(${PROJECT_NAME} PRIVATE ${PROJECTSOURCES})
# Add generated headers
target_sources(${PROJECT_NAME} PRIVATE ${GENERATED_HEADERS})
# Include directories
target_include_directories(${PROJECT_NAME} PRIVATE
${DATA_DIR}
${raylib_INCLUDE_DIRS}
${raylib_cpp_INCLUDE_DIRS}
)
# Link libraries
target_link_libraries(${PROJECT_NAME} raylib raylib_cpp)
# Web Configurations
if(${PLATFORM} STREQUAL "Web")
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY -s GL_ENABLE_GET_PROC_ADDRESS=1 -s SINGLE_FILE=1 --shell-file ${CMAKE_SOURCE_DIR}/src/minshell.html")
endif()
# macOS frameworks
if(APPLE)
target_link_libraries(${PROJECT_NAME} "-framework IOKit")
target_link_libraries(${PROJECT_NAME} "-framework Cocoa")
target_link_libraries(${PROJECT_NAME} "-framework OpenGL")
endif()

16
LICENSE Normal file
View File

@@ -0,0 +1,16 @@
Copyright (c) 2013-2023 Ramon Santamaria (@raysan5)
This software is provided "as-is", without any express or implied warranty. In no event
will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial
applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you
wrote the original software. If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented
as being the original software.
3. This notice may not be removed or altered from any source distribution.

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# RaylibGame
A template for making games with Raylib-CPP

BIN
assets/cube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

95
src/main.cpp Normal file
View File

@@ -0,0 +1,95 @@
#include "../data/cube.png.h"
#include "raylib.h"
#include <cmath>
#include <raylib-cpp.hpp>
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#endif
#define SCREEN_WIDTH (320)
#define SCREEN_HEIGHT (240)
#define WIN_WIDTH (1280)
#define WIN_HEIGHT (720)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
void MainLoop();
raylib::Window window(WIN_WIDTH, WIN_HEIGHT, "game",
FLAG_WINDOW_RESIZABLE | FLAG_VSYNC_HINT);
raylib::RenderTexture2D target(SCREEN_WIDTH, SCREEN_HEIGHT);
raylib::Image texImg =
raylib::LoadImageFromMemory(".png", cube_png, cube_png_len);
raylib::Texture2D texture = texImg.LoadTexture();
raylib::Camera3D cam(raylib::Vector3(0.0f, 0.0f, std::sqrt(3.0f)),
raylib::Vector3::Zero(), raylib::Vector3(0.0f, 1.0f, 0.0f),
60.0f, CAMERA_PERSPECTIVE);
raylib::Model cube(GenMeshCube(1.0f, 1.0f, 1.0f));
int main(void) {
window.SetMinSize({320, 240});
window.SetTargetFPS(60);
window.SetExitKey(KEY_BACKSPACE);
target.GetTexture().SetFilter(TEXTURE_FILTER_POINT);
cube.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = texture;
#if defined(PLATFORM_WEB)
emscripten_set_main_loop(MainLoop, 0, 1);
#else
while (!window.ShouldClose() && !raylib::Keyboard::IsKeyDown(KEY_ESCAPE))
MainLoop();
#endif
window.Close();
return 0;
}
void MainLoop() {
{
int winWidth = GetScreenWidth(), winHeight = GetScreenHeight();
float scale =
MIN((float)winWidth / SCREEN_WIDTH, (float)winHeight / SCREEN_HEIGHT);
cube.SetTransform(
raylib::Matrix::RotateXYZ(
raylib::Vector3(1.0f, 1.5f, 2.5f).Scale(window.GetFrameTime()))
.Multiply(cube.GetTransform()));
target.BeginMode();
{
ClearBackground(BLACK);
raylib::Vector2(160.0f, 120.0f)
.DrawCircle(120.0f, raylib::Color::White());
cam.BeginMode();
{
cube.Draw(raylib::Vector3::Zero());
}
cam.EndMode();
}
target.EndMode();
window.BeginDrawing();
{
ClearBackground(BLACK);
target.GetTexture().Draw(
raylib::Rectangle(0.0f, 0.0f, (float)SCREEN_WIDTH,
(float)-SCREEN_HEIGHT),
raylib::Rectangle((winWidth - ((float)SCREEN_WIDTH * scale)) * 0.5f,
(winHeight - ((float)SCREEN_HEIGHT * scale)) * 0.5f,
(float)SCREEN_WIDTH * scale,
(float)SCREEN_HEIGHT * scale),
raylib::Vector2(0, 0), 0.0f, WHITE);
}
window.EndDrawing();
}
}

72
src/minshell.html Normal file
View File

@@ -0,0 +1,72 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
body {
margin: 0px;
overflow: hidden;
background-color: black;
}
canvas.emscripten {
border: 0px none;
background-color: black;
padding-left: 0;
padding-right: 0;
margin-left: auto;
margin-right: auto;
display: block;
}
</style>
<script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script>
<script type='text/javascript'>
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
{
var isSafari = false; // Not supported, navigator.userAgent access is being restricted
//var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
var data = FS.readFile(memoryFSname);
var blob;
if (isSafari) blob = new Blob([data.buffer], {type: "application/octet-stream"});
else blob = new Blob([data.buffer], {type: "application/octet-binary"});
// NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome,
// in Settings/Advanced/Downloads section you have a setting:
// 'Ask where to save each file before downloading' - which you can set true/false.
// If you enable this setting it would always ask you and bring the SaveAsDialog
saveAs(blob, localFSname);
}
</script>
</head>
<body>
<canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas>
<p id="output" />
<script>
var Module = {
print: (function () {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function (text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
canvas: (function () {
var canvas = document.getElementById('canvas');
return canvas;
})()
};
</script>
{{{ SCRIPT }}}
</body>
</html>