public static void panToCharacter(Character character, Camera camera, Map map, GraphicsDeviceManager graphics, int panSeconds=1) { // camera starts at P1. Camera moves a distance equal to the differencce between the camera's center at P1 and the chracter given. //get the current camera position and center. float ViewSizeX = graphics.GraphicsDevice.Viewport.Width; // width of the current game viewport float ViewSizeY = graphics.GraphicsDevice.Viewport.Height; // height of the current game viewport Vector2 originalCameraPosition = camera.cameraLocation; //record the original position of the camera Vector2 originalCameraCenter = new Vector2(originalCameraPosition.X + ViewSizeX/2, originalCameraPosition.Y + ViewSizeY/2); int originalCharPosX = (int)character.position.X; int originalCharPosY = (int)character.position.Y; Tile OriginalCharTile = map.tiles[originalCharPosX, originalCharPosY];// character.position; int originalCharPosPixX = ((originalCharPosX * (Tile.width)) + ((originalCharPosY - 1) * (Tile.width / 2)) + (int)camera.cameraLocation.X); int originalCharPosPixY = ((originalCharPosY * (Tile.height / 2)) + (int)camera.cameraLocation.Y); Vector2 originalCharPosPix = new Vector2(originalCharPosPixX,originalCharPosPixY); //camera change equal to the difference in the camera center at p1 and the character's initial position Vector2 transformVector = originalCameraCenter - originalCharPosPix; //move the camera such that it reaches its final destination in panSeconds seconds //calculate pixels to move and sleep time such that the camera moves a distance x in panSeconds seconds panCameraToLocation(camera, transformVector); //camera.cameraLocation = transformVector; }
public static void assignCoverToTile(Cover cover, Map battleMap) { int coverPositionX = cover.PositionX; int coverPositionY = cover.PositionY; Tile assignTile = battleMap.tiles[coverPositionX, coverPositionY]; assignTile.cover = cover; assignTile.isOccupied = true; }
//default map constructor for making square maps public static Map buildDefaultMap(int width, int height) { Map defaultMap = new Map(width, height); for (int x = 1; x < width; x++) { for (int y = 1; y < height; y++) { defaultMap.tiles[x, y] = new Tile(x, y); } } return defaultMap; }
public PlayState(Map battleMap) { allies = Character.createTestAllies(5, battleMap); enemies = Character.createTestEnemies(5, battleMap); //create teams of characters allCharacters = new List<Character>(0); allCover = Cover.createTestCover(battleMap); allCharacters.AddRange(allies); allCharacters.AddRange(enemies); moveableSpaces = new MoveableSpacesTileSet(); currentMap = battleMap; playerTurn = true; playMode = Mode.moving; }
private static List<Node> getAdjacentNodes(Tile startingTile, Map map, List<Node> closedList, Node destinationNode) { List<Node> adjacentNodes = new List<Node>(); List<Tile> tilesToCheck = new List<Tile>(); Node startingNode = new Node(startingTile); int startingX = startingTile.xPos; int startingY = startingTile.yPos; if (map.coordinatesOnMap(startingX, startingY + 1)) tilesToCheck.Add(map.tiles[startingX, startingY + 1]); if (map.coordinatesOnMap(startingX, startingY - 1)) tilesToCheck.Add(map.tiles[startingX, startingY - 1]); if (map.coordinatesOnMap(startingX + 1, startingY)) tilesToCheck.Add(map.tiles[startingX + 1, startingY]); if (map.coordinatesOnMap(startingX - 1, startingY)) tilesToCheck.Add(map.tiles[startingX - 1, startingY]); foreach (Tile tile in tilesToCheck) { //make sure the tile isnt occupied and isnt in the checked list. if (!tile.isOccupied && !(closedList.FindIndex(node => node.nodeTile == tile) >= 0)) { Node newNode = new Node(tile); newNode.FValue = calculateFValue(newNode, destinationNode); newNode.parentNode = startingNode; adjacentNodes.Add(newNode); } } return adjacentNodes; }
public static List<Tile> shortestPath(Map map, Tile startingTile, Tile destinationTile) { List<Tile> path = new List<Tile>(); List<Node> openNodes = new List<Node>(); List<Node> closedNodes = new List<Node>(); List<Node> adjacentNodes = new List<Node>(); bool reachedDestination = false; //initialize. Set starting tile to be the first open node. Node startingNode = new Node(startingTile); Node destinationNode = new Node(destinationTile); startingNode.FValue = calculateFValue(startingNode, destinationNode); openNodes.Add(startingNode); Node nodeToEval = startingNode; while (openNodes.Count > 0) // while nodeToEval != destinationNode ? { //get adjacent nodes and add them to openNodes adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); openNodes.AddRange(adjacentNodes); openNodes.Remove(nodeToEval); closedNodes.Add(nodeToEval); //remove nodeToEval from open list, add to closed list if (nodeToEval.nodeTile.xPos == destinationNode.nodeTile.xPos && nodeToEval.nodeTile.yPos == destinationNode.nodeTile.yPos) { reachedDestination = true; break; } //Now we find the NEXT node to evaluate //We search for the lowest F value in the whole open list after adding the ajacent nodes above int lowestFValue = openNodes.Min(node => node.FValue); //Now get the node with that lowest value - thats our next node to examine. Node nextNodeToEval = openNodes.Find(node => node.FValue == lowestFValue); nodeToEval = nextNodeToEval; } if (reachedDestination == true) { //done! collect the destination and all parent nodes in a list path.Add(nodeToEval.nodeTile); Node nextParentNode = nodeToEval.parentNode; while (nextParentNode != null) { path.Add(nextParentNode.nodeTile); //find parent node in the closed list Node currentParentNode = closedNodes.Find(node => node.nodeTile.xPos == nextParentNode.nodeTile.xPos && node.nodeTile.yPos == nextParentNode.nodeTile.yPos); nextParentNode = currentParentNode.parentNode; } } // find adjacent available nodes and add nodeToEval to the closed list afterwards. //adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); //openNodes.Remove(nodeToEval); // openNodes.AddRange(adjacentNodes); return path; }
public static MoveableSpacesTileSet moveableSpaces(Map map, Character selectedCharacter) { List<Tile> checkedTiles = new List<Tile>(); MoveableSpacesTileSet tileSet = new MoveableSpacesTileSet(); List<Tile> tilesToCheckThisLevel = new List<Tile>(); List<Tile> tilesToCheckNextLevel = new List<Tile>(); int startingTileX = (int)selectedCharacter.position.X; int startingTileY = (int)selectedCharacter.position.Y; int maxMoves = (2 * selectedCharacter.stats.movement) + 1; Tile startingTile = map.tiles[startingTileX, startingTileY]; tilesToCheckThisLevel.Add(startingTile); for (int dist = 0; dist < maxMoves; dist++) { foreach(Tile tile in tilesToCheckThisLevel.ToList()) { List<Tile> adjacentUncheckedTiles = getAdjacentUncheckedTiles(tile, map, checkedTiles); checkedTiles.Add(tile); tileSet.AllMoveableTiles.Add(tile); if (dist <= selectedCharacter.stats.movement){ tileSet.FirstMoveMoveableTiles.Add(tile); } else { tileSet.SecondMoveMoveableTiles.Add(tile); } tilesToCheckNextLevel.AddRange(adjacentUncheckedTiles); tilesToCheckThisLevel.Remove(tile); //remove the one we just checked. No need to check it again. } //level complete tilesToCheckThisLevel = tilesToCheckNextLevel; tilesToCheckNextLevel = new List<Tile>(); } return tileSet; }
public static List<Tile> getAdjacentUncheckedTiles(Tile StartingTile, Map map, List<Tile> checkedTiles) { List<Tile> AdjacentTiles = new List<Tile>(); List<Tile> TilesToCheck = new List<Tile>(); int startingTileX = StartingTile.xPos; int startingTileY = StartingTile.yPos; //check if the tiles passed in here resolve to null if (map.coordinatesOnMap(startingTileX, startingTileY + 1) ) TilesToCheck.Add(map.tiles[startingTileX, startingTileY + 1]); if (map.coordinatesOnMap(startingTileX, startingTileY - 1)) TilesToCheck.Add(map.tiles[startingTileX, startingTileY - 1]); if (map.coordinatesOnMap(startingTileX + 1, startingTileY)) TilesToCheck.Add(map.tiles[startingTileX + 1, startingTileY]); if (map.coordinatesOnMap(startingTileX - 1, startingTileY)) TilesToCheck.Add(map.tiles[startingTileX - 1, startingTileY]); if (TilesToCheck.Count > 0) { foreach (Tile currentTile in TilesToCheck) { if (!currentTile.Equals(null)) // if the current tile is off the map, ie (1,0), the current tile will be null. { if (!currentTile.isOccupied && !checkedTiles.Contains(currentTile)) { AdjacentTiles.Add(currentTile); } } } } return AdjacentTiles; }
public static void PanToCharacter(Character targetChar, Camera camera, Map map, float viewportWidth, float viewportHeight) { int originalCharPosPixX = (((int)targetChar.position.X * (Tile.width /2)) + (((int)targetChar.position.Y - 1) * (Tile.width / 2)) + (int)camera.cameraLocation.X); int originalCharPosPixY = (((int)targetChar.position.Y * (Tile.height / 2)) - (((int)targetChar.position.X - 1) * (Tile.height /2)) + (int)camera.cameraLocation.Y); Vector2 targetCharPosition = new Vector2(originalCharPosPixX, originalCharPosPixY); Vector2 originalCameraPosition = camera.cameraLocation; Vector2 originalCameraCenter = new Vector2(originalCameraPosition.X + viewportWidth / 2, originalCameraPosition.Y + viewportHeight / 2); Vector2 cameraPanVector = originalCameraCenter - targetCharPosition; Vector2 normalizedCameraPanVector = cameraPanVector; normalizedCameraPanVector.Normalize(); camera.normalizedCameraPanVector = normalizedCameraPanVector; camera.cameraPanVector = cameraPanVector; camera.cameraDestination = targetCharPosition; camera.cameraState = cameraState.panningToTarget; }
public static List<Tile> shortestPath(Map map, Tile startingTile, Tile destinationTile) { List<Tile> path = new List<Tile>(); List<Node> openNodes = new List<Node>(); List<Node> closedNodes = new List<Node>(); List<Node> adjacentNodes = new List<Node>(); bool reachedDestination = false; //initialize. Set starting tile to be the first open node. Node startingNode = new Node(startingTile); Node destinationNode = new Node(destinationTile); startingNode.FValue = calculateFValue(startingNode, destinationNode); openNodes.Add(startingNode); Node nodeToEval = startingNode; while (openNodes.Count > 0) // while nodeToEval != destinationNode ? { //get adjacent nodes and add them to openNodes adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); openNodes.AddRange(adjacentNodes); openNodes.Remove(nodeToEval); closedNodes.Add(nodeToEval); //remove nodeToEval from open list, add to closed list if (nodeToEval.nodeTile.xPos == destinationNode.nodeTile.xPos && nodeToEval.nodeTile.yPos == destinationNode.nodeTile.yPos) { reachedDestination = true; break; } //Now we find the NEXT node to evaluate //We search for the lowest F value in the whole open list after adding the ajacent nodes above int lowestFValue = openNodes.Min(node => node.FValue); //Now get the node with that lowest value - thats our next node to examine. Node nextNodeToEval = openNodes.Find(node => node.FValue == lowestFValue); //this method will give us boring L-shaped paths if two adjacent nodes have the same F value. //lets try forcing the game to prioritize the one that indicates a change in direction! if((openNodes.FindAll(node => node.FValue == lowestFValue).Count > 1)) { List<Node> potentialNextNodesToEval = openNodes.FindAll(node => node.FValue == lowestFValue); foreach(Node node in potentialNextNodesToEval) { if (nodeToEval.parentNode != null){ if (nodeToEval.parentNode.nodeTile.xPos == nodeToEval.nodeTile.xPos && nodeToEval.nodeTile.xPos != node.nodeTile.xPos) { //change of direction in x, prioritize this node and exit nextNodeToEval = node; break; } else if (nodeToEval.parentNode.nodeTile.yPos == nodeToEval.nodeTile.yPos && nodeToEval.nodeTile.yPos != node.nodeTile.yPos) { //change of direction in y, prioritize this node and exit nextNodeToEval = node; break; } } } } nodeToEval = nextNodeToEval; } if (reachedDestination == true) { //done! collect the destination and all parent nodes in a list path.Add(nodeToEval.nodeTile); Node nextParentNode = nodeToEval.parentNode; while (nextParentNode != null) { path.Add(nextParentNode.nodeTile); //find parent node in the closed list Node currentParentNode = closedNodes.Find(node => node.nodeTile.xPos == nextParentNode.nodeTile.xPos && node.nodeTile.yPos == nextParentNode.nodeTile.yPos); nextParentNode = currentParentNode.parentNode; } } // find adjacent available nodes and add nodeToEval to the closed list afterwards. //adjacentNodes = getAdjacentNodes(nodeToEval.nodeTile, map, closedNodes, destinationNode); //openNodes.Remove(nodeToEval); // openNodes.AddRange(adjacentNodes); return path; }
public static List<Cover> createTestCover(Map map) { List<Cover> cover = new List<Cover>(); Cover testPiece1 = new Cover(1, 2, "upper-left,lower-right"); Cover testPiece2 = new Cover(2, 4, "upper-left,lower-right"); Cover testPiece3 = new Cover(3, 3, "upper-left,lower-right"); Cover testPiece4 = new Cover(19, 18, "upper-left,lower-right"); Cover testPiece5 = new Cover(19, 19, "upper-left,lower-right"); cover.Add(testPiece1); assignCoverToTile(testPiece1, map); cover.Add(testPiece2); assignCoverToTile(testPiece2, map); cover.Add(testPiece3); assignCoverToTile(testPiece3, map); cover.Add(testPiece4); assignCoverToTile(testPiece4, map); cover.Add(testPiece5); assignCoverToTile(testPiece5, map); return cover; }
public static void selectCharacter(Character character, Camera camera, Map map, GraphicsDeviceManager graphics) { character.selected = true; Camera.panToCharacter(character, camera, map, graphics); }
//create charNumber enemies for testing (AI team) public static List<Character> createTestEnemies(int charNumber, Map map) { List<Character> enemies = new List<Character>(); Random rand = new Random(); Character currentChar; StatSheet currentCharStatSheet; Profession currentCharProf; Vector2 currentCharPos; for (int i = 0; i < charNumber; i++) { int currentCharPosX = rand.Next(16, 20); int currentCharPosY = rand.Next(16, 20); while (map.tiles[currentCharPosX, currentCharPosY].isOccupied == true) { currentCharPosX = rand.Next(16, 20); currentCharPosY = rand.Next(16, 20); } currentCharPos = new Vector2(currentCharPosX, currentCharPosY); currentCharStatSheet = new StatSheet(rand.Next(24, 40), rand.Next(3, 4), rand.Next(50, 70), Ability.createTestCharacterAbiities()); currentCharProf = new Profession("test"); currentChar = new Character(currentCharStatSheet, currentCharProf, currentCharPos); enemies.Add(currentChar); assignCharacterToTile(currentChar, map); } return enemies; }
//assign the character to a location on the map public static void assignCharacterToTile(Character character, Map battleMap) { int characterPosX = (int)character.position.X; int characterPosY = (int)character.position.Y; Tile assignTile = battleMap.tiles[characterPosX, characterPosY]; assignTile.isOccupied = true; }
public static void PerformCharacterMovement(Character charToMove, Map map) { float currentDestinationX = charToMove.movementProfile.currentDestinationPixels.X; float currentDestinationY = charToMove.movementProfile.currentDestinationPixels.Y; float currentLocationX = charToMove.pixelPosition.X; float currentLocationY = charToMove.pixelPosition.Y; Tile originalTile = map.tiles[(int)charToMove.position.X, (int)charToMove.position.Y]; //if the character is within deltaX or detaY of the destination, move them there and make the next segment active. float distanceFromDestX = Math.Abs(currentDestinationX - currentLocationX); float distanceFromDestY = Math.Abs(currentDestinationY - currentLocationY); if (distanceFromDestX < Character.movementSpeedX || distanceFromDestY < Character.movementSpeedY) { //switch to next segment along character path int indexOfCurrentSegment = charToMove.movementProfile.currentpath.characterPath.IndexOf(charToMove.movementProfile.currentSegment); int numberOfSegmentsInPath = charToMove.movementProfile.currentpath.characterPath.Count(); if (indexOfCurrentSegment == numberOfSegmentsInPath - 1) { //we're done, stop movement charToMove.state = charState.still; charToMove.subtractCurrentActionPoints(charToMove.movementProfile.currentPathActionPointCost); charToMove.position.X = charToMove.movementProfile.finalDestination.xPos; charToMove.position.Y = charToMove.movementProfile.finalDestination.yPos; originalTile.isOccupied = false; Tile destinationTile = map.tiles[(int)charToMove.position.X, (int)charToMove.position.Y]; Vector2 destTilePosVector = new Vector2(destinationTile.xPos,destinationTile.yPos); charToMove.pixelPosition = charToMove.getPixelPositionByTilePosition(destTilePosVector); destinationTile.isOccupied = true; } else { //We're not done - there are more segments in this character's current path. Move to the next, then call the movement function again. charToMove.pixelPosition = new Vector2(currentDestinationX,currentDestinationY); charToMove.movementProfile.currentSegment = charToMove.movementProfile.currentpath.characterPath[indexOfCurrentSegment + 1]; charToMove.movementProfile.currentDestination = charToMove.movementProfile.currentSegment.segmentTiles.Last(); Tile newDestinationTile = charToMove.movementProfile.currentDestination; Vector2 newDestinationVector = new Vector2(newDestinationTile.xPos, newDestinationTile.yPos); charToMove.movementProfile.currentDestinationPixels = charToMove.getPixelPositionByTilePosition(newDestinationVector); PerformCharacterMovement(charToMove, map); } } if (currentDestinationX > currentLocationX) { currentLocationX += Character.movementSpeedX; } else if (currentDestinationX < currentLocationX) { currentLocationX -= Character.movementSpeedX; } else { //currentLocation == currentDestination } if (currentDestinationY > currentLocationY) { currentLocationY += Character.movementSpeedY; } else if (currentDestinationY < currentLocationX) { currentLocationY -= Character.movementSpeedY; } else { //currentLocation == currentDestination } Vector2 newCharLocation = new Vector2(currentLocationX, currentLocationY); charToMove.pixelPosition = newCharLocation; }
public static Tile getCursorCurrentTile(Tile tile, Map map, Point cursorPoint, Rectangle tileRect) { //when the cursor is over a tile's rectangle, We need to find the space we're actually selecting. The rectangular sprite just containst the diamond //So the tile you pass in, is not necessarily the tile youre hovering over - it may be the edge, and therefore, in another tile. //We want to keep this general in case we chnge tile/asset sizes later. We can use the symmetry in iso art to our advantage. //Whatever the tile size, the angles will be the same, so the math will scale. //We have to go through each of the 5 possible areas designated by the given area. The center diamond, and the four sorrounding triangles. We'll do the center diamond first //if the point isnt in the center diamond, we can use a quick+dirty method of figuring out which triangle its in, and therefore which tile to return. //first get an array of points that make up the inner diamond Point[] polygon = new Point[4]; polygon[0] = new Point(tileRect.X + Tile.width / 2, tileRect.Y); polygon[1] = new Point(tileRect.X, tileRect.Y + Tile.height / 2); polygon[2] = new Point(tileRect.X + Tile.width / 2, tileRect.Y + Tile.height); polygon[3] = new Point(tileRect.X + Tile.width, tileRect.Y + Tile.height / 2); bool insideDiamond = false; for (int i = 0, j = polygon.Length - 1; i < polygon.Length; j = i++) { if ((polygon[i].Y > cursorPoint.Y) != (polygon[j].Y > cursorPoint.Y) && cursorPoint.X < (polygon[j].X - polygon[i].X) * (cursorPoint.Y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) + polygon[i].X) { insideDiamond = !insideDiamond; } } if (insideDiamond == true) { return tile; } else { //Ok, point is not in the diamond, so let's see which triangle it's in. Keep in mind that a tile adjacent to the given tile may be off the map. //Lets create bounding rectangles that contain the triangles in the corner, Then test if the point is in those rectangles. Since its not in the center diamond, //a hit here means the point is int the correponding triangle. Rectangle upperLeft = new Rectangle(tileRect.X, tileRect.Y, Tile.width/2, Tile.height/2); Rectangle upperRight = new Rectangle(tileRect.X + Tile.width / 2, tileRect.Y, Tile.width / 2, Tile.height / 2); Rectangle lowerLeft = new Rectangle(tileRect.X, tileRect.Y + Tile.height / 2, Tile.width / 2, Tile.height / 2); Rectangle lowerRight = new Rectangle(tileRect.X + Tile.width / 2, tileRect.Y + Tile.height / 2, Tile.width / 2, Tile.height / 2); if (upperLeft.Contains(cursorPoint)) { if (map.coordinatesOnMap(tile.xPos, tile.yPos - 1)) return map.tiles[tile.xPos, tile.yPos - 1]; } else if (upperRight.Contains(cursorPoint)) { if (map.coordinatesOnMap(tile.xPos + 1, tile.yPos)) return map.tiles[tile.xPos + 1, tile.yPos]; } else if (lowerLeft.Contains(cursorPoint)) { if (map.coordinatesOnMap(tile.xPos - 1, tile.yPos)) return map.tiles[tile.xPos - 1, tile.yPos]; } else { //only one left is bottom right: if (map.coordinatesOnMap(tile.xPos, tile.yPos + 1)) return map.tiles[tile.xPos, tile.yPos + 1]; } } return null; }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); battleMap = Map.buildDefaultMap(20, 20); //build map allCover = Cover.createTestCover(battleMap); allies = Character.createTestAllies(5, battleMap); enemies = Character.createTestEnemies(5, battleMap); //create teams of characters allCharacters.AddRange(allies); allCharacters.AddRange(enemies); playerTurn = true; gameCamera = new Camera(); //create camera mapWidth = battleMap.mapWidthInTiles(); mapHeight = battleMap.mapHeightInTiles(); }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); battleMap = Map.buildDefaultMap(20, 20); //build map playState = new PlayState(battleMap); playState.viewportWidth = graphics.GraphicsDevice.Viewport.Width; playState.viewportHeight = graphics.GraphicsDevice.Viewport.Height; /*allCover = Cover.createTestCover(battleMap); allies = Character.createTestAllies(5, battleMap); enemies = Character.createTestEnemies(5, battleMap); //create teams of characters allCharacters.AddRange(allies); allCharacters.AddRange(enemies); playerTurn = true;*/ gameCamera = new Camera(); //create camera mapWidth = battleMap.mapWidthInTiles(); mapHeight = battleMap.mapHeightInTiles(); }