自制简易贪吃蛇

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,看这里

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

总结

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342