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