/// <summary> /// Donne le coût en points de mouvements pour une cellule de terrain donnée. Les villes ne sont pas prises en compte. /// </summary> /// <param name="cell">cellule de terrain</param> /// <param param name="groupe">armée accompagnant cette créature pour les bonus de groupe</param> /// <returns>le coût en points de mouvements</returns> public int getMouvementCost(TerrainDescription.TerrainCell cell, Armee groupe) { // Les bateaux ne font QUE nager if ((cell.type != TerrainDescription.TypeTerrain.EAU) && nage && !description.heros) { return(MVTINFINI); } if (cell.route) { return(1); } switch (cell.type) { case TerrainDescription.TypeTerrain.COLLINE: return(description.bonusMouvement == CreatureDescription.BonusEnvironnement.COLLINES ? 3 : 5); case TerrainDescription.TypeTerrain.EAU: return(groupe.vol ? 3 : (groupe.nage ? ((description.bonusMouvement == CreatureDescription.BonusEnvironnement.EAU) ? 1 : 2) : MVTINFINI)); case TerrainDescription.TypeTerrain.FORET: return(description.bonusMouvement == CreatureDescription.BonusEnvironnement.FORÊT ? 3 : 5); case TerrainDescription.TypeTerrain.HERBE: return(description.bonusMouvement == CreatureDescription.BonusEnvironnement.HERBE ? 2 : 3); case TerrainDescription.TypeTerrain.MARECAGE: return(description.bonusMouvement == CreatureDescription.BonusEnvironnement.MARAIS ? 3 : 5); case TerrainDescription.TypeTerrain.MONTAGNE: return(groupe.vol ? 3 : MVTINFINI); } return(MVTINFINI); }
/// <summary> /// Focus sur carte sans cliquer. Change le curseur de souris /// </summary> /// <param name="newMouseX">x souris</param> /// <param name="newMouseY">y souris</param> public void focusCarte(int mouseX, int mouseY) { // Seulement si pas modal & si pas click droit en cours Armee focusA = null; VilleDescription focusV = null; TerrainDescription.TerrainCell focusC = _jeu.infoCarte.getClicked(mouseX, mouseY, ref focusA, ref focusV); // Si sélection : peut etre l'épée pour attaquer unité ou ville if (_jeu.selectedArmee != null) { if (((focusA != null) && (focusA.faction != _jeu.tourFaction)) || ((focusV != null) && (focusV.faction != _jeu.tourFaction))) { _jeu.curseur.forme = Cursor.FormeCurseur.EPEE; } else { _jeu.curseur.forme = Cursor.FormeCurseur.FLECHE; } } // Sinon : peut être info ville si ville alliée else { if ((focusV != null) && (focusV.faction == _jeu.tourFaction)) { _jeu.curseur.forme = Cursor.FormeCurseur.INTERROGATION; } else { _jeu.curseur.forme = Cursor.FormeCurseur.FLECHE; } } }
/// <summary> /// Click gauche - point d'entrée /// </summary> /// <param name="mouseX"></param> /// <param name="mouseY"></param> /// <param name="released">true si cle bouton est relaché avant d'être cliqué</param> public void leftClick(int mouseX, int mouseY, bool released) { // Si une armée bouge, cliquer = arrêter le mouvement if (_jeu.selectedArmeeGO) { _jeu.selectedArmee.stop(); return; } // L'armée ne bouge pas // Détermine sur quoi on clique Armee clickA = null; VilleDescription clickV = null; TerrainDescription.TerrainCell clickC = _jeu.infoCarte.getClicked(mouseX, mouseY, ref clickA, ref clickV); int carteX = (mouseX + _jeu.terrain.offsetCarte.X) / _jeu.blockSize; int carteY = (mouseY + _jeu.terrain.offsetCarte.Y) / _jeu.blockSize; // Déclencheur de mvt : 2nd click if (released && relacheApresChgtCible) { relacheApresChgtCible = false; Point?target = _jeu.selectedArmee == null ? null : _jeu.selectedArmee.moveTarget; if (targetSet == target) { _jeu.selectedArmeeGO = true; } } // Sélection, ville ou mouvement. if (clickA != null) { //Click sur armée leftClickOnArmee(clickA, released); } else if (clickV != null) { // Click sur ville leftClickOnVille(new Point(carteX, carteY), clickV, released); } else { // Click sur terrain leftClickOnCell(new Point(carteX, carteY), released); } // Déclencheur de mvt : 1er click if (released && !relacheApresChgtCible) { Point?target = _jeu.selectedArmee == null ? null : _jeu.selectedArmee.moveTarget; if (target != null && target != targetSet) { relacheApresChgtCible = true; } targetSet = target; } }
/// <summary> /// Le cout d'une armée est le coût maximal (sauf vol & nage de héros) /// </summary> /// <param name="target">point visé</param> /// <returns></returns> public int getMouvementCost(TerrainDescription.TerrainCell cell) { int maxCost = 0; foreach (Creature crea in _troupe) { int cost = crea.getMouvementCost(cell, this); if (cost > maxCost) { maxCost = cost; } } return(maxCost); }
/// <summary> /// Affiche le fond de carte (sans les villes, sans les unités, avec les routes & les ruines) /// Appelé au sein d'un spriteBatch begin/end /// </summary> /// <param name="spriteBatch">spriteBatch du jeu</param> /// <param name="GraphicsDevice">gd du jeu</param> /// <param name="gameTime">temps du jeu</param> public void draw(SpriteBatch spriteBatch, GraphicsDevice GraphicsDevice, GameTime gameTime) { // Fonde de mer spriteBatch.Draw(texFondMer, new Rectangle(-offsetCarte.X, -offsetCarte.Y, jeu.blockSize * terrainDesc.getLargeur(), jeu.blockSize * terrainDesc.getHauteur()), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.99f); // Affiche la carte à partir de offsetCarte for (int y = offsetCarte.Y - jeu.blockSize * 2; y < (offsetCarte.Y + jeu.resY + jeu.blockSize * 3); y += jeu.blockSize) { for (int x = offsetCarte.X - jeu.blockSize * 2; x < (offsetCarte.X + jeu.resX + jeu.blockSize * 3); x += jeu.blockSize) { Texture2D texture; Texture2D[] textureSpray = null; bool eau = false; int sprayNumber = 0; float sprayScale = 1f; int xCell = x / jeu.blockSize; int yCell = y / jeu.blockSize; TerrainDescription.TerrainCell cellM = terrainDesc.getCellAt(xCell, yCell); TerrainDescription.TerrainCell cellG = terrainDesc.getCellAt(xCell - 1, yCell); TerrainDescription.TerrainCell cellD = terrainDesc.getCellAt(xCell + 1, yCell); TerrainDescription.TerrainCell cellH = terrainDesc.getCellAt(xCell, yCell - 1); TerrainDescription.TerrainCell cellB = terrainDesc.getCellAt(xCell, yCell + 1); TerrainDescription.TypeTerrain typeM = cellM.type; TerrainDescription.TypeTerrain typeG = cellG.type; TerrainDescription.TypeTerrain typeH = cellH.type; switch (typeM) { case TerrainDescription.TypeTerrain.COLLINE: texture = texHerbe; //texCollinesFond; textureSpray = new Texture2D[] { texCollines }; sprayNumber = 3; sprayScale = 2; break; case TerrainDescription.TypeTerrain.EAU: eau = true; texture = texEau1; break; case TerrainDescription.TypeTerrain.FORET: texture = texHerbe; textureSpray = new Texture2D[] { texSapin, texArbre }; sprayNumber = 8; sprayScale = 1.5f; break; case TerrainDescription.TypeTerrain.HERBE: texture = texHerbe; break; case TerrainDescription.TypeTerrain.MARECAGE: texture = texMarais; textureSpray = new Texture2D[] { texRoseau1, texRoseau2 }; sprayNumber = 6; sprayScale = 1; break; case TerrainDescription.TypeTerrain.MONTAGNE: texture = texHerbe; textureSpray = new Texture2D[] { texMontagne }; sprayNumber = 2; sprayScale = 2.5f; break; default: texture = jeu.pixelBlanc; break; } // Détermine le rectangle source. 256 = 4 blocs (texture.Width / jeu.blockSize) Rectangle sourceRectangle; int decalageX = ((x / jeu.blockSize) % (texture.Width / jeu.blockSize)) * jeu.blockSize; int decalageY = ((y / jeu.blockSize) % (texture.Width / jeu.blockSize)) * jeu.blockSize; if (eau) { int ytexture; if (waterAnimationOffset < 16) { texture = texEau1; ytexture = (int)waterAnimationOffset * 256; } else { texture = texEau2; ytexture = ((int)waterAnimationOffset - 16) * texture.Width; } sourceRectangle = new Rectangle(decalageX, decalageY + ytexture, jeu.blockSize, jeu.blockSize); } else { sourceRectangle = new Rectangle(decalageX, decalageY, jeu.blockSize, jeu.blockSize); } int drawX = x - offsetCarte.X - (offsetCarte.X % jeu.blockSize); int drawY = y - offsetCarte.Y - (offsetCarte.Y % jeu.blockSize); spriteBatch.Draw(texture, new Rectangle(drawX, drawY, jeu.blockSize, jeu.blockSize), sourceRectangle, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.9f); // Affiche des arbres ou des collines / montagnes (spray) if (sprayNumber != 0) { Random rnd = new Random((x / jeu.blockSize) + 10000 * (y / jeu.blockSize)); for (int i = 0; i < sprayNumber; i++) { int xspray = rnd.Next(jeu.blockSize); int yspray = rnd.Next(jeu.blockSize); int wspray = (int)(sprayScale * (float)(jeu.blockSize / 2 + rnd.Next(jeu.blockSize / 2))); int itex = rnd.Next(textureSpray.Length); SpriteEffects flip = rnd.Next(2) == 0 ? SpriteEffects.FlipHorizontally : SpriteEffects.None; spriteBatch.Draw(textureSpray[itex], new Rectangle(drawX + xspray - wspray / 2, drawY + yspray - wspray, wspray, wspray), null, Color.White, 0, Vector2.Zero, flip, getZPos(drawX + xspray - wspray / 2, drawY + yspray - wspray, 0.7f, 0.8f)); } } // Plage Verticale gauche if (((typeM == TerrainDescription.TypeTerrain.EAU) && (typeG != TerrainDescription.TypeTerrain.EAU)) || ((typeM != TerrainDescription.TypeTerrain.EAU) && (typeG == TerrainDescription.TypeTerrain.EAU))) { spriteBatch.Draw(texPlageVM, new Rectangle(drawX - jeu.blockSize / 2, drawY, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.85f); spriteBatch.Draw(texPlageVH, new Rectangle(drawX - jeu.blockSize / 2, drawY - jeu.blockSize / 2, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.85f); spriteBatch.Draw(texPlageVB, new Rectangle(drawX - jeu.blockSize / 2, drawY + jeu.blockSize / 2, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.85f); } // Plage horizontale haute if (((typeM == TerrainDescription.TypeTerrain.EAU) && (typeH != TerrainDescription.TypeTerrain.EAU)) || ((typeM != TerrainDescription.TypeTerrain.EAU) && (typeH == TerrainDescription.TypeTerrain.EAU))) { spriteBatch.Draw(texPlageHM, new Rectangle(drawX, drawY - jeu.blockSize / 2, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.85f); spriteBatch.Draw(texPlageHG, new Rectangle(drawX - jeu.blockSize / 2, drawY - jeu.blockSize / 2, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.85f); spriteBatch.Draw(texPlageHD, new Rectangle(drawX + jeu.blockSize / 2, drawY - jeu.blockSize / 2, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.85f); } // Routes if (cellM.route) { // Type de route Texture2D texRoute = null; if (cellG.route && cellD.route && cellH.route && cellB.route) { texRoute = texCheminGDHB; } else if (cellG.route && !cellD.route && cellH.route && cellB.route) { texRoute = texCheminGHB; } else if (cellG.route && cellD.route && !cellH.route && cellB.route) { texRoute = texCheminGDB; } else if (cellG.route && cellD.route && cellH.route && !cellB.route) { texRoute = texCheminGDH; } else if (!cellG.route && cellD.route && cellH.route && cellB.route) { texRoute = texCheminDHB; } else if (cellG.route && !cellD.route && !cellH.route && cellB.route) { texRoute = texCheminGB; } else if (cellG.route && !cellD.route && cellH.route && !cellB.route) { texRoute = texCheminGH; } else if (cellG.route && cellD.route && !cellH.route && !cellB.route) { texRoute = texCheminGD; } else if (!cellG.route && !cellD.route && cellH.route && cellB.route) { texRoute = texCheminHB; } else if (!cellG.route && cellD.route && !cellH.route && cellB.route) { texRoute = texCheminDB; } else if (!cellG.route && cellD.route && cellH.route && !cellB.route) { texRoute = texCheminDH; } else if (cellG.route && !cellD.route && !cellH.route && !cellB.route) { texRoute = texCheminG; } else if (!cellG.route && cellD.route && !cellH.route && !cellB.route) { texRoute = texCheminD; } else if (!cellG.route && !cellD.route && !cellH.route && cellB.route) { texRoute = texCheminB; } else if (!cellG.route && !cellD.route && cellH.route && !cellB.route) { texRoute = texCheminH; } else if (!cellG.route && !cellD.route && !cellH.route && !cellB.route) { texRoute = null; // route n'allant nulle part } if (texRoute != null) { spriteBatch.Draw(texRoute, new Rectangle(drawX, drawY, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.69f); } } // Ruines if (cellM.ruine) { spriteBatch.Draw(texRuine, new Rectangle(drawX, drawY, jeu.blockSize, jeu.blockSize), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.68f); } } } // animation de l'eau waterAnimationOffset += (double)(gameTime.ElapsedGameTime.Milliseconds) / 60.0; waterAnimationOffset %= 32; }
/// <summary> /// Créer une pop up d'info sur click droit /// </summary> /// <param name="mouseX"></param> /// <param name="mouseY"></param> public void createInfoPopup(int mouseX, int mouseY) { // Détermine où on a cliqué : terrain, ville, armée... float extraHeight = 0; int extraWidth = 0; Armee armeeClick = null; VilleDescription villeClick = null; TerrainDescription.TerrainCell cellClick = getClicked(mouseX, mouseY, ref armeeClick, ref villeClick); string titre = "(bug)"; // Priorité aux armées if (armeeClick != null) { titre = armeeClick.proue.vraiNom + " (" + _jeu.factions.getFaction(armeeClick.faction).nom + ")"; extraHeight = Creatures.CREATURE_SIZE + PopWindow.MARGE_TITRE; extraWidth = Creatures.CREATURE_SIZE * Armee.MAX_TAILLE + PopWindow.MARGE_TITRE * 2; } // puis les villes else if (villeClick != null) { titre = villeClick.nom + " (" + _jeu.factions.getFaction(villeClick.faction).nom + ")"; extraHeight = -2.5f; extraWidth = 300; } // Enfin le terrain else { // Ruines if (cellClick.ruine) { int carteX = (mouseX + _jeu.terrain.offsetCarte.X) / _jeu.blockSize; int carteY = (mouseY + _jeu.terrain.offsetCarte.Y) / _jeu.blockSize; Ruines.RuineDescription desc = _jeu.ruines.ruines[new Point(carteX, carteY)]; titre = "Ruine de " + desc.nom + " (" + (desc.visite ? "déjà visité" : "non exploré") + ")"; } else if (cellClick.route) { titre = "Route - le chemin le plus rapide"; } else { switch (cellClick.type) { case TerrainDescription.TypeTerrain.COLLINE: titre = "Collines - difficile de les traverser"; break; case TerrainDescription.TypeTerrain.EAU: titre = "Eau - il vous faut ou voler, nager ou prendre un bateau"; break; case TerrainDescription.TypeTerrain.FORET: titre = "Forêt - difficile de la traverser"; break; case TerrainDescription.TypeTerrain.HERBE: titre = "Plaine - le terrain le plus rapide après la route"; break; case TerrainDescription.TypeTerrain.MARECAGE: titre = "Marécages - difficile de les traverser"; break; case TerrainDescription.TypeTerrain.MONTAGNE: titre = "Montagnes - A moins de les survoler, on ne peut les traverser"; break; } } } // Taille du texte Vector2 fontSize = _jeu.font.MeasureString(titre); Point taille = PopWindow.getPopWindowSize(_jeu, titre); // Ajoute un bord if (taille.X < extraWidth) { taille.X = extraWidth; } if (extraHeight < 0) { taille.Y = (int)((float)taille.Y * (-extraHeight)); } else { taille.Y = (int)((float)taille.Y + extraHeight); } PopWindow info = new PopWindow(_jeu, Overlay.Position.SOURIS, taille.X, taille.Y, mouseX, mouseY, titre); // Custom Draw pour afficher l'armée s'il le faut if (armeeClick != null) { info.drawCallBack = delegate(SpriteBatch spriteBatch, GraphicsDevice GraphicsDevice, GameTime gameTime) { int x = info.xoverlay + _jeu.terrain.offsetCarte.X + PopWindow.MARGE_TITRE / 2; int y = info.yoverlay + info.height - Creatures.CREATURE_SIZE - PopWindow.MARGE_TITRE / 2 + _jeu.terrain.offsetCarte.Y; for (int i = 0; i < armeeClick.getTaille(); i++) { Creature crea = armeeClick.getCreature(i); _jeu.creatures.draw(spriteBatch, GraphicsDevice, gameTime, x, y, 0f, crea.typeCreature); x += Creatures.CREATURE_SIZE; } }; } // Custom draw pour les villes else if (villeClick != null) { info.drawCallBack = delegate(SpriteBatch spriteBatch, GraphicsDevice GraphicsDevice, GameTime gameTime) { float x = info.xoverlay + PopWindow.MARGE_TITRE / 2; float y = info.yoverlay + PopWindow.MARGE_TITRE + fontSize.Y; spriteBatch.DrawString(_jeu.font, "Défense :" + villeClick.niveauDefense, new Vector2(x, y), Color.BlanchedAlmond); if (villeClick.capitaleFaction != 0) { y += fontSize.Y; spriteBatch.DrawString(_jeu.font, "Capitale de : " + _jeu.factions.getFaction(villeClick.capitaleFaction).nom, new Vector2(x, y), _jeu.factions.getFaction(villeClick.capitaleFaction).couleur); } }; } _jeu.addOverlay(info); _jeu.curseur.forme = Cursor.FormeCurseur.INTERROGATION; }