⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.c

📁 事件驱动程序设计很好的框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** Product: "Fly'n'Shoot" game example* Last Updated for Version: 4.0.00* Date of the Last Update:  Apr 06, 2008**                    Q u a n t u m     L e a P s*                    ---------------------------*                    innovating embedded systems** Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.** This software may be distributed and modified under the terms of the GNU* General Public License version 2 (GPL) as published by the Free Software* Foundation and appearing in the file GPL.TXT included in the packaging of* this file. Please note that GPL Section 2[b] requires that all works based* on this software must also be made publicly available under the terms of* the GPL ("Copyleft").** Alternatively, this software may be distributed and modified under the* terms of Quantum Leaps commercial licenses, which expressly supersede* the GPL and are specifically designed for licensees interested in* retaining the proprietary status of their code.** Contact information:* Quantum Leaps Web site:  http://www.quantum-leaps.com* e-mail:                  info@quantum-leaps.com*****************************************************************************/#include "qp_port.h"#include "game.h"#include "bsp.h"#include <string.h>                           /* for memmove() and memcpy() */Q_DEFINE_THIS_FILE/* Tunnel Active Object ....................................................*/typedef struct TunnelTag {    QActive super;                              /* extend the QActive class */    QTimeEvt blinkTimeEvt;                       /* time event for blinking */    QTimeEvt screenTimeEvt;                /* time event for screen changes */    QHsm *mines[GAME_MINES_MAX];                            /* active mines */    QHsm *mine1_pool[GAME_MINES_MAX];    QHsm *mine2_pool[GAME_MINES_MAX];    uint8_t blink_ctr;                                     /* blink counter */    uint8_t last_mine_x;    uint8_t last_mine_y;    uint8_t wall_thickness_top;    uint8_t wall_thickness_bottom;    uint8_t minimal_gap;} Tunnel;                                       /* the Tunnel active object */static QState Tunnel_initial              (Tunnel *me, QEvent const *e);static QState Tunnel_final                (Tunnel *me, QEvent const *e);static QState Tunnel_active               (Tunnel *me, QEvent const *e);static QState Tunnel_playing              (Tunnel *me, QEvent const *e);static QState Tunnel_demo                 (Tunnel *me, QEvent const *e);static QState Tunnel_game_over            (Tunnel *me, QEvent const *e);static QState Tunnel_screen_saver         (Tunnel *me, QEvent const *e);static QState Tunnel_screen_saver_n_pixels(Tunnel *me, QEvent const *e);static QState Tunnel_screen_saver_1_pixel (Tunnel *me, QEvent const *e);/* Helper functions ........................................................*/static void Tunnel_advance(Tunnel *me);static void Tunnel_plantMine(Tunnel *me);static void Tunnel_addImageAt(Tunnel *me, uint8_t bmp,                              uint8_t x, int8_t y);static void Tunnel_dispatchToAllMines(Tunnel *me, QEvent const *e);static uint8_t Tunnel_isWallHit(Tunnel *me, uint8_t bmp,                                uint8_t x_pos, uint8_t y_pos);static void randomSeed(uint32_t seed);static uint32_t random(void);static Tunnel l_tunnel;    /* the sole instance of the Tunnel active object *//* global objects ----------------------------------------------------------*/QActive * const AO_Tunnel = (QActive *)&l_tunnel;/*opaque pointer to Tunnel *//* local objects -----------------------------------------------------------*/static uint32_t l_rnd;                                       /* random seed */static uint8_t l_walls[GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8];static uint8_t l_frame[GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8];/*..........................................................................*/void Tunnel_ctor(void) {    uint8_t n;    Tunnel *me = &l_tunnel;    QActive_ctor(&me->super, (QStateHandler)&Tunnel_initial);    QTimeEvt_ctor(&me->blinkTimeEvt,  BLINK_TIMEOUT_SIG);    QTimeEvt_ctor(&me->screenTimeEvt, SCREEN_TIMEOUT_SIG);    for (n = 0; n < GAME_MINES_MAX; ++n) {        me->mine1_pool[n] = Mine1_ctor(n); /* instantiate Mine1 in the pool */        me->mine2_pool[n] = Mine2_ctor(n); /* instantiate Mine2 in the pool */        me->mines[n] = (QHsm *)0;                     /* mine 'n' is unused */    }    me->last_mine_x = 0;   /* the last mine at the right edge of the tunnel */    me->last_mine_y = 0;}/* HSM definition ----------------------------------------------------------*//*..........................................................................*/QState Tunnel_initial(Tunnel *me, QEvent const *e) {    uint8_t n;    (void)e;                  /* avoid the "unreferenced parameter" warning */    for (n = 0; n < GAME_MINES_MAX; ++n) {        QHsm_init(me->mine1_pool[n], (QEvent *)0);/*initial tran. for Mine1 */        QHsm_init(me->mine2_pool[n], (QEvent *)0);/*initial tran. for Mine2 */    }    randomSeed(1234);                   /* seed the pseudo-random generator */    QActive_subscribe((QActive *)me, TIME_TICK_SIG);    QActive_subscribe((QActive *)me, PLAYER_TRIGGER_SIG);    QActive_subscribe((QActive *)me, PLAYER_QUIT_SIG);    QS_OBJ_DICTIONARY(&l_tunnel);    /* object dictionary for Tunnel object */    QS_OBJ_DICTIONARY(&l_tunnel.blinkTimeEvt);    QS_OBJ_DICTIONARY(&l_tunnel.screenTimeEvt);    QS_FUN_DICTIONARY(&Tunnel_initial); /* fun. dictionaries for Tunnel HSM */    QS_FUN_DICTIONARY(&Tunnel_final);    QS_FUN_DICTIONARY(&Tunnel_active);    QS_FUN_DICTIONARY(&Tunnel_playing);    QS_FUN_DICTIONARY(&Tunnel_demo);    QS_FUN_DICTIONARY(&Tunnel_game_over);    QS_FUN_DICTIONARY(&Tunnel_screen_saver);    QS_FUN_DICTIONARY(&Tunnel_screen_saver_n_pixels);    QS_FUN_DICTIONARY(&Tunnel_screen_saver_1_pixel);    QS_SIG_DICTIONARY(BLINK_TIMEOUT_SIG,  &l_tunnel);      /* local signals */    QS_SIG_DICTIONARY(SCREEN_TIMEOUT_SIG, &l_tunnel);    QS_SIG_DICTIONARY(SHIP_IMG_SIG,       &l_tunnel);    QS_SIG_DICTIONARY(MISSILE_IMG_SIG,    &l_tunnel);    QS_SIG_DICTIONARY(MINE_IMG_SIG,       &l_tunnel);    QS_SIG_DICTIONARY(MINE_DISABLED_SIG,  &l_tunnel);    QS_SIG_DICTIONARY(EXPLOSION_SIG,      &l_tunnel);    QS_SIG_DICTIONARY(SCORE_SIG,          &l_tunnel);    return Q_TRAN(&Tunnel_demo);}/*..........................................................................*/QState Tunnel_final(Tunnel *me, QEvent const *e) {    (void)me;                                     /* avoid compiler warning */    switch (e->sig) {        case Q_ENTRY_SIG: {            /* clear the screen */            memset(l_frame, (uint8_t)0,                   (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8));            BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);            QF_stop();                               /* stop QF and cleanup */            return Q_HANDLED();        }    }    return Q_SUPER(&QHsm_top);}/*..........................................................................*/QState Tunnel_active(Tunnel *me, QEvent const *e) {    switch (e->sig) {        case MINE_DISABLED_SIG: {            Q_ASSERT((((MineEvt const *)e)->id < GAME_MINES_MAX)                     && (me->mines[((MineEvt const *)e)->id] != (QHsm *)0));            me->mines[((MineEvt const *)e)->id] = (QHsm *)0;            return Q_HANDLED();        }        case PLAYER_QUIT_SIG: {            return Q_TRAN(&Tunnel_final);        }    }    return Q_SUPER(&QHsm_top);}/*..........................................................................*/QState Tunnel_demo(Tunnel *me, QEvent const *e) {    switch (e->sig) {        case Q_ENTRY_SIG: {            me->last_mine_x = 0;   /* last mine at right edge of the tunnel */            me->last_mine_y = 0;                                            /* set the tunnel properties... */            me->wall_thickness_top = 0;            me->wall_thickness_bottom = 0;            me->minimal_gap = GAME_SCREEN_HEIGHT - 3;            /* erase the tunnel walls */            memset(l_walls, (uint8_t)0,                   (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8));            QTimeEvt_postEvery(&me->blinkTimeEvt, (QActive *)me,                               BSP_TICKS_PER_SEC/2);       /* every 1/2 sec */            QTimeEvt_postIn(&me->screenTimeEvt, (QActive *)me,                            BSP_TICKS_PER_SEC*20);           /* 20s timeout */            me->blink_ctr = 0;                    /* init the blink counter */            return Q_HANDLED();        }        case Q_EXIT_SIG: {            QTimeEvt_disarm(&me->blinkTimeEvt);            QTimeEvt_disarm(&me->screenTimeEvt);            return Q_HANDLED();        }        case BLINK_TIMEOUT_SIG: {            me->blink_ctr ^= 1;                  /* toggle the blink cunter */            return Q_HANDLED();        }        case SCREEN_TIMEOUT_SIG: {            return Q_TRAN(&Tunnel_screen_saver);        }        case TIME_TICK_SIG: {            Tunnel_advance(me);            if (me->blink_ctr != 0) {                /* add the text bitmap into the frame buffer */                Tunnel_addImageAt(me,                    PRESS_BUTTON_BMP,                    (GAME_SCREEN_WIDTH - 55)/2,                    (GAME_SCREEN_HEIGHT - 8)/2);            }            BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);            return Q_HANDLED();        }        case PLAYER_TRIGGER_SIG: {            return Q_TRAN(&Tunnel_playing);        }    }    return Q_SUPER(&Tunnel_active);}/*..........................................................................*/QState Tunnel_game_over(Tunnel *me, QEvent const *e) {    switch (e->sig) {        case Q_ENTRY_SIG: {            QTimeEvt_postEvery(&me->blinkTimeEvt, (QActive *)me,                               BSP_TICKS_PER_SEC/2);             /* 1/2 sec */            QTimeEvt_postIn(&me->screenTimeEvt, (QActive *)me,                            BSP_TICKS_PER_SEC*5);          /* 5 sec timeout */            me->blink_ctr = 0;            BSP_drawNString((GAME_SCREEN_WIDTH - 6*9)/2, 0, "Game Over");            return Q_HANDLED();        }        case Q_EXIT_SIG: {            QTimeEvt_disarm(&me->blinkTimeEvt);            QTimeEvt_disarm(&me->screenTimeEvt);            BSP_updateScore(0);          /* update the score on the display */            return Q_HANDLED();        }        case BLINK_TIMEOUT_SIG: {            me->blink_ctr ^= 1;                  /* toggle the blink couner */            BSP_drawNString((GAME_SCREEN_WIDTH - 6*9)/2, 0,                             ((me->blink_ctr == 0)                             ? "Game Over"                             : "         "));            return Q_HANDLED();        }        case SCREEN_TIMEOUT_SIG: {            return Q_TRAN(&Tunnel_demo);        }    }    return Q_SUPER(&Tunnel_active);}/*..........................................................................*/QState Tunnel_playing(Tunnel *me, QEvent const *e) {    uint8_t x;    int8_t y;    uint8_t bmp;    switch (e->sig) {        case Q_ENTRY_SIG: {            static QEvent const takeoff = { TAKE_OFF_SIG, 0 };            me->minimal_gap = GAME_SCREEN_HEIGHT - 3;            /* erase the walls */            memset(l_walls, (uint8_t)0,                   (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8));            QActive_postFIFO(AO_Ship, &takeoff);    /* post the TAKEOFF sig */            return Q_HANDLED();        }        case Q_EXIT_SIG: {            QEvent recycle;            recycle.sig = MINE_RECYCLE_SIG;            Tunnel_dispatchToAllMines(me, &recycle);   /* recycle all Mines */            return Q_HANDLED();        }        case TIME_TICK_SIG: {            /* render this frame on the display */            BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);            Tunnel_advance(me);            Tunnel_plantMine(me);            Tunnel_dispatchToAllMines(me, e);            return Q_HANDLED();        }        case SHIP_IMG_SIG:        case MISSILE_IMG_SIG: {            x  = (uint8_t)((ObjectImageEvt const *)e)->x;            y  =  (int8_t)((ObjectImageEvt const *)e)->y;            bmp = (uint8_t)((ObjectImageEvt const *)e)->bmp;                               /* did the Ship/Missile hit the tunnel wall? */            if (Tunnel_isWallHit(me, bmp, x, y)) {                QEvent const hit = { HIT_WALL_SIG, 0};                if (e->sig == SHIP_IMG_SIG) {                    QActive_postFIFO(AO_Ship, &hit);                }                else {                    QActive_postFIFO(AO_Missile, &hit);                }            }            Tunnel_addImageAt(me, bmp, x, y);            Tunnel_dispatchToAllMines(me, e);   /* let Mines check for hits */            return Q_HANDLED();        }        case MINE_IMG_SIG:        case EXPLOSION_SIG: {            x  = (uint8_t)((ObjectImageEvt const *)e)->x;            y  =  (int8_t)((ObjectImageEvt const *)e)->y;            bmp = (uint8_t)((ObjectImageEvt const *)e)->bmp;            Tunnel_addImageAt(me, bmp, x, y);            return Q_HANDLED();        }        case SCORE_SIG: {            BSP_updateScore(((ScoreEvt const *)e)->score);            /* increase difficulty of the game:            * the tunnel gets narrower as the score goes up            */            me->minimal_gap = GAME_SCREEN_HEIGHT - 3                              - ((ScoreEvt const *)e)->score/2000;            return Q_HANDLED();        }        case GAME_OVER_SIG: {            uint16_t score = ((ScoreEvt const *)e)->score;            char str[5];            BSP_updateScore(score);            /* clear the screen */            memset(l_frame, (uint8_t)0,                   (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8));            BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);            /* Output the final score to the screen */            BSP_drawNString((GAME_SCREEN_WIDTH - 6*10)/2, 1, "Score:");            str[4] = '\0';                     /* zero-terminate the string */            str[3] = '0' + (score % 10); score /= 10;            str[2] = '0' + (score % 10); score /= 10;            str[1] = '0' + (score % 10); score /= 10;            str[0] = '0' + (score % 10);            BSP_drawNString((GAME_SCREEN_WIDTH - 6*10)/2 + 6*6, 1, str);            return Q_TRAN(&Tunnel_game_over);        }    }    return Q_SUPER(&Tunnel_active);}/*..........................................................................*//* A random-pixel screen saver to avoid damage to the display */QState Tunnel_screen_saver(Tunnel *me, QEvent const *e) {    switch (e->sig) {        case Q_INIT_SIG: {            return Q_TRAN(&Tunnel_screen_saver_n_pixels);        }        case PLAYER_TRIGGER_SIG: {            return Q_TRAN(&Tunnel_demo);        }    }    return Q_SUPER(&Tunnel_active);}/*..........................................................................*/QState Tunnel_screen_saver_n_pixels(Tunnel *me, QEvent const *e) {    switch (e->sig) {        case Q_ENTRY_SIG: {            QTimeEvt_postIn(&me->screenTimeEvt, (QActive *)me,                            BSP_TICKS_PER_SEC*60);           /* 60s timeout */            /* clear the screen */            memset(l_frame, (uint8_t)0,                   (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8));            return Q_HANDLED();        }        case Q_EXIT_SIG: {            QTimeEvt_disarm(&me->screenTimeEvt);            return Q_HANDLED();        }        case SCREEN_TIMEOUT_SIG: {            return Q_TRAN(&Tunnel_screen_saver_1_pixel);        }        case TIME_TICK_SIG: {            uint8_t n = 4;       /* generate 4 random pixels on the display */            while ((n--) != 0) {                uint32_t rnd = random();                l_frame[rnd % (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8)]                    = (uint8_t)(1 << ((rnd >> 8) & 0x7));            }            BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);            return Q_HANDLED();        }    }    return Q_SUPER(&Tunnel_screen_saver);}/*..........................................................................*/QState Tunnel_screen_saver_1_pixel(Tunnel *me, QEvent const *e) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -