Holding Arrow Keys Down For Character Movement C# .Net ISSUES

匿名 (未验证) 提交于 2019-12-03 02:16:02

问题:

So in short i'm simply trying to move a rectangle around a Canvas object in a WPF application. What i have here is my KeyDown event function. The problem is, when i hold a key down for long, it launches this function over and over again rapidly and screws up my rectangle location code.

My theory/logic behind it: BECAUSE WHEN YOU HOLD A BUTTON DOWN ON A KEYBOARD IT DOES NOT MOVE SMOOTHLY (TEST IT ON THE SCROLL BAR IN YOUR BROWSER, IT STARTS, pauses, THEN CONTINUES SMOOTHLY), i want it to start a forms timer that moves the object in the UI. Then when the KeyUp event happens, the timer STOPS.

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();         }      } } 

and just for reference if you need my rectangle class code i'll post what happens if the RIGHT arrow key is pressed:

  1. Position is called

    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();     }  } 
  2. GoRight is called:

    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();         }     }  } 

Finally, StopIt is called in the KeyUp event:

public void StopIt() {     tmr.Stop();     goRight = true;     goLeft = true;     goUp = true;     goDown = true; } 

I've only been learning c# for a couple months now so i'm trying to keep it relatively simple if possible, and only use .net.

Any help would be appreciated!!

EDIT:: MY SOLUTION:

I simply made a while(flag) loop around my switch case. Then i set flag = false within the cases. When Key UP is pressed i set flag equal to true again. YAY

回答1:

I assume that you want your character to move on the initial KeyDown event. Then you want to ignore any subsequent KeyDown events until you get a KeyUp event.

So you can ignore the subsequent KeyDown events by checking e.IsRepeat e.g.

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

BTW, the non-smooth movement that you observe when scrolling an application is caused by the keyboard repeat delay. You can set this in the keyboard properties or though http://msdn.microsoft.com/en-us/library/system.windows.systemparameters.keyboarddelay.aspx



回答2:

I don't know enough about WPF to tell you what is going on, though you may be correct about the push button/pause thing. It depends on how WPF treats keypresses. My guess would be that it does so the same way most Microsoft forms work; it has a pause to keep you from typing multiple characters at a time. There may be a way around this but I'm not sure.

What I will say though is that you should use something designed for games. When I first tried creating games I did so in a style similar to what you are doing and it doesn't work. What you are using is designed for office software and will not give you access to what you need; at least not without fighting and workarounds. As was suggested by Alex Beisley look into XNA. It's a dead language unfortunately but it died fairly recently. It uses c#, was made by Microsoft, and is powerful enough to do what you want without fighting you and easy enough to use once you get the hang of it. It's a shame to see it killed off.

If you want to torture yourself then I'd suggest going the route I've been trying which is to learn C++ and DirectX. It is not easy and you will need to be patient and go through multiple tutorials (no one tutorial seems to do a good job explaining anything). DirectX and C++ are not going anywhere soon, so they are a safe bet if you are looking to get into a long term language.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!