《Genesis-3D开源游戏引擎--横版格斗游戏制作教程03:碰撞检测》
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:碰撞检测》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- Django初体验
为什么使用Django 快速开发 使用python 数据库ORM系统 大量内置应用 后台管理系统 admin 用户认证系统 auth 会话系统 sessions 安全性高 表单验证 SQL注入 跨站点 ...
- 解决npm安装模块时 npm err! registry error parsing json
最近还真是点背,从yeoman生成一个react项目或是github上克隆一个项目,在npm install的时候, 一直报npm err! registry error parsing json(就 ...
- iphone下overflow失效问题的解决方法
overflow-y: auto; -webkit-overflow-scrolling:touch; /*加上这个让浏览器支持touch和自动滚动这样界面就可以滚动了*/
- jvm 性能调优
[转载]:http://blog.csdn.net/chen77716/article/details/5695893 最近因项目存在内存泄漏,故进行大规模的JVM性能调优 , 现把经验做一记录. 一 ...
- Struts2 web.xml文件配置
在导入了项目需要使用的核心jar包之后需要在web.xml中配置Struts. 1. Struts2的知识点普及: Struts2共有5类配置文件,分别罗列如下: 1), Web.xml; 在没有使用 ...
- 百度:在O(1)空间复杂度范围内对一个数组中前后连段有序数组进行归并排序
一.题目理解 题目:数组al[0,mid-1]和al[mid,num-1]是各自有序的,对数组al[0,num-1]的两个子有序段进行merge,得到al[0,num-1]整体有序.要求空间复杂度为O ...
- 小米MIUI 360wifi掉线解决方案 落雨
问: 360WIFI 小米WIFI 联网无网速的解决办法 方法1.退出电脑和手机上的360安全卫士(我抱着试试的态度退出了之后,我艹,速度立马有了!),估计是这些安全软件太强大,导致的. 方法2.我用 ...
- HTTP Keep-Alive详解
HTTP是一个请求<->响应模式的典型范例,即客户端向服务器发送一个请求信息,服务器来响应这个信息.在老的HTTP版本中,每个请求都将被创建一个新的客户端->服务器的连接,在这个连接 ...
- JAVA三大框架的各自作用
http://christhb.blog.163.com/blog/static/98982492011727114936239/ 一.Spring Spring是一个解决了许多在J2EE开发中常见的 ...
- 很受欢迎的Linux笔记(短小精悍)
http://blog.csdn.net/xsl1990/article/details/8274028 如何知道所使用的LINUX是哪个发行版? lsb_release -a 查找某个文件的另类方法 ...