Created
March 8, 2019 23:49
-
-
Save funnbot/ae1f15b14d6e23b7ffde15975310a912 to your computer and use it in GitHub Desktop.
Mostly working cross platform snake game in console that requires sfml on mac.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if defined(WIN32) || defined(_WIN32) | |
#define iswin | |
#endif | |
#include <iostream> | |
#include <vector> | |
#include <ctime> | |
#include <string> | |
#include <stdlib.h> | |
#ifdef iswin | |
#include <Windows.h> | |
#else | |
#include <SFML/Window/Keyboard.hpp> | |
#include <ncurses.h> | |
#include <unistd.h> | |
#endif | |
using namespace std; | |
#ifdef iswin | |
const int IKEY_W = 0x57, IKEY_S = 0x53, IKEY_D = 0x44, IKEY_A = 0x41, IKEY_ESC = 0x1B; | |
#else | |
const int IKEY_W = 22, IKEY_S = 18, IKEY_D = 3, IKEY_A = 0, IKEY_ESC = 36; | |
#endif | |
const int WIDTH = 40, HEIGHT = 30; | |
struct Coord { | |
int x; | |
int y; | |
}; | |
void buildMap(vector<vector<char>>&); | |
void drawMap(const vector<vector<char>>&); | |
void randCoord(Coord&); | |
void input(Coord&); | |
bool isKeyDown(int); | |
void moveCursor(int, int); | |
void hideCursor(); | |
void slp(int); | |
void prnt(char); | |
int main() { | |
#ifndef iswin | |
initscr(); | |
#endif | |
srand(static_cast<int>(time(0))); | |
hideCursor(); | |
vector<vector<char>> map(WIDTH); | |
// Init map, build walls | |
buildMap(map); | |
// Game vars | |
vector<Coord> body(4); | |
body[0] = { 9, 10 }; | |
body[1] = { 8, 10 }; | |
body[2] = { 7, 10 }; | |
body[3] = { 6, 10 }; | |
Coord head = { 10, 10}; | |
Coord dir = { 1, 0 }; | |
Coord apple; | |
randCoord(apple); | |
map[apple.x][apple.y] = '@'; | |
bool lost = false; | |
// Game loop | |
while (!isKeyDown(IKEY_ESC) && !lost) { | |
// Get input again | |
input(dir); | |
// Erase old snake | |
map[head.x][head.y] = ' '; | |
cout << map[head.x][head.y]; | |
for (int i = 0; i < body.size(); i++) { | |
map[body[i].x][body[i].y] = ' '; | |
} | |
// Update snake | |
for (int i = body.size() - 1; i > 0; i--) { | |
body[i] = { body[i - 1].x, body[i - 1].y }; | |
} | |
body[0] = { head.x, head.y }; | |
head = { head.x + dir.x, head.y + dir.y }; | |
// Check apple | |
if (head.x == apple.x && head.y == apple.y) { | |
body.resize(body.size() + 1); | |
map[apple.x][apple.y] = ' '; | |
randCoord(apple); | |
map[apple.x][apple.y] = '@'; | |
} | |
// Lose conditions | |
if (head.x == 0 || head.x == WIDTH - 1 || head.y == 0 || head.y == HEIGHT - 1) break; | |
for (int i = 1; i < body.size(); i++) { | |
if (head.x == body[i].x && head.y == body[i].y) lost = true; | |
} | |
// Draw snake | |
map[head.x][head.y] = '0'; | |
for (int i = 0; i < body.size(); i++) { | |
map[body[i].x][body[i].y] = '*'; | |
} | |
// Draw to console | |
drawMap(map); | |
// Wait | |
int wait = 10; | |
while (--wait) { | |
input(dir); | |
slp(15); | |
} | |
} | |
#ifndef iswin | |
endwin(); | |
#endif | |
cout << "Score: " << body.size() - 4 << endl; | |
return 0; | |
} | |
void buildMap(vector<vector<char>> &map) { | |
for (int x = 0; x < WIDTH; x++) { | |
map[x] = vector<char>(HEIGHT); | |
for (int y = 0; y < HEIGHT; y++) { | |
if (x == 0 || x == WIDTH - 1) | |
map[x][y] = '|'; | |
else if (y == 0 || y == HEIGHT - 1) | |
map[x][y] = '-'; | |
else map[x][y] = ' '; | |
} | |
} | |
} | |
void drawMap(const vector<vector<char>> &map) { | |
moveCursor(0, 0); | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
char c = map[x][y]; | |
moveCursor(x, y); | |
prnt(c); | |
} | |
prnt('\n'); | |
} | |
#ifndef iswin | |
refresh(); | |
#endif | |
} | |
void input(Coord& dir) { | |
if (isKeyDown(IKEY_W)) dir = { 0, -1 }; | |
else if (isKeyDown(IKEY_S)) dir = { 0, 1 }; | |
else if (isKeyDown(IKEY_D)) dir = { 1, 0 }; | |
else if (isKeyDown(IKEY_A)) dir = { -1, 0 }; | |
} | |
void randCoord(Coord& c) { | |
c.x = 1 + rand() % (WIDTH - 2); | |
c.y = 1 + rand() % (HEIGHT - 2); | |
} | |
bool isKeyDown(int key) { | |
#ifdef iswin | |
return GetKeyState(key) & 0x8000; | |
#else | |
return sf::Keyboard::isKeyPressed(static_cast<sf::Keyboard::Key>(key)); | |
#endif | |
} | |
void moveCursor(int x, int y) { | |
#ifdef iswin | |
COORD c = {x, y}; | |
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c); | |
#else | |
move(y, x); | |
#endif | |
} | |
void hideCursor() { | |
#ifdef iswin | |
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); | |
CONSOLE_CURSOR_INFO info; | |
GetConsoleCursorInfo(handle, &info); | |
info.bVisible = false; | |
SetConsoleCursorInfo(handle, &info); | |
#else | |
curs_set(0); | |
#endif | |
} | |
void slp(int t) { | |
#ifdef iswin | |
Sleep(t); | |
#else | |
usleep(t * 1000); | |
#endif | |
} | |
void prnt(char c) { | |
#ifdef iswin | |
cout << c; | |
#else | |
printw("%c", c); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment