commit 9bd6c9e71b56821ae058078db4d0776f58bd9faa Author: RinRi Date: Sun Apr 3 13:57:25 2022 +0600 initial commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..ed4a812 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +AccessModifierOffset: -2 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba904ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +main +CPPLINT.cfg \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..31c4a50 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CXX = g++ +CXXFLAGS = -g -Wall -std=c++17 +LDFLAGS = -lpthread + +SRC = main.cpp object.cpp world.cpp +OBJ = ${SRC:.cpp=.o} + +all: main + +.o: ${OBJ} + ${CXX} -c ${CXXFLAGS} $< + +main: ${OBJ} + ${CXX} -o $@ ${OBJ} ${LDFLAGS} + +clean: + rm -f main ${OBJ} \ No newline at end of file diff --git a/config.h b/config.h new file mode 100644 index 0000000..2d1c3b9 --- /dev/null +++ b/config.h @@ -0,0 +1,8 @@ +#pragma once + +#define TICKRATE 16 + +#define WORLD_HEIGHT 32 +#define WORLD_WIDTH 32 +#define DEFAULT_CHAR '.' + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..95f285d --- /dev/null +++ b/main.cpp @@ -0,0 +1,133 @@ +#include "config.h" +#include "world.h" + +#include +#include +#include +#include +#include + +#include //termios, TCSANOW, ECHO, ICANON +#include //STDIN_FILENO + +constexpr int ticktime = 1000.0 / TICKRATE; +static struct termios oldt, newt; + +enum gamestatus { RUNNING, PAUSED, STOPPED } game; + +void initTerminal() { + /*tcgetattr gets the parameters of the current terminal + STDIN_FILENO will tell tcgetattr that it should write the settings + of stdin to oldt*/ + tcgetattr(STDIN_FILENO, &oldt); + /*now the settings will be copied*/ + newt = oldt; + + /*ICANON normally takes care that one line at a time will be processed + that means it will return if it sees a "\n" or an EOF or an EOL*/ + newt.c_lflag &= ~(ICANON); + + /*ECHO - don't print user input */ + newt.c_lflag &= ~(ECHO); + + /*Those new settings will be set to STDIN + TCSANOW tells tcsetattr to change attributes immediately. */ + tcsetattr(STDIN_FILENO, TCSANOW, &newt); +} + +void restoreTerminal() { + /*restore the old settings*/ + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +} + +void input(Object &o) { + while (game != STOPPED) { + char c = getchar(); + if (game == PAUSED) { + if (c == 'p') + game = RUNNING; + continue; + } + bool ok = 1; + switch (c) { + case 'w': + o.changePosition(0, -1); + break; + case 's': + o.changePosition(0, 1); + break; + case 'd': + o.changePosition(1, 0); + break; + case 'a': + o.changePosition(-1, 0); + break; + case 'p': + game = PAUSED; + break; + case 'e': + ok = 0; + break; + default: + break; + } + + if (!ok) + break; + } +} + +void botAI(Object &o) { + while (game != STOPPED) { + if (game == PAUSED) + continue; + o.changePosition(rand() % 3 - 1, rand() % 3 - 1); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } +} + +void gameloop(World &world) { + while (game != STOPPED) { + if (game == RUNNING) + world.update(); + world.print(std::cout); + + switch (game) { + case RUNNING: + std::cout << "GAME RUNNING!\n"; + break; + case PAUSED: + std::cout << "GAME PAUSED\n"; + break; + default: + std::cout << "GAME UNDEFINED\n"; + break; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(ticktime)); + + std::cout << "\x1B[2J\x1B[H"; + } +} + +int main() { + initTerminal(); + srand(time(NULL)); + + game = RUNNING; + World world; + Object &objtest = + world.createObject(Object(Object::Position(3, 3), 3, '*')); + Object &objtestAI = + world.createObject(Object(Object::Position(20, 20), 4, '=')); + + std::thread m(gameloop, std::ref(world)); + std::thread bot(botAI, std::ref(objtestAI)); + std::thread in(input, std::ref(objtest)); + in.join(); + game = STOPPED; + bot.join(); + m.join(); + restoreTerminal(); +} + diff --git a/object.cpp b/object.cpp new file mode 100644 index 0000000..4bb281b --- /dev/null +++ b/object.cpp @@ -0,0 +1,29 @@ +#include "config.h" +#include "object.h" + +Object::Object() : m_symbol('*'), m_size(1), m_pos(0, 0) {} + +Object::Object(Position pos, int size, char symbol) + : m_symbol(symbol), m_size(size), m_pos(pos) {} + +char Object::getSymbol() { return m_symbol; } + +Object::Position Object::getPosition() { return m_pos; } + +int Object::getSize() { return m_size; } + +void Object::setPosition(Object::Position p) { m_pos = p; } + +void Object::changePosition(double dx, double dy) { + if (m_pos.X + dx + (-(m_size + 1) / 2 + 1) < 0) + dx = -(m_pos.X + (-(m_size + 1) / 2 + 1)); + if (m_pos.Y + dy + (-(m_size + 1) / 2 + 1) < 0) + dy = -(m_pos.Y + (-(m_size + 1) / 2 + 1)); + if (m_pos.X + dx + m_size / 2 >= WORLD_WIDTH) + dx = (WORLD_WIDTH-1) - (m_pos.X + m_size / 2); + if (m_pos.Y + dy + m_size / 2 >= WORLD_HEIGHT) + dy = (WORLD_HEIGHT-1) - (m_pos.Y + m_size / 2); + + m_pos.X += dx, m_pos.Y += dy; +} + diff --git a/object.h b/object.h new file mode 100644 index 0000000..8c4dc3c --- /dev/null +++ b/object.h @@ -0,0 +1,38 @@ +#pragma once + +class Object { +public: + struct Position { + double X, Y; + + Position(): X(0), Y(0) { + + } + + Position(double x, double y): X(x), Y(y) { + + } + + void setPos(double x, double y) { + X = x, Y = y; + } + + const Position& operator=(const Position &p) { + this->X = p.X, this->Y = p.Y; + return *this; + } + }; + + Object(); + Object(Position pos, int size, char symbol); + virtual char getSymbol(); + Position getPosition(); + int getSize(); + void setPosition(Position p); + void changePosition(double dx, double dy); + +protected: + char m_symbol; + int m_size; + Position m_pos; +}; diff --git a/world.cpp b/world.cpp new file mode 100644 index 0000000..8caf4ed --- /dev/null +++ b/world.cpp @@ -0,0 +1,45 @@ +#include "world.h" + +World::World() + : m_height(WORLD_HEIGHT), m_width(WORLD_WIDTH), + m_c(WORLD_HEIGHT, std::vector(WORLD_WIDTH, DEFAULT_CHAR)) { + init(); +} + +void World::init() {} + +Object &World::createObject(Object &&o) { + m_objects.push_front(o); + return m_objects.front(); +} + +void World::draw(Object &o) { + double x = o.getPosition().X, y = o.getPosition().Y; + int sz = o.getSize(); + char c = o.getSymbol(); + for (int i = -(sz + 1) / 2 + 1; i <= sz / 2; ++i) + for (int j = -(sz + 1) / 2 + 1; j <= sz / 2; ++j) + m_c[y + i][x + j] = c; +} + +void World::update() { + for (auto &i : m_c) + for (auto &j : i) + j = DEFAULT_CHAR; + + for (auto &it : m_objects) { + draw(it); + } +} + +void World::print(std::ostream &out) { + for (const auto &i : m_c) { + for (const auto &j : i) + out << j; + out << '\n'; + } +} + +void World::destroy() {} + +World::~World() { destroy(); } diff --git a/world.h b/world.h new file mode 100644 index 0000000..f13be04 --- /dev/null +++ b/world.h @@ -0,0 +1,24 @@ +#pragma once + +#include "config.h" +#include "object.h" + +#include +#include +#include + +class World { + size_t m_height, m_width; + std::vector> m_c; + std::list m_objects; + + public: + World(); + void init(); + Object &createObject(Object &&); + void draw(Object &o); + void update(); + void print(std::ostream &out); + void destroy(); + ~World(); +};