انمُ
الدرس 8 من 14 في دورة لعبة الثعبان ثلاثية الأبعاد في Unity على Coddy.
يؤدي الأكل إلى زيادة طول الثعبان بمقطع واحد. يقع المقطع الجديد في المكان الذي كان يشغله طرف الذيل قبل الخطوة: يتحرك الذيل إلى الأمام، ويملأ المقطع الجديد الخلية التي تركها الطرف، لذلك ينمو الثعبان من الخلف.
تختفي تلك الخلية بعد تحرك الذيل، لذا تذكّرها أولًا. ثم، عندما يصل الرأس إلى الطعام، أنشئ مقطعًا هناك وأضِفه إلى القائمة، لكي يتبعه ابتداءً من الخطوة التالية. المقطع الذي يُنشأ ولا يُضاف لا يتحرك أبدًا. تُضيف القطارات عربةً في الخلف بالطريقة نفسها:
Vector3 back = wagons[wagons.Count - 1].position;
// ... يواصل القطار سيره ...
Transform wagon = Instantiate(wagonPrefab, back, Quaternion.identity);
wagons.Add(wagon);أنمِ الثعبان قبل استدعاء Eat(). تنقل Eat() الطعام، وفي الدرس التالي ستجعلها تبحث عن خلية لا يشغلها الثعبان، بما في ذلك المقطع الجديد.
التحدي
متوسطيضبط المشهد segmentPrefab الخاص بـSnake على مكعب مثل الذيل.
- أضف
public Transform segmentPrefab;. - في
Step()، قبل أن يتحرك الذيل، احتفظ بخلية آخر جزء من الذيل فيVector3 tailEnd(خلية الرأس عندما يكون الذيل فارغًا). - عندما يكون الرأس فوق الطعام، أنشئ نسخة من
segmentPrefabعندtailEndوأضفها إلىtail، ثم استدعِEat().
اضغط 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>();
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;
}
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))
{
GameManager.Instance.Eat();
}
}
void Die()
{
alive = false;
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.