第7章 事件驱动编程:编写一个视频游戏

/*
 * hello.c
 * purpose  show the minimal calls needed to use curses
 * outline  initialize, draw stuff, wait for input, quit
 */

#include <stdio.h>
#include <curses.h>

main()
{
    initscr();              /* turn on curses */
                        /* send requests */
    clear();                /* clear screen */
    move(10, 20);               /* row 10, col 20 */
    addstr("Hello, world");         /* add a string */
    move(LINES-1, 0);           /* move to LL */
    refresh();              /* update the screen */
    getch();                /* wait for user input */
    endwin();               /* trun off curses */
}
/* sleep1.c
 * purpose      show how sleep works
 * usage        sleep1
 * outline      sets handler, sets alarm, pause, then returns
 */
#include <stdio.h>
#include <signal.h>
#define SHHHH

main()
{
    void wakeup(int);

    printf("about to sleep for 4 seconds\n");
    signal(SIGALRM, wakeup);            /* catch it */
    alarm(4);                           /* set clock */
    pause();                            /* freeze here */
    printf("Morning so soon? \n");      /* back to work */
}

void wakeup(int signum)
{
#ifdef SHHHH
    printf("Alarm received from kernel %d\n", signum);
#endif
}
/* set_ticker( number_of_milliseconds )
 * arranges for interval timer to issue SIGALRMs at regular intervals
 * returns -1 on error, 0 for ok
 * arg in milliseconds, converted into whole seconds and microseconds
 * note: set_ticker(0) turns off ticker
 */
#include <stdio.h>
#include <sys/time.h>

int set_ticker(int n_msecs)
{
    struct itimerval new_timeset;
    long n_sec, n_usecs;

    n_sec = n_msecs / 1000;                     /* int part */
    n_usecs = (n_msecs % 1000 ) * 1000L;        /* remainder */

    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);
}
/* ticker_demo.c
 *      demonstrates use of interval timer to generate reqular
 *      signals, which are in turn caught and used to count down
 */
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>

int main()
{
    void countdown(int);

    signal(SIGALRM, countdown);
    if (set_ticker(500) == -1)
        perror("set_ticker");
    else
        while(1)
            pause();

    return 0;
}

void countdown(int signum)
{
    static int num = 10;
    printf("%d..", num--);
    fflush(stdout);
    if(num < 0) {
        printf("DONE! \n");
        exit(0);
    }
}
/* sigactdemo.c
 * purpose:     shows use of sigaction()
 * feature:     blocks ^\ while handling ^C
 *              does not reset ^C handler, so two kill
 */

#include <stdio.h>
#include <signal.h>
#define INPUTLEN 100

main()
{
    struct sigaction    newhandler;             /* new settings */
    sigset_t            blocked;                /* set of blocked sigs */
    void                inthandler();           /* the handler */
    char                x[INPUTLEN];            

    /* load these two members first */
    newhandler.sa_handler   =   inthandler;     /* handler function */
    newhandler.sa_flags     =   SA_RESETHAND | SA_RESTART;  /* options */

    /* then build the list of blocked signals */
    sigemptyset(&blocked);                      /* clear all bits */
    sigaddset(&blocked, SIGQUIT);               /* add SIGQUIT to list */
    newhandler.sa_mask = blocked;               /* store blockmask */

    if (sigaction(SIGINT, &newhandler, NULL) == -1)
        perror("sigaction");
    else
        while (1) {
            fgets(x, INPUTLEN, stdin);
            printf("input: %s", x);
        }
}

void inthandler(int s)
{
    printf("Called with signal %d\n", s);
    sleep(s);
    printf("done handling signal %d\n", s);
}
/* digdemo3.c
 * purpose: show answers to signal questions
 * question1:   does the handler stay in effect after a signal arrives?
 * question2:   what if a signalX arrives while handling signalX?
 * question3:   what if a signalX arrives while handling signalY?
 * quesiong4:   what happens to read() when a signal arrives?
 */

#include <stdio.h>
#include <signal.h>

#define INPUTLEN    100

main(int ac, char *av[])
{
    void    inthandler(int);
    void    quithandler(int);
    char    input[INPUTLEN];
    int     nchars;

    signal(SIGINT, inthandler);         /* set handler */
    signal(SIGQUIT, quithandler);       /* set handler */

    do {
        printf("\nType a message\n");
        nchars = read(0, input, (INPUTLEN - 1));
        if (nchars == -1)
            perror("read returned an error");
        else {
            input[nchars] = '\0';
            printf("You typed: %s", input);
        }
    }
    while (strncmp(input, "quit", 4) != 0);
}

void inthandler(int s)
{
    printf("Received signal %d..waiting\n", s);
    sleep(2);
    printf("Leaving inthandle\n");
}

void quithandler(int s)
{
    printf("Received signal %d..waiting\n", s);
    sleep(3);
    printf("Leaving quithandler\n");
}
/* bounce.h         */

/* some settings for the game */

#define BLANK       '  '
#define DFL_SYMBOL  'o'
#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       5
#define Y_TTM       8

/** 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;
};
/* bounce1d.c
 * purpose      animation with user contolled speed and direction
 * not          the handler does the animation  
 *              the main program reads keyboard input
 * compile      cc bounce1d.c set_ticker.c -lcurses -o bounce1d
 */
#include <stdio.h>
#include <curses.h>
#include <signal.h>

/* some global settings main and the handler use */

#define MESSAGE     "hello"
#define BLANK       "     "

int row;    /* current row */
int col;    /* current column */
int dir;    /* where we are going */

int main()
{
    int delay;                  /* bigger => slower */
    int ndelay;                 /* new delay */
    int c;                      /* user input */
    void    move_msg(int);      /* handler for timer */

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

    row = 10;                   /* start here */
    col = 0;
    dir = 1;                    /* add 1 to row number */
    delay = 200;                /* 200ms = 0.2 seconds */

    move(row, col);             /* get into position */
    addstr(MESSAGE);            /* draw message */
    signal(SIGALRM, move_msg);
    set_ticker(delay);

    while (1) 
    {
        ndelay = 0;
        c = getch();
        if (c == 'Q') break;
        if (c == ' ') dir = -dir;
        if (c == 'f' && delay > 2)  ndelay = delay / 2;
        if (c == 's') ndelay = delay * 2;
        if (ndelay > 0)
            set_ticker(delay = ndelay);
    }
    endwin();
    return 0;
}

void move_msg(int signum)
{
    signal(SIGALRM, move_msg);  /* reset, just in case */
    move(row, col);
    addstr(BLANK);
    col += dir;                 /* move to new colum */
    move(row, col);             /* then set cursor */
    addstr(MESSAGE);            /* redo message */
    refresh();                  /* and show it */

    /*
     * now handle borders 
     */
    if (dir == -1 && col <= 0)
        dir = 1;
    else if (dir == 1 && col + strlen(MESSAGE) >= COLS)
        dir = -1;
}
/* bounce2d 1.0
 * bounce a character (default is 'o') around the screen
 * defined by some parameters
 *
 * user input: s slow down x component, S: slow y component
 *             f speed up x component, F: speed by component
 *             Q quit
 *
 * blocks on read, but timer tick sends SIGALRM caught by ball_move
 * build: cc bounce2d.c set_ticker.c -lcurses -o bounce2d
 */

#include <curses.h>
#include <signal.h>
#include "bounce.h"

struct ppball the_ball;

/** the main loop **/

void set_up();
void wrap_up();

int main()
{
    int c;

    set_up();

    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.x_ttm--;   
        else if (c == 'S')  the_ball.x_ttm++;   
    }

    wrap_up();
}

void set_up()
/*
 * init structure and other stuff
 */
{
    void ball_move(int);

    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;

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

    signal(SIGINT, SIG_IGN);
    mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol);
    refresh();

    signal(SIGALRM, ball_move);
    set_ticker(1000 / TICKS_PER_SEC);           /* send millisecs per tick */
}

void wrap_up()
{
    set_ticker(0);
    endwin();                                   /* put back to normal */
}

void ball_move(int signum)
{
    int     y_cur, x_cur, moved;

    signal(SIGALRM, SIG_IGN);                   /* dont 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-- == 1) {
        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-- == 1) {
        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);
        bounce_or_lose(&the_ball);
        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;
        return_val = 1;
    } else if (bp->y_pos == BOT_ROW) {
        bp->y_dir = -1;
        return_val = 1;
    }
    if (bp->x_pos == LEFT_EDGE) {
        bp->x_dir = 1;
        return_val = 1;
    } else if (bp->x_pos == RIGHT_EDGE) {
        bp->x_dir = -1;
        return_val = 1;
    }

    return return_val;
}
/* set_ticker( number_of_milliseconds )
 * arranges for interval timer to issue SIGALRMs at regular intervals
 * returns -1 on error, 0 for ok
 * arg in milliseconds, converted into whole seconds and microseconds
 * note: set_ticker(0) turns off ticker
 */
#include <stdio.h>
#include <sys/time.h>

int set_ticker(int n_msecs)
{
    struct itimerval new_timeset;
    long n_sec, n_usecs;

    n_sec = n_msecs / 1000;                     /* int part */
    n_usecs = (n_msecs % 1000 ) * 1000L;        /* remainder */

    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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值