3.碰撞检测

碰撞检测的概述:

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

碰撞检测原理:

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


图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开源游戏引擎:游戏起源,皆因有我!!!

 

《Genesis-3D开源游戏引擎--横版格斗游戏制作教程03:碰撞检测》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Oracle wrap 测试的一些细节问题

    今天在做 wrap 的测试实验的时候,出现一个很奇怪的现象,就是加密不成功.具体表现为:1.加密后的文件大小为0kb. 2.加密后的文件仍然可视. 具体测试步骤如下: D:\Just4work\som ...

  2. 图片上传iOS

    //图片上传 - (void)upLoadImage{ if(self.frontImage && self.backImage){ //性别 NSString *sexStr; if ...

  3. 如何学习C++[转]

    关于学C++, 我向你推荐一些书(当然能够结合课内项目实践更好) 1.The C++ Programming Language(Bjarne Stroustrup)2. Inside The C++ ...

  4. CSS3学习之 animation 属性

    发现animation这个新属性很有趣,在此学习,并整理下!  浏览器支持: Internet Explorer 10.Firefox 以及 Opera 支持 animation 属性: Safari ...

  5. Spring 数据源配置一:单一数据源

    最近遇到一个项目,需要访问都多个数据源,并且数据库是不同厂商(mysql,  sqlserver). 所以对此做了一些研究,这里咱们采用渐进的方式来展开,先谈谈单一数据源配置.(稍后有时间会陆续补充其 ...

  6. java常见内存溢出(OOM)

    jvm内存区域 程序计数器一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. java栈与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存放基本数据类型, ...

  7. hdu 4286

    splay 练手用: 杭电的oj要手动开栈: #include<cstdio> #pragma comment(linker, "/STACK:102400000,1024000 ...

  8. Newtonsoft.Json.JsonWriter

    [一篮饭特稀原创,转载请注明出自http://www.cnblogs.com/wanghafan/p/4754769.html]  JsonWriter使用: 前台 $.post("Ajax ...

  9. 4. 在Inspector面板中显示类中变量+ 拓展编辑器

    1. C#脚本如下: using UnityEngine; using System.Collections; public class MyTest : MonoBehaviour { ; ; [S ...

  10. 【Xamarin挖墙脚系列:IOS-关于手机支持的屏幕方向】

    原文:[Xamarin挖墙脚系列:IOS-关于手机支持的屏幕方向] 设置支持的屏幕方向有两个级别,一个是app级别的,另一个是viewController级别的. app 级别的可以在[target] ...