15分钟写一个贪吃蛇
蛇的移动逻辑
通常我们是在update中获得玩家的输入,fixedupdate中完成移动逻辑。
Snake脚本
@@ -1,230 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public Transform segmentPrefab;
public Vector2Int direction = Vector2Int.right;
public float speed = 20;
public int speedLevel = 1;
public int initSize = 3;
public bool MoveThroughWall = true;
public bool invincible = false; // �Ƿ�����״̬
List<Transform> segments = new List<Transform>();
private float nextUpdate;
private Vector2Int input;
float invincibleTimer = 2.0f;
private void Start()
{
ResetGame();
}
private void ResetGame()
{
invincible = true;
Time.timeScale = 1.0f;
ScoreManager.Instance.ResetScore();
ScoreManager.Instance.HidenGameOver();
direction = Vector2Int.right;
transform.position = Vector3.zero;
for (int i = 1; i < segments.Count; i++)
{
Destroy(segments[i].gameObject);
}
segments.Clear();
// ������ͷ
segments.Add(transform);
for (int i = 0; i < initSize - 1; i++)
{
Grow();
}
}
private void FixedUpdate()
{
MoveSnake();
}
private void Update()
{
MoveInput();
CancelInvincible();
}
private void CancelInvincible()
{
if(invincible)
{
invincibleTimer -= Time.deltaTime;
if (invincibleTimer < 0)
{
invincible = false;
invincibleTimer = 2.0f;
}
}
}
/// <summary>
/// С���ƶ���
/// </summary>
private void MoveSnake()
{
// �ƶ�CD
if (Time.time < nextUpdate)
{
return;
}
if (input != Vector2Int.zero)
{
direction = input;
}
for (int i = segments.Count - 1; i > 0; i--)
{
segments[i].position = segments[i - 1].position;
}
int x = Mathf.RoundToInt(transform.position.x) + direction.x;
int y = Mathf.RoundToInt(transform.position.y) + direction.y;
transform.position = new Vector2(x, y);
nextUpdate = Time.time + (1f / (speed + speedLevel));
}
/// <summary>
/// �ƶ�������
/// </summary>
private void MoveInput()
{
if(Keyboard.current.rKey.wasPressedThisFrame)
{
ResetGame();
}
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
speed = Mathf.Lerp(speed, 40, 1f);
}
if(Keyboard.current.spaceKey.wasReleasedThisFrame)
{
speed = 10f;
}
if (direction.x != 0)
{
if (Keyboard.current.wKey.wasPressedThisFrame || Keyboard.current.upArrowKey.wasPressedThisFrame)
{
input = Vector2Int.up;
}
else if (Keyboard.current.sKey.wasPressedThisFrame || Keyboard.current.downArrowKey.wasPressedThisFrame)
{
input = Vector2Int.down;
}
}
else if (direction.y != 0)
{
if (Keyboard.current.aKey.wasPressedThisFrame || Keyboard.current.leftArrowKey.wasPressedThisFrame)
{
input = Vector2Int.left;
}
else if (Keyboard.current.dKey.wasPressedThisFrame || Keyboard.current.rightArrowKey.wasPressedThisFrame)
{
input = Vector2Int.right;
}
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Food"))
{
Grow();
} else if (collision.CompareTag("Wall"))
{
CollideWall();
}
else if (collision.CompareTag("Obstacle") && !invincible)
{
GameOver();
}
}
private void CollideWall()
{
if (MoveThroughWall)
{
MoveThroughWalls(transform);
}
else
{
GameOver();
}
}
private void GameOver()
{
ScoreManager.Instance.ShowGameOver();
Time.timeScale = 0f;
}
private void MoveThroughWalls(Transform wall)
{
Vector3 position = wall.position;
if (direction.x != 0f)
{
position.x = Mathf.RoundToInt(-wall.position.x + direction.x);
}else if(direction.y != .0f)
{
position.y = Mathf.RoundToInt(-wall.position.y + direction.y);
}
transform.position = position;
}
private void Grow()
{
Transform segment = Instantiate(segmentPrefab);
segment.position = segments[^1].position;
segments.Add(segment);
ScoreManager.Instance.AddScore();
}
/// <summary>
/// ij�������Ƿ��ߵ�����ռ����
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public bool Occupies(int x, int y)
{
foreach (var seg in segments)
{
if (Mathf.RoundToInt(seg.position.x) == x &&
Mathf.RoundToInt(seg.position.y) == y)
{
return true;
}
}
return false;
}
}
评论区