当前位置: 首页 > news >正文

SDL基础

SDL

SDL(Simple DirectMedia Layer)是一个开源的跨平台多媒体开发库,主要用于开发需要图形、音频和输入设备支持的应用程序。它使用C语言编写,提供了简单易用的API,**能够帮助开发者快速实现跨平台的多媒体功能。**SDL广泛应用于游戏开发、模拟器、媒体播放器等领域。
SDL的主要特点包括:

  • 跨平台支持:兼容Windows、macOS、Linux、iOS、Android等多种操作系统。
  • 多媒体功能:提供图形渲染、音频处理、输入设备管理等功能。
  • 简单易用:API设计简洁,易于上手,适合初学者和专业开发者。
  • 社区支持:拥有活跃的开源社区,提供丰富的文档、教程和扩展库。
    视频播放器:结合SDL的窗口和渲染功能以及FFmpeg的解码能力,可以开发出跨平台的视频播放器。

实验一 创建窗口

SDL_Init(int flag):初始化SDL系统
好的!以下是将您提供的SDL初始化标志整理成表格的形式,方便查看和理解:

标志名称描述
SDL_INIT_TIMER初始化定时器子系统。
SDL_INIT_AUDIO初始化音频子系统。
SDL_INIT_VIDEO初始化视频子系统(包括窗口和渲染器)。
SDL_INIT_JOYSTICK初始化游戏手柄子系统。
SDL_INIT_HAPTIC初始化力反馈设备子系统。
SDL_INIT_GAMECONTROLLER初始化游戏控制器子系统。
SDL_INIT_EVENTS初始化事件子系统。
SDL_INIT_EVERYTHING初始化所有子系统。

SDL_CreateWindow():创建窗口SDL_Window
SDL_Window* SDL_CreateWindow(const char* title, int x, int y, int w, int h, Uint32 flags)

title:窗口的标题,显示在窗口的标题栏上。
x:窗口在屏幕上的水平位置。可以使用SDL_WINDOWPOS_UNDEFINED让系统自动选择位置。
y:窗口在屏幕上的垂直位置。可以使用SDL_WINDOWPOS_UNDEFINED让系统自动选择位置。
w:窗口的宽度,以像素为单位。
h:窗口的高度,以像素为单位。

当然可以,以下是您需要的表格:

标志名称描述
SDL_WINDOW_SHOWN创建窗口后立即显示。
SDL_WINDOW_FULLSCREEN创建全屏窗口。
SDL_WINDOW_BORDERLESS创建无边框窗口。
SDL_WINDOW_RESIZABLE创建可调整大小的窗口。
SDL_WINDOW_MAXIMIZED创建最大化窗口。
SDL_WINDOW_MINIMIZED创建最小化窗口。
SDL_WINDOW_HIDDEN创建隐藏窗口。

**SDL_Delay():**工具函数,用于延时
ms:暂停的时间,以毫秒为单位。
**SDL_Quit():**退出SDL系统

代码

    printf("Hello World!\n");SDL_Window *window = NULL;      // 声明窗口SDL_Init(SDL_INIT_VIDEO);       // 初始化SDL// 创建SDL Windowwindow = SDL_CreateWindow("Basic Window",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);if(!window) // 检测是否创建成功{printf("Can't create window, err:%s\n", SDL_GetError());return 1;}SDL_Delay(10000);  // 延迟10000msSDL_DestroyWindow(window); // 消耗窗口SDL_Quit(); // 释放资源return 0;

当设置为 SDL_WINDOWPOS_UNDEFINED 时,表示窗口的初始位置由操作系统决定,通常会根据当前的桌面布局和系统设置自动放置窗口

实验二 渲染器和纹理器

渲染器(Renderer)
渲染器是SDL中用于将图像绘制到窗口或屏幕上的核心组件。它提供了一个统一的接口,允许开发者使用硬件加速来渲染2D图形。渲染器的主要功能包括:

  • 创建纹理:渲染器可以创建纹理对象,用于存储图像数据。
  • 绘制纹理:渲染器将纹理绘制到窗口上。
  • 清除屏幕:渲染器可以清除屏幕内容,为新的绘制操作做准备。
  • 更新显示:渲染器将绘制的内容显示到屏幕上。
    SDL_Renderer* SDL_CreateRenderer(SDL_Window* window, int index, Uint32 flags);

window:指向 SDL_Window 对象的指针,指定渲染器将在哪个窗口上绘制。
index:指定渲染驱动程序的索引。通常使用 -1,表示使用默认的渲染驱动程序。
flags:指定渲染器的创建标志,用0就行

纹理(Texture)
纹理是存储在显存中的图像数据,利用硬件加速可以高效地进行绘制。纹理的主要功能包括:

  • 存储图像数据:纹理可以存储从文件加载的图像数据,或者动态生成的图像数据。
  • 高效渲染:纹理可以被快速渲染到屏幕上,适合频繁更新的场景。
    SDL_Texture* SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h);

renderer:指向 SDL_Renderer 对象的指针。
format:像素格式,例如 RGB 或 YUV。
access:指定纹理的访问模式,例如 SDL_TEXTUREACCESS_STREAMING 或 SDL_TEXTUREACCESS_TARGET。
(创建可作为渲染目标的纹理:在调用 SDL_CreateTexture 创建纹理时,将 access 参数设置为 SDL_TEXTUREACCESS_TARGET,即可创建一个可以作为渲染目标的纹理。)
w 和 h:纹理的宽度和高度。

SDL_Rect 一个简单的矩形结构

int main(){int run = 1;SDL_Window *window = NULL;SDL_Renderer *renderer = NULL;SDL_Texture *texture = NULL;SDL_Rect rect; // 长方形,原点在左上角rect.w = 50;    //方块大小rect.h = 50;SDL_Init(SDL_INIT_VIDEO);//初始化函数,可以确定希望激活的子系统window = SDL_CreateWindow("2 Window",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,640,480,SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);// 创建窗口if (!window){return -1;}renderer = SDL_CreateRenderer(window, -1, 0);//基于窗口创建渲染器if (!renderer){return -1;}texture = SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET,640,480); //创建纹理if (!texture){return -1;}int show_count = 0;while (run){rect.x = rand() % 600;rect.y = rand() % 400;SDL_SetRenderTarget(renderer, texture); // 设置渲染目标为纹理SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // 纹理背景为黑色SDL_RenderClear(renderer); //清屏->之前显示清掉SDL_RenderDrawRect(renderer, &rect); //绘制一个长方形SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); //长方形为白色 rgb ->透明成都 SDL_RenderFillRect(renderer, &rect);SDL_SetRenderTarget(renderer, NULL); //恢复默认,渲染目标为窗口SDL_RenderCopy(renderer, texture, NULL, NULL); //拷贝纹理到CPUSDL_RenderPresent(renderer); //输出到目标窗口上SDL_Delay(300);if(show_count++ > 30){run = 0;        // 不跑了}}SDL_DestroyTexture(texture);SDL_DestroyRenderer(renderer);SDL_DestroyWindow(window); //销毁窗口SDL_Quit();return 0;}

一个窗口如果只有一个渲染器,那么整个窗口都是渲染器范围
如果在使用 SDL_RenderCopy(renderer, texture, NULL, NULL); 绘制纹理时省略了源矩形(srcrect)和目标矩形(dstrect),SDL会默认执行以下操作:

源矩形(srcrect):默认为 NULL,表示使用纹理的整个区域。 目标矩形(dstrect):默认为
NULL,表示纹理会被拉伸或压缩以适应渲染目标(窗口)的尺寸。

实验三 事件检测

SDL(Simple DirectMedia Layer)的事件系统是处理用户输入和系统事件的核心机制。它允许开发者检测和响应各种事件,如键盘按键、鼠标移动、窗口调整大小
操作事件

  • SDL_WaitEvent():等待一个事件
  • SDL_PushEvent():发送一个事件
    事件
  • SDL_QUIT:用户点击窗口关闭按钮时触发。
  • SDL_KEYDOWN、SDL_KEYUP:键盘按键按下或释放时触发。
  • SDL_MOUSEBUTTONDOWN、SDL_MOUSEBUTTONUP:鼠标按键按下或释放时触发。
  • SDL_MOUSEMOTION:鼠标移动时触发。
  • SDL_USEREVENT:用户自定义事件,开发者可以通过SDL_PushEvent向队列中插入自定义事件。
#define FF_QUIT_EVENT    (SDL_USEREVENT + 2)
int main(){SDL_Window *window = NULL;              // Declare a pointerSDL_Renderer *renderer = NULL;SDL_Init(SDL_INIT_VIDEO);               // Initialize SDL2// Create an application window with the following settings:window = SDL_CreateWindow("An SDL2 window",                  // window titleSDL_WINDOWPOS_UNDEFINED,           // initial x positionSDL_WINDOWPOS_UNDEFINED,           // initial y position640,                               // width, in pixels480,                               // height, in pixelsSDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS// flags - see below);// Check that the window was successfully createdif (window == NULL){// In the case that the window could not be made...printf("Could not create window: %s\n", SDL_GetError());return 1;}/* We must call SDL_CreateRenderer in order for draw calls to affect this window. */renderer = SDL_CreateRenderer(window, -1, 0);/* Select the color for drawing. It is set to red here. */SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);/* Clear the entire screen to our selected color. */SDL_RenderClear(renderer);/* Up until now everything was drawn behind the scenes.This will show the new, red contents of the window. */SDL_RenderPresent(renderer);SDL_Event event;int b_exit = 0;for (;;){SDL_WaitEvent(&event);//检测事件switch (event.type){case SDL_KEYDOWN:	/* 键盘事件 */switch (event.key.keysym.sym){case SDLK_a:printf("key down a\n");break;case SDLK_s:printf("key down s\n");break;case SDLK_d:printf("key down d\n");break;case SDLK_q:printf("key down q and push quit event\n");SDL_Event event_q;event_q.type = FF_QUIT_EVENT;SDL_PushEvent(&event_q);break;default:printf("key down 0x%x\n", event.key.keysym.sym);break;}break;case SDL_MOUSEBUTTONDOWN:			/* 鼠标按下事件 */if (event.button.button == SDL_BUTTON_LEFT){printf("mouse down left\n");}else if(event.button.button == SDL_BUTTON_RIGHT){printf("mouse down right\n");}else{printf("mouse down %d\n", event.button.button);}break;case SDL_MOUSEMOTION:		/* 鼠标移动事件 */printf("mouse movie (%d,%d)\n", event.button.x, event.button.y);break;case FF_QUIT_EVENT://printf("receive quit event\n");b_exit = 1;break;}if(b_exit)break;}//destory rendererif (renderer)SDL_DestroyRenderer(renderer);// Close and destroy the windowif (window)SDL_DestroyWindow(window);// Clean upSDL_Quit();return 0;}

在这个例子中,FF_QUIT_EVENT 被定义为用户自定义事件类型,其值是 SDL_USEREVENT + 2。这意味着 FF_QUIT_EVENT 是第二个用户自定义事件(从 SDL_USEREVENT 开始计数)。

实验四 多线程

◼ SDL线程创建: SDL_CreateThread:无需阻塞 就能执行
◼ SDL线程等待: SDL_WaitThead
◼ SDL互斥锁: SDL_CreateMutex/SDL_DestroyMutex
◼ SDL锁定互斥: SDL_LockMutex/SDL_UnlockMutex
◼ SDL条件变量(信号量): SDL_CreateCond/SDL_DestoryCond
◼ SDL条件变量(信号量)等待/通知: SDL_CondWait/SDL_CondSinga //自动解锁

SDL_mutex *s_lock = NULL;
SDL_cond *s_cond = NULL;int thread_work(void *arg)
{SDL_LockMutex(s_lock);printf("                <============thread_work sleep\n");sleep(10);      // 用来测试获取锁printf("                <============thread_work wait\n");// 释放s_lock资源,并等待signal。之所以释放s_lock是让别的线程能够获取到s_lockSDL_CondWait(s_cond, s_lock); //另一个线程(1)发送signal和(2)释放lock后,这个函数退出printf("                <===========thread_work receive signal, continue to do ~_~!!!\n");printf("                <===========thread_work end\n");SDL_UnlockMutex(s_lock);return 0;
int main(){s_lock = SDL_CreateMutex();s_cond = SDL_CreateCond();SDL_Thread * t = SDL_CreateThread(thread_work,"thread_work",NULL);//开始执行线程if(!t){printf("  %s",SDL_GetError);return -1;}for(int i = 0;i< 2;i++){sleep(2);printf("main execute =====>\n");}printf("main SDL_LockMutex(s_lock) before ====================>\n");SDL_LockMutex(s_lock);  // 获取锁,但是子线程还拿着锁 4 秒printf("main ready send signal====================>\n");printf("main SDL_CondSignal(s_cond) before ====================>\n");SDL_CondSignal(s_cond); // 发送信号,唤醒等待的线程printf("main SDL_CondSignal(s_cond) after ====================>\n");sleep(10);SDL_UnlockMutex(s_lock);// 释放锁,让其他线程可以拿到锁printf("main SDL_UnlockMutex(s_lock) after ====================>\n");SDL_WaitThread(t, NULL);SDL_DestroyMutex(s_lock);SDL_DestroyCond(s_cond);return 0;}

main execute =====>
main execute =====>
main SDL_LockMutex(s_lock) before ============>
<thread_work wait
main ready send signal
>
main SDL_CondSignal(s_cond) before ====================>
main SDL_CondSignal(s_cond) after ====================>
main SDL_UnlockMutex(s_lock) after ====================>
<===========thread_work receive signal, continue to do _!!!
<===========thread_work end

http://www.xdnf.cn/news/361.html

相关文章:

  • MATLAB 控制系统设计与仿真 - 34
  • 机器学习 | 细说Deep Q-Network(DQN)
  • 学习笔记十六——Rust Monad从头学
  • 【音视频】FLV格式分析
  • 让SQL飞起来:搭建企业AI应用的SQL性能优化实战
  • 2025年4月16日华为留学生笔试第二题200分
  • VS2022+QT环境配置及基本操作
  • Prometheus thanos架构
  • 2025年4月16日华为留学生笔试第三题300分
  • 自求导实现线性回归与PyTorch张量详解
  • Unity3d 6(6000.*.*)版本国区下载安装参考
  • 机器学习简介
  • python20-while和for in的美
  • 2025能源网络安全大赛CTF --- Crypto wp
  • visual studio 2022更改项目名称,灾难性故障(异常来自HRESULT)
  • 【Rust基础】使用Rocket构建基于SSE的流式回复
  • 模型加载常见问题
  • C/C++指针
  • 四大wordpress模板站
  • 第十七届“华中杯”大学生数学建模挑战赛题目A题 晶硅片产销策略优化 完整成品 代码 模型 思路 分享