OT源代碼的分析,OrtHello 遲早攻破你 (七)第2個例子,碰撞和簡單運動

首先記住在main的updata裏面,OT的初始化不是放在start中的,而是在update中的,具體做法是:

void Update () {
        if (!OT.isValid) return;

        if (!initialized)
            Initialize();
    }

-,-簡單有效orz

再看看CExample2 到底做了什麼,首先傳入了兩個OTsprite:

 public OTSprite blockPrototype; // prototype to create blocks
 public OTSprite starPrototype;  // prototype to create stars

然後就是初始化函數,你會發現update裏面什麼判斷都沒有

CreateObjects()
    {
        GameObject  blocks = GameObject.Find("Blocks");  // 這是在場景中的一個空的物體,最後當成邊界用
        if (blocks!=null)
        {
            int c = (Screen.width - 20) / 85;  由屏幕大小計算橫向可以擺多少個
            int s = (Screen.width - (c * 85)) / 2;  計算間隔
           
            for (int x = 0; x < c; x++)  // 創建橫向頂部的方塊
            {
                //關鍵部分,由blockPrototype來創建,屬性就會喝blockPrototype一摸一樣
                OTSprite b = (Instantiate(blockPrototype.gameObject) as GameObject).GetComponent<OTSprite>();
                b.position = new Vector2(s + 50 + (x * 85)- (Screen.width/2), 20 - (Screen.height/2));
                b.name = "bottom" + x;
                // 鏈接到父物體
                b.transform.parent = blocks.transform;
            }


            for (int x = 0; x < c; x++)//同理 創建橫向底部的方塊
            {
                OTSprite b = (Instantiate(blockPrototype.gameObject) as GameObject).GetComponent<OTSprite>();
                b.position = new Vector2(s + 50 + (x * 85) - (Screen.width / 2), Screen.height - 20 - (Screen.height / 2));
                b.name = "top" + x;
                b.transform.parent = blocks.transform;
            }

            c = (Screen.height - 50) / 85;
            s = (Screen.height - (c * 85)) / 2;


            for (int x = 0; x < c; x++)
            {
                OTSprite b = (Instantiate(blockPrototype.gameObject) as GameObject).GetComponent<OTSprite>();
                b.rotation = 90; // 旋轉了一下
                b.position = new Vector2(20 - (Screen.width / 2), (Screen.height/2) - 40 - s - (x*85) );
                b.name = "left" + x;
                b.transform.parent = blocks.transform;
            }

            for (int x = 0; x < c; x++)
            {
                OTSprite b = (Instantiate(blockPrototype.gameObject) as GameObject).GetComponent<OTSprite>();
                b.rotation = 90;
                b.position = new Vector2((Screen.width / 2)-20, (Screen.height / 2) - 40 - s - (x * 85));
                b.name = "right" + x;
                b.transform.parent = blocks.transform;
            }
        }

        GameObject stars = GameObject.Find("Stars"); //找到空物體星星
        if (stars != null)
        {
            int c = 50;   // 創建的星星數量
            for (int x = 0; x < c; x++)
            {
                // Create a new star
                OTSprite s = (Instantiate(starPrototype.gameObject) as GameObject).GetComponent<OTSprite>();
                s.position =
                    new Vector2(
                        -1 * (Screen.width / 2) + 50 + Random.value * (Screen.width - 100),
                        (Screen.height / 2) - 40 - Random.value * (Screen.height - 80));
                s.name = "star" + x;
                s.depth = 100 + x; //星星的深度設置  不同的深度才能顯示層次感
                s.transform.parent = stars.transform;
            }
        }
    }

可以看到其實初始化也沒做什麼事,判斷部分都是由碰撞器去做了


好吧,下面看看CBlock2 是如何附加碰撞器上去的

public class CBlock2 : MonoBehaviour {
    OTSprite sprite;                // This block's sprite class
    bool colorFade = false;         //是否漸變
    float fadeTime = 0;             // 漸變的計時器
    float fadeSpeed = 0.25f;         // 漸變速度
    
    Color startColor =
        new Color(0.3f, 0.3f, 0.3f); // 磚塊顏色

    void Start () {
        sprite = GetComponent<OTSprite>();
        // Set this sprite's collision delegate
        // HINT : We could use sprite.InitCallBacks(this) as well.
        // but because delegates are the C# way we will use this technique


        sprite.onCollision = OnCollision;
        sprite.tintColor = startColor;


        // Register this material with Orthello so we can re-use it later
        OT.RegisterMaterial("Block-start", new Material(sprite.material));
      
        for (int i=0; i<10; i++)    // Generate Highlight materials and store them
        {
            var m = new Material(sprite.material);
            m.SetColor("_EmisColor", Color.Lerp(Color.white,startColor,0.1f * i));
            OT.RegisterMaterial("Block-tint"+i, m);            
        }
    }

    void Update()
    {
        if (colorFade)
        {
            int    fadeIndex  =  (int)(Mathf.Floor((fadeTime / fadeSpeed) * 10));
            sprite.material = OT.LookupMaterial("Block-tint" + fadeIndex);

            fadeTime += Time.deltaTime;
            if (fadeTime >= fadeSpeed)
            {
                colorFade = false;

                if (OT.LookupMaterial("Block-start") == null)
                    print("Block-start material not found!");

                sprite.material = OT.LookupMaterial("Block-start");  // Set block's color to start color
            }
        }
    }

    public void OnCollision(OTObject owner)
    {
        colorFade = true;          // 碰撞後調用
        fadeTime = 0;           //再次設碰撞時間
    }
}

接着看最後的星星的部分

public class CStar2 : MonoBehaviour {

    OTSprite sprite;                    // 鏈接的sprite
    Vector2 speed =   new Vector2(150, 150);        // 每秒移動的速度
    float rotation = 90;                // 每秒轉動的角度

    Color startColor =  new Color(0.5f, 1f, 0.5f);    //  開始的顏色   一開始是綠色的
    Color stayColor =   new Color(1f, 1f, 1f);    // 重疊時的顏色    兩個星星重疊後顏色就變黑

    void Start () {
        sprite = GetComponent<OTSprite>();
        // Set this sprite's stay/exit/collision delegates
        sprite.onStay = OnStay;
        sprite.onExit = OnExit;
        sprite.onCollision = OnCollision;

      
        //給一個初始的隨機速度
        speed = new Vector2(150 + 150 * Random.value, 150 + 150 * Random.value);
        sprite.tintColor = startColor;

        // 註冊星星的材質以便後面使用到它
        OT.RegisterMaterial("Star-start", new Material(sprite.material));  //創建一個開始的材質材質
        var m = new Material(sprite.material);
        m.SetColor("_EmisColor", stayColor);
        OT.RegisterMaterial("Star-stay", m);// 創建一個靜態的材質
    }
   
    void Update () {
        sprite.position += speed * Time.deltaTime;  // 注意這裏還是乘以  Time.deltaTime  表示每秒多少個
        sprite.rotation  += (rotation * Time.deltaTime);
    }

    // OnStay delegate當這個星星撞到另一個星星時調用
    // !IMPORTANT - This sprite's collidable setting has to be true otherwide
    // collision delegates will not be called
    public void OnStay(OTObject owner)
    {
        //檢查我們是否碰到另一個星星  並且 調整顏色如果我們沒了
        if (owner.collisionObject.name.IndexOf("star") == 0)
            sprite.material = OT.LookupMaterial("Star-stay");  // 關鍵步驟  lookupMaterial
    }


    // OnExit delegate 離開星星時調用
    public void OnExit(OTObject owner)
    {
        if (owner.collisionObject.name.IndexOf("star") == 0)
            sprite.material = OT.LookupMaterial("Star-start");
    }


    // OnCollision 委託是碰到了邊界時候的處理方法
    // HINT - OnEnter and OnCollision delegates 確實同時發生, 唯一不同的是命名不同
    public void OnCollision(OTObject owner)
    {
        //檢查是否碰到上邊界
        if (owner.collisionObject.name.IndexOf("top") == 0 && speed.y > 0)
        {
            speed = new Vector2(speed.x, speed.y * -1);
            if ((speed.x < 0 && rotation > 0) || (speed.x > 0 && rotation < 0))
                rotation *= -1;
        }
        else
            //檢查是否碰到下邊界
            if (owner.collisionObject.name.IndexOf("bottom") == 0 && speed.y < 0)
            {
                speed = new Vector2(speed.x, speed.y * -1);
                if ((speed.x < 0 && rotation < 0) || (speed.x > 0 && rotation > 0))
                    rotation *= -1;
            }
            else
                //檢查是否碰到左邊界
                if (owner.collisionObject.name.IndexOf("left") == 0 && speed.x < 0)
                {
                    speed = new Vector2(speed.x * -1, speed.y);
                    if ((speed.y < 0 && rotation > 0) || (speed.y > 0 && rotation < 0))
                        rotation *= -1;
                }
                else
                    //檢查是否碰到右邊界
                    if (owner.collisionObject.name.IndexOf("right") == 0 && speed.x > 0)
                    {
                        speed = new Vector2(speed.x * -1, speed.y);
                        if ((speed.y < 0 && rotation < 0) || (speed.y > 0 && rotation > 0))
                            rotation *= -1;
                    }
    }

}



發佈了32 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章