@@ -0,0 +1 @@ | |||
space-walk |
@@ -0,0 +1,74 @@ | |||
#include <algorithm> | |||
#include "board.h" | |||
#include "spaceship.h" | |||
Board::Board() { | |||
// Reserve 0 SpaceShips of memory for each planet | |||
for (unsigned char i = 0; i < BOARD_SIZE; i++) { | |||
this->planets[i] = new std::vector<SpaceShip *>(0); | |||
} | |||
} | |||
Board::~Board() { | |||
for (auto planet : this->planets) { | |||
delete planet; | |||
} | |||
} | |||
SpaceShip *Board::getShip(unsigned char planet, unsigned char pos) { | |||
if (planet >= BOARD_SIZE || pos >= this->planets[planet]->size()) { | |||
return new SpaceShip; | |||
} | |||
return this->planets[planet]->at(pos); | |||
} | |||
std::vector<SpaceShip *> *Board::getShips(unsigned char planet) { | |||
if (planet >= BOARD_SIZE) { | |||
return nullptr; | |||
} | |||
return this->planets[planet]; | |||
} | |||
bool Board::setShip(unsigned char planet, SpaceShip *ship) { | |||
if (planet >= BOARD_SIZE) { | |||
return false; | |||
} | |||
// Insert if the ship doesn't already exist on a planet | |||
if (ship->getPlanet() == PLANET_UNSET) { | |||
ship->setPlanet(planet); | |||
this->planets[planet]->push_back(ship); | |||
this->sortPlanet(planet); | |||
} | |||
return true; | |||
} | |||
bool Board::moveShip(unsigned char planet, SpaceShip *ship) { | |||
char shipPlanet = ship->getPlanet(); | |||
if (planet >= BOARD_SIZE || shipPlanet == -1 || shipPlanet == planet) { | |||
return false; | |||
} | |||
auto tmp = this->planets[(unsigned char)shipPlanet]; | |||
// Move ship to the end of the vector and then erase the last element | |||
// (Erase-remove idiom) | |||
tmp->erase(std::remove(tmp->begin(), tmp->end(), ship), tmp->end()); | |||
ship->setPlanet(planet); | |||
this->planets[planet]->push_back(ship); | |||
this->sortPlanet(planet); | |||
return true; | |||
} | |||
void Board::sortPlanet(unsigned char planet) { | |||
// Sort all ships on the planet, using function/functor/lambda | |||
std::sort(this->planets[planet]->begin(), this->planets[planet]->end(), | |||
[](SpaceShip *s1, SpaceShip *s2) -> bool { | |||
return s1->getSize() > s2->getSize(); | |||
}); | |||
} |
@@ -0,0 +1,28 @@ | |||
#ifndef BOARD_H | |||
#define BOARD_H | |||
#define BOARD_SIZE 14 | |||
#include <vector> | |||
class SpaceShip; | |||
class Board | |||
{ | |||
public: | |||
Board(); | |||
~Board(); | |||
SpaceShip *getShip(unsigned char planet, unsigned char pos); | |||
std::vector<SpaceShip *> *getShips(unsigned char planet); | |||
bool setShip(unsigned char planet, SpaceShip *ship); | |||
bool moveShip(unsigned char planet, SpaceShip *ship); | |||
void sortPlanet(unsigned char planet); | |||
private: | |||
// Data layout: | |||
// Black hole, 6 planets, 6 planets, black hole | |||
std::vector<SpaceShip *> *planets[BOARD_SIZE]; | |||
}; | |||
#endif // BOARD_H |
@@ -0,0 +1,84 @@ | |||
#include "board.h" | |||
#include "boardwindow.h" | |||
#include "maingame.h" | |||
#include "spaceship.h" | |||
BoardWindow::BoardWindow(int height, int width, Board *board) : | |||
height(height), | |||
width(width), | |||
board(board) { | |||
} | |||
BoardWindow::~BoardWindow() { | |||
} | |||
void BoardWindow::update() { | |||
Window::update(); | |||
this->resize(); | |||
int twoThirds = (this->getRows() / 3) * 2; | |||
int halfCols = this->getCols() / 2; | |||
int y = (twoThirds / 2) - 12; | |||
int x = halfCols - 4 - 1; | |||
// Print black hole | |||
this->printBlackHole(y, x, 0); | |||
y += 6; | |||
x = (this->getCols() / 2) - (46 / 2) - 1; | |||
// Print all planets | |||
for (int i = 1; i < BOARD_SIZE - 1; i++) { | |||
this->printPlanet(y, x, i); | |||
x += 8; | |||
if (i == (BOARD_SIZE - 2) / 2) { | |||
x = (this->getCols() / 2) - (46 / 2) - 1; | |||
y += 6; | |||
} | |||
} | |||
y += 6; | |||
x = halfCols - 4 - 1; | |||
// Print black hole | |||
this->printBlackHole(y, x, BOARD_SIZE - 1); | |||
} | |||
void BoardWindow::resize() { | |||
int rows = this->getMaxRows() - this->height; | |||
int cols = this->getMaxCols() - this->width; | |||
this->setWindow(rows, cols, 0, 0); | |||
Window::resize(); | |||
} | |||
void BoardWindow::printBlackHole(int y, int x, int planet) { | |||
this->print("+------+", y, x); | |||
this->print("| |", y + 1, x); | |||
this->print("| |", y + 2, x); | |||
this->print("| |", y + 3, x); | |||
this->print("+------+", y + 4, x); | |||
this->printSpaceShip(y + 1, x + 1, planet, 6); | |||
} | |||
void BoardWindow::printPlanet(int y, int x, int planet) { | |||
this->print("+----+", y, x); | |||
this->print("| |", y + 1, x); | |||
this->print("| |", y + 2, x); | |||
this->print("| |", y + 3, x); | |||
this->print("+----+", y + 4, x); | |||
this->printSpaceShip(y + 1, x + 1, planet, 4); | |||
} | |||
void BoardWindow::printSpaceShip(int y, int x, int planet, int width) { | |||
auto tmp = this->board->getShips(planet); | |||
int size = (int)tmp->size() + 1; | |||
for (int i = 1; i < size; i++) { | |||
tmp->at(i - 1)->render(this, y, x, false); | |||
x++; | |||
if (i != 1 && i % width == 0) { | |||
y++; | |||
x -= width; | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
#ifndef BOARDWINDOW_H | |||
#define BOARDWINDOW_H | |||
#include "window.h" | |||
class Board; | |||
class BoardWindow : public Window | |||
{ | |||
public: | |||
BoardWindow(int height, int width, Board *board); | |||
~BoardWindow(); | |||
void update(); | |||
void resize(); | |||
void printBlackHole(int y, int x, int planet); | |||
void printPlanet(int y, int x, int planet); | |||
void printSpaceShip(int y, int x, int planet, int width); | |||
private: | |||
int height; | |||
int width; | |||
Board *board; | |||
}; | |||
#endif // BOARDWINDOW_H |
@@ -0,0 +1,75 @@ | |||
#ifndef GAMESTATE | |||
#define GAMESTATE | |||
#include <chrono> // time | |||
#include <thread> // sleep_for | |||
#include "inputoutput.h" | |||
#include "window.h" | |||
class GameState | |||
{ | |||
public: | |||
// Makes sure that the inherited class's destructor is called | |||
virtual ~GameState() {} | |||
virtual void initialize() {} | |||
virtual void update() {} | |||
virtual void render() {} | |||
virtual void destroy() {} | |||
static void sleep(int amount) { | |||
// Sleep for amount ms | |||
std::this_thread::sleep_for(std::chrono::milliseconds(amount)); | |||
} | |||
}; | |||
class GameStateManager | |||
{ | |||
public: | |||
GameStateManager() : state(nullptr) { | |||
Window::initialize(); | |||
} | |||
~GameStateManager() { | |||
if(this->state != nullptr) { | |||
this->state->destroy(); | |||
delete this->state; | |||
} | |||
Window::destroy(); | |||
} | |||
void setState(GameState* state) { | |||
if(this->state != nullptr) { | |||
this->state->destroy(); | |||
delete this->state; | |||
} | |||
this->state = state; | |||
if(this->state != nullptr) { | |||
this->state->initialize(); | |||
} | |||
} | |||
void update() { | |||
GameState::sleep(15); | |||
if(this->state != nullptr) { | |||
this->state->update(); | |||
} | |||
} | |||
void render() { | |||
if(this->state != nullptr) { | |||
this->state->render(); | |||
} | |||
} | |||
private: | |||
GameState *state; | |||
}; | |||
extern GameStateManager gameStateManager; | |||
#endif // GAMESTATE |
@@ -0,0 +1,47 @@ | |||
#include "infowindow.h" | |||
#include "maingame.h" | |||
#include "player.h" | |||
#include "spaceship.h" | |||
InfoWindow::InfoWindow(int height, int width, Player **player, SpaceShip **ship) : | |||
height(height), | |||
width(width), | |||
player(player), | |||
ship(ship) { | |||
} | |||
InfoWindow::~InfoWindow() { | |||
} | |||
void InfoWindow::update() { | |||
Window::update(); | |||
this->resize(); | |||
int y = 0; | |||
int x = 1; | |||
for (unsigned char i = 0; i < PLAYER_SIZE; i++) { | |||
this->player[i]->render(this, y, x, i + 1); | |||
y += 6; | |||
int shipIdx = i * SHIP_SIZE / 2; | |||
for (unsigned char j = shipIdx; j < shipIdx + SHIP_SIZE / 2; j++) { | |||
this->ship[j]->render(this, y, x); | |||
x++; | |||
if (x > 3) { | |||
y++; | |||
x = 1; | |||
} | |||
} | |||
y += 2; | |||
} | |||
} | |||
void InfoWindow::resize() { | |||
int rows = this->getMaxRows() - this->height; | |||
int x = this->getMaxCols() - this->width; | |||
int cols = this->getMaxCols() - x; | |||
this->setWindow(rows, cols, 0, x); | |||
Window::resize(); | |||
} |
@@ -0,0 +1,25 @@ | |||
#ifndef INFOWINDOW_H | |||
#define INFOWINDOW_H | |||
#include "window.h" | |||
class Player; | |||
class SpaceShip; | |||
class InfoWindow : public Window | |||
{ | |||
public: | |||
InfoWindow(int height, int width, Player **player, SpaceShip **ship); | |||
~InfoWindow(); | |||
void update(); | |||
void resize(); | |||
private: | |||
int height; | |||
int width; | |||
Player **player; | |||
SpaceShip **ship; | |||
}; | |||
#endif // INFOWINDOW_H |
@@ -0,0 +1,69 @@ | |||
#include <cstdio> // size_t | |||
#include <ncurses.h> | |||
#include "inputoutput.h" | |||
void IO::initialize() { | |||
} | |||
void IO::update() { | |||
IO::keyCode = getch(); | |||
if (keyCode == KEY_ESC) { | |||
IO::setQuit(); | |||
return; | |||
} | |||
} | |||
std::string IO::trim(std::string str) { | |||
size_t first = str.find_first_not_of(" "); | |||
if (first == std::string::npos) { | |||
return ""; | |||
} | |||
size_t last = str.find_last_not_of(" "); | |||
return str.substr(first, (last - first + 1)); | |||
} | |||
std::string IO::untrim(std::string str, unsigned int length) { | |||
unsigned int strLength = str.length(); | |||
if (length > strLength) { | |||
int halfDiff = (length - strLength) / 2; | |||
std::string tmpStr; | |||
for (int i = 0; i < halfDiff; i++) { | |||
tmpStr += " "; | |||
} | |||
str.insert(0, tmpStr); | |||
str.append(tmpStr); | |||
} | |||
return str; | |||
} | |||
int IO::getKeyCode() { | |||
return IO::keyCode; | |||
} | |||
std::string IO::getKeyName() { | |||
return std::string(keyname(IO::keyCode)); | |||
} | |||
std::string IO::getStrInput() { | |||
echo(); | |||
char *tmp = new char(); | |||
getstr(tmp); | |||
noecho(); | |||
return std::string(tmp); | |||
} | |||
bool IO::getQuit() { | |||
return IO::quit; | |||
} | |||
void IO::setQuit() { | |||
IO::quit = true; | |||
} | |||
int IO::keyCode = ERR; | |||
bool IO::quit = false; |
@@ -0,0 +1,29 @@ | |||
#ifndef INPUTOUTPUT_H | |||
#define INPUTOUTPUT_H | |||
#define KEY_ESC 27 | |||
#define KEY_SPACE 32 | |||
#include <string> | |||
class IO | |||
{ | |||
public: | |||
static void initialize(); | |||
static void update(); | |||
static std::string trim(std::string str); | |||
static std::string untrim(std::string str, unsigned int length); | |||
static int getKeyCode(); | |||
static std::string getKeyName(); | |||
static std::string getStrInput(); | |||
static bool getQuit(); | |||
static void setQuit(); | |||
private: | |||
static int keyCode; | |||
static bool quit; | |||
}; | |||
#endif // INPUTOUTPUT_H |
@@ -0,0 +1,56 @@ | |||
/* | |||
* Rick van Vonderen | |||
* 0945444 | |||
* TI2B | |||
* | |||
* Avoid repeated writing by using: | |||
* - functions with parameters (no globals) instead of almost identical pieces of code | |||
* - repetitive loops and arrays instead of identical activities | |||
* - constants instead of identical values | |||
* | |||
* Divide your program into modules and/or classes that: | |||
* - have an explicit, well-defined interface | |||
* - be as independent as possible | |||
* - to be developed and tested separately | |||
* | |||
* Make your code understandable for others by using: | |||
* - Clear names in camel case, only start class names with a capital letter, consistently indent | |||
* - Clear, concise commentary, only where this adds something | |||
* - Standard terminology from the customer's field or application | |||
* | |||
* ClassExample | |||
* variableExample | |||
* DEFINE_EXAMPLE | |||
*/ | |||
#include <cstring> // strcmp() | |||
#include <ncurses.h> // refresh() | |||
#include "gamestate.h" | |||
#include "inputoutput.h" | |||
#include "mainmenu.h" | |||
#include "test.h" | |||
GameStateManager gameStateManager; | |||
int main(int argc, char *argv[]) { | |||
#ifdef DEBUG | |||
// IO::print("DEBUG MODE ENABLED"); | |||
refresh(); | |||
GameState::sleep(1000); | |||
if (argc >= 2 && strcmp(argv[1], "-t") == 0) { | |||
Test(); | |||
} | |||
#endif | |||
gameStateManager.setState(new MainMenu()); | |||
while (!IO::getQuit()) { | |||
gameStateManager.render(); | |||
gameStateManager.update(); | |||
} | |||
return 0; | |||
} |
@@ -0,0 +1,338 @@ | |||
#include <algorithm> | |||
#include "board.h" | |||
#include "boardwindow.h" | |||
#include "inputoutput.h" | |||
#include "maingame.h" | |||
#include "mainmenu.h" | |||
#include "messagebox.h" | |||
#include "player.h" | |||
#include "selectionbox.h" | |||
#include "spaceship.h" | |||
#include "window.h" | |||
#include "infowindow.h" | |||
MainGame::MainGame(Player **player) : | |||
help("Phase 1!\n\nThe players take turns, placing a spaceship on a planet\nof their choice."), | |||
phase(false), | |||
playerTurn(0), | |||
queuePlanet(-1), | |||
player(player), | |||
board(nullptr), | |||
ship(nullptr), | |||
boardWindow(nullptr), | |||
infoWindow(nullptr) { | |||
// Reserve 0 spaceships of memory for the queue | |||
this->queue = new std::vector<SpaceShip *>(0); | |||
} | |||
void MainGame::initialize() { | |||
this->board = new Board(); | |||
this->ship = new SpaceShip*[SHIP_SIZE] { nullptr }; | |||
unsigned char cCounter = 0; | |||
unsigned char colors[PLAYER_SIZE] = { PAIR_RED_BLACK, PAIR_BLUE_BLACK }; | |||
unsigned char sCounter = 0; | |||
unsigned char sizes[3] = { SpaceShip::SMALL, SpaceShip::MEDIUM, SpaceShip::BIG }; | |||
// Create 9 ships for each player, 3 of each size | |||
for (unsigned char i = 0; i < SHIP_SIZE; i++) { | |||
if (i != 0 && i % (SHIP_SIZE / PLAYER_SIZE) == 0) { | |||
cCounter++; | |||
} | |||
if (i != 0 && i % 3 == 0) { | |||
sCounter++; | |||
} | |||
if (sCounter >= 3) { | |||
sCounter = 0; | |||
} | |||
this->ship[i] = new SpaceShip(colors[cCounter], sizes[sCounter]); | |||
} | |||
this->boardWindow = new BoardWindow(0, 16, this->board); | |||
this->infoWindow = new InfoWindow(0, 16, this->player, this->ship); | |||
// Display help message | |||
MainGame::render(); | |||
MessageBox(this->help); | |||
} | |||
void MainGame::update() { | |||
MainGame::sleep(250); | |||
// Display new help message on phase change | |||
if (this->changePhase) { | |||
this->phase = true; | |||
this->changePhase = false; | |||
this->help = "Phase 2!\n\nThe players take turns, evacuating a planet of their choice."; | |||
MessageBox(this->help); | |||
return; | |||
} | |||
if (!this->phase) { | |||
this->phase1(); | |||
} | |||
else { | |||
this->phase2(); | |||
} | |||
} | |||
void MainGame::render() { | |||
this->boardWindow->clear(); | |||
this->infoWindow->clear(); | |||
this->boardWindow->update(); | |||
this->infoWindow->update(); | |||
this->boardWindow->render(); | |||
this->infoWindow->render(); | |||
} | |||
void MainGame::destroy() { | |||
delete this->board; | |||
delete this->boardWindow; | |||
delete this->infoWindow; | |||
for (int i = 0; i < SHIP_SIZE; i++) { | |||
delete this->ship[i]; | |||
} | |||
delete []this->ship; | |||
for (int i = 0; i < PLAYER_SIZE; i++) { | |||
delete this->player[i]; | |||
} | |||
delete []this->player; | |||
} | |||
void MainGame::phase1() { | |||
std::string playerTurnStr = std::to_string(this->playerTurn + 1); | |||
SelectionBox s = SelectionBox(0, 16); | |||
// Ask the current player to pick a Spaceship size | |||
std::string sizeStr = "Player " + playerTurnStr + ", pick a spaceship size."; | |||
std::string sizeOptions[] = {"S", "M", "B", "\0"}; | |||
unsigned char sizeSelection = s.select(sizeStr, &sizeOptions[0]); | |||
// Ask the current player to pick a planet | |||
std::string planetStr = "Player " + playerTurnStr + ", pick a planet to put this spaceship on."; | |||
std::string planetOptions[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "\0"}; | |||
unsigned char planetSelection = s.select(planetStr, &planetOptions[0]); | |||
// Calculate array index | |||
int startLoop = SHIP_SIZE / PLAYER_SIZE * this->playerTurn + (sizeSelection * 3); | |||
// Get ships of player selected planet | |||
auto ships = this->board->getShips(std::stoi(planetOptions[planetSelection])); | |||
bool placedShip = false; | |||
bool shouldExit; | |||
// Check all 3 ships of the size the player selected | |||
for (int i = startLoop; i < startLoop + 3; i++) { | |||
shouldExit = false; | |||
// Check if spaceship is already on a planet | |||
if (this->ship[i]->getPlanet() != PLANET_UNSET) { | |||
continue; | |||
} | |||
// If planet already holds spaceship of equal size | |||
for(auto ship : *ships) { | |||
if (this->ship[i]->getSize() == ship->getSize()) { | |||
shouldExit = true; | |||
break; | |||
} | |||
} | |||
if (shouldExit) { | |||
MessageBox("You cant place spaceships of the same size on a planet during this phase!", "Error"); | |||
break; | |||
} | |||
// Add spaceship to planet | |||
this->board->setShip(std::stoi(planetOptions[planetSelection]), this->ship[i]); | |||
this->nextPlayerTurn(); | |||
placedShip = true; | |||
break; | |||
} | |||
if (!placedShip && !shouldExit) { | |||
MessageBox("Please select a size of which you still have unplaced spaceships!", "Error"); | |||
} | |||
// Check if all ships have been placed | |||
bool allPlaced = true; | |||
for (int i = 0; i < SHIP_SIZE; i++) { | |||
if (this->ship[i]->getPlanet() == PLANET_UNSET) { | |||
allPlaced = false; | |||
break; | |||
} | |||
} | |||
if (allPlaced) { | |||
this->changePhase = true; | |||
} | |||
} | |||
void MainGame::phase2() { | |||
std::string playerTurnStr = std::to_string(this->playerTurn + 1); | |||
SelectionBox s = SelectionBox(0, 16); | |||
// Move next spaceship in the queue | |||
if (this->queue->size() > 0) { | |||
// Determine the middle of the board | |||
unsigned char halfBoard = (BOARD_SIZE - 2) / 2; // 6 | |||
// Planet rotation order, where |x| is a black hole | |||
// 1 ... 6 -> |13| -> 12 ... 7 -> |0| -> 1 | |||
// 0 .. 5 | |||
if (this->queuePlanet < halfBoard) { | |||
this->queuePlanet++; | |||
} | |||
// 8 .. 13 | |||
else if (this->queuePlanet > halfBoard + 1) { | |||
this->queuePlanet--; | |||
} | |||
// 6 | |||
else if (this->queuePlanet == halfBoard) { | |||
this->queuePlanet = BOARD_SIZE - 1; | |||
} | |||
// 7 | |||
else if (this->queuePlanet == halfBoard + 1) { | |||
this->queuePlanet = 0; | |||
} | |||
unsigned char shipSelection = 0; | |||
// If the the current and next ship are of the same size, ask which goes first | |||
if (this->queue->size() > 1) { | |||
SpaceShip *tmpShip = this->queue->at(0); | |||
SpaceShip *tmpShip2 = this->queue->at(1); | |||
if (tmpShip->getSize() == tmpShip2->getSize() && | |||
tmpShip->getColor() != tmpShip2->getColor()) { | |||
std::string shipStr = "Player " + playerTurnStr + ", pick the next ship that will evacuate."; | |||
std::string shipOptions[] = {"Yours", "Theirs", "\0"}; | |||
shipSelection = s.select(shipStr, &shipOptions[0]); | |||
} | |||
} | |||
board->moveShip(this->queuePlanet, this->queue->at(shipSelection)); | |||
return; | |||
} | |||
else if (this->queuePlanet != -1) { | |||
this->queuePlanet = -1; | |||
this->nextPlayerTurn(); | |||
this->calculateWinner(); | |||
return; | |||
} | |||
// Ask the current player if they want to skip their turn | |||
unsigned char playerChip = this->player[this->playerTurn]->getChip(); | |||
if (playerChip > 0) { | |||
std::string skipStr = "Player " + playerTurnStr + ", do you want to skip your turn for 1 chip?"; | |||
std::string skipOptions[] = {"No", "Yes", "\0"}; | |||
unsigned char skipSelection = s.select(skipStr, &skipOptions[0]); | |||
if (skipOptions[skipSelection] == "Yes") { | |||
this->player[this->playerTurn]->setChip(playerChip - 1); | |||
this->nextPlayerTurn(); | |||
return; | |||
} | |||
} | |||
// Ask the current player to pick a planet | |||
std::string planetStr = "Player " + playerTurnStr + ", pick a planet to evacuate."; | |||
std::string planetOptions[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "\0"}; | |||
unsigned char planetSelection = s.select(planetStr, &planetOptions[0]); | |||
// Get ships of player selected planet | |||
auto ships = this->board->getShips(std::stoi(planetOptions[planetSelection])); | |||
// Check if the selected planet holds a spaceship of the current player, | |||
// using function/functor/lambda | |||
unsigned char playerColor = this->player[(int)this->playerTurn]->getColor(); | |||
auto findShip = std::find_if(ships->begin(), ships->end(), | |||
[playerColor](SpaceShip *ship) {return ship->getColor() == playerColor; }); | |||
// If so, add this planet to the queue | |||
if (findShip != ships->end()) { | |||
this->queue = ships; | |||
this->queuePlanet = this->queue->at(0)->getPlanet(); | |||
} | |||
else { | |||
MessageBox("Please select a planet that holds a ship of your own!", "Error"); | |||
} | |||
} | |||
void MainGame::nextPlayerTurn() { | |||
this->playerTurn++; | |||
if (this->playerTurn > PLAYER_SIZE - 1) { | |||
this->playerTurn = 0; | |||
} | |||
} | |||
void MainGame::calculateWinner() { | |||
// Get all ships from the black holes | |||
auto blackHole1 = this->board->getShips(0); | |||
auto blackHole2 = this->board->getShips(BOARD_SIZE - 1); | |||
int totalScore = CHIP_AMOUNT * CHIP_SCORE + | |||
3 * SpaceShip::BIG + | |||
3 * SpaceShip::MEDIUM + | |||
3 * SpaceShip::SMALL; | |||
// Fill players possible total score | |||
int score[PLAYER_SIZE]; | |||
std::fill_n(score, PLAYER_SIZE, totalScore); | |||
// Calculate players score | |||
int crashedShips; | |||
bool gameOver = false; | |||
for (int i = 0; i < PLAYER_SIZE; i++) { | |||
// Subtract all used chips from the total score | |||
score[i] -= (CHIP_AMOUNT - this->player[i]->getChip()) * CHIP_SCORE; | |||
crashedShips = 0; | |||
for (auto ship : *blackHole1) { | |||
if (this->player[i]->getColor() == ship->getColor()) { | |||
crashedShips++; | |||
// Subtract crashed ship from the total score | |||
score[i] -= ship->getSize(); | |||
} | |||
} | |||
for (auto ship : *blackHole2) { | |||
if (this->player[i]->getColor() == ship->getColor()) { | |||
crashedShips++; | |||
// Subtract crashed ship from the total score | |||
score[i] -= ship->getSize(); | |||
} | |||
} | |||
// If a player has run out of ships.. | |||
if (crashedShips == SHIP_SIZE / PLAYER_SIZE) { | |||
gameOver = true; | |||
} | |||
} | |||
// Print victory screen | |||
if (gameOver) { | |||
std::string printStr; | |||
int winnerIdx = 0; | |||
for (int i = 0; i < PLAYER_SIZE; i++) { | |||
printStr += "Player " + std::to_string(i + 1) + ": scored " + | |||
std::to_string(score[i]) + " points.\n"; | |||
if (i < PLAYER_SIZE - 1 && score[i] < score[i + 1]) { | |||
winnerIdx = i + 1; | |||
} | |||
} | |||
printStr.insert(0, this->player[winnerIdx]->getName() + " has won!\n\n"); | |||
MessageBox(printStr, "Victory"); | |||
gameStateManager.setState(new MainMenu()); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
#ifndef MAINGAME_H | |||
#define MAINGAME_H | |||
// Each player holds 9 ships, 3 of each size | |||
#define SHIP_SIZE 18 | |||
#define PLAYER_SIZE 2 | |||
#include <vector> | |||
#include "gamestate.h" | |||
class Board; | |||
class BoardWindow; | |||
class InfoWindow; | |||
class Player; | |||
class SpaceShip; | |||
class MainGame : public GameState | |||
{ | |||
public: | |||
MainGame(Player **player); | |||
void initialize(); | |||
void update(); | |||
void render(); | |||
void destroy(); | |||
private: | |||
void phase1(); | |||
void phase2(); | |||
void nextPlayerTurn(); | |||
void calculateWinner(); | |||
std::string help; | |||
bool phase; | |||
bool changePhase; | |||
unsigned char playerTurn; | |||
char queuePlanet; | |||
std::vector<SpaceShip *> *queue; | |||
Player **player; | |||
Board *board; | |||
SpaceShip **ship; | |||
BoardWindow *boardWindow; | |||
InfoWindow *infoWindow; | |||
}; | |||
#endif // MAINGAME_H |
@@ -0,0 +1,98 @@ | |||
#include "inputoutput.h" | |||
#include "maingame.h" | |||
#include "mainmenu.h" | |||
#include "player.h" | |||
#include "window.h" | |||
void MainMenu::initialize() { | |||
int rows; | |||
int cols; | |||
Window::getMaXYZ(stdscr, rows, cols); | |||
this->window = new Window(rows, cols, 0, 0); | |||
this->titleScreen = true; | |||
this->player = new Player*[PLAYER_SIZE] { nullptr }; | |||
} | |||
void MainMenu::update() { | |||
if (this->titleScreen) { | |||
IO::update(); | |||
if (IO::getKeyName() == " ") { | |||
this->titleScreen = false; | |||
} | |||
} | |||
else { | |||
int y; | |||
int x; | |||
std::string tmpStr; | |||
unsigned char colors[PLAYER_SIZE] = { PAIR_RED_BLACK, PAIR_BLUE_BLACK }; | |||
for (int i = 0; i < PLAYER_SIZE; i++) { | |||
if (this->player[i] == nullptr) { | |||
this->window->getYX(y, x); | |||
tmpStr = ""; | |||
while (tmpStr == "") { | |||
tmpStr = IO::trim(this->window->getStr()); | |||
this->window->setYX(y, x); | |||
} | |||
this->player[i] = new Player(); | |||
this->player[i]->setName(tmpStr); | |||
this->player[i]->setColor(colors[i]); | |||
break; | |||
} | |||
if (i == PLAYER_SIZE - 1) { | |||
gameStateManager.setState(new MainGame(this->player)); | |||
} | |||
} | |||
} | |||
} | |||
void MainMenu::render() { | |||
this->window->clear(); | |||
this->window->update(); | |||
this->window->setWindow(this->window->getMaxRows(), this->window->getMaxCols(), 0, 0); | |||
this->window->resize(); | |||
if (this->titleScreen) { | |||
this->window->printSide("", "Rick van Vonderen"); | |||
this->window->setYX(1, 0); | |||
this->window->printSide("", "0945444"); | |||
this->window->setYX(2, 0); | |||
this->window->printSide("", "TI2B"); | |||
this->window->setYX(this->window->getRows() / 2 - 1, 0); | |||
this->window->printCenter("--- Space Walk ---"); | |||
this->window->setYX(this->window->getRows() - 4, 0); | |||
this->window->printCenter("Press <Space> to walk.."); | |||
} | |||
else { | |||
int x = this->window->getCols() / 2 - 11 ; | |||
int y = this->window->getRows() / 2; | |||
std::string tmp; | |||
for (int i = 0; i < PLAYER_SIZE; i++) { | |||
tmp = std::string("Enter Player ") + std::to_string(i + 1) + std::string(" name: "); | |||
if (this->player[i] != nullptr) { | |||
tmp += this->player[i]->getName(); | |||
} | |||
this->window->print(tmp, y, x); | |||
y++; | |||
if (this->player[i] == nullptr) { | |||
break; | |||
} | |||
} | |||
} | |||
this->window->render(); | |||
} | |||
void MainMenu::destroy() { | |||
delete this->window; | |||
} |
@@ -0,0 +1,25 @@ | |||
#ifndef MAINMENU_H | |||
#define MAINMENU_H | |||
#include <memory> | |||
#include "gamestate.h" | |||
class Player; | |||
class Window; | |||
class MainMenu : public GameState | |||
{ | |||
public: | |||
void initialize(); | |||
void update(); | |||
void render(); | |||
void destroy(); | |||
private: | |||
bool titleScreen; | |||
Window *window; | |||
Player **player; | |||
}; | |||
#endif // MAINMENU_H |
@@ -0,0 +1,54 @@ | |||
#------------------------------------------------------------------------------# | |||
PROGRAM := "space-walk" | |||
HEADERS := \ | |||
board.h \ | |||
boardwindow.h \ | |||
gamestate.h \ | |||
infowindow.h \ | |||
inputoutput.h \ | |||
maingame.h \ | |||
mainmenu.h \ | |||
messagebox.h \ | |||
player.h \ | |||
selectionbox.h \ | |||
spaceship.h \ | |||
test.h \ | |||
window.h | |||
SOURCES := \ | |||
board.cpp \ | |||
boardwindow.cpp \ | |||
infowindow.cpp \ | |||
inputoutput.cpp \ | |||
main.cpp \ | |||
maingame.cpp \ | |||
mainmenu.cpp \ | |||
messagebox.cpp \ | |||
player.cpp \ | |||
selectionbox.cpp \ | |||
spaceship.cpp \ | |||
test.cpp \ | |||
window.cpp | |||
#------------------------------------------------------------------------------# | |||
CXX := g++ | |||
CXXFLAGS := -lncurses -std=c++11 -Wall -Wextra | |||
.PHONY: all debug run clean | |||
all: run | |||
debug: CXXFLAGS += -g -DDEBUG | |||
debug: run | |||
run: compile | |||
@./$(PROGRAM) ; \ | |||
stty sane | |||
compile: ${HEADERS} ${SOURCES} | |||
$(CXX) $(CXXFLAGS) $? -o $(PROGRAM) | |||
clean: | |||
@-echo "Cleaning project.." ; \ | |||
rm -f $(PROGRAM) |
@@ -0,0 +1,57 @@ | |||
#include <ncurses.h> // A_REVERSE | |||
#include <sstream> // istringstream | |||
#include <vector> | |||
#include "inputoutput.h" | |||
#include "messagebox.h" | |||
MessageBox::MessageBox(std::string message) : | |||
MessageBox(message, "") { | |||
} | |||
MessageBox::MessageBox(std::string message, std::string title) { | |||
// Split message on newline | |||
std::vector<std::string> lines; | |||
std::istringstream strStream(message); | |||
std::string tmpStr; | |||
while (std::getline(strStream, tmpStr, '\n')) { | |||
lines.push_back(tmpStr); | |||
} | |||
int rows; | |||
int cols; | |||
Window::getMaXYZ(stdscr, rows, cols); | |||
// Calculate window dimension and size | |||
int winRows = lines.size() + 8; | |||
int winCols = cols * 0.9; | |||
int y = (rows - winRows) / 2; | |||
int x = (cols - winCols) / 2; | |||
this->setWindow(winRows, winCols, y, x); | |||
// Print title | |||
title = IO::untrim(!title.empty() ? title : "Message", winCols - 2); | |||
this->print(title, 0, 0, A_REVERSE); | |||
// Print the message line by line | |||
y = (winRows - lines.size()) / 2 - 1; | |||
for (auto l : lines) { | |||
this->setYX(y, 0); | |||
this->printCenter(l); | |||
y++; | |||
} | |||
this->setYX(winRows - 3, 0); | |||
this->printCenter("Press <Space> to continue ", | |||
COLOR_PAIR(PAIR_GRAY_BLACK_BRIGHT)); | |||
this->render(); | |||
// Press space to continue | |||
while(!IO::getQuit()) { | |||
IO::update(); | |||
if (IO::getKeyName() == " ") { | |||
break; | |||
} | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
#ifndef MESSAGEBOX_H | |||
#define MESSAGEBOX_H | |||
#include <string> | |||
#include "window.h" | |||
class MessageBox : public Window | |||
{ | |||
public: | |||
MessageBox(std::string message); | |||
MessageBox(std::string message, std::string title); | |||
private: | |||
}; | |||
#endif // MESSAGEBOX_H |
@@ -0,0 +1,53 @@ | |||
#include <ncurses.h> // A_REVERSE | |||
#include <stdio.h> | |||
#include "player.h" | |||
#include "infowindow.h" | |||
Player::Player() : | |||
chip(CHIP_AMOUNT), | |||
name("") { | |||
} | |||
void Player::render(InfoWindow *window, int y, int x, unsigned char number) { | |||
std::string print; | |||
print += " Player "; | |||
print += std::to_string(number); | |||
print += " "; | |||
window->print(print, y, x - 1, A_REVERSE); | |||
y += 2; | |||
window->print(this->name, y, x, COLOR_PAIR(this->color)); | |||
y += 2; | |||
for (unsigned char i = 0; i < this->chip; i++) { | |||
window->print("C", y, x, COLOR_PAIR(PAIR_WHITE_BLACK)); | |||
x++; | |||
window->print(" ", y, x); | |||
x++; | |||
} | |||
} | |||
unsigned char Player::getChip() { | |||
return this->chip; | |||
} | |||
void Player::setChip(unsigned char chip) { | |||
this->chip = chip; | |||
} | |||
unsigned char Player::getColor() { | |||
return this->color; | |||
} | |||
void Player::setColor(unsigned char color) { | |||
this->color = color; | |||
} | |||
std::string Player::getName() { | |||
return this->name; | |||
} | |||
void Player::setName(std::string name) { | |||
this->name = name; | |||
} |
@@ -0,0 +1,31 @@ | |||
#ifndef PLAYER_H | |||
#define PLAYER_H | |||
#define CHIP_AMOUNT 4 | |||
#define CHIP_SCORE 2 | |||
#include <string> | |||
class InfoWindow; | |||
class Player | |||
{ | |||
public: | |||
Player(); | |||
void render(InfoWindow *window, int y, int x, unsigned char number); | |||
unsigned char getChip(); | |||
void setChip(unsigned char chip); | |||
unsigned char getColor(); | |||
void setColor(unsigned char color); | |||
std::string getName(); | |||
void setName(std::string name); | |||
private: | |||
unsigned char chip; | |||
unsigned char color; | |||
std::string name; | |||
}; | |||
#endif // PLAYER_H |
@@ -0,0 +1,88 @@ | |||
#include <cstring> // strlen | |||
#include <sstream> // istringstream | |||
#include "inputoutput.h" | |||
#include "selectionbox.h" | |||
SelectionBox::SelectionBox(int height, int width) : | |||
height(height), | |||
width(width) { | |||
this->update(); | |||
} | |||
void SelectionBox::update() { | |||
Window::update(); | |||
this->resize(); | |||
} | |||
void SelectionBox::resize() { | |||
int rows = (this->getMaxRows() - this->height) / 4; | |||
int cols = this->getMaxCols() - this->width; | |||
this->setWindow(rows, cols, this->getMaxRows() - rows, 0); | |||
Window::resize(); | |||
} | |||
unsigned char SelectionBox::select(std::string str, std::string *selection) { | |||
int amount = 0; | |||
while (!selection[amount].empty()) { | |||
amount++; | |||
} | |||
std::string tmpStr; | |||
int tmpInt; | |||
// Display options and get user input | |||
while(!IO::getQuit()) { | |||
this->clear(); | |||
this->update(); | |||
this->printSelection(str, selection); | |||
this->render(); | |||
tmpStr = IO::trim(this->getStr()); | |||
if (tmpStr == "") { | |||
continue; | |||
} | |||
if (this->isNumber(tmpStr)) { | |||
tmpInt = std::stoi(tmpStr); | |||
if (tmpInt > 0 && tmpInt < amount + 1) { | |||
break; | |||
} | |||
} | |||
} | |||
return (unsigned char)tmpInt - 1; | |||
} | |||
void SelectionBox::printSelection(std::string str, std::string *selection) { | |||
int y = 0; | |||
// Split and print message on newline | |||
std::istringstream strStream(str); | |||
std::string tmpStr; | |||
while (std::getline(strStream, tmpStr, '\n')) { | |||
this->print(tmpStr, y, 1); | |||
y++; | |||
} | |||
y++; | |||
int amount = 0; | |||
while (!selection[amount].empty()) { | |||
if (amount < 6) { | |||
this->print("- " + selection[amount], y, 1); | |||
} | |||
else { | |||
this->print("- " + selection[amount], y - 6, 10); | |||
} | |||
y++; | |||
amount++; | |||
} | |||
this->print("Select option number: ", this->getRows() - 3, 1); | |||
} | |||
bool SelectionBox::isNumber(const std::string &s) { | |||
std::string::const_iterator it = s.begin(); | |||
while (it != s.end() && std::isdigit(*it)) it++; | |||
return !s.empty() && it == s.end(); | |||
} |
@@ -0,0 +1,26 @@ | |||
#ifndef SELECTIONBOX_H | |||
#define SELECTIONBOX_H | |||
#include <string> | |||
#include "window.h" | |||
class SelectionBox : public Window | |||
{ | |||
public: | |||
SelectionBox(int height, int width); | |||
void update(); | |||
void resize(); | |||
unsigned char select(std::string str, std::string *selection); | |||
void printSelection(std::string str, std::string *selection); | |||
private: | |||
bool isNumber(const std::string &s); | |||
int height; | |||
int width; | |||
}; | |||
#endif // SELECTIONBOX_H |
@@ -0,0 +1,57 @@ | |||
#include "spaceship.h" | |||
#include "window.h" | |||
SpaceShip::SpaceShip() : | |||
color(COLOR_UNSET), | |||
size(SpaceShip::SIZE_UNSET), | |||
planet(PLANET_UNSET) { | |||
} | |||
SpaceShip::SpaceShip(unsigned char color, unsigned char size) : | |||
color(color), | |||
size(size), | |||
planet(PLANET_UNSET) { | |||
} | |||
void SpaceShip::render(Window *window, int y, int x, bool checkPlaced) { | |||
if (checkPlaced && this->planet != PLANET_UNSET) { | |||
return; | |||
} | |||
std::string print = ""; | |||
if (this->size == SpaceShip::SMALL) { | |||
print = "S"; | |||
} | |||
else if (this->size == SpaceShip::MEDIUM) { | |||
print = "M"; | |||
} | |||
else if (this->size == SpaceShip::BIG) { | |||
print = "B"; | |||
} | |||
window->print(print, y, x, COLOR_PAIR(this->color)); | |||
} | |||
unsigned char SpaceShip::getColor() { | |||
return this->color; | |||
} | |||
void SpaceShip::setColor(unsigned char color) { | |||
this->color = color; | |||
} | |||
unsigned char SpaceShip::getSize() { | |||
return this->size; | |||
} | |||
void SpaceShip::setSize(unsigned char size) { | |||
this->size = size; | |||
} | |||
char SpaceShip::getPlanet() { | |||
return this->planet; | |||
} | |||
void SpaceShip::setPlanet(char planet) { | |||
this->planet = planet; | |||
} |
@@ -0,0 +1,36 @@ | |||
#ifndef SPACESHIP_H | |||
#define SPACESHIP_H | |||
#define PLANET_UNSET -1 | |||
class Window; | |||
class SpaceShip | |||
{ | |||
public: | |||
SpaceShip(); | |||
SpaceShip(unsigned char color, unsigned char size); | |||
void render(Window *window, int y, int x, bool checkPlaced = true); | |||
unsigned char getColor(); | |||
void setColor(unsigned char color); | |||
unsigned char getSize(); | |||
void setSize(unsigned char size); | |||
char getPlanet(); | |||
void setPlanet(char planet); | |||
enum Size { | |||
SIZE_UNSET = 0, | |||
SMALL = 1, | |||
MEDIUM = 3, | |||
BIG = 4, | |||
}; | |||
private: | |||
unsigned char color; | |||
unsigned char size; | |||
char planet; | |||
}; | |||
#endif // SPACESHIP_H |
@@ -0,0 +1,68 @@ | |||
#include <cassert> | |||
#include <iostream> | |||
#include <ncurses.h> | |||
#include "board.h" | |||
#include "inputoutput.h" | |||
#include "maingame.h" | |||
#include "player.h" | |||
#include "spaceship.h" | |||
#include "test.h" | |||
Test::Test() { | |||
// IO::print("Unit test\n"); | |||
refresh(); | |||
// Board tests | |||
Board *board = new Board; | |||
char arrayShip[3] = { SpaceShip::SMALL, SpaceShip::MEDIUM, SpaceShip::BIG }; | |||
SpaceShip *ship = new SpaceShip(1, arrayShip[0]); | |||
SpaceShip *ship2 = new SpaceShip(1, arrayShip[1]); | |||
SpaceShip *ship3 = new SpaceShip(1, arrayShip[2]); | |||
board->setShip(0, ship); | |||
board->setShip(0, ship); | |||
board->setShip(1, ship); | |||
board->setShip(1, ship2); | |||
board->setShip(2, ship3); | |||
for (int i = 0; i < 3; i++) { | |||
auto ships = board->getShips(i); | |||
// printf("%lu\n", ships->size()); | |||
for (int j = 0; j < (int)ships->size(); j++) { | |||
// printf("%d\n", ships->at(j)->getSize()); | |||
assert(ships->at(j)->getSize() == arrayShip[i]); | |||
} | |||
assert(ships->size() == 1); | |||
} | |||
board->moveShip(3, ship3); | |||
assert(board->getShip(3, 0)->getSize() == arrayShip[2]); | |||
// char array[SHIP_SIZE] = { | |||
// SpaceShip::SMALL, SpaceShip::SMALL, SpaceShip::SMALL, | |||
// SpaceShip::MEDIUM, SpaceShip::MEDIUM, SpaceShip::MEDIUM, | |||
// SpaceShip::BIG, SpaceShip::BIG, SpaceShip::BIG, | |||
// SpaceShip::SMALL, SpaceShip::SMALL, SpaceShip::SMALL, | |||
// SpaceShip::MEDIUM, SpaceShip::MEDIUM, SpaceShip::MEDIUM, | |||
// SpaceShip::BIG, SpaceShip::BIG, SpaceShip::BIG, | |||
// }; | |||
// for (unsigned char i = 0; i < SHIP_SIZE; i++) { | |||
// // printf("%d\n", board.ships[i]->getSize()); | |||
// // printf("%d\n", array[i]); | |||
// assert(board.ships[i]->getSize() == array[i]); | |||
// } | |||
// IO::print("Passed board checks.."); | |||
refresh(); | |||
getch(); | |||
// Cleanup resources | |||
delete board; | |||
delete ship; | |||
delete ship2; | |||
delete ship3; | |||
IO::setQuit(); | |||
} |
@@ -0,0 +1,12 @@ | |||
#ifndef TEST_H | |||
#define TEST_H | |||
class Test | |||
{ | |||
public: | |||
Test(); | |||
private: | |||
}; | |||
#endif // TEST_H |
@@ -0,0 +1,222 @@ | |||
#include <cstdio> | |||
#include "gamestate.h" | |||
#include "window.h" | |||
Window::Window(int rows, int cols, int y, int x) : | |||
rows(rows), | |||
cols(cols), | |||
y(0), | |||
x(0), | |||
window(newwin(rows, cols, y, x)) { | |||
} | |||
Window::~Window() { | |||
delwin(this->window); | |||
} | |||
void Window::initialize() { | |||
// Start curses mode | |||
initscr(); | |||
// Disable line buffering | |||
cbreak(); | |||
// Enable reading of function keys | |||
keypad(stdscr, TRUE); | |||
// Dont echo while reading input | |||
noecho(); | |||
// Disable cursor visibility | |||
curs_set(0); | |||
// If terminal supports colors | |||
if(!has_colors()) { | |||
printw("Your terminal does not support color\n"); | |||
} | |||
else { | |||
start_color(); | |||
use_default_colors(); | |||
init_pair(PAIR_WHITE_BLACK, COLOR_WHITE, COLOR_BLACK); | |||
init_pair(PAIR_WHITE_BRIGHT_BLACK, COLOR_WHITE_BRIGHT, COLOR_BLACK); | |||
init_pair(PAIR_RED_BLACK, COLOR_RED, COLOR_BLACK); | |||
init_pair(PAIR_BLUE_BLACK, COLOR_BLUE, COLOR_BLACK); | |||
init_pair(PAIR_GRAY_BLACK_BRIGHT, COLOR_GRAY, COLOR_BLACK_BRIGHT); | |||
} | |||
// Add bright colors, intensity range: 0-1000 | |||
if(!can_change_color()) { | |||
printw("Your terminal does not support changing colors\n"); | |||
} | |||
else { | |||
init_color(COLOR_BLACK, 0, 0, 0); | |||
init_color(COLOR_WHITE, 680, 680, 680); | |||
init_color(COLOR_GRAY, 380, 380, 380); | |||
init_color(COLOR_BLACK_BRIGHT, 110, 110, 110); // 0, 0, 0 | |||
init_color(COLOR_RED_BRIGHT, 900, 0, 0); // 680, 0, 0 | |||
init_color(COLOR_GREEN_BRIGHT, 0, 900, 0); // 0, 680, 0 | |||
init_color(COLOR_YELLOW_BRIGHT, 900, 900, 0); // 680, 680, 0 | |||
init_color(COLOR_BLUE_BRIGHT, 0, 0, 900); // 0, 0, 680 | |||
init_color(COLOR_MAGENTA_BRIGHT, 900, 0, 900); // 680, 0, 680 | |||
init_color(COLOR_CYAN_BRIGHT, 0, 900, 900); // 0, 680, 680 | |||
init_color(COLOR_WHITE_BRIGHT, 900, 900, 900); // 680, 680, 680 | |||
} | |||
} | |||
void Window::update() { | |||
Window::getMaXYZ(stdscr, this->maxRows, this->maxCols); | |||
} | |||
void Window::render() { | |||
box(this->window, 0, 0); | |||
wrefresh(this->window); | |||
} | |||
void Window::destroy() { | |||
// Restore line buffering | |||
nocbreak(); | |||
// Restore cursor | |||
curs_set(1); | |||
// End curses mode | |||
endwin(); | |||
} | |||
void Window::clear() { | |||
this->setYX(0, 0); | |||
// Set background color | |||
// wbkgdset(this->window, COLOR_PAIR(3)); | |||
// Copy blanks to every position in the window, clearing the screen | |||
werase(this->window); | |||
} | |||
void Window::resize() { | |||
wresize(this->window, this->rows, this->cols); | |||
mvwin(this->window, this->y, this->x); | |||
} | |||
void Window::print(std::string str, char newLine) { | |||
this->print(str, this->y, this->x); | |||
this->x += str.length(); | |||
if (newLine == 1) { | |||
this->x = 0; | |||
this->y++; | |||
} | |||
} | |||
void Window::print(std::string str, int y, int x) { | |||
this->y = y; | |||
this->x = x; | |||
mvwprintw(this->window, y + 1, x + 1, str.c_str()); | |||
} | |||
void Window::print(std::string str, int y, int x, int attribute) { | |||
wattron(this->window, attribute); | |||
this->print(str, y, x); | |||
wattroff(this->window, attribute); | |||
} | |||
void Window::printCenter(std::string str) { | |||
int halfBoard = this->cols / 2; | |||
int halfStr = str.length() / 2; | |||
this->print(str, this->y, halfBoard - halfStr - 1); | |||
} | |||
void Window::printCenter(std::string str, int attribute) { | |||
wattron(this->window, attribute); | |||
this->printCenter(str); | |||
wattroff(this->window, attribute); | |||
} | |||
void Window::printSide(std::string left, std::string right) { | |||
this->print(left, this->y, 1); | |||
this->print(right, this->y, this->cols - right.length() - 3); | |||
} | |||
void Window::getYX(int &y, int &x) { | |||
getyx(this->window, y, x); | |||
} | |||
void Window::setYX(int y, int x) { | |||
this->y = y; | |||
this->x = x; | |||
wmove(this->window, y, x); | |||
} | |||
void Window::getMaXYZ(int &rows, int &cols) { | |||
getmaxyx(this->window, rows, cols); | |||
} | |||
void Window::getMaXYZ(WINDOW *window, int &rows, int &cols) { | |||
getmaxyx(window, rows, cols); | |||
} | |||
std::string Window::getStr() { | |||
curs_set(1); | |||
echo(); | |||
char *tmp = new char(); | |||
wgetstr(this->window, tmp); | |||
noecho(); | |||
curs_set(0); | |||
return std::string(tmp); | |||
} | |||
int Window::getMaxRows() { | |||
return this->maxRows; | |||
} | |||
int Window::getMaxCols() { | |||
return this->maxCols; | |||
} | |||
int Window::getRows() { | |||
return this->rows; | |||
} | |||
void Window::setRows(int rows) { | |||
this->rows = rows; | |||
} | |||
int Window::getCols() { | |||
return this->cols; | |||
} | |||
void Window::setCols(int cols) { | |||
this->cols = cols; | |||
} | |||
int Window::getY() { | |||
return this->y; | |||
} | |||
void Window::setY(int y) { | |||
this->y = y; | |||
} | |||
int Window::getX() { | |||
return this->x; | |||
} | |||
void Window::setX(int x) { | |||
this->x = x; | |||
} | |||
void Window::setWindow(int rows, int cols, int y, int x) { | |||
this->setRows(rows); | |||
this->setCols(cols); | |||
this->setY(y); | |||
this->setX(x); | |||
if (this->window == nullptr) { | |||
this->window = newwin(rows, cols, y, x); | |||
} | |||
} | |||
//----------------------------------------------------------------------------// | |||
Window::Window() : | |||
rows(0), | |||
cols(0), | |||
y(0), | |||
x(0), | |||
window(nullptr) { | |||
} |
@@ -0,0 +1,75 @@ | |||
#ifndef WINDOW_H | |||
#define WINDOW_H | |||
#define COLOR_UNSET 0 | |||
#define COLOR_BLACK_BRIGHT 8 | |||
#define COLOR_RED_BRIGHT 9 | |||
#define COLOR_GREEN_BRIGHT 10 | |||
#define COLOR_YELLOW_BRIGHT 11 | |||
#define COLOR_BLUE_BRIGHT 12 | |||
#define COLOR_MAGENTA_BRIGHT 13 | |||
#define COLOR_CYAN_BRIGHT 14 | |||
#define COLOR_WHITE_BRIGHT 15 | |||
#define COLOR_GRAY 16 | |||
#define PAIR_WHITE_BLACK 1 | |||
#define PAIR_WHITE_BRIGHT_BLACK 2 | |||
#define PAIR_RED_BLACK 3 | |||
#define PAIR_BLUE_BLACK 4 | |||
#define PAIR_GRAY_BLACK_BRIGHT 5 | |||
#include <ncurses.h> | |||
#include <string> | |||
class Window | |||
{ | |||
public: | |||
Window(int rows, int cols, int y, int x); | |||
~Window(); | |||
static void initialize(); | |||
void update(); | |||
void render(); | |||
static void destroy(); | |||
void clear(); | |||
void resize(); | |||
void print(std::string str, char newLine = 1); | |||
void print(std::string str, int y, int x); | |||
void print(std::string str, int y, int x, int attribute); | |||
void printCenter(std::string str); | |||
void printCenter(std::string str, int attribute); | |||
void printSide(std::string left, std::string right); | |||
void getYX(int &y, int &x); | |||
void setYX(int y, int x); | |||
void getMaXYZ(int &rows, int &cols); | |||
static void getMaXYZ(WINDOW *window, int &rows, int &cols); | |||
std::string getStr(); | |||
int getMaxRows(); | |||
int getMaxCols(); | |||
int getRows(); | |||
void setRows(int rows); | |||
int getCols(); | |||
void setCols(int cols); | |||
int getY(); | |||
void setY(int y); | |||
int getX(); | |||
void setX(int x); | |||
void setWindow(int rows, int cols, int y, int x); | |||
protected: | |||
Window(); | |||
private: | |||
int maxRows; | |||
int maxCols; | |||
int rows; | |||
int cols; | |||
int y; | |||
int x; | |||
WINDOW *window; | |||
}; | |||
#endif // WINDOW_H |