From 9bd6c9e71b56821ae058078db4d0776f58bd9faa Mon Sep 17 00:00:00 2001 From: RinRi Date: Sun, 3 Apr 2022 13:57:25 +0600 Subject: [PATCH] initial commit --- .clang-format | 3 ++ .gitignore | 3 ++ Makefile | 17 +++++++ config.h | 8 +++ main.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ object.cpp | 29 +++++++++++ object.h | 38 +++++++++++++++ world.cpp | 45 +++++++++++++++++ world.h | 24 +++++++++ 9 files changed, 300 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 config.h create mode 100644 main.cpp create mode 100644 object.cpp create mode 100644 object.h create mode 100644 world.cpp create mode 100644 world.h 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(); +};