尝试制作一款小吃游戏,就像大多数游戏开发人员所做的那样,但我的版本有点复杂,因为我没有为蛇使用单个绿色或黑色盒子,我为蛇头、尾巴、身体和身体使用不同的精灵角落像这样。我的最终目标是做类似 Google Snake 游戏。
我已经完成了一款贪吃蛇游戏的大部分机制:移动、生长、改变移动方向引起的角点。蛇的移动是基于一张抽象的二维网格图。我认为蛇是由一系列snake节点组成的,一条蛇可能是这样的:
头<- body <- corner <- ... <- tail.
这些节点继承关系是:
class BaseNode; // BaseNode just handler the four direcion sprites
class SnakeNode: BaseNode;
class SnakeCorner: SnakeNode;
class SnakeHead: SnakeNode; // Singleton
class SnakeTail: SnakeNode; // Singleton
public class SnakeNode : BaseNode
{
public SnakeNode prev;
public SnakeNode next;
public Vector2Int gridPos; // The pos in the abstract two-dimensional grid map.
// every snake node have its direction
protected Vector2Int _direction;
// SnakeCorner will override this property
public virtual Vector2Int Direction
{
get => _direction;
set
{
// ...
// some code auto set spriterender.sprite when change the direction
}
}
}
我定义了一个函数来将网格位置映射到世界位置,这就是我所做的。
public Vector2 Grid2WorldPosition(int row, int col){
var offset = new Vector2(setting.cols, setting.rows) / 2;
return (new Vector2(col ,row) - offset) * setting.scale;
}
以及我如何移动蛇:
private BaseNode[,] gridMap;
private void MoveSnack(){
var tail = SnackTail.Instance;
var newTailPos = tail.prev.gridPos;
var newTailDir = tail.prev.Direction;
var head = SnackHead.Instance;
var oldPos = head.gridPos;
var newPos = head.gridPos + new Vector2Int(head.Direction.y, head.Direction.x);
if (CheckOutOfBounds(newPos.x, newPos.y)){
// some code limit bounds
}
if (gridMap[newPos.x, newPos.y] != null){
// some code handle eat apple or collision.
}
GameObject gameObj;
if (head.Direction != head.next.Direction)
{
// some code create SnakeCorner obj
}
else
{
// some code create common SnakeNode obj
}
var body = gameObj.GetComponent<SnackNode>();
body.Direction = head.Direction;
body.gridPos = oldPos;
SnackListHandler.Insert(head, body);
head.gridPos = newPos;
// here is what I do to update postion on the abstract map.
gridMap[newPos.x, newPos.y] = head;
gridMap[oldPos.x, oldPos.y] = body;
gridMap[tail.gridPos.x, tail.gridPos.y] = null;
gridMap[newTailPos.x, newTailPos.y] = tail;
tail.Direction = newTailDir;
tail.gridPos = newTailPos;
// just update head and tail positon is enough
var nodes = new SnackNode[]{head, tail};
foreach (var node in nodes){
node.transform.position = Grid2WorldPosition(node.gridPos.x, node.gridPos.y);
}
if (tail.prev != head)
SnackListHandler.Remove(tail.prev);
}
SnakeListHanler 将 Snake Nodes prev、next 关系处理为链表,我认为没有必要将其代码放在这里,也许......
问题是,当我运行 MoveSnack 函数时,头部和尾部位置就像“跳转”到新的世界位置,导致感觉卡住了。我尝试过 lerp 方式,但没有按照我喜欢的方式行事,也许 lerp 能够让我的蛇像 Google Snake 一样移动,但我不知道该怎么做。
欢迎提出任何建议、想法,以重新创建 Google 贪吃蛇游戏。
它按设计工作,仅此而已。您使用离散网格移动蛇,并且各部分根据该网格改变位置。
你可以做什么来让它更顺利: