[190] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
---|
| 2 | <!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/tutorial.doc:2032 -->
|
---|
| 3 | <html>
|
---|
| 4 | <head>
|
---|
| 5 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
---|
| 6 | <title>Qt Tutorial - Chapter 13: Game Over</title>
|
---|
| 7 | <style type="text/css"><!--
|
---|
| 8 | fn { margin-left: 1cm; text-indent: -1cm; }
|
---|
| 9 | a:link { color: #004faf; text-decoration: none }
|
---|
| 10 | a:visited { color: #672967; text-decoration: none }
|
---|
| 11 | body { background: #ffffff; color: black; }
|
---|
| 12 | --></style>
|
---|
| 13 | </head>
|
---|
| 14 | <body>
|
---|
| 15 |
|
---|
| 16 | <table border="0" cellpadding="0" cellspacing="0" width="100%">
|
---|
| 17 | <tr bgcolor="#E5E5E5">
|
---|
| 18 | <td valign=center>
|
---|
| 19 | <a href="index.html">
|
---|
| 20 | <font color="#004faf">Home</font></a>
|
---|
| 21 | | <a href="classes.html">
|
---|
| 22 | <font color="#004faf">All Classes</font></a>
|
---|
| 23 | | <a href="mainclasses.html">
|
---|
| 24 | <font color="#004faf">Main Classes</font></a>
|
---|
| 25 | | <a href="annotated.html">
|
---|
| 26 | <font color="#004faf">Annotated</font></a>
|
---|
| 27 | | <a href="groups.html">
|
---|
| 28 | <font color="#004faf">Grouped Classes</font></a>
|
---|
| 29 | | <a href="functions.html">
|
---|
| 30 | <font color="#004faf">Functions</font></a>
|
---|
| 31 | </td>
|
---|
| 32 | <td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Qt Tutorial - Chapter 13: Game Over</h1>
|
---|
| 33 |
|
---|
| 34 |
|
---|
| 35 | <p> <center><img src="t13.png" alt="Screenshot of tutorial thirteen"></center>
|
---|
| 36 | <p> In this example we start to approach a real playable game with a
|
---|
| 37 | score. We give MyWidget a new name (GameBoard) and add some slots.
|
---|
| 38 | <p> We put the definition in gamebrd.h and the implementation in gamebrd.cpp.
|
---|
| 39 | <p> The CannonField now has a game over state.
|
---|
| 40 | <p> The layout problems in LCDRange are fixed.
|
---|
| 41 | <p> <ul>
|
---|
| 42 | <li> <a href="t13-lcdrange-h.html">t13/lcdrange.h</a> contains the LCDRange
|
---|
| 43 | class definition.
|
---|
| 44 | <li> <a href="t13-lcdrange-cpp.html">t13/lcdrange.cpp</a> contains the LCDRange
|
---|
| 45 | implementation.
|
---|
| 46 | <li> <a href="t13-cannon-h.html">t13/cannon.h</a> contains the CannonField class
|
---|
| 47 | definition
|
---|
| 48 | <li> <a href="t13-cannon-cpp.html">t13/cannon.cpp</a> contains the CannonField
|
---|
| 49 | implementation.
|
---|
| 50 | <li> <a href="t13-gamebrd-h.html">t13/gamebrd.h</a> contains the GameBoard
|
---|
| 51 | class definition.
|
---|
| 52 | <li> <a href="t13-gamebrd-cpp.html">t13/gamebrd.cpp</a> contains the GameBoard
|
---|
| 53 | implementation.
|
---|
| 54 | <li> <a href="t13-main-cpp.html">t13/main.cpp</a> contains MyWidget and main.
|
---|
| 55 | </ul>
|
---|
| 56 | <p> <h2> Line-by-line Walkthrough
|
---|
| 57 | </h2>
|
---|
| 58 | <a name="1"></a><p> <h3> <a href="t13-lcdrange-h.html">t13/lcdrange.h</a>
|
---|
| 59 | </h3>
|
---|
| 60 | <a name="1-1"></a><p>
|
---|
| 61 |
|
---|
| 62 | <p> <pre> #include <<a href="qwidget-h.html">qwidget.h</a>>
|
---|
| 63 |
|
---|
| 64 | class QSlider;
|
---|
| 65 | class QLabel;
|
---|
| 66 |
|
---|
| 67 | class LCDRange : public <a href="qwidget.html">QWidget</a>
|
---|
| 68 | </pre>
|
---|
| 69 | <p> We inherit <a href="qwidget.html">QWidget</a> rather than <a href="qvbox.html">QVBox</a>. QVBox is very easy to use, but
|
---|
| 70 | again it showed its limitations so we switch to the more powerful and
|
---|
| 71 | slightly harder to use <a href="qvboxlayout.html">QVBoxLayout</a>. (As you remember, QVBoxLayout is
|
---|
| 72 | not a widget, it manages one.)
|
---|
| 73 | <p> <h3> <a href="t13-lcdrange-cpp.html">t13/lcdrange.cpp</a>
|
---|
| 74 | </h3>
|
---|
| 75 | <a name="1-2"></a><p>
|
---|
| 76 |
|
---|
| 77 | <p> <pre> #include <<a href="qlayout-h.html">qlayout.h</a>>
|
---|
| 78 | </pre>
|
---|
| 79 | <p> We need to include qlayout.h now to get the other layout management
|
---|
| 80 | API.
|
---|
| 81 | <p> <pre> LCDRange::LCDRange( <a href="qwidget.html">QWidget</a> *parent, const char *name )
|
---|
| 82 | : <a href="qwidget.html">QWidget</a>( parent, name )
|
---|
| 83 | </pre>
|
---|
| 84 | <p> We inherit QWidget in the usual way.
|
---|
| 85 | <p> The other constructor has the same change. init() is unchanged,
|
---|
| 86 | except that we've added some lines at the end:
|
---|
| 87 | <p> <pre> <a href="qvboxlayout.html">QVBoxLayout</a> * l = new <a href="qvboxlayout.html">QVBoxLayout</a>( this );
|
---|
| 88 | </pre>
|
---|
| 89 | <p> We create a QVBoxLayout with all the default values, managing this
|
---|
| 90 | widget's children.
|
---|
| 91 | <p> <pre> <a name="x2401"></a> l-><a href="qboxlayout.html#addWidget">addWidget</a>( lcd, 1 );
|
---|
| 92 | </pre>
|
---|
| 93 | <p> At the top we add the <a href="qlcdnumber.html">QLCDNumber</a> with a non-zero stretch.
|
---|
| 94 | <p> <pre> l-><a href="qboxlayout.html#addWidget">addWidget</a>( slider );
|
---|
| 95 | l-><a href="qboxlayout.html#addWidget">addWidget</a>( label );
|
---|
| 96 | </pre>
|
---|
| 97 | <p> Then we add the other two, both with the default zero stretch.
|
---|
| 98 | <p> This stretch control is something <a href="qvboxlayout.html">QVBoxLayout</a> (and <a href="qhboxlayout.html">QHBoxLayout</a>, and
|
---|
| 99 | <a href="qgridlayout.html">QGridLayout</a>) offers but classes like <a href="qvbox.html">QVBox</a> do not. In this case
|
---|
| 100 | we're saying that the QLCDNumber should stretch and the others should
|
---|
| 101 | not.
|
---|
| 102 | <p> <h3> <a href="t13-cannon-h.html">t13/cannon.h</a>
|
---|
| 103 | </h3>
|
---|
| 104 | <a name="1-3"></a><p> The CannonField now has a game over state and a few new functions.
|
---|
| 105 | <p>
|
---|
| 106 |
|
---|
| 107 | <p> <pre> bool gameOver() const { return gameEnded; }
|
---|
| 108 | </pre>
|
---|
| 109 | <p> This function returns TRUE if the game is over or FALSE if a game
|
---|
| 110 | is going on.
|
---|
| 111 | <p> <pre> void setGameOver();
|
---|
| 112 | void restartGame();
|
---|
| 113 | </pre>
|
---|
| 114 | <p> Here are two new slots: setGameOver() and restartGame().
|
---|
| 115 | <p> <pre> void canShoot( bool );
|
---|
| 116 | </pre>
|
---|
| 117 | <p> This new signal indicates that the CannonField is in a state where the
|
---|
| 118 | shoot() slot makes sense. We'll use it below to enable/disable the
|
---|
| 119 | Shoot button.
|
---|
| 120 | <p> <pre> bool gameEnded;
|
---|
| 121 | </pre>
|
---|
| 122 | <p> This private variable contains the game state. TRUE means that the
|
---|
| 123 | game is over, and FALSE means that a game is going on.
|
---|
| 124 | <p> <h3> <a href="t13-cannon-cpp.html">t13/cannon.cpp</a>
|
---|
| 125 | </h3>
|
---|
| 126 | <a name="1-4"></a><p>
|
---|
| 127 |
|
---|
| 128 | <p> <pre> gameEnded = FALSE;
|
---|
| 129 | </pre>
|
---|
| 130 | <p> This line has been added to the constructor. Initially, the game is not
|
---|
| 131 | over (luckily for the player :-).
|
---|
| 132 | <p> <pre> void CannonField::shoot()
|
---|
| 133 | {
|
---|
| 134 | if ( isShooting() )
|
---|
| 135 | return;
|
---|
| 136 | timerCount = 0;
|
---|
| 137 | shoot_ang = ang;
|
---|
| 138 | shoot_f = f;
|
---|
| 139 | <a name="x2407"></a> autoShootTimer-><a href="qtimer.html#start">start</a>( 50 );
|
---|
| 140 | emit canShoot( FALSE );
|
---|
| 141 | }
|
---|
| 142 | </pre>
|
---|
| 143 | <p> We added a new isShooting() function, so shoot() uses it instead of
|
---|
| 144 | testing directly. Also, shoot tells the world that the CannonField
|
---|
| 145 | cannot shoot now.
|
---|
| 146 | <p> <pre> void CannonField::setGameOver()
|
---|
| 147 | {
|
---|
| 148 | if ( gameEnded )
|
---|
| 149 | return;
|
---|
| 150 | if ( isShooting() )
|
---|
| 151 | autoShootTimer-><a href="qtimer.html#stop">stop</a>();
|
---|
| 152 | gameEnded = TRUE;
|
---|
| 153 | <a href="qwidget.html#repaint">repaint</a>();
|
---|
| 154 | }
|
---|
| 155 | </pre>
|
---|
| 156 | <p> This slot ends the game. It must be called from outside CannonField,
|
---|
| 157 | because this widget does not know when to end the game. This is an
|
---|
| 158 | important design principle in component programming. We choose to
|
---|
| 159 | make the component as flexible as possible to make it usable with
|
---|
| 160 | different rules (for example, a multi-player version of this in which the
|
---|
| 161 | first player to hit ten times wins could use the CannonField unchanged).
|
---|
| 162 | <p> If the game has already been ended we return immediately. If a game is
|
---|
| 163 | going on we stop the shot, set the game over flag, and repaint the entire
|
---|
| 164 | widget.
|
---|
| 165 | <p> <pre> void CannonField::restartGame()
|
---|
| 166 | {
|
---|
| 167 | if ( isShooting() )
|
---|
| 168 | <a name="x2408"></a> autoShootTimer-><a href="qtimer.html#stop">stop</a>();
|
---|
| 169 | gameEnded = FALSE;
|
---|
| 170 | <a href="qwidget.html#repaint">repaint</a>();
|
---|
| 171 | emit canShoot( TRUE );
|
---|
| 172 | }
|
---|
| 173 | </pre>
|
---|
| 174 | <p> This slot starts a new game. If a shot is in the air, we stop shooting.
|
---|
| 175 | We then reset the <tt>gameEnded</tt> variable and repaint the widget.
|
---|
| 176 | <p> moveShot() too emits the new canShoot(TRUE) signal at the same time as
|
---|
| 177 | either hit() or miss().
|
---|
| 178 | <p> Modifications in CannonField::paintEvent():
|
---|
| 179 | <p> <pre> void CannonField::<a href="qwidget.html#paintEvent">paintEvent</a>( <a href="qpaintevent.html">QPaintEvent</a> *e )
|
---|
| 180 | {
|
---|
| 181 | <a name="x2405"></a> <a href="qrect.html">QRect</a> updateR = e-><a href="qpaintevent.html#rect">rect</a>();
|
---|
| 182 | <a href="qpainter.html">QPainter</a> p( this );
|
---|
| 183 |
|
---|
| 184 | if ( gameEnded ) {
|
---|
| 185 | p.<a href="qpainter.html#setPen">setPen</a>( black );
|
---|
| 186 | <a name="x2403"></a> p.<a href="qpainter.html#setFont">setFont</a>( QFont( "Courier", 48, QFont::Bold ) );
|
---|
| 187 | p.<a href="qpainter.html#drawText">drawText</a>( <a href="qwidget.html#rect">rect</a>(), AlignCenter, "Game Over" );
|
---|
| 188 | }
|
---|
| 189 | </pre>
|
---|
| 190 | <p> The paint event has been enhanced to display the text "Game Over" if
|
---|
| 191 | the game is over, i.e., <tt>gameEnded</tt> is TRUE. We don't bother to
|
---|
| 192 | check the update rectangle here because speed is not critical when
|
---|
| 193 | the game is over.
|
---|
| 194 | <p> To draw the text we first set a black pen; the pen color is used
|
---|
| 195 | when drawing text. Next we choose a 48 point bold font from the
|
---|
| 196 | Courier family. Finally we draw the text centered in the widget's
|
---|
| 197 | rectangle. Unfortunately, on some systems (especially X servers with
|
---|
| 198 | Unicode fonts) it can take a while to load such a large font. Because
|
---|
| 199 | Qt caches fonts, you will notice this only the first time the font is
|
---|
| 200 | used.
|
---|
| 201 | <p> <pre> <a name="x2406"></a> if ( updateR.<a href="qrect.html#intersects">intersects</a>( cannonRect() ) )
|
---|
| 202 | paintCannon( &p );
|
---|
| 203 | if ( isShooting() && updateR.<a href="qrect.html#intersects">intersects</a>( shotRect() ) )
|
---|
| 204 | paintShot( &p );
|
---|
| 205 | if ( !gameEnded && updateR.<a href="qrect.html#intersects">intersects</a>( targetRect() ) )
|
---|
| 206 | paintTarget( &p );
|
---|
| 207 | }
|
---|
| 208 | </pre>
|
---|
| 209 | <p> We draw the shot only when shooting and the target only when playing
|
---|
| 210 | (that is, when the game is not ended).
|
---|
| 211 | <p> <h3> <a href="t13-gamebrd-h.html">t13/gamebrd.h</a>
|
---|
| 212 | </h3>
|
---|
| 213 | <a name="1-5"></a><p> This file is new. It contains the definition of the GameBoard class,
|
---|
| 214 | which was last seen as MyWidget.
|
---|
| 215 | <p>
|
---|
| 216 |
|
---|
| 217 | <p> <pre> class QPushButton;
|
---|
| 218 | class LCDRange;
|
---|
| 219 | class QLCDNumber;
|
---|
| 220 | class CannonField;
|
---|
| 221 |
|
---|
| 222 | #include "lcdrange.h"
|
---|
| 223 | #include "cannon.h"
|
---|
| 224 |
|
---|
| 225 | class GameBoard : public <a href="qwidget.html">QWidget</a>
|
---|
| 226 | {
|
---|
| 227 | <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
|
---|
| 228 | public:
|
---|
| 229 | GameBoard( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
|
---|
| 230 |
|
---|
| 231 | protected slots:
|
---|
| 232 | void fire();
|
---|
| 233 | void hit();
|
---|
| 234 | void missed();
|
---|
| 235 | void newGame();
|
---|
| 236 |
|
---|
| 237 | private:
|
---|
| 238 | <a href="qlcdnumber.html">QLCDNumber</a> *hits;
|
---|
| 239 | <a href="qlcdnumber.html">QLCDNumber</a> *shotsLeft;
|
---|
| 240 | CannonField *cannonField;
|
---|
| 241 | };
|
---|
| 242 | </pre>
|
---|
| 243 | <p> We have now added four slots. These are protected and are used internally.
|
---|
| 244 | We have also added two QLCDNumbers (<tt>hits</tt> and <tt>shotsLeft</tt>) which display
|
---|
| 245 | the game status.
|
---|
| 246 | <p> <h3> <a href="t13-gamebrd-cpp.html">t13/gamebrd.cpp</a>
|
---|
| 247 | </h3>
|
---|
| 248 | <a name="1-6"></a><p> This file is new. It contains the implementation of the GameBoard
|
---|
| 249 | class, which was last seen as MyWidget.
|
---|
| 250 | <p>
|
---|
| 251 |
|
---|
| 252 | <p> We have made some changes in the GameBoard constructor.
|
---|
| 253 | <p> <pre> cannonField = new CannonField( this, "cannonField" );
|
---|
| 254 | </pre>
|
---|
| 255 | <p> <tt>cannonField</tt> is now a member variable, so we carefully change the
|
---|
| 256 | constructor to use it. (The <em>good</em> programmers at Trolltech never
|
---|
| 257 | forget this, but I do. Caveat programmor - if "programmor" is Latin,
|
---|
| 258 | at least. Anyway, back to the code.)
|
---|
| 259 | <p> <pre> <a href="qobject.html#connect">connect</a>( cannonField, SIGNAL(hit()),
|
---|
| 260 | this, SLOT(hit()) );
|
---|
| 261 | <a href="qobject.html#connect">connect</a>( cannonField, SIGNAL(missed()),
|
---|
| 262 | this, SLOT(missed()) );
|
---|
| 263 | </pre>
|
---|
| 264 | <p> This time we want to do something when the shot has hit or missed the
|
---|
| 265 | target. Thus we connect the hit() and missed() signals of the
|
---|
| 266 | CannonField to two protected slots with the same names in this class.
|
---|
| 267 | <p> <pre> <a href="qobject.html#connect">connect</a>( shoot, SIGNAL(<a href="qbutton.html#clicked">clicked</a>()), SLOT(fire()) );
|
---|
| 268 | </pre>
|
---|
| 269 | <p> Previously we connected the Shoot button's clicked() signal directly
|
---|
| 270 | to the CannonField's shoot() slot. This time we want to keep track of
|
---|
| 271 | the number of shots fired, so we connect it to a protected slot in
|
---|
| 272 | this class instead.
|
---|
| 273 | <p> Notice how easy it is to change the behavior of a program when you are
|
---|
| 274 | working with self-contained components.
|
---|
| 275 | <p> <pre> <a href="qobject.html#connect">connect</a>( cannonField, SIGNAL(canShoot(bool)),
|
---|
| 276 | <a name="x2416"></a> shoot, SLOT(<a href="qwidget.html#setEnabled">setEnabled</a>(bool)) );
|
---|
| 277 | </pre>
|
---|
| 278 | <p> We also use the cannonField's canShoot() signal to enable or disable
|
---|
| 279 | the Shoot button appropriately.
|
---|
| 280 | <p> <pre> QPushButton *restart
|
---|
| 281 | = new <a href="qpushbutton.html">QPushButton</a>( "&New Game", this, "newgame" );
|
---|
| 282 | restart->setFont( QFont( "Times", 18, QFont::Bold ) );
|
---|
| 283 |
|
---|
| 284 | <a href="qobject.html#connect">connect</a>( restart, SIGNAL(clicked()), this, SLOT(newGame()) );
|
---|
| 285 | </pre>
|
---|
| 286 | <p> We create, set up, and connect the New Game button as we have done
|
---|
| 287 | with the other buttons. Clicking this button will activate the
|
---|
| 288 | newGame() slot in this widget.
|
---|
| 289 | <p> <pre> hits = new <a href="qlcdnumber.html">QLCDNumber</a>( 2, this, "hits" );
|
---|
| 290 | shotsLeft = new <a href="qlcdnumber.html">QLCDNumber</a>( 2, this, "shotsleft" );
|
---|
| 291 | <a href="qlabel.html">QLabel</a> *hitsL = new <a href="qlabel.html">QLabel</a>( "HITS", this, "hitsLabel" );
|
---|
| 292 | QLabel *shotsLeftL
|
---|
| 293 | = new <a href="qlabel.html">QLabel</a>( "SHOTS LEFT", this, "shotsleftLabel" );
|
---|
| 294 | </pre>
|
---|
| 295 | <p> We create four new widgets. Note that we don't bother to keep the
|
---|
| 296 | pointers to the <a href="qlabel.html">QLabel</a> widgets in the GameBoard class because there's
|
---|
| 297 | nothing much we want to do with them. Qt will delete them when the
|
---|
| 298 | GameBoard widget is destroyed, and the layout classes will resize them
|
---|
| 299 | appropriately.
|
---|
| 300 | <p> <pre> <a href="qhboxlayout.html">QHBoxLayout</a> *topBox = new <a href="qhboxlayout.html">QHBoxLayout</a>;
|
---|
| 301 | <a name="x2413"></a> grid-><a href="qgridlayout.html#addLayout">addLayout</a>( topBox, 0, 1 );
|
---|
| 302 | topBox-><a href="qboxlayout.html#addWidget">addWidget</a>( shoot );
|
---|
| 303 | topBox-><a href="qboxlayout.html#addWidget">addWidget</a>( hits );
|
---|
| 304 | topBox-><a href="qboxlayout.html#addWidget">addWidget</a>( hitsL );
|
---|
| 305 | topBox-><a href="qboxlayout.html#addWidget">addWidget</a>( shotsLeft );
|
---|
| 306 | topBox-><a href="qboxlayout.html#addWidget">addWidget</a>( shotsLeftL );
|
---|
| 307 | <a name="x2410"></a> topBox-><a href="qboxlayout.html#addStretch">addStretch</a>( 1 );
|
---|
| 308 | <a name="x2411"></a> topBox-><a href="qboxlayout.html#addWidget">addWidget</a>( restart );
|
---|
| 309 | </pre>
|
---|
| 310 | <p> The number of widgets in the top-right cell is getting large. Once it
|
---|
| 311 | was empty; now it's full enough that we group together the layout
|
---|
| 312 | setting for better overview.
|
---|
| 313 | <p> Notice that we let all the widgets have their preferred sizes, instead
|
---|
| 314 | putting the stretch just to the left of the New Game button.
|
---|
| 315 | <p> <pre> newGame();
|
---|
| 316 | }
|
---|
| 317 | </pre>
|
---|
| 318 | <p> We're all done constructing the GameBoard, so we start it all using
|
---|
| 319 | newGame(). (NewGame() is a slot, but as we said, slots can be used as
|
---|
| 320 | ordinary functions, too.)
|
---|
| 321 | <p> <pre> void GameBoard::fire()
|
---|
| 322 | {
|
---|
| 323 | if ( cannonField->gameOver() || cannonField->isShooting() )
|
---|
| 324 | return;
|
---|
| 325 | shotsLeft-><a href="qlcdnumber.html#display">display</a>( shotsLeft-><a href="qlcdnumber.html#intValue">intValue</a>() - 1 );
|
---|
| 326 | cannonField->shoot();
|
---|
| 327 | }
|
---|
| 328 | </pre>
|
---|
| 329 | <p> This function fires a shot. If the game is over or if there is a shot in the
|
---|
| 330 | air, we return immediately. We decrement the number of shots left and tell
|
---|
| 331 | the cannon to shoot.
|
---|
| 332 | <p> <pre> void GameBoard::hit()
|
---|
| 333 | {
|
---|
| 334 | hits-><a href="qlcdnumber.html#display">display</a>( hits-><a href="qlcdnumber.html#intValue">intValue</a>() + 1 );
|
---|
| 335 | if ( shotsLeft-><a href="qlcdnumber.html#intValue">intValue</a>() == 0 )
|
---|
| 336 | cannonField->setGameOver();
|
---|
| 337 | else
|
---|
| 338 | cannonField->newTarget();
|
---|
| 339 | }
|
---|
| 340 | </pre>
|
---|
| 341 | <p> This slot is activated when a shot has hit the target. We increment the
|
---|
| 342 | number of hits. If there are no shots left, the game is over. Otherwise,
|
---|
| 343 | we make the CannonField generate a new target.
|
---|
| 344 | <p> <pre> void GameBoard::missed()
|
---|
| 345 | {
|
---|
| 346 | <a name="x2415"></a> if ( shotsLeft-><a href="qlcdnumber.html#intValue">intValue</a>() == 0 )
|
---|
| 347 | cannonField->setGameOver();
|
---|
| 348 | }
|
---|
| 349 | </pre>
|
---|
| 350 | <p> This slot is activated when a shot has missed the target. If there are no
|
---|
| 351 | shots left, the game is over.
|
---|
| 352 | <p> <pre> void GameBoard::newGame()
|
---|
| 353 | {
|
---|
| 354 | <a name="x2414"></a> shotsLeft-><a href="qlcdnumber.html#display">display</a>( 15 );
|
---|
| 355 | hits-><a href="qlcdnumber.html#display">display</a>( 0 );
|
---|
| 356 | cannonField->restartGame();
|
---|
| 357 | cannonField->newTarget();
|
---|
| 358 | }
|
---|
| 359 | </pre>
|
---|
| 360 | <p> This slot is activated when the user clicks the Restart button. It is
|
---|
| 361 | also called from the constructor. First it sets the number of shots
|
---|
| 362 | to 15. Note that this is the only place in the program where we set
|
---|
| 363 | the number of shots. Change it to whatever you like to change the
|
---|
| 364 | game rules. Next we reset the number of hits, restart the game, and
|
---|
| 365 | generate a new target.
|
---|
| 366 | <p> <h3> <a href="t13-main-cpp.html">t13/main.cpp</a>
|
---|
| 367 | </h3>
|
---|
| 368 | <a name="1-7"></a><p> This file has just been on a diet. MyWidget is gone, and the only
|
---|
| 369 | thing left is the main() function, unchanged except for the name
|
---|
| 370 | change.
|
---|
| 371 | <p> <h2> Behavior
|
---|
| 372 | </h2>
|
---|
| 373 | <a name="2"></a><p> The cannon can shoot at a target; a new target is automatically created
|
---|
| 374 | when one has been hit.
|
---|
| 375 | <p> Hits and shots left are displayed and the program keeps track of them.
|
---|
| 376 | The game can end, and there's a button to start a new game.
|
---|
| 377 | <p> (See <a href="tutorial1-07.html#compiling">Compiling</a> for how to create a
|
---|
| 378 | makefile and build the application.)
|
---|
| 379 | <p> <h2> Exercises
|
---|
| 380 | </h2>
|
---|
| 381 | <a name="3"></a><p> Add a random wind factor and show it to the user.
|
---|
| 382 | <p> Make some splatter effects when the shot hits the target.
|
---|
| 383 | <p> Implement multiple targets.
|
---|
| 384 | <p> You're now ready for <a href="tutorial1-14.html">Chapter 14.</a>
|
---|
| 385 | <p> [<a href="tutorial1-12.html">Previous tutorial</a>]
|
---|
| 386 | [<a href="tutorial1-14.html">Next tutorial</a>]
|
---|
| 387 | [<a href="tutorial.html">Main tutorial page</a>]
|
---|
| 388 | <p>
|
---|
| 389 | <!-- eof -->
|
---|
| 390 | <p><address><hr><div align=center>
|
---|
| 391 | <table width=100% cellspacing=0 border=0><tr>
|
---|
| 392 | <td>Copyright © 2007
|
---|
| 393 | <a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
|
---|
| 394 | <td align=right><div align=right>Qt 3.3.8</div>
|
---|
| 395 | </table></div></address></body>
|
---|
| 396 | </html>
|
---|