在KeyDown事件之后删除延迟? [英] Removing the delay after KeyDown event?

查看:123
本文介绍了在KeyDown事件之后删除延迟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public void MainForm_KeyDown(object sender,KeyEventArgs e) 
{
if(e.KeyCode == Keys.Up)
{
Player.MoveUp();
}
}

一旦我按下,播放器立即移动一步向下箭头,然后在开始平稳移动之前暂停一段短时间。为什么会这样?如何防止它?

解决方案

建议的复本不正确,不幸的是。它不会忽略重复的 KeyDown 事件,因此将逐渐增加每个密钥大小写处理方向上的delta值。它也不会立即响应按键(即在第一个定时器计时之前不会发生任何动作)。



这个答案是按箭头键降低字符移动C#.Net ISSUES 解释了如何忽略后续的 KeyDown 事件,



换句话说,我找不到一个重复的问题,实际上正确地回答了你的问题。所以…



你想做的基本技巧是:


  1. t移动实际键输入。而是使用自己的定时逻辑来移动对象。

  2. 而不是使用 KeyDown 事件来实际移动对象,请使用它设置一个运动方向,然后由您的计时逻辑进行处理。

有多种方法可以完成此操作。一个版本将如下所示:

  private bool _moveUp; 
private bool _moveDown;
private bool _moveLeft;
private bool _moveRight;

//如果您喜欢,您可以在Winforms Designer中添加Timer;
//可以同时配置Interval属性,沿着
//与Tick事件处理程序,在此简化非Des​​igner代码。
private System.Windows.Forms.Timer _movementTimer = new Timer {Interval = 100};

public MainForm()
{
InitializeComponent();

_movementTimer.Tick + = movementTimer_Tick;
}

private void movingTimer_Tick(object sender,EventArgs e)
{
_DoMovement();
}

private void _DoMovement()
{
if(_moveLeft)Player.MoveLeft();
if(_moveRight)Player.MoveRight();
if(_moveUp)Player.MoveUp();
if(_moveDown)Player.MoveDown();
}

//您当然可以重写OnKeyDown()方法,而
//假设处理程序在Form子类中生成
//事件。
public void MainForm_KeyDown(object sender,KeyEventArgs e)
{
if(e.IsRepeat)
{
//忽略键重复...让定时器句柄那个
返回;
}

switch(e.KeyCode)
{
case Keys.Up:
_moveUp = true;
break;
case Keys.Down:
_moveDown = true;
break;
case Keys.Left:
_moveLeft = true;
break;
case Keys.Right:
_moveRight = true;
break;
}

_DoMovement();
_movementTimer.Start();
}

public void MainForm_KeyUp(object sender,KeyEventArgs e)
{
switch(e.KeyCode)
{
case Keys。 Up:
_moveUp = false;
break;
case Keys.Down:
_moveDown = false;
break;
case Keys.Left:
_moveLeft = false;
break;
case Keys.Right:
_moveRight = false;
break;
}

if(!(_ moveUp || _moveDown || _moveLeft || _moveRight))
{
_movementTimer.Stop();
}
}

请注意,.NET中的定时器对象有限解析度。我显示上面的100 ms(每秒10次)的间隔(与其他问题的答案相同),这与您将要可靠地获得的更新频率相同。即使这样,定时器的 Tick 事件可能不会(也可能不会)在100 ms的间隔内完全上升。会有一些变化来回。但是对于一个基本的游戏来说,这将是足够接近的。



如果你需要更多的精度,那么你必须在某个地方实现自己的状态轮询和动画循环。这是一个完整的其他球蜡。 :)


When I hold a key in my game to move my player:

public void MainForm_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Up)
    {
        Player.MoveUp();
    }
}

The player instantly moves one step as soon as I press the down arrow, and then pauses for a short duration before starting to smoothly move again. Why's this? How can I prevent it?

解决方案

The answer in the proposed duplicate is incorrect, unfortunately. It doesn't ignore repeated KeyDown events, and so will gradually increase the "delta" value in the direction being handled by each key case. It also doesn't respond to the keypress immediately (i.e. no action happens until the first timer tick).

This answer to Holding Arrow Keys Down For Character Movement C# .Net ISSUES explains how to ignore the subsequent KeyDown events, but doesn't explain how then your character would move.

In other words, I couldn't find a duplicate question that actually correctly answers your question. So…

The basic technique you want to do is:

  1. Don't move on the actual key input. Instead, generate your own timing logic that will move the object.
  2. Instead of using the KeyDown event to actually move the object, use it to set a movement direction, which is then processed by your timing logic.

There are a variety of ways to accomplish this. One version would look like this:

private bool _moveUp;
private bool _moveDown;
private bool _moveLeft;
private bool _moveRight;

// You can add the Timer in the Winforms Designer instead if you like;
// The Interval property can be configured there at the same time, along
// with the Tick event handler, simplifying the non-Designer code here.
private System.Windows.Forms.Timer _movementTimer = new Timer { Interval = 100 };

public MainForm()
{
    InitializeComponent();

    _movementTimer.Tick += movementTimer_Tick;
}

private void movementTimer_Tick(object sender, EventArgs e)
{
    _DoMovement();
}

private void _DoMovement()
{
    if (_moveLeft) Player.MoveLeft();
    if (_moveRight) Player.MoveRight();
    if (_moveUp) Player.MoveUp();
    if (_moveDown) Player.MoveDown();
}

// You could of course override the OnKeyDown() method instead,
// assuming the handler is in the Form subclass generating the
// the event.
public void MainForm_KeyDown(object sender, KeyEventArgs e)
{
    if (e.IsRepeat)
    {
        // Ignore key repeats...let the timer handle that
        return;
    }

    switch (e.KeyCode)
    {
    case Keys.Up:
        _moveUp = true;
        break;
    case Keys.Down:
        _moveDown = true;
        break;
    case Keys.Left:
        _moveLeft = true;
        break;
    case Keys.Right:
        _moveRight = true;
        break;
    }

    _DoMovement();
    _movementTimer.Start();
}

public void MainForm_KeyUp(object sender, KeyEventArgs e)
{
    switch (e.KeyCode)
    {
    case Keys.Up:
        _moveUp = false;
        break;
    case Keys.Down:
        _moveDown = false;
        break;
    case Keys.Left:
        _moveLeft = false;
        break;
    case Keys.Right:
        _moveRight = false;
        break;
    }

    if (!(_moveUp || _moveDown || _moveLeft || _moveRight))
    {
        _movementTimer.Stop();
    }
}

Do note that the timer objects in .NET have limited resolution. I show an interval of 100 ms (10 times per second) above (same as in the other question's answer), and this is about as frequent an update as you're going to reliably get. Even then, the timer's Tick event may not (and probably won't) be raised on exactly 100 ms intervals. There will be some variation back and forth. But it will be close enough for a basic game.

If you need more precision than that, you will have to implement your own state-polling-and-animation loop somewhere. That's a whole other ball o' wax. :)

这篇关于在KeyDown事件之后删除延迟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆