12.改变蛇类移动方向

12.游戏场景-改变蛇类移动方向


12.1 知识点

蛇类中创建蛇改变移动方向方法,供游戏场景类检测输入时调用。蛇只有头部的时候,可以直接180度转,否则不能这样转。写一个判断条件,不满足直接return回去。

#region Lesson7 蛇移动
/// <summary>
/// 蛇的移动方向
/// </summary>
enum E_MoveDir
{
    /// <summary>
    /// 上
    /// </summary>
    Up,
    /// <summary>
    /// 下
    /// </summary>
    Down,
    /// <summary>
    /// 左
    /// </summary>
    Left,
    /// <summary>
    /// 右
    /// </summary>
    Right,
}
#endregion

//蛇类 继承绘制接口
class Snake : IDraw
{
    //蛇的身体数组
    SnakeBody[] bodys;
        
    //当前蛇的长度
    int snakeBodysLength;
    
    //当前移动的方向
    E_MoveDir dir;
    
    //蛇类构造函数
    public Snake(int x, int y)
    {
        //粗暴的 申明200个空间 游戏中 基本不会出现蛇长度达到200个身体
        bodys = new SnakeBody[200];
        
        //声明蛇头
        bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);
        
        //初始时只有蛇头 初始化为1
        snakeBodysLength = 1;
        
        //初始化默认移动的方向向右
        dir = E_MoveDir.Right;
    }
    
    //蛇类绘制方法
    public void Draw()
    {
        //遍历蛇身体数组 逐个绘制蛇身体
        for (int i = 0; i < snakeBodysLength; i++)
        {
            bodys[i].Draw();
        }
    }
    
    #region Lesson7 蛇的移动
    
    //蛇移动方法
    public void Move()
    {
        //蛇移动前 擦除蛇尾 也就是最后一个位置 否则有残影
        SnakeBody lastBody = bodys[snakeBodysLength - 1];
        Console.SetCursorPosition(lastBody.pos.x, lastBody.pos.y);
        Console.Write("  ");//擦屁股
        
        //蛇头移动
        switch (dir)
        {
            case E_MoveDir.Up:
                --bodys[0].pos.y;
                break;
            case E_MoveDir.Down:
                ++bodys[0].pos.y;
                break;
            case E_MoveDir.Left:
                bodys[0].pos.x -= 2;
                break;
            case E_MoveDir.Right:
                bodys[0].pos.x += 2;
                break;
        }
    }
    #endregion
    
    #region Lesson8 改变蛇的方向
    
    //蛇改变移动方向方法
    public void ChangeDir(E_MoveDir dir)
    {
        //蛇只有头部的时候 可以直接左转右 右转左  上转下 下转上
        //蛇有身体时 这种情况就不能直接转
        
        if( 
            //假如传进来的方向就等于现在的方向
            dir == this.dir 
            ||
            //或者 蛇长度大于0且想要直接180度转向
            (
                snakeBodysLength > 1 
                && 
                (this.dir == E_MoveDir.Left && dir == E_MoveDir.Right ||
                 this.dir == E_MoveDir.Right && dir == E_MoveDir.Left ||
                 this.dir == E_MoveDir.Up && dir == E_MoveDir.Down ||
                 this.dir == E_MoveDir.Down && dir == E_MoveDir.Up)
                 )
            )
        {
            //直接return
            return;
        }
        
        //只要没有return 就记录外面传入的方向 之后就会按照这个方向去移动
        this.dir = dir;
    }
    #endregion
}

在实现游戏场景里的更新方法里,添加检测输入输出,逻辑不能再间隔帧(就是while循环一万次)里面去处理,应该每次都检测 这样才准确,否则会有延迟。不能使用Console.ReadKey(true).Key,程序会卡住等待输入。使用Console.KeyAvailable。会判断有没有键盘输入,如果有才为true,否则一直false 就不会被卡住。

//游戏场景类 继承游戏帧更新接口
class GameScene : ISceneUpdate
{
    //地图类变量 管理所有墙壁
    Map map;
    
    //蛇类变量 管理蛇相关
    Snake snake;
    
    //while循环次数 判断当前while循环进了多少次
    int whileLoopTimes = 0;
    
    //游戏场景类构造函数
    public GameScene()
    {
        //初始化地图类变量
        map = new Map();
        
        //初始化一个蛇
        snake = new Snake(40, 10);
    }
    
    //实现游戏场景里的更新方法 在游戏类中的start方法中的while循环中调用
    public void Update()
    {
        //while循环运行的太快 每次进一次while 绘制一次的话 游戏速度太快 要降速
        //用while循环次数来判断 每当进入while循环10000次后 再进行一次绘制
        //可以理解为每10000帧更新一次
        if (whileLoopTimes % 10000 == 0)
        {
            //绘制地图类
            map.Draw();
            
            //蛇移动 先移动再绘制蛇
            snake.Move();
            
            //绘制蛇类
            snake.Draw();
            
            //实际update了 重写开始计数
            whileLoopTimes = 0;
        }
        
        //每进一次while循环加一
        ++whileLoopTimes;
        
        //检测输入输出 不能再间隔帧(就是while循环一万次)里面去处理 应该每次都检测 这样才准确 否则会有延迟
        
        //假如检测玩家输入用 Console.ReadKey(true).Key 程序会卡住等待输入
        //因为Console.ReadKey(true).Key会一直等
        
        //想在控制台中 检测玩家输入 让程序不被检测卡住
        //使用 Console.KeyAvailable
        //判断 有没有键盘输入 如果有 才为true 否则一直false 就不会被卡住
        
        if ( Console.KeyAvailable )
        {
            //根据输入
            switch (Console.ReadKey(true).Key)
            {
                case ConsoleKey.W:
                    snake.ChangeDir(E_MoveDir.Up);
                    break;
                case ConsoleKey.A:
                    snake.ChangeDir(E_MoveDir.Left);
                    break;
                case ConsoleKey.S:
                    snake.ChangeDir(E_MoveDir.Down);
                    break;
                case ConsoleKey.D:
                    snake.ChangeDir(E_MoveDir.Right);
                    break;
            }
        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏