对于SDL我也只是一个初学的菜鸟,接下来和大家分享一个

[复制链接]

该用户从未签到

2380

主题

2433

帖子

9139

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
9139
QQ
跳转到指定楼层
楼主
发表于 2017-12-22 15:24:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

想要查看内容赶紧注册登陆吧!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x


突然发现csdn好流氓啊,这是我的一张程序运行的截图啊,里面就被它打上了自己的标签。。。
       从上面的图片我们可以看出,这个程序实现的功能是,当你将鼠标放到那个灰白色的按钮上时,按钮要变色(作为一种交互的表现),当你用鼠标按下按钮时,按钮会显现出凹下去的形态,然后在你拖动按钮往左滑动后灯泡点亮,这就是我们程序实现的简单功能。
下面我们先不谈程序,我们先来一起头脑风暴一下,简单想想我们怎么做、需要什么:
其实我们大家都知道,动画就是一帧一帧的图片叠加的效果,我们要实现这个程序,就需要把图片准备好,那么我们来看一下需要哪些图片
1、首先,从灯泡看起,灯要实现亮起来的要求,那么我们就需要至少两张图,一张是灯没亮时的图片,另一张是灯亮了的图片
2、其次,从按钮看,我们需要的图就更多了,首先将底层的off和on这个显示做成一张图,然后上面用于滑动的按钮要单独分离出做出三张效果图,一张是正常状态下的灰白色,一张是鼠标触碰到按钮后按钮变色,最后一张是鼠标按下去后按钮要显现出凹下去的形态
3、最后,准备一张白色的背景图,这个就比较简单了。
这些图我都已经准备好了,如下图:
                           

               

素材是已经准备好了,那么下面我们进入到程序方面的讨论:
1、首先,我们得给整个画面做一个初始化,也就是哪些东西是程序一运行我们就要展现出来的,我们可以看出,我上面展示的那张图就是初始化的界面图,要做到这我们需要好好了解一下SDL的工作方式。在SDL中,图片是画在渲染器上的,然后在将渲染器“推到“窗口上显示(这些初始化的东西可以在我文章开头提供的链接里了解到的)。
2、其次,我们得管理好鼠标和界面间的交互。在这个程序中,我们要处理的交互还是很多的,鼠标触碰到滑动按钮时按钮需要变色(作为一种交互形式,当然也可以自己设计如何表现),当我们用鼠标点击滑动按钮时,按钮要有凹陷的感觉,当我们鼠标拖动滑动按钮时,按钮要能随鼠标一起移动,当按钮到达边界时灯要亮起来,做到这些就需要我们处理好事件的响应工作。
当然,这些工作我会在代码中用注释的形式进行解释,这样才更利于理解。
首先得声明,要看懂这些代码,一定要了解SDL的简单操作(可以自己查找资料也可以使用我提供的链接)。
对于代码,先声明一句,由于是初学SDL,所以就想到哪写到哪了,没有用类进行处理,多以main函数中比较冗长,如果有机会的话,我后边会做出改进,希望大家见谅。
下面直接上代码:
  1. #include<iostream>
  2. #include<SDL/SDL.h>
  3. #include <string>

  4. using namespace std;

  5. const int SCREEN_WIDTH = 640;
  6. const int SCREEN_HEIGHT = 480;

  7. SDL_Window *window = nullptr;
  8. SDL_Renderer *renderer = nullptr;

  9. //此函数用于加载图像
  10. SDL_Texture* LoadImage(std::string file);

  11. //此函数用于将纹理画到渲染器上
  12. void ApplySurface(int x, int y, SDL_Texture *tex, SDL_Renderer *rend);

  13. //此函数用于显示将要展示的画面,将各个图片画在渲染器上并展示出来
  14. void PresentImage(SDL_Renderer *rend,SDL_Texture *background,SDL_Texture *light,int light_x,int light_y,SDL_Texture *baseButton,
  15.         int baseButton_x,int baseButton_y,SDL_Texture *button,int button_x,int button_y);

  16. int main(int argc, char** argv)
  17. {
  18.     if (SDL_Init(SDL_INIT_EVERYTHING) == -1){
  19.         std::cout << SDL_GetError() << std::endl;
  20.         return 1;
  21.     }

  22.     window = SDL_CreateWindow("LightDemo", SDL_WINDOWPOS_CENTERED,
  23.         SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);  //创建一个绘制图片的窗口
  24.     if (window == nullptr){
  25.         std::cout << SDL_GetError() << std::endl;
  26.         return 2;
  27.     }
  28.     renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED
  29.         | SDL_RENDERER_PRESENTVSYNC);   //创建一个指定到窗口的渲染器
  30.     if (renderer == nullptr){
  31.         std::cout << SDL_GetError() << std::endl;
  32.         return 3;
  33.     }
  34.         //定义我们程序需要用到的图片并加载它们
  35.         SDL_Texture *background = nullptr, *light_off = nullptr,*baseButton=nullptr,*initButton,*onButton,
  36.                         *downButton,*light_on;
  37.     background = LoadImage("bg.bmp");
  38.     light_off = LoadImage("light_off.bmp");
  39.         light_on=LoadImage("light_on.bmp");
  40.         baseButton=LoadImage("base_button.bmp");
  41.         initButton=LoadImage("init_button.bmp");
  42.         onButton=LoadImage("on_button.bmp");
  43.         downButton=LoadImage("down_button.bmp");
  44.        
  45.         //判断图片是否加载成功
  46.     if (background == nullptr || light_off == nullptr||light_on==nullptr||initButton==nullptr||
  47.                 onButton==nullptr||baseButton==nullptr||downButton==nullptr)
  48.         return 4;

  49.         SDL_RenderClear(renderer);   //清空屏幕

  50.         //设置背景图片的放置
  51.     int bW, bH;
  52.     SDL_QueryTexture(background, NULL, NULL, &bW, &bH);
  53.     ApplySurface(0, 0, background, renderer);

  54.         //设置熄灭的灯的放置位置
  55.         int iW, iH;
  56.     SDL_QueryTexture(light_off, NULL, NULL, &iW, &iH);
  57.     int light_x = SCREEN_WIDTH / 2 - iW / 2;
  58.     int light_y = SCREEN_HEIGHT / 3 - iH / 2;
  59.     ApplySurface(light_x, light_y, light_off, renderer);

  60.         //设置基础开关的位置
  61.         int buttonW,buttonH;
  62.         SDL_QueryTexture(baseButton,NULL,NULL,&buttonW,&buttonH);
  63.         int baseButton_x=SCREEN_WIDTH/2-buttonW/2;
  64.         int baseButton_y=SCREEN_WIDTH/3*2-2*buttonH;
  65.         ApplySurface(baseButton_x,baseButton_y,baseButton,renderer);

  66.         //设置开关滑动按钮的位置
  67.         int initButtonW,initButtonH;
  68.         SDL_QueryTexture(initButton,NULL,NULL,&initButtonW,&initButtonH);
  69.         //滑动按钮右边界的坐标
  70.         int moveToRight_x=baseButton_x+0.75*buttonW-initButtonW/2;
  71.         int moveToRight_y=baseButton_y+buttonH/2-initButtonH/2;
  72.         //滑动按钮左边界的坐标
  73.         int moveToLeft_x=baseButton_x+0.25*buttonW-initButtonW/2;
  74.         int moveToLeft_y=baseButton_y+buttonH/2-initButtonH/2;
  75.         ApplySurface(moveToRight_x,moveToRight_y,initButton,renderer);


  76.         SDL_RenderPresent(renderer);
  77. //    SDL_Delay(10000);

  78.         SDL_Event e;
  79.         bool quit=false;    //用于标记用户是否想退出程序
  80.         int preMouseX,preMouseY;
  81.         int mouse_x,mouse_y;  
  82.         bool mouseDown=false;   //此变量用于指示鼠标是否一直按着没有松开
  83.         bool moveTo=false;  //此变量用于表示滑动按钮可以移动的方向,false代表向左移动,true代表向右移动
  84.         int curButton_x=moveToRight_x;  //此变量代表滑动按钮X轴方向的坐标
  85.         int curButton_y=moveToRight_y;
  86.         while(!quit)
  87.         {
  88.                 while(SDL_PollEvent(&e))
  89.                 {
  90.                         switch(e.type)
  91.                         {
  92.             //此种情况是退出程序用的,当你点击窗口的红X时就会关闭界面
  93.                         case SDL_QUIT:   
  94.                                 quit=true;
  95.                                 break;
  96.                         //此处处理的是鼠标按下事件
  97.                         case SDL_MOUSEBUTTONDOWN:   
  98.                                 mouseDown=true;
  99.                                 preMouseX=e.button.x;
  100.                                 preMouseY=e.button.y;
  101.                             //当鼠标在当前按钮的区域中时,此if语句得到执行
  102.                                 if(preMouseX>=curButton_x&&preMouseX<=curButton_x+initButtonW&&preMouseY>=curButton_y&&preMouseY<=curButton_y+initButtonH)
  103.                                 {
  104.                                         //当按钮位于最左面时,灯亮
  105.                                         if(curButton_x==moveToLeft_x)
  106.                                         {
  107.                                                 PresentImage(renderer,background,light_on,light_x,light_y,baseButton,baseButton_x,baseButton_y,downButton,
  108.                                                         curButton_x,curButton_y);
  109.                                         }
  110.                                         else //当按钮不在最左面时,画灯不亮的图
  111.                                         {
  112.                                                 PresentImage(renderer,background,light_off,light_x,light_y,baseButton,baseButton_x,baseButton_y,downButton,
  113.                                                         curButton_x,curButton_y);
  114.                                         }
  115.                                 }
  116.                                 break;
  117.                          //鼠标弹起操作
  118.                         case SDL_MOUSEBUTTONUP:     
  119.                                 mouseDown=false;   //表示用户鼠标点击已经松开了
  120.                                 break;
  121.                         //鼠标移动操作
  122.                         case SDL_MOUSEMOTION:
  123.                                 //记录鼠标移动时的坐标
  124.                                 mouse_x=e.motion.x;  
  125.                                 mouse_y=e.motion.y;
  126.                                 if(!mouseDown)   //此时处理的是鼠标有可能放到滑动按钮上的情况
  127.                                 {
  128.                                         if(curButton_x==moveToRight_x)
  129.                                         {
  130.                                                 //此if语句在鼠标在按钮区域内且点击了按钮时执行,此时会刷新窗口,将按钮换成变色的按钮
  131.                                                 if(mouse_x>=moveToRight_x&&mouse_x<=moveToRight_x+initButtonW&&mouse_y>=moveToRight_y&&mouse_y<=moveToRight_y+initButtonH)
  132.                                                 {
  133.                                                         PresentImage(renderer,background,light_off,light_x,light_y,baseButton,baseButton_x,baseButton_y,onButton,
  134.                                                          curButton_x,moveToRight_y);
  135.                                                        
  136.                                                 }
  137.                                                 else  //此时表示鼠标点击在了空白区域,并不对它做出什么反应,将初始化的按钮画在窗口
  138.                                                 {
  139.                                                         PresentImage(renderer,background,light_off,light_x,light_y,baseButton,baseButton_x,baseButton_y,initButton,
  140.                                                          curButton_x,moveToRight_y);
  141.                                                 }
  142.                                         }
  143.                                         //此if语句执行的操作和上一个相似
  144.                                         if(curButton_x==moveToLeft_x)
  145.                                         {
  146.                                                 if(mouse_x>=moveToLeft_x&&mouse_x<=moveToLeft_x+initButtonW&&mouse_y>=moveToLeft_y&&mouse_y<=moveToLeft_y+initButtonH)
  147.                                                 {
  148.                                                         PresentImage(renderer,background,light_on,light_x,light_y,baseButton,baseButton_x,baseButton_y,onButton,
  149.                                                         curButton_x,moveToLeft_y);
  150.                                                 }
  151.                                                 else
  152.                                                 {
  153.                                                         PresentImage(renderer,background,light_on,light_x,light_y,baseButton,baseButton_x,baseButton_y,initButton,
  154.                                                         curButton_x,moveToLeft_y);
  155.                                                 }
  156.                                         }
  157.                                 }
  158.                                 else  //此处处理的是鼠标拖动情况
  159.                                 {
  160.                                         if(!moveTo)   //当moveTo为false时执行,此时表示滑动按钮向左移动的操作
  161.                                         {
  162.                                                 //当鼠标位于滑动按钮区域时
  163.                                                 if(mouse_x>=curButton_x&&mouse_x<=curButton_x+initButtonW&&mouse_y>=curButton_y&&mouse_y<=curButton_y+initButtonH)
  164.                                                 {
  165.                                                         if(mouse_x>=preMouseX)  //当鼠标往反方向移动时,不做操作
  166.                                                                 break;
  167.                                                         curButton_x+=mouse_x-preMouseX;  //移动后的button的x坐标位置
  168.                                                         if(curButton_x<moveToLeft_x)  //当鼠标移动后的距离超过了滑动按钮可移动的位置,便不再改变其位置
  169.                                                         {
  170.                                                                 moveTo=true;   //滑动按钮已经移动到最左端,将移动设置为可以向右移动
  171.                                                                 curButton_x=moveToLeft_x;  //将滑动按钮的位置设置为边界值
  172.                                                                 PresentImage(renderer,background,light_on,light_x,light_y,baseButton,baseButton_x,baseButton_y,initButton,
  173.                                                               curButton_x,curButton_y);
  174.                                                         }
  175.                                                         else  //滑动按钮在鼠标拖动下的实时移动
  176.                                                         {
  177.                                                                 PresentImage(renderer,background,light_off,light_x,light_y,baseButton,baseButton_x,baseButton_y,downButton,
  178.                                                             curButton_x,curButton_y);
  179.                                                                 SDL_Delay(80);  //使滑动按钮的滑动速度慢些
  180.                                                         }
  181.                                                 }
  182.                                      }
  183.                                         else   //滑动按钮向右移动的操作
  184.                                         {
  185.                                                 if(mouse_x>=curButton_x&&mouse_x<=curButton_x+initButtonW&&mouse_y>=curButton_y&&mouse_y<=curButton_y+initButtonH)
  186.                                                 {
  187.                                                         SDL_RenderClear(renderer);
  188.                                                         if(mouse_x<=preMouseX)
  189.                                                                 break;
  190.                                                         curButton_x+=mouse_x-preMouseX;  //移动后的button的x坐标位置
  191.                                                         if(curButton_x>moveToRight_x)  //当鼠标移动后的距离超过了滑动按钮可移动的位置,便不再改变其位置
  192.                                                         {
  193.                                                                 moveTo=false;   //滑动按钮已经移动到最右端,将移动设置为可以向左移动
  194.                                                                 curButton_x=moveToRight_x;  //将滑动按钮的位置设置为边界值
  195.                                                                 PresentImage(renderer,background,light_off,light_x,light_y,baseButton,baseButton_x,baseButton_y,initButton,
  196.                                                              curButton_x,curButton_y);
  197.                                                         }
  198.                                                         else  //滑动按钮在鼠标拖动下的实时移动
  199.                                                         {
  200.                                                                 PresentImage(renderer,background,light_on,light_x,light_y,baseButton,baseButton_x,baseButton_y,downButton,
  201.                                                              curButton_x,curButton_y);
  202.                                                                 SDL_Delay(50);  //使滑动按钮的滑动速度慢些
  203.                                                         }
  204.                                                 }
  205.                                         }
  206.                                 }
  207.                                 break;
  208.                                
  209.                         default:
  210.                                 break;
  211.                         }
  212.                 }
  213.         }
  214.         //做好善后工作,释放掉资源
  215.         SDL_DestroyTexture(background);
  216.     SDL_DestroyTexture(light_off);
  217.         SDL_DestroyTexture(light_on);
  218.     SDL_DestroyTexture(baseButton);
  219.         SDL_DestroyTexture(initButton);
  220.     SDL_DestroyTexture(onButton);
  221.         SDL_DestroyTexture(downButton);
  222.     SDL_DestroyRenderer(renderer);
  223.     SDL_DestroyWindow(window);

  224.     SDL_Quit();
  225.         return 0;
  226. }

  227. SDL_Texture* LoadImage(std::string file)
  228. {
  229.     SDL_Surface *loadedImage = nullptr;
  230.     SDL_Texture *texture = nullptr;
  231.   
  232.     loadedImage = SDL_LoadBMP(file.c_str());   //加载图层
  233.     if (loadedImage != nullptr)
  234.         {
  235.         texture = SDL_CreateTextureFromSurface(renderer, loadedImage);   //将图层转化为纹理
  236.         SDL_FreeSurface(loadedImage);   //释放掉图层
  237.     }
  238.     else
  239.         std::cout << SDL_GetError() << std::endl;
  240.     return texture;
  241. }

  242. //此函数用于将纹理画到渲染器上
  243. void ApplySurface(int x, int y, SDL_Texture *tex, SDL_Renderer *rend)
  244. {
  245.     SDL_Rect pos;
  246.         //x,y是图片左上角的坐标
  247.     pos.x = x;
  248.     pos.y = y;
  249.     SDL_QueryTexture(tex, NULL, NULL, &pos.w, &pos.h);

  250.     SDL_RenderCopy(rend, tex, NULL, &pos);   //将纹理tex画到渲染器rend
  251. }

  252. void PresentImage(SDL_Renderer *rend,SDL_Texture *background,SDL_Texture *light,int light_x,int light_y,SDL_Texture *baseButton,
  253.         int baseButton_x,int baseButton_y,SDL_Texture *button,int button_x,int button_y)
  254. {
  255.         SDL_RenderClear(renderer);   //清空屏幕
  256.         ApplySurface(0, 0, background, renderer);
  257.         ApplySurface(light_x, light_y, light, renderer);
  258.         ApplySurface(baseButton_x,baseButton_y,baseButton,renderer);
  259.         ApplySurface(button_x,button_y,button,renderer);
  260.         SDL_RenderPresent(renderer);
  261. }
复制代码
完整程序下载
游客,如果您要查看本帖隐藏内容请回复

分享到:  QQ好友和群QQ好友和群
收藏收藏
回复

使用道具 举报

快速回复高级模式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表