OT源代码的分析,OrtHello 迟早攻破你 (八)第3个例子,碰撞检测和动画

第3个例子其实是一个简易的飞行射击游戏的模型了=。= 看一下效果

场景中存在的预设物体


看看背后是如何做的:

有3个脚本:CExample3,CAsteroid3,CBullet3

难点:控制序列帧动画,控制动作,销毁物体

先在场景中预设了3个石头,一个子弹,然后通过实例化这些预设物体来进行多帧相同物体的操作

下面的东西可能没什么深度-,- 我会在后面补偿的


首先看看CExample3:MonoBehaviour
    public OTSprite bullet;             //用来附带子弹的脚本的

    public OTAnimatingSprite a1;  //因为这个例子里面有三种不同的动画,所以有三种不同的Animate
    public OTAnimatingSprite a2;
    public OTAnimatingSprite a3;

    OTAnimatingSprite gun;              //枪的动画是
    bool initialized = false;           //

    void Awake()
    {  //重点,为什么这么做呢,将他们的active设为false不就动不了了吗?-,- 原因是为了复制clone
        a1.gameObject.active = false;
        a2.gameObject.active = false;
        a3.gameObject.active = false;
        // By de-acivating a gameobject is becomes invisible but can still
        // be used them to instantiate copies.
    }

    int dp = 100;
    //这个方法创造一个随机点在屏幕上的石头,
    // 可以有一个新的尺寸
    OTAnimatingSprite RandomBlock(Rect r, float min, float max, OTObject o)
    {
        int t = 1 + (int)Mathf.Floor(Random.value * 3);  //3种石头  随机一种
        float s = min + Random.value * (max - min);  //最小值到 最大值的随机尺寸
        GameObject g = null;

        switch (t)
        {
            case 1: g = OT.CreateObject("asteroid1");
                break;
            case 2: g = OT.CreateObject("asteroid2");
                break;
            case 3: g = OT.CreateObject("asteroid3");
                break;
        }
        if (g != null)
        {
            g.gameObject.active = true;
            OTAnimatingSprite sprite = g.GetComponent<OTAnimatingSprite>();
            if (o != null)
                sprite.size = o.size * s;
            else
                sprite.size = sprite.size * s;

            sprite.position = new Vector2(r.xMin + Random.value * r.width, r.yMin + Random.value * r.height); //设置随机点
            sprite.rotation = Random.value * 360;
            sprite.depth = dp++;
            if (dp > 750) dp = 100;  //为了防止爆深度,-,-深度只在-1000 到1000
            return sprite;
        }
        return null; //奇怪,这个方法没有返回值为什么还要设类型
    }
    

    void CreateObjectPools() //创建缓冲池
    {
        OT.PreFabricate("asteroid1",20);
        OT.PreFabricate("asteroid2",20);
        OT.PreFabricate("asteroid3",20);        
    }

    void Initialize()
    {
        gun = OT.ObjectByName("gun") as OTAnimatingSprite;
        gun.onAnimationFinish = OnAnimationFinish;  //枪的完成动画回调函数
        // 重点  Create our object pool if we want.
        OT.objectPooling = true;
        if (OT.objectPooling)
            CreateObjectPools();
        initialized = true;
    }

    public void Explode(OTObject o, CBullet3 bullet) //被摧毁的效果
    {
        // Determine how many debree has to be be created
        int blocks = 2 + (int)Mathf.Floor(Random.value * 2);

        OT.DestroyObject(o);
        // Create debree
        for (int b = 0; b < blocks; b++)
        {
            // Shrink asteroid's rect to act as the random position container
            // for the debree
            Rect r = new Rect(
                o.rect.x + o.rect.width / 4,
                o.rect.y + o.rect.height / 4,
                o.rect.width / 2,
                o.rect.height / 2);
            // Create a debree that is relatively smaller than the asteroid that was detroyed
            OTAnimatingSprite a = RandomBlock(r, 0.6f, 0.75f, o);
                        
            // Add this debree to the bullet telling the bullet to ignore this debree
            // in this update cycle - otherwise the bullet explosions could enter some
            // recursive 'dead' loop creating LOTS of debree
            bullet.AddDebree(a);
            // Recusively explode 2 asteroids if they are big enough, to get a nice
            // exploding debree effect.
            if (b < 2 && a.size.x > 30)
                Explode(a, bullet);
        }
    }

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

        if (!initialized)
        {
            Initialize();
            return;
        }

        gun.RotateTowards(OT.view.mouseWorldPosition); //设置我们的枪的指向
        bullet.rotation = gun.rotation; //子弹方向


        if (Input.GetMouseButtonDown(0)) //发射子弹
        {
            //重点,创建新子弹
            OTSprite nBullet = (Instantiate(bullet.gameObject) as GameObject).GetComponent<OTSprite>();
            nBullet.position = gun.position + ((Vector2)gun.transform.up * (gun.size.y / 2));
            gun.PlayOnce("shoot"); //枪播放射击的动画
        }

        //不能多于15个子弹
        if (OT.objectCount <= 15)
            RandomBlock(OT.view.worldRect, 0.6f, 1.2f, null);        
    }

   //枪的动画回调函数
    public void OnAnimationFinish(OTObject owner)
    {
        if (owner == gun)
        {
            gun.PlayLoop("idle"); //播放完射击的动画之后,枪回调回正常的动画
        }
    }


看看太空石头的类

public class CAsteroid3 : MonoBehaviour {

    OTAnimatingSprite sprite;               // 石头动画的sprite
    Vector2 forwardVector = Vector2.zero;   // 石头的运动方向
    OTSpriteSheet  sheet1;

    void Start () {
        sprite =  GetComponent<OTAnimatingSprite>();
        sheet1 = OT.ContainerByName("asteroid sheet 1") as OTSpriteSheet;
    }
   
    void Update () {            
        // If we did not capture this sprite's formward vector we capture it once
        if (Vector2.Equals(forwardVector, Vector2.zero))
            forwardVector = transform.up;

        sprite.position += (forwardVector * 50 * Time.deltaTime);
        sprite.rotation += 30 * Time.deltaTime;

        if (sprite.size.x < 50 || sprite.size.y < 50)
        {
            sprite.Stop();
            sprite.depth = 100;
            sprite.frameIndex = 0;
            sprite.rotation += 90 * Time.deltaTime;
            if (sprite.size.x < 10 || sprite.size.y < 10)
            {
                sprite.spriteContainer = sheet1;
                sprite.size = sprite.size * (1f - (0.99f * Time.deltaTime));
            }
            else
                sprite.size = sprite.size * (1f - (0.95f * Time.deltaTime));
           

            //如果石头小于2个像素则删除它
            if (sprite.size.x < 2 || sprite.size.y < 2)
                OT.DestroyObject(sprite);
        }


        //超出视野就将石头放回缓冲池
        if (sprite.outOfView)
            OT.DestroyObject(sprite);
    }
}

//         子弹的类           //

public class CBullet3 : MonoBehaviour {

    OTSprite sprite;                            // 子弹的sprite
    CExample3 app;                              //主应用的类

    int speed = 1000;                           // 子弹速率  speed  将会乘以一个子弹方向
    float ignoreCollisions = 0;                 // 作为一个子弹的


    List<OTAnimatingSprite> debree =            // created debree list
        new List<OTAnimatingSprite>();

    void Start () {
        app = Camera.main.GetComponent<CExample3>();

        sprite = GetComponent<OTSprite>();
        sprite.onCollision = OnCollision;
    }
    

    void Update () {
        //检查是否是刚成立的,忽略刚成立0.1秒的物体
        if (ignoreCollisions > 0)
        {
            ignoreCollisions -= Time.deltaTime; //忽略时间每秒减1
            if (ignoreCollisions < 0) ignoreCollisions = 0;
        }
        else
        {
            //不再忽略已经成立了1秒的
            debree.Clear();
        }
        // 更新子弹位置
        sprite.position += (Vector2)sprite.transform.up    * speed * Time.deltaTime;
        //消除子弹如果失去视野
        if (sprite.outOfView)
          OT.DestroyObject(sprite);
    }

    public void AddDebree(OTAnimatingSprite debreeObject)
    {
        debree.Add(debreeObject);
    }

    //碰撞
    public void OnCollision(OTObject owner)
    {
        //检查我们碰撞的是否在我们的忽略列表里面
        if (debree.IndexOf(owner.collisionObject as OTAnimatingSprite) < 0)
        {
            //  忽略0.1秒之前发生的
            ignoreCollisions = 0.1f;
            // Lets Explode this asteroid
            app.Explode(owner.collisionObject, this);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值