void ComputeAndMergeAnOctant(Octant octant) { /* * 计算并合并第一行(因为要考虑到观察者的影响但又不能过度消耗计算量) * * 向前走直到地图边界 * if(阴影没有完全覆盖八分角) * 计算并合并每一行 * else * 填充整行的阴影 */ bool isFullShadow = false; ShadowLine shadowLine = new ShadowLine(); ComputeAndMergeStartLine(octant, shadowLine); // 因为观察者自身对视线的遮挡会导致各种问题,所以单独拿出一行来处理 for (int mainStep = 1; _visibleMap.Contains(octant.GetPosition(mainStep, 0)); mainStep++) // 第一行单独处理了,这里从距离1开始 { if (!isFullShadow) { isFullShadow = ComputeAndMergeALineAndGetIsFullShadow(octant, mainStep, shadowLine); } else { FillALineShadow(octant, mainStep); } } }
bool ComputeAndMergeALineAndGetIsFullShadow(Octant octant, int mainStep, ShadowLine shadowLine) { /* * 循环到一行结束或地图边界 * { * 获取投影 * 通过投影判断可见度并存入视野 * 通过投影判断是否遮挡视线并存入阴影线 * } * 返回阴影是否覆盖了整个八分角 */ Vector2 currentPosition; for (int sideStep = 0; sideStep <= mainStep + LINE_PATCH && _visibleMap.Contains(currentPosition = octant.GetPosition(mainStep, sideStep)); sideStep++) { Shadow projection = ShadowLine.GetQuadProjection(mainStep, sideStep); DrawShadow(shadowLine, currentPosition, projection); UpdateShadowLine(currentPosition, shadowLine, projection); } return(shadowLine.IsFullShadow()); }
void ComputeAndMergeStartLine(Octant octant, ShadowLine shadowLine) { int mainStep = 0; Vector2 currentPosition; for (int sideStep = 1; sideStep <= LINE_PATCH && _visibleMap.Contains(currentPosition = octant.GetPosition(mainStep, sideStep)); sideStep++) // 边缘方向从1开始,跳过观察者所在的位置 { Shadow projection = ShadowLine.GetQuadProjection(mainStep, sideStep); DrawShadow(shadowLine, currentPosition, projection); UpdateShadowLine(currentPosition, shadowLine, projection); } }
void FillALineShadow(Octant octant, int mainStep) { /* * 循环到一行结束或地图边界 * 填充阴影 */ Vector2 currentPosition; for (int sideStep = 0; sideStep <= mainStep && _visibleMap.Contains(currentPosition = octant.GetPosition(mainStep, sideStep)); sideStep++) { _viewField.SetVisible(currentPosition, false); } /* * 前面for判断里有一句 _visibleMap.Contains(currentPosition = octant.GetPosition(mainStep, sideStep)) * 这一句是利用括号控制代码顺序,以括号为分隔,看成两个部分: * 第一部分,括号内的运算 currentPosition = octant.GetPosition(mainStep, sideStep) 运算后 currentPosition 就变为了这次循环的位置 * 第二部分:括号外的运算,在经过第一部分后实际上变成了这样: _visibleMap.Contains(currentPosition) * 两步合到一起就完成了更新 currentPosition 并判断是否越界的效果 */ }