Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "Level.h"
- #include <ctime>
- Level::Level(DrawEngine &de, int width, int height) :
- de(de), width(width), height(height), lastTime(0.0), speed(500), score(-1)
- {
- srand(time(0));
- // Allocate the drawing board
- board = new COLORREF*[width];
- for (int i = 0; i < width; i++)
- {
- board[i] = new COLORREF[height];
- for (int j = 0; j < height; j++)
- board[i][j] = RGB(0, 0, 0);
- }
- // 初始化目前和下一個方塊
- current = 0;
- next = pieceSet.getRandomPiece();
- }
- Level::~Level()
- {
- for (int i = 0; i < width; i++)
- delete [] board[i];
- delete [] board;
- }
- void Level::drawBoard() const
- {
- for (int i = 0; i < width; i++)
- for (int j = 0; j < height; j++)
- de.drawBlock(i, j, board[i][j]);
- }
- void Level::timerUpdate()
- {
- // If the time isn't up, don't drop nor update
- currentTime = timeGetTime();
- if (currentTime - lastTime < speed)
- return;
- // Time's up, drop
- // If the piece hits the bottom, check if player gets score, drop the next
- // piece, increase speed, redraw info
- // If player gets score, increase more speed
- if (current == NULL || !move(0, -1))
- {
- int lines = clearRows();
- speed = max(speed - 2 * lines, 100);
- score += 1 + lines * lines * 5;
- dropRandomPiece();
- drawScore();
- drawSpeed();
- drawNextPiece();
- }
- lastTime = timeGetTime();
- }
- bool Level::place(int x, int y, const Piece &piece)
- {
- // Out of boundary or the position has been filled
- if (x + piece.getWidth() > width || isCovered(piece, x, y))
- return false;
- posX = x;
- posY = y;
- POINT apt[4];
- piece.getBody(apt);
- COLORREF color = piece.getColor();
- for (int i = 0; i < 4; i++)
- {
- if (y + apt[i].y > height - 1)
- continue;
- board[x+apt[i].x][y+apt[i].y] = color;
- }
- return true;
- }
- bool Level::rotate()
- {
- Piece *tmp = current;
- // Move the piece if it needs some space to rotate
- int disX = max(posX + current->getHeight() - width, 0);
- // Go to next rotation state (0-3)
- int rotation = (current->getRotation() + 1) % PieceSet::NUM_ROTATIONS;
- clear(*current);
- current = pieceSet.getPiece(current->getId(), rotation);
- // Rotate successfully
- if (place(posX - disX, posY, *current))
- return true;
- // If the piece cannot rotate due to insufficient space, undo it
- current = tmp;
- place(posX, posY, *current);
- return false;
- }
- bool Level::move(int cxDistance, int cyDistance)
- {
- if (posX + cxDistance < 0 || posY + cyDistance < 0 ||
- posX + current->getWidth() + cxDistance > width)
- return false;
- if (cxDistance < 0 && isHitLeft())
- return false;
- if (cxDistance > 0 && isHitRight())
- return false;
- if (cyDistance < 0 && isHitBottom())
- return false;
- clear(*current);
- return place(posX + cxDistance, posY + cyDistance, *current);
- }
- void Level::clear(const Piece &piece)
- {
- POINT apt[4];
- piece.getBody(apt);
- int x, y;
- for (int i = 0; i < 4; i++) {
- x = posX + apt[i].x;
- y = posY + apt[i].y;
- if (x > width -1 || y > height - 1)
- continue;
- board[posX+apt[i].x][posY+apt[i].y] = RGB(0,0,0);
- }
- }
- void Level::dropRandomPiece()
- {
- current = next;
- next = pieceSet.getRandomPiece();
- place(3, height - 1, *current);
- }
- bool Level::isHitBottom() const
- {
- POINT apt[4];
- int n = current->getSkirt(apt);
- int x, y;
- for (int i = 0; i < n; i++)
- {
- x = posX + apt[i].x;
- y = posY + apt[i].y;
- if (y < height && (y == 0 || board[x][y-1] != RGB(0,0,0)))
- return true;
- }
- return false;
- }
- bool Level::isHitLeft() const
- {
- POINT apt[4];
- int n = current->getLeftSide(apt);
- int x, y;
- for (int i = 0; i < n; i++)
- {
- x = posX + apt[i].x;
- y = posY + apt[i].y;
- if (y > height - 1)
- continue;
- if (x == 0 || board[x-1][y] != RGB(0,0,0))
- return true;
- }
- return false;
- }
- bool Level::isHitRight() const
- {
- POINT apt[4];
- int n = current->getRightSide(apt);
- int x, y;
- for (int i = 0; i < n; i++)
- {
- x = posX + apt[i].x;
- y = posY + apt[i].y;
- if (y > height - 1)
- continue;
- if (x == width - 1 || board[x+1][y] != RGB(0,0,0))
- return true;
- }
- return false;
- }
- bool Level::isCovered(const Piece &piece, int x, int y) const
- {
- POINT apt[4];
- piece.getBody(apt);
- int tmpX, tmpY;
- for (int i = 0; i < 4; i++)
- {
- tmpX = apt[i].x + x;
- tmpY = apt[i].y + y;
- if (tmpX > width - 1 || tmpY > height -1)
- continue;
- if (board[tmpX][tmpY] != RGB(0,0,0))
- return true;
- }
- return false;
- }
- int Level::clearRows()
- {
- bool isComplete;
- int rows = 0;
- for (int i = 0; i < height; i++)
- {
- for (int j = 0; j < width; j++)
- {
- if (board[j][i] == RGB(0,0,0))
- {
- isComplete = false;
- break;
- }
- // The row is full
- if (j == width - 1)
- isComplete = true;
- }
- // If the row is full, clear it (fill with black)
- if (isComplete)
- {
- for (int j = 0; j < width; j++)
- board[j][i] = RGB(0,0,0);
- // Move rows down
- for (int k = i; k < height - 1; k++)
- {
- for (int m = 0; m < width; m++)
- board[m][k] = board[m][k+1];
- }
- i = -1;
- rows++;
- }
- }
- return rows;
- }
- bool Level::isGameOver()
- {
- // Exclude the current piece
- if (current)
- clear(*current);
- // If there's a piece on the top, game over
- for (int i = 0; i < width; i++) {
- if (board[i][height-1]) {
- if (current)
- place(posX, posY, *current);
- return true;
- }
- }
- // Put the current piece back
- if (current != 0)
- place(posX, posY, *current);
- return false;
- }
- void Level::drawSpeed() const
- {
- de.drawSpeed((500 - speed) / 2, width + 1, 12);
- }
- void Level::drawScore() const
- {
- de.drawScore(score, width + 1, 13);
- }
- void Level::drawNextPiece() const
- {
- de.drawNextPiece(*next, width + 1, 14);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement