Skip to content

Instantly share code, notes, and snippets.

@oisincar
Created December 3, 2016 21:22
Show Gist options
  • Save oisincar/5825f75407320cbe32b9c527254b94f3 to your computer and use it in GitHub Desktop.
Save oisincar/5825f75407320cbe32b9c527254b94f3 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <clocale>
#include <cmath>
#include <ncurses.h>
#include <unistd.h>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
int _height, _width;
const float _PLAYER_SPEED = 0.05;
const float _ASTEROID_SPEED = 0.2;
class Player;
class Asteroid;
class Bullet;
Player *_player;
vector<Asteroid *> _asteroids;
vector<Bullet *> _bullets;
void WaitForTitle(){
vector<string> title;
title.push_back(
" _______ _______ _______ __________________ _______ _______ _________ ______ _______ ");
title.push_back(
"( ___ )( ____ \\( ____ \\\\__ __/\\__ __/( ____ )( ___ )\\__ __/( __ \\ ( ____ \\");
title.push_back(
"| ( ) || ( \\/| ( \\/ ) ( ) ( | ( )|| ( ) | ) ( | ( \\ )| ( \\/");
title.push_back(
"| (___) || (_____ | | | | | | | (____)|| | | | | | | | ) || (_____ ");
title.push_back(
"| ___ |(_____ )| | | | | | | __)| | | | | | | | | |(_____ )");
title.push_back(
"| ( ) | ) || | | | | | | (\\ ( | | | | | | | | ) | ) |");
title.push_back(
"| ) ( |/\\____) || (____/\\___) (______) (___| ) \\ \\__| (___) |___) (___| (__/ )/\\____) |");
title.push_back(
"|/ \\|\\_______)(_______/\\_______/\\_______/|/ \\__/(_______)\\_______/(______/ \\_______)");
title.push_back("");
title.push_back("");
title.push_back(" Press any key to play!");
title.push_back("");
int st_x = (_width - title[0].size())/2,
st_y = (_height - title.size())/2;
for(int y = 0; y < title.size(); y++){
string st = title[y];
for (int x = 0; x < st.size(); x++){
mvaddch(y + st_y, x + st_x, st[x]);
}
}
// sleep for a bit to stop accidental restarts of game.
wrefresh(stdscr);
usleep(500000);
char c;
do {
c = getch();
usleep(10000);
} while(c == ERR);
erase();
}
class GameObject {
protected:
pair<float, float> pos_;
pair<float, float> velocity_;
// How the object looks..
vector<string> form_;
string collide_chars_;
// if we're outside world boundaries wrap to other side..
void WrapWorld() {
pos_.first = fmod(pos_.first + _width, _width);
pos_.second = fmod(pos_.second + _height, _height);
}
bool CheckCollisions(){
if (collide_chars_ == "")
return false;
// collisions with already-rendered objects..
for (int y = 0; y < form_.size(); y++){
for (int x = 0; x < form_[0].size(); x++){
int px = x + pos_.first;
int py = y + pos_.second;
if (px > 0 && px < _width &&
py > 0 && py < _height) {
char del_c = mvinch(py, px);
if (collide_chars_.find(del_c) != string::npos){
mvaddch(py, px, ' ');
return true;
}
}
}
}
return false;
}
void Render() {
int x = pos_.first, y = pos_.second;
bool do_delete = false;
// Render each char.
for (string row : form_){
for (char c : row){
mvaddch(y, x, c);
x++;
}
x = pos_.first;
y++;
}
}
public:
// returns weither to delete.
bool Update() {
pos_.first += velocity_.first;
pos_.second += velocity_.second;
WrapWorld();
if (CheckCollisions())
return true;
Render();
return false;
}
};
class Player : public GameObject {
private:
vector< vector<string> > all_forms_;
pair<int, int> last_input_;
public:
pair<int, int> getDirection(){
return last_input_;
}
pair<float, float> getPosition(){
return pos_;
}
Player(){
pos_ = make_pair(_width/2, _height/2);
for (int i = 0; i < 4; i++) all_forms_.push_back( vector<string>() );
all_forms_[0].push_back(" ^\\____");
all_forms_[0].push_back("< o o >--");
all_forms_[0].push_back(" v/----");
all_forms_[2].push_back(" ___/^");
all_forms_[2].push_back("--< o o >");
all_forms_[2].push_back(" ----\\");
all_forms_[1].push_back(" | ");
all_forms_[1].push_back(" .^. ");
all_forms_[1].push_back(" | | ");
all_forms_[1].push_back(" | O | ");
all_forms_[1].push_back("<| O |>");
all_forms_[1].push_back(" v ");
all_forms_[3].push_back(" ^ ");
all_forms_[3].push_back("<| O |>");
all_forms_[3].push_back(" | O | ");
all_forms_[3].push_back(" | | ");
all_forms_[3].push_back(" 'v' ");
all_forms_[3].push_back(" | ");
form_ = all_forms_[0];
last_input_ = make_pair(1, 0);
collide_chars_ = ".,\\(_)/";
}
void HandleInput(pair<int, int> input_vec) {
last_input_ = make_pair(input_vec.first, input_vec.second);
velocity_.first += (float)input_vec.first * _PLAYER_SPEED;
velocity_.second += (float)input_vec.second * _PLAYER_SPEED;
if (input_vec.first != 0){
form_ = input_vec.first > 0 ? all_forms_[0] : all_forms_[2];
}
else if (input_vec.second != 0){
form_ = input_vec.second > 0 ? all_forms_[3] : all_forms_[1];
}
}
};
class Asteroid : public GameObject {
private:
int size_;
public:
Asteroid(int size){
size_ = size;
collide_chars_ = "-|";
if (size == 1){
form_.push_back(" _");
form_.push_back("<_>");
}
if (size == 2){
form_.push_back(" __.");
form_.push_back("/ \\_");
form_.push_back("\\___/");
}
if (size == 3){
form_.push_back(" __.");
form_.push_back("/ \\_");
form_.push_back("\\ ,. \\");
form_.push_back(" \\___/");
}
do {
pos_ = make_pair(rand() % _width, rand() % _height);
} while ((pos_.first < _width - _width/6 && pos_.first > _width/6) &&
(pos_.second < _height - _height/6 || pos_.second > _height/6));
velocity_ = make_pair((float)(500 - rand() % 1000)/5000, (float)((500 - rand() % 1000))/5000);
}
Asteroid(pair<float, float> pos, int size) : Asteroid(size) {
pos_ = pos;
}
bool AsteroidUpdate() {
// if we're about to delete this, spawn more!!
if (Update()) {
size_-=1;
if(size_ > 0){
_asteroids.push_back(new Asteroid(pos_, size_));
_asteroids.push_back(new Asteroid(pos_, size_));
}
return true;
}
return false;
}
};
class Bullet : public GameObject {
private:
int lifespan;
public:
Bullet(pair<float, float> pos, pair<float, float> velocity){
string f = (abs(velocity.first) > abs(velocity.second)) ? "-" : "|";
form_.push_back(f);
pos_ = pos;
velocity_ = velocity;
lifespan = 240;
}
bool BullUpdate(){
lifespan--;
return (lifespan > 0) && Update();
}
};
bool GameLoop(){
// do input..
pair<int, int> player_input_vec = make_pair(0, 0);
int c;
while ((c = getch()) != ERR) {
if (c == 'w' || c == KEY_UP) {
player_input_vec.second--;
}
else if (c == 'a' || c == KEY_LEFT) {
player_input_vec.first--;
}
else if (c == 's' || c == KEY_DOWN) {
player_input_vec.second++;
}
else if (c == 'd' || c == KEY_RIGHT) {
player_input_vec.first++;
}
else if (c == ' ') {
pair<int, int> acc = _player->getDirection();
float bullSpeed = 0.3;
pair<float, float> pos = _player->getPosition();
pos.first += 3;
pos.second += 1;
pair<float, float> accmul = make_pair((float)acc.first * bullSpeed, (float)acc.second * bullSpeed);
Bullet *b = new Bullet(pos, accmul);
_bullets.push_back(b);
}
}
// sometimes add an asteroid...
if (rand() % 100 == 0){
_asteroids.push_back(new Asteroid(1 + (rand() % 3)));
}
if (player_input_vec.first != 0 || player_input_vec.second != 0)
_player->HandleInput(player_input_vec);
erase();
for (int i = 0; i < _bullets.size(); i++){
if (_bullets[i]->BullUpdate()){
_bullets.erase(_bullets.begin()+i);
i--;
}
}
for (int i = 0; i < _asteroids.size(); i++){
if (_asteroids[i]->AsteroidUpdate()){
_asteroids.erase(_asteroids.begin()+i);
i--;
}
}
if (_player->Update()){
return false;
}
wrefresh(stdscr);
return true;
}
int main(){
srand (time(NULL));
// ncurses setup...
setlocale(LC_ALL, "");
initscr();
// No buffering.
cbreak();
noecho();
// Special chars.
keypad(stdscr, true);
// getch() can return ERR.
nodelay(stdscr, TRUE);
// No cursor.
curs_set(0);
srand(time(NULL));
getmaxyx(stdscr, _height, _width);
while (true){
WaitForTitle();
_player = new Player();
for (int i = 0; i < 15; i++)
_asteroids.push_back(new Asteroid(1 + (rand() % 3)));
while(GameLoop()){
usleep(10000);
}
// cleanup...
delete _player;
while(!_asteroids.empty())
delete _asteroids.back(), _asteroids.pop_back();
while(!_bullets.empty())
delete _bullets.back(), _bullets.pop_back();
}
endwin();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment