mirror of
https://github.com/Motschen/Adventura.git
synced 2025-12-15 19:35:09 +01:00
feat: use CMake and SDL3
Based on: https://github.com/Ravbug/sdl3-sample
This commit is contained in:
195
src/assets/main.cpp
Normal file
195
src/assets/main.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
#include <SDL3_mixer/SDL_mixer.h>
|
||||
#include <SDL3_image/SDL_image.h>
|
||||
#include <cmath>
|
||||
#include <string_view>
|
||||
#include <filesystem>
|
||||
|
||||
constexpr uint32_t windowStartWidth = 400;
|
||||
constexpr uint32_t windowStartHeight = 400;
|
||||
|
||||
struct AppContext {
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* messageTex, *imageTex;
|
||||
SDL_FRect messageDest;
|
||||
SDL_AudioDeviceID audioDevice;
|
||||
Mix_Music* music;
|
||||
SDL_AppResult app_quit = SDL_APP_CONTINUE;
|
||||
};
|
||||
|
||||
SDL_AppResult SDL_Fail(){
|
||||
SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
|
||||
// init the library, here we make a window so we only need the Video capabilities.
|
||||
if (not SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)){
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// init TTF
|
||||
if (not TTF_Init()) {
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// create a window
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow("SDL Minimal Sample", windowStartWidth, windowStartHeight, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY);
|
||||
if (not window){
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// create a renderer
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL);
|
||||
if (not renderer){
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// load the font
|
||||
#if __ANDROID__
|
||||
std::filesystem::path basePath = ""; // on Android we do not want to use basepath. Instead, assets are available at the root directory.
|
||||
#else
|
||||
auto basePathPtr = SDL_GetBasePath();
|
||||
if (not basePathPtr){
|
||||
return SDL_Fail();
|
||||
}
|
||||
const std::filesystem::path basePath = basePathPtr;
|
||||
#endif
|
||||
|
||||
const auto fontPath = basePath / "Inter-VariableFont.ttf";
|
||||
TTF_Font* font = TTF_OpenFont(fontPath.string().c_str(), 36);
|
||||
if (not font) {
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// render the font to a surface
|
||||
const std::string_view text = "Hello SDL!";
|
||||
SDL_Surface* surfaceMessage = TTF_RenderText_Solid(font, text.data(), text.length(), { 255,255,255 });
|
||||
|
||||
// make a texture from the surface
|
||||
SDL_Texture* messageTex = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
|
||||
|
||||
// we no longer need the font or the surface, so we can destroy those now.
|
||||
TTF_CloseFont(font);
|
||||
SDL_DestroySurface(surfaceMessage);
|
||||
|
||||
// load the SVG
|
||||
auto svg_surface = IMG_Load((basePath / "gs_tiger.svg").string().c_str());
|
||||
SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, svg_surface);
|
||||
SDL_DestroySurface(svg_surface);
|
||||
|
||||
|
||||
// get the on-screen dimensions of the text. this is necessary for rendering it
|
||||
auto messageTexProps = SDL_GetTextureProperties(messageTex);
|
||||
SDL_FRect text_rect{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.w = float(SDL_GetNumberProperty(messageTexProps, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0)),
|
||||
.h = float(SDL_GetNumberProperty(messageTexProps, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0))
|
||||
};
|
||||
|
||||
// init SDL Mixer
|
||||
auto audioDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
|
||||
if (not audioDevice) {
|
||||
return SDL_Fail();
|
||||
}
|
||||
if (not Mix_OpenAudio(audioDevice, NULL)) {
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// load the music
|
||||
auto musicPath = basePath / "the_entertainer.ogg";
|
||||
auto music = Mix_LoadMUS(musicPath.string().c_str());
|
||||
if (not music) {
|
||||
return SDL_Fail();
|
||||
}
|
||||
|
||||
// play the music (does not loop)
|
||||
Mix_PlayMusic(music, 0);
|
||||
|
||||
// print some information about the window
|
||||
SDL_ShowWindow(window);
|
||||
{
|
||||
int width, height, bbwidth, bbheight;
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
SDL_GetWindowSizeInPixels(window, &bbwidth, &bbheight);
|
||||
SDL_Log("Window size: %ix%i", width, height);
|
||||
SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight);
|
||||
if (width != bbwidth){
|
||||
SDL_Log("This is a highdpi environment.");
|
||||
}
|
||||
}
|
||||
|
||||
// set up the application data
|
||||
*appstate = new AppContext{
|
||||
.window = window,
|
||||
.renderer = renderer,
|
||||
.messageTex = messageTex,
|
||||
.imageTex = tex,
|
||||
.messageDest = text_rect,
|
||||
.audioDevice = audioDevice,
|
||||
.music = music,
|
||||
};
|
||||
|
||||
SDL_SetRenderVSync(renderer, -1); // enable vysnc
|
||||
|
||||
SDL_Log("Application started successfully!");
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event* event) {
|
||||
auto* app = (AppContext*)appstate;
|
||||
|
||||
if (event->type == SDL_EVENT_QUIT) {
|
||||
app->app_quit = SDL_APP_SUCCESS;
|
||||
}
|
||||
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
SDL_AppResult SDL_AppIterate(void *appstate) {
|
||||
auto* app = (AppContext*)appstate;
|
||||
|
||||
// draw a color
|
||||
auto time = SDL_GetTicks() / 1000.f;
|
||||
auto red = (std::sin(time) + 1) / 2.0 * 255;
|
||||
auto green = (std::sin(time / 2) + 1) / 2.0 * 255;
|
||||
auto blue = (std::sin(time) * 2 + 1) / 2.0 * 255;
|
||||
|
||||
SDL_SetRenderDrawColor(app->renderer, red, green, blue, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderClear(app->renderer);
|
||||
|
||||
// Renderer uses the painter's algorithm to make the text appear above the image, we must render the image first.
|
||||
SDL_RenderTexture(app->renderer, app->imageTex, NULL, NULL);
|
||||
SDL_RenderTexture(app->renderer, app->messageTex, NULL, &app->messageDest);
|
||||
|
||||
SDL_RenderPresent(app->renderer);
|
||||
|
||||
return app->app_quit;
|
||||
}
|
||||
|
||||
void SDL_AppQuit(void* appstate, SDL_AppResult result) {
|
||||
auto* app = (AppContext*)appstate;
|
||||
if (app) {
|
||||
SDL_DestroyRenderer(app->renderer);
|
||||
SDL_DestroyWindow(app->window);
|
||||
|
||||
Mix_FadeOutMusic(1000); // prevent the music from abruptly ending.
|
||||
Mix_FreeMusic(app->music); // this call blocks until the music has finished fading
|
||||
Mix_CloseAudio();
|
||||
SDL_CloseAudioDevice(app->audioDevice);
|
||||
|
||||
delete app;
|
||||
}
|
||||
TTF_Quit();
|
||||
Mix_Quit();
|
||||
|
||||
SDL_Log("Application quit successfully!");
|
||||
SDL_Quit();
|
||||
}
|
||||
Reference in New Issue
Block a user