From cb7cb424470500c11065ed51fb91e5c1f0c044f8 Mon Sep 17 00:00:00 2001 From: Alexey Karpov Date: Sun, 25 Apr 2021 23:00:33 +0400 Subject: [PATCH] initial commit --- Makefile | 2 + NMPython.pro | 11 ++ NMPython.pro.user | 326 ++++++++++++++++++++++++++++++++++++++++++++++ main.cpp | 316 ++++++++++++++++++++++++++++++++++++++++++++ nmpython | Bin 0 -> 19592 bytes 5 files changed, 655 insertions(+) create mode 100644 Makefile create mode 100644 NMPython.pro create mode 100644 NMPython.pro.user create mode 100644 main.cpp create mode 100755 nmpython diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..810dec2 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +all: + g++ -Wall -o "nmpython" "main.cpp" -lncurses -ltinfo diff --git a/NMPython.pro b/NMPython.pro new file mode 100644 index 0000000..531d45e --- /dev/null +++ b/NMPython.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += \ + main.cpp + +unix|win32: LIBS += -lncurses + +HEADERS += diff --git a/NMPython.pro.user b/NMPython.pro.user new file mode 100644 index 0000000..7c68d29 --- /dev/null +++ b/NMPython.pro.user @@ -0,0 +1,326 @@ + + + + + + EnvironmentId + {8524ac12-a20b-4167-bd46-a88712fc9362} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + true + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {5ba39876-9586-4f52-9b01-31c0a670ad7a} + 0 + 0 + 0 + + /home/nowhereman/projects/CPP/build-NMPython-Desktop-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Сборка + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + true + Сборка + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Отладка + Отладка + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/nowhereman/projects/CPP/build-NMPython-Desktop-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + true + + + true + Сборка + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + true + Сборка + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Выпуск + Выпуск + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/nowhereman/projects/CPP/build-NMPython-Desktop-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + true + + + true + Сборка + + Qt4ProjectManager.MakeStep + + false + + + false + + 2 + Сборка + + ProjectExplorer.BuildSteps.Build + + + + true + Сборка + + Qt4ProjectManager.MakeStep + + true + clean + + false + + 1 + Очистка + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Профилирование + Профилирование + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Установка + + ProjectExplorer.BuildSteps.Deploy + + 1 + Конфигурация установки + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + NMPython + + Qt4ProjectManager.Qt4RunConfiguration:/home/nowhereman/projects/CPP/NMPython/NMPython.pro + NMPython.pro + + 3768 + false + true + true + false + false + true + + /home/nowhereman/projects/CPP/build-NMPython-Desktop-Debug + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 20 + + + Version + 20 + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..0063b1b --- /dev/null +++ b/main.cpp @@ -0,0 +1,316 @@ +#include +#include + +// Пока оно true - будем крутиться в игре, +// если станет false - выходим. +static bool run = false; + +// Если true - значит проиграли и надо нарисовать плашку Game Over +static bool gameOver; + +// Если true - у нас пауза, ничего не происходит, ждем нажатия кнопок +static bool pause; + +//Ширина и высота терминального окна +static int termWidth; +static int termHeight; + +// Координаты головы +static int playerX; +static int playerY; + +// Координаты еды +static int fruitX; +static int fruitY; + +// Смещения по осям - куда бежать +// 1 или -1 - бежим вдоль оси. 0 - не бежим +static int dx; +static int dy; + +// Очки +static int score; + +// Начало и конец питона в массиве +static int pythonStart; +static int pythonEnd; + +// Максимальный размер массива, чтобы можно было теоретически покрыть весь экран +static int maxPythonSize; + +// Предварительное описание, реализация позже будет. +void DropFruit(); + +// Структурка для хранения координат в массиве. +struct coord +{ + int x; + int y; +}; + +// Массив для координат тела - определение +static coord * python; + +// Тут мы инициализируем все что надо +void InitGame() +{ + // Инициализируем ncurses и выставляем ей разное + initscr(); + raw(); + cbreak(); + noecho(); + keypad(stdscr, true); + + // Таймаут ввода, он же скорость игры + timeout(200); + + // Получаем размер терминального окна + getmaxyx(stdscr, termHeight, termWidth); + + // Убираем курсор + curs_set(0); + + //Рисуем рамку + box(stdscr, 0, 0); + + //Инициализируем разные переменные + run = true; + gameOver = false; + pause = false; + + // Голову в центр экрана + playerX = termWidth / 2; + playerY = termHeight / 2; + + // Едем вправо + dx = 1; + dy = 0; + + // Очков пока ноль + score = 0; + + // Высчитываем максимальный размер питона, исходя из размера экрана + // (ну вдруг кто-то умудрится) + maxPythonSize = (termWidth - 2) * (termHeight - 2); + + // Инициализируем массив под координаты частей тела + python = new coord[maxPythonSize](); + + // Задаем начальные координаты + python[0].x = playerX; + python[0].y = playerY; + + // и указатели на хвост и голову + pythonStart = 0; + pythonEnd = 0; + + // Бросаем первую еду + DropFruit(); +} + + +// Тут завершается ncurses +void EndGame() +{ + endwin(); +} + +// Процедура, ловящая ввод и обрабатывающая его +void Input() +{ + // Получаем нажатую клавишу + int c = getch(); + + // в зависимости от нажатой клавиши правим смещения + switch (c) { + + // Если нажали q - ставим run в false, потому как надо выходить + case 'q': + run = false; + break; + case ' ': + pause = !pause; + break; + case KEY_UP: + // На каждый чих надо проверить, не пытается ли игрок поехать в противоположную сторону. + // Если так - нафиг. Ничего не делаем. + if (dy == 1) + break; + dx = 0; + dy = -1; + break; + case KEY_DOWN: + if (dy == -1) + break; + dx = 0; + dy = 1; + break; + case KEY_LEFT: + if (dx == 1) + break; + dx = -1; + dy = 0; + break; + case KEY_RIGHT: + if (dx == -1) + break; + dx = 1; + dy = 0; + } +} + +// Микроскопическая процедурка, печатающая очки в углу +void PrintScore() +{ + mvprintw(0, termWidth - 20, "Score: %5d", score); +} + + +// Тут мы двигаем голову и проверяем все что можно +void Logic() +{ + // Двигаем по X, просто прибавляя к координатам смещение + playerX += dx; + + // Проверяем на выход за рамку + if (playerX > termWidth - 2 || playerX < 1) + { + // Если вылезли - ставим флаг GameOver и run в false, чтобы выйти + gameOver = true; + run = false; + return; + } + + playerY += dy; + if (playerY > termHeight - 2 || playerY < 1) + { + gameOver = true; + run = false; + return; + } + + // Тут мы проходим по куску массива с телом между началом и концом + // чтобы выяснить, не куснули ли сами себя. + int i = pythonStart; + while (i <= pythonEnd) + { + // Если координаты головы совпадают с координатами из массива - Game over + if (playerX == python[i].x && playerY == python[i].y) + { + gameOver = true; + run = false; + return; + } + i++; + } + + // Проверяем, не куснули ли мы еду + if (playerX == fruitX && playerY == fruitY) + { + // Если куснули - выкидываем новую + DropFruit(); + + // Добавляем очков + score++; + + // Сдвигаем хвост + pythonEnd++; + + // Если хвост дошел до конца массива - переставляем его на начало + if (pythonEnd == maxPythonSize) + pythonEnd = 0; + + // Выводим новые очки в угол + PrintScore(); + } + + // Двигаем питона + + // Стираем хвост + mvprintw(python[pythonEnd].y, python[pythonEnd].x, " "); + + // Двигаем указатель головы назад по массиву + pythonStart--; + + // Не забывая его переставить, если он дошел до нуля + if (pythonStart < 0) + pythonStart = maxPythonSize - 1; + + // Тоже и с указателем хвоста + pythonEnd--; + if (pythonEnd < 0) + pythonEnd = maxPythonSize - 1; + + // Записываем новое положение головы по указателю + python[pythonStart].x = playerX; + python[pythonStart].y = playerY; + + // Рисуем по новым координатам голову + mvprintw(playerY, playerX, "@"); +} + +// Жуткая процедура рисования окошка с Game Over +void DrawGameOver() +{ + int winWidth = termWidth / 2 + 10; + int winHeight = 7; + int winX = (termWidth - winWidth) / 2; + int winY = (termHeight - winHeight) / 2; + WINDOW * gameOverWin = newwin(winHeight, winWidth, winY, winX); + box(gameOverWin, 0, 0); + std::string str1 = "GAME OVER!"; + std::string str2 = "Score: " + std::to_string(score); + mvwprintw(gameOverWin, 2, (winWidth - (int)str1.length()) / 2, str1.c_str()); + mvwprintw(gameOverWin, 4, (winWidth - (int)str2.length()) / 2, str2.c_str()); + wrefresh(gameOverWin); + notimeout(gameOverWin, TRUE); + wgetch(gameOverWin); +} + +// Здесь мы крутимся, пока игра идет +void GameLoop() +{ + while (run) + { + // Обрабатываем ввод + Input(); + + if (!pause) + { + // Обрабатываем логику + Logic(); + } + } + + // Сюда мы выйдем, если игра так или иначе кончится + // Если Game over - рисуем плашку с очками + if (gameOver) + DrawGameOver(); +} + +// Выбрасываем новую еду +void DropFruit() +{ + // Новые координаты в переменные + fruitX = (rand() % (termWidth - 2)) + 1; + fruitY = (rand() % (termHeight - 2)) + 1; + + + + // и нарисовать + mvprintw(fruitY, fruitX, "#"); +} + +// Главная функция - просто вызывает все предыдущие последовательно +int main(int argc, const char * argv[]) { + InitGame(); + + getch(); + + PrintScore(); + + GameLoop(); + + EndGame(); + return 0; +} diff --git a/nmpython b/nmpython new file mode 100755 index 0000000000000000000000000000000000000000..126e707ee22770df0396373c8df8bcaf27e825c3 GIT binary patch literal 19592 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 literal 0 HcmV?d00001