-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5a0d322
Showing
13 changed files
with
1,105 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
build/ | ||
.cproject | ||
.project | ||
.vscode/ |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#include "BorderFrame.h" | ||
|
||
BorderFrame::BorderFrame(int x, int y, int width, int height) { | ||
this->x = x; | ||
this->y = y; | ||
this->width = width; | ||
this->height = height; | ||
} | ||
|
||
void BorderFrame::update() { | ||
|
||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#ifndef BORDER_FRAME_H_ | ||
#define BORDER_FRAME_H_ | ||
|
||
class BorderFrame { | ||
public: | ||
int width; | ||
int height; | ||
int x; | ||
int y; | ||
BorderFrame(int x, int y, int width, int height); | ||
virtual ~BorderFrame() {} | ||
void update(); | ||
}; | ||
|
||
#endif |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
cmake_minimum_required (VERSION 2.6) | ||
|
||
project (snake-game) | ||
|
||
set(CMAKE_CXX_STANDARD 17) | ||
set(CMAKE_CXX_EXTENSIONS OFF) | ||
add_compile_options(-Wall -Wextra -pedantic) | ||
|
||
find_package(Curses) | ||
|
||
file(GLOB SRC_FILES "*.cpp") | ||
|
||
add_executable(snake-game ${SRC_FILES}) | ||
target_link_libraries(snake-game ${CURSES_LIBRARIES}) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#include "FoodBuilder.h" | ||
|
||
FoodBuilder::FoodBuilder(BorderFrame* border) { | ||
this->border = border; | ||
} | ||
|
||
Food* FoodBuilder::getFood() { | ||
std::srand(std::time(nullptr)); // use current time as seed for random generator | ||
int x = border->x + std::rand() % border->width; | ||
int y = border->y + std::rand() % border->height; | ||
if (x == border->x) x++; | ||
if (y == border->y) y++; | ||
|
||
if (this->food == nullptr) { | ||
this->food = new Food(x, y); | ||
} else { | ||
this->food->x = x; | ||
this->food->y = y; | ||
} | ||
|
||
return this->food; | ||
} | ||
|
||
FoodBuilder::~FoodBuilder() { | ||
if (this->food != nullptr) { | ||
delete this->food; | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#ifndef FOOD_BUILDER_H_ | ||
#define FOOD_BUILDER_H_ | ||
|
||
#include <bits/stdc++.h> | ||
#include "BorderFrame.h" | ||
|
||
struct Food { | ||
int x; | ||
int y; | ||
Food(int x, int y) : x(x), y(y) {} | ||
}; | ||
|
||
class FoodBuilder{ | ||
private: | ||
Food* food = nullptr; | ||
BorderFrame* border; | ||
|
||
public: | ||
FoodBuilder(BorderFrame* border); | ||
virtual ~FoodBuilder(); | ||
Food* getFood(); | ||
}; | ||
|
||
#endif |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
#include "Game.h" | ||
#include <ncurses.h> | ||
#include <unistd.h> | ||
|
||
Game::Game() : foodBuilder(&borderFrame), borderFrame(0, 0, 64, 32) { | ||
|
||
} | ||
|
||
Game::~Game() { | ||
|
||
} | ||
|
||
void Game::run() { | ||
this->init(); | ||
this->food = foodBuilder.getFood(); | ||
this->isPlaying = true; | ||
|
||
while(this->isPlaying) { | ||
// begin frame | ||
std::clock_t c_start = std::clock(); | ||
|
||
this->processInput(); | ||
this->update(); | ||
this->render(); | ||
|
||
// end frame | ||
std::clock_t c_end = std::clock(); | ||
std::clock_t diff = this->frame - c_end + c_start; | ||
|
||
// delay | ||
usleep(diff); | ||
} | ||
|
||
erase(); | ||
refresh(); | ||
endwin(); | ||
} | ||
|
||
void Game::init() { | ||
// init | ||
initscr(); | ||
// TODO check for failing | ||
|
||
cbreak(); // Character input doesnt require the <enter> key anymore | ||
curs_set(0); // Makes the blinking cursor invisible | ||
noecho(); // Wont print the keys received through input | ||
nodelay(stdscr, TRUE); // Wont wait for input | ||
keypad(stdscr, TRUE); // Support for extra keys (life F1, F2, ... ) | ||
//timeout(400); | ||
//timeout(0); | ||
|
||
// Ncurses' global variable meaning number of milliseconds | ||
// to wait after the user presses ESC. | ||
// | ||
// VIM uses 25ms, so should you. | ||
// Source: http://en.chys.info/2009/09/esdelay-ncurses/ | ||
ESCDELAY = 25; | ||
|
||
refresh(); // Refresh the layout | ||
|
||
|
||
//int max_y = 0, max_x = 0; | ||
|
||
// Global var `stdscr` is created by the call to `initscr()` | ||
//getmaxyx(stdscr, max_y, max_x); | ||
} | ||
|
||
void Game::processInput() { | ||
int c = getch(); | ||
|
||
switch (c) { | ||
case KEY_LEFT: | ||
snake.changeDirection(Direction::LEFT); | ||
break; | ||
|
||
case KEY_DOWN: | ||
snake.changeDirection(Direction::DOWN); | ||
break; | ||
|
||
case KEY_UP: | ||
snake.changeDirection(Direction::UP); | ||
break; | ||
|
||
case KEY_RIGHT: | ||
snake.changeDirection(Direction::RIGHT); | ||
break; | ||
|
||
case '1': | ||
snake.grow(); | ||
break; | ||
|
||
case 27: // KEY_ESC | ||
// exit from loop | ||
this->isPlaying = false; | ||
break; | ||
} | ||
} | ||
|
||
void Game::update() { | ||
snake.update(); | ||
|
||
// collisions? | ||
std::pair<int,int> head = snake.getHead(); | ||
|
||
// itself collision | ||
std::list<std::pair<int, int>> *coords = snake.getCoordinates(); | ||
std::list<std::pair<int, int>>::iterator it = coords->begin(); | ||
for(it++; it != coords->end(); it++) { | ||
if (it->first == head.first && it->second == head.second) { | ||
// we have a collision | ||
this->isPlaying = false; | ||
// game over | ||
return; | ||
} | ||
} | ||
|
||
// border collision | ||
if ((head.first == borderFrame.x && head.second >= borderFrame.y && | ||
head.second <= borderFrame.height) || | ||
(head.first == borderFrame.width && head.second >= borderFrame.y && | ||
head.second <= borderFrame.height) || | ||
(head.second == borderFrame.y && head.first >= borderFrame.x && | ||
head.first <= borderFrame.width) || | ||
(head.second == borderFrame.height && head.first >= borderFrame.x && | ||
head.first <= borderFrame.width) | ||
) { | ||
// you don't have to go out of the border space | ||
this->isPlaying = false; | ||
// game over | ||
return; | ||
} | ||
|
||
// has eaten food? | ||
if (head.first == food->x && head.second == food->y) { | ||
snake.grow(); | ||
this->score += 10; | ||
food = foodBuilder.getFood(); | ||
} | ||
} | ||
|
||
void Game::render() { | ||
// clear screen | ||
clear(); | ||
|
||
// render snake | ||
std::list<std::pair<int, int>> *coords = snake.getCoordinates(); | ||
std::list<std::pair<int, int>>::iterator it = coords->begin(); | ||
// render head | ||
mvprintw(it->second, it->first, "@"); | ||
// render body | ||
for(it++; it != coords->end(); it++) { | ||
mvprintw(it->second, it->first, "o"); | ||
} | ||
|
||
// render boarders | ||
for(int x = borderFrame.x; x <= borderFrame.width; x++) { | ||
mvprintw(borderFrame.y, x, "x"); | ||
mvprintw(borderFrame.height, x, "x"); | ||
} | ||
for(int y = borderFrame.y; y <= borderFrame.height; y++) { | ||
mvprintw(y, borderFrame.x, "x"); | ||
mvprintw(y, borderFrame.width, "x"); | ||
} | ||
|
||
// render food | ||
mvprintw(this->food->y, this->food->x, "F"); | ||
} | ||
|
||
int Game::getScore() { | ||
return this->score; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#ifndef GAME_H_ | ||
#define GAME_H_ | ||
|
||
#include "Snake.h" | ||
#include "FoodBuilder.h" | ||
#include "BorderFrame.h" | ||
|
||
class Game { | ||
private: | ||
Snake snake; | ||
int score = 0; | ||
FoodBuilder foodBuilder; | ||
Food* food = nullptr; | ||
BorderFrame borderFrame; | ||
const std::clock_t frame = 300000l; | ||
bool isPlaying = false; | ||
|
||
void init(); | ||
void processInput(); | ||
void update(); | ||
void render(); | ||
|
||
public: | ||
Game(); | ||
virtual ~Game(); | ||
void run(); | ||
int getScore(); | ||
}; | ||
|
||
#endif |
Oops, something went wrong.