I'm making a simple text game using the pdCurses library and a few other minor things like a vertical scroller in which you avoid the randomly-generated walls.
There are two walls on left and right made out of 'X' characters and blank, black space in which you can move around and avoid the 'X's your character is an '8' and your forced to continue forward or get touched by the X's each time a new line of the randomly generated "map" is revealed (for performance tests I'm making new lines show as fast as possible).
However, I am having performance issues and need new lines to be inserted and shown at least 3-5 times per second. Please suggest some simple ways of boosting performance.
#include <iostream>
#include <time.h> // or "ctime"
#include <stdio.h> // for
#include <cstdlib>
// Windows stuff
#include <Windows.h> // GOD DAMMNIT WINDOWS WHY????
#include <conio.h>
// Ncurses
#include<curses.h>
// STL stuff
#include <algorithm>
#include <string>
#include <vector>
//String/Int conversion
#include <sstream>
// gives access to rand function
#include <cstdlib>
//gives access to time functions
#include <ctime>
// mySTOPWATCH i think i'm gonna cry.... =')
#include <myStopwatch.h> // for keeping times
#include <myMath.h> // numb_digits() and digit_val();
using namespace std;
enum{ NUMB_LINES= 24, SEC= 1000}; // time stuff
enum{TIME= 345, HEALTH = 346, MAP= 247}; // for Refresh() command
enum{NONE= 256}; // for Refresh() transition
enum{NEW = 590, OLD = 591}; // for the old/new screen command
// Some nCurses setup
int r = 0,
c = 0; // current row and column (upper-left is (0,0))
const int nrows = 56, // number of rows in window
ncols = 79; // number of columns in window
// Timer Setup
Stopwatch myStopwatch(3, START);
/////////////////////////// RandNumb() ///////////////////////////////////////
int RandNumb(int scope){
srand(GetTickCount());
return rand() % scope;};
////////////////////////// GeneratePathStart() ///////////////////////////////
void GeneratePathStart(vector<string>& buff){
int wall= RandNumb(80)/2,
space = (RandNumb(75)/2)+5,
wall2= 80- (wall+space);
buff.push_back("");
for(;wall> 0; wall--){
buff[0].push_back('X');}
for(;space> 0; space--){
buff[0].push_back(' ');}
for(; wall2 > 0; wall2--){
buff[0].push_back('X');}
};
////////////////////////// GeneratePath() ////////////////////////////////////
void GeneratePath( vector<string>& buff){// the buff is the seed too
int wall= RandNumb(80)/2,
space = (RandNumb(75)/2)+5,
wall2= 80-(space+wall);
int swall= 0;
for(char i= '0'; i!= ' ';swall++)
i= buff[buff.size()-1][swall+1];
int sspace= 0; int I= swall+1;
for(char i= '0'; i!= 'X';sspace++, I++)
i= buff[buff.size()-1][I];
int swall2 = 80-(sspace+swall);
// now the actual generation
int cwall= wall-swall;
int cspace= space-sspace;
int cwall2= wall2-swall2;
for(;cwall!= 0 || cspace!= 0 /*|| cwall2 != 0*/;){
buff.push_back("");
//cwall
if(cwall!= 0){
if(cwall>0){
swall++;
cwall--;}
else{ // cwall is negative
swall--;
cwall++;}}
for(int w= 0; w <swall; w++)
buff[buff.size()-1].push_back('X');
// cspace
if(cspace!= 0){
if(cspace>0){
sspace++;
cspace--;}
else{ // cspace is negative
sspace--;
cspace++;}}
for(int s= 0; s <sspace; s++)
buff[buff.size()-1].push_back(' ');
// cwall2
//if(cwall2!= 0){
// if(cwall2>0){
// wall2++;
// cwall2--;}
// else{ // cspace is negative
// wall2--;
// cwall2++;}}
for(int w2= 0; w2 <80- (swall+sspace); w2++)
buff[buff.size()-1].push_back('X');
}}// end of function
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Sprite Class ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Sprite
{
private:
string name;
char symbol;
float health;
int location[2];
public:
///////////////////// Get and SET all the privates ///////
Sprite(){};
Sprite(string a_name, char a_symbol, float a_health){
name = a_name;
symbol = a_symbol;
health = a_health;};
char get_symbol() {return symbol;};
void set_symbol(char sym) {symbol = sym;};
float get_health() {return health;};
void set_health(float numb) {health = numb;};
void add_health (float numb) {health += numb;};
string get_name() {return name;};
string set_name(string aName) {name = aName;};
int* get_location(){return location;};
void set_location(int X, int Y) {
location[0] = X;
location[1] = Y;};
//////////////////////////////// Move ////////////
bool move(int X, int Y) {
location[0] += X;
location[1] += Y;
return true;};
};// end of sprite
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Player Class ///////////////////////////////////////////////////////////////////////////////////////////////////////////
class Player : public Sprite
{
public:
Player(string name,int X, int Y, float health){
set_symbol('8');
set_name(name);
set_location(X,Y);
set_health(100);};
private:
// none?
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////// Map class ///////////////////////////////////////////////////////////////////////////////////////////////////
class Map
{
private:
/////////////////////////////////////////// Map Variables ///////////////
string name;
vector <string> contents;
vector <string> save;
public:
Map(){};
Map(string* lines, int i, string name= "map"){name = name;
contents.resize(56);
Insert(lines, i);};
~Map(){};
/////////////////////////////////////////// generate ////////////////////
void generate(){GeneratePath(contents);};
/////////////////////////////////////////// Return() ////////////////////
string Name() {return name;};
vector <string> Contents() {return contents;};
string Contents(int Y) {return contents[Y];};
char Contents(int Y, int X) {return contents[Y][X];};
vector <string> Save() {return save;};
int size() {return contents.size();};
/////////////////////////////////////////// Insert() ////////////////////
// string* to an array of 24 strings;
void Insert(string* lines, int i)
{contents.assign(lines, lines+i);}; //insert lines 1-24
void Insert(string astring, int Y) {contents[Y] = astring;};
void Insert(char achar, int X, int Y){contents[Y][X] = achar;};
void Saveline(string line) {save.push_back(line);};
};
///////////////////////// SCREEN CLASS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Screen
{
private:
/////////////////////////////////////////// Screen Variables ///////////////
string _name;
vector <string> new_map;
vector <string> old_map;
vector <Sprite*> sprites_p;
public:
Screen(string name){_name = name;
new_map.resize(nrows);
old_map.resize(nrows);};
~Screen(){};
//////////////////////////////////////////// Get contents ///////////////////////////
vector <string> get_contents(int comm= NEW) {switch(comm){ case NEW: return new_map; break;
case OLD: return old_map; break;}};
string get_contents (int Y, int comm= NEW) {switch(comm){ case NEW: return new_map[Y]; break;
case OLD: return old_map[Y]; break;}};
char get_contents (int X, int Y, int comm= NEW){switch(comm){ case NEW: return new_map[Y][X]; break;
case OLD: return old_map[Y][X]; break;}};
//////////////////////////////////////////// Refresh ///////////////////////////
void Refresh(int command= ALL, int transition= NONE)
{
//old_map = new_map; // update the old map
for(int r= 0; r< nrows; r++){ move(r,0);
addstr((char*)new_map[r].c_str());} // make sure this works later
// Insert Time
if(command== ALL || command== TIME){
enum{ time_loc_y= 22,
time_loc_x= 38 };
mvaddstr(time_loc_y, time_loc_x, myStopwatch.ClockTime().c_str());}
refresh();}; // end of function
/////////////////////////////////////////// Insert ////////////////////////
/////////////////// Map
void Insert(Map& map, int y1, int y2) {for ( int mc = y1, nm= 0; mc< map.size() && mc< y2; mc++, nm++){
new_map[nm] = map.Contents(mc);}
};
/////////////////// string
void Insert(string astring, int Y) {new_map[Y] = astring;};
///////////////////// char
void Insert(char achar, int X, int Y) {new_map[Y][X] = achar;};
//////////////////// sprite
void Insert(Sprite& sprite) {new_map[sprite.get_location()[1]][sprite.get_location()[0]] = sprite.get_symbol();
sprites_p.push_back(&sprite);}; // save a pointer to the sprite
/////////////////////////////////////////// Collision Detection ///////////
bool check_collision(Sprite& sprite,int X, int Y, char& buff)
{
////////////////////// check whats already there /////
char newloc = new_map[sprite.get_location()[1]+Y]
[sprite.get_location()[0]+X];
if(newloc == '|' || newloc == '/' || newloc == '_' || newloc == '=' || newloc == 'X' || newloc == '-' || newloc == 'x' ) {buff = newloc; return true;}
else return false;
};
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// MAIN //////////////////////////////////// MAIN ////////////////////////////////////////////////////////////////////////
int main()
{
cout << "make the screen fullscreen!!";
char response; cin >> response;
WINDOW *wnd;
wnd = initscr(); // curses call to initialize window and curses mode
//cbreak(); // curses call to set no waiting for Enter key
noecho(); // curses call to set no echoing
//curs_set(a number); (0 = invisible, 1 = normal, 2 = very visible)
int row,col; getmaxyx(stdscr,row,col); /* get the number of rows and columns */
clear(); // curses call to clear screen, send cursor to position (0,0)
Screen theScreen("ascreen");
string splashScreen[24] = { // HERE"S THE SPLASH !
// 1 2 3 4 5 6 7 8
// 123456789 123456789 123456789 123456789
// 0123456789 123456789 123456789 123456789 1234567
/* 0 */ "________________________________________________________________________________",
/* 1 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 2 */ "|XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 3 */ "|XXXXXX / XXXXXXXXXXXXXXXXXXXXX xXXXXXXXXXX XXXXXXXXXXXx xXXXXXXx xXXX|",
/* 4 */ "|XXXXX /0} XXXXXXXXXXXXXXXXX /XXXXx XXXXXXx /X xXXXXXXXXX XXXXXX XXX|",
/* 5 */ "|XXXX /000} XXXXXXXXXXXXXX /XXXXXXXx XXXXX /X XXXXXXXX /X XXXX /X XX|",
/* 6 */ "|XXX XXXXXXXXXXXX /XXXXXXXXxx XXXX /XXX XXXXXXX /XX XXXX |X XX|",
/* 7 */ "|XX /XXXXXX XXXXXXXXXX /XXXXXXXXXXXXXXXX /XXX XXXXXX |XXX XX /X xX|",
/* 8 */ "|X /XXXXXXXX X*X*X*XXX /XXXXx xXX XXXXX |XXX /XXX X|",
/* 9 */ "|XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXX XX /XXXXX XXXX |XXXX /XXXX X|",
/* 10 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXX Xx /XXXXXXX xXXX |XXXXx /XXXX X|",
/* 11*/ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXx /XXXXXXX xXX XXXXXxxXXXX x|",
/* 12 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 13 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxXXXX|",
/* 14 */ "|XXX XXxXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX|",
/* 15 */ "|XXX XXXx XX/ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_____XX XXXXXXXXXXXXXXXX|",
/* 16 */ "|XXX XXX / XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX|",
/* 17 */ "|XXX /0] XX/ XXXXx xXX XXXXXXXXXXX xXXX xXXXX xXXX|",
/* 18 */ "|XXX XX/ XXXXX XXXXXXXX xXXX XXX XXXXXX XXXXXXX xXXX|",
/* 19 */ "|XXXXXXXX XXXXXXX XXx xXX XXXXXX XXX xXXX xXXXX XXXXXXXXXXXXXXXX|",
/* 20 */ "|XXXXXXXXXXXXXXXXX XXXX XX XXXXXX XXX XXXXXX XXXXXXX XXXXXXXXXXXXXXXX|",
/* 21 */ "|XXXXXXXXXXXXXXXXXx xXXxxXXXXXXxxXXX xXXXXXX xXXXXXXX XXX|",
/* 22 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxXXX|",
/* 23 */ "|______________________________________________________________________________|",};
string _lines_[56] = {
// 1 2 3 4 5 6 7 8
// 123456789 123456789 123456789 123456789
// 0123456789 123456789 123456789 123456789 1234567
/* 0 */ "________________________________________________________________________________",
/* 1 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 2 */ "|XXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXX XXXXXXXX|",
/* 3 */ "|XXXXX XXXXXXXXXXXXXXXX XXXXXXXXX XXXXXXXXXX XXXXXXXX|",
/* 4 */ "|XXXX XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX|",
/* 5 */ "|XXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX|",
/* 6 */ "|XX XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX|",
/* 7 */ "|XX XXXXXXXX XXXXXXX XXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX|",
/* 8 */ "|XXX XXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXXX|",
/* 9 */ "|XXXX XXXXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXXX|",
/* 10 */ "|XXXXX XXXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXXX|",
/* 11 */ "|XXXXXXX XXXXXXXXX XXXXXX XXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX|",
/* 12 */ "|XXXXXXXX XXXXXXX XXXXXX XXXXXXXXXXXXXXXXX XXXXXXX XXXXXXXX|",
/* 13 */ "|XXXXXXXXXX XXXXX XXXXXXX XXXXXXXXXXXXXXX XXXXXXXX___XXXXXXXX|",
/* 14 */ "|XXXXXXXXXXX XXXXXXXXX XXXXXXXXXXXXXXX XXXXXXXXxxxXXXXXXXX|",
/* 15 */ "|XXXXXXXXXXXX XXXXXXXXXXXX XXXXXXXXX XXXXXXXXXXx xXXXXXXX|",
/* 16 */ "|XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXx xXXXXXXX|",
/* 17 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 18 */ "|______________________________________________________________________________|",
/* 19 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 20 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 21 */ "|XXX XXX|",
/* 22 */ "|XXX XXX|",
/* 23 */ "|XXX XXX|",
/* 0 */ "|XXX XXX|",
/* 1 */ "|XXX XXX|",
/* 2 */ "|XXX XXX|",
/* 3 */ "|XXX XXX|",
/* 4 */ "|XXX XXX|",
/* 5 */ "|XXX XXX|",
/* 6 */ "|XXX XXX|",
/* 7 */ "|XXX XXX|",
/* 8 */ "|XXX XXX|",
/* 9 */ "|XXXX XXXX|",
/* 10 */ "|XXXXX XXXXX|",
/* 11*/ "|XXXXXX XXXXXX|",
/* 12 */ "|XXXXXXX XXXXXXX|",
/* 13 */ "|XXXXXXXX XXXXXXXX|",
/* 14 */ "|XXXXXXXXX XXXXXXXXX|",
/* 15 */ "|XXXXXXXXXX XXXXXXXXXX|",
/* 16 */ "|XXXXXXXXXXX XXXXXXXXXXX|",
/* 17 */ "|XXXXXXXXXXX XXXXXXXXXXX|",
/* 18 */ "|XXXXXXXXXXXX XXXXXXXXXXXX|",
/* 19 */ "|XXXXXXXXXXXX XXXXXXXXXXXX|",
/* 20 */ "|XXXXXXXXXXXXX XXXXXXXXXXXXX|",
/* 21 */ "|XXXXXXXXXXXXX XXXXXXXXXXXXX|",
/* 22 */ "|XXXXXXXXXXXXXX XXXXXXXXXXXXXX|",
/* 23 */ "|XXXXXXXXXXXXXX XXXXXXXXXXXXXX|"
/* 24 */ "|XXXXXXXXXXXXXXX XXXXXXXXXXXXXXX|",
/* 25 */ "|XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX|",
/* 26 */ "|XXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX|",
/* 27 */ "|XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXX|",
/* 28 */ "|XXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX|",
/* 29 */ "|XXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXX|",
/* 30 */ "|XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 31*/ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
/* 32 */ "|XXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXX|",
};
////////////////////////////////// Splash Screen /////////////////////////////
Map splashScreen_map(splashScreen, 24);
theScreen.Insert(splashScreen_map, 0, nrows);
theScreen.Refresh(MAP);
myStopwatch.Wait(3);
myStopwatch.Restart();
/////////////////////////////////////////////////////////////////////////////////
Map L1(_lines_, nrows, "L1");
theScreen.Insert(L1, 0, nrows);
Sprite player("Player",'8',100); //(8, 12, 16);
player.set_location(24, 48);
////////////////////// Check if new line is needed;
double refreshes= 0;
double newSpeed= 10;
for (bool quit = false; quit != true;)
{ double newTime= myStopwatch.ElapsedTime()- refreshes;
if(newTime*newSpeed >= 1){
theScreen.Insert(L1, 0+refreshes, nrows+refreshes);
refreshes++;
if(L1.size()<= nrows+refreshes+2)
L1.generate();}
///////////////// Keypress ///////////
if (kbhit()){
int key = getch();
key = toupper(key); // makes whatever key uppercase
int xMove = 0;
int yMove = 0;
int stepSize = 1;
bool validPress = true;
switch(key){
// update health here............
case 'W': yMove = -stepSize;break;
case 'S': yMove = stepSize; break;
case 'A': xMove = -stepSize;break;
case 'D': xMove = stepSize; break;
case'P': getch(); break;
case'O': quit = true;
default: validPress = false;}
if(validPress == true){
char coll; // if there's no collision
if(theScreen.check_collision(player, xMove, yMove, coll) != true){
// get rid of old player placing
theScreen.Insert(' ', player.get_location()[0],player.get_location()[1]);
// put in new charater placing
player.move(xMove, yMove);
theScreen.Insert(player);
theScreen.Refresh();}
else{
theScreen.Refresh();}};
// do other stuff with 'coll';
} /* end of if(kbhit())*/
theScreen.Refresh();}// so refresh and restart the for loop
endwin(); // curses call to restore the original window and leave
return 0;
}