(转)不使用物理引擎实现防止群聚行为敌人扎堆

转自:http://www.gameres.com/thread_256279_1_1.html

GameRes发布,文/paladin_t,转载请注明GameRes和作者

追击、群聚是极常用到的敌人行为模式。靠拢玩家位置的移动叫追击;群聚指一批敌人集体采用统一的行动,就像一群群沙丁鱼一样。群聚敌人往往配合追击来对玩家施加压力,因此本文隐含用追击配合做群聚示例。

如果群聚行为的敌人没有对群体内其他敌人的感知能力,将造成一种很奇葩的现象:扎堆。我见过很多游戏可以控制主角兜来兜去让群聚敌人集中到一堆,或者你不动他们自己就会走成一条直线。

<ignore_js_op>

这很烦人,玩家会认为敌人非常傻,如果玩家要采取躲避敌人的策略,挑战性的要素只剩下对走位的决策和移动速度的比拼。更恶心的是往往敌人比你挨着我我挨着你还要亲密,甚至全部叠加集中到一个点上。

<ignore_js_op>

喂,这太蠢了点吧。这是最raw最simple的实现方式,谁都能想出来。

<ignore_js_op> 
敌人始终单纯的趋向主角(也许还会做出对主角移动预判的计算,但不在本文讨论范畴内),在主角从a点移动到b点的过程中敌人始终保持这样的趋向性。

<ignore_js_op>

用彩色曲线对例图中敌人的移动轨迹做描绘,也许是这个样子:

<ignore_js_op>

<ignore_js_op>

看到了吧,敌人群体的范围越来越小了。做为开发者兼玩家,这种prototype级别的做法会给我留下此游戏完成度很低的印象。

物理引擎在现代游戏中已经不是什么稀奇物件了,不管3D游戏还是2D游戏,都能找到物理机制和游戏表达结合的非常好的例子,某些游戏走的更远,对物理机制利用的更深入,物理就是这种游戏的全部乐趣。如果你的游戏中恰巧有一个可以随手拿来利用一下的物理引擎,也许你可以用它来防止敌人们过于亲密,比如给每个敌人一个比渲染包围体略大一些的防撞车碰撞体。

<ignore_js_op>

这看起来就像敌人间互相有了斥力场,酷!大功告成,万事大吉!

你得承认凡是做游戏鬼点子多的人才不会满足于把方案思考到能用就好的程度。我不是排斥使用物理引擎,相反我非常喜欢物理机制,我曾给我的首款App定制实现了一个物理引擎,效率良好,运转稳定,最关键的是这个精简版的物理引擎功能不多不少刚刚好满足我的需求,完全没必要用更加高大上的库。对于防止群聚行为敌人扎堆这件事我不想用物理引擎也是因为:完全没必要用啊。某些RTS不同兵种间有搭配性玩法,需要不同兵种的密度均衡,如果用物理引擎反而很难做。询问了几个同行,似乎不用物理引擎对这事都没什么辙,没办法,又得自己动手了。让我们来看看如果不使用物理引擎自己处理敌人间的“推搡”是怎样的情况。

<ignore_js_op>

如果有两只敌人,只需要做1次计算让一只跟另一只保持适当距离就行了;如果有3只敌人,需要做3次这样的计算;如果有4只,需要算6次;如果有5只呢,要算10次……这种算法的复杂度是O(n(n-1)/2),可想而知敌人数量多了这将成为CPU的灾难。经验告诉我,复杂度中有高达形如“n乘以n”这样的因子的算法都是要不得的,需要想办法优化或做折衷。

思考优化方案从现实切入吧,我们每个人都有在方阵队伍里齐步走的经历,左右脚步调的统一依靠“一二一”口号和踏步声音做同步数据源;在方阵中相对位置的固定不变我们不需要也不可能通过获取方阵中其他所有人的位置信息做反馈调整,事实上我们只是瞄着视线范围内与我们临近的同学来做模糊判定的。先考虑某一只敌人不管别的敌人同学自己单独行动的行为:

<ignore_js_op>

这很容易,只需要朝着主角的位置奔去就行了,我们不妨把例图中优先计算行动的敌人1当成走方阵时的排头同学,他们只需要走好自己的就行了。

取敌人1和主角位置连线(长度为R的)线段上某一点,(比如不妨定R为线段长度的一半),从主角位置到这一点(以R为半径)做一个圆,好歹我们可以知道敌人群体的总数量有几只,把这个圆平均划分为n份,每一只都朝着相对应的划分的端点袭去,嗯,也许还得给每只敌人做些移动方向的微调;由于敌人1距主角越来越近,R是越来越小的,这个圆也会越来越向主角收缩,于是我们神奇的达成了敌人的这一套行为:

1. 群体移动趋势一致统一
2. 个体间在圆收缩到很小之前不会靠的非常近

<ignore_js_op>

圆只需要划分一次,某一只敌人只需要知道自己是第几号就可以计算出速度向量,看,复杂度一下降低到了O(n),单次计算中的向量计算也锐减。

再引申谈一点点,群聚敌人分成若干堆怎样实现呢,不妨这样来看,每一堆算做一个聚集群体应用上文算法,再把某一群体看做一个整体,若干个这样的群体同理应用群聚算法(或其他行为模式)。

<ignore_js_op>

本文算法代码可在github获取。

文/paladin_t作者微博

时间: 2024-11-03 08:23:59

(转)不使用物理引擎实现防止群聚行为敌人扎堆的相关文章

不使用物理引擎实现防止群聚行为敌人扎堆

转自:http://www.gameres.com/thread_256279_1_1.html GameRes发布,文/paladin_t,转载请注明GameRes和作者 追击.群聚是极常用到的敌人行为模式.靠拢玩家位置的移动叫追击:群聚指一批敌人集体采用统一的行动,就像一群群沙丁鱼一样.群聚敌人往往配合追击来对玩家施加压力,因此本文隐含用追击配合做群聚示例.如果群聚行为的敌人没有对群体内其他敌人的感知能力,将造成一种很奇葩的现象:扎堆.我见过很多游戏可以控制主角兜来兜去让群聚敌人集中到一堆,

Verlet-js JavaScript 物理引擎

subprotocol最近在Github上开源了verlet-js.地址为https://github.com/subprotocol/verlet-js.verlet-js是一个集成Verlet的物理引擎,利用JavaScript编写.verlet-js支持粒子系统.距离限制.角度限制等.其Github声称基于这些基础,则可以帮助我们构建几乎任何我们所能想象到的东西. 其官网为我们提供了一下几个demo: Shapes (verlet-js Hello world) Fractal Trees

基于HT for Web 3D呈现Box2DJS物理引擎

上篇我们基于HT for Web呈现了A* Search Algorithm的3D寻路效果,这篇我们将采用HT for Web 3D来呈现Box2DJS物理引擎的碰撞效果,同上篇其实Box2DJS只是二维的平面碰撞物理引擎,但同样通过3D的呈现能让人更直观的体验到碰撞效果,先上张最终例子效果图: Box2D最早是Erin Catto在GDC大会上的一个展示例子,后来不断完善成C++的开源物理引擎库,这些年了衍生出Java.ActionScript以及JS等版本,被广泛应用在游戏领域.说其丰富的确

cocos2d_x_02_使用内置物理引擎

最终效果图: 一.新建工程 进入cocos2d-x的tools下的bin目录: /Users/beyond/Desktop/cocos2d-x/cocos2d-x-3.3beta0/tools/cocos2d-console/bin目录 打开终端,切换到上述bin目录 使用cocos命令,创建工程,格式如下: cocos new 工程名 -p 包名 -l 语言 -d 目标文件夹, 例如 : cocos new 01_cocos2d-x-p com.beyond-l cpp -d /Users/b

实例介绍Cocos2d-x物理引擎:HelloPhysicsWorld

我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用物理引擎的开发过程,熟悉这些API的使用.这个实例的运行后的场景,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触摸点生成一个新的精灵,精灵的运行是自由落体运动. HelloPhysicsWorld实例 使用物理引擎的一般步骤,如下图所示. 这个过程与上帝创建世界的过程类似,上帝首先创建了世界,然后为世界指定了边界,否则万物就会掉到世界之外的混沌里去了,最后上帝创建了万物.当然这只是一个最基本的步骤,有的时候还需要碰撞检测和使

关于Unity中物理引擎的使用

物理引擎控制刚体,刚体上面贴上图片,所以看起来就是游戏运行起来的状态 物理世界计算刚体的运行状态,通过贴图显现出运算结果. 一.物理引擎 1:Unity 2D物理引擎基于Box2D封装而成;2: 物理引擎模拟物理运动和计算,物理引擎帮助我们计算物体运动; 3: 重力加速度;4: 碰撞器是物体的形状 + 碰撞的物理参数(物理材质);5: 刚体控制物体运动和受力; 二.步骤 1.创建一个Canvas 2.对Canvas进行初始化,记得把Game视图的分辨率调成和Canvas里面设置的一样的分辨率64

物理引擎入门

对于物理引擎, 以前只是简单的听说过, 并朦胧的认为其就是一个封装了物理定律的模块, 如果我们游戏需要模拟真实的运动, 就使用它.至于物理引擎是如何模拟真实的运动, 以及如何使用物理引擎, 什么时候用, 则半点概念都没有. 最近因为工作关系,要在现有的游戏引擎里,集成Havok这款物理引擎.第一感觉就是信息量稍大, 第二感觉就是不知道要拿这款物理引擎达到什么样的效果, 所以也是很惆怅, 但整体还是有一个大体计划如何来完成这个颇具挑战性的任务. 计划如下: 1.了解什么是物理引擎, 以及物理引擎能

Unity 物理引擎实现匀速圆周运动

摘要 本文主要讲述如何利用Unity物理引擎实现匀速圆周运动. 前言 首先,我们可以利用Unity API,Transform.RotateAround来实现匀速圆周运动.但是这个实现,我觉得不过瘾,因为你只是了解一个API,并没有学到任何其他的知识.接下讲一点有意思东西. 物理知识 1.定义: 质点沿圆周运动,如果在任意相等的时间里通过的圆弧长度都相等,这种运动就叫做"匀速圆周运动",亦称"匀速率圆周运动".因为物体作圆周运动时速率不变,但速度方向随时发生变化.所

物理引擎接口

作者:朱凯 日期:2017年01月06日 1 结构分析 1.1 类定义 冰球类:class Puck 球桌类:class Table 击球器类:class Hockey_stick 1.2 关键函数 根据以上的类,以及如下需求: 输入:击球器的当前位置和速度(受机器人控制). 输出:冰球的当前位置和速度. 可以得知关键函数是碰撞检测以及碰撞后的速度计算.其中难点是碰撞检测. void check_collision();//检查碰撞 void update_position();//更新位置 v