Menggigit Diri Sendiri
Pelajaran 10 dari 14 dalam kursus Game Unity: Snake 3D di Coddy.
Ular mati saat kepalanya menabrak ekornya sendiri, sama seperti saat menabrak dinding. Pemeriksaan dilakukan di tempat yang sama: pada next, sel di depan, sebelum kepala bergerak, sehingga kepala tetap di tempatnya saat permainan berakhir.
Satu segmen aman. Pada langkah ini, segmen terakhir juga bergerak ke atas, keluar dari selnya, jadi kepala yang mengikuti ujung ekornya ke sel itu tidak akan pernah menyentuhnya. Ular yang terdiri dari empat kubus bisa mengitari persegi berukuran 2 kali 2 selamanya dengan cara ini. Pemeriksaan tidak menyertakan segmen terakhir dengan berhenti satu langkah sebelum akhir:
// setiap item kecuali yang terakhir
for (int i = 0; i < items.Count - 1; i++)
{
Debug.Log(items[i].name);
}Dengan dinding dan ekor yang sama-sama mematikan, permainan bisa berakhir dengan kekalahan, dan bab berikutnya menambahkan skor serta cara untuk bermain lagi.
Tantangan
SedangDi dalam Step(), setelah pemeriksaan dinding: jika next adalah sel salah satu segmen ekor selain segmen terakhir, panggil Die() lalu kembalikan, agar kepala tidak bergerak.
Tekan Play, panjangkan ular dan gigit ekormu, lalu tekan Check.
Coba sendiri
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // detik antara dua langkah
public int edge = 7; // sel papan membentang dari -edge hingga edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
public Transform segmentPrefab;
private float timer;
private Vector3 direction = Vector3.right; // arah gerak kepala pada langkah terakhirnya
private Vector3 nextDirection = Vector3.right; // belokan yang menunggu langkah berikutnya
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;
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.