开发框架——横版格斗——3.碰撞检测

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:

碰撞检测。

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 }

 

阅读更多
个人分类: 游戏开发
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭