自制简易贪吃蛇

作者: 牛水聿 | 来源:发表于2017-12-14 15:08 被阅读156次
pexels-photo-699796.jpeg

今天实现一款经典小游戏的实例,贪吃蛇想必大家都有接触过,当然今天实现的细节没有那么全面,只能算是简易版本的小游戏,使用的是Unity中的UGUI,Bug可能有点多,不过大体算是完成了。

大概的原理

整体小游戏的核心其实还蛮简单的,通俗一点讲就是:键盘控制2D网格图片的上下左右移动。我使用的是UGUI中GridLayoutGroup组件添加多个Image实现整体贪吃蛇移动的地图,其实也就是一个个的网格,网格单元就是图片,平时的网格图片都是透明的,贪吃蛇的身体则是其他图片。

我需要控制的就是贪吃蛇的头部和身体,使用键盘WASD键位进行贪吃蛇头部网格移动,后续身体只需要移动到上一节身体的位置就好了,当然理论可行,实际操作还需要考虑其他的问题。

小游戏的效果图

Demo.gif

效果图中的小问题咱们先不讨论,旨在整体的实现效果,基于此可以进行游戏的完善

关键代码演示

设置地图中具体坐标的图片,也就是实时更新屏幕画面

    public void SetSpriteImage(List<SnakeCell> snakeBody)
    {
        //设置其他格子
        SetDefaultSpriteImage();

        //设置food
        if (gameController.food.foodCoord != Vector2.zero)
            imgArray[(int)(gameController.food.foodCoord.x), (int)(gameController.food.foodCoord.y)].sprite = Resources.Load<Sprite>("002/Textures/Food");

        try
        {
            foreach (var item in snakeBody)
            {
                imgArray[(int)item.Coord.x, (int)item.Coord.y].sprite = Resources.Load<Sprite>("002/Textures/" + item.SpriteName);
            }
        }
        catch (System.Exception)
        {
            gameController.isLife = false;
            Debug.Log("游戏结束");
        }

        //判断贪吃蛇  吃食物
        if (gameController.snake.head != Vector2.zero && gameController.snake.head == gameController.food.foodCoord)
        {
            Vector2 direc = (gameController.snake.tail - gameController.snake.head).normalized;
            direc = new Vector2(direc.y, direc.x);
            if (Vector2.Dot(Vector2.up, direc) == 0)
            {
                if (gameController.snake.direction == Snake.Direction.Left)
                {
                    gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x, gameController.snake.tail.y + 1));
                }
                else if(gameController.snake.direction == Snake.Direction.Right)
                {
                    gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x, gameController.snake.tail.y - 1));
                }
            }else if(Vector2.Dot(Vector2.up, direc) == 1)
            {
                gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x + 1, gameController.snake.tail.y));
            }
            else if(Vector2.Dot(Vector2.up, direc) == -1)
            {
                gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x - 1, gameController.snake.tail.y));
            }
            else if (Vector2.Dot(Vector2.up, direc) < 0)
            {
                if(gameController.snake.tail.y < gameController.snake.head.y)
                {
                    gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x, gameController.snake.tail.y - 1));
                }
                else
                {
                    gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x, gameController.snake.tail.y + 1));
                }
            }
            else if (Vector2.Dot(Vector2.up, direc) > 0)
            {
                if (gameController.snake.tail.y < gameController.snake.head.y)
                {
                    gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x, gameController.snake.tail.y - 1));
                }
                else
                {
                    gameController.snake.AddSnakeBody(new Vector2(gameController.snake.tail.x, gameController.snake.tail.y + 1));
                }
            }


            gameController.food.CreateFood(gameController);
        }

    }

代码解析

这段代码里面涉及到三种图片的刷新,也就是不同标记的属性图片对网格的赋值。

首先需要进行的是普通网格图片的赋值,这里呢没有给出具体的方法实现,但其实内部就是将整体网格遍历一遍进行透明图片的赋值。

然后刷新的图片就是我们贪吃蛇的食物,这里呢就是红色方块,食物的生成位置其实不是完全随机的,生成的位置必须是处于地图网格中且必须不能在贪吃蛇身体进行食物的生成,每次食物一旦被贪吃蛇吃掉就会触发食物的再次生成

最后我们需要考虑的是贪吃蛇吃掉食物之后身体的延长问题,其实有人会觉得身体延长就直接在贪吃蛇尾部进行网格图片的替换就成了,但是这里就存在一个问题,就是尾部身体延长的方向位置怎么摆放。由效果图可知,在贪吃蛇进行身体移动的时候尾部的延伸方向其实是存在多种情况的。

在代码中的体现就是八个方向的判断来决定尾部身体如何生成,具体的判断依据就是贪吃蛇头部和尾部形成的向量与Y轴坐标的点积的值,再根据当前贪吃蛇移动的方向来生成贪吃蛇的身体。(具体以代码为主)

由于编码秉承面向对象的原则,所以当前代码中可能存在多个对象并未给出说明,具体可以查看源码。

代码地址

具体代码我已经上传Github,看这里

目前代码上可能存在蛮多的问题,游戏性上也是不够,但毕竟只是个小游戏,我没打算做得有多好,简简单单实现功能就成。

总结

以前动手写代码还是缺点脑子,写到哪里算哪里,完全没考虑对象封装、游戏框架这种东西,代码不一定有多么实用的功能,但至少能看的明白又舒服,减耦合才是王道!

相关文章

  • 自制简易贪吃蛇

    今天实现一款经典小游戏的实例,贪吃蛇想必大家都有接触过,当然今天实现的细节没有那么全面,只能算是简易版本的小游戏,...

  • 自制简易解释器

    title: 自制简易解释器date: 2019-02-18 22:00:01origin: 自制简易解释器 自制...

  • 生活不只苟且,还有诗和远方,哪怕减配

    废罐体自制简易笔筒

  • 自制简易MVC

    最近稍微有点时间,并且我以前是做ng的,对ng的mvc一直想研究研究。MVC的基础知识我就不多说了,总结下来就是:...

  • 自制简易书签

    这两天读书的时候总是要翻找上次读的位置颇为麻烦,正好看到边上有之前准备写字的A4纸便有了自制书签的想法。 绘画水准...

  • CSS3十二生肖--蛇

    CSS3十二生肖--贪吃蛇版 实在没时间做了,哈,就做个简易版的吧。逗死我了。 ...

  • pygame 简易贪吃蛇实现

    最近想用动手51单片机做个贪吃?的游戏机,发现没有思路索用python实现了一把(日常摸鱼),关于51贪吃蛇游戏机...

  • OpenGL初探 - 简易贪吃蛇

    本文内容包括:1、mac中新建openGL工程2、绘制一个简单图形3、键盘控制4、定时器5、文字绘制这次是初次学习...

  • 自制简易柠檬红茶

    用料 红茶 25克 纯净水 1升 白糖或蜂蜜 根据自己口味调节 方法: 1.将茶叶放在保鲜袋中,用擀面杖轻轻碾压几...

  • 自制简易throttle函数

    throttle.js test.html 这样连点就不会重复触发函数了

网友评论

    本文标题:自制简易贪吃蛇

    本文链接:https://www.haomeiwen.com/subject/hyskwxtx.html