//Returns a list of tiles containing a valid target in range of the given ability //That list is stored on the ability object and is cleared with each new (non-recursive) call to this method public List<Tile> checkRange(Tile origin, Ability ability, int range, Piece user) { //Clears the list if this is the initial call because the parameter "range" will only equal ability.range if this is the first call if (ability.getRange() == range) { validTargets = new List<Tile>(); } List<Tile> frontier = getNeighbors(origin, new List<Tile>()); if (!origin.isEmpty()) { //If ability targets enemies & the tile contains a unit from the other faction & if the tile is not already in the list THEN the tile is added if (ability.getTargetType().Equals("Enemy") && !(origin.getResident().getFaction().Equals(user.getFaction())) && !validTargets.Contains(origin)) { validTargets.Add(origin); } //If ability targets friendlies & the tile contains a unit from the same faction & if the tile is not already in the list THEN the tile is added else if (ability.getTargetType().Equals("Friendly") && (origin.getResident().getFaction().Equals(user.getFaction())) && !validTargets.Contains(origin)) { validTargets.Add(origin); } } //decrement range for the next round of checks int nRange = range - 1; if (nRange >= 0) { for (int i = 0; i < frontier.Count(); i++) { checkRange(frontier[i], ability, nRange, user); } } return validTargets; }
public List<Tile> getNeighbors(Tile tile, List<Tile> neighbors) { //returns the neighbors of the given tile and adds them to existing list //at most, will return 4 tiles int xCoord = tile.getXCoord(); int yCoord = tile.getYCoord(); //MAYBE TODO, getNeighbors and find moves back to working order //prevent array index out of bounds and check for existence of tile in list if (xCoord > 0 && !neighbors.Contains(map[xCoord - 1][yCoord])) { neighbors.Add(map[xCoord - 1][yCoord]); } if (xCoord < width && !neighbors.Contains(map[xCoord + 1][yCoord])) { neighbors.Add(map[xCoord + 1][yCoord]); } if (yCoord > 0 && !neighbors.Contains(map[xCoord][yCoord - 1])) { neighbors.Add(map[xCoord][yCoord - 1]); } if (yCoord < width && !neighbors.Contains(map[xCoord][yCoord + 1])) { neighbors.Add(map[xCoord][yCoord + 1]); } return neighbors; }
public TacMap(Tile[,] map, ContentManager content) { this.map = map; validMoves = new List<Tile>(); woods = content.Load<Texture2D>("TerrainSprites/tree 2"); woods2 = content.Load<Texture2D>("TerrainSprites/tree 1"); mountains = content.Load<Texture2D>("TerrainSprites/terrain_mountains"); river = content.Load<Texture2D>("TerrainSprites/river"); //TODO load all unit sprites and terrain sprites and effects sprites for drawing }
//checks neighbors of tiles for targets public List<Tile> checkMeleeRange(Tile origin) { List<Tile> targets = new List<Tile>(); targets = getNeighbors(origin, targets); foreach(Tile t in targets) if(t.isEmpty()) targets.Remove(t); if(targets.Count == 0) return null; else return targets; }
public void updateInfo(Tile t) { if (t.getResident() != null) { Piece display = t.getResident(); unitInfo = " UNIT \n Name : " + display.getName(); unitInfo += "\nLevel: " + display.getLevel(); unitInfo += "\nAttack: " + display.getAttack(); unitInfo += "\nDefense: " + display.getDefense(); unitInfo += "\nRange: " + display.getRange(); unitInfo += "\nHealth: " + display.getHealth() + "/" + (5 * display.getStamina()); unitInfo += "\nAction points: " + display.getAP(); unitInfo += "\nExp: " + display.getXP() + "/" + display.maxXP(); unitInfo += "\n"; unitInfo += "\n"; if (display.hasPieceAttacked()) unitInfo += "\nUnit is spent for \nthis turn"; else if (display.hasPieceMoved()) unitInfo += "\nUnit has moved \nbut can still attack"; else unitInfo += "\nUnit can still move \nthis turn"; } }
public void update() //gathers input, updates positions, and handles combat { //update inputs oldMouse = mouseState; mouseState = Mouse.GetState(); oldKeyboardState = keyboardState; keyboardState = Keyboard.GetState(); Rectangle endTurn = new Rectangle(918, 818, 268, 69); Rectangle toggleGrid = new Rectangle(1076, 70, 115, 20); Rectangle mouse = new Rectangle(mouseState.X, mouseState.Y, 1, 1); //TODO find unspent unit //click toggle grid button if (mouse.Intersects(toggleGrid) && mouseState.LeftButton == ButtonState.Pressed && oldMouse.LeftButton != ButtonState.Pressed) gridOn = !gridOn; if (controlState == ControlState.selectUnit) { //change scroll-over display based on mouse coordinates scrolledOver = mouseOverTile(); //if click and scrolled over friendly unit set unit to selected and change state to choose option if (mouseState.LeftButton == ButtonState.Pressed) { if (mouse.Intersects(endTurn) && oldMouse.LeftButton != ButtonState.Pressed) { //if end turn is clicked then refresh armies and switch players controlState = ControlState.endTurn; } else { if (mouseState.X < 900 && mouseState.Y < 900 && scrolledOver != null && !scrolledOver.isEmpty()) { if((scrolledOver.getResident().getFaction().Equals("RED") && isPlayer1Turn) || (scrolledOver.getResident().getFaction().Equals("BLUE") && !isPlayer1Turn)) { if (!scrolledOver.getResident().hasPieceAttacked()) { selectedTile = scrolledOver; selectedUnit = scrolledOver.getResident(); selectionTiles = map.getValidMoves(); controlState = ControlState.chooseOption; //hide mouse mouseVisible = false; } else status = "Unit is spent for this turn"; } } } } if (keyboardState.IsKeyDown(Keys.K)) //test win screen { status = "Nobody wins! YAY!"; controlState = ControlState.endGame; } } else if (controlState == ControlState.chooseOption) { //if keyboardState has a button pressed coressponding to the options then change state and show mouse TODO if (keyboardState.IsKeyDown(Keys.W) && !selectedUnit.hasPieceMoved()) //move { mouseVisible = true; selectionTiles = map.findValidMoves(selectedUnit); controlState = ControlState.move; } else if (keyboardState.IsKeyDown(Keys.A) && !selectedUnit.hasPieceAttacked()) //attack { mouseVisible = true; currentAbility = new Attack(selectedUnit); selectionTiles = map.checkRange(selectedTile, currentAbility, currentAbility.getRange(), selectedUnit); //if no targets in range status "says so" and don't change state controlState = ControlState.selectTarget; } else if (keyboardState.IsKeyDown(Keys.T)) //end turn { //selectedUnit.move(); selectedUnit.attack(); //TODO mouseVisible = true; controlState = ControlState.selectUnit; } else if (keyboardState.IsKeyDown(Keys.Space) && !oldKeyboardState.IsKeyDown(Keys.Space)) { mouseVisible = true; controlState = ControlState.selectUnit; } //space = cancel, go back to selectUnit } else if (controlState == ControlState.move) { //change scroll-over display based on mouse coordinates scrolledOver = mouseOverTile(); //if click and mouse XY corresponds to valid tile then move unit and return to chooseoption TODO if (selectionTiles.Contains(mouseOverTile()) && mouseState.LeftButton == ButtonState.Pressed) { map.movePiece(selectedTile, scrolledOver, selectedUnit); selectedTile = scrolledOver; selectedUnit.move(); status = selectedUnit.getName() + " has moved."; mouseVisible = false; controlState = ControlState.chooseOption; } else if (keyboardState.IsKeyDown(Keys.Space) && !oldKeyboardState.IsKeyDown(Keys.Space)) { mouseVisible = false; controlState = ControlState.chooseOption; } //space = cancel, go back to chooseOption } else if (controlState == ControlState.selectTarget) { //change scroll-over display based on mouse coordinates scrolledOver = mouseOverTile(); //if click and tile is in target list than initiate combat between selected unit and target, show mouse, return to select unit TODO if (mouseState.LeftButton == ButtonState.Pressed) { //if scrolled over tile is within targetTiles then initiate combat if(selectionTiles.Contains(scrolledOver)) { //change status to combat result string status = currentAbility.execute(selectedUnit, scrolledOver.getResident()); selectedUnit.attack(); //remove dead units if (selectedUnit.getHealth() < 1) selectedTile.removePiece(); if (scrolledOver.getResident().getHealth() < 1) scrolledOver.removePiece(); controlState = ControlState.selectUnit; //status = "attack"; } } else if (keyboardState.IsKeyDown(Keys.Space) && !oldKeyboardState.IsKeyDown(Keys.Space)) { currentAbility = null; mouseVisible = false; controlState = ControlState.chooseOption; } //space = cancel, go back to chooseOption } else if (controlState == ControlState.endTurn) { if (keyboardState.IsKeyDown(Keys.Y)) { refreshArmy(); isPlayer1Turn = !isPlayer1Turn; //refreshArmy(); status = "Turn ended, next player's turn begins"; controlState = ControlState.selectUnit; } else if (keyboardState.IsKeyDown(Keys.Space)) { controlState = ControlState.selectUnit; } } else if(controlState == ControlState.endGame) { //continue if (keyboardState.IsKeyDown(Keys.Space)) { endBattle(); } } if (isArmyDead(player1Army)) { status = "Blue Player 2 Wins!"; } else if (isArmyDead(player2Army)) { status = "Red Player 1 Wins!"; } }
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); army1 = new List<Piece>(); army2 = new List<Piece>(); //Load the screen backgrounds mTitleScreenBackground = Content.Load<Texture2D>("Menu/TitleScreen"); //Music musicTitle = Content.Load<Song>("Music/Title"); //Play the Intro Song MediaPlayer.Play(musicTitle); /* army1.Add( new Pikeman("RED", Content)); army2.Add(new Pikeman("BLUE", Content)); army1.Add(new Knight("RED", Content)); army2.Add( new Knight("BLUE", Content)); army1.Add(new Swordsman("RED", Content)); army2.Add(new Swordsman("BLUE", Content)); army1.Add(new Archer("RED", Content)); army2.Add(new Archer("BLUE", Content)); army1.Add(new Nomad("RED", Content)); army2.Add(new Nomad("BLUE", Content)); army1.Add(new Mage("RED", Content)); army2.Add(new Mage("BLUE", Content)); army1.Add(new Zealot("RED", Content)); army2.Add(new Zealot("BLUE", Content)); */ Tile[,] mm = new Tile[30,30]; for (int i = 0; i < 30; i++) for (int j = 0; j < 30; j++) mm[i,j] = new Tile("Plain", i, j); map = new TacMap(mm, Content); map.randomMap(); battle = new TacticalBattle(army1, army2, map, Content); manager = new ArmyManagment(Content, army1, army2); // TODO: use this.Content to load your game content here }
public void addTile(Tile tile, int xCoor, int yCoor) { // places tile in the given coordinates map[xCoor][yCoor] = tile; }
public TacMap(Tile[][] map, ContentManager content) { this.map = map; //validMoves = new List<Tile>(); //TODO load all unit sprites and terrain sprites and effects sprites for drawing }
private void findMoves(Tile location, int ap, Piece piece) { int remainingPoints = ap; List<Tile> neighbors = getNeighbors(location, new List<Tile>()); for (int i = 0; i < neighbors.Count; i++) { Tile tile = neighbors[i]; int cost; if (tile.getTerrain().Equals("Plain")) { cost = 1; } else if (tile.getTerrain().Equals("Woods")) { cost = 2; } else if (tile.getTerrain().Equals("Mountain")) { cost = 4; } else { cost = 999; } if (remainingPoints >= cost && !piece.validMoves.Contains(neighbors[i])) { if (neighbors[i].isEmpty()) { piece.validMoves.Add(neighbors[i]); findMoves(neighbors[i], remainingPoints - cost, piece); return; } else { if (neighbors[i].getResident().getFaction().Equals(piece.getFaction())) { findMoves(neighbors[i], remainingPoints - cost, piece); return; } else { return; } } } else { return; } } }
public void randomMap() { //constructs a randomly generated map //start by setting every tile to be plains for (int i = 0; i < width; i++) { for (int j = 0; j < width; j++) { map[i][j] = new Tile("Plain", i, j); } } //determine how many types of terrain will be on the map Random r = new Random(); int typesOfTerrain = r.Next(2) + 1; bool water = false; bool mountain = false; bool woods = false; //now figure out which of these should be true if (typesOfTerrain == 1 || typesOfTerrain == 2) { int n = r.Next(2); //0 = water //1 = mountain //2 = woods if (typesOfTerrain == 1) { if (n == 0) water = true; else if (n == 1) mountain = true; else if (n == 2) woods = true; } if (typesOfTerrain == 2) { if (n == 0) { mountain = true; woods = true; } else if (n == 1) { water = true; woods = true; } else if (n == 2) { water = true; mountain = true; } } } if (water) { //up to 25 tiles can be water int numberOfWater = r.Next(25) + 1; int n = 0; while (n < numberOfWater) { //pick a random tile, and if the tile is plains, change into water int x = r.Next(width); int y = r.Next(width); if (map[x][y].getTerrain().Equals("Plain")) { map[x][y] = new Tile("Water", x, y); n++; } } } if (mountain) { //up to 20 tiles can be mountains //mountains shouldn't block off an entire section of the map int numberOfMountains = _r.Next(25) + 1; int n = 0; while (n < numberOfMountains) { //pick a random tile, and if the tile is plains, change into mountains int x = r.Next(width); int y = r.Next(width); if (map[x][y].getTerrain().Equals("Plain")) { map[x][y] = new Tile("Mountain", x, y); n++; } } } if (woods) { //up to 40 tiles can be woods //woods can go anywhere int numberOfWoods = r.Next(40) + 1; int n = 0; while (n < numberOfWoods) { //pick a random tile, and if the tile is plains, change into woods int x = r.Next(width); int y = r.Next(width); if (map[x][y].getTerrain().Equals("Plain")) { map[x][y] = new Tile("Woods", x, y); n++; } } } }
public String movePiece(Tile origin, Tile destination, Piece piece) { if (piece.validMoves.Contains(destination)) { origin.removePiece(); origin.enterPiece(piece); // promptAbility(); piece.move(); piece.validMoves = null; return piece.getName() + " has moved"; } else return "invalid location"; }
public bool isNeighbor(Tile tile1, Tile tile2) { //returns true if the given tiles are neighbors //two tiles are neighbors if either their xCoords or yCoords are one apart (but not both) int xCoord1 = tile1.getXCoord(); int yCoord1 = tile1.getYCoord(); int xCoord2 = tile2.getXCoord(); int yCoord2 = tile2.getYCoord(); if (Math.Abs(xCoord1 - xCoord2) == 1 && (yCoord1 - yCoord2 == 0)) { return true; } else if (Math.Abs(yCoord1 - yCoord2) == 1 && (xCoord1 - xCoord2 == 0)) { return true; } else { return false; } }
private void findMoves(Tile location, int ap, Piece piece) { int remainingPoints = ap; List<Tile> neighbors = getNeighbors(location, new List<Tile>()); for (int i = 0; i < neighbors.Count; i++) { Tile tile = neighbors[i]; int cost; if (tile.getTerrain().Equals("Plain")) { cost = 1; } else if (tile.getTerrain().Equals("Woods")) { cost = 2; } else if (tile.getTerrain().Equals("Mountain")) { cost = 4; } else { cost = 999; } //If there is sufficient ap if (remainingPoints >= cost) { //If the tile is empty it is added to the list and another call made if (neighbors[i].isEmpty()) { //if validMoves does not already hold the tile if (!validMoves.Contains(neighbors[i])) { validMoves.Add(neighbors[i]); } findMoves(neighbors[i], remainingPoints - cost, piece); } else { //if the tile is occupied BUT is occupied by a friendly another call is made but the tile is not added, the tile is not a valid move //but the search still "paths" through it if (neighbors[i].getResident().getFaction().Equals(piece.getFaction())) { findMoves(neighbors[i], remainingPoints - cost, piece); } } } } }
public void randomMap() { //constructs a randomly generated map //start by setting every tile to be plains for (int i = 0; i < width; i++) { for (int j = 0; j < width; j++) { map[i, j] = new Tile("Plain", i, j); } } //determine how many types of terrain will be on the map Random _r = new Random(); //woods int ir = 5 + _r.Next(16); for (int i = 0; i < ir; i++) { int x = _r.Next(30); int y = _r.Next(30); int jr = _r.Next(12); int kr = _r.Next(12); for (int j = 0; j < jr; j++) { //int kr = _r.Next(12); for (int k = 0; k < kr; k++) { if (_r.Next(8) != 0 && x+j < 30 && y+k <30) { map[x + j, y + k] = new Tile("Woods", x + j, y + k); } } } } //Mountains ir = 3 + _r.Next(5); for (int i = 0; i < ir; i++) { int x = _r.Next(30); int y = _r.Next(30); int jr = _r.Next(7); int kr = _r.Next(7); for (int j = 0; j < jr; j++) { //int kr = _r.Next(7); for (int k = 0; k < kr; k++) { if (_r.Next(10) != 0 && x + j < 30 && y + k < 30) { map[x + j, y + k] = new Tile("Mountain", x + j, y + k); } } } } //water ir = 1 + _r.Next(2); for (int i = 0; i < ir; i++) { int x = _r.Next(11) + 7; int y = _r.Next(11) + 7; int jr = _r.Next(9); int kr = _r.Next(9); for (int j = 0; j < jr; j++) { //int kr = _r.Next(9); for (int k = 0; k < kr; k++) { if (_r.Next(20) != 0 && x + j < 30 && y + k < 30) { map[x + j, y + k] = new Tile("Water", x + j, y + k); } } } } for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { map[i, j] = new Tile("Plain", i, j); } } for (int i = 24; i < 30; i++) { for (int j = 24; j < 30; j++) { map[i, j] = new Tile("Plain", i, j); } } }
public void findTargets(Tile location, int range, Piece piece) { int remainingRange = range; List<Tile> neighbors = getNeighbors(location, new List<Tile>()); for (int i = 0; i < neighbors.Count; i++) { //If there is sufficient ap and validMoves does not already hold that tile if (remainingRange >= 1 && !validTargets.Contains(neighbors[i])) { //If the tile is empty it is not added to the list and another call made if (neighbors[i].isEmpty()) { //validTargets.Add(neighbors[i]); findTargets(neighbors[i], remainingRange - 1, piece); } else { //if the tile is occupied BUT is occupied by a friendly another call is made but the tile is not added, the tile is not a valid target //but the search still "paths" through it if (neighbors[i].getResident().getFaction().Equals(piece.getFaction())) { findTargets(neighbors[i], remainingRange - 1, piece); } //if the tile is occupied by an enemy faction, add it to validTargets else { validTargets.Add(neighbors[i]); findTargets(neighbors[i], remainingRange - 1, piece); } } } } }