public void ComputeActions(Player player, Vector2 target) { for (int i = 0; i < player.perception.Length; i++) { player.perception[i] = PerceptionTarget.Empty; } HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(0, -perceptionDistance)), PerceptionDirection.Up); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(perceptionDistance, -perceptionDistance)), PerceptionDirection.UpRight); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(perceptionDistance, 0f)), PerceptionDirection.Right); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(perceptionDistance, perceptionDistance)), PerceptionDirection.DownRight); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(0, fearOfHeightDistance)), PerceptionDirection.Down); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(-perceptionDistance, perceptionDistance)), PerceptionDirection.DownLeft); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(-perceptionDistance, 0f)), PerceptionDirection.Left); HandlePerception(player, world.RayCast(player.GetRawPosition(), player.GetRawPosition() + new Vector2(-perceptionDistance, -perceptionDistance)), PerceptionDirection.UpLeft); if (!player.hasFlag) { #region Priority #2: Determine vertical relation to target. if (target.Y < player.GetPosition().Y - moveTolerance)//Target is above us { if (player.perception[(int)PerceptionDirection.Up] == PerceptionTarget.Solid)//If there is an object directly above us, check if we can easily move to the left or right to get up there. { Control.Actions.Add(new CharacterMove(player.playerIndex, (player.perception[(int)PerceptionDirection.UpLeft] == PerceptionTarget.Solid ? Direction.Right : Direction.Left))); } else//There's nothing above us, so lets first jump and then head in the direction of our target { if (player.GetLinearVelocity().Y > -doubleJumpTolerance && player.GetLinearVelocity().Y < doubleJumpTolerance)//This line helps us double jump at the top of the previous jump { Control.Actions.Add(new CharacterJump(player.playerIndex)); } Control.Actions.Add(new CharacterMove(player.playerIndex, (target.X > player.GetPosition().X ? Direction.Right : Direction.Left))); } } else if (target.Y > player.GetPosition().Y + moveTolerance)//The object is below us. { if (player.perception[(int)PerceptionDirection.Down] == PerceptionTarget.Solid)//There is an object in our way below us. Move left or right based on availability { Control.Actions.Add(new CharacterMove(player.playerIndex, (player.perception[(int)PerceptionDirection.DownLeft] == PerceptionTarget.Solid ? Direction.Right : Direction.Left))); } else //Nothing below us, so just move towards the object { Control.Actions.Add(new CharacterMove(player.playerIndex, (target.X > player.GetPosition().X ? Direction.Right : Direction.Left))); } Control.Actions.Add(new CharacterMove(player.playerIndex, (target.X > player.GetPosition().X ? Direction.Right : Direction.Left))); } else //Object is vertically at the same point as us. { if (target.X > player.GetPosition().X + moveTolerance || target.X < player.GetPosition().X - moveTolerance) Control.Actions.Add(new CharacterMove(player.playerIndex, (target.X > player.GetPosition().X ? Direction.Right : Direction.Left))); } #endregion #region Priority #1: Jump to safety if it's too far down if (player.perception[(int)PerceptionDirection.Down] != PerceptionTarget.Solid)//Down perception works a little differently. If there's no ground under the player for a very long distance, jump towards whatever is solid. { //First remove all other move events. This action is priorty #1 for (int i = 0; i < Control.Actions.Count; i++) { if(Control.Actions[i].playerIndex == player.playerIndex) { Control.Actions.RemoveAt(i); i--; } } if (player.GetLinearVelocity().Y > -doubleJumpTolerance && player.GetLinearVelocity().Y < doubleJumpTolerance || player.GetLinearVelocity().Y > 5) //This line helps us double jump at the top of the previous jump { if (RNG.Next(100) < 1) Control.Actions.Add(new CharacterJump(player.playerIndex)); else Control.Actions.Add(new CharacterDodge(player.playerIndex, Direction.Up)); } if (player.perception[(int)PerceptionDirection.DownLeft] == PerceptionTarget.Solid) Control.Actions.Add(new CharacterMove(player.playerIndex, Direction.Left)); else if (player.perception[(int)PerceptionDirection.DownRight] == PerceptionTarget.Solid) Control.Actions.Add(new CharacterMove(player.playerIndex, Direction.Right)); else//We've gone too far! Just ehad towards the flag now. Control.Actions.Add(new CharacterMove(player.playerIndex, (target.X > player.GetPosition().X ? Direction.Right : Direction.Left))); } #endregion } else { Control.Actions.Add(new CharacterMove(player.playerIndex, Direction.None)); } #region Priority #3: Determine if there is a player within action distance if (player.perception[(int)PerceptionDirection.Up] == PerceptionTarget.Player) { Control.Actions.Add(new UpBasic(player.playerIndex)); } else if (player.perception[(int)PerceptionDirection.Down] == PerceptionTarget.Player) { Control.Actions.Add(new DownBasic(player.playerIndex)); } else if (player.perception[(int)PerceptionDirection.Left] == PerceptionTarget.Player) { Control.Actions.Add(new ForwardBasic(player.playerIndex, Direction.Left)); } else if (player.perception[(int)PerceptionDirection.Right] == PerceptionTarget.Player) { Control.Actions.Add(new ForwardBasic(player.playerIndex, Direction.Right)); } #endregion }