"Fly 'n' Shoot" game model from Chapters 1 & 9 of PSiCC2 NOTE: Requries QP6. Tunnel Active Object 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); 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; QHSM_DISPATCH(me->mines[n], (QEvt *)&ope); /* direct dispatch */ } } uint8_t n; for (n = 0U; n < GAME_MINES_MAX; ++n) { if (me->mines[n] != (QMsm *)0) { /* is the mine used? */ QHSM_DISPATCH(me->mines[n], e); } } uint8_t n; for (n = 0U; n < GAME_MINES_MAX; ++n) { QHSM_INIT(me->mine1_pool[n], (QEvt *)0);/*initial tran. for Mine1 */ QHSM_INIT(me->mine2_pool[n], (QEvt *)0);/*initial tran. for Mine2 */ } BSP_randomSeed(1234); /* seed the pseudo-random generator */ QActive_subscribe(&me->super, TIME_TICK_SIG); QActive_subscribe(&me->super, PLAYER_TRIGGER_SIG); QActive_subscribe(&me->super, PLAYER_QUIT_SIG); /* object dictionaries... */ QS_OBJ_DICTIONARY(&l_tunnel.blinkTimeEvt); QS_OBJ_DICTIONARY(&l_tunnel.screenTimeEvt); /* local signals... */ QS_SIG_DICTIONARY(BLINK_TIMEOUT_SIG, me); QS_SIG_DICTIONARY(SCREEN_TIMEOUT_SIG, me); QS_SIG_DICTIONARY(SHIP_IMG_SIG, me); QS_SIG_DICTIONARY(MISSILE_IMG_SIG, me); QS_SIG_DICTIONARY(MINE_IMG_SIG, me); QS_SIG_DICTIONARY(MINE_DISABLED_SIG, me); QS_SIG_DICTIONARY(EXPLOSION_SIG, me); QS_SIG_DICTIONARY(SCORE_SIG, me); (void)e; /* unused parameter */ 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; 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(); QTimeEvt_disarm(&me->blinkTimeEvt); QTimeEvt_disarm(&me->screenTimeEvt); me->blink_ctr ^= 1U; /* toggle the blink counter */ me->blink_ctr == 0U BSP_paintString(24U + 8U*6U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, "LeAps"); BSP_updateScreen(); else BSP_paintString(24U + 8U*6U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, "LeaPs"); BSP_updateScreen(); 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 */ QTimeEvt_disarm(&me->blinkTimeEvt); QTimeEvt_disarm(&me->screenTimeEvt); me->blink_ctr ^= 1U; /* toggle the blink cunter */ 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(); 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 */ QEvt recycle; recycle.sig = MINE_RECYCLE_SIG; Tunnel_dispatchToAllMines(me, &recycle); /* recycle all Mines */ /* render this frame on the display */ BSP_updateScreen(); Tunnel_advance(me); Tunnel_plantMine(me); Tunnel_dispatchToAllMines(me, e); 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 */ 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 */ BSP_paintBitmap(Q_EVT_CAST(ObjectImageEvt)->x, Q_EVT_CAST(ObjectImageEvt)->y, Q_EVT_CAST(ObjectImageEvt)->bmp); BSP_paintBitmap(Q_EVT_CAST(ObjectImageEvt)->x, Q_EVT_CAST(ObjectImageEvt)->y, Q_EVT_CAST(ObjectImageEvt)->bmp); 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; } BSP_clearWalls(); BSP_updateScore(Q_EVT_CAST(ScoreEvt)->score); BSP_updateScreen(); 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(); QTimeEvt_disarm(&me->blinkTimeEvt); QTimeEvt_disarm(&me->screenTimeEvt); BSP_updateScore(0); /* update the score on the display */ 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(); BSP_displayOff(); /* power down the display */ QTimeEvt_armX(&me->screenTimeEvt, BSP_TICKS_PER_SEC*3U, 0U); QTimeEvt_disarm(&me->screenTimeEvt); BSP_displayOn(); /* power up the display */ 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); QTimeEvt_disarm(&me->screenTimeEvt); BSP_clearFB(); BSP_updateScreen(); /* clear the screen */ BSP_clearFB(); BSP_updateScreen(); QF_stop(); /* stop QF and cleanup */ Ship Active Object vertical position of the ship in the 8s2 fixed-point notation. (void)e; /* avoid the compiler warning 'usused parameter' */ QActive_subscribe(&me->super, TIME_TICK_SIG); QActive_subscribe(&me->super, PLAYER_TRIGGER_SIG); /* local signals... */ //QS_SIG_DICTIONARY(PLAYER_SHIP_MOVE_SIG, me); QS_SIG_DICTIONARY(TAKE_OFF_SIG, me); QS_SIG_DICTIONARY(HIT_WALL_SIG, me); QS_SIG_DICTIONARY(HIT_MINE_SIG, me); QS_SIG_DICTIONARY(DESTROYED_MINE_SIG, me); ScoreEvt *sev; me->score = 0U; /* reset the score */ sev = Q_NEW(ScoreEvt, SCORE_SIG); sev->score = me->score; QACTIVE_POST(AO_Tunnel, (QEvt *)sev, me); /* lauch the ship from the initial position */ me->x = GAME_SHIP_X; me->y = (GAME_SHIP_Y << 2); ObjectImageEvt *oie; if (BSP_isThrottle()) { if (me->y > 0) { me->y -= 1U; } } else { if (me->y < (GAME_TUNNEL_HEIGHT << 2)) { me->y += 1U; } } /* tell the Tunnel to draw the Ship and test for hits */ oie = Q_NEW(ObjectImageEvt, SHIP_IMG_SIG); oie->x = me->x; oie->y = (uint8_t)(me->y >> 2); oie->bmp = SHIP_BMP; QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); ++me->score; /* increment the score for surviving another tick */ if ((me->score % 10U) == 0U) { /* is the score "round"? */ ScoreEvt *sev = Q_NEW(ScoreEvt, SCORE_SIG); sev->score = me->score; QACTIVE_POST(AO_Tunnel, (QEvt *)sev, me); } ObjectPosEvt *ope = Q_NEW(ObjectPosEvt, MISSILE_FIRE_SIG); ope->x = me->x; ope->y = (me->y >> 2) + SHIP_HEIGHT - 1U; QACTIVE_POST(AO_Missile, (QEvt *)ope, me); me->score += Q_EVT_CAST(ScoreEvt)->score; /* the score will be sent to the Tunnel by the next TIME_TICK */ me->exp_ctr = 0U; me->exp_ctr < 15U ObjectImageEvt *oie; ++me->exp_ctr; /* tell the Tunnel to draw the current stage of Explosion */ oie = Q_NEW(ObjectImageEvt, EXPLOSION_SIG); oie->bmp = EXPLOSION0_BMP + (me->exp_ctr >> 2); oie->x = me->x; /* x of explosion */ oie->y = (int8_t)((int)(me->y >> 2) - 4U + SHIP_HEIGHT); QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); ScoreEvt *gameOver = Q_NEW(ScoreEvt, GAME_OVER_SIG); gameOver->score = me->score; QACTIVE_POST(AO_Tunnel, (QEvt *)gameOver, me); Missile Active Object (void)e; QActive_subscribe(&me->super, TIME_TICK_SIG); /* local signals */ QS_SIG_DICTIONARY(MISSILE_FIRE_SIG, me); QS_SIG_DICTIONARY(HIT_WALL_SIG, me); QS_SIG_DICTIONARY(DESTROYED_MINE_SIG, me); me->x = Q_EVT_CAST(ObjectPosEvt)->x; me->y = Q_EVT_CAST(ObjectPosEvt)->y; me->x + GAME_MISSILE_SPEED_X < GAME_TUNNEL_WIDTH ObjectImageEvt *oie; me->x += GAME_MISSILE_SPEED_X; /*tell the Tunnel to draw the Missile and test for wall hits*/ oie = Q_NEW(ObjectImageEvt, MISSILE_IMG_SIG); oie->x = me->x; oie->y = me->y; oie->bmp = MISSILE_BMP; QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); QACTIVE_POST(AO_Ship, e, me); me->exp_ctr = 0U; (me->x >= GAME_SPEED_X) && (me->exp_ctr < 15U) ObjectImageEvt *oie; ++me->exp_ctr; /* advance the explosion counter */ me->x -= GAME_SPEED_X; /* move the explosion by one step */ /* tell the Tunnel to render the current stage of Explosion */ oie = Q_NEW(ObjectImageEvt, EXPLOSION_SIG); oie->x = me->x + 3U; /* x-pos of explosion */ oie->y = (int8_t)((int)me->y - 4U); /* y-pos */ oie->bmp = EXPLOSION0_BMP + (me->exp_ctr >> 2); QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); The Mine1 orthogonal component static uint8_t dict_sent; if (!dict_sent) { QS_OBJ_DICTIONARY(&l_mine1[0]); /* obj. dictionaries for Mine1 pool */ QS_OBJ_DICTIONARY(&l_mine1[1]); QS_OBJ_DICTIONARY(&l_mine1[2]); QS_OBJ_DICTIONARY(&l_mine1[3]); QS_OBJ_DICTIONARY(&l_mine1[4]); QS_FUN_DICTIONARY(&Mine1_initial);/*fun. dictionaries for Mine1 HSM */ QS_FUN_DICTIONARY(&Mine1_unused); QS_FUN_DICTIONARY(&Mine1_used); QS_FUN_DICTIONARY(&Mine1_planted); QS_FUN_DICTIONARY(&Mine1_exploding); dict_sent = 1U; } /* local signals */ QS_SIG_DICTIONARY(MINE_PLANT_SIG, me); QS_SIG_DICTIONARY(MINE_DISABLED_SIG, me); QS_SIG_DICTIONARY(MINE_RECYCLE_SIG, me); QS_SIG_DICTIONARY(SHIP_IMG_SIG, me); QS_SIG_DICTIONARY(MISSILE_IMG_SIG, me); (void)e; /* avoid the "unreferenced parameter" warning */ me->x = Q_EVT_CAST(ObjectPosEvt)->x; me->y = Q_EVT_CAST(ObjectPosEvt)->y; /* tell the Tunnel that this mine is becoming disabled */ MineEvt *mev = Q_NEW(MineEvt, MINE_DISABLED_SIG); mev->id = MINE_ID(me); QACTIVE_POST(AO_Tunnel, (QEvt *)mev, me); me->x >= GAME_SPEED_X ObjectImageEvt *oie; me->x -= GAME_SPEED_X; /* move the mine 1 step */ /* tell the Tunnel to draw the Mine */ oie = Q_NEW(ObjectImageEvt, MINE_IMG_SIG); oie->x = me->x; oie->y = me->y; oie->bmp = MINE1_BMP; QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); uint8_t x = Q_EVT_CAST(ObjectImageEvt)->x; uint8_t y = Q_EVT_CAST(ObjectImageEvt)->y; uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)->bmp; BSP_doBitmapsOverlap(MINE1_BMP, me->x, me->y, bmp, x, y) static MineEvt const mine1_hit = { { HIT_MINE_SIG, 0U, 0U }, /* the QEvt base instance */ 1U /* type of the mine (1 for Mine type-1) */ }; QACTIVE_POST(AO_Ship, (QEvt *)&mine1_hit, me); /* go straight to 'disabled' and let the Ship do * the exploding */ uint8_t x = Q_EVT_CAST(ObjectImageEvt)->x; uint8_t y = Q_EVT_CAST(ObjectImageEvt)->y; uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)->bmp; BSP_doBitmapsOverlap(MINE1_BMP, me->x, me->y, bmp, x, y) static ScoreEvt const mine1_destroyed = { { DESTROYED_MINE_SIG, 0U, 0U }, /* the QEvt base instance */ 25U /* score for destroying Mine type-1 */ }; QACTIVE_POST(AO_Missile, (QEvt *)&mine1_destroyed, me); me->exp_ctr = 0U; (me->x >= GAME_SPEED_X) && (me->exp_ctr < 15) ObjectImageEvt *oie; ++me->exp_ctr; /* advance the explosion counter */ me->x -= GAME_SPEED_X; /* move explosion by 1 step */ /* tell the Game to render the current stage of Explosion */ oie = Q_NEW(ObjectImageEvt, EXPLOSION_SIG); oie->x = me->x + 1U; /* x of explosion */ oie->y = (int8_t)((int)me->y - 4 + 2); /* y of explosion */ oie->bmp = EXPLOSION0_BMP + (me->exp_ctr >> 2); QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); The Mine2 orthogonal component static uint8_t dict_sent; if (!dict_sent) { /* object dictionaries for Mine2 pool... */ QS_OBJ_DICTIONARY(&l_mine2[0]); QS_OBJ_DICTIONARY(&l_mine2[1]); QS_OBJ_DICTIONARY(&l_mine2[2]); QS_OBJ_DICTIONARY(&l_mine2[3]); QS_OBJ_DICTIONARY(&l_mine2[4]); /*function dictionaries for Mine2 HSM... */ QS_FUN_DICTIONARY(&Mine2_initial); QS_FUN_DICTIONARY(&Mine2_unused); QS_FUN_DICTIONARY(&Mine2_used); QS_FUN_DICTIONARY(&Mine2_planted); QS_FUN_DICTIONARY(&Mine2_exploding); dict_sent = 1U; } /* local signals... */ QS_SIG_DICTIONARY(MINE_PLANT_SIG, me); QS_SIG_DICTIONARY(MINE_DISABLED_SIG, me); QS_SIG_DICTIONARY(MINE_RECYCLE_SIG, me); QS_SIG_DICTIONARY(SHIP_IMG_SIG, me); QS_SIG_DICTIONARY(MISSILE_IMG_SIG, me); (void)e; /* avoid the "unreferenced parameter" warning */ me->x = Q_EVT_CAST(ObjectPosEvt)->x; me->y = Q_EVT_CAST(ObjectPosEvt)->y; /* tell the Tunnel that this mine is becoming disabled */ MineEvt *mev = Q_NEW(MineEvt, MINE_DISABLED_SIG); mev->id = MINE_ID(me); QACTIVE_POST(AO_Tunnel, (QEvt *)mev, me); me->x >= GAME_SPEED_X ObjectImageEvt *oie; me->x -= GAME_SPEED_X; /* move the mine 1 step */ /* tell the Tunnel to draw the Mine */ oie = Q_NEW(ObjectImageEvt, MINE_IMG_SIG); oie->x = me->x; oie->y = me->y; oie->bmp = MINE2_BMP; QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); uint8_t x = Q_EVT_CAST(ObjectImageEvt)->x; uint8_t y = Q_EVT_CAST(ObjectImageEvt)->y; uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)->bmp; BSP_doBitmapsOverlap(MINE2_BMP, me->x, me->y, bmp, x, y) static MineEvt const mine1_hit = { { HIT_MINE_SIG, 0U, 0U }, /* the QEvt base instance */ 2U /* type of the mine (2 for Mine type-2) */ }; QACTIVE_POST(AO_Ship, (QEvt *)&mine1_hit, me); /* go straight to 'disabled' and let the Ship do * the exploding */ uint8_t x = Q_EVT_CAST(ObjectImageEvt)->x; uint8_t y = Q_EVT_CAST(ObjectImageEvt)->y; uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)->bmp; BSP_doBitmapsOverlap(MINE2_MISSILE_BMP, me->x, me->y, bmp, x, y) /* NOTE: Mine type-2 is nastier than Mine type-1. * The type-2 mine can hit the Ship with any of its * "tentacles". However, it can be destroyed by the * Missile only by hitting its center, defined as * a smaller bitmap MINE2_MISSILE_BMP. */ static ScoreEvt const mine2_destroyed = { { DESTROYED_MINE_SIG, 0U, 0U }, /* the QEvt base instance */ 45U /* score for destroying Mine type-2 */ }; QACTIVE_POST(AO_Missile, (QEvt *)&mine2_destroyed, me); me->exp_ctr = 0U; (me->x >= GAME_SPEED_X) && (me->exp_ctr < 15U) ObjectImageEvt *oie; ++me->exp_ctr; /* advance the explosion counter */ me->x -= GAME_SPEED_X; /* move explosion by 1 step */ /* tell the Game to render the current stage of Explosion */ oie = Q_NEW(ObjectImageEvt, EXPLOSION_SIG); oie->x = me->x + 1U; /* x of explosion */ oie->y = (int8_t)((int)me->y - 4 + 2); /* y of explosion */ oie->bmp = EXPLOSION0_BMP + (me->exp_ctr >> 2); QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me); /* opaque AO pointer */ = &l_tunnel.super; /* opaque AO pointer */ = &l_ship.super; /* opaque AO pointer */ = &l_missile.super; uint8_t n; Tunnel *me = &l_tunnel; QActive_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; Ship *me = &l_ship; QActive_ctor(&me->super, Q_STATE_CAST(&Ship_initial)); me->x = GAME_SHIP_X; me->y = (GAME_SHIP_Y << 2); Missile *me = &l_missile; QActive_ctor(&me->super, Q_STATE_CAST(&Missile_initial)); Mine1 *me; Q_REQUIRE(id < GAME_MINES_MAX); me = &l_mine1[id]; /* superclass' ctor */ QHsm_ctor(&me->super, Q_STATE_CAST(&Mine1_initial)); return (QHsm *)me; Mine2 *me; Q_REQUIRE(id < GAME_MINES_MAX); me = &l_mine2[id]; /* superclass' ctor */ QHsm_ctor(&me->super, Q_STATE_CAST(&Mine2_initial)); return (QHsm *)me; #ifndef GAME_H #define GAME_H enum GameSignals { /* signals used in the game */ TIME_TICK_SIG = Q_USER_SIG, /* published from tick ISR */ PLAYER_TRIGGER_SIG, /* published by Player (ISR) to trigger the Missile */ PLAYER_QUIT_SIG, /* published by Player (ISR) to quit the game */ GAME_OVER_SIG, /* published by Ship when it finishes exploding */ /* insert other published signals here ... */ MAX_PUB_SIG, /* the last published signal */ PLAYER_SHIP_UP_SIG, /* posted by Player (ISR) to Ship to move it up */ PLAYER_SHIP_DOWN_SIG, /* posted by Player (ISR) to Ship to let if fall */ BLINK_TIMEOUT_SIG, /* signal for Tunnel's blink timeout event */ SCREEN_TIMEOUT_SIG, /* signal for Tunnel's screen timeout event */ TAKE_OFF_SIG, /* from Tunnel to Ship to grant permission to take off */ HIT_WALL_SIG, /* from Tunnel to Ship when Ship hits the wall */ HIT_MINE_SIG, /* from Mine to Ship or Missile when it hits the mine */ SHIP_IMG_SIG, /* from Ship to the Tunnel to draw and check for hits */ MISSILE_IMG_SIG, /* from Missile the Tunnel to draw and check for hits */ MINE_IMG_SIG, /* sent by Mine to the Tunnel to draw the mine */ MISSILE_FIRE_SIG, /* sent by Ship to the Missile to fire */ DESTROYED_MINE_SIG, /* from Missile to Ship when Missile destroyed Mine */ EXPLOSION_SIG, /* from any exploding object to render the explosion */ MINE_PLANT_SIG, /* from Tunnel to the Mine to plant it */ MINE_DISABLED_SIG, /* from Mine to Tunnel when it becomes disabled */ MINE_RECYCLE_SIG, /* sent by Tunnel to Mine to recycle the mine */ SCORE_SIG, /* from Ship to Tunnel to adjust game level based on score */ MAX_SIG /* the last signal (keep always last) */ }; $declare${Events::ObjectPosEvt} $declare${Events::ObjectImageEvt} $declare${Events::MineEvt} $declare${Events::ScoreEvt} #define GAME_TUNNEL_WIDTH BSP_SCREEN_WIDTH #define GAME_TUNNEL_HEIGHT (BSP_SCREEN_HEIGHT - 10U) #define GAME_MINES_MAX 5U #define GAME_MINES_DIST_MIN 10U #define GAME_SPEED_X 1U #define GAME_MISSILE_SPEED_X 2U #define GAME_SHIP_X 10U #define GAME_SHIP_Y (GAME_TUNNEL_HEIGHT / 2U) #define GAME_WALLS_GAP_Y 50U #define GAME_WALLS_MIN_GAP_Y 20U enum GameBitmapIds { SHIP_BMP, MISSILE_BMP, MINE1_BMP, MINE2_BMP, MINE2_MISSILE_BMP, EXPLOSION0_BMP, EXPLOSION1_BMP, EXPLOSION2_BMP, EXPLOSION3_BMP, MAX_BMP }; /* active objects' "constructors" */ $declare${AOs::Tunnel_ctor} $declare${AOs::Ship_ctor} $declare${AOs::Missile_ctor} /* instantiation of the Mines orthogonal components */ $declare${AOs::Mine1_ctor} $declare${AOs::Mine2_ctor} /* opaque pointers to active objects in the application */ $declare${AOs::AO_Tunnel} $declare${AOs::AO_Ship} $declare${AOs::AO_Missile} #endif /* GAME_H */ #include "qpc.h" #include "bsp.h" #include "game.h" /* Q_DEFINE_THIS_FILE */ /* local objects -----------------------------------------------------------*/ $declare${AOs::Missile} static Missile l_missile; /* the sole instance of the Missile active object */ /* Public-scope objects ----------------------------------------------------*/ $define${AOs::AO_Missile} /* Active object definition ------------------------------------------------*/ $define${AOs::Missile_ctor} $define${AOs::Missile} #include "qpc.h" #include "bsp.h" #include "game.h" /* Q_DEFINE_THIS_FILE */ #define SHIP_WIDTH 5 #define SHIP_HEIGHT 3 /* encapsulated delcaration of the Ship active object ----------------------*/ $declare${AOs::Ship} /* local objects -----------------------------------------------------------*/ static Ship l_ship; /* the sole instance of the Ship active object */ /* Public-scope objects ----------------------------------------------------*/ $define${AOs::AO_Ship} /* Active object definition ------------------------------------------------*/ $define${AOs::Ship_ctor} $define${AOs::Ship} #include "qpc.h" #include "bsp.h" #include "game.h" Q_DEFINE_THIS_FILE /* local objects -----------------------------------------------------------*/ $declare${AOs::Tunnel} static Tunnel l_tunnel; /* the sole instance of the Tunnel active object */ /* Public-scope objects ----------------------------------------------------*/ $define${AOs::AO_Tunnel} /* Active object definition ================================================*/ $define${AOs::Tunnel_ctor} $define${AOs::Tunnel} #include "qpc.h" #include "bsp.h" #include "game.h" Q_DEFINE_THIS_FILE /* encapsulated delcaration of the Mine1 HSM -------------------------------*/ $declare(AOs::Mine1) /* local objects -----------------------------------------------------------*/ static Mine1 l_mine1[GAME_MINES_MAX]; /* a pool of type-1 mines */ /* helper macro to provide the ID of this mine */ #define MINE_ID(me_) ((uint8_t)((me_) - l_mine1)) /* Mine1 class definition --------------------------------------------------*/ $define(AOs::Mine1_ctor) $define(AOs::Mine1) #include "qpc.h" #include "bsp.h" #include "game.h" Q_DEFINE_THIS_FILE /* encapsulated delcaration of the Mine2 HSM -------------------------------*/ $declare(AOs::Mine2) /* local objects -----------------------------------------------------------*/ static Mine2 l_mine2[GAME_MINES_MAX]; /* a pool of type-2 mines */ /* helper macro to provide the ID of this mine */ #define MINE_ID(me_) ((uint8_t)((me_) - l_mine2)) /* Mine2 class definition --------------------------------------------------*/ $define(AOs::Mine2_ctor) $define(AOs::Mine2)