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

📄 qt教程一 —— 第十三章:游戏结束.htm

📁 嵌入式QT开发系列文档
💻 HTM
📖 第 1 页 / 共 2 页
字号:
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qpainter.html">QPainter</A> p( this );

        if ( gameEnded ) {
            p.<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qpainter.html#setPen">setPen</A>( black );
    <A name=x2335></A>        p.<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qpainter.html#setFont">setFont</A>( QFont( "Courier", 48, QFont::Bold ) );
    <A name=x2334></A>        p.<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qpainter.html#drawText">drawText</A>( <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qwidget.html#rect">rect</A>(), AlignCenter, "Game Over" );
        }
</PRE>
<P>绘画事件已经通过如果游戏结束,比如<TT>gameEnded</TT>是TRUE,就显示文本“Game 
Over”而被增强了。我们在这里不怕麻烦来检查更新矩形,是因为在游戏结束的时候速度不是关键性的。 
<P>为了画文本,我们先设置了黑色的画笔,当画文本的时候,画笔颜色会被用到。接下来我们选择Courier字体中的48号加粗字体。最后我们在窗口部件的矩形中央绘制文本。不幸的是,在一些系统中(特别是使用Unicode的X服务器)它会用一小段时间来载入如此大的字体。因为Qt缓存字体,我们只有第一次使用这个字体的时候才会注意到这一点。 

<P><PRE>    <A name=x2338></A>    if ( updateR.<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qrect.html#intersects">intersects</A>( cannonRect() ) )
            paintCannon( &amp;p );
        if ( isShooting() &amp;&amp; updateR.<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qrect.html#intersects">intersects</A>( shotRect() ) )
            paintShot( &amp;p );
        if ( !gameEnded &amp;&amp; updateR.<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qrect.html#intersects">intersects</A>( targetRect() ) )
            paintTarget( &amp;p );
    }
</PRE>
<P>我们只有在设计的时候画炮弹,在玩游戏的时候画目标(这也就是说,当游戏没有结束的时候)。 
<P>
<H3><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t13-gamebrd-h.html">t13/gamebrd.h</A> 
</H3><A name=1-5></A>
<P>这个文件是新的。它包含最后被用来作为MyWidget的GameBoard类的定义。 
<P>
<P><PRE>    class QPushButton;
    class LCDRange;
    class QLCDNumber;
    class CannonField;

    #include "lcdrange.h"
    #include "cannon.h"

    class GameBoard : public <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qwidget.html">QWidget</A>
    {
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/metaobjects.html#Q_OBJECT">Q_OBJECT</A>
    public:
        GameBoard( <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qwidget.html">QWidget</A> *parent=0, const char *name=0 );

    protected slots:
        void  fire();
        void  hit();
        void  missed();
        void  newGame();

    private:
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html">QLCDNumber</A>  *hits;
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html">QLCDNumber</A>  *shotsLeft;
        CannonField *cannonField;
    };
</PRE>
<P>我们现在已经添加了四个槽。这些槽都是被保护的,只在内部使用。我们也已经加入了两个QLCDNumbers(<TT>hits</TT>和<TT>shotsLeft</TT>)用来显示游戏的状态。 

<P>
<H3><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t13-gamebrd-cpp.html">t13/gamebrd.cpp</A> 
</H3><A name=1-6></A>
<P>这个文件是新的。它包含最后被用来作为MyWidget的GameBoard类的实现, 
<P>
<P>我们已经在GameBoard的构造函数中做了一些修改。 
<P><PRE>        cannonField = new CannonField( this, "cannonField" );
</PRE>
<P><TT>cannonField</TT>现在是一个成员变量,所以我们在使用它的时候要小心地改变它的构造函数。(Trolltech的<EM>好</EM>程序员从来不会忘记这点,但是我就忘了。告诫程序员-如果“programmor”是拉丁语,至少。无论如何,返回代码。) 

<P><PRE>        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( cannonField, SIGNAL(hit()),
                 this, SLOT(hit()) );
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( cannonField, SIGNAL(missed()),
                 this, SLOT(missed()) );
</PRE>
<P>这次当炮弹射中或者射失目标的时候,我们想做些事情。所以我们把CannonField的hit()和missed()信号连接到这个类的两个被保护的同名槽。 
<P><PRE>        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( shoot, SIGNAL(<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qbutton.html#clicked">clicked</A>()), SLOT(fire()) );
</PRE>
<P>以前我们直接把Shoot按钮的clicked()信号连接到CannonField的shoot()槽。这次我们想跟踪射击的次数,所以我们把它改为连接到这个类里面一个被保护的槽。 

<P>注意当你用独立的组件工作的时候,改变程序的行为是多么的容易。 
<P><PRE>        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( cannonField, SIGNAL(canShoot(bool)),
    <A name=x2348></A>             shoot, SLOT(<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qwidget.html#setEnabled">setEnabled</A>(bool)) );
</PRE>
<P>我们也使用cannonField的canShoot()信号来适当地使Shoot按钮生效和失效。 
<P><PRE>        QPushButton *restart
            = new <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qpushbutton.html">QPushButton</A>( "&amp;New Game", this, "newgame" );
        restart-&gt;setFont( QFont( "Times", 18, QFont::Bold ) );

        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qobject.html#connect">connect</A>( restart, SIGNAL(clicked()), this, SLOT(newGame()) );
</PRE>
<P>我们创建、设置并且连接这个New Game按钮就像我们对其它按钮所做的一样。点击这个按钮就会激活这个窗口部件的newGame()槽。 
<P><PRE>        hits = new <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html">QLCDNumber</A>( 2, this, "hits" );
        shotsLeft = new <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html">QLCDNumber</A>( 2, this, "shotsleft" );
        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlabel.html">QLabel</A> *hitsL = new <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlabel.html">QLabel</A>( "HITS", this, "hitsLabel" );
        QLabel *shotsLeftL
            = new <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlabel.html">QLabel</A>( "SHOTS LEFT", this, "shotsleftLabel" );
</PRE>
<P>我们创建了四个新的窗口部件。注意我们不怕麻烦的把<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlabel.html">QLabel</A>窗口部件的指针保留到GameBoard类中是因为我们不想再对它们做什么了。当GameBoard窗口部件被销毁的时候,Qt将会删除它们,并且布局类会适当地重新定义它们的大小。 

<P><PRE>        <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qhboxlayout.html">QHBoxLayout</A> *topBox = new <A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qhboxlayout.html">QHBoxLayout</A>;
    <A name=x2345></A>    grid-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qgridlayout.html#addLayout">addLayout</A>( topBox, 0, 1 );
        topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addWidget">addWidget</A>( shoot );
        topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addWidget">addWidget</A>( hits );
        topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addWidget">addWidget</A>( hitsL );
        topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addWidget">addWidget</A>( shotsLeft );
        topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addWidget">addWidget</A>( shotsLeftL );
    <A name=x2342></A>    topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addStretch">addStretch</A>( 1 );
    <A name=x2343></A>    topBox-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qboxlayout.html#addWidget">addWidget</A>( restart );
</PRE>
<P>右上单元格的窗口部件的数量正在变大。从前它是空的,现在它是完全充足的,我们把它们放到布局中来更好的看到它们。 
<P>注意我们让所有的窗口部件获得它们更喜欢的大小,改为在New Game按钮的左边加入了一个可以自由伸展的东西。 
<P><PRE>        newGame();
    }
</PRE>
<P>我们已经做完了所有关于GameBoard的构造,所以我们使用newGame()来开始。(newGame()是一个槽,但是就像我们所说的,槽也可以像普通的函数一样使用。) 

<P><PRE>    void GameBoard::fire()
    {
        if ( cannonField-&gt;gameOver() || cannonField-&gt;isShooting() )
            return;
        shotsLeft-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#display">display</A>( shotsLeft-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#intValue">intValue</A>() - 1 );
        cannonField-&gt;shoot();
    }
</PRE>
<P>这个函数进行射击。如果游戏结束了或者还有一个炮弹在空中,我们立即返回。我们减少炮弹的数量并告诉加农炮进行射击。 
<P><PRE>    void GameBoard::hit()
    {
        hits-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#display">display</A>( hits-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#intValue">intValue</A>() + 1 );
        if ( shotsLeft-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#intValue">intValue</A>() == 0 )
            cannonField-&gt;setGameOver();
        else
            cannonField-&gt;newTarget();
    }
</PRE>
<P>当炮弹击中目标的时候这个槽被激活。我们增加射中的数量。如果没有炮弹了,游戏就结束了。否则,我们会让CannonField生成新的目标。 
<P><PRE>    void GameBoard::missed()
    {
    <A name=x2347></A>    if ( shotsLeft-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#intValue">intValue</A>() == 0 )
            cannonField-&gt;setGameOver();
    }
</PRE>
<P>当炮弹射失目标的时候这个槽被激活,如果没有炮弹了,游戏就结束了。 
<P><PRE>    void GameBoard::newGame()
    {
    <A name=x2346></A>    shotsLeft-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#display">display</A>( 15 );
        hits-&gt;<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/qlcdnumber.html#display">display</A>( 0 );
        cannonField-&gt;restartGame();
        cannonField-&gt;newTarget();
    }
</PRE>
<P>当用户点击Restart按钮的时候这个槽被激活。它也会被构造函数调用。首先它把炮弹的数量设置为15。注意这里是我们在程序中唯一设置炮弹数量的地方。把它改变为你所想要的游戏规则。接下来我们重置射中的数量,重新开始游戏,并且生成一个新的目标。 

<P>
<H3><A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/t13-main-cpp.html">t13/main.cpp</A> 
</H3><A name=1-7></A>
<P>这个文件仅仅被删掉了一部分。MyWidget没了,并且唯一剩下的是main()函数,除了名称的改变其它都没有改变。 
<P>
<H2>行为 </H2><A name=2></A>
<P>射中的和剩余炮弹的数量被显示并且程序继续跟踪它们。游戏可以结束了,并且还有一个按钮可以开始一个新游戏。 
<P>(请看<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-07.html#compiling">编译</A>来学习如何创建一个makefile和连编应用程序。) 

<P>
<H2>练习 </H2><A name=3></A>
<P>添加一个随机的风的因素并把它显示给用户看。 
<P>当炮弹击中目标的时候做一些飞溅的效果。 
<P>实现多个目标。 
<P>现在你可以进行<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-14.html">第十四章</A>了。 
<P>[<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-12.html">上一章</A>] 
[<A 
href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial1-14.html">下一章</A>] 
[<A href="http://www.qtopia.org.cn/doc/qiliang.net/qt/tutorial.html">教程一主页</A>] 
<P><!-- eof -->
<P>
<ADDRESS>
<HR>

<DIV align=center>
<TABLE cellSpacing=0 width="100%" border=0>
  <TBODY>
  <TR>
    <TD>Copyright &copy; 2002 <A href="http://www.trolltech.com/">Trolltech</A> 
    <TD><A href="http://www.trolltech.com/trademarks.html">Trademarks</A> 
    <TD><A 
      href="http://www.qtopia.org.cn/doc/qiliang.net/qt/zh_CN.html">译者:Cavendish</A> 

    <TD align=right>
      <DIV align=right>Qt 
3.0.5版</DIV></TR></TBODY></TABLE></DIV></ADDRESS></BODY></HTML>

⌨️ 快捷键说明

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