Browse Source
Controller ready, Input methods ready, Board Ready, Snake collision events to be made and Snack class to be implemented
pull/1/head
Controller ready, Input methods ready, Board Ready, Snake collision events to be made and Snack class to be implemented
pull/1/head
VissaMoutafis
5 years ago
commit
bf2edd9fc2
18 changed files with 531 additions and 0 deletions
-
1.vscode/.easycpp
-
26.vscode/launch.json
-
6.vscode/settings.json
-
26.vscode/tasks.json
-
23Makefile
-
BINbin/main
-
20include/Controller.h
-
0include/Game.h
-
20include/Graphics.h
-
0include/Player.h
-
26include/Point.h
-
31include/Snake.h
-
50src/Controller.cpp
-
72src/Graphics.cpp
-
62src/PointClassImpl.cpp
-
148src/SnakeImpl.cpp
-
BINsrc/a.out
-
20src/main.cpp
@ -0,0 +1 @@ |
|||||
|
This file is created by Easy C++ Projects, please ignore and do not delete it |
@ -0,0 +1,26 @@ |
|||||
|
{ |
||||
|
"version": "0.2.0", |
||||
|
"configurations": [ |
||||
|
{ |
||||
|
"name": "C++ Debug (gdb)", |
||||
|
"type": "cppdbg", |
||||
|
"request": "launch", |
||||
|
"program": "${workspaceFolder}/bin/main", |
||||
|
"preLaunchTask": "Build C++ project", |
||||
|
"args": [], |
||||
|
"stopAtEntry": false, |
||||
|
"cwd": "${workspaceFolder}", |
||||
|
"environment": [], |
||||
|
"externalConsole": true, |
||||
|
"MIMode": "gdb", |
||||
|
"miDebuggerPath": "/usr/bin/gdb", |
||||
|
"setupCommands": [ |
||||
|
{ |
||||
|
"description": "Enable pretty-printing for gdb", |
||||
|
"text": "-enable-pretty-printing", |
||||
|
"ignoreFailures": true |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
] |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"files.associations": { |
||||
|
"*.tpp": "cpp" |
||||
|
}, |
||||
|
"terminal.integrated.shell.windows": "cmd.exe" |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
{ |
||||
|
"version": "2.0.0", |
||||
|
"tasks": [ |
||||
|
{ |
||||
|
"label": "Build C++ project", |
||||
|
"type": "shell", |
||||
|
"group": { |
||||
|
"kind": "build", |
||||
|
"isDefault": true |
||||
|
}, |
||||
|
"command": "make", |
||||
|
}, |
||||
|
{ |
||||
|
"label": "Build & run C++ project", |
||||
|
"type": "shell", |
||||
|
"group": { |
||||
|
"kind": "test", |
||||
|
"isDefault": true |
||||
|
}, |
||||
|
"command": "make", |
||||
|
"args": [ |
||||
|
"run" |
||||
|
] |
||||
|
} |
||||
|
] |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
CXX := g++ |
||||
|
CXX_FLAGS := -Wall -Wextra -std=c++11 -ggdb |
||||
|
|
||||
|
BIN := bin |
||||
|
SRC := src |
||||
|
INCLUDE := include |
||||
|
LIB := lib |
||||
|
|
||||
|
LIBRARIES := -lncurses |
||||
|
EXECUTABLE := main |
||||
|
|
||||
|
|
||||
|
all: $(BIN)/$(EXECUTABLE) |
||||
|
|
||||
|
run: clean all |
||||
|
clear |
||||
|
./$(BIN)/$(EXECUTABLE) |
||||
|
|
||||
|
$(BIN)/$(EXECUTABLE): $(SRC)/*.cpp |
||||
|
$(CXX) $(CXX_FLAGS) -I$(INCLUDE) -L$(LIB) $^ -o $@ $(LIBRARIES) |
||||
|
|
||||
|
clean: |
||||
|
-rm $(BIN)/* |
@ -0,0 +1,20 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "Graphics.h" |
||||
|
#include "Snake.h" |
||||
|
|
||||
|
class Controller{ |
||||
|
private: |
||||
|
Snake *snake; //the figure the controler controls |
||||
|
graphics_input inpt; |
||||
|
public: |
||||
|
Controller(Snake* _snake); |
||||
|
Controller(); |
||||
|
~Controller(); //default destructor |
||||
|
|
||||
|
graphics_input readInput(void); //basic input methods: sets inpt to what it read if i tread something |
||||
|
|
||||
|
void act(void); //basic act method: acts like a joystick |
||||
|
|
||||
|
bool wantsToQuit(void); //returns true of the user wants to quit |
||||
|
}; |
@ -0,0 +1,20 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <curses.h> //include library for terminal graphics |
||||
|
|
||||
|
#define UP KEY_UP |
||||
|
#define DOWN KEY_DOWN |
||||
|
#define LEFT KEY_LEFT |
||||
|
#define RIGHT KEY_RIGHT |
||||
|
#define EXIT_GAME 'q' |
||||
|
typedef int graphics_input; //the type of the graphics input |
||||
|
|
||||
|
|
||||
|
|
||||
|
void initializeGraphics(void); |
||||
|
void endGraphics(void); |
||||
|
void refreshScreen(void); |
||||
|
void printChar(int y, int x, graphics_input img); |
||||
|
void printMsg(int y, int x, char *str); |
||||
|
char readChar(int y, int x); |
||||
|
int readInpt(); |
@ -0,0 +1,26 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "Graphics.h" |
||||
|
|
||||
|
class Point{ |
||||
|
private: |
||||
|
int x; |
||||
|
int y; |
||||
|
graphics_input img; |
||||
|
public: |
||||
|
Point(); |
||||
|
Point(int y = 10, int x = 10, graphics_input img = '*'); |
||||
|
~Point(); |
||||
|
void setPoint(int y, int x); |
||||
|
int getX(); |
||||
|
int getY(); |
||||
|
void moveUp(); |
||||
|
void moveDown(); |
||||
|
void moveLeft(); |
||||
|
void moveRight(); |
||||
|
graphics_input getImg(); |
||||
|
void setImg(graphics_input image); |
||||
|
void printImg(); |
||||
|
void erase(); |
||||
|
void randomize(); |
||||
|
}; |
@ -0,0 +1,31 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <list> |
||||
|
|
||||
|
#include "Point.h" //the library we need to implement the snake |
||||
|
#define SNACK '*' |
||||
|
#define BODY 'o' |
||||
|
class Snake{ |
||||
|
private: |
||||
|
std::list<Point> snake; //the snake will be implemented as a list of points where the first element is the head |
||||
|
graphics_input direction; |
||||
|
void updateHead(void); |
||||
|
void printSnake(void); |
||||
|
public: |
||||
|
Snake(int headY = LINES/2, int headX = COLS/2); //default constructor |
||||
|
~Snake(); //destructor |
||||
|
|
||||
|
//basic move functions |
||||
|
void moveUp(void); |
||||
|
void moveDown(void); |
||||
|
void moveLeft(void); |
||||
|
void moveRight(void); |
||||
|
|
||||
|
bool isBitten(void); //function to check if the snake bit its self |
||||
|
bool hasBitSnack(int snackY, int snackX);//checks if the snake has bitten a snack |
||||
|
|
||||
|
int getSize(void); //get the current length |
||||
|
void incSize(void); //function to increase the length |
||||
|
|
||||
|
void move(void); //function to refresh the image of the snake |
||||
|
}; |
@ -0,0 +1,50 @@ |
|||||
|
#include "Controller.h"
|
||||
|
#include <assert.h>
|
||||
|
#include <iostream>
|
||||
|
using namespace std; |
||||
|
|
||||
|
Controller::Controller() |
||||
|
:inpt{0} |
||||
|
{ |
||||
|
snake = new Snake(); |
||||
|
} |
||||
|
|
||||
|
Controller::Controller(Snake *_snake) |
||||
|
: snake{_snake}, inpt{0} { |
||||
|
|
||||
|
assert(this->snake != NULL); |
||||
|
} |
||||
|
|
||||
|
Controller::~Controller(){} |
||||
|
|
||||
|
void Controller::act(void){ |
||||
|
switch (this->inpt) |
||||
|
{ |
||||
|
case UP: |
||||
|
snake->moveUp(); |
||||
|
break; |
||||
|
case DOWN: |
||||
|
snake->moveDown(); |
||||
|
break; |
||||
|
case LEFT: |
||||
|
snake->moveLeft(); |
||||
|
break; |
||||
|
case RIGHT: |
||||
|
snake->moveRight(); |
||||
|
break; |
||||
|
default: |
||||
|
snake->move(); |
||||
|
break; |
||||
|
} |
||||
|
refreshScreen(); |
||||
|
} |
||||
|
|
||||
|
graphics_input Controller::readInput(void){ |
||||
|
this->inpt = readInpt(); |
||||
|
refreshScreen(); |
||||
|
return inpt; |
||||
|
} |
||||
|
|
||||
|
bool Controller::wantsToQuit(void){ |
||||
|
return this->inpt == EXIT_GAME; |
||||
|
} |
@ -0,0 +1,72 @@ |
|||||
|
#include "Graphics.h"
|
||||
|
#include <chrono>
|
||||
|
#include <thread>
|
||||
|
///Utillities for the graphics
|
||||
|
unsigned int sleepTime = 50000000; |
||||
|
static WINDOW *_box = NULL; |
||||
|
|
||||
|
static void createBox(void){ |
||||
|
_box = newwin(LINES-2, COLS, 2, 0); |
||||
|
box(_box, 0, 0); |
||||
|
wrefresh(_box); |
||||
|
} |
||||
|
static void destroyBox(void){ |
||||
|
wborder(_box, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); |
||||
|
wrefresh(_box); |
||||
|
delwin(_box); |
||||
|
} |
||||
|
//Initialization function
|
||||
|
void initializeGraphics(void){ |
||||
|
initscr(); //initialize curses
|
||||
|
cbreak(); //set line buffering to false
|
||||
|
noecho(); //set input echo to false
|
||||
|
keypad(stdscr, TRUE); //this step enables the use of arrow keys and other function keys
|
||||
|
nodelay(stdscr, true); |
||||
|
//We must clear the screen from unecessary garbage
|
||||
|
clear(); |
||||
|
//Print the title
|
||||
|
mvprintw(0, (COLS/2) - 12, "~Snake Game by VissaM~"); |
||||
|
refresh(); |
||||
|
|
||||
|
//create the game box
|
||||
|
createBox(); |
||||
|
} |
||||
|
|
||||
|
//Exit function
|
||||
|
void endGraphics(void){ |
||||
|
destroyBox(); |
||||
|
endwin(); |
||||
|
} |
||||
|
|
||||
|
//Typical refresh function (ease the eye with a custom function instead of the actual one)
|
||||
|
void refreshScreen(void){ |
||||
|
using namespace std::this_thread; // sleep_for, sleep_until
|
||||
|
using namespace std::chrono; // nanoseconds, system_clock, seconds
|
||||
|
sleep_for(nanoseconds(sleepTime)); |
||||
|
|
||||
|
refresh(); // just use the curses version ;p
|
||||
|
wrefresh(_box); |
||||
|
} |
||||
|
|
||||
|
void printChar(int y, int x, graphics_input img){ |
||||
|
mvwaddch(_box, y, x, img); |
||||
|
refresh(); |
||||
|
wrefresh(_box); |
||||
|
} |
||||
|
|
||||
|
void printMsg(int y, int x, char* str){ |
||||
|
mvwaddstr(_box, y, x, str); |
||||
|
refresh(); |
||||
|
wrefresh(_box); |
||||
|
} |
||||
|
|
||||
|
char readChar(int y, int x){ |
||||
|
mvwgetch(_box, y, x); |
||||
|
refresh(); |
||||
|
wrefresh(_box); |
||||
|
} |
||||
|
|
||||
|
int readInpt(){ |
||||
|
return getch(); |
||||
|
} |
||||
|
|
@ -0,0 +1,62 @@ |
|||||
|
#include <iostream>
|
||||
|
#include <string>
|
||||
|
#include "Point.h"
|
||||
|
|
||||
|
/*snake will be an array of points*/ |
||||
|
|
||||
|
using namespace std; |
||||
|
Point::Point(int y, int x, graphics_input img) |
||||
|
: x {x}, y{y}, img{img} |
||||
|
{} |
||||
|
//delegating the previous constructor
|
||||
|
Point::Point() |
||||
|
:Point(10, 10, '*') |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Point::~Point(){ |
||||
|
/*No need to do something */ |
||||
|
} |
||||
|
|
||||
|
void Point::setPoint(int y, int x){ |
||||
|
this->x = x; |
||||
|
this->y = y; |
||||
|
} |
||||
|
|
||||
|
int Point::getX(void){ |
||||
|
return this->x; |
||||
|
} |
||||
|
|
||||
|
int Point::getY(void){ |
||||
|
return this->y; |
||||
|
} |
||||
|
|
||||
|
void Point::moveUp(void){ |
||||
|
y--; |
||||
|
} |
||||
|
|
||||
|
void Point::moveDown(void){ |
||||
|
y++; |
||||
|
} |
||||
|
|
||||
|
void Point::moveLeft(void){ |
||||
|
x--; |
||||
|
} |
||||
|
|
||||
|
void Point::moveRight(void){ |
||||
|
x++; |
||||
|
} |
||||
|
|
||||
|
graphics_input Point::getImg(){ |
||||
|
return this->img; |
||||
|
} |
||||
|
void Point::setImg(graphics_input image){ |
||||
|
this->img = image; |
||||
|
} |
||||
|
void Point::printImg(){ |
||||
|
printChar(this->y, this->x, this->img); |
||||
|
} |
||||
|
void Point::erase(void){ |
||||
|
this->img = ' '; |
||||
|
} |
@ -0,0 +1,148 @@ |
|||||
|
#include "Snake.h"
|
||||
|
#include <iostream>
|
||||
|
using namespace std; |
||||
|
|
||||
|
Snake::Snake(int headY, int headX) |
||||
|
:direction{LEFT} |
||||
|
{ |
||||
|
snake.push_back(Point{headY, headX, '>'}); //add the head of the snake
|
||||
|
for(int i=1; i<=3; i++) |
||||
|
snake.push_back(Point{headY, headX+i, BODY}); |
||||
|
this->printSnake(); |
||||
|
} |
||||
|
|
||||
|
Snake::~Snake(){} |
||||
|
|
||||
|
bool Snake::isBitten(void){ |
||||
|
Point head = *snake.begin(); |
||||
|
|
||||
|
list<Point>::iterator body_part = snake.begin(); |
||||
|
body_part++; |
||||
|
while(body_part != snake.end()){ |
||||
|
if(body_part->getX() == head.getX() && body_part->getY() == head.getY()) |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
bool Snake::hasBitSnack(int snackY, int snackX){ |
||||
|
return readChar(snackY, snackX) == SNACK; |
||||
|
} |
||||
|
|
||||
|
int Snake::getSize(void){ |
||||
|
return snake.size(); |
||||
|
} |
||||
|
|
||||
|
void Snake::incSize(void){ |
||||
|
auto tail = snake.end(); |
||||
|
//since list::end() returns one element past the actual last one we will decrease by one the tail iterator
|
||||
|
tail--; //now we actually pointing to the tail
|
||||
|
int tailX = tail->getX(); |
||||
|
int tailY = tail->getY(); |
||||
|
|
||||
|
//now we must determine the direction which is easy by just fiding the coordinates of the previous to tail element
|
||||
|
auto prev = --tail; |
||||
|
int prevX = prev->getX(); |
||||
|
int prevY = prev->getY(); |
||||
|
|
||||
|
if(prevY == tailY){ |
||||
|
//if the 2 part are on the same 'height'
|
||||
|
if (prevX < tailX) //if the tail continues to the left:
|
||||
|
snake.push_back(Point{tailY, tailX + 1, BODY}); // add one part to the right of the tail
|
||||
|
else if(prevX > tailX) //if the tail continues to the right:
|
||||
|
snake.push_back(Point{tailY, tailX - 1, BODY}); // add one part to the left of the tail
|
||||
|
}else{ |
||||
|
if (prevY < tailY) //if the tail continues to the upper side:
|
||||
|
snake.push_back(Point{tailY + 1, tailX, BODY}); // add one part facing down
|
||||
|
else if (prevY > tailY) //if the tail continues to the lower side:
|
||||
|
snake.push_back(Point{tailY - 1, tailX, BODY}); // add one part facing up
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Snake::updateHead(void){ |
||||
|
auto head = snake.begin(); |
||||
|
switch (this->direction) |
||||
|
{ |
||||
|
case UP: |
||||
|
head->moveUp(); |
||||
|
break; |
||||
|
|
||||
|
case DOWN: |
||||
|
head->moveDown(); |
||||
|
break; |
||||
|
|
||||
|
case LEFT: |
||||
|
head->moveLeft(); |
||||
|
break; |
||||
|
|
||||
|
case RIGHT: |
||||
|
head->moveRight(); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Snake::printSnake(void){ |
||||
|
//We print each element of the snake-list
|
||||
|
for(auto bodyPart : snake){ |
||||
|
bodyPart.printImg(); |
||||
|
} |
||||
|
|
||||
|
refreshScreen(); //finally call the previously implemented function at Graphics.cpp
|
||||
|
//to update the screen so the changes become noticed
|
||||
|
} |
||||
|
|
||||
|
void Snake::move(void){ |
||||
|
//now delete the tail print since teh snake moves forward
|
||||
|
auto tail = snake.end(); |
||||
|
tail--; |
||||
|
printChar(tail->getY(), tail->getX(), ' '); |
||||
|
|
||||
|
//and now we have to update all the other nodes of the body
|
||||
|
|
||||
|
auto bodyP1 = tail; |
||||
|
auto bodyP2 = --tail; |
||||
|
|
||||
|
while(bodyP2 != snake.begin()){ |
||||
|
*bodyP1 = *bodyP2; |
||||
|
bodyP1--; |
||||
|
bodyP2--; |
||||
|
} |
||||
|
|
||||
|
//update the previous to head node
|
||||
|
auto headPrev = snake.begin(); |
||||
|
headPrev++; |
||||
|
*headPrev = *snake.begin(); |
||||
|
headPrev->setImg(BODY); |
||||
|
|
||||
|
//based on direction, update the head
|
||||
|
this->updateHead(); |
||||
|
|
||||
|
this->printSnake(); // print the snake and update the screen
|
||||
|
} |
||||
|
|
||||
|
//Move Functions:
|
||||
|
//For the move functions we must change
|
||||
|
void Snake::moveUp(void){ |
||||
|
snake.begin()->setImg('v'); |
||||
|
this->direction = UP; |
||||
|
this->move(); |
||||
|
} |
||||
|
|
||||
|
void Snake::moveDown(void){ |
||||
|
snake.begin()->setImg('^'); |
||||
|
this->direction = DOWN; |
||||
|
this->move(); |
||||
|
} |
||||
|
|
||||
|
void Snake::moveLeft(void){ |
||||
|
snake.begin()->setImg('>'); |
||||
|
this->direction = LEFT; |
||||
|
this->move(); |
||||
|
} |
||||
|
|
||||
|
void Snake::moveRight(void){ |
||||
|
snake.begin()->setImg('<'); |
||||
|
this->direction = RIGHT; |
||||
|
this->move(); |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
|
||||
|
#include <ncurses.h>
|
||||
|
#include <iostream>
|
||||
|
#include "Controller.h"
|
||||
|
using namespace std; |
||||
|
|
||||
|
int main() { |
||||
|
initializeGraphics(); |
||||
|
Controller c; |
||||
|
/* CODE TO BE WRITTEN... */ |
||||
|
graphics_input in; |
||||
|
while(c.wantsToQuit() == false){ |
||||
|
c.readInput(); |
||||
|
c.act(); |
||||
|
|
||||
|
} |
||||
|
endGraphics(); |
||||
|
return 0; |
||||
|
|
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue