Sign in to follow this  

Basic game loop in C++

This topic is 4531 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone. I've been lurking these forums since forever, but didn't register until today. I know quite a bit of programming, mostly algorithm and data structure and problem solving, but not much game programming. In fact, I've just recently gotten the time to start seriously looking into it, but I've run across a silly problem that I can't seem to figure out on my own. I've mostly programmed in Java, but programming in C++ now. My problem is simply that I don't know how to make a basic game loop, specifically how to get keyboard input without having to press enter(cin) and having the gameflow continue while waiting for input. I've tried searching everywhere for the answer, but can't seem to find it. What I'm trying to do is an ASCII snake clone, so I want to be able to move the snake by pressing the arrow buttons, and have it move in that direction until another button is pressed. I think I've figured out everything else I need to do except that game loop. So, to summarize, does anyone want to help me with this? Either by posting some sample code or post a link to someplace that explains this? I've found some examples of gameloops using Allegro or DirectX, but I just want a very simple one for an ASCII game. Thanks everyone! S'king

Share this post


Link to post
Share on other sites
If you're running on a Microsoft platform, you might want to have a look at the <conio.h> header, particularly the kbhit() and getch() functions. They should be useful to help you build your console-based games.

Share this post


Link to post
Share on other sites
Hello Squirrelking,

If you are creating an ASCII game, you should obviously have the screen updated every frame. Something like this would do in your case:


#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

void DrawFrame()
{
if(KEY_DOWN(VK_RIGHT))
//Move the snake right
if(KEY_DOWN(VK_LEFT))
//Move the snake left
if(KEY_DOWN(VK_UP))
//Move the snake up
if(KEY_DOWN(VK_DOWN))
//Move the snake down

// Draw ASCII graphics
}
int main()
{
while(!KEY_DOWN(VK_ESCAPE))
{
DrawFrame();
}

return 1;
}




[Edited by - AcePilot on July 17, 2005 11:13:33 PM]

Share this post


Link to post
Share on other sites
by the way, you need the windows.h header to use those two macros.

#include <stdio.h> // Always good idea to include these two headers,
#include <conio.h> // no matter what your application type.

#include <windows.h>

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

Share this post


Link to post
Share on other sites
I'd recommend (after you learn things like how to make a guess the number game and tic-tac-toe and such) you look into a 2D graphics API, mainly either Allegro or SDL (or both if you want a broad skill base). Even if you're making text only games, these APIs have good usages when it comes to implementing input into your game.

-IV

Share this post


Link to post
Share on other sites
Here is something that I got from someone else on this forum.


// Much thanks for blizzard999 from gamedev.net


#ifndef _CWIN_KEYBOARD_INPUT_H_
#define _CWIN_KEYBOARD_INPUT_H_


#include <memory.h>
#include <windows.h>

/**
* A class to allow easy access to the state of the keyboard in Windows.
*/

class CWinKeyboardInput
{
private:
typedef short WINKEYBSTATE[256]; //< An array of short, representing the keyboard state.
typedef short* LPWINKEYBSTATE; //< A pointer to a keyboard state.

LPWINKEYBSTATE pck; //< ptr to current keyboard state
LPWINKEYBSTATE pok; //< ptr to old keyboard state

WINKEYBSTATE ks1; //< keyboard state 1
WINKEYBSTATE ks2; //< keyboard state 2

typedef char BYTE;

/**
* Constructor.
*/

CWinKeyboardInput()
{
// Get the state of the keyboard
GetKeyboardState(ks1);

// Copy the state of the keyboard to ks2, so both states are the same.
memcpy(ks2, ks1, sizeof(WINKEYBSTATE) );

// Set the current and old states of the keyboard.
pck = ks1;
pok = ks2;
}


public:

/**
* A static Get() function for the CWinKeyboardInput object.
* \return A reference to the CWinKeyboardInput object.
*/

static CWinKeyboardInput& Get()
{
static CWinKeyboardInput k;
CWinKeyboardInput& ref = k;

return ref;
}

/**
* Get the state of the keyboard.
* \param pks A pointer to an array of short, representing the state of the keyboard.
*/

void GetKeyboardState(LPWINKEYBSTATE pks)
{
for(int vk=0; vk < 256; vk++)
pks[vk] = GetKeyState(vk);
}

/**
* Get the state of a keyboard key.
* \param vkey The virtual keycode of a key.
* \return The state of the key.
*/

short GetKeyState(BYTE vkey)
{
return GetAsyncKeyState(vkey); // Win API func
}

/**
* Update the keyboard state.
*/

void Update()
{
// Swap the current state with the old state
LPWINKEYBSTATE tmp = pck;
pck = pok;
pok = tmp;

// Update the current(which was old) state
GetKeyboardState(pck);
}

/**
* Find out if a key is down.
* \param vkey The virtual keycode of the key.
* \return A boolean indicating whether the key is down.
*/

bool KeyDown(BYTE vkey)
{
return KeyDown(pck, vkey);
}

/**
* Find out if a key is down
* \param pk A pointer to an array of short, representing the state of the keyboard.
* \param vkey The virtual keycode of the key.
* \return A boolean indicating whether the key is down.
*/

bool KeyDown(LPWINKEYBSTATE pk, BYTE vkey)
{
short DOWNMASK = (short)(1 << (8 * sizeof(short)-1) );


return ((pk[vkey]&DOWNMASK) != 0);
}

/**
* Find out if a key is up.
* \param vkey The virtual keycode of the key.
* \return A boolean indicating whether the key is up.
*/

bool KeyUp(BYTE vkey)
{
return KeyUp(pck, vkey);
}

/**
* Find out if a key is up.
* \param pk A pointer to an array of short, representing the state of the keyboard.
* \param vkey The virtual keycode of the key.
* \return A boolean indicating whether the key is up.
*/

bool KeyUp(LPWINKEYBSTATE pk, BYTE vkey)
{
return (!KeyDown(pk, vkey));
}

/**
* Find out if a particular key has been pressed.
* \param vkey The virtual keycode of the key.
* \return A boolean indicating whether the key has been pressed.
*/

bool KeyPressed(BYTE vkey)
{
return ( KeyUp(pok,vkey) && KeyDown(pck,vkey) ); // Was up, now is down
}

/**
* Find out if a particular key has been released.
* \param vkey The virtual keycode of the key.
* \return A boolean indicating if the key has been released.
*/

bool KeyReleased(BYTE vkey)
{
return ( KeyDown(pok,vkey) && KeyUp(pck,vkey) ); // Was down, now is up
}


BYTE GetChange()
{
// Cycle through both pck and pok arrays and
// compare pck[i] and pok[i]
// If they are different return [i]
for(int i=0; i < 256 ; i++ ){
if( pck[i] != pok[i] )
return i;
}

return (BYTE)-1;
}


/**
* Convert a virtual keycode to a character.
* \param vkey A virtual keycode to convert to a character.
* \return The character the virtual keycode represents.
*/

unsigned int VKeyToChar(BYTE vkey)
{
return ((unsigned int) MapVirtualKey(vkey,2) );
}

/**
* Convert a character to a virtual keycode.
* \param ch An unsigned char to convert to a virtual keycode.
* \return A short variable representing the virtual keycode.
*/

short CharToVKey(unsigned char ch)
{
return ((BYTE) VkKeyScan(ch) ); // You only need the low word bits
}

};

#endif



The way to use this is like so:


int main()
{
// stuff, stuff, stuff

CWinKeyboardInput::Update();
if( CWinKeyboardInput::Get().KeyDown(VK_DOWN) ){
// stuff
}
else if( CWinKeyboardInput::Get().KeyPressed(VK_UP) ){
// more stuff
}

return 0;
}




You should be updating fairly frequently. Usually, I have two main functions: "logic()", which is the game logic: user input, ai movement, so on, and then "draw()", guess what that does. :D

So usually, I would call logic() which would call Update() then process the user input, then after logic returned, I would call draw().

Share this post


Link to post
Share on other sites
Just remember the differences between keyDown, keyPressed.

Or else the program would do the function you specified many times even if the key was pressed for only a split second because in that time the game loop excecutes many more times.

(hope that made sense)

Share this post


Link to post
Share on other sites
Wow, that's a good base to start on: and remember, game programming is a long hard road. I don't want to discourage you at all, but when you start a project, keep on it untill it's finished. Maybe even post it here! :D

[Edited by - orcfan32 on July 18, 2005 10:11:50 AM]

Share this post


Link to post
Share on other sites

This topic is 4531 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this