13.蛇撞墙撞身体结束游戏判定

13.游戏场景-蛇撞墙撞身体结束游戏判定


13.1 知识点

蛇类创建判断是否撞墙撞身体后结束游戏方法,一次遍历地图的墙数组和自己的身体数组比较位置。

#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
    
    #region Lesson9 撞墙撞身体结束逻辑
    
    //检测蛇是否撞墙撞身体后 结束游戏
    //在update中每次绘制完检测 要传入地图
    public bool CheckEnd(Map map)
    {
        //是否和墙体位置重合
        for (int i = 0; i < map.walls.Length; i++)
        {
            if( bodys[0].pos == map.walls[i].pos )
            {
                return true;
            }
        }
        
        //是否和自己的身体重合
        for (int i = 1; i < snakeBodysLength; i++)
        {
            if(bodys[0].pos == bodys[i].pos)
            {
                return true;
            }
        }
        
        return false;
    }
    #endregion
}

游戏场景类中,每次update绘制完身体,用蛇变量判断是否撞墙撞身体,是的话切换到结束场景

using System;
using System.Collections.Generic;
using System.Text;
using 贪食蛇.Lesson1;
using 贪食蛇.Lesson4;
using 贪食蛇.Lesson5;
using 贪食蛇.Lesson6;

namespace 贪食蛇.Lesson2
{
    //游戏场景类 继承游戏帧更新接口
    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();
                
                //检测是否撞墙
                if(snake.CheckEnd(map))
                {
                    //切换为结束场景
                    Game.ChangeScene(E_SceneType.End);
                }
                
                //实际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

×

喜欢就点赞,疼爱就打赏