《Genesis-3D开源游戏引擎--横版格斗游戏制作教程03:碰撞检测》
3.碰撞检测
碰撞检测的概述:
碰撞在物理学中表现为两粒子或物体间极端的相互作用。而在游戏世界中,游戏对象在游戏世界自身并不受物理左右,为了模拟真实世界的效果,需要开发者为其添加属性,以模拟真实事件的运动效果。在游戏世界里,当游戏主角与其它游戏对象发生碰撞时,都会触发一个相应的事件发生。这时候就需要开发者先检测到碰撞现象,即碰撞检测。在Genesis-3D引擎中,能检测碰撞发生的方式有两种:一种是利用碰撞器,一种是利用触发器。
碰撞检测原理:
为需要检测碰撞事件的物体创建子空Actor,作为检测碰撞物体的包装盒,用于程序对碰撞事件发生的判定。实时检测包围盒之间是否发生交叉、包含等关系时候,如若发生,及判定检测碰撞发生,触发碰撞事件。
![](http://www.genesis-3d.com.cn/tech_sup/framework/ACT/images/3-1-1.jpg)
图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开源游戏引擎:游戏起源,皆因有我!!!