Quantum Leaps 33d17c2dbd 5.8.0
2016-11-30 18:14:20 -05:00

1308 lines
47 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<model version="4.0.0" links="0">
<documentation>&quot;Fly 'n' Shoot&quot; game model from Chapters 1 &amp; 9 of PSiCC2
NOTE: Requries QP5.</documentation>
<framework name="qpc"/>
<package name="Events" stereotype="0x01">
<class name="ObjectPosEvt" superclass="qpc::QEvt">
<attribute name="x" type="uint8_t" visibility="0x00" properties="0x00"/>
<attribute name="y" type="uint8_t" visibility="0x00" properties="0x00"/>
</class>
<class name="ObjectImageEvt" superclass="qpc::QEvt">
<attribute name="x" type="uint8_t" visibility="0x00" properties="0x00"/>
<attribute name="y" type="int8_t" visibility="0x00" properties="0x00"/>
<attribute name="bmp" type="uint8_t" visibility="0x00" properties="0x00"/>
</class>
<class name="MineEvt" superclass="qpc::QEvt">
<attribute name="id" type="uint8_t" visibility="0x00" properties="0x00"/>
</class>
<class name="ScoreEvt" superclass="qpc::QEvt">
<attribute name="score" type="uint16_t" visibility="0x00" properties="0x00"/>
</class>
</package>
<package name="AOs" stereotype="0x02">
<class name="Tunnel" superclass="qpc::QActive">
<documentation>Tunnel Active Object</documentation>
<attribute name="blinkTimeEvt" type="QTimeEvt" visibility="0x02" properties="0x00"/>
<attribute name="screenTimeEvt" type="QTimeEvt" visibility="0x02" properties="0x00"/>
<attribute name="mines[GAME_MINES_MAX]" type="QMsm *" visibility="0x02" properties="0x00"/>
<attribute name="mine1_pool[GAME_MINES_MAX]" type="QMsm *" visibility="0x02" properties="0x00"/>
<attribute name="mine2_pool[GAME_MINES_MAX]" type="QMsm *" visibility="0x02" properties="0x00"/>
<attribute name="blink_ctr" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="last_mine_x" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="last_mine_y" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="wall_thickness_top" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="wall_thickness_bottom" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="wall_gap" type="uint8_t" visibility="0x02" properties="0x00"/>
<operation name="advance" type="void" visibility="0x02" properties="0x00">
<code>uint32_t rnd;
rnd = (BSP_random() &amp; 0xFFU);
/* reduce the top wall thickness 18.75% of the time */
if ((rnd &lt; 48U) &amp;&amp; (me-&gt;wall_thickness_top &gt; 0U)) {
--me-&gt;wall_thickness_top;
}
/* reduce the bottom wall thickness 18.75% of the time */
if ((rnd &gt; 208U) &amp;&amp; (me-&gt;wall_thickness_bottom &gt; 0U)) {
--me-&gt;wall_thickness_bottom;
}
rnd = (BSP_random() &amp; 0xFFU);
/* grow the bottom wall thickness 19.14% of the time */
if ((rnd &lt; 49U)
&amp;&amp; ((GAME_TUNNEL_HEIGHT
- me-&gt;wall_thickness_top
- me-&gt;wall_thickness_bottom) &gt; me-&gt;wall_gap))
{
++me-&gt;wall_thickness_bottom;
}
/* grow the top wall thickness 19.14% of the time */
if ((rnd &gt; 207U)
&amp;&amp; ((GAME_TUNNEL_HEIGHT
- me-&gt;wall_thickness_top
- me-&gt;wall_thickness_bottom) &gt; me-&gt;wall_gap))
{
++me-&gt;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-&gt;wall_thickness_top, me-&gt;wall_thickness_bottom);</code>
</operation>
<operation name="plantMine" type="void" visibility="0x02" properties="0x00">
<code>uint32_t rnd = (BSP_random() &amp; 0xFFU);
if (me-&gt;last_mine_x &gt; 0U) {
--me-&gt;last_mine_x; /* shift the last Mine 1 position to the left */
}
/* last mine far enough? */
if ((me-&gt;last_mine_x + GAME_MINES_DIST_MIN &lt; GAME_TUNNEL_WIDTH)
&amp;&amp; (rnd &lt; 8U)) /* place the mines only 5% of the time */
{
uint8_t n;
for (n = 0U; n &lt; Q_DIM(me-&gt;mines); ++n) { /*look for disabled mines */
if (me-&gt;mines[n] == (QMsm *)0) {
break;
}
}
if (n &lt; Q_DIM(me-&gt;mines)) { /* a disabled Mine found? */
ObjectPosEvt ope; /* event to dispatch to the Mine */
rnd = (BSP_random() &amp; 0xFFFFU);
if ((rnd &amp; 1U) == 0U) { /* choose the type of the mine */
me-&gt;mines[n] = me-&gt;mine1_pool[n];
}
else {
me-&gt;mines[n] = me-&gt;mine2_pool[n];
}
/* new Mine is planted by the end of the tunnel */
me-&gt;last_mine_x = GAME_TUNNEL_WIDTH - 8U;
/* choose a random y-position for the Mine in the Tunnel */
rnd %= (GAME_TUNNEL_HEIGHT
- me-&gt;wall_thickness_top
- me-&gt;wall_thickness_bottom - 4U);
me-&gt;last_mine_y = (uint8_t)(me-&gt;wall_thickness_top + 2U + rnd);
ope.super.sig = MINE_PLANT_SIG;
ope.x = me-&gt;last_mine_x;
ope.y = me-&gt;last_mine_y;
QHSM_DISPATCH(me-&gt;mines[n], (QEvt *)&amp;ope); /* direct dispatch */
}
}</code>
</operation>
<operation name="dispatchToAllMines" type="void" visibility="0x02" properties="0x00">
<parameter name="e" type="QEvt const *"/>
<code>uint8_t n;
for (n = 0U; n &lt; GAME_MINES_MAX; ++n) {
if (me-&gt;mines[n] != (QMsm *)0) { /* is the mine used? */
QHSM_DISPATCH(me-&gt;mines[n], e);
}
}</code>
</operation>
<statechart>
<initial target="../1/2">
<action>uint8_t n;
for (n = 0U; n &lt; GAME_MINES_MAX; ++n) {
QHSM_INIT(me-&gt;mine1_pool[n], (QEvt *)0);/*initial tran. for Mine1 */
QHSM_INIT(me-&gt;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(&amp;l_tunnel);
QS_OBJ_DICTIONARY(&amp;l_tunnel.blinkTimeEvt);
QS_OBJ_DICTIONARY(&amp;l_tunnel.screenTimeEvt);
/* function dictionaries for Tunnel HSM... */
QS_FUN_DICTIONARY(&amp;Tunnel_initial);
QS_FUN_DICTIONARY(&amp;Tunnel_final);
QS_FUN_DICTIONARY(&amp;Tunnel_active);
QS_FUN_DICTIONARY(&amp;Tunnel_show_logo);
QS_FUN_DICTIONARY(&amp;Tunnel_demo);
QS_FUN_DICTIONARY(&amp;Tunnel_playing);
QS_FUN_DICTIONARY(&amp;Tunnel_game_over);
QS_FUN_DICTIONARY(&amp;Tunnel_screen_saver);
QS_FUN_DICTIONARY(&amp;Tunnel_screen_saver_hide);
QS_FUN_DICTIONARY(&amp;Tunnel_screen_saver_show);
/* local signals... */
QS_SIG_DICTIONARY(BLINK_TIMEOUT_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(SCREEN_TIMEOUT_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(SHIP_IMG_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(MISSILE_IMG_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(MINE_IMG_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(MINE_DISABLED_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(EXPLOSION_SIG, &amp;l_tunnel);
QS_SIG_DICTIONARY(SCORE_SIG, &amp;l_tunnel);
(void)e; /* unused parameter */</action>
<initial_glyph conn="3,2,5,1,25,14,-2">
<action box="1,-2,11,2"/>
</initial_glyph>
</initial>
<state name="active">
<tran trig="MINE_DISABLED">
<action>Q_ASSERT((Q_EVT_CAST(MineEvt)-&gt;id &lt; GAME_MINES_MAX)
&amp;&amp; (me-&gt;mines[Q_EVT_CAST(MineEvt)-&gt;id] != (QMsm *)0));
me-&gt;mines[Q_EVT_CAST(MineEvt)-&gt;id] = (QMsm *)0;</action>
<tran_glyph conn="2,9,3,-1,14">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<tran trig="PLAYER_QUIT" target="../../2">
<tran_glyph conn="2,12,3,1,64,76,-40">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<state name="show_logo">
<entry>QTimeEvt_armX(&amp;me-&gt;blinkTimeEvt, BSP_TICKS_PER_SEC/2U,
BSP_TICKS_PER_SEC/2U);
QTimeEvt_armX(&amp;me-&gt;screenTimeEvt, BSP_TICKS_PER_SEC*5U, 0U);
me-&gt;blink_ctr = 0U;
BSP_paintString(24U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, &quot;Quantum LeAps&quot;);
BSP_paintString(16U, (GAME_TUNNEL_HEIGHT / 2U) + 0U, &quot;state-machine.com&quot;);
BSP_paintString(1U, GAME_TUNNEL_HEIGHT - 18U, &quot;Fire missile: BTN0&quot;);
BSP_paintString(1U, GAME_TUNNEL_HEIGHT - 10U, &quot;Fly ship up: BTN1&quot;);
BSP_updateScreen();</entry>
<exit>QTimeEvt_disarm(&amp;me-&gt;blinkTimeEvt);
QTimeEvt_disarm(&amp;me-&gt;screenTimeEvt);</exit>
<tran trig="SCREEN_TIMEOUT" target="../../3">
<tran_glyph conn="4,25,3,1,24,7,-2">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<tran trig="BLINK_TIMEOUT">
<action>me-&gt;blink_ctr ^= 1U; /* toggle the blink counter */</action>
<choice>
<guard>me-&gt;blink_ctr == 0U</guard>
<action>BSP_paintString(24U + 8U*6U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, &quot;LeAps&quot;);
BSP_updateScreen();</action>
<choice_glyph conn="18,22,4,-1,-3,7">
<action box="1,-3,15,2"/>
</choice_glyph>
</choice>
<choice>
<guard>else</guard>
<action>BSP_paintString(24U + 8U*6U, (GAME_TUNNEL_HEIGHT / 2U) - 8U, &quot;LeaPs&quot;);
BSP_updateScreen();</action>
<choice_glyph conn="18,22,5,-1,7">
<action box="1,0,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,22,3,-1,14">
<action box="0,-2,12,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,14,22,14">
<entry box="1,2,5,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state name="demo">
<entry>me-&gt;last_mine_x = 0U; /* last mine at right edge of the tunnel */
me-&gt;last_mine_y = 0U;
/* set the tunnel properties... */
me-&gt;wall_thickness_top = 0U;
me-&gt;wall_thickness_bottom = 0U;
me-&gt;wall_gap = GAME_WALLS_GAP_Y;
/* clear the tunnel walls */
BSP_clearWalls();
QTimeEvt_armX(&amp;me-&gt;blinkTimeEvt, BSP_TICKS_PER_SEC/2U,
BSP_TICKS_PER_SEC/2U); /* every 1/2 sec */
QTimeEvt_armX(&amp;me-&gt;screenTimeEvt, BSP_TICKS_PER_SEC*20U, 0U);
me-&gt;blink_ctr = 0U; /* init the blink counter */</entry>
<exit>QTimeEvt_disarm(&amp;me-&gt;blinkTimeEvt);
QTimeEvt_disarm(&amp;me-&gt;screenTimeEvt);</exit>
<tran trig="BLINK_TIMEOUT">
<action>me-&gt;blink_ctr ^= 1U; /* toggle the blink cunter */</action>
<tran_glyph conn="4,42,3,-1,14">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<tran trig="SCREEN_TIMEOUT" target="../../6">
<tran_glyph conn="4,45,3,3,28">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<tran trig="TIME_TICK">
<action>Tunnel_advance(me);
if (me-&gt;blink_ctr != 0U) {
/* add the text bitmap into the frame buffer */
BSP_paintString((GAME_TUNNEL_WIDTH - 10U*6U)/2U,
(GAME_TUNNEL_HEIGHT - 4U)/2U,
&quot;Press BTN0&quot;);
}
BSP_updateScreen();</action>
<tran_glyph conn="4,39,3,-1,14">
<action box="0,-2,12,2"/>
</tran_glyph>
</tran>
<tran trig="PLAYER_TRIGGER" target="../../4">
<tran_glyph conn="4,48,3,1,24,7,-2">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,30,22,20">
<entry box="1,2,6,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state name="playing">
<entry>static QEvt const takeoff = { TAKE_OFF_SIG, 0U, 0U };
me-&gt;wall_gap = GAME_WALLS_GAP_Y;
QACTIVE_POST(AO_Ship, &amp;takeoff, me); /* post the TAKEOFF sig */</entry>
<exit>QEvt recycle;
recycle.sig = MINE_RECYCLE_SIG;
Tunnel_dispatchToAllMines(me, &amp;recycle); /* recycle all Mines */</exit>
<tran trig="TIME_TICK">
<action>/* render this frame on the display */
BSP_updateScreen();
Tunnel_advance(me);
Tunnel_plantMine(me);
Tunnel_dispatchToAllMines(me, e);</action>
<tran_glyph conn="4,62,3,-1,14">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="SHIP_IMG">
<action>uint8_t x = Q_EVT_CAST(ObjectImageEvt)-&gt;x;
int8_t y = Q_EVT_CAST(ObjectImageEvt)-&gt;y;
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)-&gt;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, &amp;hit, me);
}
BSP_paintBitmap(x, y, bmp);
Tunnel_dispatchToAllMines(me, e); /* let Mines check for hits */</action>
<tran_glyph conn="4,65,3,-1,14">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="MISSILE_IMG">
<action>uint8_t x = Q_EVT_CAST(ObjectImageEvt)-&gt;x;
int8_t y = Q_EVT_CAST(ObjectImageEvt)-&gt;y;
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)-&gt;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, &amp;hit, me);
}
BSP_paintBitmap(x, y, bmp);
Tunnel_dispatchToAllMines(me, e); /* let Mines check for hits */</action>
<tran_glyph conn="4,68,3,-1,14">
<action box="0,-2,12,2"/>
</tran_glyph>
</tran>
<tran trig="MINE_IMG">
<action>BSP_paintBitmap(Q_EVT_CAST(ObjectImageEvt)-&gt;x,
Q_EVT_CAST(ObjectImageEvt)-&gt;y,
Q_EVT_CAST(ObjectImageEvt)-&gt;bmp);</action>
<tran_glyph conn="4,71,3,-1,14">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="EXPLOSION">
<action>BSP_paintBitmap(Q_EVT_CAST(ObjectImageEvt)-&gt;x,
Q_EVT_CAST(ObjectImageEvt)-&gt;y,
Q_EVT_CAST(ObjectImageEvt)-&gt;bmp);</action>
<tran_glyph conn="4,74,3,-1,14">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<tran trig="SCORE">
<action>BSP_updateScore(Q_EVT_CAST(ScoreEvt)-&gt;score);
/* increase difficulty of the game:
* the tunnel gets narrower as the score goes up
*/
me-&gt;wall_gap = (uint8_t)(GAME_WALLS_GAP_Y
- Q_EVT_CAST(ScoreEvt)-&gt;score/100U);
if (me-&gt;wall_gap &lt; GAME_WALLS_MIN_GAP_Y) {
me-&gt;wall_gap = GAME_WALLS_MIN_GAP_Y;
}</action>
<tran_glyph conn="4,77,3,-1,14">
<action box="0,-2,6,2"/>
</tran_glyph>
</tran>
<tran trig="GAME_OVER" target="../../5">
<action>BSP_clearWalls();
BSP_updateScore(Q_EVT_CAST(ScoreEvt)-&gt;score);
BSP_updateScreen();</action>
<tran_glyph conn="4,80,3,3,26,-10,2">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,52,22,30">
<entry box="1,2,6,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state name="game_over">
<entry>QTimeEvt_armX(&amp;me-&gt;blinkTimeEvt, BSP_TICKS_PER_SEC/2U,
BSP_TICKS_PER_SEC/2U); /* every 1/2 sec */
QTimeEvt_armX(&amp;me-&gt;screenTimeEvt, BSP_TICKS_PER_SEC*5U, 0U);
me-&gt;blink_ctr = 0U;
BSP_paintString((GAME_TUNNEL_WIDTH - 6U * 9U) / 2U,
(GAME_TUNNEL_HEIGHT / 2U) - 4U,
&quot;Game Over&quot;);
BSP_updateScreen();</entry>
<exit>QTimeEvt_disarm(&amp;me-&gt;blinkTimeEvt);
QTimeEvt_disarm(&amp;me-&gt;screenTimeEvt);
BSP_updateScore(0); /* update the score on the display */</exit>
<tran trig="BLINK_TIMEOUT">
<action>me-&gt;blink_ctr ^= 1U; /* toggle the blink counter */
BSP_paintString((GAME_TUNNEL_WIDTH - 6U*9U) / 2U,
(GAME_TUNNEL_HEIGHT / 2U) - 4U,
((me-&gt;blink_ctr == 0U)
? &quot;Game Over&quot;
: &quot; &quot;));
BSP_updateScreen();</action>
<tran_glyph conn="32,80,3,-1,14">
<action box="0,-2,12,2"/>
</tran_glyph>
</tran>
<tran trig="SCREEN_TIMEOUT" target="../../3">
<tran_glyph conn="32,77,3,1,30,-11,-32,-19,-4">
<action box="0,-2,14,2"/>
</tran_glyph>
</tran>
<state_glyph node="32,68,28,14">
<entry box="1,2,6,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state name="screen_saver">
<initial target="../2">
<initial_glyph conn="36,34,5,1,20,8,-2">
<action box="1,-2,6,2"/>
</initial_glyph>
</initial>
<tran trig="PLAYER_TRIGGER" target="../../3">
<tran_glyph conn="32,38,3,1,30,-10,-32,6,-4">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<state name="screen_saver_hide">
<entry>BSP_displayOff(); /* power down the display */
QTimeEvt_armX(&amp;me-&gt;screenTimeEvt, BSP_TICKS_PER_SEC*3U, 0U);</entry>
<exit>QTimeEvt_disarm(&amp;me-&gt;screenTimeEvt);
BSP_displayOn(); /* power up the display */</exit>
<tran trig="SCREEN_TIMEOUT" target="../../3">
<tran_glyph conn="36,48,3,1,20,6,-2">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<state_glyph node="36,40,18,10">
<entry box="1,2,5,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state name="screen_saver_show">
<entry>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)),
&quot;Press BTN0&quot;);
BSP_updateScreen();
QTimeEvt_armX(&amp;me-&gt;screenTimeEvt, BSP_TICKS_PER_SEC/2U, 0U);</entry>
<exit>QTimeEvt_disarm(&amp;me-&gt;screenTimeEvt);
BSP_clearFB();
BSP_updateScreen();</exit>
<tran trig="SCREEN_TIMEOUT" target="../../2">
<tran_glyph conn="36,60,3,1,22,-15,-4">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<state_glyph node="36,52,18,10">
<entry box="1,2,6,2"/>
<exit box="1,4,5,2"/>
</state_glyph>
</state>
<state_glyph node="32,30,28,34"/>
</state>
<state_glyph node="2,4,62,80"/>
</state>
<state name="final">
<entry>/* clear the screen */
BSP_clearFB();
BSP_updateScreen();
QF_stop(); /* stop QF and cleanup */</entry>
<state_glyph node="2,86,24,6">
<entry box="1,2,6,2"/>
</state_glyph>
</state>
<state_diagram size="68,94"/>
</statechart>
</class>
<class name="Ship" superclass="qpc::QActive">
<documentation>Ship Active Object</documentation>
<attribute name="x" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="y" type="uint16_t" visibility="0x02" properties="0x00">
<documentation>vertical position of the ship in the 8s2 fixed-point notation.</documentation>
</attribute>
<attribute name="exp_ctr" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="score" type="uint16_t" visibility="0x02" properties="0x00"/>
<statechart>
<initial target="../1">
<action>(void)e; /* avoid the compiler warning 'usused parameter' */
QActive_subscribe((QActive *)me, TIME_TICK_SIG);
QActive_subscribe((QActive *)me, PLAYER_TRIGGER_SIG);
/* object dictionaries... */
QS_OBJ_DICTIONARY(&amp;l_ship);
/* function dictionaries for Ship HSM... */
QS_FUN_DICTIONARY(&amp;Ship_initial);
QS_FUN_DICTIONARY(&amp;Ship_active);
QS_FUN_DICTIONARY(&amp;Ship_parked);
QS_FUN_DICTIONARY(&amp;Ship_flying);
QS_FUN_DICTIONARY(&amp;Ship_exploding);
/* local signals... */
//QS_SIG_DICTIONARY(PLAYER_SHIP_MOVE_SIG, &amp;l_ship);
QS_SIG_DICTIONARY(TAKE_OFF_SIG, &amp;l_ship);
QS_SIG_DICTIONARY(HIT_WALL_SIG, &amp;l_ship);
QS_SIG_DICTIONARY(HIT_MINE_SIG, &amp;l_ship);
QS_SIG_DICTIONARY(DESTROYED_MINE_SIG, &amp;l_ship);</action>
<initial_glyph conn="3,2,5,1,35,4,-2">
<action box="1,-2,6,2"/>
</initial_glyph>
</initial>
<state name="active">
<initial target="../1">
<initial_glyph conn="3,8,5,1,28,4,-4">
<action box="1,-2,6,2"/>
</initial_glyph>
</initial>
<state name="parked">
<tran trig="TAKE_OFF" target="../../2">
<tran_glyph conn="4,16,3,1,28,6,-2">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,10,23,8"/>
</state>
<state name="flying">
<entry>ScoreEvt *sev;
me-&gt;score = 0U; /* reset the score */
sev = Q_NEW(ScoreEvt, SCORE_SIG);
sev-&gt;score = me-&gt;score;
QACTIVE_POST(AO_Tunnel, (QEvt *)sev, me);
/* lauch the ship from the initial hight */
me-&gt;y = (GAME_SHIP_Y &lt;&lt; 2);</entry>
<tran trig="TIME_TICK">
<action>ObjectImageEvt *oie;
if (BSP_isThrottle()) {
if (me-&gt;y &gt; 0) {
me-&gt;y -= 1U;
}
}
else {
if (me-&gt;y &lt; (GAME_TUNNEL_HEIGHT &lt;&lt; 2)) {
me-&gt;y += 1U;
}
}
/* tell the Tunnel to draw the Ship and test for hits */
oie = Q_NEW(ObjectImageEvt, SHIP_IMG_SIG);
oie-&gt;x = me-&gt;x;
oie-&gt;y = (uint8_t)(me-&gt;y &gt;&gt; 2);
oie-&gt;bmp = SHIP_BMP;
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);
++me-&gt;score; /* increment the score for surviving another tick */
if ((me-&gt;score % 10U) == 0U) { /* is the score &quot;round&quot;? */
ScoreEvt *sev = Q_NEW(ScoreEvt, SCORE_SIG);
sev-&gt;score = me-&gt;score;
QACTIVE_POST(AO_Tunnel, (QEvt *)sev, me);
}</action>
<tran_glyph conn="4,27,3,-1,16">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="PLAYER_TRIGGER">
<action>ObjectPosEvt *ope = Q_NEW(ObjectPosEvt, MISSILE_FIRE_SIG);
ope-&gt;x = me-&gt;x;
ope-&gt;y = (me-&gt;y &gt;&gt; 2) + SHIP_HEIGHT - 1U;
QACTIVE_POST(AO_Missile, (QEvt *)ope, me);</action>
<tran_glyph conn="4,30,3,-1,16">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<tran trig="DESTROYED_MINE">
<action>me-&gt;score += Q_EVT_CAST(ScoreEvt)-&gt;score;
/* the score will be sent to the Tunnel by the next TIME_TICK */</action>
<tran_glyph conn="4,33,3,-1,16">
<action box="0,-2,13,2"/>
</tran_glyph>
</tran>
<tran trig="HIT_WALL" target="../../3">
<tran_glyph conn="4,36,3,1,28,10,-2">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<tran trig="HIT_MINE" target="../../3">
<tran_glyph conn="4,39,3,1,28,7,-2">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,20,26,22">
<entry box="1,2,5,2"/>
</state_glyph>
</state>
<state name="exploding">
<entry>me-&gt;exp_ctr = 0U;</entry>
<tran trig="TIME_TICK">
<choice>
<guard>me-&gt;exp_ctr &lt; 15U</guard>
<action>ObjectImageEvt *oie;
++me-&gt;exp_ctr;
/* tell the Tunnel to draw the current stage of Explosion */
oie = Q_NEW(ObjectImageEvt, EXPLOSION_SIG);
oie-&gt;bmp = EXPLOSION0_BMP + (me-&gt;exp_ctr &gt;&gt; 2);
oie-&gt;x = me-&gt;x; /* x of explosion */
oie-&gt;y = (int8_t)((int)(me-&gt;y &gt;&gt; 2) - 4U + SHIP_HEIGHT);
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="13,52,5,-1,15">
<action box="1,0,15,2"/>
</choice_glyph>
</choice>
<choice target="../../../1">
<guard brief="else"/>
<action>ScoreEvt *gameOver = Q_NEW(ScoreEvt, GAME_OVER_SIG);
gameOver-&gt;score = me-&gt;score;
QACTIVE_POST(AO_Tunnel, (QEvt *)gameOver, me);</action>
<choice_glyph conn="13,52,4,1,4,21,-42,-7">
<action box="1,4,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,52,3,-1,9">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,44,26,14">
<entry box="1,2,13,4"/>
</state_glyph>
</state>
<state_glyph node="2,4,34,56"/>
</state>
<state_diagram size="40,62"/>
</statechart>
</class>
<class name="Missile" superclass="qpc::QActive">
<documentation>Missile Active Object</documentation>
<attribute name="x" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="y" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="exp_ctr" type="uint8_t" visibility="0x02" properties="0x00"/>
<statechart>
<initial target="../1">
<action>(void)e;
QActive_subscribe((QActive *)me, TIME_TICK_SIG);
QS_OBJ_DICTIONARY(&amp;l_missile); /* object dictionary for Missile object */
QS_FUN_DICTIONARY(&amp;Missile_initial); /* dictionaries for Missile HSM */
QS_FUN_DICTIONARY(&amp;Missile_armed);
QS_FUN_DICTIONARY(&amp;Missile_flying);
QS_FUN_DICTIONARY(&amp;Missile_exploding);
QS_SIG_DICTIONARY(MISSILE_FIRE_SIG, &amp;l_missile); /* local signals */
QS_SIG_DICTIONARY(HIT_WALL_SIG, &amp;l_missile);
QS_SIG_DICTIONARY(DESTROYED_MINE_SIG, &amp;l_missile);</action>
<initial_glyph conn="3,3,5,1,35,4,-2">
<action box="1,-2,6,2"/>
</initial_glyph>
</initial>
<state name="armed">
<tran trig="MISSILE_FIRE" target="../../2">
<action>me-&gt;x = Q_EVT_CAST(ObjectPosEvt)-&gt;x;
me-&gt;y = Q_EVT_CAST(ObjectPosEvt)-&gt;y;</action>
<tran_glyph conn="3,11,3,1,35,6,-2">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<state_glyph node="3,5,33,8"/>
</state>
<state name="flying">
<tran trig="TIME_TICK">
<choice>
<guard>me-&gt;x + GAME_MISSILE_SPEED_X &lt; GAME_TUNNEL_WIDTH</guard>
<action brief="...">ObjectImageEvt *oie;
me-&gt;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-&gt;x = me-&gt;x;
oie-&gt;y = me-&gt;y;
oie-&gt;bmp = MISSILE_BMP;
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="12,21,5,-1,20">
<action box="1,0,22,4"/>
</choice_glyph>
</choice>
<choice target="../../../1">
<guard brief="else"/>
<choice_glyph conn="12,21,4,1,5,28,-17,-4">
<action box="1,5,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="3,21,3,-1,9">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="HIT_WALL" target="../../3">
<tran_glyph conn="3,33,3,1,35,6,-2">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<tran trig="DESTROYED_MINE" target="../../1">
<action>QACTIVE_POST(AO_Ship, e, me);</action>
<tran_glyph conn="3,30,3,1,39,-21,-6">
<action box="0,-2,15,2"/>
</tran_glyph>
</tran>
<state_glyph node="3,15,33,20"/>
</state>
<state name="exploding">
<entry>me-&gt;exp_ctr = 0U;</entry>
<tran trig="TIME_TICK">
<choice>
<guard>(me-&gt;x &gt;= GAME_SPEED_X) &amp;&amp; (me-&gt;exp_ctr &lt; 15U)</guard>
<action brief="...">ObjectImageEvt *oie;
++me-&gt;exp_ctr; /* advance the explosion counter */
me-&gt;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-&gt;x = me-&gt;x + 3U; /* x-pos of explosion */
oie-&gt;y = (int8_t)((int)me-&gt;y - 4U); /* y-pos */
oie-&gt;bmp = EXPLOSION0_BMP + (me-&gt;exp_ctr &gt;&gt; 2);
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="12,46,5,-1,20">
<action box="1,0,19,4"/>
</choice_glyph>
</choice>
<choice target="../../../1">
<guard brief="else"/>
<choice_glyph conn="12,46,4,1,5,32,-42,-8">
<action box="1,5,7,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="3,46,3,-1,9">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<state_glyph node="3,37,33,16">
<entry box="1,2,14,4"/>
</state_glyph>
</state>
<state_diagram size="46,55"/>
</statechart>
</class>
<class name="Mine1" superclass="qpc::QHsm">
<documentation>The Mine1 orthogonal component</documentation>
<attribute name="x" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="y" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="exp_ctr" type="uint8_t" visibility="0x00" properties="0x00"/>
<statechart>
<initial target="../1">
<action>static uint8_t dict_sent;
if (!dict_sent) {
QS_OBJ_DICTIONARY(&amp;l_mine1[0]); /* obj. dictionaries for Mine1 pool */
QS_OBJ_DICTIONARY(&amp;l_mine1[1]);
QS_OBJ_DICTIONARY(&amp;l_mine1[2]);
QS_OBJ_DICTIONARY(&amp;l_mine1[3]);
QS_OBJ_DICTIONARY(&amp;l_mine1[4]);
QS_FUN_DICTIONARY(&amp;Mine1_initial);/*fun. dictionaries for Mine1 HSM */
QS_FUN_DICTIONARY(&amp;Mine1_unused);
QS_FUN_DICTIONARY(&amp;Mine1_used);
QS_FUN_DICTIONARY(&amp;Mine1_planted);
QS_FUN_DICTIONARY(&amp;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 &quot;unreferenced parameter&quot; warning */</action>
<initial_glyph conn="2,2,5,1,31,4,-2">
<action box="0,-2,11,2"/>
</initial_glyph>
</initial>
<state name="unused">
<tran trig="MINE_PLANT" target="../../2/1">
<action>me-&gt;x = Q_EVT_CAST(ObjectPosEvt)-&gt;x;
me-&gt;y = Q_EVT_CAST(ObjectPosEvt)-&gt;y;</action>
<tran_glyph conn="2,10,3,1,43,16,-8">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,4,29,8"/>
</state>
<state name="used">
<exit brief="...">/* tell the Tunnel that this mine is becoming disabled */
MineEvt *mev = Q_NEW(MineEvt, MINE_DISABLED_SIG);
mev-&gt;id = MINE_ID(me);
QACTIVE_POST(AO_Tunnel, (QEvt *)mev, me);</exit>
<tran trig="MINE_RECYCLE" target="../../1">
<tran_glyph conn="2,21,3,1,41,-13,-12">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<state name="planted">
<tran trig="TIME_TICK">
<choice>
<guard>me-&gt;x &gt;= GAME_SPEED_X</guard>
<action>ObjectImageEvt *oie;
me-&gt;x -= GAME_SPEED_X; /* move the mine 1 step */
/* tell the Tunnel to draw the Mine */
oie = Q_NEW(ObjectImageEvt, MINE_IMG_SIG);
oie-&gt;x = me-&gt;x;
oie-&gt;y = me-&gt;y;
oie-&gt;bmp = MINE1_BMP;
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="15,30,5,-1,20">
<action box="1,0,20,2"/>
</choice_glyph>
</choice>
<choice target="../../../../1">
<guard brief="else"/>
<choice_glyph conn="15,30,4,1,4,32,-26,-16">
<action box="1,4,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,30,3,-1,11">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<tran trig="SHIP_IMG">
<action>uint8_t x = Q_EVT_CAST(ObjectImageEvt)-&gt;x;
uint8_t y = Q_EVT_CAST(ObjectImageEvt)-&gt;y;
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)-&gt;bmp;</action>
<choice target="../../../../1">
<guard brief="collision with MINE1_BMP?">BSP_doBitmapsOverlap(MINE1_BMP, me-&gt;x, me-&gt;y, bmp, x, y)</guard>
<action brief="...">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 *)&amp;mine1_hit, me);
/* go straight to 'disabled' and let the Ship do
* the exploding */</action>
<choice_glyph conn="15,37,5,1,34,-29,-18">
<action box="1,0,22,4"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,37,3,-1,11">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<tran trig="MISSILE_IMG">
<action>uint8_t x = Q_EVT_CAST(ObjectImageEvt)-&gt;x;
uint8_t y = Q_EVT_CAST(ObjectImageEvt)-&gt;y;
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)-&gt;bmp;</action>
<choice target="../../../2">
<guard brief="collision with MINE1_BMP?">BSP_doBitmapsOverlap(MINE1_BMP, me-&gt;x, me-&gt;y, bmp, x, y)</guard>
<action brief="...">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 *)&amp;mine1_destroyed, me);</action>
<choice_glyph conn="15,43,5,1,24,9,-2">
<action box="1,0,22,4"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,43,3,-1,11">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,24,33,24"/>
</state>
<state name="exploding">
<entry>me-&gt;exp_ctr = 0U;</entry>
<tran trig="TIME_TICK">
<choice>
<guard brief="still on screen?">(me-&gt;x &gt;= GAME_SPEED_X) &amp;&amp; (me-&gt;exp_ctr &lt; 15)</guard>
<action>ObjectImageEvt *oie;
++me-&gt;exp_ctr; /* advance the explosion counter */
me-&gt;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-&gt;x = me-&gt;x + 1U; /* x of explosion */
oie-&gt;y = (int8_t)((int)me-&gt;y - 4 + 2); /* y of explosion */
oie-&gt;bmp = EXPLOSION0_BMP + (me-&gt;exp_ctr &gt;&gt; 2);
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="14,57,5,-1,21">
<action box="1,0,20,2"/>
</choice_glyph>
</choice>
<choice target="../../../../1">
<guard brief="else"/>
<choice_glyph conn="14,57,4,1,5,37,-54,-20">
<action box="1,5,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,57,3,-1,10">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,50,33,14">
<entry box="1,2,5,2"/>
</state_glyph>
</state>
<state_glyph node="2,14,39,52">
<exit box="1,2,5,2"/>
</state_glyph>
</state>
<state_diagram size="53,68"/>
</statechart>
</class>
<class name="Mine2" superclass="qpc::QHsm">
<documentation>The Mine2 orthogonal component</documentation>
<attribute name="x" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="y" type="uint8_t" visibility="0x02" properties="0x00"/>
<attribute name="exp_ctr" type="uint8_t" visibility="0x00" properties="0x00"/>
<statechart>
<initial target="../1">
<action>static uint8_t dict_sent;
if (!dict_sent) {
/* object dictionaries for Mine2 pool... */
QS_OBJ_DICTIONARY(&amp;l_mine2[0]);
QS_OBJ_DICTIONARY(&amp;l_mine2[1]);
QS_OBJ_DICTIONARY(&amp;l_mine2[2]);
QS_OBJ_DICTIONARY(&amp;l_mine2[3]);
QS_OBJ_DICTIONARY(&amp;l_mine2[4]);
/*function dictionaries for Mine2 HSM... */
QS_FUN_DICTIONARY(&amp;Mine2_initial);
QS_FUN_DICTIONARY(&amp;Mine2_unused);
QS_FUN_DICTIONARY(&amp;Mine2_used);
QS_FUN_DICTIONARY(&amp;Mine2_planted);
QS_FUN_DICTIONARY(&amp;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 &quot;unreferenced parameter&quot; warning */</action>
<initial_glyph conn="2,2,5,1,31,4,-2">
<action box="1,-2,6,2"/>
</initial_glyph>
</initial>
<state name="unused">
<tran trig="MINE_PLANT" target="../../2/1">
<action>me-&gt;x = Q_EVT_CAST(ObjectPosEvt)-&gt;x;
me-&gt;y = Q_EVT_CAST(ObjectPosEvt)-&gt;y;</action>
<tran_glyph conn="2,10,3,1,43,16,-8">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<state_glyph node="2,4,29,8"/>
</state>
<state name="used">
<exit brief="...">/* tell the Tunnel that this mine is becoming disabled */
MineEvt *mev = Q_NEW(MineEvt, MINE_DISABLED_SIG);
mev-&gt;id = MINE_ID(me);
QACTIVE_POST(AO_Tunnel, (QEvt *)mev, me);</exit>
<tran trig="MINE_RECYCLE" target="../../1">
<tran_glyph conn="2,21,3,1,41,-13,-12">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<state name="planted">
<tran trig="TIME_TICK">
<choice>
<guard>me-&gt;x &gt;= GAME_SPEED_X</guard>
<action>ObjectImageEvt *oie;
me-&gt;x -= GAME_SPEED_X; /* move the mine 1 step */
/* tell the Tunnel to draw the Mine */
oie = Q_NEW(ObjectImageEvt, MINE_IMG_SIG);
oie-&gt;x = me-&gt;x;
oie-&gt;y = me-&gt;y;
oie-&gt;bmp = MINE2_BMP;
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="15,30,5,-1,20">
<action box="1,0,20,2"/>
</choice_glyph>
</choice>
<choice target="../../../../1">
<guard brief="else"/>
<choice_glyph conn="15,30,4,1,4,32,-26,-16">
<action box="1,4,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,30,3,-1,11">
<action box="0,-2,10,2"/>
</tran_glyph>
</tran>
<tran trig="SHIP_IMG">
<action>uint8_t x = Q_EVT_CAST(ObjectImageEvt)-&gt;x;
uint8_t y = Q_EVT_CAST(ObjectImageEvt)-&gt;y;
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)-&gt;bmp;</action>
<choice target="../../../../1">
<guard brief="collision with MINE2_BMP?">BSP_doBitmapsOverlap(MINE2_BMP, me-&gt;x, me-&gt;y, bmp, x, y)</guard>
<action>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 *)&amp;mine1_hit, me);
/* go straight to 'disabled' and let the Ship do
* the exploding */</action>
<choice_glyph conn="15,37,5,1,34,-29,-18">
<action box="1,0,21,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,37,3,-1,11">
<action box="0,-2,8,2"/>
</tran_glyph>
</tran>
<tran trig="MISSILE_IMG">
<action>uint8_t x = Q_EVT_CAST(ObjectImageEvt)-&gt;x;
uint8_t y = Q_EVT_CAST(ObjectImageEvt)-&gt;y;
uint8_t bmp = Q_EVT_CAST(ObjectImageEvt)-&gt;bmp;</action>
<choice target="../../../2">
<guard brief="collision with MINE2_MISSILE_BMP?">BSP_doBitmapsOverlap(MINE2_MISSILE_BMP, me-&gt;x, me-&gt;y, bmp, x, y)</guard>
<action>/* NOTE: Mine type-2 is nastier than Mine type-1.
* The type-2 mine can hit the Ship with any of its
* &quot;tentacles&quot;. 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 *)&amp;mine2_destroyed, me);</action>
<choice_glyph conn="15,43,5,1,24,9,-2">
<action box="1,0,26,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,43,3,-1,11">
<action box="0,-2,11,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,24,33,24"/>
</state>
<state name="exploding">
<entry>me-&gt;exp_ctr = 0U;</entry>
<tran trig="TIME_TICK">
<choice>
<guard brief="still on screen?">(me-&gt;x &gt;= GAME_SPEED_X) &amp;&amp; (me-&gt;exp_ctr &lt; 15U)</guard>
<action>ObjectImageEvt *oie;
++me-&gt;exp_ctr; /* advance the explosion counter */
me-&gt;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-&gt;x = me-&gt;x + 1U; /* x of explosion */
oie-&gt;y = (int8_t)((int)me-&gt;y - 4 + 2); /* y of explosion */
oie-&gt;bmp = EXPLOSION0_BMP + (me-&gt;exp_ctr &gt;&gt; 2);
QACTIVE_POST(AO_Tunnel, (QEvt *)oie, me);</action>
<choice_glyph conn="15,57,5,-1,20">
<action box="1,0,19,2"/>
</choice_glyph>
</choice>
<choice target="../../../../1">
<guard brief="else"/>
<choice_glyph conn="15,57,4,1,5,36,-54,-20">
<action box="1,5,6,2"/>
</choice_glyph>
</choice>
<tran_glyph conn="4,57,3,-1,11">
<action box="0,-2,9,2"/>
</tran_glyph>
</tran>
<state_glyph node="4,50,33,14">
<entry box="1,2,5,2"/>
</state_glyph>
</state>
<state_glyph node="2,14,39,52">
<exit box="1,2,5,2"/>
</state_glyph>
</state>
<state_diagram size="53,68"/>
</statechart>
</class>
<attribute name="AO_Tunnel" type="QActive * const" visibility="0x00" properties="0x00"/>
<attribute name="AO_Ship" type="QActive * const" visibility="0x00" properties="0x00"/>
<attribute name="AO_Missile" type="QActive * const" visibility="0x00" properties="0x00"/>
<operation name="Tunnel_ctor" type="void" visibility="0x00" properties="0x01">
<code>uint8_t n;
Tunnel *me = &amp;l_tunnel;
QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Tunnel_initial));
QTimeEvt_ctorX(&amp;me-&gt;blinkTimeEvt, &amp;me-&gt;super, BLINK_TIMEOUT_SIG, 0U);
QTimeEvt_ctorX(&amp;me-&gt;screenTimeEvt, &amp;me-&gt;super, SCREEN_TIMEOUT_SIG, 0U);
for (n = 0; n &lt; GAME_MINES_MAX; ++n) {
me-&gt;mine1_pool[n] = Mine1_ctor(n); /* instantiate Mine1 in the pool */
me-&gt;mine2_pool[n] = Mine2_ctor(n); /* instantiate Mine2 in the pool */
me-&gt;mines[n] = (QMsm *)0; /* mine 'n' is unused */
}
me-&gt;last_mine_x = 0; /* the last mine at the right edge of the tunnel */
me-&gt;last_mine_y = 0;</code>
</operation>
<operation name="Ship_ctor" type="void" visibility="0x00" properties="0x01">
<code>Ship *me = &amp;l_ship;
QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Ship_initial));
me-&gt;x = GAME_SHIP_X;
me-&gt;y = (GAME_SHIP_Y &lt;&lt; 2);</code>
</operation>
<operation name="Missile_ctor" type="void" visibility="0x00" properties="0x01">
<code>Missile *me = &amp;l_missile;
QActive_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Missile_initial));</code>
</operation>
<operation name="Mine1_ctor" type="QHsm *" visibility="0x00" properties="0x01">
<parameter name="id" type="uint8_t"/>
<code>Mine1 *me;
Q_REQUIRE(id &lt; GAME_MINES_MAX);
me = &amp;l_mine1[id];
/* superclass' ctor */
QHsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Mine1_initial));
return (QHsm *)me;</code>
</operation>
<operation name="Mine2_ctor" type="QHsm *" visibility="0x00" properties="0x01">
<parameter name="id" type="uint8_t"/>
<code>Mine2 *me;
Q_REQUIRE(id &lt; GAME_MINES_MAX);
me = &amp;l_mine2[id];
/* superclass' ctor */
QHsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;Mine2_initial));
return (QHsm *)me;</code>
</operation>
</package>
<directory name=".">
<file name="game.h">
<text>#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' &quot;constructors&quot; */
$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 */</text>
</file>
<file name="missile.c">
<text>#include &quot;qpc.h&quot;
#include &quot;bsp.h&quot;
#include &quot;game.h&quot;
/* Q_DEFINE_THIS_FILE */
/* local objects -----------------------------------------------------------*/
$declare(AOs::Missile)
static Missile l_missile; /* the sole instance of the Missile active object */
/* Public-scope objects ----------------------------------------------------*/
QMActive * const AO_Missile = &amp;l_missile.super; /* opaque AO pointer */
/* Active object definition ------------------------------------------------*/
$define(AOs::Missile_ctor)
$define(AOs::Missile)</text>
</file>
<file name="ship.c">
<text>#include &quot;qpc.h&quot;
#include &quot;bsp.h&quot;
#include &quot;game.h&quot;
/* 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 ----------------------------------------------------*/
QMActive * const AO_Ship = &amp;l_ship.super; /* opaque AO pointer */
/* Active object definition ------------------------------------------------*/
$define(AOs::Ship_ctor)
$define(AOs::Ship)</text>
</file>
<file name="tunnel.c">
<text>#include &quot;qpc.h&quot;
#include &quot;bsp.h&quot;
#include &quot;game.h&quot;
Q_DEFINE_THIS_FILE
/* local objects -----------------------------------------------------------*/
$declare(AOs::Tunnel)
static Tunnel l_tunnel; /* the sole instance of the Tunnel active object */
/* Public-scope objects ----------------------------------------------------*/
QMActive * const AO_Tunnel = &amp;l_tunnel.super; /* opaque AO pointer */
/* Active object definition ================================================*/
$define(AOs::Tunnel_ctor)
$define(AOs::Tunnel)</text>
</file>
<file name="mine1.c">
<text>#include &quot;qpc.h&quot;
#include &quot;bsp.h&quot;
#include &quot;game.h&quot;
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)</text>
</file>
<file name="mine2.c">
<text>#include &quot;qpc.h&quot;
#include &quot;bsp.h&quot;
#include &quot;game.h&quot;
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)</text>
</file>
</directory>
</model>