<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                #(33):貪吃蛇游戲(3) 繼續前面一章的內容。上次我們講完了有關蛇的靜態部分,也就是繪制部分。現在,我們開始添加游戲控制的代碼。首先我們從最簡單的四個方向鍵開始: ~~~ void Snake::moveLeft() { head.rx() -= SNAKE_SIZE; if (head.rx() < -100) { head.rx() = 100; } } void Snake::moveRight() { head.rx() += SNAKE_SIZE; if (head.rx() > 100) { head.rx() = -100; } } void Snake::moveUp() { head.ry() -= SNAKE_SIZE; if (head.ry() < -100) { head.ry() = 100; } } void Snake::moveDown() { head.ry() += SNAKE_SIZE; if (head.ry() > 100) { head.ry() = -100; } } ~~~ 我們有四個以 move 開頭的函數,內容都很類似:分別以 SNAKE_SIZE 為基準改變頭部坐標,然后與場景邊界比較,大于邊界值時,設置為邊界值。這么做的結果是,當蛇運動到場景最右側時,會從最左側出來;當運行到場景最上側時,會從最下側出來。 然后我們添加一個比較復雜的函數,借此,我們可以看出 Graphics View Framework 的強大之處: ~~~ void Snake::handleCollisions() { QList collisions = collidingItems(); // Check collisions with other objects on screen foreach (QGraphicsItem *collidingItem, collisions) { if (collidingItem->data(GD_Type) == GO_Food) { // Let GameController handle the event by putting another apple controller.snakeAteFood(this, (Food *)collidingItem); growing += 1; } } // Check snake eating itself if (tail.contains(head)) { controller.snakeAteItself(this); } } ~~~ 顧名思義,`handleCollisions()`的意思是處理碰撞,也就是所謂的“碰撞檢測”。首先,我們使用`collidingItems()`取得所有碰撞的元素。這個函數的簽名是: ~~~ QList<QGraphicsItem *> QGraphicsItem::collidingItems( Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const ~~~ 該函數返回與這個元素碰撞的所有元素。Graphcis View Framework 提供了四種碰撞檢測的方式: * `Qt::ContainsItemShape`:如果被檢測物的形狀(`shape()`)完全包含在檢測物內,算做碰撞; * `Qt::IntersectsItemShape`:如果被檢測物的形狀(`shape()`)與檢測物有交集,算做碰撞; * `Qt::ContainsItemBoundingRect`:如果被檢測物的包含矩形(`boundingRect()`)完全包含在檢測物內,算做碰撞; * `Qt::IntersectsItemBoundingRect`:如果被檢測物的包含矩形(`boundingRect()`)與檢測物有交集,算做碰撞。 注意,該函數默認是`Qt::IntersectsItemShape`。回憶一下,我們之前編寫的代碼,`Food`的`boundingRect()`要大于其實際值,卻不影響我們的游戲邏輯判斷,這就是原因:因為我們使用的是`Qt::IntersectsItemShape`判斷檢測,這與`boundingRect()`無關。 后面的代碼就很簡單了。我們遍歷所有被碰撞的元素,如果是食物,則進行吃食物的算法,同時將蛇的長度加 1。最后,如果身體包含了頭,那就是蛇吃了自己的身體。 還記得我們在 Food 類中有這么一句: ~~~ setData(GD_Type, GO_Food); ~~~ `QGraphicsItem::setData()`以鍵值對的形式設置元素的自定義數據。所謂自定義數據,就是對應用程序有所幫助的用戶數據。Qt 不會使用這種機制來存儲數據,因此你可以放心地將所需要的數據存儲到元素對象。例如,我們在`Food`的構造函數中,將`GD_Type`的值設置為`GO_Food`。那么,這里我們取出`GD_Type`,如果其值是`GO_Food`,意味著這個`QGraphicsItem`就是一個`Food`,因此我們可以將其安全地進行后面的類型轉換,從而完成下面的代碼。 下面是`advance()`函數的代碼: ~~~ void Snake::advance(int step) { if (!step) { return; } if (tickCounter++ % speed != 0) { return; } if (moveDirection == NoMove) { return; } if (growing > 0) { QPointF tailPoint = head; tail << tailPoint; growing -= 1; } else { tail.takeFirst(); tail << head; } switch (moveDirection) { case MoveLeft: moveLeft(); break; case MoveRight: moveRight(); break; case MoveUp: moveUp(); break; case MoveDown: moveDown(); break; } setPos(head); handleCollisions(); } ~~~ `QGraphicsItem::advance()`函數接受一個 int 作為參數。這個 int 代表該函數被調用的時間。`QGraphicsItem::advance()`函數會被`QGraphicsScene::advance()`函數調用兩次:第一次時這個 int 為 0,代表即將開始調用;第二次這個 int 為 1,代表已經開始調用。在我們的代碼中,我們只使用不為 0 的階段,因此當 !step 時,函數直接返回。 `tickCounter`實際是我們內部的一個計時器。我們使用 speed 作為蛇的兩次動作的間隔時間,直接影響到游戲的難度。speed 值越大,兩次運動的間隔時間越大,游戲越簡單。這是因為隨著 speed 的增大,tickCounter % speed != 0 的次數響應越多,刷新的次數就會越少,蛇運動得越慢。 `moveDirection`顯然就是運動方向,當是 NoMove 時,函數直接返回。 `growing`是正在增長的方格數。當其大于 0 時,我們將頭部追加到尾部的位置,同時減少一個方格;當其小于 0 時,我們刪除第一個,然后把頭部添加進去。我們可以把 growing 看做即將發生的變化。比如,我們將 growing 初始化為 7。第一次運行`advance()`時,由于 7 > 1,因此將頭部追加,然后 growing 減少 1。直到 growing 為 0,此時,蛇的長度不再發生變化,直到我們吃了一個食物。 下面是相應的方向時需要調用對應的函數。最后,我們設置元素的坐標,同時檢測碰撞。
                  <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>

                              哎呀哎呀视频在线观看