נשוך את עצמך
שיעור 10 מתוך 14 בקורס משחק Unity: נחש בתלת־ממד של Coddy.
הנחש מת כשהראש שלו נתקל בזנב שלו, בדיוק כפי שהוא מת כשהוא נתקל בקיר. הבדיקה מתבצעת באותו מקום: על next, התא שלפנים, לפני שהראש זז, כך שהראש נשאר במקומו כשהמשחק מסתיים.
מקטע אחד בטוח. בצעד הזה גם המקטע האחרון זז למעלה, ויוצא מהתא שלו, ולכן ראש שעוקב אחר קצה הזנב שלו אל התא הזה לעולם לא נוגע בו. נחש המורכב מארבעה קוביות יכול להקיף ריבוע של 2 על 2 לנצח בדרך הזאת. הבדיקה משאירה את המקטע האחרון מחוץ לבדיקה בכך שהיא עוצרת אחד לפני הסוף:
// כל פריט מלבד האחרון
for (int i = 0; i < items.Count - 1; i++)
{
Debug.Log(items[i].name);
}כשהקירות והזנב קטלניים, אפשר להפסיד במשחק, ובפרק הבא יתווספו הניקוד ואפשרות לשחק שוב.
אתגר
בינוניב־Step(), אחרי בדיקת הקיר: אם next הוא התא של אחד ממקטעי הזנב מלבד האחרון, יש לקרוא ל־Die() ולחזור, כדי שהראש לא יזוז.
לחצו על Play, האריכו את הנחש ונשכו את הזנב שלכם, ואז לחצו על Check.
נסו בעצמכם
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // מספר השניות בין שני צעדים
public int edge = 7; // תאי הלוח נעים מ־-edge עד edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
public Transform segmentPrefab;
private float timer;
private Vector3 direction = Vector3.right; // הכיוון שבו הראש נע בצעד האחרון שלו
private Vector3 nextDirection = Vector3.right; // הפנייה שממתינה לצעד הבא
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;
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.