Initial commit
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
#include "Brick.h"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
Platform *Brick::platform = 0;
|
||||
|
||||
Brick::Brick(int xPosition, int descentRate)
|
||||
{
|
||||
//ctor
|
||||
this->xPosition = xPosition;
|
||||
this->yPosition = -1;
|
||||
this->descentRate = descentRate;
|
||||
this->falling = false;
|
||||
|
||||
randomColor();
|
||||
}
|
||||
|
||||
Brick::~Brick()
|
||||
{
|
||||
//dtor
|
||||
}
|
||||
|
||||
void Brick::setPlatform(Platform *newPlatform)
|
||||
{
|
||||
platform = newPlatform;
|
||||
}
|
||||
|
||||
int Brick::getxPosition()
|
||||
{
|
||||
return xPosition;
|
||||
}
|
||||
|
||||
int Brick::getyPosition()
|
||||
{
|
||||
return yPosition;
|
||||
}
|
||||
|
||||
int Brick::getColor()
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
bool Brick::isFalling()
|
||||
{
|
||||
return falling;
|
||||
}
|
||||
|
||||
void Brick::fall()
|
||||
{
|
||||
if(!initialized)
|
||||
{
|
||||
std::cout << "Scene size not initialized!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(platform == 0)
|
||||
{
|
||||
std::cout << "Platform not set!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
falling = true;
|
||||
|
||||
while(running & falling & yPosition < yMax - 2)
|
||||
{
|
||||
// Freeze game
|
||||
if(freezed)
|
||||
{
|
||||
std::unique_lock<std::mutex> freezeLock(freezeMutex);
|
||||
|
||||
while(freezed)
|
||||
{
|
||||
freezeCondition.wait(freezeLock);
|
||||
}
|
||||
}
|
||||
|
||||
// If game terminated, we shouldn't do all this stuff
|
||||
if(running)
|
||||
{
|
||||
yPosition++;
|
||||
|
||||
if(yPosition == yMax - 2 && platform->getPosition() <= xPosition && platform->getEnd() >= xPosition)
|
||||
{
|
||||
falling = false;
|
||||
|
||||
if(platform->getColor() == color)
|
||||
{
|
||||
points += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(points != 0)
|
||||
{
|
||||
points--;
|
||||
}
|
||||
|
||||
freeze();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(250000 - 10000 * descentRate);
|
||||
}
|
||||
}
|
||||
|
||||
if(running)
|
||||
{
|
||||
// Reset
|
||||
yPosition = -1;
|
||||
falling = false;
|
||||
randomColor();
|
||||
}
|
||||
}
|
||||
|
||||
std::thread Brick::fallThread()
|
||||
{
|
||||
return std::thread(&Brick::fall, this);
|
||||
}
|
||||
|
||||
void Brick::randomColor()
|
||||
{
|
||||
color = rand() % 6 + 1;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef BRICK_H
|
||||
#define BRICK_H
|
||||
|
||||
#include <thread>
|
||||
#include "Platform.h"
|
||||
#include "Scene.h"
|
||||
|
||||
class Brick : public Scene
|
||||
{
|
||||
public:
|
||||
Brick(int xPosition, int descentRate);
|
||||
~Brick();
|
||||
static void setPlatform(Platform *newPlatform);
|
||||
int getxPosition();
|
||||
int getyPosition();
|
||||
int getColor();
|
||||
bool isFalling();
|
||||
std::thread fallThread();
|
||||
protected:
|
||||
private:
|
||||
static Platform *platform;
|
||||
int xPosition;
|
||||
int yPosition;
|
||||
int descentRate;
|
||||
int color;
|
||||
bool falling;
|
||||
void fall();
|
||||
void randomColor();
|
||||
};
|
||||
|
||||
#endif // BRICK_H
|
||||
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
CXXFLAGS = -Wall -std=c++11
|
||||
|
||||
OBJS = so2-game.o Brick.o Platform.o Scene.o Stopwatch.o
|
||||
|
||||
LIBS = -pthread -lncurses
|
||||
|
||||
TARGET = so2-game
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(TARGET)
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "Platform.h"
|
||||
#include <iostream>
|
||||
#include <ncurses.h>
|
||||
#include <unistd.h>
|
||||
|
||||
Platform::Platform()
|
||||
{
|
||||
//ctor
|
||||
points = 0;
|
||||
color = 0;
|
||||
sprite = "<--->";
|
||||
}
|
||||
|
||||
Platform::~Platform()
|
||||
{
|
||||
//dtor
|
||||
}
|
||||
|
||||
const char *Platform::getSprite()
|
||||
{
|
||||
return sprite.c_str();
|
||||
}
|
||||
|
||||
int Platform::getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
int Platform::getEnd()
|
||||
{
|
||||
int endPos = position + sprite.length() - 1;
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int Platform::getColor()
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
void Platform::terminateThreads()
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
|
||||
void Platform::moveKey()
|
||||
{
|
||||
if(!initialized)
|
||||
{
|
||||
std::cout << "Scene size not initialized!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int key;
|
||||
|
||||
while(running)
|
||||
{
|
||||
ncursesMutex.lock();
|
||||
key = getch();
|
||||
ncursesMutex.unlock();
|
||||
|
||||
// Freeze game
|
||||
if(freezed)
|
||||
{
|
||||
std::unique_lock<std::mutex> freezeLock(freezeMutex);
|
||||
|
||||
while(freezed)
|
||||
{
|
||||
freezeCondition.wait(freezeLock);
|
||||
}
|
||||
|
||||
// Ignore keys pressed when frozen
|
||||
flushinp();
|
||||
}
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case 'a':
|
||||
if(position > 0)
|
||||
{
|
||||
position--;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if(position < xMax - sprite.length())
|
||||
{
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::thread Platform::moveKeyThread()
|
||||
{
|
||||
return std::thread(&Platform::moveKey, this);
|
||||
}
|
||||
|
||||
void Platform::colorChange()
|
||||
{
|
||||
const int idleSeconds = 15;
|
||||
|
||||
while(running)
|
||||
{
|
||||
color = rand() % 6 + 1;
|
||||
|
||||
// Waiting - this must be interruptable, so it can't be just sleep(idleSeconds)
|
||||
for(int i = 0; i < idleSeconds * 10; i++)
|
||||
{
|
||||
// Freeze game
|
||||
if(freezed)
|
||||
{
|
||||
std::unique_lock<std::mutex> freezeLock(freezeMutex);
|
||||
|
||||
while(freezed)
|
||||
{
|
||||
freezeCondition.wait(freezeLock);
|
||||
}
|
||||
}
|
||||
|
||||
if(!running)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Every tick = 100 ms
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::thread Platform::colorChangeThread()
|
||||
{
|
||||
return std::thread(&Platform::colorChange, this);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "Scene.h"
|
||||
|
||||
class Platform : public Scene
|
||||
{
|
||||
public:
|
||||
Platform();
|
||||
~Platform();
|
||||
const char *getSprite();
|
||||
int getPosition();
|
||||
int getEnd();
|
||||
int getColor();
|
||||
void terminateThreads();
|
||||
std::thread moveKeyThread();
|
||||
std::thread colorChangeThread();
|
||||
protected:
|
||||
private:
|
||||
std::string sprite;
|
||||
int position;
|
||||
int points;
|
||||
int color;
|
||||
void moveKey();
|
||||
void colorChange();
|
||||
};
|
||||
|
||||
#endif // PLATFORM_H
|
||||
Binary file not shown.
@@ -0,0 +1,71 @@
|
||||
#include "Scene.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int Scene::xMax;
|
||||
int Scene::yMax;
|
||||
int Scene::points = 0;
|
||||
bool Scene::initialized = false;
|
||||
bool Scene::freezed = false;
|
||||
bool Scene::running = false;
|
||||
std::mutex Scene::ncursesMutex;
|
||||
std::mutex Scene::freezeMutex;
|
||||
std::condition_variable Scene::freezeCondition;
|
||||
|
||||
Scene::Scene()
|
||||
{
|
||||
//ctor
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
{
|
||||
//dtor
|
||||
}
|
||||
|
||||
void Scene::init(int xRes, int yRes)
|
||||
{
|
||||
xMax = xRes;
|
||||
yMax = yRes;
|
||||
running = true;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
int Scene::getPoints()
|
||||
{
|
||||
return points;
|
||||
}
|
||||
|
||||
bool Scene::isFreezed()
|
||||
{
|
||||
return freezed;
|
||||
}
|
||||
|
||||
void Scene::freeze()
|
||||
{
|
||||
const int idleSeconds = 10;
|
||||
|
||||
std::unique_lock<std::mutex> freezeLock(freezeMutex);
|
||||
freezed = true;
|
||||
sleep(idleSeconds);
|
||||
|
||||
// // This must be interruptable, so it can't be just sleep(idleSeconds)
|
||||
// for(int i = 0; i < idleSeconds * 10; i++)
|
||||
// {
|
||||
// if(running)
|
||||
// {
|
||||
// // Every tick = 100 ms
|
||||
// usleep(100000);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
freezed = false;
|
||||
freezeCondition.notify_all();
|
||||
}
|
||||
|
||||
void Scene::terminateAll()
|
||||
{
|
||||
Scene::running = false;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef SCENE_H
|
||||
#define SCENE_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
static std::mutex ncursesMutex;
|
||||
static std::mutex freezeMutex;
|
||||
static std::condition_variable freezeCondition;
|
||||
Scene();
|
||||
virtual ~Scene();
|
||||
static void init(int xRes, int yRes);
|
||||
static int getPoints();
|
||||
static bool isFreezed();
|
||||
static void terminateAll();
|
||||
protected:
|
||||
static int xMax;
|
||||
static int yMax;
|
||||
static int points;
|
||||
static bool initialized;
|
||||
static bool freezed;
|
||||
static bool running;
|
||||
static void freeze();
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // SCENE_H
|
||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
#include "Stopwatch.h"
|
||||
|
||||
Stopwatch::Stopwatch()
|
||||
{
|
||||
//ctor
|
||||
// Jan Potocki 2018
|
||||
}
|
||||
|
||||
void Stopwatch::start()
|
||||
{
|
||||
running = true;
|
||||
miliseconds = 0;
|
||||
measureThread = std::thread(&Stopwatch::measure, this);
|
||||
}
|
||||
|
||||
void Stopwatch::stop()
|
||||
{
|
||||
running = false;
|
||||
measureThread.join();
|
||||
}
|
||||
|
||||
bool Stopwatch::isRunning()
|
||||
{
|
||||
return running;
|
||||
}
|
||||
|
||||
float Stopwatch::read()
|
||||
{
|
||||
float measurement = (float)miliseconds / 1000;
|
||||
return measurement;
|
||||
}
|
||||
|
||||
void Stopwatch::measure()
|
||||
{
|
||||
while(running)
|
||||
{
|
||||
usleep(1000);
|
||||
miliseconds++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef STOPWATCH_H
|
||||
#define STOPWATCH_H
|
||||
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
// Klasa do pomiaru czasu w oparciu o funkcje systemowe
|
||||
// Jan Potocki 2018
|
||||
class Stopwatch
|
||||
{
|
||||
public:
|
||||
Stopwatch();
|
||||
void start();
|
||||
void stop();
|
||||
bool isRunning();
|
||||
float read();
|
||||
protected:
|
||||
private:
|
||||
unsigned long long int miliseconds;
|
||||
bool running;
|
||||
std::thread measureThread;
|
||||
void measure();
|
||||
};
|
||||
|
||||
#endif // STOPWATCH_H
|
||||
Binary file not shown.
@@ -0,0 +1,202 @@
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <ncurses.h>
|
||||
#include <unistd.h>
|
||||
#include "Brick.h"
|
||||
#include "Platform.h"
|
||||
#include "Stopwatch.h"
|
||||
|
||||
const int gameTime = 120;
|
||||
|
||||
int xMax, yMax;
|
||||
bool refreshing = false;
|
||||
bool climate = false;
|
||||
std::vector<Brick> bricks;
|
||||
Platform platform;
|
||||
Stopwatch gameClock;
|
||||
|
||||
// "Monitor" function
|
||||
void refreshScreen()
|
||||
{
|
||||
while(refreshing == true)
|
||||
{
|
||||
Scene::ncursesMutex.lock();
|
||||
clear();
|
||||
|
||||
for(int i = 0; i < bricks.size(); i++)
|
||||
{
|
||||
// Easter egg (1)
|
||||
if(climate)
|
||||
{
|
||||
attron(COLOR_PAIR(bricks[i].getColor()));
|
||||
mvprintw(bricks[i].getyPosition(), bricks[i].getxPosition(), "*");
|
||||
attroff(COLOR_PAIR(bricks[i].getColor()));
|
||||
}
|
||||
else
|
||||
{
|
||||
attron(COLOR_PAIR(bricks[i].getColor()));
|
||||
mvprintw(bricks[i].getyPosition(), bricks[i].getxPosition(), "#");
|
||||
attroff(COLOR_PAIR(bricks[i].getColor()));
|
||||
}
|
||||
}
|
||||
|
||||
attron(COLOR_PAIR(platform.getColor()));
|
||||
mvprintw(yMax - 2, platform.getPosition(), platform.getSprite());
|
||||
attroff(COLOR_PAIR(platform.getColor()));
|
||||
|
||||
mvprintw(yMax - 1, 0, "%.3f", gameClock.read());
|
||||
mvprintw(yMax - 1, xMax - 3, "%.3d", Scene::getPoints());
|
||||
|
||||
refresh();
|
||||
Scene::ncursesMutex.unlock();
|
||||
|
||||
// Refresh every 0.01 s
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::vector<std::thread> brickThreads;
|
||||
|
||||
srand(time(0));
|
||||
|
||||
// Easter egg (2)
|
||||
if(argc == 2)
|
||||
{
|
||||
std::string param(argv[1]);
|
||||
|
||||
if(param == "--globalwarming")
|
||||
{
|
||||
climate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize ncurses
|
||||
initscr();
|
||||
curs_set(0);
|
||||
getmaxyx(stdscr, yMax, xMax);
|
||||
|
||||
// Initialize colors
|
||||
start_color();
|
||||
init_pair(1, COLOR_RED, COLOR_BLACK);
|
||||
init_pair(2, COLOR_GREEN, COLOR_BLACK);
|
||||
init_pair(3, COLOR_YELLOW, COLOR_BLACK);
|
||||
init_pair(4, COLOR_BLUE, COLOR_BLACK);
|
||||
init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
|
||||
init_pair(6, COLOR_CYAN, COLOR_BLACK);
|
||||
|
||||
// Non-blocking input for platform-movement
|
||||
timeout(0);
|
||||
|
||||
// Initialize scene
|
||||
Scene::init(xMax, yMax);
|
||||
Brick::setPlatform(&platform);
|
||||
|
||||
// Initialize all bricks...
|
||||
for(int i = 0; i < xMax; i++)
|
||||
{
|
||||
// ...with random descent rate in range 0 (slow) to 15 (fast)
|
||||
Brick brick(i, rand() % 16);
|
||||
bricks.push_back(brick);
|
||||
}
|
||||
|
||||
// Start monitor
|
||||
refreshing = true;
|
||||
std::thread monitor(refreshScreen);
|
||||
|
||||
// Start platform treads
|
||||
std::thread platformMover(platform.moveKeyThread());
|
||||
std::thread platformColorChanger(platform.colorChangeThread());
|
||||
|
||||
// Start game
|
||||
gameClock.start();
|
||||
|
||||
while(gameClock.read() < gameTime)
|
||||
{
|
||||
// Freeze game
|
||||
if(Scene::isFreezed() == true)
|
||||
{
|
||||
std::unique_lock<std::mutex> freezeLock(Scene::freezeMutex);
|
||||
|
||||
while(Scene::isFreezed() == true)
|
||||
{
|
||||
Scene::freezeCondition.wait(freezeLock);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine random brick...
|
||||
int randBrick = rand() % xMax;
|
||||
while(bricks.at(randBrick).isFalling())
|
||||
{
|
||||
// ...which still isn't falling down...
|
||||
randBrick = rand() % xMax;
|
||||
}
|
||||
|
||||
// ...and launch it with nuclear-powered hammer ;-)
|
||||
brickThreads.push_back(bricks.at(randBrick).fallThread());
|
||||
|
||||
// Random time in range 400 to 800 ms until next fall
|
||||
unsigned randTime = rand() % 4 + 4;
|
||||
usleep(100000 * randTime);
|
||||
}
|
||||
|
||||
// Stop clock
|
||||
gameClock.stop();
|
||||
|
||||
// Stop scene objects threads
|
||||
Scene::terminateAll();
|
||||
|
||||
platformMover.join();
|
||||
platformColorChanger.join();
|
||||
|
||||
for(int i = 0; i < brickThreads.size(); i++)
|
||||
{
|
||||
brickThreads.at(i).join();
|
||||
}
|
||||
|
||||
// Stop monitor
|
||||
refreshing = false;
|
||||
monitor.join();
|
||||
sleep(1);
|
||||
|
||||
// Close ncurses
|
||||
endwin();
|
||||
|
||||
std::cout << "Your score: " << Scene::getPoints() << " points" << std::endl;
|
||||
|
||||
if(Scene::getPoints() != 0)
|
||||
{
|
||||
std::cout << "Congratulations!" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "BRIcks-ng Caban Kernel-thread System Next Generation v1.0" << std::endl;
|
||||
std::cout << "Jan Potocki 2018" << std::endl;
|
||||
std::cout << "(beerware)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << '"' << "...Back around that Halloween," << std::endl;
|
||||
std::cout << "Microsoft said open source would never last," << std::endl;
|
||||
std::cout << "But now they use the repo tools," << std::endl;
|
||||
std::cout << "In the same open access way..." << '"' << std::endl;
|
||||
std::cout << "(and recently acquired GitHub)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// Easter egg (3)
|
||||
if(climate)
|
||||
{
|
||||
std::cout << "SEVERE WEATHER ALERT: major snowfall predicted in 48h forecast for Lower Silesia, south-western Poland" << std::endl;
|
||||
std::cout << "Global warming affecting again!... ;-)" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Beware of BRICKS! ;-)" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user