QFrame::paintEvent(event); QPainter painter(this);
QRect rect = contentsRect(); // QRect定义了平面上的矩形 (详见API),是主游戏区
// 暂停的时候显示的信息 if (isPaused) {
painter.drawText(rect, Qt::AlignCenter, tr(\游戏暂停\ return; }
// BoardHeight*squareHeight() 相当于 contentsRect().Height(),是小网格的高
// 因为squareHeight() {return contentsRect().Width()/BoardWidth();} // 见tetrixboard.h中的定义
int boardTop = rect.bottom() - BoardHeight*squareHeight(); for (int i=0; i // TetrixShape &shapeAt(int x, int y) { return board[(y * BoardWidth) + x]; } TetrixShape shape = shapeAt(j, BoardHeight-i-1); if (shape != NoShape) // rect.left() 返回游戏区矩形左边的x坐标,squareWidth()为小网格的宽度 drawSquare(painter, rect.left() + j*squareWidth(), boardTop + i*squareHeight(), shape); } } // 绘图 if (curPiece.shape() != NoShape) { for (int i=0; i<4; ++i) { int x = curX + curPiece.x(i); int y = curY - curPiece.y(i); drawSquare(painter, rect.left() + x*squareWidth(), boardTop + (BoardHeight - y - 1 )*squareHeight(), curPiece.shape()); } } } // 键盘事件 void TetrixBoard::keyPressEvent(QKeyEvent *event) { if (!isStarted || isPaused || curPiece.shape() == NoShape) { QFrame::keyPressEvent(event); return; } switch (event->key()) { case Qt::Key_Left: tryMove(curPiece, curX-1, curY); // 左移 break; case Qt::Key_Right: tryMove(curPiece, curX+1, curY); // 右移 break; case Qt::Key_Up: tryMove(curPiece.rotatedLeft(),curX,curY); // 方块左转 break; case Qt::Key_Down: dropDown(); // 快速下落 break; default: QFrame::keyPressEvent(event); } } // 计时时间 void TetrixBoard::timerEvent(QTimerEvent *event) { if (event->timerId() == timer.timerId()) { // 如果还有方块已下落完毕 if (isWaitingAfterLine) { isWaitingAfterLine = false; // 重标记为有方块正在下落 newPiece(); // 添加新方块 (timeoutTime(), this); } else { oneLineDown(); //否则进行下落动作 } } else { QFrame::timerEvent(event); } } // 清空游戏区所有绘图 void TetrixBoard::clearBoard() { for (int i=0; i // 直接快速下落操作 void TetrixBoard::dropDown() { int dropHeight = 0; int newY = curY; // 进行下落过程,并求得方块还能下落的最大高度 while (newY > 0) { if (!tryMove(curPiece,curX,newY-1)) break; --newY; ++dropHeight; } // 把下落高度传递给此函数 pieceDropped(dropHeight); } // 正常下落操作 void TetrixBoard::oneLineDown() { if (!tryMove(curPiece, curX,curY-1)) // 如果能移动,则下落一行 pieceDropped(0);// 正常下落不几分 } // 进行方块下落后的行为,如绘图,加分等 参数:下落方块的高度 void TetrixBoard::pieceDropped(int dropHeight) { for (int i=0; i<4; ++i) { int x = curX + curPiece.x(i); int y = curY - curPiece.y(i); shapeAt(x,y) = curPiece.shape(); } ++numPiecesDropped; // 等级划分,加快下落速度 if (numPiecesDropped % 25 == 0) { ++level; timer.start(timeoutTime(), this); // 加速,游戏时间加快 emit levelChanged(level); } emit scoreChanged(score); // 判断是否已有满行 removeFullLines(); if (!isWaitingAfterLine) newPiece(); } // 移除整行 void TetrixBoard::removeFullLines() { int numFullLines = 0; // 循环判断有几行已满 for (int i = BoardHeight-1; i >= 0; --i) { bool lineIsFull = true; // 判断是否已满一行 for (int j=0; j < BoardWidth; ++j) { if (shapeAt(j,i)==NoShape) { lineIsFull = false; break; } } // 上面所有行下移 if (lineIsFull) { ++numFullLines; for(int k = i; k < BoardHeight-1; ++k) { for (int j = 0; j < BoardWidth; ++j) shapeAt(j,k) = shapeAt(j, k+1); } // 整行清零 for (int j = 0; j < BoardWidth; ++j) { shapeAt(j, BoardHeight-1) = NoShape; score += numFullLines-1 ; } } } // 如果已满行数大于0,则进行加分等操作,并更新窗口 if (numFullLines > 0) { numLinesRemoved += numFullLines; score += 10 * numFullLines; // 同时发送信号至相应的槽 emit linesRemovedChanged(numLinesRemoved); emit scoreChanged(score); (500,this); isWaitingAfterLine = true; curPiece.setShape(NoShape); update(); } } // 新方块 void TetrixBoard::newPiece() {