/// <summary> /// End a jump /// </summary> internal void EndJump() { if (_currentJumpSpot != null) { _currentJumpSpot.Complete(this); } this.IsNinja = false; _inactiveTime = 0; _fxPea.CollidesWith = Category.None; // This line is to prevent manifold to become 0 (fx) _fxPea.ResetDynamics(); _fxPea.IgnoreGravity = true; _fxPea.IsSensor = true; _fxPea.CollidesWith = Category.All; if (!IsTrapped) { ChangeMood(Mood.Ninja); } this.OnJumpCompleted.Invoke(new JumpEventArgs(_currentJumpSpot, this, 0)); _currentJumpSpot = null; }
/// <summary> /// /// </summary> /// <param name="spot"></param> /// <param name="pea"></param> public JumpEventArgs(DataJumpSpot spot, DataPea pea, Int32 points) : base() { this.Spot = spot; this.Pea = pea; this.Points = points; }
/// <summary> /// Jumps this DataJumpSpot /// </summary> /// <param name="location"></param> internal void Jump(DataJumpSpot jumpspot) { this.IsNinja = true; this.IsNotHappy = jumpspot == null; _fxPea.CollidesWith = Category.None; // This line is to prevent manifold to become 0 (fx) _fxPea.ResetDynamics(); _fxPea.IsSensor = false; _fxPea.IgnoreGravity = false; _fxPea.CollidesWith = Category.All; if (jumpspot == null) { _fxPea.ApplyLinearImpulse(ConvertUnits.ToSimUnits(Vector2.UnitX * 120 * (Random.Next(100) >= 50 ? -1 : 1) + Vector2.UnitY * -220)); this.OnJumpStarted.Invoke(new JumpEventArgs(jumpspot, this, 0)); return; } var location = jumpspot.Placement; _currentJumpSpot = jumpspot; _currentJumpSpot.Start(this); _fxPea.ApplyLinearImpulse(ConvertUnits.ToSimUnits(Vector2.UnitX * 120 * (location == DataJumpSpot.Location.Left ? -1 : 1) + Vector2.UnitY * -220)); ChangeMood(Mood.Happy); this.OnJumpStarted.Invoke(new JumpEventArgs(jumpspot, this, 0)); }
/// <summary> /// Creates a new flag sprite /// </summary> /// <param name="layer"></param> /// <param name="source"></param> public SpriteFlag(SceneLayer layer, DataJumpSpot source) : base(layer, "Graphics/Flag-Pole" ) { _source = source; //if (source.Placement == DataJumpSpot.Location.Left) // this.Effects = SpriteEffects.FlipHorizontally; }
/// <summary> /// Binds a jump spot to this block /// </summary> /// <param name="spot"></param> public void BindJumpSpot(DataJumpSpot spot) { if (spot.Placement == DataJumpSpot.Location.Left) { this.JumpLeft = spot; } else if (spot.Placement == DataJumpSpot.Location.Right) { this.JumpRight = spot; } this.OnJumpSpotBound.Invoke(spot, EventArgs.Empty); }
/// <summary> /// Kills the pea /// </summary> internal void Die() { this.IsAlive = false; this.IsNinja = false; _inactiveTime = 0; _fxPea.LinearVelocity = Vector2.Zero; _fxPea.CollidesWith = Category.None; // stop colliding _fxPea.IgnoreGravity = true; _collisions.Clear(); if (_currentJumpSpot != null) { _currentJumpSpot.Fail(this); } ChangeMood(Mood.Dying); this.OnJumpFailed.Invoke(new JumpEventArgs(_currentJumpSpot, this, 0)); _currentJumpSpot = null; }
/// <summary> /// Finds a jump spot /// </summary> /// <param name="spot"></param> /// <param name="location"></param> /// <returns></returns> private Boolean IsJumpSpot(DataBlock spot, DataJumpSpot.Location location) { /// ----- /// --X-- /// -LSR- /// S = spot, X = jump location (up) /// /// upup should be clear /// up should be clear /// /// left should be clear /// leftleft should be clear /// leftup should be clear /// leftleftup should be clear /// leftupup questionable var position = spot.GridPosition; var down = (position.Y < DataGrid.Height - 1) ? _grid.Grid[position.X][position.Y + 1] : null; var solid = (spot == null || spot.IsFlatTop); var upup = (position.Y > 1) ? _grid.Grid[position.X][position.Y - 2] : null; var up = (position.Y > 0) ? _grid.Grid[position.X][position.Y - 1] : null; var left = (position.X > 0) ? _grid.Grid[position.X - 1][position.Y] : null; var leftleft = (position.X > 1) ? _grid.Grid[position.X - 2][position.Y] : null; var leftup = (position.X > 0 && (position.Y > 0)) ? _grid.Grid[position.X - 1][position.Y - 1] : null; var leftdown = (position.X > 0 && (position.Y < DataGrid.Height - 1)) ? _grid.Grid[position.X - 1][position.Y + 1] : null; var leftleftdown = (position.X > 1 && (position.Y < DataGrid.Height - 1)) ? _grid.Grid[position.X - 2][position.Y + 1] : null; var leftleftup = (position.X > 1 && (position.Y > 0)) ? _grid.Grid[position.X - 2][position.Y - 1] : null; var leftupup = (position.X > 0 && (position.Y > 1)) ? _grid.Grid[position.X - 1][position.Y - 2] : null; var right = (position.X < DataGrid.Width - 1) ? _grid.Grid[position.X + 1][position.Y] : null; var rightright = (position.X < DataGrid.Width - 2) ? _grid.Grid[position.X + 2][position.Y] : null; var rightup = (position.X < DataGrid.Width - 1 && (position.Y > 0)) ? _grid.Grid[position.X + 1][position.Y - 1] : null; var rightdown = (position.X < DataGrid.Width - 1 && (position.Y < DataGrid.Height - 1)) ? _grid.Grid[position.X + 1][position.Y + 1] : null; var rightrightdown = (position.X < DataGrid.Width - 2 && (position.Y < DataGrid.Height - 1)) ? _grid.Grid[position.X + 2][position.Y + 1] : null; var rightrightup = (position.X < DataGrid.Width - 2 && (position.Y > 0)) ? _grid.Grid[position.X + 2][position.Y - 1] : null; var rightupup = (position.X < DataGrid.Width - 1 && (position.Y > 1)) ? _grid.Grid[position.X + 1][position.Y - 2] : null; // Above and above that should be clear if (!solid || (up != null && (!up.IsClear || up.IsTransitioning)) || (upup != null && (!upup.IsClear || upup.IsTransitioning))) return false; if (location == DataJumpSpot.Location.Left) return ((left != null && left.IsClear && !left.IsTransitioning) && (leftleft != null && leftleft.IsClear && !leftleft.IsTransitioning) && (leftupup == null || (leftupup.IsClear && !leftupup.IsTransitioning)) && (leftleftup == null || (leftleftup.IsClear && !leftleftup.IsTransitioning)) && (leftup == null || (leftup.IsClear))); if (location == DataJumpSpot.Location.Right) return ((right != null && right.IsClear && !right.IsTransitioning) && (rightright != null && rightright.IsClear && !rightright.IsTransitioning) && (rightupup == null || (rightupup.IsClear && !rightupup.IsTransitioning)) && (rightrightup == null || (rightrightup.IsClear && !rightrightup.IsTransitioning)) && (rightup == null || (rightup.IsClear && !rightup.IsTransitioning))); return false; }
/// <summary> /// Finds a path to a jumping spot /// </summary> /// <param name="spot">Spot to jump</param> /// <param name="path">Path</param> /// <returns>Has found</returns> private Boolean FindPath(DataPea pea, DataJumpSpot spot, out Queue<MoveNode> path) { path = new Queue<MoveNode>(); var startNode = new Node<MoveNode>() { Value = GetSnapshot(pea).PreviousNode }; //.Action == MoveNode.Type.None ? new Node<MoveNode>() { Value = new MoveNode() { Position = pea.GridPosition, Action = MoveNode.Type.Walk} } : ; var goalNode = new Node<MoveNode>() { Value = new MoveNode() { Position = new Point(spot.Source.X, spot.Source.Y - 1), Action = MoveNode.Type.Walk } }; var domain = new List<Node<MoveNode>>(); domain.Add(startNode); // Notes: Normally you would build the domain from ALL the walkable places and // have the neighbourghing function run just once for each node. Because that // function is complex, I added it dynamically (runs on reach node). This changes // some of the behavior of A*. Don't forget that... // Debuging Solver<MoveNode>.SolverProgress += new EventHandler<SolverResultEventArgs<MoveNode>>(PeaController_SolverProgress); // Get a path var result = Solver<MoveNode>.Solve( startNode, goalNode, domain, CreateMoveNodesFrom, // This was initialially not in the solver n => Math.Abs(n.Value.Position.X - goalNode.Value.Position.X) + Math.Abs(n.Value.Position.Y - goalNode.Value.Position.Y), n => Math.Abs(n.Value.Position.X - startNode.Value.Position.X) + Math.Abs(n.Value.Position.Y - startNode.Value.Position.X), (n, m) => n.Value.Equals(m.Value), #if DEBUG true #else false #endif ); if (result == null) { path = null; return false; } foreach (Node<MoveNode> node in result) path.Enqueue(node.Value); return true; }
/// <summary> /// /// </summary> /// <param name="spot"></param> public void CompleteJumpSpot(DataJumpSpot spot) { this.OnJumpSpotCompleted.Invoke(spot, EventArgs.Empty); }
/// <summary> /// Kills the pea /// </summary> internal void Die() { this.IsAlive = false; this.IsNinja = false; _inactiveTime = 0; _fxPea.LinearVelocity = Vector2.Zero; _fxPea.CollidesWith = Category.None; // stop colliding _fxPea.IgnoreGravity = true; _collisions.Clear(); if (_currentJumpSpot != null) _currentJumpSpot.Fail(this); ChangeMood(Mood.Dying); this.OnJumpFailed.Invoke(new JumpEventArgs(_currentJumpSpot, this, 0)); _currentJumpSpot = null; }
/// <summary> /// End a jump /// </summary> internal void EndJump() { if (_currentJumpSpot != null) _currentJumpSpot.Complete(this); this.IsNinja = false; _inactiveTime = 0; _fxPea.CollidesWith = Category.None; // This line is to prevent manifold to become 0 (fx) _fxPea.ResetDynamics(); _fxPea.IgnoreGravity = true; _fxPea.IsSensor = true; _fxPea.CollidesWith = Category.All; if (!IsTrapped) ChangeMood(Mood.Ninja); this.OnJumpCompleted.Invoke(new JumpEventArgs(_currentJumpSpot, this, 0)); _currentJumpSpot = null; }
/// <summary> /// Jumps this DataJumpSpot /// </summary> /// <param name="location"></param> internal void Jump(DataJumpSpot jumpspot) { this.IsNinja = true; this.IsNotHappy = jumpspot == null; _fxPea.CollidesWith = Category.None; // This line is to prevent manifold to become 0 (fx) _fxPea.ResetDynamics(); _fxPea.IsSensor = false; _fxPea.IgnoreGravity = false; _fxPea.CollidesWith = Category.All; if (jumpspot == null) { _fxPea.ApplyLinearImpulse(ConvertUnits.ToSimUnits(Vector2.UnitX * 120 * (Random.Next(100) >= 50 ? -1 : 1) + Vector2.UnitY * -220)); this.OnJumpStarted.Invoke(new JumpEventArgs(jumpspot, this, 0)); return; } var location = jumpspot.Placement; _currentJumpSpot = jumpspot; _currentJumpSpot.Start(this); _fxPea.ApplyLinearImpulse(ConvertUnits.ToSimUnits(Vector2.UnitX * 120 * (location == DataJumpSpot.Location.Left ? -1 : 1) + Vector2.UnitY * -220)); ChangeMood(Mood.Happy); this.OnJumpStarted.Invoke(new JumpEventArgs(jumpspot, this, 0)); }
/// <summary> /// /// </summary> /// <param name="spot"></param> public void CompleteJumpSpot(DataJumpSpot spot) { this.OnJumpSpotCompleted.Invoke(spot, EventArgs.Empty); }
/// <summary> /// Is reachable from spot /// </summary> /// <param name="spot"></param> /// <returns></returns> private Boolean IsReachable(DataPea pea, DataJumpSpot spot, out Queue<MoveNode> path) { // Question: Is it worth it to save paths found (need re-evaluation when grid // changes). Should test that later and work from there. if (!FindPath(pea, spot, out path)) return false; return true; }
/// <summary> /// Binds a jump spot to this block /// </summary> /// <param name="spot"></param> public void BindJumpSpot(DataJumpSpot spot) { if (spot.Placement == DataJumpSpot.Location.Left) this.JumpLeft = spot; else if (spot.Placement == DataJumpSpot.Location.Right) this.JumpRight = spot; this.OnJumpSpotBound.Invoke(spot, EventArgs.Empty); }
/// <summary> /// Is still a valid jumpspot /// </summary> /// <param name="dataJumpSpot"></param> /// <returns></returns> protected Boolean IsValid(DataJumpSpot dataJumpSpot) { return (dataJumpSpot.Placement == DataJumpSpot.Location.Left ? dataJumpSpot == dataJumpSpot.Source.JumpLeft : dataJumpSpot == dataJumpSpot.Source.JumpRight) || IsJumpSpot(dataJumpSpot.Source, dataJumpSpot.Placement); }
/// <summary> /// /// </summary> /// <param name="spot"></param> /// <param name="pea"></param> public JumpEventArgs(DataJumpSpot spot, DataPea pea) : base() { this.Spot = spot; this.Pea = pea; }