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 }
private void HandlePerception(Player player, List<Fixture> fixtures, PerceptionDirection direction) { foreach (var item in fixtures) { if (item.CollisionCategories == Category.Cat1) player.perception[(int)direction] = PerceptionTarget.Solid; else if (item.CollisionCategories == Category.Cat2 && ((PhysicalData)item.Body.UserData).player.playerIndex != player.playerIndex) player.perception[(int)direction] = PerceptionTarget.Player; } }
public void ReleaseFlag() { untouchableTimer = UNTOUCHABLE_TIMELIMIT; holder.stunTimer += TimeSpan.FromSeconds(2); body.IgnoreGravity = false; totalDamage = 0; holder.hasFlag = false; holder = null; body.ApplyLinearImpulse(new Vector2(Player.RNG.Next(-RELEASE_FORCE, RELEASE_FORCE), RELEASE_FORCE)); }
bool body_OnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact) { if (fixtureA.CollisionCategories == Category.Cat1 || fixtureB.CollisionCategories == Category.Cat1) return true; if (fixtureA.CollisionCategories == Category.Cat2 && holder == null && untouchableTimer <= TimeSpan.Zero) { if (!((PhysicalData)fixtureB.Body.UserData).player.isStunned) { holder = ((PhysicalData)fixtureA.Body.UserData).player; holder.hasFlag = true; lastDamageValue = holder.damage; body.IgnoreGravity = true; } } else if (fixtureB.CollisionCategories == Category.Cat2 && holder == null && untouchableTimer <= TimeSpan.Zero) { if (!((PhysicalData)fixtureB.Body.UserData).player.isStunned) { this.holder = ((PhysicalData)fixtureB.Body.UserData).player; holder.hasFlag = true; lastDamageValue = holder.damage; body.IgnoreGravity = true; } } return false; }
public void Respawn() { untouchableTimer = UNTOUCHABLE_TIMELIMIT; if(holder != null) holder.hasFlag = false; holder = null; totalDamage = 0; world.RemoveBody(body); position = level.GetSpawnPoint(); currentColor = Color.Green; previousColor = Color.Blue; colorTimer = TimeSpan.Zero; size = new Vector2(50f / PPM, 50f / PPM); body = BodyFactory.CreateRectangle(world, size.X, size.Y, 10f); body.UserData = this; body.Position = position / PPM; body.BodyType = BodyType.Dynamic; body.Restitution = 0.2f; body.Friction = 0.2f; body.SleepingAllowed = false; body.FixedRotation = true; body.CollisionCategories = Category.Cat5; body.CollidesWith = Category.Cat1 | Category.Cat2; body.OnCollision += body_OnCollision; }
public PhysicalData(Vector2 _size, Player _player, Color _color) { size = _size; player = _player; color = _color; }