按住箭头键进行角色移动C#.Net问题

按住箭头键进行角色移动C#.Net问题,c#,.net,wpf,animation,keypress,C#,.net,Wpf,Animation,Keypress,简言之,我只是想在WPF应用程序中围绕画布对象移动一个矩形。这里是我的KeyDown事件函数。问题是,当我长时间按住一个键时,它会一次又一次地快速启动这个函数,并将我的矩形位置代码搞乱 我的理论/逻辑: 因为当你按住键盘上的按钮时,它不会平稳地移动(在浏览器的滚动条上测试它,它开始、暂停,然后平稳地继续),我希望它启动一个窗体计时器,在UI中移动对象。然后,当KeyUp事件发生时,计时器停止 public void Window_KeyDown(object sender, KeyEventAr

简言之,我只是想在WPF应用程序中围绕画布对象移动一个矩形。这里是我的KeyDown事件函数。问题是,当我长时间按住一个键时,它会一次又一次地快速启动这个函数,并将我的矩形位置代码搞乱

我的理论/逻辑: 因为当你按住键盘上的按钮时,它不会平稳地移动(在浏览器的滚动条上测试它,它开始、暂停,然后平稳地继续),我希望它启动一个窗体计时器,在UI中移动对象。然后,当KeyUp事件发生时,计时器停止

public void Window_KeyDown(object sender, KeyEventArgs e)
{
    string msg;
    string keystr = e.Key.ToString();
    Key keyval = e.Key;


    switch (keystr)
    {
        case "Down":
            Console.WriteLine("Case 1");
            Display.Content = "Down";
            foreach (Character character in creatures)
            {
                //character.buttondown = true;
                character.Position("Down");
            }
            break;
        case "Up":
            Console.WriteLine("Case 2");
            Display.Content = "Up";
            foreach (Character character in creatures)
            {
                //character.buttondown = true;
                character.Position("Up");
            }
            break;
        case "Left":
            Console.WriteLine("Case 3");
            Display.Content = "Left";
            foreach (Character character in creatures)
            {
                //character.buttondown = true;
                character.Position("Left");
            }
            break;
        case "Right":
            Display.Content = "Right";
            foreach (Character character in creatures)
            {

                //character.buttondown = true;
                character.Position("Right");
            }
            break;
    }
}

public void Window_KeyUp(object sender, KeyEventArgs e)
{
    Display.Content = "No key is pressed.";
    foreach (Character character in creatures)
    {
        if (e.Key == Key.Right)
        {
            character.StopIt();
        }
        if (e.Key == Key.Left)
        {
            character.StopIt();
        }
        if (e.Key == Key.Up)
        {
            character.StopIt();
        }
        if (e.Key == Key.Down)
        {
            character.StopIt();
        }

    }
}
如果您需要我的矩形类代码,我将发布右箭头键按下时发生的情况,仅供参考:

  • 位置被称为

    public void Position(String Direction)
    {
    
        if (Direction == "Right")
        {
            tmr = new System.Windows.Forms.Timer();
            tmr.Interval = this.waitTime;
            tmr.Tick += new EventHandler(GoRight);
            tmr.Start();
        }
     }
    
  • 戈赖特被称为:

    public void GoRight(object sender, System.EventArgs e)
    {
        if (x < Background.ActualWidth - CharacterWidth)
        {
            if (goRight)
            {
                x += incrementSize;
                CharacterImage.SetValue(Canvas.LeftProperty, x);
    
            }
            if (x > Background.ActualWidth - CharacterWidth)
            {
                goRight = false;
                tmr.Stop();
            }
        }
    
    }
    
    我现在只学了几个月c#,所以如果可能的话,我会尽量保持它相对简单,并且只使用.net

    任何帮助都将不胜感激

    编辑::我的解决方案:


    我只是在我的开关盒上做了一个while(flag)循环。然后在案例中设置flag=false。当按下UP键时,我再次将标志设置为true。耶

    我对WPF了解不够,无法告诉你发生了什么,尽管你可能对按钮/暂停的事情是正确的。这取决于WPF如何处理按键。我的猜测是,这与大多数微软表单的工作方式相同;它有一个暂停,防止您一次键入多个字符。也许有办法解决这个问题,但我不确定

    不过我要说的是,你应该使用为游戏设计的东西。当我第一次尝试创建游戏时,我是以一种类似于你现在所做的风格来创建的,但它不起作用。您使用的是专为办公软件设计的,不会让您访问所需的内容;至少在没有战斗和解决办法的情况下。正如亚历克斯·贝斯利所建议的,调查新华社。不幸的是,这是一种过时的语言,但它是最近才消亡的。它使用的是微软公司生产的c#,功能强大,可以做任何你想做的事情,而不必与你发生冲突,一旦你掌握了窍门,它就很容易使用。看到它被杀死真是太遗憾了


    如果你想折磨自己,我建议你去我一直在尝试的路线,那就是学习C++和DirectX。这并不容易,你需要耐心地阅读多个教程(似乎没有一个教程能很好地解释任何内容)。DirectX和C++不会很快到达任何地方,所以如果你想进入一个长期的语言,他们是一个安全的赌注。

    < P>我假设你希望你的角色在最初的按键事件上移动。然后,您希望忽略任何后续的KeyDown事件,直到获得keydup事件

    因此,您可以通过检查e.IsRepeat来忽略后续的KeyDown事件,例如

    public void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.IsRepeat) return;
    
        // rest of your code...
    

    顺便说一句,滚动应用程序时观察到的不平滑移动是由键盘重复延迟引起的。您可以在键盘属性中进行设置,或者作为提示,如果您想制作游戏,我建议您使用XNA或OpenTK之类的工具。我使用MonoGame的输入和一个专门构建的输入队列为战斗机解决了一个类似的问题。WPF确实是为UI设计的。@AlexBeisley当然,但对于一些简单的游戏来说,它是可以的(即使是
    winforms
    中的一些
    GDI+
    也可以)。有一些游戏甚至是用控件制作的,比如
    DataGrid
    DataGridView
    ,很有趣。这是我初级c#类的一个项目。我真的不想进入XNA,除非我必须进入。@RyanBrady问题是,你通过学习WPF来绕开它,WPF同样复杂,目的也不同。完整的XNA可能有些过分,需要安装额外的东西,这就是为什么我倾向于选择MonoGame:您可以将引用打包到项目中。最终,复杂性也会一样糟糕,但至少会更加相关。或者,你也可以研究WPF的动画、变换等,因为如果你坚持硬的方法,它们可能会对你有所帮助。我很感激这些提示,但我正在为我的C#类工作,所以它一定是C#。没什么复杂的,但我必须假设有一些简单的方法可以使用按键输入在画布上移动矩形。@RyanBrady:有几种简单的方法,但最简单的方法是使用为应用程序设计的框架。这些都存在。您可以在WPF中执行此操作,但您可能得不到太多信息,因为任何认真执行此操作的人都将在WPF中使用OpenTK usercontrol,否则他们将完全跳过WPF。@AlexBeisley请查看我的编辑!这是有史以来最简单的修复方法。我真正需要做的就是移动一个矩形,现在它可以完美地工作了。看看我为实现这一点而编写的大量代码,您是否认为与您的方法相比过于复杂?你喜欢我在straight.net中的风格吗?@RyanBrady:这是一个很好的解决方案,祝贺你没有把它做得太长。我仍然坚持我的意见,你正在弯曲一个复杂的API来做一些它不适合做的事情,而且你的整个程序就像使用任何其他框架一样复杂,所以你最好使用一个合适的框架。不过,很高兴你成功了。啊,这正是我想要的!非常感谢。我现在用一个while循环修复了它,但是这会更好!
    public void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.IsRepeat) return;
    
        // rest of your code...