SDL基础使用05(事件系统event)

简介: 本文介绍了如何使用SDL库中的事件系统来控制图片的平铺和前景图的移动,包括响应键盘和鼠标事件调整图片位置和大小。

SDL事件实现背景平铺、前景图移动

#include <iostream>
#include <string>
// SDL_Event事件使用 sdl_event.h
extern "C"
{
#include <SDL.h>
#include <SDL_image.h>
}
#pragma comment(lib, "SDL2.lib")


// 窗口宽度
#define SCREEN_WIDTH  1600
#define SCREEN_HEIGHT  900

// 全局窗口和渲染器
SDL_Window   *window   = nullptr;
SDL_Renderer *renderer = nullptr;

// 加载图片(返回纹理指针)
SDL_Texture* LoadImage(std::string file)
{
    SDL_Texture* tex = nullptr;
    tex = IMG_LoadTexture(renderer, file.c_str());            // 加载图片到纹理
    if (tex == nullptr)
        throw std::runtime_error("Load image failed" + file + IMG_GetError());
    return tex;
}

// 拷贝纹理到渲染器
void copyTextureToRender(int x, int y, SDL_Texture *tex, SDL_Renderer *rend)
{
    SDL_Rect pos;            // srcRect
    pos.x = x;
    pos.y = y;
    SDL_QueryTexture(tex, NULL, NULL, &pos.w, &pos.h);            // 查询纹理的宽高
    SDL_RenderCopy(rend, tex, NULL, &pos);                        // 拷贝纹理到渲染器
}

#undef main
int main(int argc, char** argv)
{
    // 1. 初始化SDL
    if (::SDL_Init(SDL_INIT_EVERYTHING) == -1)
    {
        std::cout << SDL_GetError() << std::endl;
        return 1;
    }

    // 2. 创建窗口
    window = ::SDL_CreateWindow("Event Demo",
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        SCREEN_WIDTH, SCREEN_HEIGHT, 
        SDL_WINDOW_SHOWN);
    if (window == nullptr)
    {
        std::cout << SDL_GetError() << std::endl;
        return 2;
    }

    // 3. 基于窗口创建渲染器
    renderer = ::SDL_CreateRenderer(window, -1,
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (renderer == nullptr)
    {
        std::cout << SDL_GetError() << std::endl;
        return 3;
    }

    // 4. 创建背景和前景纹理            ::IMG_LoadTexture
    SDL_Texture *background = nullptr, *image = nullptr;
    try {
        background = LoadImage("./bk.jpg");
        image = LoadImage("./longong.jpg");
    }
    catch (const std::runtime_error &e) {
        std::cout << e.what() << std::endl;
        return 4;
    }

    bool quit = false;            // 是否退出循环
    SDL_Event e;                // SDL事件
    int iW, iH, x, y;            // x y为前景图pos, iW iH 为前景图宽高
    int dx = 0, dy = 0;            // 前景图偏移pos
    // 主循环(CPU高占用)
    while (!quit)
    {
        // 轮询事件栈e
        while (SDL_PollEvent(&e))        // 循环从事件队列中获取事件
        {
            if (e.type == SDL_QUIT)        // 退出事件
                quit = true;

            if (e.type == SDL_KEYDOWN)    // 键盘事件
            {
                if (e.key.keysym.sym == SDLK_LEFT)    
                {
                    dx -= 10;
                    printf("SDLK_LEFT...");
                }
                else if (e.key.keysym.sym == SDLK_RIGHT)
                {
                    printf("SDLK_RIGHT...");
                    dx += 10;

                }
                else if (e.key.keysym.sym == SDLK_UP)
                {
                    printf("SDLK_UP...");
                    dy -= 10;
                }
                else if (e.key.keysym.sym == SDLK_DOWN)
                {
                    printf("SDLK_DOWN...");
                    dy += 10;
                }

            }

            if (e.type == SDL_MOUSEBUTTONDOWN)             // 用户点击鼠标
                quit = true;

            // 清空渲染器
            SDL_RenderClear(renderer);

            // 在渲染器内平铺背景
            int bW, bH;
            SDL_QueryTexture(background, NULL, NULL, &bW, &bH);        // 查询背景纹理宽高
            for (int y = 0; y <= SCREEN_HEIGHT; y += bH)            // (0, 0) (bW, bH)  防止背景图太小,循环平铺         
            for (int x = 0; x <= SCREEN_WIDTH; x += bW)                
                copyTextureToRender(x, y, background, renderer);    


            // 在渲染器中央放置前景            
            SDL_QueryTexture(image, NULL, NULL, &iW, &iH);            // 查询前景纹理宽高
            x = SCREEN_WIDTH / 2 - iW / 2 + dx;
            y = SCREEN_HEIGHT / 2 - iH / 2 + dy;
            copyTextureToRender(x, y, image, renderer);

            SDL_RenderPresent(renderer);                            // 刷新渲染器显示
        }
    }

    // 释放资源
    if (background)
    {
        SDL_DestroyTexture(background);
    }
    if (image)
    {
        SDL_DestroyTexture(image);
    }
    if (renderer)
    {
        SDL_DestroyRenderer(renderer);
    }
    if (window)
    {
        SDL_DestroyWindow(window);
    }
    SDL_Quit();

    return 0;
}

使用SDL事件实现图片的移动、缩放

#include <iostream>

extern "C"
{
    #include <SDL.h>
}

#undef main
int main()
{
    // 1. 初始化SDL
    SDL_Init(SDL_INIT_EVERYTHING);

    // 2. 创建窗口
    SDL_Window* win = SDL_CreateWindow("yx3sxmeng", 
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
        800, 600, 
        SDL_WINDOW_SHOWN);

    // 3. 创建渲染器
    SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);

    // 4. 将图片加载到surface
    SDL_Surface* surface = SDL_LoadBMP("./Panda.bmp");

    // 5. 根据surface创建纹理
    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);


    // 6. SDL事件循环机制 
    bool quit = false;
    SDL_Event ev;                        // SDL 事件
    SDL_Rect rect = { 0, 0, 800, 600 };    // 图片位置大小(x,y, w,h);
    int sx = 0, sy = 0;                    // 保存经过事件处理后的图片的位置
    while (!quit)
    {
        while (SDL_PollEvent(&ev))        // 从循环队列中获取事件
        {
            switch (ev.type)
            {
            case SDL_QUIT:
                quit = true;
                break;
            case SDL_MOUSEBUTTONDOWN:            // 鼠标按下(记录鼠标按下位置到图片x y的距离)
                sx = ev.button.x + rect.x;
                sy = ev.button.y + rect.y;
                break;
            case SDL_MOUSEMOTION:                            // 鼠标左键按下移动
                if (ev.motion.state & SDL_BUTTON_LMASK)
                {
                    rect.x = ev.motion.x - sx;                // 计算图片应该绘制的xy位置(通过鼠标按下记录的sx xy)
                    rect.y = ev.motion.y - sy;
                }
                break;
            case SDL_KEYDOWN:
                if (ev.key.keysym.sym == SDLK_LEFT)        // 向左移动
                {
                    rect.x -= 10;                    
                    printf("SDLK_LEFT...");
                }
                else if (ev.key.keysym.sym == SDLK_RIGHT)        // 向右移动
                {        
                    rect.x += 10;
                    printf("SDLK_RIGHT...");
                }
                else if (ev.key.keysym.sym == SDLK_UP)            // 放大
                {
                    rect.w += 10;
                    rect.h += 10;
                    printf("SDLK_UP...");
                }
                else if (ev.key.keysym.sym == SDLK_DOWN)        // 缩小
                {
                    rect.w -= 10;
                    rect.h -= 10;
                    printf("SDLK_DOWN...");
                }
                printf("scancode=%d\n", ev.key.keysym.scancode);
                break;
            case SDL_MOUSEWHEEL:
                if (ev.wheel.y > 0)        // 放大
                {
                    rect.h *= 1.1;
                    rect.w *= 1.1;
                }
                if (ev.wheel.y < 0)        // 缩小
                {
                    rect.w /= 1.1;
                    rect.h /= 1.1;
                }
                break;
            }
        }
        // 7. 渲染三部曲
        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, &rect);
        SDL_RenderPresent(renderer);
        SDL_Delay(16);
    }

    // 8. 释放资源 退出
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);

    SDL_Quit();
    return 0;
}
相关文章
|
27天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
4天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
438 17
|
7天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
20天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
7天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
379 2
|
22天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
24天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2600 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
6天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
286 2
|
4天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
106 65
|
24天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1582 17
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码