C#-俄罗斯方块克隆-无法获得阻止以正确响应箭头键组合 [英] C# - Tetris clone - Can't get block to respond properly to arrow key combinations

查看:107
本文介绍了C#-俄罗斯方块克隆-无法获得阻止以正确响应箭头键组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Visual C#2005编写俄罗斯方块游戏.这是我设计的最广泛的程序.

I'm working on programming a Tetris game in Visual C# 2005. This is the most extensive program I have designed yet.

我创建一个形状类和一个块类来控制不同俄罗斯方块的位置,移动和显示.对于每种形状,我都有moveDown(),moveLeft()和moveRight()函数(以及相应的canMoveDown(),canMoveLeft()和canMoveRight()布尔函数,它们可以确定是否可以移动).一切都很漂亮.

I create a shape class and a block class to control the location, movement, and display of the different Tetris pieces. I have moveDown(), moveLeft(), and moveRight() functions for each shape (and corresponding canMoveDown(), canMoveLeft(), canMoveRight() boolean functions that verify it's ok to move). This is all working beautifully.

除了要使用计时器使形状每隔这么多毫秒自动落下一行外,我还想使用向下,向右和向左箭头键让用户在周围移动块.

I want to use the down, right, and left arrow keys to let the user move the block around, in addition to using a timer to have the shape automatically fall one row every so many milliseconds.

我正在使用KeyDown事件处理程序来检查用户何时按下向下,向左和向右箭头键.这并不难.问题是我想允许对角线运动,并且希望它尽可能平稳地工作.我尝试了多种解决该问题的方法,并获得了不同程度的成功.但是我不能完全正确...

I am using the KeyDown event handler to check when the user presses the down, left, and right arrow key. This isn't so hard. The problem is that I want to allow for diagonal motion, and I want it work as smoothly possible. I have tried a bunch of different ways of approaching this problem, with varying levels of success. But I can't get it quite right...

我最成功的方法是使用三个布尔变量来跟踪何时按下向下,向左和向右箭头键.我将在KeyDown事件中将布尔值设置为true,在KeyUp事件中将布尔值设置为false.在KeyDown事件中,我还将通过使用布尔变量检查当前按下的组合来告诉块如何移动.除了一件事之外,它确实运作良好.

My most successful approach was to use three boolean variables to keep track of when the down, left, and right arrow keys are being held down. I would set the booleans to true in the KeyDown event, and to false in the KeyUp event. In the KeyDown event I would also tell the block how to move, using the boolean variables to check which combination was currently being pressed. It worked really well, except for one thing.

如果我按住其中一个箭头键,然后按住第二个箭头键,然后松开第二个键,则该块将完全停止移动,而不是继续向没有移动的第一个箭头键的方向移动还没有发布.我认为这是因为第二个键触发了KeyDown事件,并且释放后触发了KeyUp事件,并且即使第一个键被触发,KeyDown事件也完全停止触发.

If I pressed one of the arrow keys and held, then pressed a second arrow key and then released the second key, the block would stop moving altogether, instead of continuing to move in the direction of the first arrow key which hasn't been released yet. I think this is because the second key triggered the KeyDown event, and upon its release the KeyUp event was fired, and the KeyDown event stopped firing completely, even though the first key is fired.

我终生无法找到令人满意的解决方案.

I cannot for the life me of find a satisfactory solution to this problem.

任何帮助将不胜感激=)

Any help would be greatly appreciated =)

推荐答案

大多数游戏不等待事件发生.他们在必要时轮询输入设备,并采取相应的措施.实际上,如果您看过XNA,就会发现在更新例程中调用了Keyboard.GetState()方法(或Gamepad.GetState()),并根据以下内容更新了游戏逻辑结果.使用Windows.Forms时,没有任何开箱即用的方法来执行此操作,但是您可以P/调用GetKeyBoardState()函数来利用它.这样做的好处是,您可以一次轮询多个键,因此一次可以响应多个按键.这是我在网上找到的一个简单的类,对此有帮助:

Most games don't wait for events. They poll the input device when neccessary and act accodringly. In fact, if you ever take a look at XNA, you'll see that there's a Keyboard.GetState() method (or Gamepad.GetState()) that you'll call in your update routine, and update your game logic based on the results. When working with Windows.Forms, there's nothing out of the box to do this, however you can P/Invoke the GetKeyBoardState() function to take advantage of this. The good thing about this is, that you can poll multiple keys at once, and you can therefore react to more than one key press at a time. Here's a simple class I found online that helps with this:

http://sanity-free.org/17/obtaining_key_state_info_in_dotnet_csharp_getkeystate_implementation>.

http://sanity-free.org/17/obtaining_key_state_info_in_dotnet_csharp_getkeystate_implementation.html

为了演示,我编写了一个简单的Windows应用程序,该应用程序基本上根据键盘输入来移动球.它使用我链接到的类来轮询键盘的状态.您会注意到,如果同时按住两个键,它将沿对角线移动.

To demonstrate, I wrote a simple windows app that basically moves a ball around based on keyboard input. It uses the class I linked you to, to poll the keyboard's state. You'll notice that if you hold down two keys at a time, it'll move diagonally.

首先,Ball.cs:

First, 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;
        }
    }

真的什么都没花哨....

Really nothing fancy at all....

然后是Form1代码:

Then here's the Form1 code:

    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毫秒,它将检查键盘状态,如果按下了一个键,它将移动键盘并使其无效,以便可以重新绘制.

Simple little app. Just creates a ball and a timer. Every 20 milliseconds, it checks the keyboard state, and if a key is pressed it moves it and invalidates so that it can repaint.

这篇关于C#-俄罗斯方块克隆-无法获得阻止以正确响应箭头键组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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