Hello,

I have to make a small game in C++ as a school project. Now, although I've made many 2D games before I'm very new to C++, and I ran into a few problems.

One: I need dynamic key input. I now use getch() and it makes the program wait for key input, but I want other code to keep running while no key is pressed yet.

Two: I think I have a memory leak or something, because if I keep running my game a few times, my pc becomes slower. (I have a dutch pc so can't describe it very clearly, but if you press CTRL+ALT+DEL, and look at the performance tab, and then the thing beneath the CPU gets higher everytime I play (from 178 MB to 200, to 300 and then my pc becomes kind of slow).

My code (the game's a very silly not-yet-working correctly car-racing game):

#include <cstdlib>
#include <iostream>
#include <string>
#include <conio.h>
#include <process.h>

using namespace std;

//car variables
string car("|=|");
string car_frontback("0-0");
string car_space_left("");
string car_space_right("");
int car_space_int = 10;
//int car_health = 100;

//enemy variables
string enemy("|=|");
string enemy_frontback("X=X");
string enemy_space_left("");
string enemy_space_right("");
int enemy_space_int = 0;
int enemy_pos = 0;

//game variables
int row_total = 15;
int space_total = 20;
string game_space("       ");
string line("|");
string show_nothing("   ");
int nothing[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int i = 0;
int num = 0;

//keyboard variables
const char KEYRIGHT = 75;
const char KEYLEFT = 77;
char arrow = 0;

int main(int argc, char *argv[])
{
    //title screen
    cout << "   -----------------" << endl
         << "   -    Welcome    -" << endl
         << "   -      to       -" << endl
         << "   -   Ultra Car   -" << endl
         << "   -    Racing     -" << endl
         << "   -     3000      -" << endl
         << "   -----------------" << endl
    << "" << endl
    << "Use the left and right keys to dodge cars." << endl
    << "Press any key to start.";
    
    srand(time(NULL));

    //check keyboard
    arrow = kbhit();
    while(arrow !=27) {
                
                //variables
                i = 0; 
                car_space_left = "";
                car_space_right = "";
                enemy_space_left = "";
                enemy_space_right = "";
        
        //wait for kb input... why wait?! :( ..stupid c++
        arrow = getch();     
        switch(arrow)
        {                          
            case KEYLEFT:
                 //left arrow key
                 if (car_space_int <= space_total) car_space_int+=1;
            break;
            case KEYRIGHT:
                 //right arrow key
                 if (car_space_int > 0) car_space_int-=1;
            break;
        }
                
        //space left to the car
        for (i=0; i < car_space_int; i++) {
            car_space_left = car_space_left + " ";
        }
        
        //space right to the car
        for (i=0; i <= space_total-car_space_int; i++) {
            car_space_right = car_space_right + " ";
        }
        
        //set enemy position
        if (enemy_pos == 14) {
            num = 1 + rand() % (20 - 1 + 1);
            enemy_space_int = num;
        }
        
        //space left to the enemy
        for (i=0; i < enemy_space_int; i++) {
            enemy_space_left = enemy_space_left + " ";
        }
        
        //space right to the enemy
        for (i=0; i <= space_total-enemy_space_int; i++) {
            enemy_space_right = enemy_space_right + " ";
        }
        
        
        
        enemy_pos += 1;
        if (enemy_pos > row_total) {
           enemy_pos = 0;
        }
        

        
        //clear screen
        system("cls"); 
        
        //place game screen lower
        
        cout << endl;
        cout << endl;
        cout << endl;
        
        //position of enemy
        for (i=0; i<row_total; i++)
        {
            
             nothing[i] = 0;
             
        }
        
        
        
        nothing[enemy_pos] = 1;
        nothing[enemy_pos+1] = 2;
        nothing[enemy_pos+2] = 1;
        
        //show road, enemy
        for (i=0; i<row_total; i++) {
                  if (nothing[i] == 0) { show_nothing = "   "; }
             else if (nothing[i] == 1) { show_nothing = enemy_frontback; }
             else if (nothing[i] == 2) { show_nothing = enemy; }
        cout << game_space << line << enemy_space_left << show_nothing << enemy_space_right << line << endl;
        }
        
        //show car
        cout << game_space << line << car_space_left << car_frontback << car_space_right << line << endl;
        cout << game_space << line << car_space_left << car           << car_space_right << line << endl;
        cout << game_space << line << car_space_left << car_frontback << car_space_right << line << endl;
        
        cout << endl << "check " << enemy_pos << " + " << i;  
        
          
        }
                
    //end game
    system("PAUSE");
    return EXIT_SUCCESS;
}

//I HAVE A MEMORY LEAK SOMEWHERE!!! :(

Yes, I know my code is very very bad... this is the first time I use C++. And yes it's a text-based racing game... :eek:

Basically what it does now is that you can steer a car from left to right, and that other cars run down the road from top to bottom, but they only can down if you keep driving (no keyboard input and they stop moving).

Any help would be much appreciated!

Recommended Answers

All 29 Replies

Member Avatar for iamthwee

you need kbhit()

It's in there already:


//check keyboard
arrow = kbhit();
while(arrow !=27) {

Member Avatar for iamthwee

Oopsie. I didn't see it. In that case you need to use it correctly.

So you're saying I don't use it correctly? I have no idea how to do so, sorry.

Please be more descriptive.

Also, what could be the reason that my pc becomes slower? I have no previous experiences with memory leaks etc. In Flash you don't have to worry about that...

Member Avatar for iamthwee

Well where is your time delay as well?

I have none... i'm not sure where i would need that for...

also, if you just load the code in Dev-C++ for example, you should be able to run it (i only use standard libraries).

Member Avatar for iamthwee

i only use standard libraries

That's nice, do you think system("cls") is standard and cross platform compatible?

No, i think it only works on Windows...

I know I'm a noob when it comes to C++, but I do know the basics of programming.

Member Avatar for iamthwee

It's also a compiler issue as well, <conio.h> isn't supported by all compilers.


Anyway back on topic, so where is you time delay?

I'm sorry,I have no idea what a time delay is...

Member Avatar for iamthwee

Let's imagine instead of clearing the screen every time you pressed one of the arrow keys, you cleared the screen every half second.

Timer? Yes.

I need to refresh the screen everytime the screen changes...

Anyway, when using getch() the program waits till there's keyboard input. Is there a way to make it so that the program keeps doing code, while still using getch() (or something else) to check for keyboard input?

If I could just get that to work everything'd be fine..

Member Avatar for iamthwee

Yes but you keep ignoring my suggestion about using a timer/delay function.

That's because I have no idea what to do with it, what it's for, why I need it, etc.

Member Avatar for iamthwee

Well basically it is telling you how many times you need to refresh the screen.

you need kbhit()

That's nice, do you think system("cls") is standard and cross platform compatible?

This was hilarious!!! Suggesting a non-standard function then pointing out something that's not standard! :) Decide which side of the standard you sit on and stay there, don't vacillate.

Also, system() is a standard library function. It's the parameter "cls" that's system dependent.

You don't have memory leaks. You have a runaway program that will take whatever resources it wants.

Fix the kbhit() problem, and that will correct most of it. (if you knew to use kbhit() you certainly can find out how to use it)

Fix your input then we'll get the timer thing working...

Hey, actually...

It works now...! I used GetAsyncKey and I now have a working text based car racing game.

system(cls) NEEDS to be done every time you press the key, because everytime you press it the car moves to the left or right.

Now it's actually done more often (also when you not press) because the opposing cars drive down the road.

So, the screen needs to be refreshed a lot because it's a constantly changing game. Well, it's a game.

ANyway, maybe what you mean is that it runs as quick as the processor allows it to, so that's why i need a delay? (so it runs this quick on every pc)??

You don't have memory leaks. You have a runaway program that will take whatever resources it wants.

Ah i see... that makes it a bit more clear for me, thanks.

Member Avatar for iamthwee

>This was hilarious!!! Suggesting a non-standard function then pointing out something that's not standard!

I only pointed that out cos the OP thought he was using standard functions. I know very well, due to the nature of this program that non-standard functions are necessary - for example clearing the screen reliably. But keep laughing if you found that funny mr disney -or better still next time read the thread more carefully:)

Since we're using WinAPI already, why not use it to clear the screen instead of using system calls? The solution below I found at CProgramming:

#include <windows.h>

void clear_screen ( void )
{
  DWORD n;                         /* Number of characters written */
  DWORD size;                      /* number of visible characters */
  COORD coord = {0};               /* Top left screen position */
  CONSOLE_SCREEN_BUFFER_INFO csbi;

  /* Get a handle to the console */
  HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );

  GetConsoleScreenBufferInfo ( h, &csbi );

  /* Find the number of characters to overwrite */
  size = csbi.dwSize.X * csbi.dwSize.Y;

  /* Overwrite the screen buffer with whitespace */
  FillConsoleOutputCharacter ( h, TEXT ( ' ' ), size, coord, &n );
  GetConsoleScreenBufferInfo ( h, &csbi );
  FillConsoleOutputAttribute ( h, csbi.wAttributes, size, coord, &n );

  /* Reset the cursor to the top left position */
  SetConsoleCursorPosition ( h, coord );
}

Why is that better than using system("cls") ?

system function calls in C / C++ invoke the operating system functionality (here cls ) so the context has to be changed and control be handed from the currently running program to the Operating System to invoke the clear screen function.

Using the method posted by Joey won't invoke OS functions and hence even though it looks a bit length, its performance is way better than the system call.

Read this.

but I want other code to keep running while no key is pressed yet.

use a loop for that

use a loop for that

He was using a loop for that, if you read his code. The problem was that he wasn't using kbhit correctly.

Ok, I changed the system(cls) into the clear_screen() function, works great.

Thanks for the replies everyone. Here is the full code:

[removed]

The game works well now... the only problem is that it quits after you've been hit or after you've passed 10 cars (end of the game).

How to restart the game?

EDIT: Whhoops I didn't really change it.. and when I do.. the game runs way way to fast. delay necessary i guess?

>How to restart the game?
Usually how you do this in game programming is create a huge loop. In encompasses everything that you need to play again. It's usually a while() loop, waiting for a bool to be set to true. When the user decides to quit, this bool is then set to true, and the loop exits.

You should also have a special function that resets all your variables back to 0 or whatever they were before the game started. That way you simply call this function when the player wants to start again, and in a sense, you've restarted the game.

>the game runs way way to fast. delay necessary i guess?
Listen to iamthwee. Use timers. Typically what you do is get the time at the top of the loop, and then get the time at the bottom of the loop. The difference is how much time has elapsed. Now... the key is to figure out how long the delay is supposed to be. If it's 1/30 of a second, you only wait the remaining time, that way saving slower processors from idling when they've already taken more than 1/30 of a second processing.

Thanks for the info everyone!

I learned a bit about C++ which is great. Yesterday I showed the game to my teacher and he liked itvery much (actually, he was happy when it had a function, an iteration and a do, while, or for loop)..

Since I'm finished, I won't add stuff like a restart and time dealy, but I will keep them in mind for later. (maybe I will make some PSP homebrew later on. I learned that there's a good library for it. Also much easier actually, making a game that's not text based).

Hi There,

Your question was a bit on an inspiration to a fellow newbie.

It works if if you wrap an if statement around your getch() cammand like this:

if (kbhit()){
arrow=getch();
}

This means that your engine only stops to look if there actually is a key being pressed, and also moves on imperceptably!

Wahey!)

Hope this helps!

James:eek:

The gamevial team

tried the game (compiled using bloodshed dev C++) and i just thought id point out that u cant actually lose the game, as the cars cant crash into u. They disappear just before hitting u.

Just thought I'd point out that 4 years ago this might have been an issue, but today this was a long-buried thread. Now you've resurrected a zombie. Thanks...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.