SDL基础

news2025/4/19 15:06:06

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 Window
    window = 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);  // 延迟10000ms

    SDL_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); //拷贝纹理到CPU

        SDL_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 pointer
        SDL_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 title
                    SDL_WINDOWPOS_UNDEFINED,           // initial x position
                    SDL_WINDOWPOS_UNDEFINED,           // initial y position
                    640,                               // width, in pixels
                    480,                               // height, in pixels
                    SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS// flags - see below
                    );

        // Check that the window was successfully created
        if (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 renderer
        if (renderer)
            SDL_DestroyRenderer(renderer);

        // Close and destroy the window
        if (window)
            SDL_DestroyWindow(window);

        // Clean up
        SDL_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_lock
    SDL_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.coloradmin.cn/o/2337139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十三种通信接口芯片——《器件手册--通信接口芯片》

目录 通信接口芯片 简述 基本功能 常见类型 应用场景 详尽阐述 1 RS485/RS422芯片 1. RS485和RS422标准 2. 芯片功能 3. 典型芯片及特点 4. 应用场景 5. 设计注意事项 6. 选型建议 2 RS232芯片 1. RS232标准 2. 芯片功能 3. 典型芯片及特点 4. 应用场景 5. 设计注意事项 6…

反转一个字符串

用数组栈实现 void Reverse(char *C, int len) {top -1;for(int i 0; i < len; i){push(C[i]);}for(int i 0; i < len; i){C[i] Top();pop();} } 全部函数 #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAX_SIZE 101int …

【限流算法】计数器、漏桶、令牌桶算法

1 计数器 使用计数器实现限流&#xff0c;可限制在指定时间间隔内请求数小于阈值的情况&#xff0c;但存在临界问题。如图1-17所示&#xff0c;假设每分钟系统限流500个请求&#xff0c;在XX:00:59时刻系统接收到500个请求&#xff0c;在XX:01:00时刻系统又接收到500个请求&am…

秘密任务 2.0:如何利用 WebSockets + DTOs 设计实时操作

在之前的文章中&#xff0c;我们探讨了为什么 DTO 是提升 API 效率和安全性的秘密武器。现在&#xff0c;我们进入了一个全新的场景——我们将深入探讨如何通过 WebSockets DTOs 实现实时操作&#xff01; Agent X 正在进行一项高风险的卧底任务。突然&#xff0c;总部更新了…

SpringAI+DeepSeek大模型应用开发——3 SpringAI简介

SpringAI整合了全球&#xff08;主要是国外&#xff09;的大多数大模型&#xff0c;而且对于大模型开发的三种技术架构都有比较好的封装和支持&#xff0c;开发起来非常方便&#xff1b; 不同的模型能够接收的输入类型、输出类型不一定相同。SpringAI根据模型的输入和输出类型…

MySQL GTID集合运算函数总结

MySQL GTID 有一些运算函数可以帮助我们在运维工作中提高运维效率。 1 GTID内置函数 MySQL 包含GTID_SUBSET、GTID_SUBTRACT、WAIT_FOR_EXECUTED_GTID_SET、WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 4个内置函数&#xff0c;用于GTID集合的基本运算。 1.1 GTID_SUBSET(set1,set2) …

从“链主”到“全链”:供应链数字化转型的底层逻辑

1. 制造业与供应链数字化转型的必然性 1.1. 核心概念与战略重要性 制造业的数字化转型&#xff0c;是利用新一代数字技术&#xff08;如工业互联网、人工智能、大数据、云计算、边缘计算等&#xff09;对制造业的整体价值链进行根本性重塑的过程。这不仅涉及技术的应用&#…

定制化突围:遨游防爆手机的差异化竞争策略

在石油、化工、矿山等危险作业场景中&#xff0c;随着工业智能化与安全生产需求的升级&#xff0c;行业竞争逐渐从单一产品性能的比拼转向场景化解决方案的深度较量。遨游通讯以九重防爆标准为技术底座&#xff0c;融合多模稳控系统与全景前瞻架构&#xff0c;开辟出"千行…

士兵乱斗(贪心)

问题 B: 士兵乱斗 - USCOJ

【C++面向对象】封装(下):探索C++运算符重载设计精髓

&#x1f525;个人主页 &#x1f525; &#x1f608;所属专栏&#x1f608; 每文一诗 &#x1f4aa;&#x1f3fc; 年年岁岁花相似&#xff0c;岁岁年年人不同 —— 唐/刘希夷《代悲白头翁》 译文&#xff1a;年年岁岁繁花依旧&#xff0c;岁岁年年看花之人却不相同 目录 C运…

JVM初探——走进类加载机制|三大特性 | 打破双亲委派SPI机制详解

目录 JVM是什么&#xff1f; 类加载机制 Class装载到JVM的过程 装载&#xff08;load&#xff09;——查找和导入class文件 链接&#xff08;link&#xff09;——验证、准备、解析 验证&#xff08;verify&#xff09;——保证加载类的正确性 准备&#xff08;Prepare&…

UML-饮料自助销售系统(无法找零)序列图

一、题目&#xff1a; 在饮料自动销售系统中&#xff0c;顾客选择想要的饮料。系统提示需要投入的金额&#xff0c;顾客从机器的前端钱币口投入钱币&#xff0c;钱币到达钱币记录仪&#xff0c;记录仪更新自己的选择。正常时记录仪通知分配器分发饮料到机器前端&#xff0c;但可…

爬虫利器SpiderTools谷歌插件教程v1.0.0!!!web端JavaScript环境检测!!!

SpiderTools谷歌插件教程v1.0.0 一、SpiderTools简介二、下载通道三、插件介绍四、插件使用五、工具函数使用 一、SpiderTools简介 SpiderTools主要用于检测和监控网页的JavaScript运行环境。该插件可以帮助开发者更好地查看网页运行环境&#xff0c;特别是在处理复杂的前端环…

计算机视觉算法实战——基于YOLOv8的农田智能虫情测报灯害虫种类识别系统开发指南

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​ ​​​​​​​​​ ​​ 一、智能虫情监测领域概述 1.1 农业虫害防治现状 全球每年因虫害造成的粮食损失达20%-40%&#xff0c;我…

14-算法打卡-哈希表-基本概念-第十四天

1 基本概念 1.1 哈希表 百度百科解释&#xff1a; 散列表&#xff08;Hash table&#xff0c;也叫哈希表&#xff09;&#xff0c;是根据关键码值(Key value)而直接进行访问的数据结构。也就是说&#xff0c;它通过把关键码值映射到表中一个位置来访问记录&#xff0c;以加快…

第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解

赛时参加的是Python组&#xff0c;这是赛后写的题解&#xff0c;还有两题暂时还不会&#xff0c;待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案&#xff1a;1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…

英文查重的时候参考文献显示重复是怎么回事?

像上图这样参考文献部分有颜色的情况&#xff0c;是属于参考文献没有排除干净的问题。 如何解决这样的问题&#xff1f; 首先第一步&#xff0c;先确认该报告是不是排除参考文献的版本&#xff1b; 第二步&#xff0c;如果是排除参考文献的版本&#xff0c;且参考文献仍然有…

八股文---MySQl(3)

目录 12.事务的特性是什么&#xff1f;可以详细说一下吗&#xff1f; 回答 13并发事务带来哪些问题&#xff1f;怎么解决这些问题呢&#xff1f;MySQL的默认隔离级别是&#xff1f; 脏读&#xff1a;一个事务读到另外一个事务还没有提交的数据。 不可重复读&#xff1a;一个…

基于labview的钢琴程序设计

部分程序如下 按照上图子vi更改输出频率即可 若需完整程序可以联系我

基于CNN+ViT的蔬果图像分类实验

本文只是做一个简单融合的实验&#xff0c;没有任何新颖&#xff0c;大家看看就行了。 1.数据集 本文所采用的数据集为Fruit-360 果蔬图像数据集&#xff0c;该数据集由 Horea Mureșan 等人整理并发布于 GitHub&#xff08;项目地址&#xff1a;Horea94/Fruit-Images-Datase…