As a diversion from my regular learning, I was making a game of Snake using NCurses. However, my Snake class below is completely not working and I have ABSOLUTELY NO IDEA what is wrong. Could any of you give a hint as to what the errors are, since I am absolutely stuck. Irrelevant code is hidden here, since I have a lot
Here is the structure of my code:
There is a class SnakeGame, in which the user in main only calls
game.runLoop
. SnakeGame has its own appropriate members, such as the class Snake, which is not working. Additionally, SnakeGame has a WINDOW inside, which the game will be played in:
SnakeGame.hpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
#ifndef SNAKEGAME_HPP
#define SNAKEGAME_HPP
#include <ncurses.h>
#include "Snake.hpp"
class SnakeGame
{
WINDOW * gameWindow; //Represents what Snake will be played inside
bool isRunning;
Snake snake;
//Window limits initialized in constructor
//End window limits
//Basic Functions
void initGame();
void readInput();
void updateGame();
void gameOver();
//End basic functions
public:
SnakeGame();
void runLoop();
~SnakeGame();
};
#endif
|
SnakeGame.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
#include <ncurses.h>
#include <unistd.h>
#include <string>
#include "SnakeGame.hpp"
#include "Snake.hpp"
SnakeGame::SnakeGame()
{
initscr(); //Initalizes curses mode
cbreak(); //Disallows special functions to interrupt game
keypad(gameWindow, true); //Allows reading of arrow keys
noecho();
}
void SnakeGame::initGame()
{
//Shows title text
int gameStartKey = getch();
refresh();
gameWindow = newwin(30, 100, 0, 0);
box(gameWindow, 0, 0);
wrefresh(gameWindow);
}
void SnakeGame::readInput()
{
int nextKey = wgetch(gameWindow);
switch(nextKey)
{
case KEY_BACKSPACE:
isRunning = false;
break;
case KEY_LEFT:
snake.setDirection(Direction::LEFT);
break;
case KEY_RIGHT:
snake.setDirection(Direction::RIGHT);
break;
case KEY_UP:
snake.setDirection(Direction::UP);
break;
case KEY_DOWN:
snake.setDirection(Direction::DOWN);
break;
}
}
void SnakeGame::updateGame()
{
snake.moveForward();
snake.draw(gameWindow);
wrefresh(gameWindow);
}
void SnakeGame::gameOver()
{
wborder(gameWindow, ' ', ' ', ' ',' ',' ',' ',' ',' ');
wrefresh(gameWindow);
delwin(gameWindow);
//Does countdown at end in stdscr
}
void SnakeGame::runLoop()
{
isRunning = true;
initGame();
while (isRunning)
{
readInput();
updateGame();
//wrefresh(gameWindow);
}
gameOver();
}
SnakeGame::~SnakeGame()
{
endwin(); //Ends curses modes. Makes use of RAII to guarantee endwin() is called
}
|
Snake.hpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#ifndef SNAKE_HPP
#define SNAKE_HPP
#include <ncurses.h>
#include "Utilities.hpp"
#include <vector>
class Snake
{
std::vector<Coord> bodyLocations;
Coord previousTailLocation;
Direction currentDirection;
public:
Snake();
inline void setDirection(Direction dir) { currentDirection = dir; };
void moveForward();
void increaseSize();
void draw(WINDOW * win);
};
#endif
|
Below is the main code which is driving me crazy:
Snake.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
#include <ncurses.h>
#include "Snake.hpp"
#include "Utilities.hpp"
#include <vector>
Snake::Snake()
{
Coord tail{49, 15};
Coord head{50, 15};
bodyLocations.push_back(tail);
bodyLocations.push_back(head);
previousTailLocation = tail;
currentDirection = Direction::RIGHT;
}
void Snake::moveForward()
{
previousTailLocation = bodyLocations[0];
Coord currentHeadLocation = bodyLocations[bodyLocations.size() - 1];
for (int i = 0; i < bodyLocations.size() - 2; ++i)
{
bodyLocations[i] = bodyLocations[i + 1];
}
switch(currentDirection)
{
case Direction::UP:
--currentHeadLocation.y;
break;
case Direction::DOWN:
++currentHeadLocation.y;
break;
case Direction::LEFT:
--currentHeadLocation.x;
break;
case Direction::RIGHT:
++currentHeadLocation.x;
break;
}
}
void Snake::increaseSize()
{}
void Snake::draw(WINDOW * win)
{
for (int i = 0; i < bodyLocations.size(); ++i)
{
mvwprintw(win, bodyLocations[i].y, bodyLocations[i].x, "o");
}
wrefresh(win);
}
|
I would have expected this to work, but I have really no idea why it is not. The only thing this does is place 2 characters in the center of the window, and not let me do anything with them. In fact, when I press backspace, nothing happens and I have to use Ctrl-C to exit the app from the command line. Coord here represents a simple struct with two public members x and y. Here are the command line arguments I am using:
|
g++ -o snake main.cpp SnakeGame.cpp Snake.cpp -std=c++11 -lncurses
|