http://www.microsoft.com/windowsxp/using/accessibility/characterrepeatrate.mspx-Windows中有一个用于设置重复延迟的选项。这意味着如果一个人持续按下该键,则在第一次击键与其他击键之间的延迟。我正在创建一种游戏,我需要摆脱这种“功能”。
到目前为止,我设法找到了这种方法:
[DllImport("user32.dll")]
static extern ushort GetAsyncKeyState(int vKey);
public static bool IsKeyPushedDown(Keys keyData)
{
return 0 != (GetAsyncKeyState((int)keyData) & 0x8000);
}
Run Code Online (Sandbox Code Playgroud)
但是方法IsKeyPushedDown会在调用函数的时刻发现按键是否被按下-因此我需要一个循环来测试按键是否按下。问题是它仍然不能捕获所有击键-我猜循环太慢。
第二选择是重写ProcessCmdKey:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// processing keys
if (keyData == Keys.Left || keyData == Keys.Right || keyData == Keys.Up || keyData == Keys.Down)
{
return true;
}
else
{
return base.ProcessCmdKey(ref msg, keyData);
}
}
Run Code Online (Sandbox Code Playgroud)
这确实很好,但是会受到重复延迟的影响,因此游戏中怪物的移动就像:
我的问题有解决方案吗?谢谢
编辑:我通过结合两个程序解决了问题。但这是非常丑陋的解决方案。我仍然希望有更好的解决方案。
您应该进行处理KeyDown,KeyUp而不是ProcessCmdKey想要更大程度地控制按下和释放键之间的时间。
在这种情况下,最简单的操作就是在窗体上放置一个计时器来移动怪物。KeyDown发射时启用计时器(并设置某种指示变量如何移动怪物的变量或deltaX和deltaY),然后在KeyUp发射时停止计时器。
编辑
举个例子(非常准)
public class MyForm : Form
{
private int deltaX;
private int deltaY;
private const int movementAmount = 10;
private Timer movementTimer = new Timer();
public MyForm()
{
movementTimer.Interval = 100; // make this whatever interval you'd like there to be in between movements
movementTimer.Tick += new EventHandler(movementTimer_Tick);
}
void movementTimer_Tick(object sender, EventArgs e)
{
myMonster.Location = new Point(myMonster.X + deltaX, myMonster.Y + deltaY);
}
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
switch (e.KeyCode)
{
case Keys.Left:
{
deltaX -=movementAmount;
} break;
case Keys.Right:
{
deltaX += movementAmount;
} break;
case Keys.Up:
{
deltaY -= movementAmount;
} break;
case Keys.Down:
{
deltaY += movementAmount;
} break;
}
UpdateTimer();
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
switch (e.KeyCode)
{
case Keys.Left:
{
deltaX += movementAmount;
} break;
case Keys.Right:
{
deltaX -= movementAmount;
} break;
case Keys.Up:
{
deltaY += movementAmount;
} break;
case Keys.Down:
{
deltaY -= movementAmount;
} break;
}
UpdateTimer();
}
private void UpdateTimer()
{
movementTimer.Enabled = deltaX != 0 || deltaY != 0;
}
}
Run Code Online (Sandbox Code Playgroud)