private void ExponentialInfluence(PotentielMapCell cell, NavigationCell navCell) { float influence = 0; for (int iNeighbour = 0; iNeighbour < navCell.Neighbours.Length; iNeighbour++) { var nextNavCell = navCell.Neighbours[iNeighbour]; if (navCell.Neighbours[iNeighbour] == null || !navCell.CanNavigateToNeighbour[iNeighbour]) { continue; } var nextCell = m_grid[nextNavCell.Index]; float dist = Vector2.Distance(nextNavCell.Position, navCell.Position) / m_navManager.Parameters.GridSpacing; float costFactor = 1 / (1 + cell.CostValue); costFactor = LBE.MathHelper.Clamp(0, 1, costFactor); float cellInfluence = nextCell.Value * (float)Math.Exp(-dist * m_influenceDecay * (1 + cell.CostValue)); if (cellInfluence > Math.Abs(influence)) { influence = cellInfluence; } } cell.Influence = LBE.MathHelper.Clamp(-1, 1, influence); }
private void LinearInfluence(float linearDecay, PotentielMapCell cell, NavigationCell navCell) { float influence = float.NegativeInfinity; for (int iNeighbour = 0; iNeighbour < navCell.Neighbours.Length; iNeighbour++) { var nextNavCell = navCell.Neighbours[iNeighbour]; if (navCell.Neighbours[iNeighbour] == null || !navCell.CanNavigateToNeighbour[iNeighbour]) { continue; } var nextCell = m_grid[nextNavCell.Index]; //Linear approx. of distance, that is exact for distSq = 1 or distSq = 2 float distSq = Vector2.DistanceSquared(nextNavCell.Position, navCell.Position) / (m_navManager.Parameters.GridSpacing * m_navManager.Parameters.GridSpacing); float sq2minusOne = 1.414213f - 1; float fastDist = (1 - sq2minusOne) + sq2minusOne * distSq; float cellInfluence = nextCell.Value - linearDecay * (1 + cell.CostValue) * fastDist * fastDist; influence = Math.Max(influence, cellInfluence); } cell.Influence = LBE.MathHelper.Clamp(m_linearParameters.MinValue, 1, influence); }
public void Init() { m_paramAsset = Engine.AssetManager.GetAsset <NavigationParameters>("Game/Navigation.lua::Navigation"); m_potentialMaps = new Dictionary <string, PotentialMap>(); m_mapDebugIndex = 0; m_debugIndexPlusCtrl = new KeyControl(Keys.PageDown); m_debugIndexMinusCtrl = new KeyControl(Keys.PageUp); Vector2 arenaSize = Game.Arena.Description.Size; if (arenaSize == Vector2.Zero) { arenaSize = new Vector2(1280, 720); } int nPointX = (int)(arenaSize.X / Parameters.GridSpacing); int nPointY = (int)(arenaSize.Y / Parameters.GridSpacing); m_navigationGridOrigin = new Vector2( -nPointX * Parameters.GridSpacing * 0.5f, -nPointY * Parameters.GridSpacing * 0.5f); //Create the grid m_navigationGrid = new Grid <NavigationCell>(nPointX, nPointY); //Initialise data points for (int i = 0; i < m_navigationGrid.Width; i++) { for (int j = 0; j < m_navigationGrid.Height; j++) { Point index = new Point(i, j); m_navigationGrid[index] = new NavigationCell(); m_navigationGrid[index].Index = index; m_navigationGrid[index].Position = new Vector2( m_navigationGridOrigin.X + i * Parameters.GridSpacing, m_navigationGridOrigin.Y + j * Parameters.GridSpacing); m_navigationGrid[index].CanSeePlayer = new bool[4]; } } //Initialise neighbours in a second pass for (int i = 0; i < m_navigationGrid.Width; i++) { for (int j = 0; j < m_navigationGrid.Height; j++) { Point index = new Point(i, j); List <NavigationCell> neighbours = new List <NavigationCell>(8); foreach (var p in index.Neighbours()) { if (m_navigationGrid.TestBounds(p)) { neighbours.Add(m_navigationGrid[p]); } else { neighbours.Add(null); } } m_navigationGrid[index].Neighbours = neighbours.ToArray(); m_navigationGrid[index].CanNavigateToNeighbour = new bool[8]; } } var ballMap = new PotentialMap(Game.GameManager.Navigation, PotentialMapType.Linear); m_ballSource = new PotentialMapInfluencePoint(); m_ballSource.Radius = 60; m_ballSource.Value = 1; ballMap.Sources.Add(m_ballSource); ballMap.UpdateFrequency = PotentialMapUpdateFrequency.Fast; Game.GameManager.Navigation.PotentialMaps.Add("BallMap", ballMap); m_shootLeftPlayerCosts = new PotentialMapInfluencePoint[2]; m_shootLeftPlayerCosts[0] = new PotentialMapInfluencePoint(); m_shootLeftPlayerCosts[1] = new PotentialMapInfluencePoint(); m_shootRightPlayerCosts = new PotentialMapInfluencePoint[2]; m_shootRightPlayerCosts[0] = new PotentialMapInfluencePoint(); m_shootRightPlayerCosts[1] = new PotentialMapInfluencePoint(); foreach (var playerCost in m_shootLeftPlayerCosts) { playerCost.Value = Engine.Debug.EditSingle("PlayerValue", 3); playerCost.Radius = Engine.Debug.EditSingle("PlayerCostRadius", 350); playerCost.Attenuation = 0; } foreach (var playerCost in m_shootRightPlayerCosts) { playerCost.Value = Engine.Debug.EditSingle("PlayerValue", 3); playerCost.Radius = Engine.Debug.EditSingle("PlayerCostRadius", 350); playerCost.Attenuation = 0; } var shootLeftMap = new PotentialMap(Game.GameManager.Navigation, PotentialMapType.Linear); shootLeftMap.Sources.Add(new CanShootLeftPotentialSource()); shootLeftMap.Costs.Add(m_shootLeftPlayerCosts[0]); shootLeftMap.Costs.Add(m_shootLeftPlayerCosts[1]); shootLeftMap.LinearParameters.SpatialDecay = 0.01f; shootLeftMap.LinearParameters.MinValue = -10; shootLeftMap.UpdateFrequency = PotentialMapUpdateFrequency.Fast; Game.GameManager.Navigation.PotentialMaps.Add("ShootLeft", shootLeftMap); var shootRightMap = new PotentialMap(Game.GameManager.Navigation, PotentialMapType.Linear); shootRightMap.Sources.Add(new CanShootRightPotentialSource()); shootRightMap.Costs.Add(m_shootRightPlayerCosts[0]); shootRightMap.Costs.Add(m_shootRightPlayerCosts[1]); shootRightMap.LinearParameters.SpatialDecay = 0.01f; shootRightMap.LinearParameters.MinValue = -10; shootRightMap.UpdateFrequency = PotentialMapUpdateFrequency.Fast; Game.GameManager.Navigation.PotentialMaps.Add("ShootRight", shootRightMap); }