// Register and update specific playerData public void UpdatePlayerData(FOWPlayerData playerData) { if (!IsInited()) { return; } if (m_PlayerDataList == null) { m_PlayerDataList = new List <FOWPlayerData>(); } if (!m_PlayerDataList.Contains(playerData)) { m_PlayerDataList.Add(playerData); } if (!m_IsPlayerDatasUpdated) { // Async update map's maskData m_FOWShadow.UpdatePlayerData(m_PlayerDataList); m_IsPlayerDatasUpdated = true; } }
private void CalculateCircular(FOWPlayerData playerData, FOWMapData mapData) { Vector3 playerPositionLS = m_FOWData.WorldToLocal(playerData.position); int rx = (int)(playerData.radius * invDeltaX); int rz = (int)(playerData.radius * invDeltaZ); int rs = rx * rx; int x = Mathf.FloorToInt((playerPositionLS.x) * invDeltaX); int z = Mathf.FloorToInt((playerPositionLS.z) * invDeltaZ); int beginx = Mathf.Max(0, x - rx); int beginy = Mathf.Max(0, z - rz); int endx = Mathf.Min(texWidth, x + rx); int endy = Mathf.Min(texHeight, z + rz); for (int j = beginy; j < endy; j++) { for (int i = beginx; i < endx; i++) { int dx = i - x; int dy = j - z; int rads = dx * dx + dy * dy; if (rads <= rs && !mapData[i, j]) { SetVisible(i, j); } } } }
private void CalculateFOVMask(FOWPlayerData playerData, FOWMapData mapData) { Vector3 playerLocalPosition = m_FOWData.WorldToLocal(playerData.position); float radiusSq = playerData.radiusSqr; int x = Mathf.FloorToInt((playerLocalPosition.x) * invDeltaX); int z = Mathf.FloorToInt((playerLocalPosition.z) * invDeltaZ); if (x < 0 || x >= texWidth) { return; } if (z < 0 || z >= texHeight) { return; } if (mapData[x, z]) { return; } m_RootPixelQueue.Clear(); m_ArrivedPixels.Clear(); m_RootPixelQueue.Enqueue(new Vector2Int(x, z)); m_ArrivedPixels.Add(z * texWidth + x); SetVisible(x, z); while (m_RootPixelQueue.Count > 0) { var root = m_RootPixelQueue.Dequeue(); if (mapData[root.x, root.y]) { if (PreRayCast(root, x, z)) { int index = root.y * texWidth + root.x; if (!m_ArrivedPixels.Contains(index)) { m_ArrivedPixels.Add(index); } SetVisible(root.x, root.y); } else { RayCast(root, x, z, playerData); } continue; } // spread the visible area around root position in four direction SetVisibleAtPosition(root.x - 1, root.y, x, z, radiusSq); SetVisibleAtPosition(root.x, root.y - 1, x, z, radiusSq); SetVisibleAtPosition(root.x + 1, root.y, x, z, radiusSq); SetVisibleAtPosition(root.x, root.y + 1, x, z, radiusSq); } }
public void RemovePlayerData(FOWPlayerData playerData) { if (!IsInited()) { return; } if (m_PlayerDataList != null && m_PlayerDataList.Contains(playerData)) { m_PlayerDataList.Remove(playerData); } }
public void Calculate(FOWPlayerData playerData, FOWMapData mapData) { switch (m_MaskType) { case MaskType.Circular: CalculateCircular(playerData, mapData); break; case MaskType.AccurateFOV: case MaskType.BasicFOV: CalculateFOVMask(playerData, mapData); break; default: CalculateCircular(playerData, mapData); break; } }
private void RayCast(Vector2Int pos, int centX, int centZ, FOWPlayerData playerData) { float r = playerData.radius * invDeltaX; Vector2 dir = new Vector2(pos.x - centX, pos.y - centZ); float l = dir.magnitude; if (r - l <= 0) { return; } dir = dir.normalized * (r - l); int x = pos.x + (int)dir.x; int y = pos.y + (int)dir.y; SetInvisibleLine(pos.x, pos.y, x, y, centX, centZ, playerData.radiusSqr); }