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. 七,WPF的元素绑定

    数据绑定是一种关系,该关系告诉WPF从一个源对象提取一些信息,并使用这些信息设置目标对象的属性,目标属性总是依赖项属性,然而,源对象可以是任何内容. 源对象是WPF元素并且源属性是依赖项属性的数据绑定 ...

  2. 【web安全】第六弹:手工SQL注入详解

    前一段时间,在对SQL注入有了新的理解之后,写了这篇文章.本来准备投稿,因为内容过于基础被打回来了,想想屯着也没意思,发出来发出来~~本来有好多图的,但是博客园发图很麻烦,word文档的链接会贴在文章 ...

  3. IIS MIME类型问题(html5 video 本地打开可以,IIS打开不了)

    问题: mediaelement js(html 5 视频插件)网页用ie9本地打开可以,iis,vs2010在ie9上运行不了,chrome可以 (在博客园里有个人跟我遇到相同的问题:http:// ...

  4. android 界面布局 很好的一篇总结[转]

    1.LinearLayout ( 线性布局 ) :(里面只可以有一个控件,并且不能设计这个控件的位置,控件会放到左上角) 线性布局分为水平线性和垂直线性二者的属性分别为:android:orienta ...

  5. 基于协同过滤的个性化Web推荐

    下面这是论文笔记,其实主要是摘抄,这片博士论文很有逻辑性,层层深入,所以笔者保留的比较多. 看到第二章,我发现其实这片文章对我来说更多是科普,科普吧…… 一.论文来源 Personalized Web ...

  6. 用Firefly创建第一个工程

    原地址:http://blog.csdn.net/uxqclm/article/details/10382097 安装完成之后,在python script包中就存在 firefly-admin的工具 ...

  7. HDU3368+枚举

    题意看不懂的直接看百度百科对黑白棋的解释... 做法:分情况讨论,一共8个方向. /* 搜索 */ #include<stdio.h> #include<string.h> ; ...

  8. API:System V & POSI

    http://blog.sina.com.cn/s/blog_5b1572e30100gulz.html

  9. Android-AttributeSet详解

    public interface AttributeSet { /** * Returns the number of attributes available in the set. * * @re ...

  10. jdk1.7升级到jdk1.8后出错: [ERROR] javadoc: warning - Multiple sources of package comments found for package

    from: http://blog.joda.org/2014/02/turning-off-doclint-in-jdk-8-javadoc.html [ERROR] javadoc: warnin ...