mirror of
https://github.com/QuantumLeaps/qpc.git
synced 2025-01-21 06:53:11 +08:00
827 lines
31 KiB
C
827 lines
31 KiB
C
/*****************************************************************************
|
|
* Model: game.qm
|
|
* File: ./tunnel.c
|
|
*
|
|
* This code has been generated by QM tool (see state-machine.com/qm).
|
|
* DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
|
|
*
|
|
* This program is open source software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as published
|
|
* by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*****************************************************************************/
|
|
/*${.::tunnel.c} ...........................................................*/
|
|
#include "qpc.h"
|
|
#include "bsp.h"
|
|
#include "game.h"
|
|
|
|
Q_DEFINE_THIS_FILE
|
|
|
|
/* local objects -----------------------------------------------------------*/
|
|
/*${AOs::Tunnel} ...........................................................*/
|
|
typedef struct {
|
|
/* protected: */
|
|
QMActive super;
|
|
|
|
/* private: */
|
|
QTimeEvt blinkTimeEvt;
|
|
QTimeEvt screenTimeEvt;
|
|
QMsm * mines[GAME_MINES_MAX];
|
|
QMsm * mine1_pool[GAME_MINES_MAX];
|
|
QMsm * mine2_pool[GAME_MINES_MAX];
|
|
uint8_t blink_ctr;
|
|
uint8_t last_mine_x;
|
|
uint8_t last_mine_y;
|
|
uint8_t wall_thickness_top;
|
|
uint8_t wall_thickness_bottom;
|
|
uint8_t wall_gap;
|
|
} Tunnel;
|
|
|
|
/* private: */
|
|
static void Tunnel_advance(Tunnel * const me);
|
|
static void Tunnel_plantMine(Tunnel * const me);
|
|
static void Tunnel_dispatchToAllMines(Tunnel * const me, QEvt const * e);
|
|
|
|
/* protected: */
|
|
static QState Tunnel_initial(Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_active (Tunnel * const me, QEvt const * const e);
|
|
static QMState const Tunnel_active_s = {
|
|
(QMState const *)0, /* superstate (top) */
|
|
Q_STATE_CAST(&Tunnel_active),
|
|
Q_ACTION_CAST(0), /* no entry action */
|
|
Q_ACTION_CAST(0), /* no exit action */
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_show_logo (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_show_logo_e(Tunnel * const me);
|
|
static QState Tunnel_show_logo_x(Tunnel * const me);
|
|
static QMState const Tunnel_show_logo_s = {
|
|
&Tunnel_active_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_show_logo),
|
|
Q_ACTION_CAST(&Tunnel_show_logo_e),
|
|
Q_ACTION_CAST(&Tunnel_show_logo_x),
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_demo (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_demo_e(Tunnel * const me);
|
|
static QState Tunnel_demo_x(Tunnel * const me);
|
|
static QMState const Tunnel_demo_s = {
|
|
&Tunnel_active_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_demo),
|
|
Q_ACTION_CAST(&Tunnel_demo_e),
|
|
Q_ACTION_CAST(&Tunnel_demo_x),
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_playing (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_playing_e(Tunnel * const me);
|
|
static QState Tunnel_playing_x(Tunnel * const me);
|
|
static QMState const Tunnel_playing_s = {
|
|
&Tunnel_active_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_playing),
|
|
Q_ACTION_CAST(&Tunnel_playing_e),
|
|
Q_ACTION_CAST(&Tunnel_playing_x),
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_game_over (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_game_over_e(Tunnel * const me);
|
|
static QState Tunnel_game_over_x(Tunnel * const me);
|
|
static QMState const Tunnel_game_over_s = {
|
|
&Tunnel_active_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_game_over),
|
|
Q_ACTION_CAST(&Tunnel_game_over_e),
|
|
Q_ACTION_CAST(&Tunnel_game_over_x),
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_screen_saver (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_screen_saver_i(Tunnel * const me);
|
|
static QMState const Tunnel_screen_saver_s = {
|
|
&Tunnel_active_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_screen_saver),
|
|
Q_ACTION_CAST(0), /* no entry action */
|
|
Q_ACTION_CAST(0), /* no exit action */
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_i)
|
|
};
|
|
static QState Tunnel_screen_saver_hide (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_screen_saver_hide_e(Tunnel * const me);
|
|
static QState Tunnel_screen_saver_hide_x(Tunnel * const me);
|
|
static QMState const Tunnel_screen_saver_hide_s = {
|
|
&Tunnel_screen_saver_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_screen_saver_hide),
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_hide_e),
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_hide_x),
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_screen_saver_show (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_screen_saver_show_e(Tunnel * const me);
|
|
static QState Tunnel_screen_saver_show_x(Tunnel * const me);
|
|
static QMState const Tunnel_screen_saver_show_s = {
|
|
&Tunnel_screen_saver_s, /* superstate */
|
|
Q_STATE_CAST(&Tunnel_screen_saver_show),
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_show_e),
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_show_x),
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
static QState Tunnel_final (Tunnel * const me, QEvt const * const e);
|
|
static QState Tunnel_final_e(Tunnel * const me);
|
|
static QMState const Tunnel_final_s = {
|
|
(QMState const *)0, /* superstate (top) */
|
|
Q_STATE_CAST(&Tunnel_final),
|
|
Q_ACTION_CAST(&Tunnel_final_e),
|
|
Q_ACTION_CAST(0), /* no exit action */
|
|
Q_ACTION_CAST(0) /* no intitial tran. */
|
|
};
|
|
|
|
static Tunnel l_tunnel; /* the sole instance of the Tunnel active object */
|
|
|
|
/* Public-scope objects ----------------------------------------------------*/
|
|
QMActive * const AO_Tunnel = &l_tunnel.super; /* opaque AO pointer */
|
|
|
|
/* Active object definition ================================================*/
|
|
/*${AOs::Tunnel_ctor} ......................................................*/
|
|
void Tunnel_ctor(void) {
|
|
uint8_t n;
|
|
Tunnel *me = &l_tunnel;
|
|
QMActive_ctor(&me->super, Q_STATE_CAST(&Tunnel_initial));
|
|
QTimeEvt_ctorX(&me->blinkTimeEvt, &me->super, BLINK_TIMEOUT_SIG, 0U);
|
|
QTimeEvt_ctorX(&me->screenTimeEvt, &me->super, SCREEN_TIMEOUT_SIG, 0U);
|
|
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] = (QMsm *)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;
|
|
}
|
|
/*${AOs::Tunnel} ...........................................................*/
|
|
/*${AOs::Tunnel::advance} ..................................................*/
|
|
static void Tunnel_advance(Tunnel * const me) {
|
|
uint32_t rnd;
|
|
|
|
rnd = (BSP_random() & 0xFFU);
|
|
|
|
/* reduce the top wall thickness 18.75% of the time */
|
|
if ((rnd < 48U) && (me->wall_thickness_top > 0U)) {
|
|
--me->wall_thickness_top;
|
|
}
|
|
|
|
/* reduce the bottom wall thickness 18.75% of the time */
|
|
if ((rnd > 208U) && (me->wall_thickness_bottom > 0U)) {
|
|
--me->wall_thickness_bottom;
|
|
}
|
|
|
|
rnd = (BSP_random() & 0xFFU);
|
|
|
|
/* grow the bottom wall thickness 19.14% of the time */
|
|
if ((rnd < 49U)
|
|
&& ((GAME_TUNNEL_HEIGHT
|
|
- me->wall_thickness_top
|
|
- me->wall_thickness_bottom) > me->wall_gap))
|
|
{
|
|
++me->wall_thickness_bottom;
|
|
}
|
|
|
|
/* grow the top wall thickness 19.14% of the time */
|
|
if ((rnd > 207U)
|
|
&& ((GAME_TUNNEL_HEIGHT
|
|
- me->wall_thickness_top
|
|
- me->wall_thickness_bottom) > me->wall_gap))
|
|
{
|
|
++me->wall_thickness_top;
|
|
}
|
|
|
|
/* advance the Tunnel by 1 game step to the left
|
|
* and copy the Tunnel layer to the main frame buffer
|
|
*/
|
|
BSP_advanceWalls(me->wall_thickness_top, me->wall_thickness_bottom);
|
|
}
|
|
/*${AOs::Tunnel::plantMine} ................................................*/
|
|
static void Tunnel_plantMine(Tunnel * const me) {
|
|
uint32_t rnd = (BSP_random() & 0xFFU);
|
|
|
|
if (me->last_mine_x > 0U) {
|
|
--me->last_mine_x; /* shift the last Mine 1 position to the left */
|
|
}
|
|
/* last mine far enough? */
|
|
if ((me->last_mine_x + GAME_MINES_DIST_MIN < GAME_TUNNEL_WIDTH)
|
|
&& (rnd < 8U)) /* place the mines only 5% of the time */
|
|
{
|
|
uint8_t n;
|
|
for (n = 0U; n < Q_DIM(me->mines); ++n) { /*look for disabled mines */
|
|
if (me->mines[n] == (QMsm *)0) {
|
|
break;
|
|
}
|
|
}
|
|
if (n < Q_DIM(me->mines)) { /* a disabled Mine found? */
|
|
ObjectPosEvt ope; /* event to dispatch to the Mine */
|
|
rnd = (BSP_random() & 0xFFFFU);
|
|
|
|
if ((rnd & 1U) == 0U) { /* choose the type of the mine */
|
|
me->mines[n] = me->mine1_pool[n];
|
|
}
|
|
else {
|
|
me->mines[n] = me->mine2_pool[n];
|
|
}
|
|
|
|
/* new Mine is planted by the end of the tunnel */
|
|
me->last_mine_x = GAME_TUNNEL_WIDTH - 8U;
|
|
|
|
/* choose a random y-position for the Mine in the Tunnel */
|
|
rnd %= (GAME_TUNNEL_HEIGHT
|
|
- me->wall_thickness_top
|
|
- me->wall_thickness_bottom - 4U);
|
|
me->last_mine_y = (uint8_t)(me->wall_thickness_top + 2U + rnd);
|
|
|
|
ope.super.sig = MINE_PLANT_SIG;
|
|
ope.x = me->last_mine_x;
|
|
ope.y = me->last_mine_y;
|
|
QMSM_DISPATCH(me->mines[n], (QEvt *)&ope); /* direct dispatch */
|
|
}
|
|
}
|
|
}
|
|
/*${AOs::Tunnel::dispatchToAllMines} .......................................*/
|
|
static void Tunnel_dispatchToAllMines(Tunnel * const me, QEvt const * e) {
|
|
uint8_t n;
|
|
|
|
for (n = 0U; n < GAME_MINES_MAX; ++n) {
|
|
if (me->mines[n] != (QMsm *)0) { /* is the mine used? */
|
|
QMSM_DISPATCH(me->mines[n], e);
|
|
}
|
|
}
|
|
}
|
|
/*${AOs::Tunnel::SM} .......................................................*/
|
|
static QState Tunnel_initial(Tunnel * const me, QEvt const * const e) {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[2];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_show_logo_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_show_logo_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
/* ${AOs::Tunnel::SM::initial} */
|
|
uint8_t n;
|
|
for (n = 0U; n < GAME_MINES_MAX; ++n) {
|
|
QMSM_INIT(me->mine1_pool[n], (QEvt *)0);/*initial tran. for Mine1 */
|
|
QMSM_INIT(me->mine2_pool[n], (QEvt *)0);/*initial tran. for Mine2 */
|
|
}
|
|
BSP_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);
|
|
|
|
/* object dictionaries... */
|
|
QS_OBJ_DICTIONARY(&l_tunnel);
|
|
QS_OBJ_DICTIONARY(&l_tunnel.blinkTimeEvt);
|
|
QS_OBJ_DICTIONARY(&l_tunnel.screenTimeEvt);
|
|
|
|
/* function dictionaries for Tunnel HSM... */
|
|
QS_FUN_DICTIONARY(&Tunnel_initial);
|
|
QS_FUN_DICTIONARY(&Tunnel_final);
|
|
QS_FUN_DICTIONARY(&Tunnel_active);
|
|
QS_FUN_DICTIONARY(&Tunnel_show_logo);
|
|
QS_FUN_DICTIONARY(&Tunnel_demo);
|
|
QS_FUN_DICTIONARY(&Tunnel_playing);
|
|
QS_FUN_DICTIONARY(&Tunnel_game_over);
|
|
QS_FUN_DICTIONARY(&Tunnel_screen_saver);
|
|
QS_FUN_DICTIONARY(&Tunnel_screen_saver_hide);
|
|
QS_FUN_DICTIONARY(&Tunnel_screen_saver_show);
|
|
|
|
/* local signals... */
|
|
QS_SIG_DICTIONARY(BLINK_TIMEOUT_SIG, &l_tunnel);
|
|
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);
|
|
|
|
(void)e; /* unused parameter */
|
|
return QM_TRAN_INIT(&tatbl_);
|
|
}
|
|
/*${AOs::Tunnel::SM::active} ...............................................*/
|
|
/* ${AOs::Tunnel::SM::active} */
|
|
static QState Tunnel_active(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::MINE_DISABLED} */
|
|
case MINE_DISABLED_SIG: {
|
|
Q_ASSERT((Q_EVT_CAST(MineEvt)->id < GAME_MINES_MAX)
|
|
&& (me->mines[Q_EVT_CAST(MineEvt)->id] != (QMsm *)0));
|
|
me->mines[Q_EVT_CAST(MineEvt)->id] = (QMsm *)0;
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::PLAYER_QUIT} */
|
|
case PLAYER_QUIT_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[2];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_final_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_final_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::show_logo} ....................................*/
|
|
/* ${AOs::Tunnel::SM::active::show_logo} */
|
|
static QState Tunnel_show_logo_e(Tunnel * const me) {
|
|
QTimeEvt_armX(&me->blinkTimeEvt, BSP_TICKS_PER_SEC/2U,
|
|
BSP_TICKS_PER_SEC/2U);
|
|
QTimeEvt_armX(&me->screenTimeEvt, BSP_TICKS_PER_SEC*5U, 0U);
|
|
me->blink_ctr = 0U;
|
|
BSP_paintString(24U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, "Quantum LeAps");
|
|
BSP_paintString(16U, (GAME_TUNNEL_HEIGHT / 2U) + 0U, "state-machine.com");
|
|
|
|
BSP_paintString(1U, GAME_TUNNEL_HEIGHT - 18U, "Fire missile: BTN0");
|
|
BSP_paintString(1U, GAME_TUNNEL_HEIGHT - 10U, "Fly ship up: BTN1");
|
|
|
|
BSP_updateScreen();
|
|
return QM_ENTRY(&Tunnel_show_logo_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::show_logo} */
|
|
static QState Tunnel_show_logo_x(Tunnel * const me) {
|
|
QTimeEvt_disarm(&me->blinkTimeEvt);
|
|
QTimeEvt_disarm(&me->screenTimeEvt);
|
|
return QM_EXIT(&Tunnel_show_logo_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::show_logo} */
|
|
static QState Tunnel_show_logo(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::show_logo::SCREEN_TIMEOUT} */
|
|
case SCREEN_TIMEOUT_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_demo_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_show_logo_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_demo_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::show_logo::BLINK_TIMEOUT} */
|
|
case BLINK_TIMEOUT_SIG: {
|
|
me->blink_ctr ^= 1U; /* toggle the blink counter */
|
|
/* ${AOs::Tunnel::SM::active::show_logo::BLINK_TIMEOUT::[me->blink_ctr==0U]} */
|
|
if (me->blink_ctr == 0U) {
|
|
BSP_paintString(24U + 8U*6U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, "LeAps");
|
|
BSP_updateScreen();
|
|
status_ = QM_HANDLED();
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::show_logo::BLINK_TIMEOUT::[else]} */
|
|
else {
|
|
BSP_paintString(24U + 8U*6U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, "LeaPs");
|
|
BSP_updateScreen();
|
|
status_ = QM_HANDLED();
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
(void)me; /* avoid compiler warning in case 'me' is not used */
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::demo} .........................................*/
|
|
/* ${AOs::Tunnel::SM::active::demo} */
|
|
static QState Tunnel_demo_e(Tunnel * const me) {
|
|
me->last_mine_x = 0U; /* last mine at right edge of the tunnel */
|
|
me->last_mine_y = 0U;
|
|
/* set the tunnel properties... */
|
|
me->wall_thickness_top = 0U;
|
|
me->wall_thickness_bottom = 0U;
|
|
me->wall_gap = GAME_WALLS_GAP_Y;
|
|
|
|
/* clear the tunnel walls */
|
|
BSP_clearWalls();
|
|
|
|
QTimeEvt_armX(&me->blinkTimeEvt, BSP_TICKS_PER_SEC/2U,
|
|
BSP_TICKS_PER_SEC/2U); /* every 1/2 sec */
|
|
QTimeEvt_armX(&me->screenTimeEvt, BSP_TICKS_PER_SEC*20U, 0U);
|
|
|
|
me->blink_ctr = 0U; /* init the blink counter */
|
|
return QM_ENTRY(&Tunnel_demo_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::demo} */
|
|
static QState Tunnel_demo_x(Tunnel * const me) {
|
|
QTimeEvt_disarm(&me->blinkTimeEvt);
|
|
QTimeEvt_disarm(&me->screenTimeEvt);
|
|
return QM_EXIT(&Tunnel_demo_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::demo} */
|
|
static QState Tunnel_demo(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::demo::BLINK_TIMEOUT} */
|
|
case BLINK_TIMEOUT_SIG: {
|
|
me->blink_ctr ^= 1U; /* toggle the blink cunter */
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::demo::SCREEN_TIMEOUT} */
|
|
case SCREEN_TIMEOUT_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_screen_saver_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_demo_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_i), /* init.tran. */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::demo::TIME_TICK} */
|
|
case TIME_TICK_SIG: {
|
|
Tunnel_advance(me);
|
|
if (me->blink_ctr != 0U) {
|
|
/* add the text bitmap into the frame buffer */
|
|
BSP_paintString((GAME_TUNNEL_WIDTH - 10U*6U)/2U,
|
|
(GAME_TUNNEL_HEIGHT - 4U)/2U,
|
|
"Press BTN0");
|
|
}
|
|
BSP_updateScreen();
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::demo::PLAYER_TRIGGER} */
|
|
case PLAYER_TRIGGER_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_playing_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_demo_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_playing_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::playing} ......................................*/
|
|
/* ${AOs::Tunnel::SM::active::playing} */
|
|
static QState Tunnel_playing_e(Tunnel * const me) {
|
|
static QEvt const takeoff = { TAKE_OFF_SIG, 0U, 0U };
|
|
me->wall_gap = GAME_WALLS_GAP_Y;
|
|
QACTIVE_POST(AO_Ship, &takeoff, me); /* post the TAKEOFF sig */
|
|
return QM_ENTRY(&Tunnel_playing_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing} */
|
|
static QState Tunnel_playing_x(Tunnel * const me) {
|
|
QEvt recycle;
|
|
recycle.sig = MINE_RECYCLE_SIG;
|
|
Tunnel_dispatchToAllMines(me, &recycle); /* recycle all Mines */
|
|
return QM_EXIT(&Tunnel_playing_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing} */
|
|
static QState Tunnel_playing(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::playing::TIME_TICK} */
|
|
case TIME_TICK_SIG: {
|
|
/* render this frame on the display */
|
|
BSP_updateScreen();
|
|
Tunnel_advance(me);
|
|
Tunnel_plantMine(me);
|
|
Tunnel_dispatchToAllMines(me, e);
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing::SHIP_IMG} */
|
|
case SHIP_IMG_SIG: {
|
|
uint8_t x = Q_EVT_CAST(ObjectImageEvt)->x;
|
|
int8_t y = Q_EVT_CAST(ObjectImageEvt)->y;
|
|
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)->bmp;
|
|
|
|
/* did the Ship/Missile hit the tunnel wall? */
|
|
if (BSP_isWallHit(bmp, x, y)) {
|
|
static QEvt const hit = { HIT_WALL_SIG, 0U, 0U };
|
|
QACTIVE_POST(AO_Ship, &hit, me);
|
|
}
|
|
BSP_paintBitmap(x, y, bmp);
|
|
Tunnel_dispatchToAllMines(me, e); /* let Mines check for hits */
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing::MISSILE_IMG} */
|
|
case MISSILE_IMG_SIG: {
|
|
uint8_t x = Q_EVT_CAST(ObjectImageEvt)->x;
|
|
int8_t y = Q_EVT_CAST(ObjectImageEvt)->y;
|
|
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)->bmp;
|
|
|
|
/* did the Ship/Missile hit the tunnel wall? */
|
|
if (BSP_isWallHit(bmp, x, y)) {
|
|
static QEvt const hit = { HIT_WALL_SIG, 0U, 0U };
|
|
QACTIVE_POST(AO_Missile, &hit, me);
|
|
}
|
|
BSP_paintBitmap(x, y, bmp);
|
|
Tunnel_dispatchToAllMines(me, e); /* let Mines check for hits */
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing::MINE_IMG} */
|
|
case MINE_IMG_SIG: {
|
|
BSP_paintBitmap(Q_EVT_CAST(ObjectImageEvt)->x,
|
|
Q_EVT_CAST(ObjectImageEvt)->y,
|
|
Q_EVT_CAST(ObjectImageEvt)->bmp);
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing::EXPLOSION} */
|
|
case EXPLOSION_SIG: {
|
|
BSP_paintBitmap(Q_EVT_CAST(ObjectImageEvt)->x,
|
|
Q_EVT_CAST(ObjectImageEvt)->y,
|
|
Q_EVT_CAST(ObjectImageEvt)->bmp);
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing::SCORE} */
|
|
case SCORE_SIG: {
|
|
BSP_updateScore(Q_EVT_CAST(ScoreEvt)->score);
|
|
/* increase difficulty of the game:
|
|
* the tunnel gets narrower as the score goes up
|
|
*/
|
|
me->wall_gap = (uint8_t)(GAME_WALLS_GAP_Y
|
|
- Q_EVT_CAST(ScoreEvt)->score/100U);
|
|
if (me->wall_gap < GAME_WALLS_MIN_GAP_Y) {
|
|
me->wall_gap = GAME_WALLS_MIN_GAP_Y;
|
|
}
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::playing::GAME_OVER} */
|
|
case GAME_OVER_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_game_over_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_playing_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_game_over_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
BSP_clearWalls();
|
|
BSP_updateScore(Q_EVT_CAST(ScoreEvt)->score);
|
|
BSP_updateScreen();
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::game_over} ....................................*/
|
|
/* ${AOs::Tunnel::SM::active::game_over} */
|
|
static QState Tunnel_game_over_e(Tunnel * const me) {
|
|
QTimeEvt_armX(&me->blinkTimeEvt, BSP_TICKS_PER_SEC/2U,
|
|
BSP_TICKS_PER_SEC/2U); /* every 1/2 sec */
|
|
QTimeEvt_armX(&me->screenTimeEvt, BSP_TICKS_PER_SEC*5U, 0U);
|
|
me->blink_ctr = 0U;
|
|
BSP_paintString((GAME_TUNNEL_WIDTH - 6U * 9U) / 2U,
|
|
(GAME_TUNNEL_HEIGHT / 2U) - 4U,
|
|
"Game Over");
|
|
BSP_updateScreen();
|
|
return QM_ENTRY(&Tunnel_game_over_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::game_over} */
|
|
static QState Tunnel_game_over_x(Tunnel * const me) {
|
|
QTimeEvt_disarm(&me->blinkTimeEvt);
|
|
QTimeEvt_disarm(&me->screenTimeEvt);
|
|
BSP_updateScore(0); /* update the score on the display */
|
|
return QM_EXIT(&Tunnel_game_over_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::game_over} */
|
|
static QState Tunnel_game_over(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::game_over::BLINK_TIMEOUT} */
|
|
case BLINK_TIMEOUT_SIG: {
|
|
me->blink_ctr ^= 1U; /* toggle the blink counter */
|
|
BSP_paintString((GAME_TUNNEL_WIDTH - 6U*9U) / 2U,
|
|
(GAME_TUNNEL_HEIGHT / 2U) - 4U,
|
|
((me->blink_ctr == 0U)
|
|
? "Game Over"
|
|
: " "));
|
|
BSP_updateScreen();
|
|
status_ = QM_HANDLED();
|
|
break;
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::game_over::SCREEN_TIMEOUT} */
|
|
case SCREEN_TIMEOUT_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_demo_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_game_over_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_demo_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::screen_saver} .................................*/
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::initial} */
|
|
static QState Tunnel_screen_saver_i(Tunnel * const me) {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[2];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_screen_saver_hide_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_hide_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::initial} */
|
|
return QM_TRAN_INIT(&tatbl_);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::screen_saver} */
|
|
static QState Tunnel_screen_saver(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::PLAYER_TRIGGER} */
|
|
case PLAYER_TRIGGER_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[2];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_demo_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_demo_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::screen_saver::screen_saver_hide} ..............*/
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_hide} */
|
|
static QState Tunnel_screen_saver_hide_e(Tunnel * const me) {
|
|
BSP_displayOff(); /* power down the display */
|
|
QTimeEvt_armX(&me->screenTimeEvt, BSP_TICKS_PER_SEC*3U, 0U);
|
|
return QM_ENTRY(&Tunnel_screen_saver_hide_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_hide} */
|
|
static QState Tunnel_screen_saver_hide_x(Tunnel * const me) {
|
|
QTimeEvt_disarm(&me->screenTimeEvt);
|
|
BSP_displayOn(); /* power up the display */
|
|
return QM_EXIT(&Tunnel_screen_saver_hide_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_hide} */
|
|
static QState Tunnel_screen_saver_hide(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_hid~::SCREEN_TIMEOUT} */
|
|
case SCREEN_TIMEOUT_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_screen_saver_show_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_hide_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_show_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::active::screen_saver::screen_saver_show} ..............*/
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_show} */
|
|
static QState Tunnel_screen_saver_show_e(Tunnel * const me) {
|
|
uint32_t rnd = BSP_random();
|
|
/* clear the screen frame buffer */
|
|
BSP_clearFB();
|
|
BSP_paintString((uint8_t)(rnd % (GAME_TUNNEL_WIDTH - 10U*6U)),
|
|
(uint8_t) (rnd % (GAME_TUNNEL_HEIGHT - 8U)),
|
|
"Press BTN0");
|
|
BSP_updateScreen();
|
|
QTimeEvt_armX(&me->screenTimeEvt, BSP_TICKS_PER_SEC/2U, 0U);
|
|
return QM_ENTRY(&Tunnel_screen_saver_show_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_show} */
|
|
static QState Tunnel_screen_saver_show_x(Tunnel * const me) {
|
|
QTimeEvt_disarm(&me->screenTimeEvt);
|
|
BSP_clearFB();
|
|
BSP_updateScreen();
|
|
return QM_EXIT(&Tunnel_screen_saver_show_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_show} */
|
|
static QState Tunnel_screen_saver_show(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
/* ${AOs::Tunnel::SM::active::screen_saver::screen_saver_sho~::SCREEN_TIMEOUT} */
|
|
case SCREEN_TIMEOUT_SIG: {
|
|
static struct {
|
|
QMState const *target;
|
|
QActionHandler act[3];
|
|
} const tatbl_ = { /* transition-action table */
|
|
&Tunnel_screen_saver_hide_s, /* target state */
|
|
{
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_show_x), /* exit */
|
|
Q_ACTION_CAST(&Tunnel_screen_saver_hide_e), /* entry */
|
|
Q_ACTION_CAST(0) /* zero terminator */
|
|
}
|
|
};
|
|
status_ = QM_TRAN(&tatbl_);
|
|
break;
|
|
}
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
return status_;
|
|
}
|
|
/*${AOs::Tunnel::SM::final} ................................................*/
|
|
/* ${AOs::Tunnel::SM::final} */
|
|
static QState Tunnel_final_e(Tunnel * const me) {
|
|
/* clear the screen */
|
|
BSP_clearFB();
|
|
BSP_updateScreen();
|
|
QF_stop(); /* stop QF and cleanup */
|
|
(void)me; /* avoid compiler warning in case 'me' is not used */
|
|
return QM_ENTRY(&Tunnel_final_s);
|
|
}
|
|
/* ${AOs::Tunnel::SM::final} */
|
|
static QState Tunnel_final(Tunnel * const me, QEvt const * const e) {
|
|
QState status_;
|
|
switch (e->sig) {
|
|
default: {
|
|
status_ = QM_SUPER();
|
|
break;
|
|
}
|
|
}
|
|
(void)me; /* avoid compiler warning in case 'me' is not used */
|
|
return status_;
|
|
}
|
|
|