《Genesis-3D开源游戏引擎--横版格斗游戏制作教程03:碰撞检测》

时间:2021-11-22 15:58:57

3.碰撞检测

碰撞检测的概述:

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

碰撞检测原理:

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

《Genesis-3D开源游戏引擎--横版格斗游戏制作教程03:碰撞检测》
图3-1-1
 

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

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

//玩家碰撞体的创建,三部分:左手、右手和身体

public override void OnLoad()

{

 Actor leftActor = ActorManager.FindActiveActor("BBCollider_LeftCollider");

 Actor rightActor = ActorManager.FindActiveActor("BBCollider_RightCollider");

 Actor playerActor = ActorManager.FindActiveActor("BBCollider_Player");

 playerCollder.RegistFun(playerActor,BBCollideHitCallBack);

 leftCollder.RegistFun(leftActor ,BBCollideCallBack);

 rightCollder.RegistFun(rightActor,BBCollideCallBack);

 Logic.BBCollideMgr.Instance.Register(leftCollder);

 Logic.BBCollideMgr.Instance.Register(rightCollder);

 Logic.BBCollideMgr.Instance.Register(playerCollder);

}

//敌人的碰撞体创建分两部分:武器和身体。

public override void OnLoad()//武器

{

 Logic.BBCollder weaponCollder = new Logic.BBCollder();

 Actor weaponCollderActor = Owner;

 if (weaponCollderActor != null)

 {

  weaponCollder.RegistFun(weaponCollderActor, BBCollideATKCallBack);

  Logic.BBCollideMgr.Instance.Register(weaponCollder);

 }

}

public override void OnLoad()//敌人

{

 string ownerNum = Owner.Name.Substring(TriggerNameHead.Length);

 EnemyParent = ActorManager.FindActiveActor(EnemyParentNameHead + ownerNum);

 Name = "BBCollider_Enemy001";

 Logic.BBCollder collder = new Logic.BBCollder();

 Actor collderActor = Owner;

 if (collderActor != null)

 {

  collder.RegistFun(collderActor, BBCollideCallBack);

  Logic.BBCollideMgr.Instance.Register(collder);

 }

}
步骤3:
碰撞检测。
view sourceprint? //实时监测碰撞状态 public void Tick(float elapseTime) {  //遍历碰撞体容器,检测每两个碰撞体间碰撞状态  int iCollidersCount = Colliders.Count;  for (int ii = ; ii < iCollidersCount; ++ii)  {   for (int jj = ii + ; jj < iCollidersCount; ++jj)   {    RemoveBeCollidedActor(Colliders[ii], Colliders[jj]);    BoundingBox bbi = Colliders[ii].ColliderActor.WorldBoundingBox;    BoundingBox bbj = Colliders[jj].ColliderActor.WorldBoundingBox;    if (ClipStatus.Outside != bbi.Contains(bbj) && ClipStatus.Outside != bbj.Contains(bbi))    {     if (Colliders[jj].ColliderActor.IsActive && !Colliders[ii].IsContainsBeCollidedActor(Colliders[jj].ColliderActor))     {      Colliders[ii].Call(Colliders[jj].ColliderActor);      Colliders[ii].AddBeCollidedActor(Colliders[jj].ColliderActor);     }     if (Colliders[ii].ColliderActor.IsActive && !Colliders[jj].IsContainsBeCollidedActor(Colliders[ii].ColliderActor))     {      Colliders[jj].Call(Colliders[ii].ColliderActor);      Colliders[jj].AddBeCollidedActor(Colliders[ii].ColliderActor);     }    }   }  } } //移除碰撞对象 private void RemoveBeCollidedActor(BBCollder actor, BBCollder beCollided) {  BoundingBox actorBox = actor.ColliderActor.WorldBoundingBox;  BoundingBox beCollidedBox = beCollided.ColliderActor.WorldBoundingBox;  if (ClipStatus.Outside == actorBox.Contains(beCollidedBox))  {   actor.RemoveBeCollidedActor(beCollided.ColliderActor);  }   if (ClipStatus.Outside == beCollidedBox.Contains(actorBox))  {   beCollided.RemoveBeCollidedActor(actor.ColliderActor);  } } //定义BBCollder类 public class BBCollder {  public void RegistFun(Actor self, callback fun)  {   _colliderActor = self;   _callback = fun;  }  public void Call(Actor other)  {   _callback(other);  } // public void RemoveBeCollidedActor(Actor beCollidedActor) {  if (_beCollidedActors.Contains(beCollidedActor))  {   _beCollidedActors.Remove(beCollidedActor);  } } public bool IsContainsBeCollidedActor(Actor beCollidedActor) {  return _beCollidedActors.Contains(beCollidedActor); } public delegate void callback(Actor other);//注册回调函数??? private callback _callback; private Actor _colliderActor; private List<actor> _beCollidedActors = new List<actor>(); //碰撞中Actor列表</actor></actor>
步骤4:
碰撞效果。举例:主角攻击敌人,敌人掉血。 public void BBCollideHitCallBack (Actor other) {  if (other.Name.StartsWith ("BBCollider_EnemyATK"))  {  EnemyState state = Logic.EnemyMgr.Instance.EnemyState(other.Parent.Name);  bool judget = Logic.EnemyMgr.Instance.GetEnemyJudge(other.Parent.Name);   if (state == EnemyState.Attack && judget && !Logic.LogicMgr.Instance.CurPlayer.CheckDefenseState() && !Logic.LogicMgr.Instance.CurPlayer.CheckDieState())   {    int playerHP = Logic.PlayerDateMgr.Instance.HP;    playerHP --;    Logic.PlayerDateMgr.Instance.SetHP(playerHP);    Logic.LogicMgr.Instance.CurPlayer.State = Logic.CharacterState.Hurt;   }  } }

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

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

官方千人大群:59113309   135439306

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

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