《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 安装并启动 ...
随机推荐
- 七,WPF的元素绑定
数据绑定是一种关系,该关系告诉WPF从一个源对象提取一些信息,并使用这些信息设置目标对象的属性,目标属性总是依赖项属性,然而,源对象可以是任何内容. 源对象是WPF元素并且源属性是依赖项属性的数据绑定 ...
- 【web安全】第六弹:手工SQL注入详解
前一段时间,在对SQL注入有了新的理解之后,写了这篇文章.本来准备投稿,因为内容过于基础被打回来了,想想屯着也没意思,发出来发出来~~本来有好多图的,但是博客园发图很麻烦,word文档的链接会贴在文章 ...
- IIS MIME类型问题(html5 video 本地打开可以,IIS打开不了)
问题: mediaelement js(html 5 视频插件)网页用ie9本地打开可以,iis,vs2010在ie9上运行不了,chrome可以 (在博客园里有个人跟我遇到相同的问题:http:// ...
- android 界面布局 很好的一篇总结[转]
1.LinearLayout ( 线性布局 ) :(里面只可以有一个控件,并且不能设计这个控件的位置,控件会放到左上角) 线性布局分为水平线性和垂直线性二者的属性分别为:android:orienta ...
- 基于协同过滤的个性化Web推荐
下面这是论文笔记,其实主要是摘抄,这片博士论文很有逻辑性,层层深入,所以笔者保留的比较多. 看到第二章,我发现其实这片文章对我来说更多是科普,科普吧…… 一.论文来源 Personalized Web ...
- 用Firefly创建第一个工程
原地址:http://blog.csdn.net/uxqclm/article/details/10382097 安装完成之后,在python script包中就存在 firefly-admin的工具 ...
- HDU3368+枚举
题意看不懂的直接看百度百科对黑白棋的解释... 做法:分情况讨论,一共8个方向. /* 搜索 */ #include<stdio.h> #include<string.h> ; ...
- API:System V & POSI
http://blog.sina.com.cn/s/blog_5b1572e30100gulz.html
- Android-AttributeSet详解
public interface AttributeSet { /** * Returns the number of attributes available in the set. * * @re ...
- 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 ...