J
Joshua Weston
I am new to C++ and I am very interested in becoming proficient. This post
is two-fold. One, I am having problems with this small test program. It is
meant to allow user input to control a "@" character as it moves around the
screen. I understand that it does not have error checking. The problem I am
having is that when I hit the arrow key it moves TWO spaces instead of one.
As I understand it, the FlushConsoleInputBuffer(handle) should prevent
this.... The strange thing is, at one point, it did! The first time I
compiled and ran this it seemed to work. I am using DevCpp 4.9.8.1. Now,
when I call the FlushConsoleInputBuffer it doesn't seem to be working. Is
there a problem with my code? Does anyone have any ideas? The SECOND part of
this, my first post of what I am sure will be an illustrious career (ya
sure), is to ask those who are willing to help me with the FlushConsole
problem to glance over my comments to make sure I am grasping the logic
correctly. All I ask is for any glaring problems to be pointed out. If
anyone can help me with this I would VERY much appreciate it. I am picking
this up quickly and maybe at some point I can return the favor. Code follows
below.
Thanks, Josh Weston
// *************** This is the beginning of main.cpp
#include <stdlib.h>
#include "Manipulation.h"
using namespace std;
HANDLE hInput, hOutput;
void DrawPlayer(PLAYER player, int Draw){
// This is the basis of OOP. When I need to change the player
representation on the screen,
// for any reason, whether to move the character or to erase the old. It
is a logical
// categorization of data. It is much easier, when you get used to it,
to call a function
// that does multiple things. Anytime I need to change the PR I just
send the coordinates
// and put in the DRAW type and it will do what I ask. Having written
the code for this
// function I can save much later on.
if(Draw){
SetConsoleCursorPosition(hOutput, player.position);
cout << "@";
} //end DRAW condition - sets "@" character to COORD of the passed
player.position - Not Referenced
else {
SetConsoleCursorPosition(hOutput, player.position);
cout << " ";
} //end ERASE condition - sets " " and erases old position
} // end DrawPlayer Function - Does not return a value, simply performs
onscreen manipulation
void MovePlayer(PLAYER &player){
// This is the function called within the endless loop in the Main()
function. First thing
// to notice is that the variable is referenced. the ampersand (&)
character means that
// when I pass in the "player" parameter in the Main() function I am not
passing along a COPY
// of the "player" to be manipulated and then destroyed when the
function ends. I am passing a
// REFERENCE to the actual location (address) of the "player" struct,
declared in the Main()
// code, so that when the function ends, the data is stored in the
"player" struct that was
// declared in Main(). The endless game loop that exists in Main()
passes the new "player"
// struct data right back into MovePlayer and the whole thing happens
again.
INPUT_RECORD InputRecord; // This variable is actually a structure
that stores player input DATA
// which is compatible with the EVENT
recognition needed to take input
// DATA from the player input BUFFER and
translate it into WINDOWS
// recognized Virtual KeyCodes or Mouse
Events that the code can
// manipulate and cause appropriate onscreen
events.
DWORD Events =0; // The ReadConsoleInput(1,2,3,4) parameters,
seen later, will call for a
// a 32bit variable in the 4th place of the
parameter to designate the
// number of events that have taken place.
For our purposes, it is only one.
// However, if I wanted to be able to hold
down "alt" and then press an arrow key
// so that the player would "run" in a
certain direction, I would want to
// look for more than one event during
ReadConsoleInput.
ReadConsoleInput(hInput, &InputRecord , 1 , &Events); // Reads user
input and stores it into InputRecord for
// later use. I
must find out if the program pauses here
// while waiting
for input or loops continuously while
// waiting for
input, which is also possible.
if (InputRecord.EventType == MOUSE_EVENT){ // The first condition the
conditional statements looks for is a
// Mouse Event. It Does not
detect the specific type.
if(InputRecord.Event.MouseEvent.dwButtonState ==
FROM_LEFT_1ST_BUTTON_PRESSED){ // We are only looking for
// a Left Button Click
DrawPlayer(player , ERASE); // First, we must erase the existing
representation. This is done now because
// "player" still contains the
COORDinates from the last loop.
player.position.X = InputRecord.Event.MouseEvent.dwMousePosition.X;
// Adjust the X-Axis based upon the click
player.position.Y = InputRecord.Event.MouseEvent.dwMousePosition.Y;
// Adjust the Y-Axis based upon the click
DrawPlayer(player, DRAW); // There! We have re-drawn the
representation based upon the Mouse Click COORDinates.
}} //end Mouse Input conditional statement. Work on conventions.
if (InputRecord.EventType == KEY_EVENT){ // Looking at all possible KEY
events now.
if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT){
DrawPlayer(player , ERASE);
player.position.X++;
DrawPlayer(player , DRAW);
} // End RIGHT move.
else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_LEFT){
DrawPlayer(player , ERASE);
player.position.X--;
DrawPlayer(player , DRAW);
} // End Left move.
else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_UP){
DrawPlayer(player , ERASE);
player.position.Y--;
DrawPlayer(player , DRAW);
} // End UP move.
else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_DOWN){
DrawPlayer(player , ERASE);
player.position.Y++;
DrawPlayer(player , DRAW);
} // End DOWN move.
} // end KEY EVENT conditional statement
FlushConsoleInputBuffer (hInput); // Prevents strange behavior.
} // end MovePlayer function
int main()
{
PLAYER player; // Builds the PLAYER struct that is referenced by
MovePlayer
hInput = GetStdHandle(STD_INPUT_HANDLE); // Sets these HANDLES to
INPUT and OUTPUT HANDLES to "handle" the
hOutput = GetStdHandle(STD_OUTPUT_HANDLE); // data stream to the
console window.
SetConsoleMode(hInput, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); //
Lets the following code know that we will
//
be handling Keyboard AND Mouse input.
player.position.X = SW / 2; // Start off in the middle.
player.position.Y = SH / 2;
while (1){
MovePlayer(player);
} // end While loop
system("pause");
return 0;
} //end Main() This should do it... lets see.
// ****************** THIS IS THE END OF main.cpp
// ******************** This is the beginning of Manipulation.h
#include <iostream>
#include <windows.h>
using namespace std;
#define NORTH 0 //Direction Manipulation Standards
#define SOUTH 2
#define EAST 1
#define WEST 3
#define DRAW 1 //Drawing Manipulation Standards
#define ERASE 0
#define SW 79 //Default Screen Size
#define SH 24
struct PLAYER {
COORD position;
int direction;
};
void DrawPlayer (PLAYER player, int Draw);
void MovePlayer (PLAYER &player);
// *********************** end of Manipulation.h
is two-fold. One, I am having problems with this small test program. It is
meant to allow user input to control a "@" character as it moves around the
screen. I understand that it does not have error checking. The problem I am
having is that when I hit the arrow key it moves TWO spaces instead of one.
As I understand it, the FlushConsoleInputBuffer(handle) should prevent
this.... The strange thing is, at one point, it did! The first time I
compiled and ran this it seemed to work. I am using DevCpp 4.9.8.1. Now,
when I call the FlushConsoleInputBuffer it doesn't seem to be working. Is
there a problem with my code? Does anyone have any ideas? The SECOND part of
this, my first post of what I am sure will be an illustrious career (ya
sure), is to ask those who are willing to help me with the FlushConsole
problem to glance over my comments to make sure I am grasping the logic
correctly. All I ask is for any glaring problems to be pointed out. If
anyone can help me with this I would VERY much appreciate it. I am picking
this up quickly and maybe at some point I can return the favor. Code follows
below.
Thanks, Josh Weston
// *************** This is the beginning of main.cpp
#include <stdlib.h>
#include "Manipulation.h"
using namespace std;
HANDLE hInput, hOutput;
void DrawPlayer(PLAYER player, int Draw){
// This is the basis of OOP. When I need to change the player
representation on the screen,
// for any reason, whether to move the character or to erase the old. It
is a logical
// categorization of data. It is much easier, when you get used to it,
to call a function
// that does multiple things. Anytime I need to change the PR I just
send the coordinates
// and put in the DRAW type and it will do what I ask. Having written
the code for this
// function I can save much later on.
if(Draw){
SetConsoleCursorPosition(hOutput, player.position);
cout << "@";
} //end DRAW condition - sets "@" character to COORD of the passed
player.position - Not Referenced
else {
SetConsoleCursorPosition(hOutput, player.position);
cout << " ";
} //end ERASE condition - sets " " and erases old position
} // end DrawPlayer Function - Does not return a value, simply performs
onscreen manipulation
void MovePlayer(PLAYER &player){
// This is the function called within the endless loop in the Main()
function. First thing
// to notice is that the variable is referenced. the ampersand (&)
character means that
// when I pass in the "player" parameter in the Main() function I am not
passing along a COPY
// of the "player" to be manipulated and then destroyed when the
function ends. I am passing a
// REFERENCE to the actual location (address) of the "player" struct,
declared in the Main()
// code, so that when the function ends, the data is stored in the
"player" struct that was
// declared in Main(). The endless game loop that exists in Main()
passes the new "player"
// struct data right back into MovePlayer and the whole thing happens
again.
INPUT_RECORD InputRecord; // This variable is actually a structure
that stores player input DATA
// which is compatible with the EVENT
recognition needed to take input
// DATA from the player input BUFFER and
translate it into WINDOWS
// recognized Virtual KeyCodes or Mouse
Events that the code can
// manipulate and cause appropriate onscreen
events.
DWORD Events =0; // The ReadConsoleInput(1,2,3,4) parameters,
seen later, will call for a
// a 32bit variable in the 4th place of the
parameter to designate the
// number of events that have taken place.
For our purposes, it is only one.
// However, if I wanted to be able to hold
down "alt" and then press an arrow key
// so that the player would "run" in a
certain direction, I would want to
// look for more than one event during
ReadConsoleInput.
ReadConsoleInput(hInput, &InputRecord , 1 , &Events); // Reads user
input and stores it into InputRecord for
// later use. I
must find out if the program pauses here
// while waiting
for input or loops continuously while
// waiting for
input, which is also possible.
if (InputRecord.EventType == MOUSE_EVENT){ // The first condition the
conditional statements looks for is a
// Mouse Event. It Does not
detect the specific type.
if(InputRecord.Event.MouseEvent.dwButtonState ==
FROM_LEFT_1ST_BUTTON_PRESSED){ // We are only looking for
// a Left Button Click
DrawPlayer(player , ERASE); // First, we must erase the existing
representation. This is done now because
// "player" still contains the
COORDinates from the last loop.
player.position.X = InputRecord.Event.MouseEvent.dwMousePosition.X;
// Adjust the X-Axis based upon the click
player.position.Y = InputRecord.Event.MouseEvent.dwMousePosition.Y;
// Adjust the Y-Axis based upon the click
DrawPlayer(player, DRAW); // There! We have re-drawn the
representation based upon the Mouse Click COORDinates.
}} //end Mouse Input conditional statement. Work on conventions.
if (InputRecord.EventType == KEY_EVENT){ // Looking at all possible KEY
events now.
if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT){
DrawPlayer(player , ERASE);
player.position.X++;
DrawPlayer(player , DRAW);
} // End RIGHT move.
else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_LEFT){
DrawPlayer(player , ERASE);
player.position.X--;
DrawPlayer(player , DRAW);
} // End Left move.
else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_UP){
DrawPlayer(player , ERASE);
player.position.Y--;
DrawPlayer(player , DRAW);
} // End UP move.
else if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_DOWN){
DrawPlayer(player , ERASE);
player.position.Y++;
DrawPlayer(player , DRAW);
} // End DOWN move.
} // end KEY EVENT conditional statement
FlushConsoleInputBuffer (hInput); // Prevents strange behavior.
} // end MovePlayer function
int main()
{
PLAYER player; // Builds the PLAYER struct that is referenced by
MovePlayer
hInput = GetStdHandle(STD_INPUT_HANDLE); // Sets these HANDLES to
INPUT and OUTPUT HANDLES to "handle" the
hOutput = GetStdHandle(STD_OUTPUT_HANDLE); // data stream to the
console window.
SetConsoleMode(hInput, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT); //
Lets the following code know that we will
//
be handling Keyboard AND Mouse input.
player.position.X = SW / 2; // Start off in the middle.
player.position.Y = SH / 2;
while (1){
MovePlayer(player);
} // end While loop
system("pause");
return 0;
} //end Main() This should do it... lets see.
// ****************** THIS IS THE END OF main.cpp
// ******************** This is the beginning of Manipulation.h
#include <iostream>
#include <windows.h>
using namespace std;
#define NORTH 0 //Direction Manipulation Standards
#define SOUTH 2
#define EAST 1
#define WEST 3
#define DRAW 1 //Drawing Manipulation Standards
#define ERASE 0
#define SW 79 //Default Screen Size
#define SH 24
struct PLAYER {
COORD position;
int direction;
};
void DrawPlayer (PLAYER player, int Draw);
void MovePlayer (PLAYER &player);
// *********************** end of Manipulation.h