<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之旅 廣告
                # Qt4 中的打磚塊游戲 > 原文: [http://zetcode.com/gui/qt4/breakoutgame/](http://zetcode.com/gui/qt4/breakoutgame/) 在 Qt4 教程的這一部分中,我們創建一個簡單的打磚塊游戲克隆。 打磚塊是 Atari Inc.開發的一款街機游戲。該游戲創建于 1976 年。在該游戲中,玩家移動槳葉并彈跳球。 目的是銷毀窗口頂部的磚塊。 可以在此處下載游戲圖像。 ## 開發 在我們的游戲中,我們只有一個槳,一個球和三十個磚頭。 計時器用于創建游戲周期。 我們不使用角度,而是僅更改方向:頂部,底部,左側和右側。 該代碼的靈感來自 Nathan Dawson 在 PyGame 庫中開發的 PyBreakout 游戲。 游戲是故意簡單的。 沒有獎金,等級或分數。 這樣更容易理解。 Qt4 庫是為創建計算機應用而開發的。 但是,它也可以用于創建游戲。 開發計算機游戲是了解 Qt4 的好方法。 `paddle.h` ```cpp #pragma once #include <QImage> #include <QRect> class Paddle { public: Paddle(); ~Paddle(); public: void resetState(); void move(); void setDx(int); QRect getRect(); QImage & getImage(); private: QImage image; QRect rect; int dx; static const int INITIAL_X = 200; static const int INITIAL_Y = 360; }; ``` 這是槳對象的頭文件。 `INITIAL_X`和`INITIAL_Y`是代表槳狀對象的初始坐標的常數。 `paddle.cpp` ```cpp #include "paddle.h" #include <iostream> Paddle::Paddle() { dx = 0; image.load("paddle.png"); rect = image.rect(); resetState(); } Paddle::~Paddle() { std::cout << ("Paddle deleted") << std::endl; } void Paddle::setDx(int x) { dx = x; } void Paddle::move() { int x = rect.x() + dx; int y = rect.top(); rect.moveTo(x, y); } void Paddle::resetState() { rect.moveTo(INITIAL_X, INITIAL_Y); } QRect Paddle::getRect() { return rect; } QImage & Paddle::getImage() { return image; } ``` 槳板可以向右或向左移動。 ```cpp Paddle::Paddle() { dx = 0; image.load("paddle.png"); rect = image.rect(); resetState(); } ``` 在構造器中,我們啟動`dx`變量并加載槳圖像。 我們得到圖像矩形并將圖像移動到其初始位置。 ```cpp void Paddle::move() { int x = rect.x() + dx; int y = rect.top(); rect.moveTo(x, y); } ``` `move()`方法移動槳的矩形。 移動方向由`dx`變量控制。 ```cpp void Paddle::resetState() { rect.moveTo(INITIAL_X, INITIAL_Y); } ``` `resetState()`將撥片移動到其初始位置。 `brick.h` ```cpp #pragma once #include <QImage> #include <QRect> class Brick { public: Brick(int, int); ~Brick(); public: bool isDestroyed(); void setDestroyed(bool); QRect getRect(); void setRect(QRect); QImage & getImage(); private: QImage image; QRect rect; bool destroyed; }; ``` 這是磚對象的頭文件。 如果銷毀了積木,則`destroyed`變量將設置為`true`。 `brick.cpp` ```cpp #include "brick.h" #include <iostream> Brick::Brick(int x, int y) { image.load("brickie.png"); destroyed = false; rect = image.rect(); rect.translate(x, y); } Brick::~Brick() { std::cout << ("Brick deleted") << std::endl; } QRect Brick::getRect() { return rect; } void Brick::setRect(QRect rct) { rect = rct; } QImage & Brick::getImage() { return image; } bool Brick::isDestroyed() { return destroyed; } void Brick::setDestroyed(bool destr) { destroyed = destr; } ``` `Brick`類代表磚對象。 ```cpp Brick::Brick(int x, int y) { image.load("brickie.png"); destroyed = false; rect = image.rect(); rect.translate(x, y); } ``` 磚的構造器加載其圖像,啟動`destroyed`標志,然后將圖像移至其初始位置。 ```cpp bool Brick::isDestroyed() { return destroyed; } ``` 磚塊具有`destroyed`標志。 如果設置了`destroyed`標志,則不會在窗口上繪制磚塊。 `ball.h` ```cpp #pragma once #include <QImage> #include <QRect> class Ball { public: Ball(); ~Ball(); public: void resetState(); void autoMove(); void setXDir(int); void setYDir(int); int getXDir(); int getYDir(); QRect getRect(); QImage & getImage(); private: int xdir; int ydir; QImage image; QRect rect; static const int INITIAL_X = 230; static const int INITIAL_Y = 355; static const int RIGHT_EDGE = 300; }; ``` 這是球形對象的頭文件。 `xdir`和`ydir`變量存儲球的運動方向。 `ball.cpp` ```cpp #include "ball.h" #include <iostream> Ball::Ball() { xdir = 1; ydir = -1; image.load("ball.png"); rect = image.rect(); resetState(); } Ball::~Ball() { std::cout << ("Ball deleted") << std::endl; } void Ball::autoMove() { rect.translate(xdir, ydir); if (rect.left() == 0) { xdir = 1; } if (rect.right() == RIGHT_EDGE) { xdir = -1; } if (rect.top() == 0) { ydir = 1; } } void Ball::resetState() { rect.moveTo(INITIAL_X, INITIAL_Y); } void Ball::setXDir(int x) { xdir = x; } void Ball::setYDir(int y) { ydir = y; } int Ball::getXDir() { return xdir; } int Ball::getYDir() { return ydir; } QRect Ball::getRect() { return rect; } QImage & Ball::getImage() { return image; } ``` `Ball`類表示球對象。 ```cpp xdir = 1; ydir = -1; ``` 開始時,球向東北方向移動。 ```cpp void Ball::autoMove() { rect.translate(xdir, ydir); if (rect.left() == 0) { xdir = 1; } if (rect.right() == RIGHT_EDGE) { xdir = -1; } if (rect.top() == 0) { ydir = 1; } } ``` 在每個游戲周期都會調用`autoMove()`方法來在屏幕上移動球。 如果它破壞了邊界,球的方向就會改變。 如果球越過底邊,則球不會反彈回來-游戲結束。 `breakout.h` ```cpp #pragma once #include <QWidget> #include <QKeyEvent> #include "ball.h" #include "brick.h" #include "paddle.h" class Breakout : public QWidget { Q_OBJECT public: Breakout(QWidget *parent = 0); ~Breakout(); protected: void paintEvent(QPaintEvent *); void timerEvent(QTimerEvent *); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); void drawObjects(QPainter *); void finishGame(QPainter *, QString); void moveObjects(); void startGame(); void pauseGame(); void stopGame(); void victory(); void checkCollision(); private: int x; int timerId; static const int N_OF_BRICKS = 30; static const int DELAY = 10; static const int BOTTOM_EDGE = 400; Ball *ball; Paddle *paddle; Brick *bricks[N_OF_BRICKS]; bool gameOver; bool gameWon; bool gameStarted; bool paused; }; ``` 這是突破對象的頭文件。 ```cpp void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); ``` 使用光標鍵控制槳。 在游戲中,我們監聽按鍵和按鍵釋放事件。 ```cpp int x; int timerId; ``` `x`變量存儲槳的當前 x 位置。 `timerId`用于識別計時器對象。 當我們暫停游戲時,這是必需的。 ```cpp static const int N_OF_BRICKS = 30; ``` `N_OF_BRICKS`常數存儲游戲中的積木數量。 ```cpp static const int DELAY = 10; ``` `DELAY`常數控制游戲的速度。 ```cpp static const int BOTTOM_EDGE = 400; ``` 當球通過底邊時,比賽結束。 ```cpp Ball *ball; Paddle *paddle; Brick *bricks[N_OF_BRICKS]; ``` 游戲包括一個球,一個球拍和一系列磚塊。 ```cpp bool gameOver; bool gameWon; bool gameStarted; bool paused; ``` 這四個變量代表游戲的各種狀態。 `breakout.cpp` ```cpp #include <QPainter> #include <QApplication> #include "breakout.h" Breakout::Breakout(QWidget *parent) : QWidget(parent) { x = 0; gameOver = false; gameWon = false; paused = false; gameStarted = false; ball = new Ball(); paddle = new Paddle(); int k = 0; for (int i=0; i<5; i++) { for (int j=0; j<6; j++) { bricks[k] = new Brick(j*40+30, i*10+50); k++; } } } Breakout::~Breakout() { delete ball; delete paddle; for (int i=0; i<N_OF_BRICKS; i++) { delete bricks[i]; } } void Breakout::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QPainter painter(this); if (gameOver) { finishGame(&painter, "Game lost"); } else if(gameWon) { finishGame(&painter, "Victory"); } else { drawObjects(&painter); } } void Breakout::finishGame(QPainter *painter, QString message) { QFont font("Courier", 15, QFont::DemiBold); QFontMetrics fm(font); int textWidth = fm.width(message); painter->setFont(font); int h = height(); int w = width(); painter->translate(QPoint(w/2, h/2)); painter->drawText(-textWidth/2, 0, message); } void Breakout::drawObjects(QPainter *painter) { painter->drawImage(ball->getRect(), ball->getImage()); painter->drawImage(paddle->getRect(), paddle->getImage()); for (int i=0; i<N_OF_BRICKS; i++) { if (!bricks[i]->isDestroyed()) { painter->drawImage(bricks[i]->getRect(), bricks[i]->getImage()); } } } void Breakout::timerEvent(QTimerEvent *e) { Q_UNUSED(e); moveObjects(); checkCollision(); repaint(); } void Breakout::moveObjects() { ball->autoMove(); paddle->move(); } void Breakout::keyReleaseEvent(QKeyEvent *e) { int dx = 0; switch (e->key()) { case Qt::Key_Left: dx = 0; paddle->setDx(dx); break; case Qt::Key_Right: dx = 0; paddle->setDx(dx); break; } } void Breakout::keyPressEvent(QKeyEvent *e) { int dx = 0; switch (e->key()) { case Qt::Key_Left: dx = -1; paddle->setDx(dx); break; case Qt::Key_Right: dx = 1; paddle->setDx(dx); break; case Qt::Key_P: pauseGame(); break; case Qt::Key_Space: startGame(); break; case Qt::Key_Escape: qApp->exit(); break; default: QWidget::keyPressEvent(e); } } void Breakout::startGame() { if (!gameStarted) { ball->resetState(); paddle->resetState(); for (int i=0; i<N_OF_BRICKS; i++) { bricks[i]->setDestroyed(false); } gameOver = false; gameWon = false; gameStarted = true; timerId = startTimer(DELAY); } } void Breakout::pauseGame() { if (paused) { timerId = startTimer(DELAY); paused = false; } else { paused = true; killTimer(timerId); } } void Breakout::stopGame() { killTimer(timerId); gameOver = true; gameStarted = false; } void Breakout::victory() { killTimer(timerId); gameWon = true; gameStarted = false; } void Breakout::checkCollision() { if (ball->getRect().bottom() > BOTTOM_EDGE) { stopGame(); } for (int i=0, j=0; i<N_OF_BRICKS; i++) { if (bricks[i]->isDestroyed()) { j++; } if (j == N_OF_BRICKS) { victory(); } } if ((ball->getRect()).intersects(paddle->getRect())) { int paddleLPos = paddle->getRect().left(); int ballLPos = ball->getRect().left(); int first = paddleLPos + 8; int second = paddleLPos + 16; int third = paddleLPos + 24; int fourth = paddleLPos + 32; if (ballLPos < first) { ball->setXDir(-1); ball->setYDir(-1); } if (ballLPos >= first && ballLPos < second) { ball->setXDir(-1); ball->setYDir(-1*ball->getYDir()); } if (ballLPos >= second && ballLPos < third) { ball->setXDir(0); ball->setYDir(-1); } if (ballLPos >= third && ballLPos < fourth) { ball->setXDir(1); ball->setYDir(-1*ball->getYDir()); } if (ballLPos > fourth) { ball->setXDir(1); ball->setYDir(-1); } } for (int i=0; i<N_OF_BRICKS; i++) { if ((ball->getRect()).intersects(bricks[i]->getRect())) { int ballLeft = ball->getRect().left(); int ballHeight = ball->getRect().height(); int ballWidth = ball->getRect().width(); int ballTop = ball->getRect().top(); QPoint pointRight(ballLeft + ballWidth + 1, ballTop); QPoint pointLeft(ballLeft - 1, ballTop); QPoint pointTop(ballLeft, ballTop -1); QPoint pointBottom(ballLeft, ballTop + ballHeight + 1); if (!bricks[i]->isDestroyed()) { if(bricks[i]->getRect().contains(pointRight)) { ball->setXDir(-1); } else if(bricks[i]->getRect().contains(pointLeft)) { ball->setXDir(1); } if(bricks[i]->getRect().contains(pointTop)) { ball->setYDir(1); } else if(bricks[i]->getRect().contains(pointBottom)) { ball->setYDir(-1); } bricks[i]->setDestroyed(true); } } } } ``` 在`breakout.cpp`文件中,我們有游戲邏輯。 ```cpp int k = 0; for (int i=0; i<5; i++) { for (int j=0; j<6; j++) { bricks[k] = new Brick(j*40+30, i*10+50); k++; } } ``` 在打磚塊對象的構造器中,我們實例化了三十個磚塊。 ```cpp void Breakout::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QPainter painter(this); if (gameOver) { finishGame(&painter, "Game lost"); } else if(gameWon) { finishGame(&painter, "Victory"); } else { drawObjects(&painter); } } ``` 根據`gameOver`和`gameWon`變量,我們要么用消息結束游戲,要么在窗口上繪制游戲對象。 ```cpp void Breakout::finishGame(QPainter *painter, QString message) { QFont font("Courier", 15, QFont::DemiBold); QFontMetrics fm(font); int textWidth = fm.width(message); painter->setFont(font); int h = height(); int w = width(); painter->translate(QPoint(w/2, h/2)); painter->drawText(-textWidth/2, 0, message); } ``` `finishGame()`方法在窗口中心繪制一條最終消息。 它是`"Game Over"`或`"Victory"`。 `QFontMetrics'` `width()`用于計算字符串的寬度。 ```cpp void Breakout::drawObjects(QPainter *painter) { painter->drawImage(ball->getRect(), ball->getImage()); painter->drawImage(paddle->getRect(), paddle->getImage()); for (int i=0; i<N_OF_BRICKS; i++) { if (!bricks[i]->isDestroyed()) { painter->drawImage(bricks[i]->getRect(), bricks[i]->getImage()); } } } ``` `drawObjects()`方法在窗口上繪制游戲的所有對象:球,球拍和磚頭。 這些對象由圖像表示,`drawImage()`方法將它們繪制在窗口上。 ```cpp void Breakout::timerEvent(QTimerEvent *e) { Q_UNUSED(e); moveObjects(); checkCollision(); repaint(); } ``` 在`timerEvent()`中,我們移動對象,檢查球是否與槳或磚相撞,并生成繪圖事件。 ```cpp void Breakout::moveObjects() { ball->autoMove(); paddle->move(); } ``` `moveObjects()`方法移動球和槳對象。 他們自己的移動方法被調用。 ```cpp void Breakout::keyReleaseEvent(QKeyEvent *e) { int dx = 0; switch (e->key()) { case Qt::Key_Left: dx = 0; paddle->setDx(dx); break; case Qt::Key_Right: dx = 0; paddle->setDx(dx); break; } } ``` 當播放器釋放`左`光標鍵或`右`光標鍵時,我們將板的`dx`變量設置為零。 結果,槳停止運動。 ```cpp void Breakout::keyPressEvent(QKeyEvent *e) { int dx = 0; switch (e->key()) { case Qt::Key_Left: dx = -1; paddle->setDx(dx); break; case Qt::Key_Right: dx = 1; paddle->setDx(dx); break; case Qt::Key_P: pauseGame(); break; case Qt::Key_Space: startGame(); break; case Qt::Key_Escape: qApp->exit(); break; default: QWidget::keyPressEvent(e); } } ``` 在`keyPressEvent()`方法中,我們監聽與游戲相關的按鍵事件。 `左`和`右`光標鍵移動槳狀對象。 他們設置`dx`變量,該變量隨后添加到槳的 x 坐標中。 `P` 鍵暫停游戲,`空格鍵`啟動游戲。 `Esc` 鍵退出應用。 ```cpp void Breakout::startGame() { if (!gameStarted) { ball->resetState(); paddle->resetState(); for (int i=0; i<N_OF_BRICKS; i++) { bricks[i]->setDestroyed(false); } gameOver = false; gameWon = false; gameStarted = true; timerId = startTimer(DELAY); } } ``` `startGame()`方法重置球和槳對象; 他們被轉移到他們的初始位置。 在`for`循環中,我們將每個積木的`destroyed`標志重置為`false`,從而將它們全部顯示在窗口中。 `gameOver`,`gameWon`和`gameStarted`變量獲得其初始布爾值。 最后,使用`startTimer()`方法啟動計時器。 ```cpp void Breakout::pauseGame() { if (paused) { timerId = startTimer(DELAY); paused = false; } else { paused = true; killTimer(timerId); } } ``` `pauseGame()`用于暫停和開始暫停的游戲。 狀態由`paused`變量控制。 我們還存儲計時器的 ID。 為了暫停游戲,我們使用`killTimer()`方法終止計時器。 要重新啟動它,我們調用`startTimer()`方法。 ```cpp void Breakout::stopGame() { killTimer(timerId); gameOver = true; gameStarted = false; } ``` 在`stopGame()`方法中,我們終止計時器并設置適當的標志。 ```cpp void Breakout::checkCollision() { if (ball->getRect().bottom() > BOTTOM_EDGE) { stopGame(); } ... } ``` 在`checkCollision()`方法中,我們對游戲進行碰撞檢測。 如果球撞到底邊,則比賽結束。 ```cpp for (int i=0, j=0; i<N_OF_BRICKS; i++) { if (bricks[i]->isDestroyed()) { j++; } if (j == N_OF_BRICKS) { victory(); } } ``` 我們檢查了多少磚被破壞了。 如果我們摧毀了所有積木,我們將贏得這場比賽。 ```cpp if (ballLPos < first) { ball->setXDir(-1); ball->setYDir(-1); } ``` 如果球碰到了槳的第一部分,我們會將球的方向更改為西北。 ```cpp if(bricks[i]->getRect().contains(pointTop)) { ball->setYDir(1); } ``` 如果球撞擊磚的底部,我們將改變球的 y 方向; 它下降了。 `main.cpp` ```cpp #include <QApplication> #include "breakout.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Breakout window; window.resize(300, 400); window.setWindowTitle("Breakout"); window.show(); return app.exec(); } ``` 這是主文件。 ![The Breakout game](https://img.kancloud.cn/94/12/941207514269d2abca85a3993eb61ee3_302x426.jpg) 圖:打磚塊游戲 這是 Qt4 中的打磚塊游戲。
                  <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>

                              哎呀哎呀视频在线观看