zoukankan      html  css  js  c++  java
  • 《Genesis-3D开源游戏引擎--横版格斗游戏制作教程03:碰撞检测》

    3.碰撞检测

    碰撞检测的概述:

    碰撞在物理学中表现为两粒子或物体间极端的相互作用。而在游戏世界中,游戏对象在游戏世界自身并不受物理左右,为了模拟真实世界的效果,需要开发者为其添加属性,以模拟真实事件的运动效果。在游戏世界里,当游戏主角与其它游戏对象发生碰撞时,都会触发一个相应的事件发生。这时候就需要开发者先检测到碰撞现象,即碰撞检测。在Genesis-3D引擎中,能检测碰撞发生的方式有两种:一种是利用碰撞器,一种是利用触发器。

    碰撞检测原理:

    为需要检测碰撞事件的物体创建子空Actor,作为检测碰撞物体的包装盒,用于程序对碰撞事件发生的判定。实时检测包围盒之间是否发生交叉、包含等关系时候,如若发生,及判定检测碰撞发生,触发碰撞事件。


    图3-1-1
     

    实现方法:
    实现整个碰撞事件过程中,值得开发者花心思的是检测这一块内容。举例:主角攻击敌人的碰撞检测事件。在一定范围内,玩家控制主角攻击敌人,武器与敌人发生碰撞检测事件,敌人掉血。本来一系列的程序设定都十分顺畅,但这里要注意,因为碰撞检测是实时监测,但是碰撞结果掉血在这一过程中只发生一次,如何在一定事件内,只发生一次碰撞事件的成功检测,值得开发者考究一下。

    步骤1:
    碰撞检测体包围盒的制作。在场景中创建->空物体(空物体,即空Actor),将空Actor拖动到物体上,成为其子空Actor。
    步骤2:
    程序上碰撞提包围盒的创建如下所示。

    01
    //玩家碰撞体的创建,三部分:左手、右手和身体
    02
    public override void OnLoad()
    03
    {
    04
     Actor leftActor = ActorManager.FindActiveActor("BBCollider_LeftCollider");
    05
     Actor rightActor = ActorManager.FindActiveActor("BBCollider_RightCollider");
    06
     Actor playerActor = ActorManager.FindActiveActor("BBCollider_Player");
    07
     playerCollder.RegistFun(playerActor,BBCollideHitCallBack);
    08
     leftCollder.RegistFun(leftActor ,BBCollideCallBack);
    09
     rightCollder.RegistFun(rightActor,BBCollideCallBack);
    10
     Logic.BBCollideMgr.Instance.Register(leftCollder);
    11
     Logic.BBCollideMgr.Instance.Register(rightCollder);
    12
     Logic.BBCollideMgr.Instance.Register(playerCollder);
    13
    }
    14
    //敌人的碰撞体创建分两部分:武器和身体。
    15
    public override void OnLoad()//武器
    16
    {
    17
     Logic.BBCollder weaponCollder = new Logic.BBCollder();
    18
     Actor weaponCollderActor = Owner;
    19
     if (weaponCollderActor != null)
    20
     {
    21
      weaponCollder.RegistFun(weaponCollderActor, BBCollideATKCallBack);
    22
      Logic.BBCollideMgr.Instance.Register(weaponCollder);
    23
     }
    24
    }
    25
     
    26
    public override void OnLoad()//敌人
    27
    {
    28
     string ownerNum = Owner.Name.Substring(TriggerNameHead.Length);
    29
     EnemyParent = ActorManager.FindActiveActor(EnemyParentNameHead + ownerNum);
    30
     Name = "BBCollider_Enemy001";
    31
     Logic.BBCollder collder = new Logic.BBCollder();
    32
     Actor collderActor = Owner;
    33
     if (collderActor != null)
    34
     {
    35
      collder.RegistFun(collderActor, BBCollideCallBack);
    36
      Logic.BBCollideMgr.Instance.Register(collder);
    37
     }
    38
    }
    步骤3:
    碰撞检测。
    view sourceprint?
    01
    //实时监测碰撞状态
    02
    public void Tick(float elapseTime)
    03
    {
    04
     //遍历碰撞体容器,检测每两个碰撞体间碰撞状态
    05
     int iCollidersCount = Colliders.Count;
    06
     for (int ii = 0; ii < iCollidersCount; ++ii)
    07
     {
    08
      for (int jj = ii + 1; jj < iCollidersCount; ++jj)
    09
      {
    10
       RemoveBeCollidedActor(Colliders[ii], Colliders[jj]);
    11
       BoundingBox bbi = Colliders[ii].ColliderActor.WorldBoundingBox;
    12
       BoundingBox bbj = Colliders[jj].ColliderActor.WorldBoundingBox;
    13
       if (ClipStatus.Outside != bbi.Contains(bbj) && ClipStatus.Outside != bbj.Contains(bbi))
    14
       {
    15
        if (Colliders[jj].ColliderActor.IsActive && !Colliders[ii].IsContainsBeCollidedActor(Colliders[jj].ColliderActor))
    16
        {
    17
         Colliders[ii].Call(Colliders[jj].ColliderActor);
    18
         Colliders[ii].AddBeCollidedActor(Colliders[jj].ColliderActor);
    19
        }
    20
     
    21
        if (Colliders[ii].ColliderActor.IsActive && !Colliders[jj].IsContainsBeCollidedActor(Colliders[ii].ColliderActor))
    22
        {
    23
         Colliders[jj].Call(Colliders[ii].ColliderActor);
    24
         Colliders[jj].AddBeCollidedActor(Colliders[ii].ColliderActor);
    25
        }
    26
       }
    27
      }
    28
     }
    29
    }
    30
    //移除碰撞对象
    31
    private void RemoveBeCollidedActor(BBCollder actor, BBCollder beCollided)
    32
    {
    33
     BoundingBox actorBox = actor.ColliderActor.WorldBoundingBox;
    34
     BoundingBox beCollidedBox = beCollided.ColliderActor.WorldBoundingBox;
    35
     if (ClipStatus.Outside == actorBox.Contains(beCollidedBox))
    36
     {
    37
      actor.RemoveBeCollidedActor(beCollided.ColliderActor);               
    38
     }
    39
      if (ClipStatus.Outside == beCollidedBox.Contains(actorBox))
    40
     {
    41
      beCollided.RemoveBeCollidedActor(actor.ColliderActor);               
    42
     }
    43
    }
    44
     
    45
    //定义BBCollder类
    46
    public class BBCollder
    47
    {
    48
     public void RegistFun(Actor self, callback fun)
    49
     {
    50
      _colliderActor = self;
    51
      _callback = fun;
    52
     }
    53
     public void Call(Actor other)
    54
     {
    55
      _callback(other);
    56
     }
    57
         //
    58
    public void RemoveBeCollidedActor(Actor beCollidedActor)
    59
    {
    60
     if (_beCollidedActors.Contains(beCollidedActor))
    61
     {
    62
      _beCollidedActors.Remove(beCollidedActor);
    63
     }
    64
    }
    65
    public bool IsContainsBeCollidedActor(Actor beCollidedActor)
    66
    {
    67
     return _beCollidedActors.Contains(beCollidedActor);
    68
    }
    69
    public delegate void callback(Actor other);//注册回调函数???
    70
    private callback _callback;
    71
    private Actor _colliderActor;
    72
    private List<actor> _beCollidedActors = new List<actor>(); //碰撞中Actor列表</actor></actor>
    步骤4:
    碰撞效果。举例:主角攻击敌人,敌人掉血。
    01
    public void BBCollideHitCallBack (Actor other)
    02
    {
    03
     if (other.Name.StartsWith ("BBCollider_EnemyATK"))
    04
     {
    05
     EnemyState state = Logic.EnemyMgr.Instance.EnemyState(other.Parent.Name);
    06
     bool judget = Logic.EnemyMgr.Instance.GetEnemyJudge(other.Parent.Name);
    07
      if (state == EnemyState.Attack && judget
    08
                      && !Logic.LogicMgr.Instance.CurPlayer.CheckDefenseState()
    09
                      && !Logic.LogicMgr.Instance.CurPlayer.CheckDieState())
    10
      {
    11
       int playerHP = Logic.PlayerDateMgr.Instance.HP;
    12
       playerHP --;
    13
       Logic.PlayerDateMgr.Instance.SetHP(playerHP);
    14
       Logic.LogicMgr.Instance.CurPlayer.State = Logic.CharacterState.Hurt;
    15
      }
    16
     }
    17
    }

     

    引擎官方网站:http://www.genesis-3d.com.cn/

    官方论坛:http://bbs.9tech.cn/genesis-3d/

    官方千人大群:59113309   135439306

    YY频道-游戏开发大讲堂(完全免费,定期开课):51735288 

    Genesis-3D开源游戏引擎:游戏起源,皆因有我!!!

     
  • 相关阅读:
    总结
    设置导航栏上面的内容
    统一所有控制器导航栏左上角和右上角内容
    直接设置UIView的x,y,width,height...
    block浅析
    const浅析
    - (BOOL)isEqual:(id)object
    数据存入沙盒
    swift感悟2
    swift自学感悟1
  • 原文地址:https://www.cnblogs.com/G-3D/p/3500784.html
Copyright © 2011-2022 走看看