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. python学习笔记——列表生成式与生成器

    1.列表生成式(List Comprehensions) python中,列表生成式是用来创建列表的,相较于用循环实现更为简洁.举个例子,生成[1*1, 2*2, ... , 10*10],循环用三行 ...

  2. Vijos P1063 迎春舞会之交谊舞 DP

    题目链接:https://vijos.org/p/1063 题意:有n(n <= 100)行,每行有2*i-1个可显字符'#'与'-',组成一个倒三角形,问由'-'组成的最大三角形的'-'的个数 ...

  3. WebService 学习总结

    一.概念 Web Web应用程序 Web服务( Web Serivce), SOAP, WSDL, UDDI .Net 框架 ASP.net IIS C#, 代理(委托) 二.实践 1.创建WebSe ...

  4. Timer组件

    1.常用属性 Interval 用于获取或设置Timer组件Tick事件发生的时间间隔,属性值不能小于1 制作左右飘摇窗体 private void timer1_Tick(object sender ...

  5. MVC-Model数据注解(一)-系统(DataAnnotations)

    要使用验证,首先,web.config要开户验证: <appSettings> <add key="ClientValidationEnabled" value= ...

  6. 异步委托 多线程实现摇奖器 winform版

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  7. 网络请求 post 的接受请求头的代理方法

    接收响应头 content-Length content-Type - (void)connection:(NSURLConnection *)connection didReceiveRespons ...

  8. ctf总结

    在过去的一个学期中,草人在西普学院还有一些其他安全夺旗网站上刷了一些题,草人我是菜鸟一个,刚开始很是苦恼,所以经历过以后希望将之分享给一起学习安全的同学,目的呢是希望以后学习的人能尽快理清学习思路,进 ...

  9. firefox浏览器删除插件

    打开注册表编辑器([开始菜单]→[运行]或 Win+R快捷键打开运行,输入regedit). 2 点击菜单栏[编辑]→[搜索],或者按 Ctrl + F 快捷键,搜索 MozillaPlugins . ...

  10. 对于数组使用sizeof(a)和使用sizeof(a[0])

    #include "stdafx.h" #include <iostream> using namespace std; int main() { ]={}; cout ...