zoukankan      html  css  js  c++  java
  • 定时器的使用

      如果我们在SDL程序中需要每个一个固定时间去处理一件事情,那么我们需要一个定时器,就像生活中钟表一样可以整点报时,这个功能就是SDL的定时器子系统,你要使用SDL的定时器必须初始化定时器子系统,请看《SDL起动与退出》,SDL定时器比较简单就是一个间隔固定时间的函数调用,如果你要添加一个定时器可以使用函数SDL_AddTimer,其原型为:

    SDL_TimerID SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param);

    其中:函数的返回值SDL_TimerID是一个结构体指针,SDL文档中并没有给出其结构,所以我们只要知道这是一个指向添加的定时器的指针就可以了。

       函数的第一个参数interval是定时器间隔的时间,以毫秒(1秒=1000毫秒)为单位;第二个参数是要执行的函数,也称回调函数,是定时器每个interval时间段调用的函数,不是我们自己调用的,SDL_NewTimerCallback是一个函数指针类型,指明了要调用的函数原型:

    typedef Uint32 (SDLCALL *SDL_NewTimerCallback)(Uint32 interval, void *param);

      要调用的函数的原型满足返回值是Uint32,函数的第一个参数是定时器的时间间隔(一般和SDL_AddTimer的interval一样),第二个参数是需要给函数传递的参数,不需要传参的话可以写NULL。SDL_AddTimer第三个参数也是同样的。

      下面我们做一个SDL电子表,显示当前时间,所需图片如下图所示:

    所需图片 程序效果

       程序代码如下:

     1 /*
     2   功能:Timer的用法
     3   作者:csl
     4   日期:2012-5-24
     5 */
     6 #include <stdio.h> 
     7 #include <stdlib.h> 
     8 #include <time.h>
     9 #include <string.h>
    10 #include <SDL.h>
    11 
    12 //窗口长和宽
    13 #define SCREENWIDTH  280
    14 #define SCREENHEIGH  40
    15 #define BPP 32
    16 
    17 //图片长和宽
    18 #define DIGITALWIDTH 13
    19 #define DIGITALHEIGH 23
    20 
    21 SDL_Surface *gpScreen;//显示表面
    22 SDL_Surface *gpDigitals;//数字的精灵图
    23 SDL_Event myEvent;//事件
    24 
    25 //时间定时器
    26 SDL_TimerID myTime;
    27 const unsigned int INTERVALS = 1000;//1秒 
    28 
    29 SDL_Surface *loadImage(char *aFilename);
    30 void cleanUp();
    31 int cToD(char ch);
    32 SDL_Rect locatePosition(char ch);
    33 Uint32 displayTime(Uint32 interval, void *param);
    34 
    35 int main(int argc,char *argv[])
    36 {
    37     int quit = 0;
    38     SDL_Rect src,dst;
    39     
    40     if((SDL_Init(SDL_INIT_EVERYTHING)==-1)) //初始化视频子系统
    41     {
    42         printf("Unable to init SDL: %s\n", SDL_GetError());
    43         exit(-1);
    44     }
    45     atexit(cleanUp);// 注册cleanUp,当退出时调用,使得退出时程序自动清理
    46 
    47     //创建32位600*480窗口
    48     gpScreen = SDL_SetVideoMode(SCREENWIDTH,SCREENHEIGH, BPP, SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF ||SDL_NOFRAME );
    49     if(!gpScreen) 
    50     { 
    51         exit(1);
    52     }
    53     gpDigitals = loadImage("jpg\\digitals.jpg");
    54     //displayTime(1000,0);
    55 
    56     myTime = SDL_AddTimer(INTERVALS,displayTime,NULL);
    57     if (!myTime)
    58     {
    59         exit(0);
    60     }
    61 
    62     while (!quit)
    63     {
    64         while (SDL_PollEvent(&myEvent))
    65         {
    66             switch (myEvent.type)
    67             {
    68             case SDL_QUIT:
    69                 quit = 1;
    70                 break;
    71             }
    72         }
    73     }
    74     
    75     system("pause"); 
    76     return 0; 
    77 }

      要使用定时器,我们首先要定义一个SDL_TimerID myTime;值得注意的是myTime是一个指针,在主函数里初始化子系统的时候要初始化定时器子系统,所以我们的初始化SDL_Init(SDL_INIT_EVERYTHING),是初始化所有的SDL子系统,然后要首先添加一个定时器,在56行我们添加了定时器,如果不成功则要结束程序。添加以后每隔1秒也就是1000毫秒就会调用回调函数displayTime来显示时间。displayTime代码如下:

    /*--------------------------------------------------------------------
    	函数名:	displayTime
    	参  数:	interval定时器的时间间隔;
    		param需要传递给displayTime函数的参数
    	返回值: 下一次要调用该函数的时间间隔
    	功  能:	定时器回调函数,每隔interval时间段被系统调用
    	备  注:
    ----------------------------------------------------------------------*/
    Uint32 displayTime(Uint32 interval, void *param)
    {
    	struct tm *currentTime;
    	SDL_Rect src;
    	SDL_Rect dst = {(SCREENWIDTH-19*DIGITALWIDTH)/2,(SCREENHEIGH-DIGITALHEIGH)/2,DIGITALWIDTH,DIGITALHEIGH};
    	char strTime[20];
    	int i,len;
    	time_t t = time(NULL);//取得当前系统时间
    
    
    	//取得当前时间,并按格式转换成字符串
    	currentTime = localtime(&t);//将t转换成当地时间
    	strftime(strTime,20,"%Y-%m-%d %H:%M:%S",currentTime);
    
    	//在屏幕中央显示系统时间
    	for (i = 0;strTime[i]!='\0';i++)
    	{
    		src = locatePosition(strTime[i]);
    		SDL_BlitSurface(gpDigitals,&src,gpScreen,&dst);
    		dst.x+=DIGITALWIDTH;
    	}
    	SDL_Flip(gpScreen);
    	
    	return INTERVALS;
    }
    

       在函数里,我们首先要取得当前系统时间,其中time_t是c语言标准库里定义的,是一个整型类型,C语言里用这个类型的变量保存系统时间,实际上保存的是按unix时间格式保存自1970年1月1日0时0分0秒起至现在的总秒数,这个我们很难看懂,所以我们使用了另外一种描述时间的结构struct tm:

    struct tm {   
        int tm_sec; /* 秒–取值区间为[0,59] */   
        int tm_min; /* 分 - 取值区间为[0,59] */   
        int tm_hour; /* 时 - 取值区间为[0,23] */   
        int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */   
        int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */   
        int tm_year; /* 年份,其值从1900开始 */   
        int tm_wday; /* 星期–取值区间为[0,6],其中0代表星期天,1代表星期一,以此类推 */   
        int tm_yday; /* 从每年的1月1日开始的天数–取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */   
        int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负。*/   
    }; 

      我们需要把time_t格式的时间转换成struct tm表示的时间,这个转换函数就是localtime,转换完成后我们就可以得到当前时间了,strftime函数可以将strcut tm时间转换成一个字符串,并且可以指定转换格式:

    %a

    星期的缩略形式

    %A

    星期的完整形式

    %b

    月份的缩略形式

    %B

    月份的完整形式

    %c

    月份的缩略形式

    %d

    月中的第几天(1-31)

    %H

    小时, 24小时格式 (0-23)

    %I

    小时, 12小时格式  (1-12)

    %j

    年中的第几天(1-366)

    %m

    月份 (1-12). Note: 某些版本的Microsoft Visual C++ 可能使用取值范围0-11.

    %M

    分钟(0-59)

    %p

    本地时间的上午或下午(AM or PM)

    %S

    秒钟(0-59)

    %U

    年中的第几周,星期天是一周的第一天

    %w

    星期几的数字表示(0-6, 星期天=0)

    %W

    一年中的第几周,星期天是一周的第一天

    %x

    标准日期字符串

    %X

    标准时间字符串

    %y

    年(0-99)

    %Y

    用CCYY表示的年(如:2004)

    %Z

    时区名

    %%

    百分号

       转换完成后我们得到一个字符格式的当前日期,比如说:2012-05-24 7:47:23,这个串里的每一个字符对对应精灵图里的一个精灵,所以我们就可以根据字符取得它在精灵图里的位置,然后将它显示在窗口上,我们是通过locatePosition函数取得位置的,它的代码如下:

    /*--------------------------------------------------------------------
        函数名:    locatePosition
        参  数:    ch需要确定位置的字符
        返回值: 字符在精灵图中的位置
        功  能:    计算字符在精灵图中的位置
        备  注:
    ----------------------------------------------------------------------*/
    SDL_Rect locatePosition(char ch)
    {
        int y;
        SDL_Rect tmp;
    
        switch(ch)
        {
        case '-':
            tmp.y=0;
            break;
        case ' ':
            tmp.y=DIGITALHEIGH;
            break;
        case ':':
            tmp.y = 2 * DIGITALHEIGH ;
            break;
        default:
            tmp.y=(12-cToD(ch))*DIGITALHEIGH;
        }
    
        tmp.x = 0;
        tmp.w = DIGITALWIDTH;
        tmp.h = DIGITALHEIGH;
    
        return tmp;
    }

      每一副精灵图其x坐标都是0,y坐标可以分门别类加以列举,每一副精灵图的长和宽固定,最后返回一个矩形变量(SDL_Rect)就可以了 。

      我们取得了字符的精灵图,在计算它应该显示在屏幕的位置就可以了,然后将其传输到显示表面上显示就可以了,显示完一副图片后将dst的x坐标加上图片宽度就是下一副图片的位置。

      这样我们就可以每隔1秒钟显示下当前的系统时间了。最后不要忘记调用SDL_RemoveTimer(myTime)移除定时器。

      例子的完整代码请点击这儿下载。  

      各位看官,如果你觉得那里不清楚请给回复,如果你觉得还可以请加关注,加粉丝,谢谢!总之有点反映。

  • 相关阅读:
    断点续传的原理
    中国无线音乐搜索综合测评结果
    从头开始学jsp
    SQLServer和Oracle常用函数对比
    Asp.net程序重启自己
    What Can I do if "The type initializer for 'Emgu.CV.CvInvoke' threw an exception"?
    C++Builder2010多线程调用WebService的问题
    Desmon and Penny
    C#显示摄像头预览
    甲骨文78亿美金并购全球第二芯片商AMD
  • 原文地址:https://www.cnblogs.com/landmark/p/2517434.html
Copyright © 2011-2022 走看看