使用链表与Queue实现连续性移动的贪吃蛇
前言-经典贪吃蛇
贪吃蛇可以说是十分经典的游戏了,在游戏中,玩家操控蛇的上下左右方向来让蛇移动并且吃到生成的果实。
经典贪吃蛇的移动方式为离散的,断续的
正常来说,大部分贪吃蛇的实现都是通过各种不同的集合实现的,其中列表与链表都比较常见
链表的介绍(新手向,可跳过)
**链表(Linked List)**是一种常见的集合类型,它是由一个头部与N个节点(Node)构成的
之所以叫他链表,就是因为节点与节点之间是有联系的,看起来就像“锁链”一样。
这里我们将使用最简单的单链表:
**单链表:** 每一个节点可以获取下一个节点,但是不能向前访问(单向性)
C#的Collections.Generic实际上也提供了可以直接使用的链表,但本例我们将自己写阵对本例的链表
Queue的介绍(新手向,可跳过)
**队列(Queue)**是一个有序的FIFO(First In First Out, 即先入先出)集合
**常用的方法和属性:**
在队尾增加一个值: Enqueue(value)
移除并返回队首值: Dequeue()
返回队首值但不移除: Peek()
返回队列的长度: Count
清空队列: Clear()
队列是否包含某值: Contains(value)
连续性移动贪吃蛇的实现方法与代码
核心解释
贪吃蛇的移动的核心就是使后面一个蛇身能够走过前面一个蛇身已经经过的路线。
假设我们现在有一条蛇,并且只有一个头部,一节身体
我们已知蛇的移动速度为 2m/s
因为移动是在FixedUpdate里执行,一秒50帧(frame),所以速度可以换算为 0.04m/frame
本代码中,蛇头与蛇身间距为0.2m
为了确保蛇身能连贯的跟随蛇头,我们必须要存储0.2m间距内蛇头走过的位置
0.2 / 0.04 = 5帧,每一帧都进行移动,所以我们一共要存储5帧里的每一个位置,也就是一共5个位置
这个时候,Queue的先入先出就派上用场了
为了保持0.2m的间距,我们只能存储至多5个位置
所以,当蛇头存储了已经5个位置后,每下一帧,他都要把最旧的位置给蛇身,并且获取一个最新的位置
着完全契合了Queue的特征:先拿旧的
这个例子之应用于一个蛇身,一个蛇头,但通过链表,我们可以让每一个蛇身都存储5个位置
并且按照老规矩向后传递(扔旧的给后面,从前面拿新的,依此类推)
测试准备
如果你需要复制下面的源码进行测试,请确保制作了蛇身的预设体并且拖拽组件Node
蛇头则需要拖拽Head和HeadMovement
蛇头的移动
这个没什么好说的,很简单的移动代码
using UnityEngine;
public class HeadMovement : MonoBehaviour
{
public float moveSpeed = 2f;
public float rotateSpeed = 120f;
private void FixedUpdate()
{
Move();
}
private void Move()
{
float xAxis = -Input.GetAxis("Horizontal");
transform.Rotate(0f, 0f, xAxis * rotateSpeed * Time.fixedDeltaTime);
transform.Translate