Actions.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. #from __future__ import unicode_literals
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. from PyQt4.QtCore import *
  5. from PyQt4.QtGui import *
  6. import AEtoile
  7. from Combattant import Combattant
  8. from Decor import Decor
  9. from Pion import Pion
  10. import br
  11. from lib.ui.ecran_attaqueZone import Ui_zne_fenetre
  12. import regles
  13. class Action(object):
  14. """action effectuee par un combattant sur le plateau de jeu"""
  15. def __init__(self):
  16. self._num = None #no du pion actif
  17. self._nom = "Action"
  18. self._coordCible = None #coord de la case ciblee par le curseur
  19. self._cible = None #cible (case ou pion)
  20. self._sourceCurseur = ""
  21. self._nomBouton = ""
  22. self._enCours = False
  23. self._desactivationDemandee = False
  24. #decorateur
  25. def autorise(f):
  26. def _autorise(self, *args):
  27. def fVide(*args):
  28. pass
  29. retour = fVide
  30. if not self._desactivationDemandee:
  31. retour = f
  32. retour(self, *args)
  33. return _autorise
  34. def nom(self):
  35. return self._nom
  36. def typeAtt(self):
  37. return ""
  38. def description(self):
  39. """description de l'action en cours, pour le panneau d'action"""
  40. return ""
  41. def activer(self, plateau, numPion):
  42. self.plateau = plateau
  43. self._num = numPion
  44. self.activerCurseur()
  45. self.creerItemsGraphiques()
  46. self._enCours = True
  47. self.majPanneauAction()
  48. def majCoordCible(self, coord):
  49. """met a jour les coordonnees de la cible,
  50. cad la case actuellement survolee par la souris"""
  51. if self.plateau.coordonneesValides(coord):
  52. self._coordCible = coord
  53. self.maj()
  54. def desactiver(self):
  55. self._desactivationDemandee = True
  56. self.afficherCibles(False)
  57. self.detruireItemsGraphiques()
  58. self.desactiverCurseur()
  59. self._enCours = False
  60. self.majPanneauAction()
  61. def enCours(self):
  62. return self._enCours
  63. def valider(self):
  64. #envoyer signal
  65. self.envoiSignal()
  66. self.desactiver()
  67. def estValide(self):
  68. return True
  69. def maj(self):
  70. pass
  71. def acteur(self):
  72. return self.plateau.pions[self._num]
  73. def coordActeur(self):
  74. return self.acteur().position
  75. def activerCurseur(self):
  76. if len(self._sourceCurseur) > 0:
  77. curseurPix = QPixmap(self._sourceCurseur)
  78. if not curseurPix.isNull():
  79. curseur = QCursor(curseurPix, 0, curseurPix.height())
  80. self.plateau.fenetre.ui.cbt_vue.setCursor(curseur)
  81. def desactiverCurseur(self):
  82. self.plateau.fenetre.ui.cbt_vue.setCursor(QCursor(Qt.ArrowCursor))
  83. def majPanneauAction(self):
  84. for bouton in self.plateau.fenetre.ui.page_act.findChildren(QToolButton):
  85. if self._enCours:
  86. if bouton.objectName() == self._nomBouton:
  87. bouton.setChecked(True)
  88. else:
  89. bouton.setVisible(False)
  90. else:
  91. bouton.setVisible(True)
  92. bouton.setChecked(False)
  93. self.plateau.fenetre.ui.act_description.setVisible(self._enCours)
  94. self.plateau.fenetre.ui.act_valider.setVisible(self._enCours)
  95. if self._enCours:
  96. self.plateau.fenetre.ui.act_description.majTexte(self.description())
  97. #manipulation des items graphiques
  98. def creerItemsGraphiques(self):
  99. pass
  100. def majItemsGraphiques(self):
  101. pass
  102. def detruireItemsGraphiques(self):
  103. pass
  104. #affichage des cibles
  105. def afficherCibles(self, actif):
  106. pass
  107. #envoi du signal en cas de validation
  108. def envoiSignal(self):
  109. pass
  110. def pivoter(self, modRotation):
  111. pass
  112. class Deplacement(Action):
  113. ### a completer avec des icones de deplacement,
  114. #la prise en compte de la nage et de l'escalade
  115. #et le calcul du cout de deplacement
  116. def __init__(self):
  117. super(Deplacement, self).__init__()
  118. self._nom = "Deplacement"
  119. self._chemin = [] #liste des coord des cases a traverser
  120. self._chercheurChemin = None
  121. self._cout = 0 #cout en points de dep
  122. self._zCible = 0
  123. self.cible_aConfirmer = None
  124. self._sourceCurseur = ""
  125. self._nomBouton = "act_deplacement"
  126. def typeAtt(self):
  127. return "dep"
  128. def description(self):
  129. txt = " - {} - \n".format(self.nom().upper())
  130. if not self.cible_aConfirmer:
  131. txt += " Cliquez sur la case de destination\n"
  132. txt += " (Maintenez [MAJ] pour changer l'altitude cible)\n"
  133. txt += " (Maintenez [MAJ] pour changer l'altitude cible)\n"
  134. txt += " (Maintenez [MAJ] pour changer l'altitude cible)\n"
  135. else:
  136. txt += " Destination: {}\n".format(self.plateau.proj.coord())
  137. if self._zCible != 0: txt += " Altitude de destination: {}\n".format(self._zCible)
  138. txt += self.decrireChemin()
  139. return txt
  140. def activer(self, plateau, numPion):
  141. super(Deplacement, self).activer(plateau, numPion)
  142. self.plateau.proj.creer(self.acteur())
  143. def desactiver(self):
  144. self.plateau.proj.desactiver()
  145. if self._chercheurChemin:
  146. self._chercheurChemin.arreter()
  147. self._chercheurChemin = None
  148. super(Deplacement, self).desactiver()
  149. def valider(self):
  150. if not self.cible_aConfirmer or self.cible_aConfirmer != self._coordCible:
  151. self.cible_aConfirmer = self._coordCible
  152. self.recupZCible()
  153. self.creerChemin()
  154. else:
  155. if self.estValide() and self.plateau.proj.projectionValide():
  156. self.acteur().majPosition(self.plateau.proj.coord(), self.plateau.proj.nbRotations())
  157. self.acteur().majZ(self._zCible)
  158. super(Deplacement, self).valider()
  159. def estValide(self):
  160. return len(self._chemin) > 0
  161. def majCoordCible(self, coord):
  162. if coord != self.coordActeur():
  163. super(Deplacement, self).majCoordCible(coord)
  164. def maj(self):
  165. self.plateau.proj.majCoord(self._coordCible)
  166. def pivoter(self, modRotation):
  167. self.plateau.proj.majRotation(modRotation)
  168. def creerChemin(self):
  169. self.afficherCibles(False)
  170. self._chemin = []
  171. self._cout = 0
  172. if self._chercheurChemin:
  173. self._chercheurChemin.arreter()
  174. self._chercheurChemin = None
  175. if self.plateau.cases[self._coordCible].terrain.franchissable and not self.plateau.cases[self._coordCible].occupeeParCombattant():
  176. self._chercheurChemin = AEtoile.Chemin(self.plateau, self.coordActeur(), self._coordCible, self.acteur().z, self._zCible)
  177. self._chemin = self._chercheurChemin.liste()
  178. self.afficherCibles(True)
  179. def decrireChemin(self):
  180. """decrit le chemin emprunte"""
  181. return ""
  182. def afficherCibles(self, actif):
  183. compte = 0 ; coutTotal = 0 ; valide = True
  184. z = self.plateau.cases[self.acteur().position].zDep()
  185. for coord, cout in self._chemin:
  186. compte += 1 ; coutTotal += cout
  187. if actif:
  188. if int(coutTotal) > self.acteur().pM(): valide = False
  189. dz = self.plateau.cases[coord].zDep() - z
  190. self.plateau.cases[coord].majAffichageDeplacement(compte, valide, dz)
  191. else:
  192. self.plateau.cases[coord].majAffichageDeplacement(0)
  193. z = self.plateau.cases[coord].zDep()
  194. def envoiSignal(self):
  195. coutTotal = 0
  196. for coord, cout in self._chemin:
  197. coutTotal += cout
  198. print "{} s'est deplacé et a utilisé {} points de mouvement".format(self.acteur().txtId(), cout)
  199. def recupZCible(self):
  200. self._zCible = self.acteur().z
  201. class Vol(Deplacement):
  202. """idem que Deplacement, mais affiche en plus la boite de dialogue Vol
  203. (et n'utilise pas le meme algo de deplacement?)"""
  204. def __init__(self):
  205. super(Vol, self).__init__()
  206. self._nom = "Deplacement (vol)"
  207. self._zCible = 0
  208. self._nomBouton = "pi_vol"
  209. def description(self):
  210. txt = " - {} - \n".format(self.nom().upper())
  211. return txt
  212. def typeAtt(self):
  213. return "vol"
  214. def recupZCible(self):
  215. nouveauZ = self.plateau.dialogueVol(self.acteur().z)
  216. self._zCible = nouveauZ
  217. class Attaque(Action):
  218. """attaque pre-parametree affectee a un pion, un personnage ou une creature"""
  219. def __init__(self):
  220. super(Attaque, self).__init__()
  221. self._nom = "Attaque"
  222. self._icone = ""
  223. self._portee = 1 #portee max en cases
  224. self._rayon = 0
  225. self._attributs = regles.listeAttributsAttaques()
  226. self._notes = ""
  227. def typeAtt(self):
  228. return "att"
  229. def description(self):
  230. return ""
  231. def nom(self):
  232. return self._nom
  233. def majNom(self, nom):
  234. if len(str(nom)) > 0:
  235. self._nom = nom
  236. def portee(self):
  237. return self._portee
  238. def majPortee(self, portee):
  239. try:
  240. ent = int(portee)
  241. if ent > 0:
  242. if ent >= 1000: ent = 999
  243. self._portee = ent
  244. except:
  245. pass
  246. def rayon(self):
  247. return self._rayon
  248. def majRayon(self, rayon):
  249. try:
  250. ent = int(rayon)
  251. if ent > 0:
  252. if ent >= 100: ent = 99
  253. self._rayon = ent
  254. except:
  255. pass
  256. def majAttribut(self, nom, nouvelleVal):
  257. if nom in self._attributs:
  258. if regles.attributAttaque(nom).controler(nouvelleVal):
  259. self._attributs[nom] = nouvelleVal
  260. def majAttributs(self, dicoAttributs):
  261. self._attributs = dicoAttributs
  262. def attributs(self):
  263. return self._attributs
  264. def notes(self):
  265. return self._notes
  266. def majNotes(self, notes):
  267. #on limite a 400 le nombre de caracteres
  268. notes = str(notes)
  269. self._notes = notes[0:400]
  270. def icone(self):
  271. return QIcon(self._icone)
  272. class Cac(Attaque):
  273. """attaque au corps a corps"""
  274. def __init__(self):
  275. super(Cac, self).__init__()
  276. self._nom = "Attaque au corps-à-corps"
  277. self._pionCible = None
  278. self._sourceCurseur = ""
  279. self._nomBouton = "act_attaqueCac"
  280. self._icone = "img\\curseurEpee.png"
  281. def typeAtt(self):
  282. return "cac"
  283. def desactiver(self):
  284. self.afficherCibles(False)
  285. super(Cac, self).desactiver()
  286. def description(self):
  287. txt = " - {} - \n".format(self.nom().upper())
  288. txt += " Cliquez sur une cible a portee"
  289. return txt
  290. def valider(self):
  291. if self.estValide() and self._pionCible:
  292. super(Cac, self).valider()
  293. def maj(self):
  294. self.afficherCibles(False)
  295. pionCible = self.plateau.cases[self._coordCible].occupant()
  296. if pionCible != None and pionCible != self.plateau.pionSelectionne():
  297. self._pionCible = pionCible
  298. else:
  299. self._pionCible = None
  300. self.afficherCibles(True)
  301. def estValide(self):
  302. return (self._coordCible in self.plateau.zone(self.plateau.pionSelectionne().position, self.portee, 0, False, True))
  303. def afficherCibles(self, actif):
  304. if self._pionCible:
  305. self._pionCible.estCibleAttaque(actif, self.estValide())
  306. def envoiSignal(self):
  307. print "{} a attaqué {} au corps-à-corps".format(self.acteur().txtId(), self._pionCible.txtId())
  308. class Distance(Attaque):
  309. """attaque a distance"""
  310. def __init__(self):
  311. super(Distance, self).__init__()
  312. self._nom = "Attaque à distance"
  313. self._itemLigne = None
  314. self._pionCible = None
  315. self._sourceCurseur = ""
  316. self._nomBouton = "act_attaqueDist"
  317. self._icone = ":/interface/16/ressource/arc_16.png"
  318. def typeAtt(self):
  319. return "dist"
  320. def description(self):
  321. txt = " - {} - \n".format(self.nom().upper())
  322. txt += " Cliquez sur une cible visible"
  323. return txt
  324. def majCoordCible(self, coord):
  325. if self._pionCible:
  326. self._pionCible.estCibleAttaque(False, self.estValide())
  327. if self._coordCible in self.plateau.cases:
  328. self.plateau.cases[self._coordCible].majEstCibleCurseur(False)
  329. super(Distance, self).majCoordCible(coord)
  330. def valider(self):
  331. if self.estValide() and self._pionCible != None:
  332. super(Distance, self).valider()
  333. def maj(self):
  334. """met a jour la ligne de mire representant l'attaque a distance"""
  335. self.afficherCibles(False)
  336. pionCible = self.plateau.cases[self._coordCible].occupant()
  337. self.majItemsGraphiques()
  338. if pionCible != None and pionCible != self.plateau.pionSelectionne():
  339. self._pionCible = pionCible
  340. else:
  341. self._pionCible = None
  342. self.afficherCibles(True)
  343. def estValide(self):
  344. return self.plateau.estCibleAttaqueDistValide(self._coordCible)
  345. def afficherCibles(self, actif):
  346. valide = True
  347. if actif: valide = self.estValide()
  348. if self._pionCible:
  349. self._pionCible.estCibleAttaque(actif, valide)
  350. else:
  351. #si pas de pion vise, on affiche la case cible comme visee
  352. self.plateau.cases[self._coordCible].majEstCibleCurseur(actif, valide)
  353. def creerItemsGraphiques(self):
  354. self._itemLigne = QGraphicsLineItem()
  355. self._itemLigne.setZValue(100)
  356. pinceau = QPen()
  357. pinceau.setWidth(6)
  358. self._itemLigne.setPen(pinceau)
  359. self._itemLigne.prepareGeometryChange()
  360. self.plateau.addItem(self._itemLigne)
  361. def majItemsGraphiques(self):
  362. self._itemLigne.setLine(QLineF(self.plateau.cases[self.plateau.pionSelectionne().position].centreGraphique, \
  363. self.plateau.cases[self._coordCible].centreGraphique))
  364. def detruireItemsGraphiques(self):
  365. if self._itemLigne != None:
  366. self._itemLigne.prepareGeometryChange()
  367. self.plateau.removeItem(self._itemLigne)
  368. self._itemLigne = None
  369. def envoiSignal(self):
  370. print "{} a attaqué {} a distance".format(self.acteur().txtId(), self._pionCible.txtId())
  371. class Zone(Attaque):
  372. """attaque de zone de base"""
  373. def __init__(self):
  374. super(Zone, self).__init__()
  375. self._nom = "Attaque de zone"
  376. self._itemLigne = None
  377. self._itemCible = None
  378. self._casesCibles = []
  379. self._sourceCurseur = ""
  380. self._nomBouton = "act_attaqueZone"
  381. self._icone = ":/interface/16/ressource/baguette_16.png"
  382. def typeAtt(self):
  383. return "zone"
  384. def valider(self):
  385. if self.estValide() and len(self._casesCibles) > 0:
  386. super(Zone, self).valider()
  387. # def desactiver(self):
  388. # self.detruireItemsGraphiques()
  389. # super(Zone, self).desactiver()
  390. def description(self):
  391. txt = " - {} - \n".format(self.nom().upper())
  392. txt += " Cliquez sur une cible visible"
  393. return txt
  394. def maj(self):
  395. """maj la forme de l'attaque de zone et les items cibles"""
  396. self.afficherCibles(False)
  397. self.majItemsGraphiques()
  398. self.majCibles()
  399. self.afficherCibles(True)
  400. def afficherCibles(self, actif):
  401. for coord in self._casesCibles:
  402. self.plateau.cases[(coord[0], coord[1])].majEstCibleCurseur(actif)
  403. z = 0 if len(coord) == 2 else coord[2]
  404. if self.plateau.cases[(coord[0], coord[1])].estOccupee(z):
  405. pion = self.plateau.cases[(coord[0], coord[1])].occupant(z)
  406. pion.estCibleAttaque(actif)
  407. def listePionsCibles(self):
  408. retour = []
  409. for coord in self._casesCibles:
  410. z = 0 if len(coord) == 2 else coord[2]
  411. if self.plateau.cases[(coord[0], coord[1])].estOccupee(z):
  412. pion = self.plateau.cases[(coord[0], coord[1])].occupant(z)
  413. if not pion in retour:
  414. retour.append(pion)
  415. return retour
  416. def creerItemsGraphiques(self):
  417. self._itemLigne = QGraphicsLineItem()
  418. self._itemLigne.setPen(QPen(QColor("black")))
  419. self._itemLigne.prepareGeometryChange()
  420. self.plateau.addItem(self._itemLigne)
  421. self._itemCible = QGraphicsEllipseItem()
  422. self._itemCible.setPen(QPen(QColor("black")))
  423. self._itemCible.prepareGeometryChange()
  424. self.plateau.addItem(self._itemCible)
  425. def detruireItemsGraphiques(self):
  426. if self._itemCible != None:
  427. self._itemCible.prepareGeometryChange()
  428. self.plateau.removeItem(self._itemCible)
  429. self._itemCible = None
  430. if self._itemLigne != None:
  431. self._itemLigne.prepareGeometryChange()
  432. self.plateau.removeItem(self._itemLigne)
  433. self._itemLigne = None
  434. def envoiSignal(self):
  435. touches = ""
  436. for pion in self.listePionsCibles():
  437. touches += "{}, ".format(pion.txtId())
  438. touches = touches[:-2]
  439. print "{} a lancé une attaque de zone. Les pions suivants sont touches: \n {}".format(self.acteur().txtId(), touches)
  440. class Ligne(Zone):
  441. """attaque de zone de forme lineaire"""
  442. def __init__(self):
  443. super(Ligne, self).__init__()
  444. self._nom = "Attaque de zone: ligne"
  445. def typeAttZone(self):
  446. return "ligne"
  447. def majItemsGraphiques(self):
  448. if not self._desactivationDemandee:
  449. self._itemLigne.setLine(QLineF(self.plateau.cases[self.plateau.pionSelectionne().position].centreGraphique, \
  450. self.plateau.cases[self._coordCible].centreGraphique))
  451. def majCibles(self):
  452. """met a jour la liste des cases cibles"""
  453. if not self._desactivationDemandee:
  454. self._casesCibles = []
  455. x1, y1 = self.acteur().position
  456. z1 = self.acteur().zAbs() + self.acteur().hauteur
  457. x2, y2 = self._coordCible
  458. if self.plateau.cases[(x2, y2)].estOccupee():
  459. z2 = self.plateau.cases[(x2, y2)].occupant().zAbs()
  460. else:
  461. z2 = self.plateau.cases[(x2, y2)].altitude
  462. for coord in br.ligne((x1, y1, z1), (x2, y2, z2)):
  463. if coord != (x1, y1, z1):
  464. self._casesCibles.append(coord)
  465. if not self.estValide(): self._casesCibles = []
  466. def estValide(self):
  467. retour = True
  468. for coord in self._casesCibles:
  469. x, y, z = coord
  470. if not self.plateau.cases[(x, y)].estFranchissable(z):
  471. if not isinstance(self.plateau.cases[(x, y)].occupant(z), Combattant):
  472. retour = False
  473. break
  474. return retour
  475. class Disque(Zone):
  476. """attaque de zone de forme circulaire"""
  477. def __init__(self):
  478. super(Disque, self).__init__()
  479. self._nom = "Attaque de zone (disque)"
  480. #decorateur
  481. def autorise(f):
  482. def _autorise(self, *args):
  483. def fVide(*args):
  484. pass
  485. retour = fVide
  486. if not self._desactivationDemandee:
  487. retour = f
  488. retour(self, *args)
  489. return _autorise
  490. def typeAttZone(self):
  491. return "disque"
  492. def activer(self, plateau, numPion):
  493. super(Disque, self).activer(plateau, numPion)
  494. @autorise
  495. def majCoordCible(self, coord):
  496. if self._coordCible in self.plateau.cases:
  497. self.plateau.cases[self._coordCible].majEstCibleCurseur(False)
  498. super(Disque, self).majCoordCible(coord)
  499. @autorise
  500. def majCibles(self):
  501. if self.plateau.cases[self._coordCible].estOccupee():
  502. zCible = self.plateau.cases[self._coordCible].occupant().zAbs()
  503. else:
  504. zCible = self.plateau.cases[self._coordCible].altitude
  505. self._casesCibles = self.plateau.zone3d(self._coordCible, self._rayon, zCible)
  506. def afficherCibles(self, actif):
  507. if self.estValide():
  508. super(Disque, self).afficherCibles(actif)
  509. else:
  510. super(Disque, self).afficherCibles(False)
  511. self.plateau.cases[self._coordCible].majEstCibleCurseur(actif, False)
  512. @autorise
  513. def majRayon(self, val):
  514. self._rayon = val
  515. self.maj()
  516. @autorise
  517. def majItemsGraphiques(self):
  518. self._itemLigne.setLine(QLineF(self.plateau.cases[self.plateau.pionSelectionne().position].centreGraphique, \
  519. self.plateau.cases[self._coordCible].centreGraphique))
  520. if self.estValide():
  521. rect = self.rectEllipseCirculaire(self.plateau.cases[self._coordCible].centreGraphique, self._rayon)
  522. if rect != None:
  523. self._itemCible.setRect(rect)
  524. self._itemCible.setVisible(self.estValide() and rect != None)
  525. def estValide(self):
  526. return self.plateau.estCibleAttaqueDistValide(self._coordCible)
  527. @autorise
  528. def rectEllipseCirculaire(self, centre, rayon):
  529. """renvoie le QRectF definissant une ellipse ayant le QPointF pour centre et le rayon en cases entres en param
  530. attention: l'ellipse n'est pas tout a fait circulaire, elle couvre horizontalement et
  531. verticalement le nombre de cases demandees"""
  532. rect = None
  533. if rayon > 0:
  534. p1 = QPointF((centre.x() - (rayon * self.plateau.hCase)), (centre.y() - (rayon * self.plateau.hCase)))
  535. p2 = QPointF((centre.x() + (rayon * self.plateau.hCase)), (centre.y() + (rayon * self.plateau.hCase)))
  536. if p1 != p2:
  537. rect = QRectF()
  538. rect.setTopLeft(p1)
  539. rect.setBottomRight(p2)
  540. return rect
  541. class Cone(Zone):
  542. """attaque de zone de forme conique"""
  543. def __init__(self):
  544. super(Cone, self).__init__()
  545. self._nom = "Attaque de zone: cône"
  546. def typeAttZone(self):
  547. return "cone"
  548. def description(self):
  549. return "Attaque à de zone (cone)"
  550. def majCibles(self):
  551. if self.plateau.cases[self._coordCible].estOccupee():
  552. zCible = self.plateau.cases[self._coordCible].occupant().zAbs()
  553. else:
  554. zCible = self.plateau.cases[self._coordCible].altitude
  555. self._casesCibles = self.plateau.cone3d(self.acteur().position, self._coordCible, \
  556. (self.acteur().z + self.acteur().hauteur), zCible)
  557. def creerItemsGraphiques(self):
  558. self._itemCible = QGraphicsPolygonItem()
  559. self._itemCible.setPen(QPen(QColor("black")))
  560. self._itemCible.prepareGeometryChange()
  561. self.plateau.addItem(self._itemCible)
  562. def majItemsGraphiques(self):
  563. self._itemCible.setPolygon(self.polygoneCone(self.plateau.cases[self.plateau.pionSelectionne().position].centreGraphique, \
  564. self.plateau.cases[self._coordCible].centreGraphique))
  565. def polygoneCone(self, point1, point2):
  566. """renvoie le polygone du cone defini par les deux points (origine, distance)"""
  567. ligne1 = QLineF(point1, point2)
  568. longueur = ligne1.length()
  569. ligne1.setAngle(ligne1.angle() + 22.5)
  570. ligne1.setLength(1.1547*longueur)
  571. ligne2 = QLineF(point1, point2)
  572. ligne2.setAngle(ligne2.angle() - 22.5)
  573. ligne2.setLength(1.1547*longueur)
  574. polygone = QPolygonF()
  575. polygone.append(point1)
  576. polygone.append(ligne1.p2())
  577. polygone.append(ligne2.p2())
  578. return polygone
  579. class EcranAttaqueZone(QDialog):
  580. """boite de dialogue de parametrage de l'attaque de zone"""
  581. def __init__(self, parent=None):
  582. super (EcranAttaqueZone, self).__init__()
  583. self.createWidgets()
  584. def createWidgets(self):
  585. """construction de l'interface"""
  586. self.ui = Ui_zne_fenetre()
  587. self.ui.setupUi(self)
  588. self.connect(self.ui.zne_forme, SIGNAL("currentIndexChanged(int)"), self.majAffichage, Qt.UniqueConnection)
  589. self.connect(self.ui.zne_valider, SIGNAL("clicked()"), self.ok, Qt.UniqueConnection)
  590. self.connect(self.ui.zne_annuler, SIGNAL("clicked()"), self.ok, Qt.UniqueConnection)
  591. self.ui.zne_valider.setShortcut("Enter")
  592. self.majAffichage(self.ui.zne_forme.currentIndex())
  593. def majAffichage(self, index):
  594. self.ui.zne_rayon.setVisible((index == 1))
  595. self.ui.zne_rayon_lbl.setVisible((index == 1))
  596. def resultat(self):
  597. if self.ui.zne_forme.currentIndex() == 0:
  598. attaque = Ligne()
  599. elif self.ui.zne_forme.currentIndex() == 1:
  600. attaque = Disque()
  601. attaque.majRayon(int(self.ui.zne_rayon.value()))
  602. elif self.ui.zne_forme.currentIndex() == 2:
  603. attaque = Cone()
  604. attaque.majPortee(int(self.ui.zne_portee.value()))
  605. return attaque
  606. def ok(self):
  607. self.done(1)
  608. def annuler(self):
  609. self.done(0)
  610. if __name__ == "__main__":
  611. app = QApplication(sys.argv)
  612. ecran = EcranAttaqueZone()
  613. ecran.show()
  614. r = app.exec_()
  615. att = ecran.resultat()
  616. print att.typeAtt(), att.portee()
  617. exit(r)