寻找流氓般的阴影



尊敬的Khabrovchans,我请您注意关于为2D百吉饼找到合适的阴影这一主题的持续研究。

这篇文章是该出版物的续篇,是有关错误和该思想进一步发展的一种工作。

受到尊敬的批评家在评论中正确地指出,在封闭的空间中,阴影被证明是有角度的,有些不自然。 提出了几种解决方案,我喜欢使用射线投射来计算阴影的提议。



我澄清一下,我不使用视频卡(我现在不工作),所有结果均在CPU上建模。

在有关reykasting的工作中,我们了解了通过将观察者发出的光线投射到空间中直至与障碍物(屏幕边界)相交并突出显示它们发生碰撞的位置的方法来构造图像。

在这里,我们将基于图块与射线的交点使用简化版的rakecasting。 该方法在过去的伪三维游戏中得到了广泛的应用(例如, Wolfenstein_3D ,相对于主题对象而言),我们将其用于二维空间。



该算法对于理解和实施都足够简单。 我将带来自己的实现:

帕斯卡
// i,j -  ,  -  // X,Y -    // r -     //   if cos(a)<0 then begin di :=-1; ddi:= 0; end else begin di := 1; ddi:= 1; end; if sin(a)<0 then begin dj :=-1; ddj:= 0; end else begin dj := 1; ddj:= 1; end; //        Y x1 := (i+ddi) * tile_size; y1 := y+ (x1-x) * tan(a); Dx := len(x,y,x1,y1); y1 := (j+ddj) * tile_size; x1 := x+ (y1-y) * cotan(a); Dy := len(x,y,x1,y1); sum_lenX := 0; sum_lenY := 0; //    X  Y   a rX := abs(tile_size / cos(a)); rY := abs(tile_size / sin(a)); //    repeat if sum_lenX+DX < sum_lenY+DY then begin x1 := (i+ddi) * tile_size; y1 := y+ (x1-x) * tan(a); i := i+di; //         key := is_wall(i,j); sum_lenX := sum_lenX + DX; if DX<>rX then DX:=rX; //       if r<sum_lenX then Break; end else begin y1 := (j+ddj) * tile_size; x1 := x+ (y1-y) * cotan(a); j := j+dj; //         key := is_wall(i,j); sum_lenY := sum_lenY + DY; if DY<>rY then DY:=rY; //       if r<sum_lenY then Break; end; until (      ); // x1,y1   

由于光束以相同的距离穿过每个轴上的像元,因此您可以节省计算并仅检查瓷砖内是否有墙。 我们需要与障碍物相交并记住其坐标。

在我的实现中,我将所有三角函数和除法函数放入每个角度的单独表格中,这极大地加快了算法的速度。

以所需的步骤向各个方向发射光线后,我们大致得到以下图片:



将射线数量增加到几千,并获得所需的示波器多面体。 当然,可以像在3D加速器上一样为图像的每个像素投射射线,但是这里不能没有视频卡。



开始进一步研究图层。

适用范围 此后,光线略微进入物体的深度。 这样的游戏习惯创造了2D游戏的独特环境。



照明图生成。 我们预先生成静态光源并缓存以提高性能,我们在屏幕上显示过程中应用动态光源。



汇集一切。 所缺少的只是可怕的怪物和宝藏……许多宝藏。



具有可变的光穿透曲率的墙并没有传给我,但也许是业余爱好者。



在创建原型的过程中,我尝试了许多模型变体,其中一些更适合恐怖



我特别喜欢墙壁上光线的多次反射的效果,但是即使是幼稚的实现也是如此缓慢,以至于我在与视频卡成为朋友时留给以后使用。

谢谢您的关注。

播放链接 (适用于Windows的exe)

第1 部分第3部分

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


All Articles