Beiße dich selbst
Lektion 10 von 14 im Kurs Unity-Spiel: 3D-Snake von Coddy.
Die Schlange stirbt, wenn ihr Kopf gegen ihren eigenen Schwanz stößt, genau wie bei einer Wand. Die Prüfung erfolgt an derselben Stelle: bei next, dem Feld vor ihr, bevor sich der Kopf bewegt. So bleibt der Kopf an seiner Stelle, wenn das Spiel endet.
Ein Segment ist ungefährlich. In diesem Schritt bewegt sich auch das letzte Segment nach oben aus seinem Feld heraus, sodass ein Kopf, der dem Ende seines Schwanzes in dieses Feld folgt, es nie berührt. Eine Schlange aus vier Würfeln kann auf diese Weise für immer ein Quadrat mit einer Seitenlänge von 2 umkreisen. Bei der Prüfung bleibt das letzte Segment außen vor, indem sie einen Schritt vor dem Ende stoppt:
// jedes Element außer dem letzten
for (int i = 0; i < items.Count - 1; i++)
{
Debug.Log(items[i].name);
}Da sowohl die Wände als auch der Schwanz tödlich sind, kann man das Spiel verlieren. Im nächsten Kapitel kommen die Punktzahl und eine Möglichkeit, erneut zu spielen, hinzu.
Aufgabe
MittelIn Step(), nach der Wandprüfung: Wenn next die Zelle eines beliebigen Schlangensegments außer des letzten ist, rufe Die() auf und kehre zurück, damit sich der Kopf nicht bewegt.
Drücke Play, lass die Schlange wachsen und beiße dir in den Schwanz. Drücke dann Check.
Probier es selbst
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // Sekunden zwischen zwei Schritten
public int edge = 7; // die Zellen des Spielfelds reichen von -edge bis edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
public Transform segmentPrefab;
private float timer;
private Vector3 direction = Vector3.right; // die Richtung, in die sich der Kopf beim letzten Schritt bewegt hat
private Vector3 nextDirection = Vector3.right; // die für den nächsten Schritt vorgemerkte Richtungsänderung
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;
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.