Dan*_*rip 4 c# keydown arrow-keys
我正在使用Visual C#2005编写一个俄罗斯方块游戏.这是我设计的最广泛的程序.
我创建了一个形状类和一个块类来控制不同俄罗斯方块的位置,移动和显示.我有每个形状的moveDown(),moveLeft()和moveRight()函数(和相应的canMoveDown(),canMoveLeft(),canMoveRight()布尔函数,验证它可以移动).这一切都很美妙.
我想使用向下,向右和向左箭头键让用户移动块,除了使用计时器使形状每隔几毫秒自动下降一行.
我正在使用KeyDown事件处理程序来检查用户何时按下向下,向左和向右箭头键.这不是那么难.问题是我想允许对角线运动,我希望它能够顺利运行.我已经尝试了一系列不同的方法来解决这个问题,并取得了不同程度的成功.但我不能说得对......
我最成功的方法是使用三个布尔变量来跟踪向下,向左和向右箭头键被按下的时间.我会在KeyDown事件中将布尔值设置为true,在KeyUp事件中将布尔值设置为false.在KeyDown事件中,我还将告诉块如何移动,使用布尔变量来检查当前正在按下哪个组合.除了一件事,它的效果非常好.
如果我按下其中一个箭头键并按住,然后按下第二个箭头键然后释放第二个键,该块将完全停止移动,而不是继续向第一个箭头键的方向移动,而第一个箭头键尚未释放然而.我认为这是因为第二个键触发了KeyDown事件,并且在释放时,KeyUp事件被触发,并且KeyDown事件完全停止触发,即使第一个键被触发.
我不能为我的生活找到一个满意的解决方案来解决这个问题.
任何帮助将不胜感激=)
大多数游戏都不等待事件.他们在必要时轮询输入设备并采取相应的行动.事实上,如果你看过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;
}
}
Run Code Online (Sandbox Code Playgroud)
真的没什么特别的....
那么这是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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
简单的小应用.只需创建一个球和一个计时器.每隔20毫秒,它会检查键盘状态,如果按下一个键,它会移动它并使其无效,以便重新绘制.