C# - 俄罗斯方块克隆 - 无法阻止正确响应箭头键组合

2023-11-22

我正在使用 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;
        }
    }

实在是没什么好看的......

然后是 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 毫秒,它检查一次键盘状态,如果按下某个键,它会移动该键并使其失效,以便可以重新绘制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# - 俄罗斯方块克隆 - 无法阻止正确响应箭头键组合 的相关文章

随机推荐