具有私有覆盖属性的 C++ GetAsyncKeyState()
C++ GetAsyncKeyState() with private overridden attributes
我正在尝试弄清楚如何将 GetAsyncKeyState
与基于 class 的私有属性 forward
和 backwards
一起使用。我需要能够将 GetAsyncKeyState
重置为其他按键。任何的想法?
也许用其他按键覆盖 forward
和 backwards
?
#include <iostream>
#include <windows.h>
#include <string>
#include<conio.h>
using namespace std;
bool reset_defaults = false;
class Base {
protected: // OR private
int forward = VK_UP, backwards = VK_DOWN;
public: //...
}
////////////
class Move : public Base {
public:
Base def;
int move() {
while (true) {
if (GetAsyncKeyState(forward) < 0){
cout << ("forward >>>\n");
if (GetAsyncKeyState(forward) == 0){
cout << ("Stopped\n");
}
}
if (GetAsyncKeyState(VK_SPACE) < 0){break;}
}
}
int main() {
Move move;
move.move();
}
抱歉,我想我还没有完全理解这一切的逻辑。
PS更新:
如何覆盖 baseKeys 值:
class MovementKeys {
protected:
int baseKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right){
default_key_forward = VK_UP;
default_key_backward = VK_DOWN;
default_key_left = VK_LEFT;
default_key_right = VK_RIGHT;
}
public:
int definedCommand(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
while (reset_defaults == false)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(default_key_forward) < 0)
{
cout << ("forward\n");
}
if (GetAsyncKeyState(default_key_backward) < 0)
{
court << ("backwards\n");
}
if (GetAsyncKeyState(default_key_left) < 0)
{
cout << ("left\n");
}
if (GetAsyncKeyState(default_key_right) < 0)
{
cout << ("right\n");
}
if (GetAsyncKeyState(VK_SPACE) < 0) { break; }
}
return 0;
}
int derived_newKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
return baseKeys(default_key_forward, default_key_backward, default_key_left, default_key_right);
}
您可能想使用成员变量来存储键。您可以在构造函数中设置变量(默认值或更改值),而不是使用新键派生 class,并且稍后还可以更改键分配。
您可能想创建一个单独的 class,它对事件做出反应。
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
class World {
public:
void forward() { y--; };
void backward() { y++; };
void left() { x--; };
void right() { x++; };
private:
int x = 0;
int y = 0;
};
class MovementKeys {
// member variables
private:
// keep reference to world instead of copy; main() has to make sure World object outlives MovementKeys object
World& world;
int key_forward;
int key_backward;
int key_left;
int key_right;
public:
// constructor, which only sets world, but keeps the keys at their default settings
//
// world has to be initialized before the constructor function body
// as references have no default value
// put initialization in member initialization list
MovementKeys(World& w) : world(w)
{
key_forward = VK_UP;
key_backward = VK_DOWN;
key_left = VK_LEFT;
key_right = VK_RIGHT;
}
// constructor which modifies keys
MovementKeys(World& w, int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : world(w)
{
changeKeys(change_key_forward, change_key_backward, change_key_left, change_key_right);
}
// command loop controlled by keys
int definedCommand()
{
while (true)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(key_forward) < 0)
{
cout << ("forward\n");
world.forward();
}
if (GetAsyncKeyState(key_backward) < 0)
{
cout << ("backwards\n");
world.backward();
}
if (GetAsyncKeyState(key_left) < 0)
{
cout << ("left\n");
world.left();
}
if (GetAsyncKeyState(key_right) < 0)
{
cout << ("right\n");
world.right();
}
// optionally change keys from within while loop
if (GetAsyncKeyState(VK_BACK) < 0)
{
key_forward = VK_RETURN;
}
if (GetAsyncKeyState(VK_SPACE) < 0)
{
break;
}
}
return 0;
}
// function for changing the keys stored in the member variables
// can be called by constructor or externally
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
key_forward = change_key_forward;
key_backward = change_key_backward;
key_left = change_key_left;
key_right = change_key_right;
}
};
int main()
{
World earth;
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move(earth);
move.definedCommand();
// use custom keys, share same world, declares local variable and constructs MovementKeys object called move2
// static_cast<int>() with a letter in a literal char parameter works, because the VK_ values of letter keys are the actual ASCII values (on purpose by Microsoft, I would assume)
MovementKeys move2(earth, static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
move2.definedCommand();
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand();
// run first one again for the fun of it
move.definedCommand();
}
或者仅传递 World&,它在 definedCommand
中使用(同时能够使用多个世界):
class World {
// ...
};
class MovementKeys {
// member variables without world, we can also put default value here
private:
int key_forward = VK_UP;
int key_backward = VK_DOWN;
int key_left = VK_LEFT;
int key_right = VK_RIGHT;
public:
// default constructor with no parameters, delegate to other constructor
// delegating not necessary, as the default values are set above anyway; just demonstrating various techniques for initializing member variables
MovementKeys() : MovementKeys(VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT) {};
// constructor which modifies keys, put everything in member initialization list
MovementKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : key_forward(change_key_forward), key_backward(change_key_backward), key_left(change_key_left), key_right(change_key_right) {};
// command loop controlled by keys, pass World& here as parameter
int definedCommand(World& world)
{
while (true)
{
// ...
}
return 0;
}
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
// ...
}
};
int main()
{
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move;
// use custom keys, declares local variable and constructs MovementKeys object called move2
MovementKeys move2(static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
MovementKeys defaultMenuKeys;
World earth;
World moon;
World menu; // between moving in worlds, we want to control some settings in a menu
move.definedCommand(earth);
move2.definedCommand(earth);
move2.definedCommand(moon);
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand(earth);
defaultMenuKeys.definedCommand(menu);
// run first one again for the fun of it
move.definedCommand(moon);
}
你可以引入一个 (class
) enum
和状态列表,为什么 definedCommand()
returns:
// outside or can be put into MovementKeys and henceforth used as MovementKeys::ReturnReason
class enum ReturnReason { EXIT, NEWKEYS, SHOWMENU, SWITCHWORLD };
// in class MovementKeys
ReturnReason definedCommand() {
// ...
return NEWKEYS;
// ...
return EXIT;
// ...
return SHOWMENU;
// ...
}
// in main()
ReturnReason r = definedCommand();
if (r == NEWKEYS)
move2.changeKeys(...);
else if (r == EXIT)
return 0;
如果您还使用 'trick' 来控制菜单,现在对 World
使用虚拟继承可能是有意义的。由于 normal World
和菜单 World
的反应可能完全不同。 (基础 class(祖先)将是 World
,它被 MovementKeys
识别。您的实际 World
是派生(子)classes 的对象,具有更具体的行为。
然后可以调用 definedCommand
并且 运行 与基数 class World
.
的任何派生 class
我正在尝试弄清楚如何将 GetAsyncKeyState
与基于 class 的私有属性 forward
和 backwards
一起使用。我需要能够将 GetAsyncKeyState
重置为其他按键。任何的想法?
也许用其他按键覆盖 forward
和 backwards
?
#include <iostream>
#include <windows.h>
#include <string>
#include<conio.h>
using namespace std;
bool reset_defaults = false;
class Base {
protected: // OR private
int forward = VK_UP, backwards = VK_DOWN;
public: //...
}
////////////
class Move : public Base {
public:
Base def;
int move() {
while (true) {
if (GetAsyncKeyState(forward) < 0){
cout << ("forward >>>\n");
if (GetAsyncKeyState(forward) == 0){
cout << ("Stopped\n");
}
}
if (GetAsyncKeyState(VK_SPACE) < 0){break;}
}
}
int main() {
Move move;
move.move();
}
抱歉,我想我还没有完全理解这一切的逻辑。
PS更新:
如何覆盖 baseKeys 值:
class MovementKeys {
protected:
int baseKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right){
default_key_forward = VK_UP;
default_key_backward = VK_DOWN;
default_key_left = VK_LEFT;
default_key_right = VK_RIGHT;
}
public:
int definedCommand(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
while (reset_defaults == false)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(default_key_forward) < 0)
{
cout << ("forward\n");
}
if (GetAsyncKeyState(default_key_backward) < 0)
{
court << ("backwards\n");
}
if (GetAsyncKeyState(default_key_left) < 0)
{
cout << ("left\n");
}
if (GetAsyncKeyState(default_key_right) < 0)
{
cout << ("right\n");
}
if (GetAsyncKeyState(VK_SPACE) < 0) { break; }
}
return 0;
}
int derived_newKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
return baseKeys(default_key_forward, default_key_backward, default_key_left, default_key_right);
}
您可能想使用成员变量来存储键。您可以在构造函数中设置变量(默认值或更改值),而不是使用新键派生 class,并且稍后还可以更改键分配。
您可能想创建一个单独的 class,它对事件做出反应。
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
class World {
public:
void forward() { y--; };
void backward() { y++; };
void left() { x--; };
void right() { x++; };
private:
int x = 0;
int y = 0;
};
class MovementKeys {
// member variables
private:
// keep reference to world instead of copy; main() has to make sure World object outlives MovementKeys object
World& world;
int key_forward;
int key_backward;
int key_left;
int key_right;
public:
// constructor, which only sets world, but keeps the keys at their default settings
//
// world has to be initialized before the constructor function body
// as references have no default value
// put initialization in member initialization list
MovementKeys(World& w) : world(w)
{
key_forward = VK_UP;
key_backward = VK_DOWN;
key_left = VK_LEFT;
key_right = VK_RIGHT;
}
// constructor which modifies keys
MovementKeys(World& w, int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : world(w)
{
changeKeys(change_key_forward, change_key_backward, change_key_left, change_key_right);
}
// command loop controlled by keys
int definedCommand()
{
while (true)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(key_forward) < 0)
{
cout << ("forward\n");
world.forward();
}
if (GetAsyncKeyState(key_backward) < 0)
{
cout << ("backwards\n");
world.backward();
}
if (GetAsyncKeyState(key_left) < 0)
{
cout << ("left\n");
world.left();
}
if (GetAsyncKeyState(key_right) < 0)
{
cout << ("right\n");
world.right();
}
// optionally change keys from within while loop
if (GetAsyncKeyState(VK_BACK) < 0)
{
key_forward = VK_RETURN;
}
if (GetAsyncKeyState(VK_SPACE) < 0)
{
break;
}
}
return 0;
}
// function for changing the keys stored in the member variables
// can be called by constructor or externally
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
key_forward = change_key_forward;
key_backward = change_key_backward;
key_left = change_key_left;
key_right = change_key_right;
}
};
int main()
{
World earth;
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move(earth);
move.definedCommand();
// use custom keys, share same world, declares local variable and constructs MovementKeys object called move2
// static_cast<int>() with a letter in a literal char parameter works, because the VK_ values of letter keys are the actual ASCII values (on purpose by Microsoft, I would assume)
MovementKeys move2(earth, static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
move2.definedCommand();
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand();
// run first one again for the fun of it
move.definedCommand();
}
或者仅传递 World&,它在 definedCommand
中使用(同时能够使用多个世界):
class World {
// ...
};
class MovementKeys {
// member variables without world, we can also put default value here
private:
int key_forward = VK_UP;
int key_backward = VK_DOWN;
int key_left = VK_LEFT;
int key_right = VK_RIGHT;
public:
// default constructor with no parameters, delegate to other constructor
// delegating not necessary, as the default values are set above anyway; just demonstrating various techniques for initializing member variables
MovementKeys() : MovementKeys(VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT) {};
// constructor which modifies keys, put everything in member initialization list
MovementKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : key_forward(change_key_forward), key_backward(change_key_backward), key_left(change_key_left), key_right(change_key_right) {};
// command loop controlled by keys, pass World& here as parameter
int definedCommand(World& world)
{
while (true)
{
// ...
}
return 0;
}
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
// ...
}
};
int main()
{
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move;
// use custom keys, declares local variable and constructs MovementKeys object called move2
MovementKeys move2(static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
MovementKeys defaultMenuKeys;
World earth;
World moon;
World menu; // between moving in worlds, we want to control some settings in a menu
move.definedCommand(earth);
move2.definedCommand(earth);
move2.definedCommand(moon);
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand(earth);
defaultMenuKeys.definedCommand(menu);
// run first one again for the fun of it
move.definedCommand(moon);
}
你可以引入一个 (class
) enum
和状态列表,为什么 definedCommand()
returns:
// outside or can be put into MovementKeys and henceforth used as MovementKeys::ReturnReason
class enum ReturnReason { EXIT, NEWKEYS, SHOWMENU, SWITCHWORLD };
// in class MovementKeys
ReturnReason definedCommand() {
// ...
return NEWKEYS;
// ...
return EXIT;
// ...
return SHOWMENU;
// ...
}
// in main()
ReturnReason r = definedCommand();
if (r == NEWKEYS)
move2.changeKeys(...);
else if (r == EXIT)
return 0;
如果您还使用 'trick' 来控制菜单,现在对 World
使用虚拟继承可能是有意义的。由于 normal World
和菜单 World
的反应可能完全不同。 (基础 class(祖先)将是 World
,它被 MovementKeys
识别。您的实际 World
是派生(子)classes 的对象,具有更具体的行为。
definedCommand
并且 运行 与基数 class World
.