/// <summary> /// Finds a path between 2 position on a map /// </summary> /// <param name="startPosition">Starting position</param> /// <param name="endPosition">Destination</param> /// <param name="map">Game map currently being used</param> /// <param name="endNodeUnWalkable"></param> /// <returns>A list of Vector2 waypoints that the object must traverse to get to its destination</returns> internal Stack <Vector2> FindPath(Vector2 startPosition, Vector2 endPosition, ref Map.Map map, EndNodeUnWalkableTreatment endNodeUnWalkable = EndNodeUnWalkableTreatment.DISALLOW) { if (!Map.Map.IsOnTop(endPosition) || !map.GetCollisionMap().GetWalkabilityGrid().IsWalkableAt(VectorToGridPos(endPosition))) { return(new Stack <Vector2>()); } var startGridPos = VectorToGridPos(startPosition); var endGridPos = VectorToGridPos(endPosition); if (ClearDirectPath(startGridPos.x, startGridPos.y, endGridPos.x, endGridPos.y, ref map)) { var pathVector = new Stack <Vector2>(1); pathVector.Push(endPosition); return(pathVector); } else { if (mJpParam != null) { mJpParam.Reset(VectorToGridPos(startPosition), VectorToGridPos(endPosition)); } else { mJpParam = new JumpPointParam(map.GetCollisionMap().GetWalkabilityGrid(), startGridPos, iDiagonalMovement: DiagonalMovement.OnlyWhenNoObstacles, iEndPos: endGridPos, iAllowEndNodeUnWalkable: endNodeUnWalkable, iMode: HeuristicMode.MANHATTAN); } var pathGrid = JumpPointFinder.FindPath(mJpParam); var pathVector = new Stack <Vector2>(pathGrid.Count); pathVector.Push(endPosition); for (var i = pathGrid.Count - 1; i > 0; i--) { var gridPos = GridPosToVector2(pathGrid[i]); pathVector.Push(gridPos); } return(pathVector); } }
/// <summary> /// Removes the given object from the game screens list of objects to handle. /// </summary> /// <typeparam name="T">The type of the object to be removed. Needs to inherit from IDraw or IUpdate</typeparam> /// <param name="toRemove">The object to be removed to the game screen</param> /// <returns>True if the given object could be removed, false otherwise</returns> public bool RemoveObject <T>(T toRemove) { var road = toRemove as Road; var platform = toRemove as PlatformBlank; var settler = toRemove as Settler; var freeMovingUnit = toRemove as FreeMovingUnit; if (!typeof(IDraw).IsAssignableFrom(typeof(T)) && !typeof(IUpdate).IsAssignableFrom(typeof(T)) && road == null && platform == null) { return(false); } if (typeof(ICollider).IsAssignableFrom(typeof(T))) { mMap.GetCollisionMap().RemoveCollider((ICollider)toRemove); } if (road != null && !road.Blueprint) { mMap.RemoveRoad(road); } if (platform != null && !platform.mBlueprint) { mMap.RemovePlatform(platform); mDirector.GetMilitaryManager.RemovePlatform(platform); } if (settler != null) { settler.BuildCommandCenter -= SettlerBuild; } // unsubscribe from this military unit when deleted if (freeMovingUnit != null && freeMovingUnit.Friendly) { mSelBox.SelectingBox -= freeMovingUnit.BoxSelected; } if (typeof(IRevealing).IsAssignableFrom(typeof(T))) { mFow.RemoveRevealingObject((IRevealing)toRemove); } if (typeof(ISpatial).IsAssignableFrom(typeof(T))) { mSpatialObjects.Remove((ISpatial)toRemove); return(true); } if (typeof(IDraw).IsAssignableFrom(typeof(T))) { mDrawables.Remove((IDraw)toRemove); } if (typeof(IUpdate).IsAssignableFrom(typeof(T))) { mUpdateables.Remove((IUpdate)toRemove); } return(true); }
/// <summary> /// Checks if a direct plath is clear of obstacles. Based on Bresenham's /// line algorithm. /// </summary> /// <see cref="http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm"/> /// <param name="x">Starting x position.</param> /// <param name="y">Starting y position.</param> /// <param name="x2">Target x position.</param> /// <param name="y2">Target y position.</param> /// <param name="map">Reference to the game map.</param> /// <returns>True if there is a clear direct path to the target.</returns> public static bool ClearDirectPath(int x, int y, int x2, int y2, ref Map.Map map) { var w = x2 - x; var h = y2 - y; int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0; if (w < 0) { dx1 = -1; } else if (w > 0) { dx1 = 1; } if (h < 0) { dy1 = -1; } else if (h > 0) { dy1 = 1; } if (w < 0) { dx2 = -1; } else if (w > 0) { dx2 = 1; } var longest = Math.Abs(w); var shortest = Math.Abs(h); if (!(longest > shortest)) { longest = Math.Abs(h); shortest = Math.Abs(w); if (h < 0) { dy2 = -1; } else if (h > 0) { dy2 = 1; } dx2 = 0; } var numerator = longest >> 1; for (var i = 0; i <= longest; i++) { if (!map.GetCollisionMap().GetWalkabilityGrid().IsWalkableAt(x, y)) { return(false); } numerator += shortest; if (!(numerator < longest)) { numerator -= longest; x += dx1; y += dy1; } else { x += dx2; y += dy2; } } return(true); }
public void Update(GameTime gametime) { switch (mCurrentState.GetState()) { case 1: if (!mIsRoadPlacement) { mNatureObjectThere = false; mPlatform.ResetColor(); // for this, we want the platform to follow the mouse, and also be centered on the sprite. mPlatform.AbsolutePosition = new Vector2(mMouseX - mPlatform.AbsoluteSize.X / 2f, mMouseY - mPlatform.AbsoluteSize.Y / 2f); for (int x = (int)(mPlatform.AbsolutePosition.X / MapConstants.GridWidth); x < (int)((mPlatform.AbsolutePosition.X + mPlatform.AbsoluteSize.X) / MapConstants.GridWidth); x++) { for (int y = (int)(mPlatform.AbsolutePosition.Y / MapConstants.GridWidth); y < (int)((mPlatform.AbsolutePosition.Y + mPlatform.AbsoluteSize.Y) / MapConstants.GridWidth); y++) { if (!mMap.GetCollisionMap().GetWalkabilityGrid().IsWalkableAt(x, y)) { mNatureObjectThere = true; } } } if (mHoveringPlatform == null && !mNatureObjectThere) { break; } mPlatform.SetColor(Color.Red); mPlaySound = false; } break; case 2: if (!mIsRoadPlacement) { // now we want a road to follow our mouse mConnectionRoad.Destination = new Vector2(mMouseX, mMouseY); if (!mPlaySound) { // makes a sound once when platform is placed mDirector.GetSoundManager.SetSoundPosition(mPlatformCreateSoundId, mMouseX, mMouseY); mDirector.GetSoundManager.PlaySound(mPlatformCreateSoundId); mPlaySound = true; } // we prematurely reset the color of the platform, so we don't have to worry about it being red mPlatform.ResetColor(); if (mHoveringPlatform == null) { break; } // at this point we have a hovering platform, so we clip the road destination to its center mConnectionRoad.Destination = mHoveringPlatform.Center; // we only color the platform red if the distance to the platform hovered is too great if (Vector2.Distance(mHoveringPlatform.Center, mPlatform.Center) > mPlatform.RevelationRadius + mHoveringPlatform.RevelationRadius || !mHoveringPlatform.Friendly) { mPlatform.SetColor(Color.Red); } } else { mRoadToBuild.Destination = new Vector2(mMouseX, mMouseY); if (mHoveringPlatform == null) { break; } mRoadToBuild.Destination = mHoveringPlatform.Center; } break; case 3: if (!mIsRoadPlacement) { // this case is the 'finish' state, we set everything up, so the platform can get added to the game mPlatform.SetLayer(LayerConstants.PlatformLayer); mConnectionRoad.Place(mPlatform, mHoveringPlatform); mHoveringPlatform.AddBlueprint(new BuildBluePrint(mHoveringPlatform, mPlatform, mConnectionRoad, ref mDirector)); } else { mRoadToBuild.Place(mOldHovering, mHoveringPlatform); } mIsFinished = true; mUnregister = true; mDirector.GetUserInterfaceController.BuildingProcessFinished(); break; } if (mUnregister) { UnregisterFromInputManager(); } // don't forget to always update the relative position since the camera might have moved. UpdateBounds(); }