/// <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> /// Registers a pea /// </summary> /// <param name="pea"></param> public void Register(DataPea pea) { pea.OnSeparation += new OnSeparationEventHandler(pea_OnSeparation); pea.OnJumpStarted += new JumpEventHandler(pea_OnJumpStarted); pea.OnJumpFailed += new JumpEventHandler(pea_OnJumpFailed); pea.OnJumpCompleted += new JumpEventHandler(pea_OnJumpCompleted); }
/// <summary> /// Creates a new sprite pea /// </summary> /// <param name="layer"></param> /// <param name="source"></param> /// <param name="pointsController"></param> public SpritePea(SceneLayer layer, DataPea source, PointsController pointsController) : base(layer) { _source = source; _pointsController = pointsController; _source.OnJumpStarted += new JumpEventHandler(_source_OnJumpStarted); _source.OnJumpCompleted += new JumpEventHandler(_source_OnJumpCompleted); _source.OnJumpFailed += new JumpEventHandler(_source_OnJumpCompleted); _source.OnRevive += new EventHandler(_source_OnRevive); }
/// <summary> /// Starts jumping /// </summary> public void Start(DataPea pea) { _hasStarted.Add(pea); var getOnSource = (Placement == Location.Left ? Source.JumpLeft : Source.JumpRight); // Register if (getOnSource == null) Source.BindJumpSpot(this); else if (getOnSource != this) getOnSource.Start(pea); }
/// <summary> /// Fail the spot for this pea /// </summary> /// <param name="dataPea"></param> internal void Fail(DataPea pea) { _hasFailed.Add(pea); var getOnSource = (Placement == Location.Left ? Source.JumpLeft : Source.JumpRight); // Complete on other and kill this (shouldnt be needed) if (getOnSource != this) { getOnSource.Fail(pea); } }
/// <summary> /// Creates a new state /// </summary> /// <param name="pea"></param> public PointsControllerState(DataPea pea) { this.Times = new Dictionary<BlockType, Int32>() { { BlockType.Normal, 0 }, { BlockType.LeftRamp, 0 }, { BlockType.RightRamp, 0 }, { BlockType.Spring, 0}, { BlockType.Gel, 0}, { BlockType.None, 0}, }; this.Pea = pea; this.RecentHits = new Queue<DataBlock>(); }
/// <summary> /// Starts jumping /// </summary> public void Start(DataPea pea) { _hasStarted.Add(pea); var getOnSource = (Placement == Location.Left ? Source.JumpLeft : Source.JumpRight); // Register if (getOnSource == null) { Source.BindJumpSpot(this); } else if (getOnSource != this) { getOnSource.Start(pea); } }
/// <summary> /// Complete this for a pea /// </summary> /// <param name="pea"></param> public void Complete(DataPea pea) { _hasCompleted.Add(pea); var getOnSource = (Placement == Location.Left ? Source.JumpLeft : Source.JumpRight); // Complete on other and kill this (shouldnt be needed) if (getOnSource != this) { getOnSource.Complete(pea); } if (_hasCompleted.Count == MaxCompletion) { getOnSource.Source.CompleteJumpSpot(getOnSource); } }
/// <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> /// Finds a jump target for a pea /// <param name="pea"></param> /// </summary> private Boolean FindTarget(DataPea pea) { IEnumerable<Tuple<Boolean, DataJumpSpot, Queue<MoveNode>>> spots = null; //new List<DataJumpSpot>(); for (int y = 0; y < _destinations.Length; y++) { if (_destinations[y].Count > 0) { // See if spots are available to pea and are reachable var potential = _destinations[y].Where(spot => !spot.HasJumped(pea)); spots = potential.Select(spot => { var path = new Queue<MoveNode>(); Boolean r = IsReachable(pea, spot, out path); return new Tuple<Boolean, DataJumpSpot, Queue<MoveNode>>(r, spot, path); }).Where(a => a.Item1); //Debug.WriteLine("Found {0} spots for y = {1} reachable", spots.Count(), y); if (spots.Count() > 0) break; } } var snapshot = GetSnapshot(pea); // Select a target if (spots != null) { var targets = spots.Where(spot => spot.Item2.Completion == spots.Max(cspot => cspot.Item2.Completion)); var target = targets.Count() > 0 ? targets.ElementAt(DataPea.Random.Next(targets.Count())) : null; if (target != null) { snapshot.Target = target.Item2; // Get the path snapshot.StartPath(target.Item3); } return target != null; } return false; }
/// <summary> /// Jumping start /// </summary> /// <param name="pea"></param> /// <param name="gameTime"></param> public void Jump(DataPea pea, GameTime gameTime) { var snapshot = GetSnapshot(pea); var d = (snapshot.Target.Source.Position + Vector2.UnitX * 35 - Vector2.UnitY * 8 - pea.Position); // If not in range of the target, stop jumping if (d.Length() > 5 || !IsValid(snapshot.Target) || ((snapshot.Target.Placement == DataJumpSpot.Location.Left ? (snapshot.Target.Source == null ? snapshot.Target : snapshot.Target.Source.JumpLeft) : (snapshot.Target.Source == null ? snapshot.Target : snapshot.Target.Source.JumpRight)) ?? snapshot.Target).HasJumped(pea)) { // TODO REMOVE JUMPSPOT FROM CANDIDATES snapshot.Target = null; return; } pea.Jump(snapshot.Target); }
/// <summary> /// Update moving towards a goal /// </summary> /// <param name="pea"></param> /// <param name="gameTime"></param> public Boolean UpdateMoveTo(DataPea pea, GameTime gameTime) { if (RunningSpeed <= 0) return false; var snapshot = GetSnapshot(pea); var previousNode = snapshot.PreviousNode; var nextNode = snapshot.HasRemainingPath ? snapshot.CurrentNode : snapshot.WanderingNode.Value; var reached = false; // If no longer valid move if (!IsValid(previousNode, nextNode)) { // Detroy target, node list and so on snapshot.Target = null; snapshot.EndPath(); return true; } // Branch move action switch (nextNode.Action) { case MoveNode.Type.Round: case MoveNode.Type.Climb: case MoveNode.Type.Wander: case MoveNode.Type.Ramp: var dclimbmovement = (Single)(gameTime.ElapsedGameTime.TotalSeconds * (nextNode.Action == MoveNode.Type.Wander ? 70 : 50)) * RunningSpeed; var dclimb = (nextNode.ScreenPosition - pea.Position); if (dclimb != Vector2.Zero) { var climbdir = Vector2.Normalize(dclimb); var dclimbdt = climbdir * dclimbmovement; dclimbdt = dclimbdt.Length() < dclimb.Length() ? dclimbdt : dclimb; pea.Rotation += (Single)(gameTime.ElapsedGameTime.TotalSeconds * 4) * RunningSpeed * (climbdir).Length() * (nextNode.Dir == MoveNode.Direction.Left ? -1 : 1); pea.Position = pea.Position + dclimbdt; } reached = Math.Abs((dclimb).Length()) < 1f * RunningSpeed; break; /*case MoveNode.Type.Jump: // TODO: path var jlength = Math.Abs((nextNode.ScreenPosition - previousNode.ScreenPosition).X); var djumpmovement = (Single)(gameTime.ElapsedGameTime.TotalSeconds * 2.5f); snapshot.JumpAmount += djumpmovement / (jlength / 70); var djumpwalk = (nextNode.ScreenPosition - pea.Position); var jumpdir = Vector2.Normalize(djumpwalk); var jamount = Math.Max(0, Math.Min(1, (1 - Math.Abs(djumpwalk.X) / jlength))); if (djumpwalk != Vector2.Zero) { pea.Rotation += (Single)(gameTime.ElapsedGameTime.TotalSeconds * 7) * (jumpdir).X; pea.Position = Vector2.Hermite(previousNode.ScreenPosition, -Vector2.UnitY * 50, nextNode.ScreenPosition, Vector2.UnitY * 50 , snapshot.JumpAmount); //if (jamount < 0.4f) { //pea.Position = Vector2.Lerp(pea.Position, nextNode.ScreenPosition - Vector2.UnitY * 60, djumpmovement / (jlength / 70f)); //pea.Position + jumpdir * djumpmovement; Vector2.CatmullRom(previousNode.ScreenPosition + Vector2.UnitY * 5, previousNode.ScreenPosition, nextNode.ScreenPosition, nextNode.ScreenPosition + Vector2.UnitY * 5, jamount); //} else { //pea.Position = Vector2.Lerp(Vector2.Lerp(nextNode.ScreenPosition, nextNode.ScreenPosition - Vector2.UnitY * 60, 0.8f), // nextNode.ScreenPosition, jamount + djumpmovement * 0.005f); //} reached = Math.Abs((djumpwalk).Length()) < 0.8f; } else { reached = true; } if (reached) snapshot.JumpAmount = 0; break;*/ case MoveNode.Type.None: case MoveNode.Type.Walk: default: var dwalkmovement = (Single)(gameTime.ElapsedGameTime.TotalSeconds * 70) * RunningSpeed; var dwalk = (nextNode.ScreenPosition - pea.Position); var walkdir = Vector2.Normalize(dwalk); if (dwalk != Vector2.Zero) { var dwalkdt = walkdir * dwalkmovement; dwalkdt = dwalkdt.Length() < dwalk.Length() ? dwalkdt : dwalk; pea.Rotation += (Single)(gameTime.ElapsedGameTime.TotalSeconds * 4) * RunningSpeed * (walkdir).X;; pea.Position = pea.Position + dwalkdt; } reached = Math.Abs((dwalk).Length()) < Math.Min(30f, 1f * RunningSpeed); break; } // If reached node, dequeue if (reached) snapshot.ProgressPath(); // Jump if reached spot if (!snapshot.HasRemainingPath && snapshot.Target != null) Jump(pea, gameTime); return reached; }
/// <summary> /// Gets the controller state for a pea /// </summary> /// <param name="pea"></param> /// <returns></returns> protected PeaControllerState GetSnapshot(DataPea pea) { return _snapshots[pea]; }
/// <summary> /// Updates a pea /// </summary> /// <param name="gameTime"></param> public void Update(DataPea pea, GameTime gameTime) { if (!this.Enabled) return; // If dead, move up if (!pea.IsAlive) { if (!pea.IsDying) { pea.Position -= Vector2.UnitY * (Single)(gameTime.ElapsedGameTime.TotalSeconds * 100 * RunningSpeed); if (pea.Position.Y + 300 + 200 < 0) pea.Revive(); } return; } // Update task limiter var snapshot = GetSnapshot(pea); snapshot.UpdateTargetLimit(gameTime, RunningSpeed); // Wait for rehab to pass if (pea.IsRehabilitating) { // If there is still a target if (snapshot.Target != null || !GetSnapshot(pea).WanderingNode.HasValue) { // Update the wandering node to the arrived location if (IsValid(pea.GridPosition)) { var block = pea.GridPosition.Y >= 0 ? _grid.Grid[pea.GridPosition.X][pea.GridPosition.Y] : new DataBlock(new Point(pea.GridPosition.X, pea.GridPosition.Y - 1), BlockType.None, null); var wanderto = CreateNode(block, MoveNode.Type.Walk, MoveNode.Direction.None).Value; snapshot.Wander(wanderto, wanderto); } else { pea.Die(); } snapshot.Target = null; } //pea.Rotation = Math.Min((Single)(Math.PI * 2), pea.Rotation + (Single)gameTime.ElapsedGameTime.TotalSeconds * 5); return; } // If we still can move if (snapshot.HasRemainingPath) { if (UpdateMoveTo(pea, gameTime) && snapshot.Target == null && !snapshot.HasRemainingPath) FindWanderNode(pea, new Node<MoveNode>() { Value = snapshot.PreviousNode }); } // else Wander else if (UpdateMoveTo(pea, gameTime)) { // If no target and pathfinding is available. // What I do here is chain the pathfinding tasks so they don't take up so // much CPU. Pathfinding isn't that expensive but I didn't do a great job on it. // Reached wander node so lets find a new path if (snapshot.Target == null) // && (_targetTask == null || _targetTask.IsCompleted) && snapshot.TargetLimit <= 0) //_targetTask = Task.Factory.StartNew(() => FindTarget(pea)).ContinueWith((a) => snapshot.ResetTargetLimit()); if (snapshot.TargetLimit <= 0) { if (!FindTarget(pea)) // Also find a new wander node so we can wander while it searches. // when the findTarget function finishes, replaces the nodelist so // the next iteration the movement WILL go to the target FindWanderNode(pea); snapshot.ResetTargetLimit(); } else { FindWanderNode(pea); } } }
/// <summary> /// Used to determine the active jump info /// </summary> /// <param name="pea"></param> /// <returns></returns> public Dictionary<BlockType, Int32> ActiveTimes(DataPea pea) { return _active.FirstOrDefault(s => s.Pea == pea).Times; }
/// <summary> /// Fail the spot for this pea /// </summary> /// <param name="dataPea"></param> internal void Fail(DataPea pea) { _hasFailed.Add(pea); var getOnSource = (Placement == Location.Left ? Source.JumpLeft : Source.JumpRight); // Complete on other and kill this (shouldnt be needed) if (getOnSource != this) getOnSource.Fail(pea); }
/// <summary> /// Has jumped this for a pea /// </summary> /// <param name="pea"></param> /// <returns></returns> public Boolean HasJumped(DataPea pea) { return _hasStarted.Contains(pea); }
/// <summary> /// Is valid path /// </summary> /// <param name="path"></param> /// <returns></returns> private Boolean IsValid(DataPea pea, Queue<MoveNode> path) { // TODO: retry a path from a new position position if (path.Peek().Position != pea.GridPosition) return false; var valid = new Queue<MoveNode>(); // Dummy previous node valid.Enqueue(CreateNode(pea.GridPosition, MoveNode.Type.Walk, MoveNode.Direction.None).Value); while (path.Count > 0) { var node = path.Peek(); // Check validity of a node itself if (!IsValid(node.Position)) return false; // Check validity of moving from to the node if (!IsValid(valid.LastOrDefault(), node)) return false; valid.Enqueue(path.Dequeue()); } // Remove dummy valid.Dequeue(); // Restore path while (valid.Count > 0) path.Enqueue(valid.Dequeue()); return true; }
/// <summary> /// Finds a node to wander /// </summary> /// <param name="pea"></param> /// <returns></returns> protected void FindWanderNode(DataPea pea, Node<MoveNode> prev = null) { var snapshot = GetSnapshot(pea); var block = pea.GridPosition.Y >= 0 ? _grid.Grid[pea.GridPosition.X][pea.GridPosition.Y] : new DataBlock(new Point(pea.GridPosition.X, pea.GridPosition.Y - 1), BlockType.None, null); var node = (prev == null) ? (snapshot.WanderingNode.HasValue && snapshot.WanderingNode.Value.Action != MoveNode.Type.None && snapshot.WanderingNode.Value.Position == pea.GridPosition ? new Node<MoveNode>() { Value = snapshot.WanderingNode.Value } : CreateNode(block, MoveNode.Type.Walk, MoveNode.Direction.None) ) : prev; var possibleNodes = CreateMoveNodesFrom(node); if (possibleNodes.Count > 0) { // Find nodes that go higher (non walk nodes and non lineair jumps) var nonwalk = possibleNodes.Where(a => a.Value.Action != MoveNode.Type.Walk && !((a.Value.Action == MoveNode.Type.Jump) && (a.Value.Dir == MoveNode.Direction.None))); // Limit to these if needed if (nonwalk.Count() > 0) { possibleNodes = nonwalk.ToList(); } else if (DataPea.Random.Next(100) < 10) { snapshot.Wander(node.Value, null); pea.Jump(null); return; } snapshot.Wander(node.Value, possibleNodes[DataPea.Random.Next(possibleNodes.Count)].Value); } else { snapshot.Wander(node.Value, null); pea.Jump(null); } }
/// <summary> /// Initializes screen /// </summary> public override void Initialize() { // Create the scene and add it _camera = new Camera2D(this.Game); _camera.Initialize(); _fxcamera = new Camera2D(this.Game); _fxcamera.Initialize(); _scene = new Scene(this.Game, _camera); _scene.TransitionPosition = 0; _scene.TransitionOnTime = TimeSpan.FromSeconds(1); _scene.TransitionOffTime = TimeSpan.FromSeconds(1); _scene.OffTransition(); _fx = new World(Vector2.UnitY * 10); _fxStaticBody = new Body(_fx) { Restitution = 0, Mass = 0, BodyType = BodyType.Static, Friction = 0.5f/*, Position = ConvertUnits.ToSimUnits(Vector2.UnitX * (_width - DataGrid.WidthInPixels) / 2f + Vector2.UnitY * 150)*/ }; // Create controllers _timeController = new TimeController(this.Game); _pointsController = new PointsController(this.Game); _dataGrid = DataGrid.CreateDataGrid(this.Game, _fxStaticBody, _width / 70 - 1, _height / 49 - 4); _peaController = new PeaController(this.Game); _inputController = new InputController(this.Game); _achievementController = new AchievementController(this.Game); // Initialize controllers _timeController.Initialize(); _pointsController.Initialize(); _dataGrid.Initialize(); _peaController.Initialize(); _inputController.Initialize(); _achievementController.Initialize(); // Register controllers _dataGrid.Register(_peaController); #if DEBUG && _ DataBlock testBlock = _dataGrid.Add(new Point(0, 0), BlockType.Normal); DataBlock testBlock2 = _dataGrid.Add(new Point(0, 1), BlockType.Gel); DataBlock testBlock3 = _dataGrid.Add(new Point(1, 1), BlockType.Normal); DataBlock testBlock4 = _dataGrid.Add(new Point(2, 1), BlockType.RightRamp); DataBlock testBlock5 = _dataGrid.Add(new Point(3, 2), BlockType.Normal); DataBlock testBlock6 = _dataGrid.Add(new Point(DataGrid.Width - 1, DataGrid.Height - 1), BlockType.Normal); #endif // Create the peas DataPea pea1 = new DataPea(this.Game, _fx, _peaController); _pointsController.Register(pea1); _achievementController.Register(pea1); pea1.Initialize(); this.Game.Components.Add(pea1); DataPea pea2 = new DataPea(this.Game, _fx, _peaController); DataPea pea3 = new DataPea(this.Game, _fx, _peaController); DataPea pea4 = new DataPea(this.Game, _fx, _peaController); DataPea pea5 = new DataPea(this.Game, _fx, _peaController); // This needs to be done BEFORE sprites of pea _pointsController.Register(pea2); _pointsController.Register(pea3); _pointsController.Register(pea4); _pointsController.Register(pea5); _achievementController.Register(pea2); _achievementController.Register(pea3); _achievementController.Register(pea4); _achievementController.Register(pea5); pea2.Initialize(); pea3.Initialize(); pea4.Initialize(); pea5.Initialize(); this.Game.Components.Add(pea2); this.Game.Components.Add(pea3); this.Game.Components.Add(pea4); this.Game.Components.Add(pea5); // Create layers _sceneryLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.9f }; _levelLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.6f }; _peasLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.3f }; _hudLayer = new SceneLayer(this.Game, _scene.Camera) { MoveSpeed = 0f, Distance = 0.1f }; // Create sprites _spriteGrid = new SpritesetGrid(_levelLayer) { Position = Vector2.UnitX * (_width - DataGrid.WidthInPixels) / 2f + Vector2.UnitY * 150 }; SpritePea.BaseOffset = _spriteGrid.Position; _peasLayer.Add(new SpritePea(_peasLayer, pea1, _pointsController)); #if !DEBUG || !TEST _peasLayer.Add(new SpritePea(_peasLayer, pea2, _pointsController)); _peasLayer.Add(new SpritePea(_peasLayer, pea3, _pointsController)); _peasLayer.Add(new SpritePea(_peasLayer, pea4, _pointsController)); _peasLayer.Add(new SpritePea(_peasLayer, pea5, _pointsController)); #endif #if DEBUG && TEST for (int i = 0; i < DataGrid.Width; i++) { if (new int[] { 3, 4, 5, 10, 12, 14 }.Contains(i) == false) { DataBlock b = _dataGrid.Add(new Point(i, DataGrid.Height - 1), BlockType.Normal); //_spriteGrid.Add(new SpriteBlock(_levelLayer, b)); if (new int[] { 0 , 1, 2, 5, 8, 15 }.Contains(i)) { b = _dataGrid.Add(new Point(i, DataGrid.Height - 2), BlockType.Normal); //_spriteGrid.Add(new SpriteBlock(_levelLayer, b)); } if (new int[] { 0, 15 }.Contains(i)) { b = _dataGrid.Add(new Point(i, DataGrid.Height - 3), BlockType.Gel); //_spriteGrid.Add(new SpriteBlock(_levelLayer, b)); } if (new int[] { 0, 15 }.Contains(i)) { b = _dataGrid.Add(new Point(i, DataGrid.Height - 4), BlockType.Gel); //_spriteGrid.Add(new SpriteBlock(_levelLayer, b)); } } } DataBlock jump = _dataGrid.Add(new Point(3, 7), BlockType.Normal); //_spriteGrid.Add(new SpriteBlock(_levelLayer, jump)); DataBlock ramp = _dataGrid.Add(new Point(1, 8), BlockType.RightRamp); //_spriteGrid.Add(new SpriteBlock(_levelLayer, ramp)); //DataBlock gel = _dataGrid.Add(new Point(5, 10), BlockType.LeftRamp); //_spriteGrid.Add(new SpriteBlock(_levelLayer, gel)); #else // Some boundary blocks _dataGrid.Add(new Point(0, DataGrid.Height - 1), BlockType.Gel); _dataGrid.Add(new Point(DataGrid.Width - 1, DataGrid.Height - 1), BlockType.Gel); _dataGrid.Add(new Point(0, DataGrid.Height - 2), BlockType.Gel); _dataGrid.Add(new Point(DataGrid.Width - 1, DataGrid.Height - 2), BlockType.Gel); #endif SpriteToolbox toolbox = new SpriteToolbox(_hudLayer) { Position = new Vector2(_width - (1280 - 1220), (Single)Math.Ceiling(150 * (_height / 720f))) }; SpritesetHud hud = new SpritesetHud(_hudLayer, _pointsController, _inputController.State, _width, _height); // Register sprites at inputControllers _inputController.Register(_spriteGrid); _inputController.Register(toolbox); _inputController.Register(_camera, _width, _height); foreach (var blockRow in _dataGrid.Grid) foreach (var block in blockRow) { block.Place(block.BlockType, BlockState.Placed); // Direct placing; _spriteGrid.Add(new SpriteBlock(_levelLayer, block)); } // Add the layers _scene.Add(_sceneryLayer); _scene.Add(_levelLayer); _scene.Add(_peasLayer); _scene.Add(_hudLayer); // Add the content Sprite background = new Sprite(_sceneryLayer, "Graphics/Background"); background.Position = new Vector2(_width / 2f, _height / 2f); background.Origin = new Vector2(1280f / 2f, 720f / 2f); background.Scale = Math.Max(_width / 1280f, _height / 720f); Sprite splate = new Sprite(_sceneryLayer, "Graphics/Plate"); splate.Position = new Vector2(_width / 2f, _height / 2f); splate.Origin = new Vector2(1280f / 2f, 720f / 2f); splate.Scale = Math.Max(_width / 1280f, _height / 720f); _sceneryLayer.Add(background); _sceneryLayer.Add(splate); _levelLayer.Add(_spriteGrid); _hudLayer.Add(toolbox); _hudLayer.Add(hud); // Bottom plate physics var plate = FixtureFactory.AttachRectangle(ConvertUnits.ToSimUnits(_width), ConvertUnits.ToSimUnits(20), 1f, ConvertUnits.ToSimUnits(Vector2.UnitY * (49 * (DataGrid.Height - 3) + _spriteGrid.Position.Y + 5) + (_width / 2 - _spriteGrid.Position.X) * Vector2.UnitX), _fxStaticBody); plate.Restitution = 0; plate.Friction = 0.5f; // Initializes scene and so on base.Initialize(); _scene.Initialize(); _camera.Position = new Vector2(_width / 2f, _height / 2f); _fxcamera.Position = new Vector2(_width / 2f, _height / 2f)- _spriteGrid.Position; // + ConvertUnits.ToSimUnits(_spriteGrid.Position); _camera.Jump2Target(); _fxcamera.Jump2Target(); #if DEBUG && !SILVERLIGHT view = new DebugViewXNA(_fx); view.AppendFlags(FarseerPhysics.DebugViewFlags.CenterOfMass | FarseerPhysics.DebugViewFlags.DebugPanel | FarseerPhysics.DebugViewFlags.PerformanceGraph | FarseerPhysics.DebugViewFlags.PolygonPoints); #endif // Add components this.Game.Components.Add(_peaController); this.Game.Components.Add(_timeController); this.Game.Components.Add(_inputController); this.Game.Components.Add(_pointsController); this.Game.Components.Add(_achievementController); this.Game.Components.Add(_camera); this.Game.Components.Add(_fxcamera); this.Game.Components.Add(_dataGrid); this.Game.Components.Add(_scene); // Add popups _achievementController.OnCompletedAchievement += new AchievementCompletedHandler(_achievementController_OnCompletedAchievement); // Add overlay _overlay = new PauseOverlay(_camera, _width, _height); _overlay.Exiting += new EventHandler(_overlay_Exiting); // Events this.Exited += new EventHandler(PeaScreen_Exited); this.OnEnabledChanged += new BooleanDelegate(PeaScreen_OnEnabledChanged); this.OnVisibleChanged += new BooleanDelegate(PeaScreen_OnVisibleChanged); // Add end _pointsController.OnReachedGoal += new Action(_pointsController_OnReachedGoal); this.IsEnabled = false; this.IsVisible = false; }
/// <summary> /// Has jumped this for a pea /// </summary> /// <param name="pea"></param> /// <returns></returns> public Boolean HasJumped(DataPea pea) { return(_hasStarted.Contains(pea)); }
/// <summary> /// Complete this for a pea /// </summary> /// <param name="pea"></param> public void Complete(DataPea pea) { _hasCompleted.Add(pea); var getOnSource = (Placement == Location.Left ? Source.JumpLeft : Source.JumpRight); // Complete on other and kill this (shouldnt be needed) if (getOnSource != this) getOnSource.Complete(pea); if (_hasCompleted.Count == MaxCompletion) getOnSource.Source.CompleteJumpSpot(getOnSource); }
/// <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> /// Process collision /// </summary> /// <param name="pea"></param> /// <param name="speed"></param> /// <param name="block"></param> private void DoHappyCollision(DataPea pea, Vector2 speed, DataBlock block) { PointsControllerState state; if (block != null && !block.IsPlaced) return; if ((state = _active.FirstOrDefault(p => p.Pea == pea)) != null) if (!state.IncreaseHappiness(speed, block)) pea.Trap(); }
/// <summary> /// Registers a pea /// </summary> /// <param name="pea"></param> public void Register(DataPea pea) { _peas.Add(pea); _snapshots.Add(pea, new PeaControllerState()); pea.OnRevive += new EventHandler(pea_OnRevive); }
/// <summary> /// /// </summary> /// <param name="spot"></param> /// <param name="pea"></param> public JumpEventArgs(DataJumpSpot spot, DataPea pea) : base() { this.Spot = spot; this.Pea = pea; }