biquadris / graphicdisplay.cc
graphicdisplay.cc
Raw
#include "graphicdisplay.h"
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;

const int MARGIN = 20;
const int CELL_WIDTH = 20;
const int CELL_HEIGHT = 20;
const int BOARD_GAP_WIDTH = 120;
const int TEXT_HEIGHT = 22;
const int HEADER_HEIGHT = TEXT_HEIGHT * 2;
const int FOOTER_HEIGHT = TEXT_HEIGHT;
const int MAX_BLOCK_LENGTH = 4;

map<char,int> GraphicDisplay::colors = {
    {'I', Xwindow::Cyan},
    {'J', Xwindow::DarkBlue},
    {'L', Xwindow::Coral},
    {'O', Xwindow::Yellow},
    {'S', Xwindow::Green},
    {'Z', Xwindow::Red},
    {'T', Xwindow::DeepPink},
    {' ', Xwindow::Black},
    {'*', Xwindow::Brown},
    {'?', Xwindow::White}
};

const int BORDER_COLOR = Xwindow::Brown;

const int NUM_BOARDS = 2;

const int windowWidth = 4 * MARGIN + (2 * ((11 + 2) * CELL_WIDTH)) + 10 * CELL_WIDTH + BOARD_GAP_WIDTH;

void GraphicDisplay::updateLevel(int boardId, int level) {
    const int boardWidth = (width + 2) * CELL_WIDTH;
    ostringstream ss;
    ss << "Level:" << setw(5) << level;
    w->fillRectangle(80 + 5 + boardId * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH), MARGIN - 7, 100, TEXT_HEIGHT, Xwindow::Black);
    w->drawString(80 + 5 + boardId * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH), MARGIN + TEXT_HEIGHT - 7, ss.str());
}

void GraphicDisplay::updateScore(int boardId, int score) {
    const int boardWidth = (width + 2) * CELL_WIDTH;
    ostringstream ss;
    ss << "Score:" << setw(5) << score;
    w->fillRectangle(80 + 5 + boardId * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH), MARGIN + TEXT_HEIGHT - 7, 250, TEXT_HEIGHT,
                    Xwindow::Black);
    w->drawString(80 + 5 + boardId * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH), MARGIN + 2 * TEXT_HEIGHT - 7, ss.str());
}

void GraphicDisplay::updateHighScore(int highScore) {
    ostringstream ss;
    ss << "High Score:" << setw(5) << highScore;
    w->fillRectangle((width + 3) * CELL_WIDTH, MARGIN + TEXT_HEIGHT, 125, TEXT_HEIGHT, Xwindow::Black);
    w->drawString((width + 3) * CELL_WIDTH, MARGIN + 2 * TEXT_HEIGHT, ss.str());
}

GraphicDisplay::GraphicDisplay(int width, int height) :
    BiquadrisDisplay{NUM_BOARDS, width, height},
    w{make_unique<Xwindow>(2 * MARGIN + (2 * ((width + 2) * CELL_WIDTH)) + BOARD_GAP_WIDTH,
      2 * MARGIN + ((height + 2) * CELL_HEIGHT) + HEADER_HEIGHT + FOOTER_HEIGHT + MAX_BLOCK_LENGTH * CELL_HEIGHT)} {
    w->fillRectangle(0, 0,
                    4 * MARGIN + (2 * ((width + 2) * CELL_WIDTH)) + BOARD_GAP_WIDTH,
                    2 * MARGIN + ((height + 2) * CELL_HEIGHT) + HEADER_HEIGHT + FOOTER_HEIGHT + MAX_BLOCK_LENGTH * CELL_HEIGHT);
    
    const int boardWidth = (width + 2) * CELL_WIDTH;
    // Draw boards
    for (int i = 0; i < NUM_BOARDS; ++i) {
        w->fillRectangle(i * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH), MARGIN + HEADER_HEIGHT, boardWidth,
                        (height + 2) * CELL_HEIGHT, Xwindow::Silver);
        w->fillRectangle(CELL_WIDTH + i * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH), MARGIN + HEADER_HEIGHT + CELL_HEIGHT,
                        width * CELL_WIDTH, height * CELL_HEIGHT, Xwindow::Black);
    }

    // Draws scoreboards and other info
    for (int i = 0; i < amount; ++i) {
        updateLevel(i, 0);
        updateScore(i, 0);
        updateHighScore(0);
        w->drawString(5 + i * (boardWidth + 2 * MARGIN + BOARD_GAP_WIDTH),
                     MARGIN + HEADER_HEIGHT + (height + 2) * CELL_HEIGHT + TEXT_HEIGHT, "Next Block:");
    }
}

void GraphicDisplay::update(int _highScore) {
    coverHint();
    highScore = _highScore;
    updateHighScore(highScore);
}

void GraphicDisplay::update(int boardId, int score) {
    coverHint();
    updateScore(boardId, score);
}

void GraphicDisplay::update(int boardId, int level, char nextBlock) {
    coverHint();
    updateLevel(boardId, level);
    Shapes theShape(nextBlock);
    vector<pair<int,int>> layout = theShape.getLayout(0);
    const int color = colors.find(nextBlock)->second;
    w->fillRectangle(boardId * (((width + 4) * CELL_WIDTH) + BOARD_GAP_WIDTH),
                    MARGIN + HEADER_HEIGHT + TEXT_HEIGHT + (height + 2) * CELL_HEIGHT + 5,
                    MAX_BLOCK_LENGTH * CELL_WIDTH, MAX_BLOCK_LENGTH * CELL_HEIGHT, Xwindow::Black);
    for (auto p : layout) {
        w->fillRectangle(boardId * (((width + 4) * CELL_WIDTH) + BOARD_GAP_WIDTH) + p.second * CELL_WIDTH,
                        5 + HEADER_HEIGHT + TEXT_HEIGHT + (height + 2 + MAX_BLOCK_LENGTH) * CELL_HEIGHT + p.first * CELL_HEIGHT,
                        CELL_WIDTH, CELL_HEIGHT, color);
    }
}

void GraphicDisplay::update(int boardId, int row, int col, char type) {
    coverHint();
    const int color = colors.find(type)->second;
    w->fillRectangle(CELL_WIDTH + boardId * ((width + 4) * CELL_WIDTH + BOARD_GAP_WIDTH) + col * CELL_WIDTH,
                    HEADER_HEIGHT + (row + 2) * CELL_HEIGHT,
                    CELL_WIDTH, CELL_HEIGHT, color);
}

void GraphicDisplay::coverHint() {
    w->fillRectangle(width * CELL_WIDTH + 50, MARGIN, 200, TEXT_HEIGHT, Xwindow::Black);
}

void GraphicDisplay::setHint(string hint) {
    w->drawString(width * CELL_WIDTH + 50, MARGIN + TEXT_HEIGHT, hint);
}

bool GraphicDisplay::printable() { return false; }

void GraphicDisplay::playerLoses() {}