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)移除定时器。

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

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

  • 相关阅读:
    107. Binary Tree Level Order Traversal II
    103. Binary Tree Zigzag Level Order Traversal
    102. Binary Tree Level Order Traversal
    690. Employee Importance
    1723. Find Minimum Time to Finish All Jobs
    LeetCode 329 矩阵中最长增长路径
    7.2 物理内存管理
    LeetCode 面试题 特定深度节点链表
    LeetCode 100 相同的树
    npm安装包命令详解,dependencies与devDependencies实际区别
  • 原文地址:https://www.cnblogs.com/landmark/p/2517434.html
Copyright © 2011-2022 走看看