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 InitializeTargeting(Character originatingChar, Ability castedAbility, PlayState playState) { //change playState mode to targeting playState.playMode = PlayState.Mode.targeting; playState.abilityBeingTargeted = castedAbility; if(castedAbility is CharAbility) { InitializeTargetingCharAbility(originatingChar, (CharAbility)castedAbility, playState); } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { currentControlState.keyState = Keyboard.GetState(); MouseState mouseState = Mouse.GetState(); mousePosition = new Point(mouseState.X, mouseState.Y); currentControlState.mouseState = mouseState; for (int x = 1; x < mapWidth; x++) { for (int y = 1; y < mapHeight; y++) { Tile currentTile = battleMap.tiles[x, y]; Rectangle currentSourceRect = Tile.getSourceRect(); int xOrigin = ((x * (Tile.width / 2)) + ((y - 1) * (Tile.width / 2)) + (int)gameCamera.cameraLocation.X); int yOrigin = ((y * (Tile.height / 2)) - ((x - 1) * Tile.height / 2) + (int)gameCamera.cameraLocation.Y); int drawWidth = Tile.width; int drawHeight = Tile.height; Rectangle thisTileRect = new Rectangle(xOrigin, yOrigin, drawWidth, drawHeight); if (thisTileRect.Contains(mousePosition) && moveableSpaces.containsTile(currentTile)) { Tile potentialHoveredTile = Controls.getCursorCurrentTile(currentTile, battleMap, mousePosition, thisTileRect); if (potentialHoveredTile != null && moveableSpaces.containsTile(potentialHoveredTile)) { currentControlState.hoveredTile = Controls.getCursorCurrentTile(currentTile, battleMap, mousePosition, thisTileRect); } } } } //if an ally is moving, move them! foreach (Character character in allCharacters) { if (character.state == charState.moveing) { CharacterMovement.PerformCharacterMovement(character); } } if ((oldControlState.hoveredTile != currentControlState.hoveredTile) && (currentControlState.hoveredTile != null)) { currentPath = Pathfinding.shortestPath(battleMap, battleMap.tiles[(int)currentlySelectedChar.position.X, (int)currentlySelectedChar.position.Y], battleMap.tiles[currentControlState.hoveredTile.xPos, currentControlState.hoveredTile.yPos]); } else if(currentControlState.hoveredTile == null) { currentPath = null; } if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); if (currentControlState.keyState.IsKeyDown(Keys.Left)) { //increment x gameCamera.cameraLocation.X = MathHelper.Clamp(gameCamera.cameraLocation.X + 4, 0 - Map.mapBuffer - battleMap.mapWidthInPixels(), 0 + Map.mapBuffer); } if (currentControlState.keyState.IsKeyDown(Keys.Right)) { //decrement x gameCamera.cameraLocation.X = MathHelper.Clamp(gameCamera.cameraLocation.X - 4, 0 - Map.mapBuffer - battleMap.mapWidthInPixels(), 0 + Map.mapBuffer); } if (currentControlState.keyState.IsKeyDown(Keys.Up)) { //increment y gameCamera.cameraLocation.Y = MathHelper.Clamp(gameCamera.cameraLocation.Y + 4, 0 - Map.mapBuffer, 0 + Map.mapBuffer); } if (currentControlState.keyState.IsKeyDown(Keys.Down)) { //decrement y gameCamera.cameraLocation.Y = MathHelper.Clamp(gameCamera.cameraLocation.Y - 4, 0 - Map.mapBuffer, 0 + Map.mapBuffer); } if (currentControlState.keyState.IsKeyDown(Keys.Tab) && oldControlState.keyState.IsKeyUp(Keys.Tab)) { //determine if any characters are currently selected. If they are, select the one after them in [allies], and de-select the current one. //if none are selected, select allies[0] currentlySelectedChar = Character.selectNextCharacter(allies); Camera.panToCharacter(currentlySelectedChar, gameCamera, battleMap, graphics); moveableSpaces = Pathfinding.moveableSpaces(battleMap, currentlySelectedChar); //List<Tile> path = Pathfinding.shortestPath(battleMap, battleMap.tiles[(int)nextCharacter.position.X, (int)nextCharacter.position.Y], battleMap.tiles[8, 9]); } if (currentPath != null) { if (currentControlState.mouseState.LeftButton == ButtonState.Pressed && oldControlState.mouseState.LeftButton == ButtonState.Released) { CharacterMovement.setCharMovement(currentlySelectedChar, currentPath); //calculate current character movement path and execute movement, if the current character doesnt have one. } } if (currentControlState.keyState.IsKeyDown(Keys.X)) gameCamera.cameraLocation = Vector2.Zero; // Check the state and location of the mouse - act accordingly oldControlState.keyState = currentControlState.keyState; oldControlState.hoveredTile = currentControlState.hoveredTile; oldControlState.mouseState = currentControlState.mouseState; //oldControlState = currentControlState; base.Update(gameTime); }
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 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 MovementProfile(MovementPath moveProfile, PathSegment pathSegment, Character charToMove) { currentpath = moveProfile; currentSegment = pathSegment; currentDestination = pathSegment.segmentTiles.Last(); Vector2 currentDestinationVector = new Vector2(currentDestination.xPos, currentDestination.yPos); finalDestination = currentpath.characterPath.Last().segmentTiles.Last(); Vector2 finalDestinationVector = new Vector2(finalDestination.xPos,finalDestination.yPos); currentDestinationPixels = charToMove.getPixelPositionByTilePosition(currentDestinationVector); finalDestinationPixels = charToMove.getPixelPositionByTilePosition(finalDestinationVector); }
public static void selectCharacter(Character character, Camera camera, Map map, GraphicsDeviceManager graphics) { character.selected = true; Camera.panToCharacter(character, camera, map, graphics); }
public static void InitializeTargetSelection(Character targetingChar, Ability abilityBeingTargeted) { }
//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 InitializeTargetingCharAbility(Character originatingChar, CharAbility castedAbility, PlayState playstate) { List<Character> potentialTargets = new List<Character>(); switch (castedAbility.abilityPossibleTargets) { case (AbilityPosibleTargets.singleAlly): if (castedAbility.limitedByRange) { potentialTargets = GetCharatersInAbilityRange(originatingChar, castedAbility, playstate); if (potentialTargets.Count > 0) { playstate.charactersTargeted = new List<Character> { potentialTargets[0] }; playstate.potentialTargets = potentialTargets; } }else { playstate.charactersTargeted = new List<Character> { playstate.allies[0] }; playstate.potentialTargets = playstate.allies; } break; case (AbilityPosibleTargets.singleEnemy): if (castedAbility.limitedByRange) { potentialTargets = GetCharatersInAbilityRange(originatingChar, castedAbility, playstate); if (potentialTargets.Count > 0) { playstate.charactersTargeted = new List<Character> { potentialTargets[0] }; playstate.potentialTargets = potentialTargets; } } else { playstate.charactersTargeted = new List<Character> { playstate.enemies[0] }; playstate.potentialTargets = playstate.enemies; } break; case (AbilityPosibleTargets.allAllies): playstate.charactersTargeted = playstate.allies; playstate.potentialTargets = playstate.allies; break; case (AbilityPosibleTargets.allEnemies): playstate.charactersTargeted = playstate.enemies; playstate.potentialTargets = playstate.enemies; break; case (AbilityPosibleTargets.allInRange): potentialTargets = GetCharatersInAbilityRange(originatingChar, castedAbility, playstate); if (potentialTargets.Count > 0) { playstate.charactersTargeted = new List<Character> { potentialTargets[0] }; playstate.potentialTargets = potentialTargets; } break; case (AbilityPosibleTargets.global): playstate.charactersTargeted = playstate.allCharacters; playstate.potentialTargets = playstate.allCharacters; break; case (AbilityPosibleTargets.singleChar): if (castedAbility.limitedByRange) { potentialTargets = GetCharatersInAbilityRange(originatingChar, castedAbility, playstate); if (potentialTargets.Count > 0) { playstate.charactersTargeted = new List<Character> { potentialTargets[0] }; playstate.potentialTargets = potentialTargets; } } else { playstate.charactersTargeted = new List<Character> { playstate.allCharacters[0] }; playstate.potentialTargets = playstate.allCharacters; } break; } }
public static void TargetGroup(Character originatingChar, CharAbility castedAbility) { //this ability needs to automatically target a group of characters, like allies, enemies, or all characters }
public static void TargetAllInRange(Character originatingChar, CharAbility castedAbility) { //this ability needs to automatically target all characters in range }
public static void SelectTargetSingleChar(Character originatingChar, CharAbility castedAbility) { //this ability needs to target a single character /* * 0. Set casting character to targeting state * 0. When targeting, Esc cancels targeting and resets char/playstate * 1. Isolate all potential targets in range * 2. Automatically place selection indicator over nearest target * 3. tab now switches between potential targets rather than chars to move */ originatingChar.state = charState.selectingTargets; }
/*Character movement path is a set of tiles broken into linear segments * One path is made of 1 to N linear segments. * Path object is a List of Tile Lists * Game loops through Tile Lists and moves the character until there are no more * Then we change the char's position to it's destination, change its state, and set the profile to null */ public static void setCharMovement(Character charToMove, List<Tile> optimalPath) { //using the char and the calcuated path, create a movementPath object. //cycle through the tiles on the optimal path. bool pathComplete = false; //if yes, we're done List<PathSegment> movementPathSegments = new List<PathSegment>(); List<Tile> closedList = new List<Tile>(); //prepare the given path for this process - reverse the list! optimalPath.Reverse(); List<Tile> openList = optimalPath; while (!pathComplete) { //pass the openlist into createSegmentFromPath. Add the tiles from the returned segment to the closed list, and remove them from the open list. if (openList.Count > 1) { PathSegment currentSegment = createSegmentFromPath(openList); for (int i = 0; i < currentSegment.segmentTiles.Count - 1; i++) { Tile tile = currentSegment.segmentTiles[i]; closedList.Add(tile); openList.Remove(tile); } movementPathSegments.Add(currentSegment); } else { pathComplete = true; } } MovementPath movementPath = new MovementPath(movementPathSegments); MovementProfile charMoveProfile = new MovementProfile(movementPath, movementPath.characterPath[0], charToMove); charToMove.movementProfile = charMoveProfile; charToMove.state = charState.moveing; }
public static Rectangle getSourceRect(Character character) { int offsetX = 0; int offsetY = 0; //offsets which describe where to look for the sprite based on the specific character in question. if (character.ally == false) { offsetX += (Character.width + Character.spriteSheetBuffer*2); } Rectangle sourceRect = new Rectangle(Character.spriteSheetPosX + offsetX, Character.spriteSheetPosY + offsetY, Character.width , Character.height); return sourceRect; }
public static void PerformCharacterMovement(Character charToMove) { float currentDestinationX = charToMove.movementProfile.currentDestinationPixels.X; float currentDestinationY = charToMove.movementProfile.currentDestinationPixels.Y; float currentLocationX = charToMove.pixelPosition.X; float currentLocationY = charToMove.pixelPosition.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.position.X = charToMove.movementProfile.finalDestination.xPos; charToMove.position.Y = charToMove.movementProfile.finalDestination.yPos; } 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); } } 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 List<Character> GetCharatersInAbilityRange(Character originatingChar, CharAbility castedAbility, PlayState playstate) { //get subset of tiles in range of ability via the distance formula //boundaries of square to search defined by ability range int rangeToSearch = castedAbility.range; List<Tile> tilesInAbilityRange = new List<Tile>(); List<Character> charactersInAbilityRange = new List<Character>(); int castingCharacterPosX = (int)originatingChar.position.X; int castingCharacterPosY = (int)originatingChar.position.Y; int minimumXtoSearch = (int)originatingChar.position.X - rangeToSearch; int maximumXtoSearch = (int)originatingChar.position.X + rangeToSearch; int minimumYtoSearch = (int)originatingChar.position.Y - rangeToSearch; int maximumYtoSearch = (int)originatingChar.position.Y + rangeToSearch; if (minimumXtoSearch < 1) minimumXtoSearch = 1; if (minimumYtoSearch < 0) minimumYtoSearch = 1; if (maximumXtoSearch > playstate.currentMap.mapWidthInTiles()-1) maximumXtoSearch = playstate.currentMap.mapWidthInTiles()-1; if (maximumYtoSearch > playstate.currentMap.mapHeightInTiles()-1) maximumYtoSearch = playstate.currentMap.mapHeightInTiles()-1; for (int x = 0; x <= rangeToSearch; x++) { for (int y = 0; y <= rangeToSearch; y++) { if (x >= minimumXtoSearch && x <= maximumXtoSearch && y >= minimumYtoSearch && y <= maximumYtoSearch) { int distanceFromSource = Math.Abs(castingCharacterPosX - x) + Math.Abs(castingCharacterPosY - y); if (distanceFromSource <= rangeToSearch) { //this tile is in range - add it to the list. Also check to see if it has a character, and if so, add it as a viable target Tile currentTile = playstate.currentMap.tiles[x, y]; tilesInAbilityRange.Add(currentTile); Character currentChar = null; if (castedAbility.abilityPossibleTargets == AbilityPosibleTargets.singleChar || castedAbility.abilityPossibleTargets == AbilityPosibleTargets.allInRange) { currentChar = playstate.allCharacters.Find(character => (int)character.position.X == x && (int)character.position.Y == y); } else if (castedAbility.abilityPossibleTargets == AbilityPosibleTargets.singleAlly) { currentChar = playstate.allies.Find(character => (int)character.position.X == x && (int)character.position.Y == y); } else if (castedAbility.abilityPossibleTargets == AbilityPosibleTargets.singleEnemy) { currentChar = playstate.enemies.Find(character => (int)character.position.X == x && (int)character.position.Y == y); } if (currentChar != null) { charactersInAbilityRange.Add(currentChar); } } } } } if (charactersInAbilityRange.Count > 0) { //if characters can be targeted, we wil want to draw the targeting range playstate.tilesInAbilityRange = tilesInAbilityRange; } return charactersInAbilityRange; }