zoukankan      html  css  js  c++  java
  • 用 SDL2 处理精灵图

    上面就是一个精灵图,由多个固定间隔的图标组成。利用精灵图的好处就是不必将图标逐个读入内存进行操作。我们可以将精灵图中需要的部分用一个个矩形截取下来,然后再输出到渲染器上。

    环境:SDL2 + VC++2015

    下面的代码将打开sprite.png,并对相应的操作做出响应。

    sprite.png

      1 #include <stdexcept>
      2 #include <string>
      3 #include <iostream>
      4 #include "SDL.h"
      5 #include "SDL_image.h"
      6 
      7 //屏幕宽度
      8 const int SCREEN_WIDTH = 500;
      9 const int SCREEN_HEIGHT = 500;
     10 
     11 //全局窗口和渲染器
     12 SDL_Window *window = nullptr;
     13 SDL_Renderer *renderer = nullptr;
     14 
     15 //记录SDL错误
     16 void logSDLError(std::ostream &os, const std::string &msg)
     17 {
     18     os << msg << " error: " << SDL_GetError() << std::endl;
     19 }
     20 
     21 //加载图像材质
     22 SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren)
     23 {
     24     SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
     25     if (texture == nullptr) logSDLError(std::cout, "LoadTexture");
     26     return texture;
     27 }
     28 
     29 
     30 //根据坐标生成截取区域并复制输出到渲染器
     31 void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, SDL_Rect *clip = nullptr)
     32 {
     33     //目标截面区域初始化,提供目标在渲染器的坐标
     34     SDL_Rect dst; dst.x = x; dst.y = y;
     35     //源截面区域不为空,将其值赋给目标截面
     36     if (clip != nullptr) { dst.w = clip->w; dst.h = clip->h; }
     37     //将截面输出到渲染器
     38     SDL_RenderCopy(ren, tex, clip, &dst);
     39 }
     40 
     41 int main(int argc, char** argv)
     42 {
     43     //初始化SDL
     44     if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
     45     {
     46         std::cout << SDL_GetError() << std::endl;
     47         return 1;
     48     }
     49 
     50     //创建窗口
     51     window = SDL_CreateWindow("Lesson 5",
     52         SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
     53         SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
     54     if (window == nullptr)
     55     {
     56         std::cout << SDL_GetError() << std::endl;
     57         return 2;
     58     }
     59 
     60     //创建渲染器
     61     renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
     62     if (renderer == nullptr)
     63     {
     64         std::cout << SDL_GetError() << std::endl;
     65         return 3;
     66     }
     67 
     68     //创建纹理
     69     SDL_Texture *image = nullptr;
     70     try
     71     {
     72         image = loadTexture("sprite.png", renderer);
     73     }
     74     catch (const std::runtime_error &e)
     75     {
     76         std::cout << e.what() << std::endl;
     77         return 4;
     78     }
     79 
     80     //iW,iH 表示截面宽高
     81     int iW = 100, iH = 100;
     82     //x,y 分别为截面在渲染器输出的坐标
     83     int x = SCREEN_WIDTH / 2 - iW / 2;
     84     int y = SCREEN_HEIGHT / 2 - iH / 2;
     85 
     86     //为精灵图设置截面
     87     SDL_Rect clips[4];
     88 
     89     //初始化截面信息
     90     for (int i = 0; i < 4; ++i)
     91     {
     92         clips[i].x = i / 2 * iW;
     93         clips[i].y = i % 2 * iH;
     94         clips[i].w = iW;
     95         clips[i].h = iH;
     96     }
     97 
     98     //表示将要输出的截面
     99     int useClip = 0;
    100 
    101     SDL_Event e;
    102     bool quit = false;
    103     //主循环
    104     while (!quit)
    105     {
    106         //事件轮询
    107         while (SDL_PollEvent(&e))
    108         {
    109             //按右上角的X退出
    110             if (e.type == SDL_QUIT) quit = true;
    111 
    112             //点击鼠标随机输出截面
    113             if (e.type == SDL_MOUSEBUTTONDOWN) useClip = rand() % 4;
    114 
    115             //使用数字键决定输出截面,分别有1,2,3,4
    116             if (e.type == SDL_KEYDOWN)
    117             {
    118                 switch (e.key.keysym.sym)
    119                 {
    120                 case SDLK_1:
    121                 case SDLK_KP_1:
    122                     useClip = 0;
    123                     break;
    124                 case SDLK_2:
    125                 case SDLK_KP_2:
    126                     useClip = 1;
    127                     break;
    128                 case SDLK_3:
    129                 case SDLK_KP_3:
    130                     useClip = 2;
    131                     break;
    132                 case SDLK_4:
    133                 case SDLK_KP_4:
    134                     useClip = 3;
    135                     break;
    136                 case SDLK_ESCAPE:
    137                     quit = true;
    138                     break;
    139                 default:
    140                     break;
    141                 }
    142             }
    143         }
    144         //清空渲染器
    145         SDL_RenderClear(renderer);
    146         //绘制材质
    147         renderTexture(image, renderer, x, y, &clips[useClip]);
    148         //呈现渲染器
    149         SDL_RenderPresent(renderer);
    150     }
    151 
    152     //释放资源
    153     SDL_DestroyTexture(image);
    154     SDL_DestroyRenderer(renderer);
    155     SDL_DestroyWindow(window);
    156 
    157     SDL_Quit();
    158 
    159     return 0;
    160 }
  • 相关阅读:
    关于Java集合框架,这篇讲的还算不错了,建议大家看看!
    其实SQL优化调优,就跟吃饭喝水一样简单,教你抓住SQL的本质!
    深度分析ReentrantLock源码及AQS源码,从入门到入坟,建议先收藏!
    建议收藏,从零开始创建一个Activiti工作流,手把手教你完成
    这个厉害了,ssm框架整合全过程,建议收藏起来好好看看
    阿里技术专家深入讲解,SpringMVC入门到进阶,看这一篇就够了
    python3.6:AttributeError: 'generator' object has no attribute 'next'
    【转】modulenotfounderror: no module named 'matplotlib._path'问题的解决
    sublime中使用插件anaconda而在代码中出现方框
    Linux上用sublime编辑Python时候出现"SyntaxError: Non-ASCII character ‘xe5′ in file"的问题
  • 原文地址:https://www.cnblogs.com/joxon/p/5561980.html
Copyright © 2011-2022 走看看