返回0数组的数组上的按位OR XOR

时间:2014-01-09 15:02:51

标签: c++ arrays sdl bitwise-operators

我希望得到一个数组,表示用户只按下所有按键(不按下,只是按下,就像你正在输入一样)。我认为最好的方法是使用3个数组 - currentKeyboard(cK),previousKeyboard(pK),并在函数中获取当前按下的键,返回键盘(rK)。

假设cK和pK看起来像这样:

 pK = [1 1 0 1 0 1]  
 cK = [0 1 1 0 1 0]

两者上的按位OR应该返回

rK = cK | rK //[1 1 1 1 1 1]

通过在rK和pK上使用按位XOR,它应该给我当前被按下的按键,这些按键之前没有被按下。

    [1 1 0 1 0 1]
XOR [1 1 1 1 1 1]
------------------
    [0 0 1 0 1 0] 

然而,当我运行我的代码时,似乎我总是回到0数组。 (我假设我的按位运算没有出错;如果我这样做,请告诉我!)

以下是获取按键的代码:

Uint8* KeyboardController::getPressedKeys()
{
    Uint8* r_Keyboard= new Uint8[283]; 
    //Loop through every SDL_SCANCODE(starting at 4) and set them to 0 in r_Keyboard
    for (int i = 0; i < 283; i++) {
        r_Keyboard[i] = 0;
    }

    //If there is a previous keyboard to compare to
    if (m_preKeyboard) {
        //Now, compare m_curKeyboard to m_preKeyboard and set 1 in r_Keyboard to any differences (OR pK and cK, then XOR pK with the resultant of OR)
        for (int i = 4; i < 283; i++) {
            r_Keyboard[i] = m_preKeyboard[i] | m_curKeyboard[i];
            r_Keyboard[i] = m_preKeyboard[i] ^ r_Keyboard[i];
        }
    }

   //Testing - am I just getting back a 0 array? 
    for (int i = 0; i < 283; i++) {
        if (r_Keyboard[i]) {
            printf("%d\n", i);
        }
    }

    return r_Keyboard;
}

我设置m_curKeyboard和m_preKeyboard的函数:

void KeyboardController::Update()
{

    if (m_curKeyboard) {
        m_preKeyboard = m_curKeyboard;
    }

    m_curKeyboard = SDL_GetKeyboardState(NULL);
}

这是主循环代码:

            bool isOn = true;
        while (isOn)
        {
            //Pump events(Needed for SDL_GetKeyboardState to work)
            SDL_PumpEvents();

            keyboard->Update();

            //Get window surface
            screenSurface = SDL_GetWindowSurface(window);

            //Fill the surface white
            SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF));

            //Update the surface
            SDL_UpdateWindowSurface(window);

            Uint8 *keysPressed = keyboard->getPressedKeys();

            if (keysPressed[SDL_SCANCODE_A]==1) {
                printf("A key pressed!\n");
            }
            if (keysPressed[SDL_SCANCODE_S]==1) {
                printf("S key was pressed!\n");
            }
            if (keysPressed[SDL_SCANCODE_ESCAPE]==1){
                isOn = false;
                //delete keysPressed;
            }


        }

现在,如果我在getPressedKeys()函数中注释掉OR或XOR行,我将从程序中获得输出。然而,它是徒劳的,因为它会垃圾输出看到一个键被按下而不是被按下。

2 个答案:

答案 0 :(得分:2)

您可以使用标准模板库轻松完成此操作。这是一个小例子。另请注意,您需要修复返回临时引用(请参阅我对该问题的评论)。移至std::vector(如本例所示)将使您的生活更轻松:

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    // previous keyboard presses
    std::vector<int> prev_kb{0, 0, 0, 1, 1, 0, 0, 0, 1, 1};

    // current keyboard presses
    std::vector<int> next_kb{0, 1, 1, 1, 1, 1, 0, 0, 1, 0};

    // combined keyboard - sized to the size of next
    std::vector<int> combined(next_kb.size());

    // apply the logical_or<int> algorithm to each keyboard press
    std::transform(
        prev_kb.begin(),
        prev_kb.end(),
        next_kb.begin(),
        combined.begin(),
        logical_or<int>());

    // print to verify it worked
    std::for_each(
        combined.begin(),
        combined.end(),
        [] (int c)
        {
            cout << c << ' ';   
        });
    return 0;
}

答案 1 :(得分:1)

我猜SDL_GetKeyboardState总是返回相同的指针。所以这个:

if (m_curKeyboard) {
    m_preKeyboard = m_curKeyboard;
}

真的是无操作。您需要分配和复制数组:

void KeyboardController::Update()
{
    if (m_curKeyboard) {
        if (!m_preKeyboard)
            m_preKeyboard = new Uint8[283];
        for (int i = 0; i < 283; i++) {
            m_preKeyboard[i] = m_curKeyboard[i];
        }
    }

    if (!m_curKeyboard)
        m_curKeyboard = new Uint8[283];
    auto curKeyboard = SDL_GetKeyboardState(NULL);
    for (int i = 0; i < 283; i++) {
        m_curKeyboard[i] = curKeyboard[i];
     }
}