Tự cắn mình
Bài học 10 trên 14 trong khóa học Game Unity: rắn 3D của Coddy.
Con rắn chết khi đầu đâm vào đuôi của chính nó, giống như khi đâm vào tường. Phép kiểm tra diễn ra ở cùng vị trí: tại next, ô phía trước, trước khi đầu di chuyển, nên đầu vẫn ở nguyên chỗ khi trò chơi kết thúc.
Một đoạn thân thì an toàn. Ở bước này, đoạn cuối cũng di chuyển lên, rời khỏi ô của nó, nên đầu rắn đi theo đuôi vào ô đó sẽ không chạm vào đoạn thân ấy. Một con rắn gồm bốn khối lập phương có thể đi vòng quanh một hình vuông 2 nhân 2 mãi theo cách này. Phép kiểm tra bỏ qua đoạn cuối bằng cách dừng trước đoạn cuối một vị trí:
// Mọi phần tử trừ phần tử cuối cùng
for (int i = 0; i < items.Count - 1; i++)
{
Debug.Log(items[i].name);
}Khi cả tường lẫn đuôi đều gây chết, bạn có thể thua trò chơi. Chương tiếp theo sẽ thêm điểm số và cách chơi lại.
Thử thách
Trung bìnhCắn phải đuôi sẽ kết thúc trò chơi.
- Trong
Step(), sau khi kiểm tra tường, lặp qua đuôi bằngi < tail.Count - 1, bỏ qua đoạn cuối cùng. - Nếu
tail[i].position == next, gọiDie()rồi trả về, để đầu rắn không di chuyển.
Nhấn Chơi, làm rắn dài ra rồi rẽ vào đuôi: rắn sẽ dừng lại. Sau đó nhấn Kiểm tra.
Tự làm thử
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // Số giây giữa hai bước di chuyển
public int edge = 7; // Các ô trên bảng trải từ -edge đến edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
public Transform segmentPrefab;
private float timer;
private Vector3 direction = Vector3.right; // Hướng di chuyển của đầu rắn ở bước trước
private Vector3 nextDirection = Vector3.right; // Hướng rẽ chờ đến bước tiếp theo
void Update()
{
if (!alive) return;
Keyboard keyboard = Keyboard.current;
if (keyboard != null)
{
if (keyboard.upArrowKey.wasPressedThisFrame || keyboard.wKey.wasPressedThisFrame) Turn(Vector3.forward);
if (keyboard.downArrowKey.wasPressedThisFrame || keyboard.sKey.wasPressedThisFrame) Turn(Vector3.back);
if (keyboard.leftArrowKey.wasPressedThisFrame || keyboard.aKey.wasPressedThisFrame) Turn(Vector3.left);
if (keyboard.rightArrowKey.wasPressedThisFrame || keyboard.dKey.wasPressedThisFrame) Turn(Vector3.right);
}
timer += Time.deltaTime;
if (timer >= tick)
{
timer -= tick;
Step();
}
}
void Turn(Vector3 newDirection)
{
if (newDirection != -direction)
{
nextDirection = newDirection;
}
}
void Step()
{
direction = nextDirection;
Vector3 next = transform.position + direction;
if (Mathf.Abs(next.x) > edge || Mathf.Abs(next.z) > edge)
{
Die();
return;
}
Vector3 tailEnd = tail.Count > 0 ? tail[tail.Count - 1].position : transform.position;
for (int i = tail.Count - 1; i > 0; i--)
{
tail[i].position = tail[i - 1].position;
}
if (tail.Count > 0)
{
tail[0].position = transform.position;
}
transform.position = next;
if (GameManager.Instance.IsFood(next))
{
tail.Add(Instantiate(segmentPrefab, tailEnd, Quaternion.identity));
GameManager.Instance.Eat();
}
}
public bool Occupies(Vector3 cell)
{
if (transform.position == cell) return true;
foreach (Transform segment in tail)
{
if (segment.position == cell) return true;
}
return false;
}
void Die()
{
alive = false;
}
}
Tất cả bài học trong Game Unity: rắn 3D
Tự luyện tập: Playground Unity