Unity3D 小案例 像素贪吃蛇 03 蛇的碰撞

news2024/9/23 12:29:50

Unity3D 小案例 像素贪吃蛇 第三期 蛇的碰撞(完结)

像素贪吃蛇

碰撞蛇身

当蛇头碰撞到蛇身时,游戏应该判定为失败。

找到蛇身预制体,添加 Body 标签和碰撞体,碰撞体的大小为 0.5,跟蛇头和蛇身的碰撞体范围一样,避免因碰撞范围过大而产生错误的碰撞效果。

添加蛇身标签

修改一下 OnTriggerEnter2D 方法,判断碰撞到 Body 标签的物体,判定游戏失败,蛇停止移动。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Snake : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Food"))
        {
            // ...
        }
        else if (other.CompareTag("Body"))
        {
            // 取消定时器
            CancelInvoke(nameof(Move));
        }
    }
}

如果此时运行游戏,会发现蛇一开始就不动了。因为之前初始生成身体时,都在同一个位置生成,一开始就会碰撞蛇身。

修改一下之前的逻辑,让初始生成的蛇身偏移位置。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Snake : MonoBehaviour
{
    Vector2 initPos;  // 初始位置

    void Start()
    {
        initPos = transform.position;

        // 初始生成身体
        for (int i = 0; i < initBodyCount; i++)
        {
            GenerateBody(true);
        }

        // ...
    }
    
    void GenerateBody(bool isInit = false)
    {
        GameObject obj = Instantiate(body);

        // 初始生成
        if (isInit)
        {
            obj.transform.position = initPos + Vector2.left;
            initPos = obj.transform.position;
        }
        else
        {
            // 已有身体
            if (bodyList.Count > 0)
            {
                // 获取最后一个身体,在它的位置生成
                GameObject lastBody = bodyList[bodyList.Count - 1];
                obj.transform.position = lastBody.transform.position;
            }
            // 没有身体
            else
            {
                // 以蛇头的位置生成身体
                obj.transform.position = transform.position;
            }
        }

        // ...
    }
}

现在运行游戏,蛇身的初始位置就不会跟蛇头重叠了。

初始位置

另外,蛇头的层级也要调整一下,当蛇头与蛇身重叠时,让蛇头能够显示在蛇身之上。

调整层级

运行效果:

蛇头碰撞蛇身

添加墙壁

创建四个正方形,调整缩放和位置,调整颜色,分别布置在上下左右四个方向。

因为蛇的移动范围,在 X 轴是 [-8, 8],在 Y 轴是 [-4, 4],所以左右的墙壁分别放置在 X 轴的 -9 和 9 的位置,上下的墙壁分别放置在 Y 轴的 5 和 -5 的位置。

布置墙壁

然后给墙壁也添加标签 Wall,并且要添加碰撞体,碰撞体的大小保持默认的 1 即可。

添加墙壁标签

在代码中也添加碰撞墙壁的逻辑。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Snake : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Food"))
        {
            // ...
        }
        else if (other.CompareTag("Body") || other.CompareTag("Wall"))
        {
            // 取消定时器
            CancelInvoke(nameof(Move));
        }
    }
}

运行效果:

蛇头碰撞墙壁

游戏失败

显示失败界面

简单搭建一个游戏失败界面。

游戏失败界面

创建一个 UIGameOver.cs 脚本,引用命名空间 UnityEngine.UI,定义 UI 组件变量,拖拽引用。

using UnityEngine;
using UnityEngine.UI;

public class UIGameOver : MonoBehaviour
{
    public Button btnRestart;
    public CanvasGroup canvasGroup;

    void Start()
    {

    }
}

拖拽引用

创建一个 GameManager.cs 脚本,引用命名空间 System,创建单例。

定义一个 Action 事件 showGameOver,带一个布尔值参数,并对外提供一个接口,用于触发事件。

using System;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager instance;
    public event Action<bool> showGameOver;

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public void TriggerGameOver(bool isShow)
    {
        showGameOver.Invoke(isShow);
    }
}

界面脚本添加事件监听,根据是否显示界面,修改 canvasGroup 的参数。

using UnityEngine;
using UnityEngine.UI;

public class UIGameOver : MonoBehaviour
{
    public Button btnRestart;
    public CanvasGroup canvasGroup;

    void Start()
    {
        GameManager.instance.showGameOver += (isShow) =>
        {
            canvasGroup.alpha = isShow ? 1 : 0;
            canvasGroup.blocksRaycasts = isShow;
        };
    }
}

当蛇碰撞时,触发事件显示游戏失败界面。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Snake : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Food"))
        {
            // ...
        }
        else if (other.CompareTag("Body") || other.CompareTag("Wall"))
        {
            // 取消定时器
            CancelInvoke(nameof(Move));
            // 显示游戏失败界面
            GameManager.instance.TriggerGameOver(true);
        }
    }
}

运行效果:

显示游戏失败

重开游戏

UIGameOver.cs 脚本上添加按钮事件,隐藏失败界面,重新开始游戏。

using UnityEngine;
using UnityEngine.UI;

public class UIGameOver : MonoBehaviour
{
    public Button btnRestart;
    public CanvasGroup canvasGroup;

    void Start()
    {
        // ...

        btnRestart.onClick.AddListener(()=>
        {
            GameManager.instance.TriggerGameOver(false);
            GameManager.instance.RestartGame();
        });
    }
}

GameManager.cs 脚本上添加重开游戏的事件和触发接口。

using System;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    //...

    public event Action restartGame;

    // ...

    public void RestartGame()
    {
        restartGame.Invoke();
    }
}

FoodManager.cs 脚本上添加重置网格接口,同时定义一个变量记录当前生成的食物,在重置网格时销毁当前食物。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FoodManager : MonoBehaviour
{
    // ...
    
    public GameObject currentFood;
    
    public void GenerateFood()
    {
        // ...

        currentFood = obj;
    }
    
    public void ResetGrid()
    {
        gridList.Clear();
        for (int i = 0; i < rowMax; i++)
        {
            for (int j = 0; j < colMax; j++)
            {
                gridList.Add(new Vector3(borderLeft + j, borderTop - i, 0));
            }
        }
        Destroy(currentFood);
    }
}

最后,在 Snake.cs 脚本上添加事件监听,重置网格、蛇头、蛇身、食物,最后再次开启定时器,让蛇头重新开始移动。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Snake : MonoBehaviour
{
    // ...
    
    void Start()
    {
        // ...
        
        // 重开游戏,重置游戏物体
        GameManager.instance.restartGame += ()=>
        {
            // 重置网格
            FoodManager.instance.ResetGrid();

            // 销毁蛇身
            for (int i = 0; i < bodyList.Count; i++)
            {
                Destroy(bodyList[i]);
            }
            bodyList.Clear();

            // 重置蛇头位置和方向
            transform.position = Vector3.zero;
            FoodManager.instance.MarkGridList(transform.position, true);
            direction = Vector2.right;
            lastDirection = Vector2.right;
            firstDirection = Vector2.right;

            initPos = transform.position;

            // 初始生成身体
            for (int i = 0; i < initBodyCount; i++)
            {
                GenerateBody(true);
            }

            // 初始生成食物
            FoodManager.instance.GenerateFood();

            // 重新开始移动
            InvokeRepeating(nameof(Move), time, time);
        };
    }
}

运行效果:

重开游戏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2157527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

两台虚拟机之分布式部署

Apache2 和 PHP 安装 在虚拟机1上执行以下步骤: 更新系统包列表: sudo apt update安装 Apache2: sudo apt install apache2 -y安装 PHP 及其扩展: sudo apt install php libapache2-mod-php php-mysql配置Apache和PHP sudo nano /etc/apache2/mods-enabled/dir.conf#…

【BEV 视图变换】Ray-based(2): 代码复现+画图解释 基于深度估计、bev_pool(代码一键运行)

paper&#xff1a;Lift, Splat, Shoot: Encoding Images from Arbitrary Camera Rigs by Implicitly Unprojecting to 3D code&#xff1a;https://github.com/nv-tlabs/lift-splat-shoot 一、完整复现代码(可一键运行)和效果图 import torch import torch.nn as nn import mat…

【Go】Go语言切片(Slice)深度剖析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

知乎:从零开始做自动驾驶定位; 注释详解(二)

这个个系统整体分为: 数据预处理 前端里程计 后端优化 回环检测 显示模块。首先来看一下数据预处理节点做的所有事情&#xff1a; 数据预处理节点 根据知乎文章以及代码我们知道: 节点功能输入输出数据预处理1.接收各传感器信息2.传感器数据时间同步 3.点云运动畸变补偿 4.传…

免杀对抗—python混淆算法反序列化shellcode

一、前言 内网已经学的七七八八了(主要是实验环境太麻烦了&#xff0c;累了)&#xff0c;今天就开启新的篇章——免杀。免杀我们主要是对生成的shellcode做免杀&#xff0c;而不是对生成的exe做免杀。为啥呢&#xff0c;你可以这样理解&#xff0c;exe已经是成品了&#xff0c…

Vue 内存泄漏分析:如何避免开发过程中导致的内存泄漏问题

一. 引言 Vue 作为一款流行的前端框架&#xff0c;已经在许多项目中得到广泛应用。然而&#xff0c;随着我们在 Vue 中构建更大规模的应用程序&#xff0c;我们可能会遇到一个严重的问题&#xff0c;那就是内存泄漏。内存泄漏是指应用程序在使用内存资源时未正确释放&#xff…

昇思MindSpore进阶教程-模型模块自定义

大家好&#xff0c;我是刘明&#xff0c;明志科技创始人&#xff0c;华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享&#xff0c;如果你也喜欢我的文章&#xff0c;就点个关注吧 基础用法示例 神经网络模型由各种层(Lay…

【AI实战攻略】保姆级教程:用AI打造治愈动画vlog,轻松打造爆款,快速涨粉!

在当今这个快节奏的社会中&#xff0c;你是否也曾在某个雨夜&#xff0c;沉浸于那些温馨而治愈的动画短视频中&#xff0c;找到片刻的宁静与放松&#xff1f; 窗外大雨滂沱&#xff0c;而你&#xff0c;刚结束一天的忙碌&#xff0c;沐浴在温暖的热水中&#xff0c;随后裹上柔…

Integer 源码记录

Integer 公共方法结构 注意&#xff1a; 通过构造函数创建一个Integer对象&#xff0c;每次都会返回一个新的对象&#xff0c;如果使用 进行对象的比较&#xff0c;那么结果是false。 public Integer(int value) {this.value value;}与之对应的是&#xff0c;valueOf 方法…

java -----泛型

泛型的理解和好处 泛型是在JDK5之后引入的一个新特性&#xff0c;可以在编译阶段约束操作的数据类型&#xff0c;并进行检查。 泛型的格式为 <数据类型> import java.util.ArrayList;SuppressWarnings({"all"}) public class Generic02 {public static void…

WGS1984快速度确定平面坐标系UTM分带(快速套表、公式计算、软件范围判定)

之前我们介绍了坐标系3带6带快速确定带号及中央经线&#xff08;快速套表、公式计算、软件范围判定&#xff09;就&#xff0c;讲的是CGCS2000 高斯克吕格的投影坐标系。 那还有我们经常用的WGS1984的平面坐标系一般用什么投影呢? 对于全球全国的比如在线地图使用&#xff1a…

探索GraphRAG:用yfiles-jupyter-graphs将知识库可视化!

yfiles-jupyter-graphs 可视化 GraphRAG 结构 前言 前面我们通过 GraphRag 命令生成了知识库文件 parquet&#xff0c;这节我们看一下如何使用 yfiles-jupyter-graphs 添加 parquet 文件的交互式图形可视化以及如何可视化 graphrag 查询的结果。 yfiles-jupyter-graphs 是一…

前端-js例子:收钱转账

支付宝转账 在这里用到周期定时器setInterval(function,time)&#xff0c;设置达到目标钱数时停止定时器。 点击转账按钮时&#xff0c;开始函数显示。 同时要确定输入框里输入的是数字。&#xff08;有一定容错&#xff09; window.onloadfunction(){var btn document.que…

vue3 + ts + pnpm:nprogress / 页面顶部进度条

一、简介 nprogress 是一个轻量级的进度条库&#xff0c;它适用于在网页上添加顶部进度条&#xff0c;用于指示页面加载进度或任何长时间的运行过程。这个库非常流行&#xff0c;因为它易于使用且视觉效果很好。 二、安装 pnpm add nprogress 三、在使用的页面引入 / src/v…

MySQL连接查询解析与性能优化成本

文章目录 一、连接查询1.连接查询基础1. INNER JOIN内连接2. LEFT JOIN (或 LEFT OUTER JOIN)左外连接3. RIGHT JOIN (或 RIGHT OUTER JOIN)右外连接4. FULL OUTER JOIN 2.连接查询的两种过滤条件3.连接的原理 二、性能优化成本1.基于成本的优化2.调节成本常数(1)mysql.server_…

ECharts基础使用方法 ---vue

1.安装依赖文件 仔细看项目" README.md " 描述&#xff0c;确定用什么安装 npm npm install echarts --save //官网推荐使用 pnpm pnpm install echarts --save 其他也是 在项目根目录&#xff0c;打开当前目录命令控制栏&#xff0c;输入以上命令并运行 安装成功后…

动动手指探索世界,旅游APP如何定制开发?

旅游APP的出现为旅行带来了许多便利。随着移动互联网的发展&#xff0c;旅游行业也在不断寻求创新与变革。旅游APP为游客提供了更加便捷的旅行体验&#xff0c;通过旅游APP&#xff0c;用户可以了解旅游信息、旅游服务、在线咨询等&#xff0c;实现在线一站式解决旅行需求的目标…

Github 2024-09-23 开源项目周报 Top15

根据Github Trendings的统计,本周(2024-09-23统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6C++项目3C项目3HTML项目2PowerShell项目1TypeScript项目1JavaScript项目1Blade项目1PHP项目1Bootstrap 5: Web上开发响应式、移动优…

【文心智能体】 旅游手绘手帐 开发分享 零代码 手绘风景 记录行程和心情 旅游攻略

旅游手绘手帐&#xff0c;点击文心智能体平台AgentBuilder | 想象即现实 (baidu.com) 目录 背景 创作灵感 开发历程 一、基础配置 二、高级配置 三、引导示例&#xff08;提示词&#xff09; 期待优化 背景 这个智能体是一个零代码智能体&#xff08;文心智能体平台现…

MySQL篇(管理工具)

目录 一、系统数据库 二、常用工具 1. mysql 2. mysqladmin 3. mysqlbinlog 4. mysqlshow 5. mysqldump 6. mysqlimport/source 6.1 mysqlimport 6.2 source 一、系统数据库 MySQL数据库安装完成后&#xff0c;自带了一下四个数据库&#xff0c;具体作用如下&#xf…