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 }
  • 相关阅读:
    The Python Standard Library
    Python 中的round函数
    Python文件类型
    Python中import的用法
    Python Symbols 各种符号
    python 一行写多个语句
    免费SSL证书(https网站)申请,便宜SSL https证书申请
    元宇宙游戏Axie龙头axs分析
    OLE DB provider "SQLNCLI10" for linked server "x.x.x.x" returned message "No transaction is active.".
    The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "xxx.xxx.xxx.xxx" was unable to begin a distributed transaction.
  • 原文地址:https://www.cnblogs.com/joxon/p/5561980.html
Copyright © 2011-2022 走看看