如何用粒子实现软边缘区域


13

我的游戏是使用Phaser创建的,但问题本身与引擎无关。

在我的游戏中,我有几个环境,本质上是玩家角色可以进入并受到其影响的多边形区域。例如,冰,火,毒药等。这些区域的图形元素是颜色填充的多边形区域本身,以及适当类型的粒子(在此示例中为冰碎片)。这就是我目前正在实现的方式-使用覆盖有粒子图案的tileprite的多边形蒙版:

在此处输入图片说明

硬边看起来不好。我想通过做两件事来改进:1.使多边形填充区域具有柔和的边缘,并融合到背景中。2.让一些碎片离开多边形区域,这样它们就不会在中间切开并且该区域没有直线

例如(样机):

在此处输入图片说明

我认为模糊多边形可以实现1,但是我不确定如何处理2。

您将如何实施呢?


2
看起来很棒。我可以链接到您的游戏吗?:)
ashes999 2014年

@GameAlchemist这是图块图像i.imgur.com/y54CeQ9.png
OpherV 2014年

@ ashes999仍在进行中。确定链接后,我肯定会在这里发布链接:)
OpherV 2014年

请注意,它是带有白色物体的透明PNG。如果您在白色背景上观看图片(与在浏览器中打开图片一样常见),您将看不到任何内容
OpherV,2014年

@OpherV太好了。请编辑您的问题并发布链接-这可能是在本网站上进行营销的最热门话题:)
ashes999 2014年

Answers:


2

1.如果您想要的东西接近您的模型,我会使用粒子(它不一定是完全成熟的粒子系统)。

在RenderTexture上以多边形的形式渲染粒子。确保在颗粒上使用添加剂混合。多边形内部的粒子将彼此平滑融合,而外部的粒子将提供所需的柔和边缘。(可以在此youtube视频中观看效果的示例:附加粒子视频 现在将RenderTexture渲染到主屏幕上,您就完成了。RenderTexture是必需的,这样粒子才不会与背景融合。

您可以尝试将三角形直接放置到粒子纹理上,然后看看如何实现。否则,将它们作为单独的图层放在“粒子汤”的顶部。

在如下所示的更新的jsfiddle中创建了一个快速的模型,演示版 您可以在此处找到更新的演示

2.每个粒子都有一个速度和一个原点。当播放器触摸多边形时,您将更改每个与播放器速度成比例的粒子速度。粒子离您的播放器越远,受播放器速度的影响就越小。

计算粒子速度的公式如下所示:

//player.velocity and particle.velocity are vectors 
//k is a factor to enhance or weaken the influence of players velocity
var distanceToPlayer = (player.position - particle.position).length();
particle.velocity = particle.velocity + ((k * player.velocity) + particle.velocity) * (1/distanceToPlayer);

要计算粒子的位置,请将其放在更新方法中:

var speedY = -(springConstant * (particle.position.y - particle.origin.y)) - (dampingFactor * particle.velocity.y);
var speedX = -(springConstant * (particle.position.x - particle.origin.x)) - (dampingFactor * particle.velocity.x);

particle.position.y = particle.position.y + speedY;
particle.position.x = particle.position.x + speedX;

particle.velocity.x = particle.velocity.x + speedX;
particle.velocity.y = particle.velocity.y + speedY;

这应该给您一个“流体”,当玩家搅拌流体时,每个粒子都围绕其原点摆动。springConstant会改变粒子从其原点摆动的幅度,而阻尼系数会改变粒子静止的速度。您可能需要调整代码,因为它是我在游戏中使用的一维模拟的修改版本。

现在有了一个演示:演示 只需调整顶部的3个常量,直到流体的行为像您想要的那样即可。


解决#1是一个非常有趣的主意!我喜欢。您如何建议实施三角形运动\间距?
OpherV

1
我编辑了原始帖子以回答问题2。
zillus 2014年

添加了粒子效果的小演示。我认为您只要稍作调整就可以达到预期的效果。
zillus 2014年

我最终使用了您的解决方案,它与我想要达到的效果最接近。谢谢!但是,有一个问题-我将如何限制示例中的弹性,使真正的微小移动不会导致粒子跳出如此大的距离?
OpherV 2014年

您可以使用阻尼系数和springConstant。高阻尼将使颗粒更快地静止。较低的弹簧常数会降低颗粒的速度。不幸的是,这两个值都使颗粒汤感觉更粘。因此,相反,当玩家触摸粒子时,您可以钳制玩家添加到粒子上的最大速度,如下所示:粒子。速度(x) )+ particle.velocity.x)*(1 / distanceToPlayer)); 有关夹具的信息,请参见:stackoverflow.com/a/11409944
zilluss 2014年

4

我对这两点的想法:

  1. 您可以使用着色器模糊,但这将非常昂贵。取而代之的是,我将绘制一个额外的三角形边框,该边框从中心的半透明逐渐淡入边缘,变为透明,以模拟“模糊”。我已经在我的游戏中做到了,效果很好。这是我游戏中彩虹般的助推器的两个屏幕截图。

    在此处输入图片说明 在此处输入图片说明

    外边界具有渐变。在我的情况下,边框与内部部分的透明度不一样,但是如果将这些透明度设置为相等,则渐变效果会很好。

  2. 我将对粒子系统进行编程,并使粒子遵循多边形。这样,您不必担心边缘会发生什么。粒子系统的动力学将确保粒子在多边形内部并均匀分布。您可以尝试使最接近的粒子彼此推开,但要使其具有很多“质量”,因此您具有惯性并且看起来很平滑。为了使事情更快,有一些可能性,但是最大的问题将是相互推动机制的时间复杂性。如果将每个粒子推到每个其他粒子上,则将具有O(n ^ 2),如果您的系统中有100个粒子,那么这将是不好的。关于PixelJunk的演示,很好地了解了如何优化它:http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf

    一种更简单的方法是在构建粒子系统时将每个粒子连接到三个或四个其他粒子。现在,每个粒子将只需要推动与其连接的其他四个粒子。但是,这种方法使粒子系统中的湍流成为不可能。但这似乎不是问题,因为您的当前情况使用静态纹理。这种方法将是O(n),这很好。


谢谢!1.我很难想象这一点。您能否发布游戏外观/工作原理的模型?2.有趣!将继续阅读
OpherV

感谢您的图片。我可以看到它如何在基于管或线的形状中工作,但如何与多边形一起工作?从两侧投影的三角形的梯度会不会很好地对齐...?
OpherV 2014年

使它们很好地适合。那是主意。这涉及一些数学和相交点等。您还可以细分边界并将其平滑。无限的可能性。
Martijn Courteaux 2014年

3

我在阅读文章时的想法是:
•构建一组将用于您所在区域的图块。
•在小临时画布上以图块分辨率渲染区域多边形(例如:如果图块为16X16,则以(16X,16X)较低的分辨率渲染)。
•使用该临时画布决定是否在主画布上渲染图块或不渲染图块:
如果在低分辨率画布上设置了点,则在主画布上绘制一个“随机”图块。如果一个点只是设定点的邻居,请在主画布上以较低的不透明度绘制“随机”图块(以进行过渡)。

我担心降低分辨率会产生块效应,但是即使使用20X20的图块,它看起来也相当不错:

在此处输入图片说明

为此,请执行以下步骤:采用多边形:
在此处输入图片说明

以您的图块分辨率绘制多边形:(在此处输入图片说明!!是的,这是购物中心的红色物件)。

然后使用低分辨率画布的imageData决定是否绘制图块或便笺。
如果在低分辨率画布上设置了像素,则意味着我们应该绘制图块:拾取“随机”图块索引以选择要绘制的图块。对于给定的面积/瓷砖,该随机指数应始终相同。
如果一个点是空的但在填充点旁边,则还要绘制一个图块,但不透明度为一半。

在此处输入图片说明

因此,让我们绘制瓷砖:

在此处输入图片说明

对于多边形,我只是绘制了多边形的几倍,将其缩小并在每次绘制时增加了不透明度(也可以使用globalCompositeOperation'lighter')。

在此处输入图片说明

一旦将所有内容加起来,就会得到:

在此处输入图片说明

小提琴在这里:

http://jsfiddle.net/gamealchemist/T7b4Y/

让我知道这是否有帮助。


感谢您详细介绍您的解决方案并提供代码!您的意思是“然后使用低分辨率画布的imageData决定是否绘制图块或便笺”。您如何使用小图像数据来决定在大图像上的位置\如何绘制?使用这种方法,如何避免三角形的重叠,从而实现与模型相似的间距?
OpherV 2014年

我的意思是,这是一个完整的布尔测试:是否需要填充此图块?true或false是通过对imageData [(x + y * width)* 4]的低分辨率测试的测试给出的!= 0,也就是说=='我是否在较低分辨率的画布上绘制了一些内容那个瓷砖的地方?然后,如果是,我使用一些详细的质数填充公式(getRandomNumber)从(x,y)转到“随机”图块索引,该索引将始终为给定区域+(x,y)提供相同的数字。如果您正确定义多边形,那么我看不到任何东西会重叠,因此我不会遇到第二个问题。
GameAlchemist 2014年

1

只是一个想法:

在图块中,“片段”最多约80像素宽。我建议做两个方面。绘制原始多边形,然后从每条边开始制作大约80像素的模型。然后,您将图块绘制到更大的多边形中。

然后,所有“块”都在内部多边形的外部具有像素,并且与内部多边形没有任何交集,因此您可以使用透明填充它们。

这是非常高的水平,但是我想与您分享。这里有很多细节需要确定。

粗略的图像演示:

在此处输入图片说明

如果内部黑色多边形是原始多边形,则将用红点删除所有多边形。


但是,如何检查嵌入在图块图像中的块与内部多边形的交集?
OpherV 2014年

@OpherV嗯,您可以确定点X是否在多边形中吗?您可以遍历外部多边形中的所有像素,并对每个白色像素进行泛洪检查所有像素,并查看内部/外部是否存在任何像素。虽然这听起来并不是特别有效,但是一旦有了一些东西,您就可以想到优化方法了吗?
user46560 2014年

那是在CPU上完成的后处理。本身很难乐观。如果内部多边形和外部通过三角带连接,则您的想法可能会奏效。OP可以添加顶点属性信息,并将每个顶点标记为内部或外部。然后,在顶点着色器中,可以将不透明度/ alpha从不太透明的值线性插值到完全不透明的值。
teodron

@teodron这就是我试图在答案中提出的观点。这是一个高水平的想法,我并不是真正的游戏开发人员。我只是有一个主意。
user46560 2014年

@ user46560是的,但是通过这种方式,您根本不必计算多边形间带中的像素。由于您不习惯所说的游戏开发方式,因此您的想法值得+1 :)。
teodron
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.