SDL(Simple DirectMedia Layer)是一个开源的跨平台多媒体开发库,使用C语言编写,主要用于游戏、模拟器和媒体播放器等多媒体应用的开发。它提供了控制图像、声音、输入输出等功能的函数,使开发者能够用相同的代码开发跨平台(如Linux、Windows、macOS等)的应用程序。
本文使用VS2022
参考
官方文档 SDL3/FrontPage - SDL Wiki
API SDL3/APIByCategory - SDL Wiki
SDL3_image/FrontPage - SDL WikiSDL3_image SDL3_image/FrontPage - SDL Wiki
SDL3_ttf/FrontPage - SDL WikiSDL3_tff SDL3_ttf/FrontPage - SDL Wiki
Lazy Foo' Productions - Beginning Game Programming v2.0,详细讲述了原理,目前为SDL2教程,但文章末尾附有SDL3相应代码,作者未来会更新为SDL3教程
以上资料对学习SDL3尤为重要
SDL3
01. Visual Studio 配置 SDL3_哔哩哔哩_bilibili
按照上述视频配置。似乎使用Cmake可以简化很多流程
拓展库
(注意所有下载的版本都是devel,即开发者版!)
SDL3_image :如果要加载png等多种格式的图片,需要下载
SDL3_tff:渲染文字 (ttf表示TrueType Font),注意SDL3_ttf 不自带字体文件 ,它是一个用于加载和渲染 TrueType (.ttf) 或 OpenType (.otf) 字体文件的库,但需要自行提供字体文件。
-
你需要自行获取合法的字体文件(如
Arial.ttf
、SimHei.ttf
等),并放在项目目录中(例如assets/fonts/
)。 -
字体来源:
-
系统自带字体(如 Windows 的
C:\Windows\Fonts
)。 -
免费字体网站(如 Google Fonts)。
-
注意遵守字体版权许可。
-
测试
测试SDL3
如果配置成功,会创建一个窗口,并在3s后关闭
cpp
#include<iostream>
#include"SDL3/SDL.h"
int main(int argc, char* argv[])
{
//a test to exam whether SDL3 has been added properly.
SDL_Window* window;
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow("test_SDL", 480, 600, SDL_WINDOW_OPENGL);
if (window == NULL)
{
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "failed to create a window\n");
return EXIT_FAILURE;
}
SDL_Delay(3000);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
测试SDL3_image
注意换成自己图片的路径,成功则会显示图片
cpp
#include<iostream>
#include "SDL3_image/SDL_image.h" //"SDL3/SDL.h" is inside
using namespace std;
int main(int argc, char* argv[])
{
//a test to exam whether SDL3_image has been added properly.
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
float width = 1080;
float height = 720;
SDL_Window* win = SDL_CreateWindow("test for SDL3_image", width, height, 0);
if (win == nullptr) {
std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return 1;
}
SDL_Renderer* ren = SDL_CreateRenderer(win, NULL);
if (ren == nullptr) {
std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(win);
SDL_Quit();
return 1;
}
SDL_Surface* imag = IMG_Load("resources/0.png"); //the path of the file
if (!imag){
cout << "failed to load the image\n";
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 1;
}
SDL_Texture* tex = SDL_CreateTextureFromSurface(ren, imag);//转化为纹理
SDL_DestroySurface(imag);
if (tex == nullptr) {
std::cerr << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 1;
}
SDL_Event e;
bool quit = false;
while (!quit) {
SDL_RenderClear(ren);
SDL_RenderTexture(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);
while (SDL_PollEvent(&e)) {
if (e.type == SDL_EVENT_QUIT) {
quit = true;
}
}
}
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
测试SDL3_tff
把字体换成相应路径
cpp
#include "SDL3_image/SDL_image.h" //"SDL3/SDL.h" is inside
#include <SDL3_ttf/SDL_ttf.h>
#include<vector>
#include<iostream>
using namespace std;
int main(int argc, char* argv[])
{
//a test to exam whether SDL3_ttf has been added properly.
// Initialize SDL3
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
float width = 1080;
float height = 720;
// Create SDL Window
SDL_Window* window = SDL_CreateWindow("SDL3 Unicode Text", 420, 300, SDL_WINDOW_RESIZABLE);
if (!window) {
std::cerr << "Failed to create window: " << SDL_GetError() << std::endl;
return -1;
}
// Create Renderer
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL);
if (!renderer) {
std::cerr << "Failed to create renderer: " << SDL_GetError() << std::endl;
SDL_DestroyWindow(window);
return -1;
}
// Load Font
TTF_Font* font = TTF_OpenFont("resources/FontRoboto/static/Roboto_Condensed-Black.ttf", 16);
if (!font) {
std::cerr << "Failed to load font: " << SDL_GetError() << std::endl;
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return -1;
}
// Unicode text to render
std::wstring text = L"A test for SDL3_ttf";
// Vector of surfaces
std::vector<SDL_Surface*> surfaces;
surfaces.reserve(text.size());
// Render each character as a surface
for (size_t i = 0; i < text.size(); i++) {
SDL_Surface* textSurface = TTF_RenderGlyph_LCD(font, text[i], SDL_Color{ 255, 255, 255, 255 }, SDL_Color{ 0, 0, 0, 255 });
if (!textSurface) {
std::cerr << "Failed to create text surface: " << SDL_GetError() << std::endl;
continue; // Skip if surface creation fails
}
surfaces.push_back(textSurface);
}
// Calculate total width and max height for the combined surface
int totalWidth = 0;
int maxHeight = 0;
for (auto& surf : surfaces) {
totalWidth += surf->w + 5; // Add spacing between glyphs
if (surf->h > maxHeight) {
maxHeight = surf->h;
}
}
SDL_FRect rect{ 5, 50, static_cast<float>(totalWidth), static_cast<float>(maxHeight) };
// Create the final combined surface
SDL_Surface* combinedSurface = SDL_CreateSurface(totalWidth, maxHeight, SDL_PIXELFORMAT_RGBA32);
if (!combinedSurface) {
std::cerr << "Failed to create combined surface: " << SDL_GetError() << std::endl;
return -1;
}
// Blit each glyph onto the combined surface
int xOffset = 0;
for (auto& surf : surfaces) {
SDL_Rect destRect = { xOffset, 0, surf->w, surf->h };
SDL_BlitSurface(surf, NULL, combinedSurface, &destRect);
xOffset += surf->w + 5; // Move to the next position with spacing
SDL_DestroySurface(surf); // Free individual surfaces after blitting
}
surfaces.clear(); // Clear the vector since we don't need it anymore
// Convert the combined surface to a texture
SDL_Texture* combinedTexture = SDL_CreateTextureFromSurface(renderer, combinedSurface);
SDL_DestroySurface(combinedSurface); // Free the surface after conversion
// Event loop
bool running = true;
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT ||
(event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_ESCAPE)) {
running = false;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// Render the combined text texture
SDL_RenderTexture(renderer, combinedTexture, NULL, &rect);
SDL_RenderPresent(renderer);
}
// Cleanup
SDL_DestroyTexture(combinedTexture);
TTF_CloseFont(font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
// Shutdown SDL3 and TTF
TTF_Quit();
SDL_Quit();
return 0;
}
结果
