C#贪吃蛇游戏如何停止蛇的移动

3

我需要在学校的一个小项目中制作一个贪吃蛇游戏。目前我已经实现了蛇不断地朝一个方向移动。但是,如果按下另一个方向键,蛇的移动方向会改变,导致它朝着多个方向移动。我现在卡在了如何解决这个问题上。我已经编写了一个stop()方法,但我不知道如何实现它。如果你们能给我一些提示,我将不胜感激。

            using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Snake
{
    class Snake
    {
        //Attributes go here....
        private Form frmSnake;
        private static Button btnSnake;
        private static Label lblStatus;
        private static Timer timerUP;
        private static Timer timerLEFT;
        private static Timer timerDOWN;
        private static Timer timerRIGHT;

        //Initialize a Snake Object...
        public Snake()
        {            
            initComponents();
            initTimers ();
            startAllTimers ();
            initEventHandler(this);
            frmSnake.ShowDialog();
        }

        //give the Components of snake object values        
        private void initComponents()
        {
            frmSnake = new Form();
            lblStatus = new Label();
            btnSnake = new Button();            

            frmSnake.Controls.Add(btnSnake);
            frmSnake.Controls.Add(lblStatus);
            frmSnake.SetBounds(400, 400, 700, 550);
            frmSnake.Text = "Snake";

            lblStatus.SetBounds(0, 495, 700, 20);
            lblStatus.BackColor = System.Drawing.Color.Red;

            btnSnake.SetBounds((frmSnake.Width / 2) - (btnSnake.Width / 2), ((frmSnake.Height - lblStatus.Height) / 2) - (btnSnake.Height / 2), 10, 10);
        }

        private void initTimers ()
        {            
            timerUP = new Timer ();
            timerLEFT = new Timer ();
            timerDOWN = new Timer ();
            timerRIGHT = new Timer ();
            timerUP.Enabled = true;
            timerUP.Interval = 100;
            timerLEFT.Enabled = true;
            timerLEFT.Interval = 100;
            timerDOWN.Enabled = true;
            timerDOWN.Interval = 100;
            timerRIGHT.Enabled = true;
            timerRIGHT.Interval = 100;
        }

        private void disposeTimers ()
        {
            timerUP.Dispose ();
            timerLEFT.Dispose ();
            timerDOWN.Dispose ();
            timerRIGHT.Dispose ();
        }

        private void stopTimer (Timer timer)
        {
            timer.Stop ();
        }

        private void stopAllTimers ()
        {
            timerUP.Stop ();
            timerDOWN.Stop ();
            timerLEFT.Stop();
            timerRIGHT.Stop();
        }
        private void startAllTimers ()
        {
            timerUP.Start ();
            timerDOWN.Start ();
            timerRIGHT.Start ();
            timerLEFT.Start ();
        }

        private void startTimer (Timer timer)
        {
            timer.Start ();
        }

        //initializes the event handler which handles a key press W,A,S,D from user 
        //W,A,S,D correspondents UP,LEFT,DOWN,RIGHT
        private void initEventHandler(Snake snake)
        {
            snake.frmSnake.KeyPreview = true;
            snake.frmSnake.KeyDown += new KeyEventHandler(snake.frm_KeyDown);
        }

        //handle the key press event sent from previous method
        private void frm_KeyDown(object sender, KeyEventArgs e)
        {
            disposeTimers ();
            initTimers ();
            switch ( e.KeyData )
            {

                //if up is pressed
                case Keys.W:
                    {                        
                        startTimer ( timerUP );
                        timerUP.Tick += new EventHandler ( timerUP_Tick );
                    }
                    break;
                //if left is pressed
                case Keys.A:
                    {                        
                        startTimer ( timerLEFT );
                        timerLEFT.Tick += new EventHandler ( timerLEFT_Tick );
                        //move snake 5 spaces
                    }
                    break;
                //if down is pressed
                case Keys.S:
                    {                        
                        startTimer ( timerDOWN );
                        timerDOWN.Tick += new EventHandler ( timerDOWN_Tick );
                        //move snake 5 spaces
                    }
                    break;
                //if right is pressed
                case Keys.D:
                    {                        
                        startTimer ( timerRIGHT );
                        timerRIGHT.Tick += new EventHandler ( timerRIGHT_Tick );
                        //move snake 5 spaces
                    }
                    break;
            }            
        }

        void timerRIGHT_Tick ( object sender, EventArgs e )
        {
            btnSnake.Location = new Point ( btnSnake.Location.X + 5, btnSnake.Location.Y );
        }

        void timerDOWN_Tick ( object sender, EventArgs e )
        {
            btnSnake.Location = new Point ( btnSnake.Location.X, btnSnake.Location.Y + 5 );
        }

        void timerLEFT_Tick ( object sender, EventArgs e )
        {
            btnSnake.Location = new Point ( btnSnake.Location.X - 5, btnSnake.Location.Y );
        }

        void timerUP_Tick ( object sender, EventArgs e )
        {
            //move snake 5 spaces
            btnSnake.Location = new Point ( btnSnake.Location.X, btnSnake.Location.Y - 5 ); 
        }        



        private void setLabelStatus(string text, Color color)
        {
            lblStatus.Text = "";
            lblStatus.BackColor = color;
            lblStatus.Text = text;
        }

        //main method initializes a snake game
        static void Main(string[] args)
        {
            Snake snake = new Snake();
        }
    }
}

你尝试过在按下键时停止其他计时器吗?看起来你从来没有停止过任何方向的计时器,这就是为什么它会同时运行两个方向的原因。 - Bob.
这基本上就是我的问题,我已经尝试从代码的各个位置调用stop()方法,但都没有成功。 - LeonidasFett
除了@ravuya的出色回答之外,我想补充一点,你可以从阅读游戏设计方面的书籍中受益匪浅。特别是要关注游戏循环,也许还有像XNA这样的游戏框架。 - Sam Axe
好的,我已经编辑了上面的源代码,现在它可以正常工作。接下来,我将设置游戏场地的限制。我会将这个问题加入书签,因为我想将来可能还需要一些建议;) 无论如何,非常感谢所有的帮助! - LeonidasFett
好的,我又编辑了代码。我实现了4个计时器,每个方向一个。当按下键时,我会处理并重新初始化它们,然后只需启动相应的计时器。 - LeonidasFett
显示剩余2条评论
2个回答

4
你需要记录已创建的计时器,以便稍后可以删除它们(可能在“停止”方法内)。
或者,你可以为运动设置一个始终触发的计时器(在游戏启动时启动),然后存储“当前方向”,并在计时器内使用它。
第二种方法可能更好,因为你可以稍后将一些“每帧”游戏逻辑放入其中(检查蛇是否吃到了自己等),而不是在所有不同的计时器回调中重复。

1

将每个键的计时器声明为私有全局变量,然后在需要更改方向时调用Start()Stop()方法。

 // Declare
 Timer UpTimer = new Timer();
 Timer DownTimer = new Timer();
 Timer LeftTimer = new Timer();
 Timer RightTimer = new Timer();


 // If Left Key pressed
 UpTimer.Stop();
 DownTimer.Stop();
 LeftTimer.Start();
 RightTimer.Stop();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接