/// <summary> /// Click gauche sur une ville /// </summary> /// <param name="posCell">position de la map clickée</param> /// <param name="clickV">la ville</param> /// <param name="released">si on a clické ou relaché</param> private void leftClickOnVille(Point posCell, VilleDescription clickV, bool released) { // Si aucune armée n'est sélectionnée et que c'est notre ville, ouvre le panneau de gestion if ((_jeu.selectedArmee == null) && (clickV.faction == _jeu.tourFaction)) { _jeu.addOverlay(new PanneauVille(_jeu, clickV)); } // Si une armée est sélectionnée, on calcul une nouvelle trajectoire si c'est une ville amie else if ((_jeu.selectedArmee != null) && (clickV.faction == _jeu.tourFaction)) { setTarget(posCell); } // si c'est une ville ennemie, c'est une attaque else if ((_jeu.selectedArmee != null) && (clickV.faction != _jeu.tourFaction)) { // raccourci d'écriture pour vérifier si on est à coté Point v = clickV.positionMap; Point a = _jeu.selectedArmee.positionCarte; if ((a.X >= (v.X - 1)) && (a.X <= (v.X + 2)) && (a.Y >= (v.Y - 1)) && (a.Y <= (v.Y + 2))) { // Oui ! A l'attaaaaaaaaaaaaaaaaaaaaaaaaque ! attaqueVille(clickV); } } }
/// <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> /// L'armée attaque la ville /// </summary> /// <param name="armee">armée</param> /// <param name="v">ville</param> private void attaqueVille(Armee armee, VilleDescription vd) { _jeu.selectedArmee = armee; if (_jeu.interactionJoueur.attaqueVille(vd)) { // Si on a gagné, se déplace dans la ville si on a encore du mouvement armee.moveTarget = vd.positionMap; } }
/// <summary> /// Attaque d'une ville ennemie -- appelée aussi par l'IA /// </summary> /// <returns> true si on a gagné</returns> /// <param name="cible">ville cible</param> public bool attaqueVille(VilleDescription cible) { bool retVal = false; // Détermine toutes les armées de la ville List <Armee> garnison = new List <Armee>(); foreach (Armee arme in _jeu.armees) { if (cible.contains(arme.positionCarte)) { garnison.Add(arme); } } // Mode auto ou graphique if (_jeu.factions.getFaction(_jeu.tourFaction).humanPlayer || _jeu.factions.getFaction(cible.faction).humanPlayer) { if (garnison.Count != 0) { // Mode graphique Combat combat = new Combat(_jeu, _jeu.selectedArmee, garnison); ZoneCombat zc = new ZoneCombat(_jeu, combat, delegate(bool attaquantVainqueur) { if (!attaquantVainqueur) { _jeu.selectedArmee = null; } else { // On gagne cible.faction = _jeu.selectedArmee.faction; } }); _jeu.addOverlay(zc); } else { // On gagne cible.faction = _jeu.selectedArmee.faction; } } else { if (garnison.Count != 0) { attaqueArmee(garnison); } // Si il y a encore un attaquant, c'est la victoire ! if (_jeu.selectedArmee != null) { // Capture la ville cible.faction = _jeu.selectedArmee.faction; retVal = true; } } return(retVal); }
/// <summary> /// Création d'un nouvel héros pour la faction courante /// </summary> /// <param name="nom">nom du héros</param> /// <param name="femme">true si femme</param> /// <param name="allies">true si on ajoute des alliés</param> public void createHeros(string nom, bool femme, bool allies) { // Choix de la ville List <VilleDescription> villesFaction = new List <VilleDescription>(); foreach (VilleDescription vd in _jeu.villes.villeDesc) { if (vd.faction == _jeu.tourFaction) { villesFaction.Add(vd); } } if (villesFaction.Count != 0) { VilleDescription vd = villesFaction[_jeu.rnd.Next(villesFaction.Count)]; int herosType = femme ? TYPE_HEROS : TYPE_HEROINE; Creature heros = new Creature(_jeu, herosType, vd.faction, vd.positionMap); heros.vraiNom = nom; // Possède un étendard heros.addItem(_jeu.items.itemDesc[Items.ETENDARD]); Armee armee = new Armee(_jeu); armee.addCreature(heros); // Alliés éventuels : types 19-27 int nbAllie = 0; if (allies) { int typeAllie = _jeu.rnd.Next(TYPE_ALLIEMAX + 1 - TYPE_ALLIEMIN) + TYPE_ALLIEMIN; nbAllie = _jeu.rnd.Next(3) + 1; for (int i = 0; i < nbAllie; i++) { armee.addCreature(new Creature(_jeu, typeAllie, vd.faction, vd.positionMap)); } } armee.positionCarte = armee.getPositionLibre(armee.positionCarte, false, false).Value; _jeu.addArmee(armee); if (allies) { _jeu.messageInfo = nom + " est accompagné" + (femme ? "e" : "") + " de " + nbAllie + " allié" + (nbAllie > 1 ? "s" : "") + " et se trouve à " + vd.nom; } else { _jeu.messageInfo = nom + " se trouve à " + vd.nom; } } }
/// <summary> /// L'armée doit rentrer dans la ville la plus proche /// </summary> /// <param name="armee"></param> private void choisitCibleVilleRefuge(Armee armee) { int minChemin = Int32.MaxValue; VilleDescription vdcible = null; foreach (VilleDescription vd in _jeu.villes.villeDesc) { if (vd.faction == _jeu.tourFaction) { Point cible = vd.positionMap; if (armee.positionCarte == cible) { minChemin = 0; vdcible = vd; break; } else { armee.moveTarget = cible; if ((armee.trajectoire != null) && (armee.trajectoire.chemin != null)) { int lenChem = armee.trajectoire.chemin.Count; if (lenChem != 0 && lenChem < minChemin) { minChemin = lenChem; vdcible = vd; } } } } } if (vdcible != null) { armee.moveTarget = vdcible.positionMap; } else { armee.moveTarget = null; } }
/// <summary> /// Créateur à partir de fichier de description des villes /// </summary> /// <param name="leJeu">jeu en cours</param> /// <param name="nomFichierRessource">nom du fichier texte (sans préfixe SeigneursDeGuerre.)</param> public Villes(Jeu leJeu, string nomFichierRessource) : this(leJeu) { // Format du fichier : // Indice;Nom;NiveauDefense;NiveauProductivtié;CapitaleFaction;Faction;Productions possibles (indexes séparées par |) // (header présent dans le fichier) _description = new VilleDescription[leJeu.terrain.terrainDesc.nombreVilles]; CSVReader csv = new CSVReader(nomFichierRessource, ";"); // header if (!csv.readLine()) { throw new SdGException("Le fichier des villes est vide"); } ; try { while (csv.readLine()) { VilleDescription ville = new VilleDescription(Int32.Parse(csv.getField(0))); ville.nom = csv.getField(1); ville.niveauDefense = Int32.Parse(csv.getField(2)); ville.niveauProductivite = Int32.Parse(csv.getField(3)); ville.capitaleFaction = Int32.Parse(csv.getField(4)); ville.faction = Int32.Parse(csv.getField(5)); _description[ville.indice] = ville; ville.positionMap = leJeu.terrain.terrainDesc.getPositionVilles(ville.indice); string[] types = csv.getField(6).Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); ville.typeCreatures = new int[types.Length]; for (int i = 0; i < types.Length; i++) { ville.typeCreatures[i] = Int32.Parse(types[i]); } // La faction neutre ne produit rien ville.productionCourante = (ville.faction == 0) ? -1 : 0; } } finally { csv.dispose(); } }
/// <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; }
/// <summary> /// Retourne ce sur quoi le curseur de souris a cliqué /// </summary> /// <param name="mouseX">position X du curseur</param> /// <param name="mouseY">position Y du curseur</param> /// <param name="armeeClick">si non null, l'armée cliquée</param> /// <param name="villeClick">si non null, la ville cliquée</param> /// <returns>la cellule du terrain cliqué</returns> public TerrainDescription.TerrainCell getClicked(int mouseX, int mouseY, ref Armee armeeClick, ref VilleDescription villeClick) { int carteX = (mouseX + _jeu.terrain.offsetCarte.X) / _jeu.blockSize; int carteY = (mouseY + _jeu.terrain.offsetCarte.Y) / _jeu.blockSize; armeeClick = null; villeClick = null; // Une armée se trouve ici ? foreach (Armee armee in _jeu.armees) { if (armee.positionCarte.X == carteX && armee.positionCarte.Y == carteY) { armeeClick = armee; break; } } // Une ville se trouve ici ? foreach (VilleDescription vd in _jeu.villes.villeDesc) { if (carteX >= vd.positionMap.X && carteX <= (vd.positionMap.X + 1) && carteY >= vd.positionMap.Y && carteY <= (vd.positionMap.Y + 1)) { villeClick = vd; break; } } return(_jeu.terrain.terrainDesc.getCellAt(carteX, carteY)); }
public void cEstMonTour() { switch (this._etat) { case Etat.PHASE_INIT: idxChoixDest = 0; idxChoixDestVD = 0; minChemin = Int32.MaxValue; minCheminArmee = Int32.MaxValue; armeeCible = null; vdcible = null; armada = _jeu.factions.getArmada(_jeu.tourFaction); _etat = Etat.PHASE_CHOIX_DEST; break; case Etat.PHASE_CHOIX_DEST: // Itère plusieurs fois par update() sur cette phase for (int iter = 1; iter < 10; iter++) { // Passe en revue toutes les armées et choisit ce qu'il faut faire if (idxChoixDest < armada.Count) { // Pour toutes les armées de l'armada, regarde la ville la plus proche à attataquer if (idxChoixDestVD < _jeu.villes.villeDesc.Length) { choisitCibleArmee(armada[idxChoixDest], _jeu.villes.villeDesc[this.idxChoixDestVD++]); if (minChemin == 0) { // on ne peut pas faire mieux, on coupe court à la recherche idxChoixDestVD = _jeu.villes.villeDesc.Length; } } else { // Plus ville, Maintenant passe aux armées cibles if (idxChoixDestArmee < _jeu.armees.Count) { choisitCibleArmee(armada[idxChoixDest], _jeu.armees[idxChoixDestArmee++]); if (minCheminArmee == 0) { // On ne peut pas faire mieux, on coupe court à la recherche idxChoixDestArmee = _jeu.armees.Count; } } else { // Plus de ville, plus d'armées, regarde le plus proche si on a trouvé une ville avant de passer à l'armée à bouger suivante idxChoixDestVD = 0; idxChoixDestArmee = 0; // Choisit-on l'armée ou la ville ? if (minCheminArmee < minChemin) { // l'armée cible est plus proche vdcible = null; } else { // la ville cible est plus proche armeeCible = null; } if (armeeCible != null) { // La cible est une armée armada[idxChoixDest].realTarget = armeeCible.positionCarte; // Se déplace jusqu'à la position de la ville Point?target = getPointPresDeArmee(armada[idxChoixDest], armeeCible.positionCarte); // Si l'armée est inaccessible, rentre en ville ! if (target == null) { choisitCibleVilleRefuge(armada[idxChoixDest]); } else if (armada[idxChoixDest].moveTarget != target) { armada[idxChoixDest].moveTarget = target; } } else if (vdcible != null) { // La cible est une ville armada[idxChoixDest].realTarget = vdcible.positionMap; // Se déplace jusqu'à la position de la ville Point?target = getPointPresDeVille(armada[idxChoixDest], vdcible.positionMap); // Si la ville est inaccessible, rentre en ville ! if (target == null) { choisitCibleVilleRefuge(armada[idxChoixDest]); } else if (armada[idxChoixDest].moveTarget != target) { armada[idxChoixDest].moveTarget = target; } } else { // Pas de ville ni d'armée à attaquer, se retire // Trouve la ville amie la plus proche choisitCibleVilleRefuge(armada[idxChoixDest]); } // Passe à l'armée suivante minChemin = Int32.MaxValue; minCheminArmee = Int32.MaxValue; armeeCible = null; vdcible = null; idxChoixDest++; } } } else { _etat = Etat.PHASE_CHOIX_PRODUCTION; break; } } break; case Etat.PHASE_CHOIX_PRODUCTION: // Passe en revue toutes les villes et choisit ce qu'il faut construire foreach (VilleDescription vd in _jeu.villes.villeDesc) { if (vd.faction == _jeu.tourFaction) { choisirProduction(vd); } } _etat = Etat.PHASE_MOUVEMENT; _jeu.selectedArmee = null; _jeu.selectedArmeeGO = false; break; case Etat.PHASE_MOUVEMENT: case Etat.PHASE_MOUVEMENT_2: // Trouve la prochaine armée qui peut bouger if ((_jeu.selectedArmee != null) && !_jeu.selectedArmeeGO) { _jeu.selectedArmee = null; armada = _jeu.factions.getArmada(_jeu.tourFaction); } if ((_jeu.selectedArmee == null)) { foreach (Armee armee in armada) { //armee.reinitTrajectoire(); if (deplaceArmee(armee)) { _jeu.selectedArmee = armee; _jeu.selectedArmeeGO = true; break; } } // Si rien n'est sélectionné, phase d'après if (_jeu.selectedArmee == null) { if (_etat == Etat.PHASE_MOUVEMENT) { _etat = Etat.PHASE_ATTAQUE; } else { // Fini, fin du tour // reinit pour la suite _etat = Etat.PHASE_INIT; _jeu.finTour(); } idxChoixDest = 0; } } break; case Etat.PHASE_ATTAQUE: // Si un combat est en cours ; on continue; if (_jeu.getTopOverlay().modalOverlay != Overlays.Overlay.ModalOverlay.COMBAT) { armada = _jeu.factions.getArmada(_jeu.tourFaction); // Si on peut attaquer une ville, on le fait. if (idxChoixDest < armada.Count) { // Peut-on attaquer ? Point?vqm = armada[idxChoixDest].realTarget; if (vqm != null) { Point v = vqm.Value; Point a = armada[idxChoixDest].positionCarte; // Attaque de ville ou d'armée ? VilleDescription villeAttaquee = null; foreach (VilleDescription vd in _jeu.villes.villeDesc) { if (vd.positionMap == v) { villeAttaquee = vd; break; } } if (villeAttaquee != null) { if ((a.X >= (v.X - 1)) && (a.X <= (v.X + 2)) && (a.Y >= (v.Y - 1)) && (a.Y <= (v.Y + 2))) { // Oui ! A l'attaaaaaaaaaaaaaaaaaaaaaaaaque ! _jeu.terrain.zoomSur(armada[idxChoixDest].positionEcran); attaqueVille(armada[idxChoixDest], villeAttaquee); } } else { // Attaque d'armée ? foreach (Armee cible in _jeu.armees) { if (cible.positionCarte == v && cible.faction != _jeu.tourFaction) { // oui ! attaque l'armée ! _jeu.terrain.zoomSur(armada[idxChoixDest].positionEcran); attaqueArmee(armada[idxChoixDest], cible); break; } } } } idxChoixDest++; } else { // phase de mouvement suivante (jusque dans les villes prises) _etat = Etat.PHASE_MOUVEMENT_2; } } break; } }
/// <summary> /// Déplacement des armées : met à jour vdcible avec la meilleure cible pour une armée & une ville choisie /// </summary> /// <param name="armee">armee</param> /// <param name="vd">ville</param> private void choisitCibleArmee(Armee armee, VilleDescription vd) { // Choisit la ville la plus proche et l'attaque si on peut gagner if (vd.faction != _jeu.tourFaction) { // Regarde d'abord si elle n'est pas trop loin... Taille max const int DISTANCE_MAX = 25; if (Math.Max(Math.Abs(vd.positionMap.X - armee.positionCarte.X), Math.Abs(vd.positionMap.Y - armee.positionCarte.Y)) < DISTANCE_MAX) { // Regarde d'abord si on gagnerait pour éviter de calculer des trajectoires pour rien // peut-on gagner le combat ? List <Armee> garnison = new List <Armee>(); foreach (Armee arme in _jeu.armees) { if (vd.contains(arme.positionCarte)) { garnison.Add(arme); } } bool gagne; if (garnison.Count != 0) { Combat combat = new Combat(_jeu, armee, garnison); gagne = combat.simulationCombat(); } else { gagne = true; } if (gagne) { // Accessible ? // choisit un point accessible près de la ville Point?cible = getPointPresDeVille(armee, vd.positionMap); if (cible != null) // sinon inaccessible // Déjà là ? { if (armee.positionCarte == cible) { minChemin = 0; vdcible = vd; } else { armee.moveTarget = cible; if ((armee.trajectoire != null) && (armee.trajectoire.chemin != null)) { int lenChem = armee.trajectoire.chemin.Count; if (lenChem != 0 && lenChem < minChemin) { if (minChemin > lenChem) { minChemin = lenChem; vdcible = vd; } } } } } } } } }
/// <summary> /// Choisit la production /// </summary> /// <param name="vd"></param> private void choisirProduction(VilleDescription vd) { // Je prend au hasard ! vd.productionCourante = _jeu.rnd.Next(vd.typeCreatures.Length); }