Skip to content

Instantly share code, notes, and snippets.

@Lightnet
Last active February 27, 2025 04:41
Show Gist options
  • Save Lightnet/802f51fe762ecb2f99be2980a70dec56 to your computer and use it in GitHub Desktop.
Save Lightnet/802f51fe762ecb2f99be2980a70dec56 to your computer and use it in GitHub Desktop.
# CMake configuration for SDL 3.2.4 project with SDL_ttf, SDL_image, SDL_mixer, and GLAD
cmake_minimum_required(VERSION 3.11)
project(MySDLProject VERSION 1.0 DESCRIPTION "SDL 3.2.4 C/C++ test with callbacks" LANGUAGES C CXX)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "Suppress deprecated warnings" FORCE)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Default to shared libs" FORCE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>")
include(FetchContent)
option(BUILD_EXAMPLES "Build example executables from examples/ folder" ON)
# Fetch SDL 3.2.4
FetchContent_Declare(
SDL3
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
GIT_TAG release-3.2.4
)
message(STATUS "Fetching and building SDL 3.2.4...")
set(SDL_SHARED ON CACHE BOOL "Build SDL shared library" FORCE)
set(SDL_STATIC OFF CACHE BOOL "Build SDL static library" FORCE)
set(SDL_TEST_LIBRARY OFF CACHE BOOL "Build SDL test library" FORCE)
FetchContent_MakeAvailable(SDL3)
# Fetch SDL_ttf prerelease-3.1.2
FetchContent_Declare(
SDL3_ttf
GIT_REPOSITORY https://github.com/libsdl-org/SDL_ttf.git
GIT_TAG prerelease-3.1.2
)
message(STATUS "Fetching and building SDL_ttf prerelease-3.1.2...")
set(SDL3TTF_BUILD_SHARED_LIBS ON CACHE BOOL "Build SDL_ttf shared library" FORCE)
set(CMAKE_DISABLE_FIND_PACKAGE_PkgConfig ON CACHE BOOL "Disable PkgConfig" FORCE)
set(CMAKE_DISABLE_FIND_PACKAGE_Python ON CACHE BOOL "Disable Python" FORCE)
set(SDL3TTF_INSTALL OFF CACHE BOOL "Disable SDL_ttf installation" FORCE)
FetchContent_MakeAvailable(SDL3_ttf)
# Fetch SDL_image release-3.2.0
set(SDL3IMAGE_BUILD_SHARED_LIBS ON CACHE BOOL "Build SDL_image shared library" FORCE)
set(SDLIMAGE_VENDORED ON CACHE BOOL "Use vendored libraries" FORCE)
set(FETCHCONTENT_UPDATES_DISCONNECTED_ZLIB OFF CACHE BOOL "Allow zlib updates" FORCE)
set(FETCHCONTENT_UPDATES_DISCONNECTED_LIBPNG OFF CACHE BOOL "Allow libpng updates" FORCE)
set(FETCHCONTENT_UPDATES_DISCONNECTED_LIBJPEG-TURBO OFF CACHE BOOL "Allow libjpeg-turbo updates" FORCE)
set(SDLIMAGE_BMP ON CACHE BOOL "Enable BMP support" FORCE)
set(SDLIMAGE_JPG ON CACHE BOOL "Enable JPG support" FORCE)
set(SDLIMAGE_PNG ON CACHE BOOL "Enable PNG support" FORCE)
FetchContent_Declare(
SDL3_image
GIT_REPOSITORY https://github.com/libsdl-org/SDL_image.git
GIT_TAG release-3.2.0
)
message(STATUS "Fetching and building SDL_image release-3.2.0...")
FetchContent_MakeAvailable(SDL3_image)
# Fetch SDL_mixer from main branch
# FetchContent_Declare(
# SDL3_mixer
# GIT_REPOSITORY https://github.com/libsdl-org/SDL_mixer.git
# GIT_TAG main
# )
# message(STATUS "Fetching and building SDL_mixer from main branch...")
# set(SDL3MIXER_BUILD_SHARED_LIBS ON CACHE BOOL "Build SDL_mixer shared library" FORCE)
# set(SDL3MIXER_SAMPLES OFF CACHE BOOL "Build SDL_mixer sample programs" FORCE)
# set(SDL3MIXER_FLAC OFF CACHE BOOL "Support FLAC audio" FORCE)
# set(SDL3MIXER_MP3 OFF CACHE BOOL "Support MP3 audio via mpg123" FORCE)
# set(SDL3MIXER_OGG OFF CACHE BOOL "Support OGG Vorbis audio" FORCE)
# set(SDL3MIXER_OPUS OFF CACHE BOOL "Support Opus audio" FORCE)
# set(SDL3MIXER_MOD OFF CACHE BOOL "Support MOD audio" FORCE)
# set(SDL3MIXER_MIDI OFF CACHE BOOL "Support MIDI audio" FORCE)
# set(SDL3MIXER_WAV ON CACHE BOOL "Support WAV audio" FORCE)
# set(SDL3MIXER_VENDORED OFF CACHE BOOL "Use vendored libraries" FORCE)
# set(SDL3MIXER_DEPS_SHARED OFF CACHE BOOL "Link dependencies as shared libs" FORCE)
# FetchContent_MakeAvailable(SDL3_mixer)
# Fetch GLAD
FetchContent_Declare(
glad
GIT_REPOSITORY https://github.com/Dav1dde/glad.git
GIT_TAG v0.1.36
)
message(STATUS "Fetching GLAD...")
FetchContent_MakeAvailable(glad)
# Find Python 3 (required for GLAD generation)
find_package(Python3 COMPONENTS Interpreter REQUIRED)
if(NOT Python3_FOUND)
message(FATAL_ERROR "Python 3 is required to generate GLAD sources. Please install Python 3.")
endif()
# Generate GLAD sources if not already present
set(GLAD_OUT_DIR "${CMAKE_BINARY_DIR}/glad_generated")
if(NOT EXISTS "${GLAD_OUT_DIR}/include/glad/glad.h")
message(STATUS "Generating GLAD sources for OpenGL 3.3 core profile...")
execute_process(
COMMAND ${Python3_EXECUTABLE} -m glad --generator=c --out-path=${GLAD_OUT_DIR} --profile=core --api=gl=3.3
WORKING_DIRECTORY ${glad_SOURCE_DIR}
RESULT_VARIABLE GLAD_GENERATE_RESULT
OUTPUT_VARIABLE GLAD_GENERATE_OUTPUT
ERROR_VARIABLE GLAD_GENERATE_ERROR
)
if(NOT GLAD_GENERATE_RESULT EQUAL "0")
message(FATAL_ERROR "Failed to generate GLAD sources: ${GLAD_GENERATE_RESULT}\nOutput: ${GLAD_GENERATE_OUTPUT}\nError: ${GLAD_GENERATE_ERROR}")
endif()
endif()
# Add GLAD as a custom static library
add_library(glad_custom STATIC
"${GLAD_OUT_DIR}/src/glad.c"
)
target_include_directories(glad_custom PUBLIC "${GLAD_OUT_DIR}/include")
# Define main executable from src/main.c
add_executable(MySDLProject src/main.c)
target_compile_definitions(MySDLProject PRIVATE SDL_MAIN_USE_CALLBACKS)
# Custom command to copy assets folder
add_custom_target(copy_assets
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/assets" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
COMMENT "Copying assets to build output directory"
)
add_dependencies(MySDLProject copy_assets)
# Conditionally build example executables
if(BUILD_EXAMPLES)
file(GLOB EXAMPLE_SOURCES "examples/*.c" "examples/*.cpp")
foreach(EXAMPLE_SOURCE ${EXAMPLE_SOURCES})
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SOURCE} NAME_WE)
add_executable(${EXAMPLE_NAME} ${EXAMPLE_SOURCE})
if(${EXAMPLE_SOURCE} MATCHES "\\.c$")
target_compile_definitions(${EXAMPLE_NAME} PRIVATE SDL_MAIN_USE_CALLBACKS)
endif()
target_include_directories(${EXAMPLE_NAME} PRIVATE
"${sdl3_SOURCE_DIR}/include"
"${sdl3_ttf_SOURCE_DIR}"
"${sdl3_image_SOURCE_DIR}"
#"${sdl3_mixer_SOURCE_DIR}"
)
target_link_libraries(${EXAMPLE_NAME} PRIVATE
SDL3::SDL3
SDL3_ttf::SDL3_ttf
SDL3_image::SDL3_image
#SDL3_mixer::SDL3_mixer
)
# Link GLAD for sdl3_open (or example_sdl3_opengl if you prefer that name)
if(${EXAMPLE_NAME} STREQUAL "sdl3_open" OR ${EXAMPLE_NAME} STREQUAL "example_sdl3_opengl")
target_include_directories(${EXAMPLE_NAME} PRIVATE "${GLAD_OUT_DIR}/include")
target_link_libraries(${EXAMPLE_NAME} PRIVATE glad_custom)
if(WIN32)
target_link_libraries(${EXAMPLE_NAME} PRIVATE opengl32)
elseif(UNIX AND NOT APPLE)
target_link_libraries(${EXAMPLE_NAME} PRIVATE GL)
elseif(APPLE)
target_link_libraries(${EXAMPLE_NAME} PRIVATE "-framework OpenGL")
endif()
endif()
add_dependencies(${EXAMPLE_NAME} copy_assets)
endforeach()
endif()
# Debug include paths
message(STATUS "SDL3 include dir: ${sdl3_SOURCE_DIR}/include")
message(STATUS "SDL_ttf include dir: ${sdl3_ttf_SOURCE_DIR}")
message(STATUS "SDL_image include dir: ${sdl3_image_SOURCE_DIR}")
message(STATUS "SDL_mixer include dir: ${sdl3_mixer_SOURCE_DIR}")
message(STATUS "GLAD include dir: ${GLAD_OUT_DIR}/include")
# Set include directories for the main executable
target_include_directories(MySDLProject PRIVATE
"${sdl3_SOURCE_DIR}/include"
"${sdl3_ttf_SOURCE_DIR}"
"${sdl3_image_SOURCE_DIR}"
#"${sdl3_mixer_SOURCE_DIR}"
)
# Link libraries to the main executable
target_link_libraries(MySDLProject PRIVATE
SDL3::SDL3
SDL3_ttf::SDL3_ttf
SDL3_image::SDL3_image
#SDL3_mixer::SDL3_mixer
)
// example_sdl3_opengl.c
#include <SDL3/SDL.h>
#include <glad/glad.h>
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
// Vector structure
typedef struct {
float x, y, z;
} Vec3;
// Camera structure
typedef struct {
Vec3 position;
Vec3 front;
Vec3 up;
Vec3 right;
float yaw;
float pitch;
} Camera;
// Global variables
SDL_Window* window = NULL;
SDL_GLContext gl_context;
bool running = true;
GLuint shaderProgram;
Camera camera;
bool mouse_captured = false;
GLuint VAO, VBO;
// Vertex shader
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
"}\0";
// Fragment shader
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec3 lightColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(lightColor, 1.0);\n"
"}\0";
// Full cube vertices (36 vertices, 6 faces)
float vertices[] = {
-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f
};
// Simple matrix functions
void mat4_identity(float* m) {
for (int i = 0; i < 16; i++) m[i] = (i % 5 == 0) ? 1.0f : 0.0f;
}
void mat4_perspective(float* m, float fov, float aspect, float near, float far) {
float tanHalfFov = tanf(fov / 2.0f);
mat4_identity(m);
m[0] = 1.0f / (aspect * tanHalfFov);
m[5] = 1.0f / tanHalfFov;
m[10] = -(far + near) / (far - near);
m[11] = -1.0f;
m[14] = -(2.0f * far * near) / (far - near);
}
void mat4_lookat(float* m, Vec3 eye, Vec3 center, Vec3 up) {
Vec3 f = {center.x - eye.x, center.y - eye.y, center.z - eye.z};
float len = sqrtf(f.x * f.x + f.y * f.y + f.z * f.z);
f.x /= len; f.y /= len; f.z /= len;
Vec3 s = {f.y * up.z - f.z * up.y, f.z * up.x - f.x * up.z, f.x * up.y - f.y * up.x};
len = sqrtf(s.x * s.x + s.y * s.y + s.z * s.z);
s.x /= len; s.y /= len; s.z /= len;
Vec3 u = {s.y * f.z - s.z * f.y, s.z * f.x - s.x * f.z, s.x * f.y - s.y * f.x};
mat4_identity(m);
m[0] = s.x; m[4] = s.y; m[8] = s.z;
m[1] = u.x; m[5] = u.y; m[9] = u.z;
m[2] = -f.x; m[6] = -f.y; m[10] = -f.z;
m[12] = -(s.x * eye.x + s.y * eye.y + s.z * eye.z);
m[13] = -(u.x * eye.x + u.y * eye.y + u.z * eye.z);
m[14] = -(-f.x * eye.x - f.y * eye.y - f.z * eye.z);
}
// Update camera direction based on yaw and pitch
void update_camera_direction(Camera* cam) {
float yaw_rad = cam->yaw * 3.14159f / 180.0f;
float pitch_rad = cam->pitch * 3.14159f / 180.0f;
cam->front.x = cosf(yaw_rad) * cosf(pitch_rad);
cam->front.y = sinf(pitch_rad);
cam->front.z = sinf(yaw_rad) * cosf(pitch_rad);
float len = sqrtf(cam->front.x * cam->front.x + cam->front.y * cam->front.y + cam->front.z * cam->front.z);
cam->front.x /= len; cam->front.y /= len; cam->front.z /= len;
Vec3 world_up = {0.0f, 1.0f, 0.0f};
cam->right = (Vec3){
cam->front.y * world_up.z - cam->front.z * world_up.y,
cam->front.z * world_up.x - cam->front.x * world_up.z,
cam->front.x * world_up.y - cam->front.y * world_up.x
};
len = sqrtf(cam->right.x * cam->right.x + cam->right.y * cam->right.y + cam->right.z * cam->right.z);
cam->right.x /= len; cam->right.y /= len; cam->right.z /= len;
cam->up = (Vec3){
cam->right.y * cam->front.z - cam->right.z * cam->front.y,
cam->right.z * cam->front.x - cam->right.x * cam->front.z,
cam->right.x * cam->front.y - cam->right.y * cam->front.x
};
}
void init() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL_Init failed: %s\n", SDL_GetError());
exit(1);
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
window = SDL_CreateWindow("SDL3 OpenGL", 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window) {
printf("Window creation failed: %s\n", SDL_GetError());
SDL_Quit();
exit(1);
}
gl_context = SDL_GL_CreateContext(window);
if (!gl_context) {
printf("GL context creation failed: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
exit(1);
}
SDL_GL_MakeCurrent(window, gl_context);
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
printf("Failed to initialize GLAD\n");
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
exit(1);
}
camera.position = (Vec3){0.0f, 0.0f, 3.0f};
camera.front = (Vec3){0.0f, 0.0f, -1.0f};
camera.up = (Vec3){0.0f, 1.0f, 0.0f};
camera.right = (Vec3){1.0f, 0.0f, 0.0f};
camera.yaw = -90.0f;
camera.pitch = 0.0f;
update_camera_direction(&camera);
glEnable(GL_DEPTH_TEST);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("Vertex shader compilation failed: %s\n", infoLog);
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("Fragment shader compilation failed: %s\n", infoLog);
}
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
printf("Shader program linking failed: %s\n", infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void handle_input(float deltaTime) {
SDL_Event event;
const Uint8* keyboard_state = SDL_GetKeyboardState(NULL);
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) running = false;
if (event.type == SDL_EVENT_KEY_DOWN) {
if (event.key.key == SDLK_ESCAPE) {
mouse_captured = false;
if (SDL_SetWindowRelativeMouseMode(window, false) != 0) {
printf("Failed to unset relative mouse mode: %s\n", SDL_GetError());
}
}
}
if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && !mouse_captured) {
mouse_captured = true;
if (SDL_SetWindowRelativeMouseMode(window, true) != 0) {
printf("Failed to set relative mouse mode: %s\n", SDL_GetError());
}
}
if (event.type == SDL_EVENT_MOUSE_MOTION && mouse_captured) {
float sensitivity = 0.1f;
camera.yaw += event.motion.xrel * sensitivity;
camera.pitch -= event.motion.yrel * sensitivity;
if (camera.pitch > 89.0f) camera.pitch = 89.0f;
if (camera.pitch < -89.0f) camera.pitch = -89.0f;
update_camera_direction(&camera);
}
}
float cameraSpeed = 2.5f * deltaTime;
if (keyboard_state[SDL_SCANCODE_W]) {
camera.position.x += cameraSpeed * camera.front.x;
camera.position.y += cameraSpeed * camera.front.y;
camera.position.z += cameraSpeed * camera.front.z;
}
if (keyboard_state[SDL_SCANCODE_S]) {
camera.position.x -= cameraSpeed * camera.front.x;
camera.position.y -= cameraSpeed * camera.front.y;
camera.position.z -= cameraSpeed * camera.front.z;
}
if (keyboard_state[SDL_SCANCODE_A]) {
camera.position.x -= cameraSpeed * camera.right.x;
camera.position.y -= cameraSpeed * camera.right.y;
camera.position.z -= cameraSpeed * camera.right.z;
}
if (keyboard_state[SDL_SCANCODE_D]) {
camera.position.x += cameraSpeed * camera.right.x;
camera.position.y += cameraSpeed * camera.right.y;
camera.position.z += cameraSpeed * camera.right.z;
}
}
void render() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram);
float model[16], view[16], projection[16];
mat4_identity(model);
Vec3 center = {
camera.position.x + camera.front.x,
camera.position.y + camera.front.y,
camera.position.z + camera.front.z
};
mat4_lookat(view, camera.position, center, camera.up);
mat4_perspective(projection, 45.0f * 3.14159f / 180.0f, 800.0f / 600.0f, 0.1f, 100.0f);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, model);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, view);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, projection);
Vec3 lightColor = {1.0f, 1.0f, 1.0f};
glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"),
lightColor.x, lightColor.y, lightColor.z);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
void cleanup() {
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
}
int main(int argc, char* argv[]) {
init();
Uint64 previous = SDL_GetTicks();
while (running) {
Uint64 current = SDL_GetTicks();
float deltaTime = (current - previous) / 1000.0f;
previous = current;
handle_input(deltaTime);
render();
}
cleanup();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment