converting to c
This commit is contained in:
+180
@@ -0,0 +1,180 @@
|
||||
#include "engine.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
set(vec2* vec2, int _x, int _y)
|
||||
{
|
||||
vec2->x = _x;
|
||||
vec2->y = _y;
|
||||
}
|
||||
|
||||
int
|
||||
equals(vec2* a, vec2* b)
|
||||
{
|
||||
return (a->x == b->x && a->y == b->y);
|
||||
}
|
||||
|
||||
void
|
||||
engine_init(Engine* engine)
|
||||
{
|
||||
srand(time(0));
|
||||
set(&engine->head, COL / 2, ROW / 2);
|
||||
set(&engine->prev_head, engine->head.x, engine->head.y);
|
||||
set(&engine->fruit, rand() % COL, rand() % ROW);
|
||||
|
||||
engine->dir = RIGHT;
|
||||
engine->m_score = 0;
|
||||
engine->tail_size = 0;
|
||||
memset(engine->view, 0, sizeof(engine->view));
|
||||
|
||||
for (unsigned char i = 0; i < ROW; i++)
|
||||
{
|
||||
for (unsigned char j = 0; j < COL; j++)
|
||||
{
|
||||
engine->view[i][j] = '.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
engine_display(Engine* engine)
|
||||
{
|
||||
engine->view[engine->fruit.y][engine->fruit.x] = 'o';
|
||||
if (engine->tail_size != 0)
|
||||
{
|
||||
for (char i = 0; i < engine->tail_size; i++)
|
||||
{
|
||||
if (engine->tail[i]->x < COL &&
|
||||
engine->tail[i]->y < ROW)
|
||||
{
|
||||
engine->view[engine->tail[i]->y]
|
||||
[engine->tail[i]->x] = '~';
|
||||
}
|
||||
}
|
||||
}
|
||||
write(1, "\033[H\033[J", sizeof("\033[H\033[J") - 1);
|
||||
for (unsigned char i = 0; i < ROW; i++)
|
||||
{
|
||||
for (unsigned char j = 0; j < COL; j++)
|
||||
{
|
||||
write(1, &engine->view[i][j], 1);
|
||||
write(1, " ", 1);
|
||||
}
|
||||
write(1, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
process_input(Direction* dir)
|
||||
{
|
||||
unsigned char ch;
|
||||
if (read(1, &ch, 1) > 0)
|
||||
{
|
||||
if (ch == 'q') return false;
|
||||
if (ch == 'w')
|
||||
if (*dir != DOWN) *dir = UP;
|
||||
if (ch == 's')
|
||||
if (*dir != UP) *dir = DOWN;
|
||||
if (ch == 'd')
|
||||
if (*dir != LEFT) *dir = RIGHT;
|
||||
if (ch == 'a')
|
||||
if (*dir != RIGHT) *dir = LEFT;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
is_open(char* status, size_t len, Engine* engine)
|
||||
{
|
||||
if ((sizeof(engine->tail) / sizeof(engine->tail[0])) >= ROW * COL)
|
||||
{
|
||||
snprintf(status, len,
|
||||
"You filled the whole board and won! "
|
||||
"Score: %d",
|
||||
engine->m_score);
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < engine->tail_size; i++)
|
||||
{
|
||||
if (equals(engine->tail[i], &engine->head))
|
||||
{
|
||||
snprintf(status, len,
|
||||
"You collided with yourself and died! "
|
||||
"Score: %d",
|
||||
engine->m_score);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
determine_index_zero_pos(Engine* engine)
|
||||
{
|
||||
set(&engine->prev_head, engine->head.x, engine->head.y);
|
||||
|
||||
if (engine->dir == LEFT)
|
||||
engine->head.x = (engine->head.x + COL - 1) % COL;
|
||||
else if (engine->dir == RIGHT)
|
||||
engine->head.x = (engine->head.x + 1) % COL;
|
||||
else if (engine->dir == UP)
|
||||
engine->head.y = (engine->head.y + ROW - 1) % ROW;
|
||||
else if (engine->dir == DOWN)
|
||||
engine->head.y = (engine->head.y + 1) % ROW;
|
||||
engine->view[engine->prev_head.y][engine->prev_head.x] = '.';
|
||||
engine->view[engine->head.y][engine->head.x] = '*';
|
||||
}
|
||||
|
||||
void
|
||||
move_tail_indicies(vec2** tail, int tail_size, vec2* prev_head,
|
||||
unsigned char (*view)[COL])
|
||||
{
|
||||
if (tail_size == 0) return;
|
||||
|
||||
view[tail[tail_size - 1]->y][tail[tail_size - 1]->x] = '.';
|
||||
for (int i = tail_size - 1; i > 0; i--)
|
||||
{
|
||||
set(tail[i], tail[i - 1]->x, tail[i - 1]->y);
|
||||
}
|
||||
set(tail[0], prev_head->x, prev_head->y);
|
||||
}
|
||||
|
||||
void
|
||||
add_tail_and_respawn_fruit(Engine* engine)
|
||||
{
|
||||
if (!equals(&engine->fruit, &engine->head)) return;
|
||||
vec2 new_pos;
|
||||
set(&new_pos, 0, 0);
|
||||
int collision = 0;
|
||||
do
|
||||
{
|
||||
collision = 0;
|
||||
set(&new_pos, (rand() % COL), (rand() % ROW));
|
||||
if (equals(&new_pos, &engine->head))
|
||||
{
|
||||
collision = 1;
|
||||
break;
|
||||
}
|
||||
if (engine->tail_size > 0)
|
||||
{
|
||||
for (int i = 0; i < engine->tail_size; i++)
|
||||
{
|
||||
if (equals(&new_pos, engine->tail[i]))
|
||||
{
|
||||
collision = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (collision);
|
||||
engine->fruit = new_pos;
|
||||
engine->tail[engine->tail_size] = (vec2*)malloc(sizeof(vec2));
|
||||
engine->tail_size++;
|
||||
engine->m_score++;
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
#include <engine.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <format>
|
||||
#include <ranges>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
void Window::draw_display() {
|
||||
for(int i : std::ranges::views::iota(0, ROW)) {
|
||||
for(int j : std::ranges::views::iota(0, COL)) {
|
||||
mvaddch(i, j * 2, view[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::update_display(const vec2 fruit, std::deque<vec2> &buf) {
|
||||
view[fruit.y][fruit.x] = 'o';
|
||||
for(const auto& segment : buf) {
|
||||
if(segment.x < COL && segment.y < ROW) {
|
||||
view[segment.y][segment.x] = '~';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Engine::Engine() {
|
||||
std::srand(std::time(0));
|
||||
initscr();
|
||||
cbreak();
|
||||
noecho();
|
||||
curs_set(0);
|
||||
nodelay(stdscr, true);
|
||||
for(auto& row : win.view) row.fill('.');
|
||||
}
|
||||
|
||||
void Engine::run() {
|
||||
while (exit_summary() && process_input()) {
|
||||
add_tail_and_respawn_fruit();
|
||||
determine_index_zero_pos();
|
||||
move_tail_indicies();
|
||||
|
||||
win.update_display(fruit, tail);
|
||||
win.draw_display();
|
||||
refresh();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds((int) (200)));
|
||||
}
|
||||
nodelay(stdscr, false);
|
||||
mvprintw(ROW, 0, status.c_str());
|
||||
refresh();
|
||||
getch();
|
||||
}
|
||||
|
||||
bool Engine::process_input() {
|
||||
int ch;
|
||||
while((ch = getch()) != ERR) {
|
||||
if(ch == 'q') { return status = "Quitting", false; }
|
||||
else if(ch == 'w') { if(dir != Direction::DOWN) dir = Direction::UP; }
|
||||
else if(ch == 's') { if(dir != Direction::UP) dir = Direction::DOWN; }
|
||||
else if(ch == 'd') { if(dir != Direction::LEFT) dir = Direction::RIGHT; }
|
||||
else if(ch == 'a') { if(dir != Direction::RIGHT) dir = Direction::LEFT; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Engine::exit_summary() {
|
||||
if(tail.size() >= ROW * COL) {
|
||||
return status = std::format("You filled the whole board and won! Score: {}\n", m_score), false;
|
||||
}
|
||||
if(std::any_of(tail.begin(), tail.end(), [&](const vec2& segment) { return segment == head; })) {
|
||||
return status = std::format("You collided with yourself and died! Score: {}\n", m_score), false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Engine::determine_index_zero_pos() {
|
||||
prev_head.set(head.x, head.y);
|
||||
|
||||
if(dir == Direction::LEFT) { head.x = (head.x + COL - 1) % COL; }
|
||||
else if(dir == Direction::RIGHT) { head.x = (head.x + 1) % COL; }
|
||||
else if(dir == Direction::UP) { head.y = (head.y + ROW - 1) % ROW; }
|
||||
else if(dir == Direction::DOWN) { head.y = (head.y + 1) % ROW; }
|
||||
win.view[prev_head.y][prev_head.x] = '.';
|
||||
win.view[head.y][head.x] = '*';
|
||||
}
|
||||
|
||||
void Engine::move_tail_indicies() {
|
||||
if(tail.empty()) return;
|
||||
vec2 last_tail = tail.back();
|
||||
tail.pop_back();
|
||||
tail.push_front(prev_head);
|
||||
if(last_tail.x < COL && last_tail.y < ROW) { win.view[last_tail.y][last_tail.x] = '.'; }
|
||||
}
|
||||
|
||||
void Engine::add_tail_and_respawn_fruit() {
|
||||
if(fruit != head) return;
|
||||
vec2 new_pos { 0, 0 };
|
||||
do { new_pos.set((rand() % ROW), (rand() % COL)); }
|
||||
while (new_pos == head || std::any_of(tail.begin(), tail.end(), [&](const vec2& seg) { return seg == new_pos; }));
|
||||
fruit = new_pos;
|
||||
tail.push_front(vec2 { ROW, COL });
|
||||
m_score++;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
Engine engine;
|
||||
engine_init(&engine);
|
||||
char status[64] = { 0 };
|
||||
static struct termios oldt, newt;
|
||||
struct timespec req;
|
||||
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
req.tv_nsec = 1.5e8;
|
||||
req.tv_sec = 0;
|
||||
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
|
||||
|
||||
while (is_open(status, 64, &engine) && process_input(&engine.dir))
|
||||
{
|
||||
add_tail_and_respawn_fruit(&engine);
|
||||
determine_index_zero_pos(&engine);
|
||||
move_tail_indicies(engine.tail, engine.tail_size, &engine.prev_head, engine.view);
|
||||
|
||||
engine_display(&engine);
|
||||
nanosleep(&req, NULL);
|
||||
}
|
||||
for(int i = 0; i < engine.tail_size; i++) {
|
||||
free(engine.tail[i]);
|
||||
}
|
||||
write(1, status, sizeof(status));
|
||||
write(1, "\033[?25h", 6);
|
||||
tcsetattr(0, TCSANOW, &oldt);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include <engine.hpp>
|
||||
|
||||
int main () {
|
||||
Engine engine;
|
||||
engine.run();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user