您的位置:首页 > 大数据 > 人工智能

The sample of O_ASYNC and aio_read

2007-09-27 10:20 609 查看
O_ASYNC 和 aio_read 示例代码, 主要用来示范Linux中的信号量.

代码为一个游戏,用*去捕捉小球,
Q --退出
S,s,F,f --加快或减缓小球x或y方向移动速度
z,x--改变小球x或y轴移动方向
i,j,k,l 移动*号.

bounce.h:




/**//* bounce.h


* somet settings for the game


*/


#ifndef bounce_h


#define bounce_h




#include <aio.h>


#include <curses.h>


#include <fcntl.h>


#include <string.h>


#include <unistd.h>




#define BLANK ' '


#define DFL_SYMBOL 'o'


#define PL_SYMBOL '*'


#define TOP_ROW 5


#define BOT_ROW 20


#define LEFT_EDGE 10


#define RIGHT_EDGE 70


#define X_INIT 10 // starting col


#define Y_INIT 10 // starting row


#define TICKS_PER_SEC 50 // affects speed


#define X_TTM 8


#define Y_TTM 8




int done = 0;


int score = 0;




// the ping pong ball




struct ppball...{


int y_pos,x_pos,


y_ttm,x_ttm,


y_ttg,x_ttg,


y_dir,x_dir;


char symbol;


};




// the player




struct player ...{


int y_pos,x_pos;


char symbol;


};




struct aiocb kbcbuf;


struct ppball the_ball;


struct player the_player;




int set_ticker(int);


void draw_wall();


void draw_score();


void draw_player();


void move_player(char);


#endif



bounce2d.c:




/**//* bounce2d 1.0


* bounce a character (defaults is 'o') around the screen


* defined by some paraments


*


* user input:


* s slow down x component, S: slow y component


* f speed up x component, F: speed y component


* Q quit


*


* purpose animation with use control, using aio_read() or O_ASYNC


* timer tick sends SIGALRM, handler does animation


* keybords sends SIGIO


* main only class pause()


* build: cc bounce2d.c set_ticker.c -lcurses -l rt-o bounce2d


*/


#include "bounce.h"






// the main loop




void set_up();


void wrap_up();






int main() ...{


set_up();




while(!done) // the main loop


pause();




wrap_up();




return 0;


}






/**//*


* init structure and other stuff


*/




void set_up() ...{


void ball_move(int);


void enable_kdb_signals();


void setup_aio_buffer();


void on_input(int);




// setup the ball's state


the_ball.y_pos = Y_INIT;


the_ball.x_pos = X_INIT;


the_ball.y_ttg = the_ball.y_ttm = Y_TTM;


the_ball.x_ttg = the_ball.x_ttm = X_TTM;


the_ball.y_dir = 1;


the_ball.x_dir = 1;


the_ball.symbol = DFL_SYMBOL;




done = 0;




initscr(); // setup the screen


noecho();


crmode();


clear();




// setup the player's state and draw the player


the_player.x_pos = LEFT_EDGE;


the_player.y_pos = TOP_ROW;


the_player.symbol = PL_SYMBOL;


draw_player();




// draw the wall


draw_wall();




// setup and draw the score


score = 0;


draw_score();




signal(SIGINT,SIG_IGN);


mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol);


refresh();




signal(SIGIO,on_input); // install a handler




// use O_ASYNC


// enable_kdb_signals(); // turn on kbd signals




// use aio_read


setup_aio_buffer(); // initialize aio ctrl buff


aio_read(&kbcbuf); // place a read quest




signal(SIGALRM,ball_move); // install alarm handler


set_ticker(1000/TICKS_PER_SEC); // send millisecs per tick


}






void wrap_up() ...{


set_ticker(0);


endwin(); // put back normal


}






void ball_move(int signum) ...{


int y_cur,x_cur,moved;




int bounce_or_lose(struct ppball *);




signal(SIGALRM,ball_move); // don't get caught now


y_cur = the_ball.y_pos; // old spot


x_cur = the_ball.x_pos;


moved = 0;






if(the_ball.y_ttm > 0 && --the_ball.y_ttg == 0) ...{


the_ball.y_pos += the_ball.y_dir; // move


the_ball.y_ttg = the_ball.y_ttm; // reset


moved = 1;


}






if(the_ball.x_ttm > 0 && --the_ball.x_ttg == 0) ...{


the_ball.x_pos += the_ball.x_dir; // move


the_ball.x_ttg = the_ball.x_ttm; // reset


moved = 1;


}






if(moved) ...{


mvaddch(y_cur,x_cur,BLANK);


// mvaddch(y_cur,x_cur,BLANK);


mvaddch(the_ball.y_pos,the_ball.x_pos,the_ball.symbol);




if(bounce_or_lose(&the_ball)) ...{


++score;


draw_score();


draw_wall();


}


move(LINES - 1,COLS - 1);


refresh();


}


signal(SIGALRM,ball_move); // for unreliable systems


}






int bounce_or_lose(struct ppball *bp) ...{


int return_val = 0;






if(bp -> y_pos <= TOP_ROW) ...{


bp -> y_dir = 1;




} else if(bp -> y_pos >= BOT_ROW) ...{


bp -> y_dir = -1;


}






if(bp -> x_pos <= LEFT_EDGE) ...{


bp -> x_dir = 1;




} else if(bp -> x_pos >= RIGHT_EDGE) ...{


bp -> x_dir = -1;


}




if(bp -> x_pos == the_player.x_pos


&& bp -> y_pos == the_player.y_pos)


return_val = 1;




return return_val;


}






/**//*


* intstall a handler, tell kernel who to notify on input, enable signals


*/




void enable_kdb_signals() ...{


int fd_flags;




fcntl(0,F_SETOWN,getpid());


fd_flags = fcntl(0,F_GETFL);


fcntl(0,F_SETFL,(fd_flags | O_ASYNC));


}






/**//*


* handler called to when aio_read() has stuff to read


* First check for any errors codes, and if ok, then get the return code


*/




void on_input(int signum) ...{


int c;






while((c = getchar()) != 'Q') ...{


if(c == 'f') --the_ball.x_ttm;


else if(c == 's') ++the_ball.x_ttm;


else if(c == 'F') --the_ball.y_ttm;


else if(c == 'S') ++the_ball.y_ttm;


else if(c == 'z')


the_ball.x_dir = -the_ball.x_dir;


else if(c == 'x')


the_ball.y_dir = -the_ball.y_dir;


else if(c == 'i' || c == 'j' || c == 'k' || c == 'l')


move_player(c);


}




done = 1;


}






/**//*


* set memebers of struct


* First specify args like those for read(fd,buf,num) and offset


* Then specify what to do(send signal) and what signal(SIGIO)


*/




void setup_aio_buffer() ...{


static char input[1]; // 1 char of input




// describe what to read


kbcbuf.aio_fildes = 0; // standard input


kbcbuf.aio_buf = input; // buffer


kbcbuf.aio_nbytes = 1; // number to read


kbcbuf.aio_offset = 0; // offset in file




// describe what to do when read is ready


kbcbuf.aio_sigevent.sigev_notify = SIGEV_SIGNAL;


kbcbuf.aio_sigevent.sigev_signo = SIGIO; // send SIGIO


}






/**//*


* draw the wall when setup.


*/




void draw_wall() ...{


int i,j;




// draw four corner


mvaddch(TOP_ROW - 1,LEFT_EDGE - 1,'+');


mvaddch(BOT_ROW + 1,LEFT_EDGE - 1,'+');


mvaddch(TOP_ROW - 1,RIGHT_EDGE + 1,'+');


mvaddch(BOT_ROW + 1,RIGHT_EDGE + 1,'+');




// draw top row




for(i = LEFT_EDGE,j = TOP_ROW - 1; i <= RIGHT_EDGE; ++i) ...{


mvaddch(j,i,'-');


}




// draw left column




for(i = LEFT_EDGE - 1,j = TOP_ROW; j <= BOT_ROW; ++j) ...{


mvaddch(j,i,'|');


}




// draw botton row




for(i = LEFT_EDGE,j = BOT_ROW + 1; i <= RIGHT_EDGE; ++i) ...{


mvaddch(j,i,'-');


}




// draw right column




for(i = RIGHT_EDGE + 1,j = TOP_ROW; j <= BOT_ROW; ++j) ...{


mvaddch(j,i,'|');


}


}






/**//*


* draw score on the left top corner


*/




void draw_score() ...{


char score_string[100];


sprintf(score_string,"score:%d",score);


move(1,1);


addstr(score_string);


}






/**//*


* draw the player


*/




void draw_player() ...{


mvaddch(the_player.y_pos,the_player.x_pos,the_player.symbol);


}






/**//*


* move the player


*/




void move_player(char input) ...{


mvaddch(the_player.y_pos,the_player.x_pos,BLANK);




switch(input) ...{


case 'i':


if(the_player.y_pos > TOP_ROW)


--the_player.y_pos;


break;


case 'k':


if(the_player.y_pos < BOT_ROW)


++the_player.y_pos;


break;


case 'j':


if(the_player.x_pos > LEFT_EDGE)


--the_player.x_pos;


break;


case 'l':


if(the_player.x_pos < RIGHT_EDGE)


++the_player.x_pos;


break;


}


draw_player();


}



set_ticker.c:


#include <stdio.h>


#include <sys/time.h>


#include <signal.h>






/**//*


* set_ticker.c


* set_ticker( number_of_milliseconds )


* arranges for the interval timer to issue


* SIGALRM's at regular intervals


* returns -1 on error, 0 for ok


*


* arg in milliseconds, converted into micro seoncds


*/






int set_ticker( int n_msecs )




...{


struct itimerval new_timeset;


long n_sec, n_usecs;




n_sec = n_msecs / 1000 ;


n_usecs = ( n_msecs % 1000 ) * 1000L ;






new_timeset.it_interval.tv_sec = n_sec; /**//* set reload */




new_timeset.it_interval.tv_usec = n_usecs; /**//* new ticker value */




new_timeset.it_value.tv_sec = n_sec ; /**//* store this */




new_timeset.it_value.tv_usec = n_usecs ; /**//* and this */




return setitimer(ITIMER_REAL, &new_timeset, NULL);


}







makefile:


bounce2d: bounce2d.c bounce.h set_ticker.c


gcc $^ -l curses -l rt -o $@ -Wall

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐