【linux编程实践教程(Bruce Molay)】第七章 事件驱动编程:编写一个视频游戏

一 视频游戏要做哪些方面

  1. 空间—屏幕的展示与控制
  2. 时间—如何控制物体的移动—什么时间出现什么样的物体
  3. 中断----用户的操作如何进行中断
  4. 同时的做几件事----又控制物体的移动,又实时接收操作的输入

二 屏幕空间的控制

  1. curses库—编译时记得gcc的so库链接方式
    在这里插入图片描述
    mvaddch()函数
  2. refresh如何修改屏幕显示
    在进程中有两个虚拟屏幕:一个是真实屏幕的复制;另一个是工作屏幕。所有函数进行修改都是在工作屏幕中进行的,然后对比真实屏幕cp版和工作屏幕,修改真实屏幕copy版------只传输改变的内容,而不是影像本身在这里插入图片描述

三 时间的精确控制

Alarm

  1. sleep本身就调用了alarm函数----alarm的单位是秒
  2. 系统中的每一个进程都在内核中有一个私有的闹钟,调用alarm函数时会给该闹钟定时,时间一到,内核中的闹钟就会响,然后给进程发送信号,进程利用signal函数对信号进行处理

间隔计时器

  1. alarm的精度不够及一些缺点—》usleep函数(以微秒为单位)----》出现了功能更多的间隔计时器(interval timer)
  2. 每一个进程有三个计时器—每个计时器都有两个设置—一个是初始间隔,还有一个重复间隔时间。
  3. 三个计时器的功能:在这里插入图片描述
  4. 步骤:对itimerval结构体进行赋值设置----->然后通过setitimer函数传给内核中的计时器(哪个计时器由setitimer的参数决定)

四 中断

  1. signal信号有时不能满足任务的需求—比如阻塞信号等等
  2. 所以有了sigaction函数与sigaction结构体
  3. 数据损毁----临界区代码(不能被打断执行的代码称为临界区)被打断就会产生数据损毁-----解决方法:阻塞信号或者忽略
  4. 在sigaction结构体中很重要的一个变量便是sa_mask变量,该变量控制阻塞哪些信号,被阻塞的信号,在进程的任务完成后,会接收被阻塞的信号。信号阻塞详解
  5. sigemptyset----sigaddset----sigfillset----sigdelset------>sigprocmask函数
    在这里插入图片描述
    注意:程序中对资源修改完毕后,要注意对资源的恢复,这是一个好习惯。

五 视频游戏制作

  1. 如何控制代码中不同资源的不同运行速度—通过在程序中虚拟计时器实现—以进程的基本计时器为基准----类似时针分针和秒针
  2. 例如在球的竖直与水平运动中----控制球的斜向运动-----需要为数竖直与水平方向的运动各维持一个结构体,在结构体中虚拟出计时器的两个时间在这里插入图片描述

六 异步输入

  1. 什么是异步:发送一个请求,不必等待,可以去做其他事情
  2. 什么是异步输入:键盘进行输入,输入作为一个信号,不必立即处理(信号阻塞),等待进程空闲,来接收该信号
  3. 键盘的信号控制:
    1. 在这里插入图片描述
    2. aio_read函数+aiocb结构体—将设置好的结构体传给aio_read函数—记得gcc链接时链接rt的动态库

七 总结

  1. 空间:curses库来进行控制
  2. 时间:signal的SIGALRM信号+间隔计时器----设置好信号处理函数,以及计时器设置函数
  3. 信号中断:异步输入—>signal的SIGIO信号
  4. 多过程同时进行:多线程----多信号
#include<stdio.h>
#include<ncurses.h>
#include<signal.h>
#include<sys/time.h>
// 一共三部分:
//1.初始设置;
//      初始设置中:屏幕初始化---》位置速度方向初始化---》往屏幕中添加物体---》添加信号和延时
// 2. 获取终端字符,更改设置 
//   3. 还原设置
#define MSG 'o'
#define BLK ' '
#define TOP 5
#define BOT 20
#define LEFT 10
#define RIGHT 70
struct ppball{
    int y_pos,x_pos,
        y_dir,x_dir,
        y_ttg,x_ttg,
        y_ttm,x_ttm;
    char symb;
}ball;
int row,col,x_dir,y_dir;

int set_itimer(float);
int main(){
    set_up();

    while(1){
        int c=getch();
        if(c=='w')ball.y_ttm--;
        if(c=='s')ball.y_ttm++;
        if(c=='a')ball.x_ttm++;
        if(c=='d')ball.x_ttm--;
        if(c=='q')break;
    }
    echo();
    endwin();
}

void set_up(){
    void ball_move();

     initscr();
    noecho();
    crmode();

   ball.symb=MSG;
   ball.x_dir=ball.y_dir=1;
   ball.x_pos=ball.y_pos=10;
   ball.x_ttg=ball.x_ttm=5;
   ball.y_ttg=ball.y_ttm=8;

   signal(SIGINT,SIG_IGN);
   mvaddch(ball.y_pos,ball.x_pos,ball.symb);
   refresh();

   signal(SIGALRM,ball_move);
   set_itimer(0.005);
}

int set_itimer(float secs){
    struct itimerval tmp;
    int sec=secs/1;//浮点数相除,似乎得到的就是浮点数
    float a=(secs-sec);
    int usec=a*1000000;
    tmp.it_value.tv_sec=sec;
    tmp.it_value.tv_usec=usec;
    tmp.it_interval.tv_sec=sec;
    tmp.it_interval.tv_usec=usec;

    return setitimer(ITIMER_REAL,&tmp,NULL);
}

void ball_move(){
    int y_cur,x_cur,moved;
    signal(SIGALRM,SIG_IGN);
    y_cur=ball.y_pos;
    x_cur=ball.x_pos;
    moved=0;

    if(ball.y_ttm>0&&ball.y_ttg--==1){
        ball.y_pos+=ball.y_dir;
        ball.y_ttg=ball.y_ttm;
        moved=1;
    }
    if(ball.x_ttm>0&&ball.x_ttg--==1){
        ball.x_pos+=ball.x_dir;
        ball.x_ttg=ball.x_ttm;
        moved=1;
    }
    if(moved){
        mvaddch(y_cur,x_cur,BLK);
         mvaddch(y_cur,x_cur,BLK);
        mvaddch(ball.y_pos,ball.x_pos,ball.symb);
        bounce_lose(&ball);
        refresh();
    }
    signal(SIGALRM,ball_move);
}


void bounce_lose(struct ppball*tmp){
    if(tmp->y_pos<=TOP&&tmp->y_dir==-1)tmp->y_dir=1;
    if(tmp->y_pos>=BOT&&tmp->y_dir==1)tmp->y_dir=-1;
    if(tmp->x_pos<=LEFT&&tmp->x_dir==-1)tmp->x_dir=1;
    if(tmp->x_pos>=RIGHT&&tmp->x_dir==1)tmp->x_dir=-1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值