Basic game loop in C++

Started by
6 comments, last by orcfan32 18 years, 9 months ago
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
Advertisement
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.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
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]
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)
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

-IVHumble Student

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 and pok		// If they are different return 		for(int i=0; i < 256 ; i++ ){			if( pck != pok )				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().
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
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)
______________________TradeMark Designs
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]
The best thing to do is just choose whatever you think you'd prefer, and go for it. -Promit

This topic is closed to new replies.

Advertisement