逼真的阴影

图片

好的,哈伯社区。

许多年前,我遇到了一个帖子(1) 。 然后,我为有机会为roguelike (2)创建有趣的游戏元素而感到困惑。 假设对手可能在墙后,直到我们在视线内遇到他,我们才看到他。 但是我更喜欢这样一种情况,当我们沿着地牢的走廊旅行时,会根据可见区域逐渐揭示物体位置的特征。

在后面的文章(3)(4)(5)中 ,考虑了2D游戏中的阴影投射问题。 正如作者自己和评论中所指出的那样,对于计算器和设计而言,阴影的计算非常繁琐,而且并非易事。

不知何故,我有一些自由的日子,所以我决定回到阴影更美好的问题。 显然,视频卡可以成功且快速地处理阴影,但是在这种情况下,我想为2D游戏处理阴影,因此将计算转移到视频卡似乎是多余的。 是的,近年来处理器能力整体上有所增长,实际上是一篇有关最终情况的文章。

该程序是用Pascal编写的,因为我很了解Lazarus,它是一个开放的IDE,具有许多组件。

最初的想法是绘制从观察者到瓷砖各个角的线,然后使所得图形变暗。

图片

然而,当视角改变时,这种阴影看起来有些不自然。 阴影现在更宽,现在更窄。

图片

圆形物体的阴影看起来要好得多。 为了构建这样的阴影,您需要从观察点到圆以及到屏幕的边界绘制两个切线。 圆的直径将对应于瓷砖的尺寸。

在我的程序中,我使用了以下功能:

//       function tangent_to_circle(x1,y1,x2,y2,r:Single; var x3,y3,x4,y4:Single):Boolean; var l,dx,dy,i,ii,ij:Single; begin dx := x1 - x2; dy := y1 - y2; l := Sqrt(dx*dx + dy*dy); if l<=r then begin tangent_to_circle:=false; exit; end; i := r/l; ii := i*i; ij := i * Sqrt(1 - ii); x3 := x2 + dx*ii - dy*ij; y3 := y2 + dx*ij + dy*ii; x4 := x2 + dx*ii + dy*ij; y4 := y2 - dx*ij + dy*ii; tangent_to_circle:=true; end; 

其中(x1,y1)是观察点,(x2,y2)是圆的中心,®是其半径,(x3,y3)和(x4,y4)是直线和圆的交点。 仅当观察者在圆外时,该函数才返回true。

由于处理器对三角函数不是很友好,因此我尝试将其最小化。 实际上会依靠一个简单的规则(粗略模型),专家会告诉您原因。

(错误)SIN,COS ..>'/',SQRT>'DIV','MOD'>'SHR','SHL'>'*'>':=','+','-','AND ','XOR'..(好)

很高兴在画布上实现图元的图形部分,有很多库和引擎可以简化工作。 在Delphi上进行开发时,我不得不使用Agg2D库,在Lazarus上有端口(6) ,因此我决定实现这一想法。 实际上,从库中获得的好处是将alpha通道添加到RGB颜色,并且平滑了基元,并且由于直接访问像素和各种技巧,处理比画布快得多。

当绘制图块的阴影时,我本来打算用阴影填充该扇区,但随后图块内部的图像很难分辨(图3中所讨论的扇区用绿色填充)。 在尝试了各种选项之后,我停止从阴影区域中选择一个扇区。

要绘制扇形,我们需要以弧度为单位的角度,但是三角学仍然无法做到。 (arctan2-数学模块库函数)

 //     function alpha_angle(x1,y1,x2,y2:Single):Single; begin alpha_angle := arctan2(y1 - y2, x1 - x2); end; 

实际上,一切都准备好进行图像组装。 我们绘制一张瓷砖地图,并在单独的图层上依次逐一应用阴影。 对于树木,阴影更暗,对于其他物体,阴影更透明。

图片

将完成的图像应用于图块的主层。 进行一些背景设计,并选择更加通用的tileset。 实际上,我花了两天的时间来寻找合适的磁贴集,这些磁贴集属于公共领域,或者质量很低或成本很高。 结果,他亲自绘制了树木,并从用户Joe Williamson (7) (出色的风格)中借用了其他元素。

图片

到此为止,但是关于性能的一些沉淀。 随着对象数量的增加,大约有五百次缩编开始。 考虑了各种优化方法,将其拆分为多个内核并将绘图区域限制为一定的半径,更改阴影的形状(比弧线便宜),我什至想到了将计算转移到视频。

结果,我得出的结论是,最好的选择是减少用作荫罩的图像的采样。 由于计算数量显着减少,以及阴影轮廓的像素化的意外影响,因此具有一定的传统魅力。

图片

我非常喜欢这种效果,以至于我不得不通过给定的多重性参数来缩放动态过程。

图片

剩下的就是创建不透明的墙并将结果呈现给社区。

图片

我期待使用这种效果或其发展的新游戏。
谢谢你

演示可以触摸手柄的位置(Windows的exe)。

第2 部分第3部分

参考文献:
1)habr.com/post/16927/
2)en.wikipedia.org/wiki/Roguelike
3)habr.com/post/204782/
4)habr.com/post/305252/
5)habr.com/post/319530/
6)wiki.freepascal.org/BGRABitmap
7)twitter.com/joecreates

Source: https://habr.com/ru/post/zh-CN430438/


All Articles