Menu
CoddyTech

أسرع فأسرع

الدرس 13 من 14 في دورة لعبة Unity: الثعبان ثلاثي الأبعاد على Coddy.

تصبح لعبة Snake أصعب كلما كبرت: فكل طعام يجعل مدة النبضة أقصر قليلًا، لذا تتحرك الأفعى بسرعة أكبر. يضمن الحد الأدنى بقاء اللعبة قابلة للعب: وهو أقصر مدة نبضة يمكن أن تصل إليها.

تعيد Mathf.Max الأكبر من رقمين، ما يجعلها حدًا أدنى: فالقيمة Mathf.Max(value, floor) لا تقل أبدًا عن floor. برج يطلق النار بسرعة أكبر مع كل ترقية، ولكن ليس أكثر من مرة كل 0.2 ثانية:

cooldown = Mathf.Max(cooldown - 0.05f, 0.2f);

Mathf.Min هي العكس، أي حد أعلى. من السهل الخلط بينهما: باستخدام Min، سينخفض وقت التهدئة أعلاه إلى 0.2 عند أول ترقية. يقرأ المؤقت في Update() قيمة tick في كل إطار، لذا يبدأ احتساب مدة النبضة الأقصر من الخطوة التالية.

challenge icon

التحدي

صعب

تزداد سرعة الثعبان كلما أكل.

  1. في Snake، أضف public float speedUp = 0.005f; وpublic float minTick = 0.08f;
  2. عند تناول الطعام، اجعل قيمة tick أقصر بمقدار speedUp، ولا تقل أبدًا عن minTick: tick = Mathf.Max(tick - speedUp, minTick);

اضغط «العب» وتناول الطعام: يتحرك الثعبان بسرعة أكبر قليلًا في كل مرة. ثم اضغط «تحقق».

جرّب بنفسك

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;
        }

        for (int i = 0; i < tail.Count - 1; i++)
        {
            if (tail[i].position == next)
            {
                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;
        GameManager.Instance.GameOver();
    }
}

جميع دروس لعبة Unity: الثعبان ثلاثي الأبعاد

تدرّب بنفسك: Playground لـ Unity