lrdcq 发表于 2014-12-10 17:40:09

本帖最后由 lrdcq 于 2014-12-10 20:13 编辑

因为制作过以还原东方曲线激光为目标的小游戏(http://tieba.baidu.com/p/2827270606)
所以自誉对东方中的曲线激光还算有点研究了
准备长篇大论,占楼待编辑好吧,其实我刚才去吃了个晚饭,然后回来慢慢截图然后来了几局STG
其实LZ已经把问题解决得差不多了,我从一些细节和大家争论的地方,以ZUN为标准来讲一些东西吧。

1.定义,什么是东方中的曲线激光?
嘛,曲线激光就曲线激光嘛,东方的曲线激光,ZUN的曲线激光,非要确定下来的话是自东方亲民船出现的,使用bullet文件夹的这张贴图作为素材(除了火葬场里面的闪电曲线激光)

形成的激光。所以,这样



这样就是曲线激光。
而另一种大家很容易想到的方法,由大量高光blend出来的弹幕组成的看起来像激光一样的瞎眼的东西,比如这样



就不属于东方的曲线激光,不在我们讨论范围之列。


2.曲线激光模型是的怎么构成的呢?
a.仔细观察每一条曲线激光,它是由完整的一块贴图扭曲而成,也就是大家想到的四边形细分扭曲。

b.游戏中可以显而易见的得到,曲线激光的形状是由一颗弹幕移动牵引出的轨迹而得到的,并且牵引轨迹的控制点的数目对于每一条激光是固定(通过大圣非符速度变慢的激光长度变短可证)。


3.曲线激光的牵引弹幕的控制点是怎么选取的?
前提:牵引弹幕的移动路径留下的点压入长度为按需求定义的N的队列中,作为控制点队列
a.可以直接选取需求长度中的所有的N个点构成曲线激光模型。
b.对于宽度过大或速度过慢的曲线激光会出现问题,比如弹幕腾讯狗早喵二符

会导致控制点相对太慢,构成的模型拐弯处内侧可能会出现如下情况

此时应修改参数来解决问题。
c.对于放B或者拍照(文花帖ds),有可能将一条激光打断为两条甚至多条

仔细观察打断的激光,他们各自应用了完整的贴图,是一条完整的激光,但是是沿着相同的轨迹在行进
因此可以得到结论:一个牵引弹幕可以牵引多条曲线激光


4.曲线激光的判定点是怎么构成的?
a.是点构成的么?肯定不是,对于速度稍快的牵引弹幕牵引出的控制点间距就较大,显然如果全是点构成的判定对于激光来说也是凹凸不平的,如下图

如果速度更快,甚至有神穿的可能,显然就完全是游戏BUG。
因此曲线激光的判断一定是由N个牵引点的N-1条短线段做判定构成的:
(附赠点到线段判定算法)
hit_test_line=function(p,n1,n2,d){//测试点 碰撞线段点1 碰撞线段点1 测试距离
      var a=MATH.dis(p,n1),b=MATH.dis(p,n2),c=MATH.dis(n2,n1),ds=0;
      if(a*a>=b*b+c*c){ds=b}
      else if(b*b>=a*a+c*c){ds=a}
      else{
                var s=(a+b+c)/2;
                s=Math.sqrt(s*(s-a)*(s-b)*(s-c));
                ds=2*s/c;
      }
      if(ds>d){return 0;}
      else{return 1;}
}b.是所有的控制点间线段都有判定么?显然不是,首先,收尾的两段肯定没有判定,否则判断肯定就超出激光模型范围了
同理,对于超宽曲线激光,判定范围减退到收尾第X个点,显然X=判定长度/牵引点平均间距。
但其实这样判断也会在拐歪处稍微超出一点点,这就是弹幕腾讯狗早喵那张符小弯的激光外侧特别难擦很容易撞的原因。

大概要关注的点就是这些?具体数据结构应该肯定没问题了

HHui 发表于 2014-12-10 17:41:19

本帖最后由 HHui 于 2014-12-10 17:47 编辑

Darksword 发表于 2014-12-10 17:26 static/image/common/back.gif
信号处理相关专业的Baka在这里看到FFT莫名感动QwQ 原来还能做滤波以外的事!
用shader来解决平滑扭曲的想 ...
shader的好处就是在于它能够动态加载而不用硬编码,因此对于不同的激光效果可以给予不同的shader进行处理,因此这并不是一个effect的事,而是effect集合的问题了,诚如你所说的,这种方法大概就是一个激光一个fx,不过这都不是什么事,尤其是当嵌入一个interpreter的情况下(比如lua),这样子既降低了耦合同时也能够照顾到软编码与extendibility的需求。

HHui 发表于 2014-12-10 17:46:58

Darksword 发表于 2014-12-10 17:26 static/image/common/back.gif
信号处理相关专业的Baka在这里看到FFT莫名感动QwQ 原来还能做滤波以外的事!
用shader来解决平滑扭曲的想 ...

另一方面,事实上对于很多商业级别的游戏而言,连effect本身的使用就比较少了,大多数情况下都是直接使用单独的shader来操作,毕竟effect的灵活性并不算很高。越是复杂的游戏它的渲染就更加多样化,不可能存在一个所谓的global-render-solution-in-one-fx(GRSIOF)模型的(当然非常简单的游戏或者直接使用游戏引擎简化的另当别论)。

lrdcq 发表于 2014-12-10 20:13:53

这是赠品
刚才搞了个很好玩(误)的http://lrdcq.com/test/webgl/demo4/index2.html 虽然是老物了

Darksword 发表于 2014-12-10 23:53:37

lrdcq 发表于 2014-12-10 17:40 static/image/common/back.gif
因为制作过以还原东方曲线激光为目标的小游戏(http://tieba.baidu.com/p/2827270606)
所以自誉对东方中的 ...

感谢分享!!
十分敬佩你的反复实践研究,有理有据不得不服!
顺着你的思路我测试了一下,如下图

这张图撞出了3段,忘保存录像了,下面是用PIX分析撞成两段的结果:

下面是撞出来的一小段的分析。

还有很多截图不方便传了,简单总结下结论。。
1、分段前总顶点数256(254个三角形,128个控制结点),
分段后小的顶点数10(8个三角形,5个结点),大的顶点数226(224个三角形,118个结点),
由消失的结点数128-118-5=5来看,绘制与碰撞检测分离,5个结点为一组进行碰撞拟合判断。
(也许计算方法不对,我没有细想。。)
2、每一段的纹理都是0-1重新取平均的,如5个结点的纹理横坐标分别是(0,0.25,0.5,0.75,1)
3、每一段不同时绘制!且新分离的激光,后端激光最后绘制!
关于这点我试着凭经验解释一下,不一定对。
①激光本身顶点数巨大,如果按相同纹理批处理绘制的话,几十条激光会共同绘制会超出预设的顶点最大缓存值,画不出来。因此每条激光都是独立的。
②后段激光并不紧跟着前段激光,而是在其他激光都绘制完再绘制,仿佛诞生了一个新激光一样。如果是直接分裂,显然应该前后的绘制顺序紧密相连,但是,我并不认为会重新生成新的控制点队列。头结点还是唯一的。
因此我推测:控制点序列与绘制顶点序列分离,绘制部分只需确定各段首结点(不一定是控制头)的位置以及该段长度,而控制点序列则应该作为一种游戏实际逻辑体存在,并且5结点作为一个碰撞检测部分。当碰撞分段后,前段直接缩减段长,同时new一个从第二段段首开始的新的绘制体,并且放到绘制队列的最后。
如此一来,绘制和逻辑部分较好的分离了。
于是,一个逻辑体对应N个不同的绘制体,一个绘制体对应M个effect。。。
天哪,我要好好重写我的架构了,收获巨大。。。


凯风快晴 发表于 2014-12-14 09:32:18

lrdcq 发表于 2014-12-10 17:40 static/image/common/back.gif
因为制作过以还原东方曲线激光为目标的小游戏(http://tieba.baidu.com/p/2827270606)
所以自誉对东方中的 ...

真要算的话曲线激光第一次出现大概是在妖妖梦……蕾迪之类的

Sonicthedgehog 发表于 2014-12-22 19:38:45

关于判定.d2d也提供了另一种思路.

d2d中有直接对于Geometry对象的定义.
可以自己把所有的弹幕的判定域定义成geometry然后在一个覆盖屏幕的geometry对象里执行combine命令.这样所有的判定域就都在一张图里了(我表达不好,大概意思是这样.)这时候再用角色坐标参照刚刚的geometry对比直接看出是否在定义域中.
曲线激光可以用比较复杂的Geometry,通过加点,连线的方法实现.
页: 1 [2]
查看完整版本: Dx中曲线激光的实现方法