Hi everyone. My name is Zvjezdan Veselinovic and I am a student at Rasmussen College over in New Port Richey, Florida studying Game and Simulation Programming. For my student portfolio, I want to create a "tron-like"/ "snake-like" game called Colors and Explosions.

I have so far arrow key movement. That was no biggie. What I do not have is constant movement while my key is not pressed. Can anyone help me out please? Here is my code. I just want to bounce ideas; not have the project done for me. I can't learn that way.
.
.
.
.

// My "Things_in_background.h" Header file code

#include <iostream>
#include <string>
#include <windows.h> // resize the screen, gotoxy, delay, and so on.
#include <iomanip> // GetAsyncKeyState(), GetKeyState(), and so on.
#include <ctime>
#include <conio.h> // _getch(), _kbhit()

using namespace std;


int gotoxy(int x, int y) // used to place things anywhere in the window
{  
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD point;
    point.X = x-1;
    point.Y = y-1;     
    SetConsoleCursorPosition(hConsole, point);
    return SetConsoleCursorPosition(hConsole, point);
}


void Continue_() { cout << "Press any key to continue... "; _getch(); }
void Space_() { cout << "Press SPACE to continue... "; _getch(); }
void Clear_Line() { gotoxy(5,35); cout << "                                                             " << endl; }

void Up_arrow() { printf("%c", 30); }
void Down_arrow() { printf("%c", 31); }
void Left_arrow() { printf("%c", 17); }
void Right_arrow() { printf("%c", 16); }

void Object() { cout << "&" << endl; }







// my main_program.cpp code


#include "Things_in_background.h"

struct Player_Presses
{
    char up_arrow, down_arrow, left_arrow, right_arrow;
};

int main()
{
    Player_Presses player1;

    char movement;

    int objectx = 2, objecty = 2;



    cout << "Press the Up arrow: "; player1.up_arrow = _getch();

    if(_kbhit())
    {
        player1.up_arrow = _getch(); Up_arrow();

        if(player1.up_arrow == GetAsyncKeyState(VK_UP))
        {
            player1.up_arrow = VK_UP;
        }
    } cout << endl << endl;



    cout << "Press the Down arrow: "; player1.down_arrow = _getch();

    if(_kbhit())
    {
        player1.down_arrow = _getch(); Down_arrow();

        if(player1.down_arrow == GetAsyncKeyState(VK_DOWN))
        {
            player1.down_arrow = VK_DOWN;
        }
    } cout << endl << endl;



    cout << "Press the Left arrow: "; player1.left_arrow = _getch();

    if(_kbhit())
    {
        player1.left_arrow = _getch(); Left_arrow();

        if(player1.left_arrow == GetAsyncKeyState(VK_LEFT))
        {
            player1.left_arrow = VK_LEFT;
        }
    } cout << endl << endl;



    cout << "Press the Right arrow: "; player1.right_arrow = _getch(); 

    if(_kbhit())
    {
        player1.right_arrow = _getch(); Right_arrow(); 

        if(player1.right_arrow == GetAsyncKeyState(VK_RIGHT))
        {
            player1.right_arrow = VK_RIGHT;
        }
    } cout << endl << endl << endl << endl;



    cout << "Your arrows are..." << endl << endl << endl;

    cout << "Up: " << player1.up_arrow << endl << endl;
    cout << "Down: " << player1.down_arrow << endl << endl;
    cout << "Left: " << player1.left_arrow << endl << endl;
    cout << "Right: " << player1.right_arrow << endl << endl;

    Space_(); system("cls");

    system("mode 100,40");

    gotoxy(5,35); Space_();
    Clear_Line();

    gotoxy(objectx,objecty); Object();

    a: gotoxy(5,35); cout << "Press any key to move piece: "; movement = _getch(); 


    if(_kbhit())
    {
        movement = _getch();

        if(movement == player1.up_arrow)
        {
            objecty--;
            gotoxy(objectx, objecty); Object();

            Clear_Line(); goto a;
        }

        if(movement == player1.down_arrow)
        {
            objecty++;
            gotoxy(objectx, objecty); Object();
            Clear_Line(); goto a;
        }

        if(movement == player1.left_arrow)
        {
            objectx--;
            gotoxy(objectx, objecty); Object();
            Clear_Line(); goto a;
        }

        if(movement == player1.right_arrow)
        {
            objectx++;
            gotoxy(objectx, objecty); Object();
            Clear_Line(); goto a;
        }

    } // end of _kbhit()


    return 0;
}

and change line 138 to use getchar().

That won't work because getchar() requires a newline to terminate input in the shell. getch() is used because it's a non-blocking input function. This is an appropriate usage of the conio library.

perhaps a while loop around lines 138-168

Yes. Basically you need a game loop that runs forever and handles any input appropriately. For example:

#include <iostream>
#include <Windows.h>

int main()
{
    CONSOLE_SCREEN_BUFFER_INFO info;
    conio::Keys dir = conio::Keys::RIGHT;
    POINT curr = {1, 1};

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);

    for (;;) {
        // Clear the current position
        conio::gotoxy(curr.x, curr.y);
        conio::putch(' ');

        // Handle input if necessary
        if (conio::kbhit()) {
            int ch = conio::get_code();

            if (ch == conio::Keys::ESC)
                break;

            switch (ch) {
            case conio::Keys::UP:    dir = conio::Keys::UP;    break;
            case conio::Keys::DOWN:  dir = conio::Keys::DOWN;  break;
            case conio::Keys::LEFT:  dir = conio::Keys::LEFT;  break;
            case conio::Keys::RIGHT: dir = conio::Keys::RIGHT; break;
            }
        }

        // Always adjust the direction to keep things moving
        switch (dir) {
        case conio::Keys::UP:    curr.y = curr.y > 1 ? curr.y - 1 : curr.y;             break;
        case conio::Keys::DOWN:  curr.y = curr.y < info.dwSize.Y ? curr.y + 1 : curr.y; break;
        case conio::Keys::LEFT:  curr.x = curr.x > 1 ? curr.x - 1 : curr.x;             break;
        case conio::Keys::RIGHT: curr.x = curr.x < info.dwSize.X ? curr.x + 1 : curr.x; break;
        }

        // Move to the new position
        conio::gotoxy(curr.x, curr.y);
        conio::putch('@');

        Sleep(100);
    }
}

Note that I'm using a custom conio library for Win32 in that example rather than the conio.h that may or may not be supplied with the compiler. There's still a dependency on Windows, but it's a bit more general than expecting conio.h to be implemented by every Windows compiler. If you're interested, here's the code:

#include <cstdio>
#include <vector>
#include <windows.h>

namespace conio {
    enum Keys {
        ESC   = 27,
        UP    = 256 + 72,
        DOWN  = 256 + 80,
        LEFT  = 256 + 75,
        RIGHT = 256 + 77
    };

    namespace {
        bool unget_avail;  /* True if a character is available for ungetch */
        int unget_char;
    }

    int get_code();
    void gotoxy(int x, int y);
    int kbhit();
    int putch(int c);
    int ungetch(int c);
    int getch();

    int get_code()
    {
        int ch = getch();

        if (ch == 0 || ch == 224)
            ch = 256 + getch();

        return ch;
    }

    void gotoxy(int x, int y)
    {
        COORD pos;

        /* Conio positions are 1-based, but Win32 positions are 0-based */
        pos.X = (short)x - 1;
        pos.Y = (short)y - 1;

        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
    }

    int kbhit()
    {
        HANDLE sys_stdin = GetStdHandle(STD_INPUT_HANDLE);
        DWORD saved_mode, pending, read;

        /* Save the current mode and switch to raw mode */
        GetConsoleMode(sys_stdin, &saved_mode);
        SetConsoleMode(sys_stdin, 0);

        /* Get the number of pending input events (including key presses) */
        if (!GetNumberOfConsoleInputEvents(sys_stdin, &pending) || !pending)
            return 0;

        std::vector<INPUT_RECORD> info(pending);
        int key_ready = 0;

        /* Peek at and check each pending input event for a key press */
        if (PeekConsoleInput(sys_stdin, &info[0], pending, &read) && read) {
            for (DWORD i = 0; i < read; ++i) {
                if (info[i].EventType == KEY_EVENT && info[i].Event.KeyEvent.bKeyDown) {
                    key_ready = 1;
                    break;
                }
            }
        }

        /* Restore the original console mode */
        SetConsoleMode(sys_stdin, saved_mode);

        return key_ready;
    }

    int putch(int c)
    {
        DWORD written;

        if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &c, 1, &written, 0))
            return EOF;

        return c;
    }

    int ungetch(int c)
    {
        if (unget_avail)
            return EOF; /* Only allow one ungetch at a time */

        unget_avail = true;
        unget_char = c;

        return c;
    }

    int getch()
    {
        if (unget_avail) {
            /* There was a preceding ungetch */
            unget_avail = false;
            return unget_char;
        }
        else {
            HANDLE sys_stdin = GetStdHandle(STD_INPUT_HANDLE);
            DWORD saved_mode, read;
            INPUT_RECORD info;
            int ch = EOF;

            /* Save the current mode and switch to raw mode */
            GetConsoleMode(sys_stdin, &saved_mode);
            SetConsoleMode(sys_stdin, 0);

            /* Read a raw character */
            while (ch == EOF) {
                if (!ReadConsoleInput(sys_stdin, &info, 1, &read) || !read) {
                    ch = EOF;
                    break;
                }
                else {
                    KEY_EVENT_RECORD key = info.Event.KeyEvent;

                    if (info.EventType == KEY_EVENT && key.bKeyDown) {
                        /* Save the current code (may be an escape for extended codes) */
                        ch = key.uChar.AsciiChar;

                        if (ch == 0 || ch == 0xe0) {
                            /* Push the extended code for the next call */
                            ungetch(key.wVirtualScanCode);
                        }
                    }
                }
            }

            /* Restore the original console mode */
            SetConsoleMode(sys_stdin, saved_mode);

            return ch;
        }
    }
}
This article has been dead for over six months. Start a new discussion instead.