大多数游戏不等待事件。他们在必要时轮询输入设备并采取相应措施。事实上,如果你看过 XNA,你会发现有一个 Keyboard.GetState() 方法(或 Gamepad.GetState()),你会在你的更新例程中调用它,并根据它更新你的游戏逻辑结果。使用 Windows.Forms 时,没有任何开箱即用的方法可以执行此操作,但是您可以 P/Invoke GetKeyBoardState() 函数来利用此功能。这样做的好处是,您可以一次轮询多个键,因此您可以一次对多个按键做出反应。这是我在网上找到的一个简单的类,可以帮助解决这个问题:
http://sanity-free.org/17/obtaining_key_state_info_in_dotnet_csharp_getkeystate_implementation.html
为了演示,我编写了一个简单的 Windows 应用程序,它基本上根据键盘输入移动一个球。它使用我链接到的类来轮询键盘的状态。您会注意到,如果一次按住两个键,它会沿对角线移动。
首先,Ball.cs:
public class Ball
{
private Brush brush;
public float X { get; set; }
public float Y { get; set; }
public float DX { get; set; }
public float DY { get; set; }
public Color Color { get; set; }
public float Size { get; set; }
public void Draw(Graphics g)
{
if (this.brush == null)
{
this.brush = new SolidBrush(this.Color);
}
g.FillEllipse(this.brush, X, Y, Size, Size);
}
public void MoveRight()
{
this.X += DX;
}
public void MoveLeft()
{
this.X -= this.DX;
}
public void MoveUp()
{
this.Y -= this.DY;
}
public void MoveDown()
{
this.Y += this.DY;
}
}
真的没有什么花哨的......
然后是 Form1 代码:
public partial class Form1 : Form
{
private Ball ball;
private Timer timer;
public Form1()
{
InitializeComponent();
this.ball = new Ball
{
X = 10f,
Y = 10f,
DX = 2f,
DY = 2f,
Color = Color.Red,
Size = 10f
};
this.timer = new Timer();
timer.Interval = 20;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
var left = KeyboardInfo.GetKeyState(Keys.Left);
var right = KeyboardInfo.GetKeyState(Keys.Right);
var up = KeyboardInfo.GetKeyState(Keys.Up);
var down = KeyboardInfo.GetKeyState(Keys.Down);
if (left.IsPressed)
{
ball.MoveLeft();
this.Invalidate();
}
if (right.IsPressed)
{
ball.MoveRight();
this.Invalidate();
}
if (up.IsPressed)
{
ball.MoveUp();
this.Invalidate();
}
if (down.IsPressed)
{
ball.MoveDown();
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (this.ball != null)
{
this.ball.Draw(e.Graphics);
}
}
}
简单的小应用程序。只需创建一个球和一个计时器。每 20 毫秒,它检查一次键盘状态,如果按下一个键,它会移动它并使其无效,以便它可以重新绘制。