<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                #(34):貪吃蛇游戲(4) 這將是我們這個稍大一些的示例程序的最后一部分。在本章中,我們將完成`GameController`中有關用戶控制的相關代碼。 首先,我們來給`GameController`添加一個事件過濾器: ~~~ bool GameController::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::KeyPress) { handleKeyPressed((QKeyEvent *)event); return true; } else { return QObject::eventFilter(object, event); } } ~~~ 回憶一下,我們使用`QGraphicsScene`作為游戲場景。為什么不直接繼承`QGprahicsScene`,重寫其`keyPressEvent()`函數呢?這里的考慮是:第一,我們不想只為重寫一個鍵盤事件而繼承`QGraphicScene`。這不符合面向對象設計的要求。繼承首先應該有“是一個(is-a)”的關系。我們將游戲場景繼承`QGraphcisScene`當然滿足這個關系,無可厚非。但是,繼承還有一個“特化”的含義,我們只想控制鍵盤事件,并沒有添加其它額外的代碼,因此感覺并不應該作此繼承。第二,我們希望將表示層與控制層分離:明明已經有了`GameController`,顯然,這是一個用于控制游戲的類,那么,為什么鍵盤控制還要放在場景中呢?這豈不將控制與表現層耦合起來了嗎?基于以上兩點考慮,我們選擇不繼承`QGraphicsScene`,而是在`GameController`中為場景添加事件過濾器,從而完成鍵盤事件的處理。下面我們看看這個`handleKeyPressed()`函數是怎樣的: ~~~ void GameController::handleKeyPressed(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Left: snake->setMoveDirection(Snake::MoveLeft); break; case Qt::Key_Right: snake->setMoveDirection(Snake::MoveRight); break; case Qt::Key_Up: snake->setMoveDirection(Snake::MoveUp); break; case Qt::Key_Down: snake->setMoveDirection(Snake::MoveDown); break; } } ~~~ 這段代碼并不復雜:只是設置蛇的運動方向。記得我們在前面的代碼中,已經為蛇添加了運動方向的控制,因此,我們只需要修改這個狀態,即可完成對蛇的控制。由于前面我們已經在蛇的對象中完成了相應控制的代碼,因此這里的游戲控制就是這么簡單。接下來,我們要完成游戲邏輯:吃食物、生成新的食物以及咬到自己這三個邏輯: ~~~ void GameController::snakeAteFood(Snake *snake, Food *food) { scene.removeItem(food); delete food; addNewFood(); } ~~~ 首先是蛇吃到食物。如果蛇吃到了食物,那么,我們將食物從場景中移除,然后添加新的食物。為了避免內存泄露,我們需要在這里 delete 食物,以釋放占用的空間。當然,你應該想到,我們肯定會在`addNewFood()`函數中使用 new 運算符重新生成新的食物。 ~~~ void GameController::addNewFood() { int x, y; do { x = (int) (qrand() % 100) / 10; y = (int) (qrand() % 100) / 10; x *= 10; y *= 10; } while (snake->shape().contains(snake->mapFromScene(QPointF(x + 5, y + 5)))); Food *food = new Food(x , y); scene.addItem(food); } ~~~ 在`addNewFood()`代碼中,我們首先計算新的食物的坐標:使用一個循環,直到找到一個不在蛇身體中的坐標。為了判斷一個坐標是不是位于蛇的身體上,我們利用蛇的`shape()`函數。需要注意的是,`shape()`返回元素坐標系中的坐標,而我們計算而得的 x,y 坐標位于場景坐標系,因此我們必須利用`QGraphicsItem::mapFromScene()`將場景坐標系映射為元素坐標系。當我們計算出食物坐標后,我們在堆上重新創建這個食物,并將其添加到游戲場景。 ~~~ void GameController::snakeAteItself(Snake *snake) { QTimer::singleShot(0, this, SLOT(gameOver())); } void GameController::gameOver() { scene.clear(); snake = new Snake(*this); scene.addItem(snake); addNewFood(); } ~~~ 如果蛇咬到了它自己,游戲即宣告結束。因此,我們直接調用`gameOver()`函數。這個函數將場景清空,然后重新創建蛇并增加第一個食物。為什么我們不直接調用`gameOver()`函數,而是利用`QTimer`調用呢(希望你沒有忘記`QTimer::singleShot(0, ...)`的用法)?這是因為,我們不應該在一個 update 操作中去清空整個場景。因此我們使用`QTimer`,在 update 事件之后完成這個操作。 至此,我們已經把這個簡單的貪吃蛇游戲全部完成。最后我們來看一下運行結果: [![](https://box.kancloud.cn/2015-12-29_56823257cdf5b.png)](http://files.devbean.net/images/2012/12/snake-demo.png) 文末的附件中是我們當前的全部代碼。如果你檢查下這部分代碼,會發現我們其實還沒有完成整個游戲:`Wall`對象完全沒有實現,難度控制也沒有完成。當然,通過我們的講解,希望你已經理解了我們設計的原則以及各部分代碼之間的關系。如果感興趣,可以繼續完成這部分代碼。豆子在 github 上面創建了一個代碼庫,如果你感覺自己的改進比較成功,或者希望與大家分享,歡迎 clone 倉庫提交代碼!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看