在看似无关的代码更改后,Keypress检测不起作用

时间:2013-11-05 03:42:51

标签: c# xna keyboard

我正在尝试使用Enter键为我的游戏生成一个新的“地图”,但无论出于什么原因,在实施全屏后,输入检查将不再有效。我尝试删除新代码,一次只按一个键,但它仍然无效。

这是检查代码及其使用的方法,以及newMap方法:

public class Game1 : Microsoft.Xna.Framework.Game
{
    // ...

    protected override void Update(GameTime gameTime)
    {
        // ...

        // Check if Enter was pressed - if so, generate a new map
        if (CheckInput(Keys.Enter, 1))
        {
            blocks = newMap(map, blocks, console);
        }

        // ...
    }

    // Method: Checks if a key is/was pressed
    public bool CheckInput(Keys key, int checkType)
    {
        // Get current keyboard state
        KeyboardState newState = Keyboard.GetState();
        bool retType = false; // Return type

        if (checkType == 0)
        {
            // Check Type: Is key currently down?
            retType = newState.IsKeyDown(key);
        }
        else if (checkType == 1)
        {
            // Check Type: Was the key pressed?
            if (newState.IsKeyDown(key))
            {
                if (!oldState.IsKeyDown(key))
                {
                    // Key was just pressed
                    retType = true;
                }
                else
                {
                    // Key was already pressed, return false
                    retType = false;
                }
            }
        }

        // Save keyboard state
        oldState = newState;

        // Return result
        return retType;
    }

    // Method: Generate a new map
    public List<Block> newMap(Map map, List<Block> blockList, Console console)
    {
        // Create new map block coordinates
        List<Vector2> positions = new List<Vector2>();
        positions = map.generateMap(console);

        // Clear list and reallocate memory previously used up by it
        blockList.Clear();
        blockList.TrimExcess();

        // Add new blocks to the list using positions created by generateMap()
        foreach (Vector2 pos in positions)
        {
            blockList.Add(new Block() { Position = pos, Texture = dirtTex });
        }

        // Return modified list
        return blockList;
    }

    // ...
}

我从来没有触及任何上述代码,因为它破坏了 - 更改密钥似乎无法修复它。尽管如此,我还是在另一个使用WASD的Game1方法中设置了相机移动并且工作得很好。我所做的就是在这里添加几行代码:

private int BackBufferWidth = 1280; // Added these variables
private int BackBufferHeight = 800;

public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    graphics.PreferredBackBufferWidth = BackBufferWidth; // and this
    graphics.PreferredBackBufferHeight = BackBufferHeight; // this
    Content.RootDirectory = "Content";

    this.graphics.IsFullScreen = true; // and this
}

当我尝试在按下按键的情况下添加要显示的文本时,似乎即使按下了正确的按键也不会触发If。

似乎当CheckInput方法尝试检查刚刚按下的“Enter”时,它会通过第一次检查if (newState.IsKeyDown(key))(返回true)但未通过第二次if (!oldState.IsKeyDown(key))检查。 (并返回true,但不应该)

2 个答案:

答案 0 :(得分:1)

滚动答案,已更新

以下是我编写代码的方法:

public class Game1 : Microsoft.Xna.Framework.Game
{
    // ...
    protected override void Update(GameTime gameTime)
    {
        // ...
        // Check if Enter was pressed - if so, generate a new map
        if (CheckInput(Keys.Enter, 1))
        {
            blocks = newMap(map, blocks, console);
        }
        // ...
    }

    // Method: Checks if a key is/was pressed
    public bool CheckInput(Keys key, int checkType)
    { 
        KeyboardState newState = Keyboard.GetState();   // Get current keyboard state
        bool retType = false;                           // Return type

        var debug_new = newState.IsKeyDown(key);
        var debug_old = oldState.IsKeyDown(key);

        if (checkType == 0)         // Check Type: Is key currently down?
        {
            retType = newState.IsKeyDown(key);
        }
        // Should happen only once, if key wasn't pressed before
        else if (checkType == 1 && newState.IsKeyDown(key))    
        {
            // Key pressed, wasn't pressed last update  -> true. 
            // Key pressed, but was pressed last update -> false.
            retType = !oldState.IsKeydown(key); 
        }

        oldState = newState;            // Save keyboard state

        return retType;                 // Return result
    }
    // ...
}

它更短更容易阅读。

<小时/> 现在,何时/如何调用您的更新方法?当你按一下钥匙时会发生什么?它是在循环中吗?

接下来,如果您删除(或注释掉)您更改的内容(在第3个代码块中),它是否有效?

接下来,如果你在CheckInput中设置一个断点,那么每当你按下一个键时它是否会停在那里?

希望从那里你能得到更多的帮助。

修改

好的,让我们看看,何时/为什么要用CheckInput(key, 0)调用方法? 您是否试图避免双击Enter? (这些检查的重点是什么?)

另一个编辑:
是的,我知道它被称为每一帧,而不是按键。唯一的问题是我不知道经常是多少... 60 fps vs 5 fps是一个很大的区别 想知道它是否有可能以某种方式失去同步......我要做的是在那里设置一个条件调试点,打破Enter按下,释放,并好好看看你的{{1 } / newState,以确保逻辑按照您想要的方式工作(我相信使用更短的代码更容易:)

答案 1 :(得分:0)

通过向Update方法添加一行来修复它,而不是依赖于在CheckInput方法期间更新它。

更新方法:

protected override void Update(GameTime gameTime)
{
    // ...

    if (CheckInput(Keys.Enter, 1))
    {
        blocks = newMap(map, blocks, console);
    }

    oldState = Keyboard.GetState();

    // ...
}

// Method: Checks if a key is/was pressed
public bool CheckInput(Keys key, int checkType)
{
    // Get current keyboard state
    KeyboardState newState = Keyboard.GetState();
    bool retType = false; // Return type

    if (checkType == 0)
    {
        // Check Type: Is key currently down?
        if (newState.IsKeyDown(key))
        {
            retType = true;
        }
        else
        {
            retType = false;
        }
    }
    else if (checkType == 1)
    {
        // Check Type: Was the key pressed?
        if (newState.IsKeyDown(key))
        {
            if (!oldState.IsKeyDown(key))
            {
                // Key was just pressed
                retType = true;
            }
            else
            {
                // Key was already pressed, return false
                retType = false;
            }
        }
    }

    // Return result
    return retType;
}

虽然我不完全确定这是如何使它起作用的(特别是考虑到它之前没有经过这种修改而工作)但它仍然是一个解决方案。