
21 Décembre au 5 Janvier
Voici ce qui a été fait pendant les vacances de noël.
Attention : étant donné la quantité d'information présent dans cette onglet, j'ai pris certain bout qui avez le même thème (exemple : les cartes) et je l'ai est mis dans des sous-onglet à celui ci.
La dernière fois nous avons réglé l'attaque de nos différents personnages. Mais comme dit dans les règles nous posséderont différentes unités, ainsi que des cartes sorts, bâtiment ... Il nous faut donc un moyen de choisir au préalable nos cartes afin de créer un paquet de cartes. Puis nous verrons comment mélanger aléatoirement nos paquets de cartes.
Pour commencer, il nous faut définir nos cartes, pour cela nous créons une instance d'objet appelé Carte.
class Carte{
int xposition;
int yposition;
int Cout1;
int Cout2;
PImage icon;
int xtaille_unit;
int ytaille_unit;
int VieMax;
int Vit;
String Portee;
int att;
int def;
String Faction;
String Type;
String Nom;
PImage Icon_unit;
Sur toute ces variables et objets seul 3 concerne directement la carte en question. Les variables de positions en x et en y afin d'afficher la carte dans une interface, et l'objet image icon qui correspond à l'image de la carte.
Toute les autre variable et objet sont destiné à l'unité ou les futurs sort utilisé.
Donc maintenant que l'instance d'objet est créer, créons nos carte via des tableaux. nous avons besoin en tout de 9 tableaux auxquels j'en rajoute 1 pour la suite. Pour récapituler les tableaux, deux pour chaque joueurs : un pour la pioche et un pour la main. Pour chacun de ces 4 tableaux d'objet carte je rajoute un tableau booléen de même longueur. Ensuite un tableau qui sert de glossaire de toute les cartes existantes. Ensuite le dernier tableaux (de valeur entière) nous sert d'intermédiaire lors de la sélection de carte.
Sélection de Menu:
Pour pouvoir choisir nos cartes, il nous faut d'abord mettre en pause l'ancienne partie déjà codée. Chose très simple j'utilise une variable que j'appelle histoire. Dans la fonction draw(), je crée deux condition : si la variable histoire est égale à 1 alors ... (ici on englobe tout ce qui est relatif à la sélection de carte); si la variable histoire est égale à 2 alors ...(ici on englobe tout ce qui ce rapporte à la partie de jeu).
Sélection de Menu :
Pour notre sélection de carte nous avons besoin d'aux moins 2 cartes (définie dans le tableau glossaire) qui serviront de test à notre code :
Glossaire[0]= new Carte(0,0, taille,taille, 1,0, 3,4, 2,0,"1", TICarte[1], "Mort-Vivant", "Unite", "Guerrier Squelette",IconUnite[0]);
Glossaire[1]= new Carte(0,0, taille,taille, 2,0, 2,4, 2,0,"2", TICarte[2], "Mort-Vivant", "Unite", "Archer Squelette",IconUnite[1]);
Pour définir une carte dans le glossaire on fait appel au constructeur de l'objet carte et rien de plus :
Carte(int Nxposition, int Nyposition, int Nxtaille_unit, int Nytaille_unit, int NCout1, int NCout2, int NVieMax, int NVit, int Natt, int Ndef, String NPortee, PImage Nicon, String NFaction, String NType, String NNom, PImage NIcon_unit){
Sélection de Cartes :
Etant donné qu'il existera plusieurs paquet de cartes différents à l'avenir, je crée un simple menu avec des icons correspondant à la faction du paquet de cartes en question. Pour l'instant il n'y a q'une seule possibilité celui de la faction mort-vivante. En cliquant sur l'icon on arrive donc sur la sélection de carte.
Il nous faut d'abord définir les différentes variable et objet : -On reprend d'abord nos tableaux de cartes créés précédemment auquel on rajoute la variable CarteRestante, tout est dit dans son nom pas besoin d'explication et un tableau d'entier NmbCarte_DebutDeck. -Après on a besoin de la variable PCamera (position caméra) ainsi que de Ress1, Ress2, Faction_Deck (pour savoir qu'elle partie du glossaire à afficher), et ChFaction (qui sert lors de l’initialisation d'un Joueur). -Nous avons aussi besoin d'une variable (Random) et d'un tableaux d'entier (Elimine) pour mélanger notre paquet de cartes ainsi que de deux autres variable : Actuel_Carte et Position.
Maintenant que nous avons sélectionné notre faction et que nous avons toute nos variables/objet/etc, il faut afficher les différentes cartes.
for(int C=0; C<Glossaire.length; C++){
image(Glossaire[C].icon, 50+300*(C-Pcamera),20,250,400);
image(TflecheDirectionnel[1], 70+300*(C-Pcamera),440,48,48);
image(TflecheDirectionnel[3], 235+300*(C-Pcamera),440,48,48);
text(NmbCarte_DebutDeck[C],165+300*(C-Pcamera),475);
On lance donc une boucle pour chaque carte du glossaire. A chaque boucle, on affiche la carte (avec toute ses caractéristiques), ensuite on affiche en-dessous 2 flèches opposée l'une à l'autre et entre les deux, on affiche la valeur du tableau NmbCarte_DebutDeck à la case égale à C, valeur correspondant au nombre de fois que l'on a sélectionné cette carte. En multipliant par C la position x des images on obtient un défilement horizontale des cartes, c'est bien mais si on a trop de carte, elles sortent de l'écran. On soustrait donc à C la valeur de Pcamera, une valeur qui varie en fonction des touches droite et gauche. De la sorte on a un défilé de carte que l'on peut parcourir très simplement.
Maintenant il nous faut sélectionner les cartes. Nous avons donc 2 possibilité : "le Joueur clique sur la flèche de gauche, donc la valeur de NmbCarte_DebutDeck diminue, on enlève une carte de la sélection". Et la possibilité inverse "le Joueur clique sur la flèche de droite, donc la valeur de NmbCarte_DebutDeck augmente, on rajoute une carte à la sélection".
Commençons par la seconde possibilité.
//Flèche de Droite////Additionne//
if(mouseX>=235+300*(C-Pcamera) && mouseX<=235+48+300*(C-Pcamera) && mouseY>=440 && mouseY<=440+48){
image(TflecheDirectionnel[7], 235+300*C,440,48,48);
if(mousePressed==true){
NmbCarte_DebutDeck[C]++;
Limit_ChoixDeck++;
if(Limit_ChoixDeck>Limit_deck){
NmbCarte_DebutDeck[C]=NmbCarte_DebutDeck[C]-1;
Limit_ChoixDeck--; }
mousePressed=false; } }
On commence donc par la condition, si la souris se trouvent aux coordonnées de l'image, alors changer l'image, et si la souris est pressée alors : On augmente la valeur de NmbCarte_DebutDeck à la case C de un cran, pareil pour limit_ChoixDeck (variable enregistrant le nombre de carte sélectionné). Puis on cherche à savoir si l'on dépasse le nombre de carte sélectionné, si c'est le cas on annule l'action précédente.
Ensuite la deuxième possibilité, la flèche gauche :
//Flèche De Gauche////Soustrait//
if(mouseX>=70+300*(C-Pcamera) && mouseX<=70+48+300*(C-Pcamera) && mouseY>=440 && mouseY<=440+48){
image(TflecheDirectionnel[5], 70+300*C,440,48,48);
if(mousePressed==true){
NmbCarte_DebutDeck[C]--;
Limit_ChoixDeck--;
if(NmbCarte_DebutDeck[C]<0){
NmbCarte_DebutDeck[C]=0;
Limit_ChoixDeck++; }
mousePressed=false; } }
Ici même raisonnement, on procède juste de la manière inverse.
Quand le joueur a fini, il va devoir confirmé en appuyant sur entrée puis le programme mélange son paquet de cartes, initialise le joueur (base, ressource, etc). Prenons l'exemple du joueur 1.
if(tour==0){
///Joueur 1///////////////////////////////////////////////////////////////////////////////////////////////
Base[0]= new Commandant(taille*0,taille*6, Ress1,Ress2, ChFaction, 15);
Base[0].J=1;
for(int i=0; i<NmbCarte_DebutDeck.length; i++){
for(int N=0; N<NmbCarte_DebutDeck[i]; N++){
Deck_En_Cour[Position]=Glossaire[i];
Position++; } }
for(int i=0; i<Elimine.length; i++){
Elimine[i]=-1; }
for(int D=0; D<Deck_JI.length; D++){
Actuel_Carte=D;
Random();
Deck_JI[Actuel_Carte]=Deck_En_Cour[Random];
DeckV1[Actuel_Carte]=true;
Elimine[Actuel_Carte]=Random; }
for(int D=0; D<Limit_Main; D++){
tour=1;
Deck(); }
tour=2;
keyPressed=false;
Faction_Deck=0;
for(int i=0; i<NmbCarte_DebutDeck.length; i++){
NmbCarte_DebutDeck[i]=0; }
Limit_ChoixDeck=0; }
On commence par savoir si c'est bien la sélection du Joueur 1 par la variable tour. Ensuite on initialise la base du joueur (objet regroupant les ressources et le QG du Joueur). On lance deux boucle, une boucle de la longueur du tableaux NmbCarte_DebutDeck puis une seconde de la longueur de la valeur de la case égale à i. Ces deux boucles nous permettent de remplir le tableau d'objet carte intermédiaire seulement avec les cartes choisie et ceux sans parasite.
Après on a une boucle qui ne sert qu'à éviter de potentiel bug. Cette boucle consiste donc à initialiser toute les cases du tableaux Elimine sur -1 (vous comprendrais plus tard pourquoi c'est nécessaire).
On passe enfin au mélange du paquet de carte avec la boucle suivante. On commence par affecté la valeur de D à Actuel_Carte (utile car on dois faire appel à d'autre fonction indépendante), on fait un appel de la fonction Random() (fonction nous permettant d'avoir un nombre aléatoire non tiré précédemment). On affecte donc le paquet de carte avec une carte aléatoire du tableaux d'objet carte intermédiaire on considère cette carte comme active puis la valeur Random est enregistrer dans le tableau Elimine. Avec ce processus on range donc toute les cartes choisies précédemment dans le paquet de carte d'un joueur tout en le mélangeant. Ci-dessous, la fonction Random() :
void Random(){
Random=int(random(0,Limit_deck));
for(int E=0; E<Elimine.length; E++){
if(Random==Elimine[E]){
Random(); } } }
Dans la fonction, on affecte donc une valeur aléatoire à Random, puis on compare cette valeur à toute les autres du tableaux Elimine, si l'une des valeurs est la même on rappel la fonction Random() par récurrence. De la sorte on est sur que la valeur de Random est aléatoire et non sortie précédemment.
La boucle suivante concerne la main du Joueur, on demande à l'ordi via la fonction deck() de tirer une carte en fonction du paquet de carte du joueur et ce 5x.
void Deck(){
pioche=1;
if(tour==1){
for(int C=0; C<Limit_Main; C++){
if(MainV1[C]==false && pioche>=1){
Main_JI[C]=Deck_JI[DeckPost_JI];
DeckPost_JI++;
pioche--;
MainV1[C]=true;
if(DeckPost_JI>=Deck_JI.length){
Melange(); } } }
tour=1.1;}
Pour la fonction deck() on utilise une variable pioche qu'on affecte à la valeur 1. Puis on vérifie le tour (1=Joueur1 et 2=Joueur2), on débute alors une boucle de la longueur de la main. On vérifie à chaque boucle si la carte de la main à cette position est absente et si la variable pioche est supérieur ou égale à 1. Si c'est le cas alors, on affecte à la main la carte à la case égale à DeckPost_JI (Position dans le paquet du Joueur 1), variable augmentant d'un cran à chaque tirage. De la sorte, chaque carte du paquet est tiré l'une après l'autre. Si l'on arrive au bout du paquet, on appel la fonction Melange() qui agit de la même manière que lorsqu'on a mélanger le paquet au début.
On revient à notre sélection avec les dernières lignes de Code :
tour=2;
keyPressed=false;
Faction_Deck=0;
for(int i=0; i<NmbCarte_DebutDeck.length; i++){
NmbCarte_DebutDeck[i]=0;
}
Limit_ChoixDeck=0;
On change donc le tour pour passer au Joueur 2, on affecte false à la variable booléenne keyPressed afin d'éviter des bugs. Puis on remet les valeurs de base du menu de sélection de carte afin de passer au Joueur 2.
A savoir, pour le Joueur 2, on met juste :
Histoire=2;
tour=1.2;
On change de tour (Joueur 1) et de scène (par la variable histoire).
La main d'un Joueur :
Nous avons une pioche et une main pour chaque Joueur mais nous ne pouvons pas encore jouer les différentes cartes. Il nous faut donc afficher la main pour pouvoir sélectionner l'une de ces cartes.
Pour afficher la main rien de plus simple, dans la partie interface de l'écran de jeu (actuellement à gauche du terrain), Je place un icon qui sert à afficher ou masquer la main du Joueur.
Pour la main en question, on utilise la fonction Main() :
void Main(){
if(AfficheMain==true){
if(tour>=1.1 && tour<2){
for(int C=0; C<Limit_Main; C++){
if(MainV1[C]==true){
image(Main_JI[C].icon,taille*6*C+(taille/4)*C,taille*3,taille*6,taille*10);
if(mouseX>=taille*6*C+(taille/4)*C && mouseX<=taille*6*C+(taille/4)*C+taille*6){
if(mouseY>=taille*3 && mouseY<=taille*3+taille*10){
noFill();
stroke(150,150,0);
strokeWeight(10);
rect(taille*6*C+(taille/4)*C,taille*3,taille*6,taille*10);
Première condition, si on appuyait précédemment sur l'icon qui affiche la main. La seconde condition cherche qui joue (ici le joueur 1). Puis on débute une boucle de la longueur de la main (5 carte). On cherche à chaque boucle si à cet emplacement de la main il y a une carte valide, si c'est le cas, on affiche la carte. On compare ensuite les coordonnées de la souris à celle de la carte, si les coordonnées de la souris sont comprise dans celle de la carte alors on affiche un rectangle vide mais au contour grossit et de couleur jaune autour de la carte.
Après on effectue une condition si la souris est pressé alors... et c'est là qu'on s'amuse. Commençons avec le 1er cas, la carte est une unité.
if(mousePressed==true){
if(Base[0].RessI-Main_JI[C].Cout1>=0 && Base[0].RessII-Main_JI[C].Cout2>=0){
/////Unité/////
if(Main_JI[C].Type=="Unite"){
Tunite_JI[NmbUnite1]= new Unite(/*Position*/taille*3,taille*7,/*taille* /Main_JI[C].xtaille_unit,Main_JI[C].xtaille_unit,/*Vie*/Main_JI[C].VieMax,/*Vitesse*/Main_JI[C].Vit,/*Stats*/Main_JI[C].att,Main_JI[C].def,/*Portee*/Main_JI[C].Portee,Main_JI[C].Icon_unit, Main_JI[C].Type, Main_JI[C].Nom, 1);
TuniteVivant_JI[NmbUnite1]= true;
NmbUnite1++;
if(NmbUnite1>=limite_d_unit){
NmbUnite1=0; } }
On cherche avant tout à savoir si le joueur a assez de ressources pour jouer la carte. Puis on cherche à savoir le type de carte (Pour rappel il y a 4 type Unité/Sort/Bâtiment/Amélioration). Si la carte est une unité alors : Créer dans le tableau Tunite_JI, à la case NmbUnite1, une unité avec les caractéristique de la carte. Puis on active cet unité dans le tableau booléen TuniteVivant_JI. On augmente par la suite la valeur de NmbUnite1 afin de ne pas avoir deux unité pour la même case sans oublier de vérifier que cette valeur ne dépasse pas la longueur de nos deux tableaux précedent.
On passe maintenant au sort :
/////Sort/////
if(Main_JI[C].Type=="Sort"){
if(Main_JI[C].Nom=="Fauchage"){
Fauchage();
}
if(Main_JI[C].Nom=="Récolte d'Os"){
RecolteAct=true;
action=1;
}
Donc on recherche encore le type de la carte, mais on rajoute une autre condition, le nom de la carte afin de savoir quel sort il faut activer. On a ici deux types de sort, le premier à effet immédiat (où l'on fait un bête appel de fonction) et le deuxième à effet "retarder" c'est à dire que le joueur doit choisir une case précise (là on active une variable qui va activer une fonction lié au sort, cela permet que le draw répète la fonction laissant le Joueur choisir la case voulue (effet non possible avec un bête appel de fonction) ).
On passe au bâtiment :
/////Batiment/////
if(Main_JI[C].Type=="Batiment"){
if(Main_JI[C].Nom=="Ferme à Charnier"){
ConstAct=true;
action=1;
}
}
Même principe que les sort à effet "retardé". Mais je vous détaille quand même la fonction construction :
void Construc(){
for(int C=0; C<Emplacement.length; C++){
if(C+1<300 && C+20<300 && C+21<300){
if(mouseX>=Emplacement[C].xposition && mouseX<=Emplacement[C].xposition+taille && mouseY>=Emplacement[C].yposition && mouseY<=Emplacement[C].yposition+taille){
fill(150,150,0,63);
strokeWeight(4);
stroke(150,150,0);
rect(Emplacement[C].xposition,Emplacement[C].yposition,taille*2,taille*2);
if(mousePressed==true){
if(tour>=1 && tour<2){
Batiment_JI[NmbBatiment1]=new Batisse(Emplacement[C].xposition,Emplacement[C].yposition, 10, 1, IBatiment[1], "Ferme à Charnier", 1, 2);
BatimentVivant_JI[NmbBatiment1]=true;
NmbBatiment1++;
}
if(tour>=2 && tour<3){
Batiment_JII[NmbBatiment2]=new Batisse(Emplacement[C].xposition,Emplacement[C].yposition, 10, 1, IBatiment[1], "Ferme à Charnier", 2, 2);
BatimentVivant_JII[NmbBatiment2]=true;
NmbBatiment2++;
}
Emplacement[C].Tas_d_os=0;
ConstAct=false;
action=0; } } } } }
Pour la fonction, on lance une boucle pour chaque case du terrain, on cherche (pour un bâtiment de dimension 2*2) si toute les case sont sur le terrain et non en-dehors, puis on compare les coordonnées de la souris à la case de la boucle actuelle, si les coordonnées sont similaires, on affiche un rectangle jaune sur les case où seras construit le bâtiment. On cherche ensuite si la souris est pressée, on crée alors en conséquence le bâtiment (ici il n'y a qu'un seul bâtiment disponible pour l'instant). Attention, ne pas oublier de vérifie le tour de jeu afin de bien attribuer le bâtiment à un Joueur. Le processus pour créer un bâtiment est le même que pour créer une unité. Après la création du bâtiment, on supprime les potentiels tas d'os des cases, on annule la phase de construction est on remet la variable action à 0.
A savoir, pour les sorts, le principe est le même à quelque ligne prêt.
J'en profite pour faire un aparté sur le ciblage du bâtiment lors d'une attaque :
if(U_Att<limite_d_unit && Emplacement[C_Deff].Presence=="Batiment 2"){
for(int B=0; B<Batiment_JII.length; B++){
if(BatimentVivant_JII[B]==true){
for(int X=0; X<taille*2; X+=taille){
for(int Y=0; Y<taille*2; Y+=taille){
if(Emplacement[C_Deff].xposition==Batiment_JII[B].xperso+X && Emplacement[C_Deff].yposition==Batiment_JII[B].yperso+Y){
Degat=int(Tunite_JI[U_Att].att-Batiment_JII[B].def);
if(Degat<=0){
Degat=1;}
Batiment_JII[B].Vie-=Degat;
action=0;
Tunite_JI[U_Att].Phase_Perso=0;
Tunite_JI[U_Att].mouvement=0; } } } } } }
Cet partie se situe dans la fonction degat() que nous avons précédemment utilisé pour attaquer avec les unités. Le principe est exactement le même, sauf que lorsque l'on cherche si le bâtiment est sur la case ciblée, on fait le test sur toute les cases que le bâtiment occupe (ici 4 au lieu de 1 pour les unités).
On passe maintenant aux amélioration :
/////Amélioration/////
if(Main_JI[C].Type=="Amélioration"){
if(Main_JI[C].Nom=="Boyau Ferme"){
Boyau1=3;
BoyAct1=true;
}
Donc le principe est le même que les batiments et les sorts mais aux lieu de changer la valeur de la variable action (qui nous permettait de ne pas avoir d'action en simultané) on change un valeur lié à l'amélioration elle même : cet variable corespond au délai d'activation de l'amélioration. Mais penchons nous un peu sur ce qui se passe à la fin du délai
void Project_Acide(){
textSize(20);
fill(255);
if(ProjAcide_Act1==true){
if(tour>=1 && tour<2){
if(ProjAcide1>0){
text("Projection Acide dans "+ProjAcide1+" tour",taille*23.5,taille*4.75); }
if(ProjAcide1==0){
for(int C=0; C<Limit_deck; C++){
if(Deck_JI[C].Nom=="Zombie"){
if(Deck_JI[C].J==1){
Deck_JI[C].Portee="1-2";
}
}
}
for(int U=0; U<Tunite_JI.length; U++){
if(TuniteVivant_JI[U]==true){
if(Tunite_JI[U].Nom=="Zombie"){
Tunite_JI[U].portee="1-2"; } } } } } }
On a donc un fonction pour chaque amélioration (ici on a mis que la partie de la fonction sur le Joueur 1). Chaque fonction commence par la condition si la variable booléenne lié à ce joueur pour cet amélioration est vrai alors... Puis on cherche à savoir qui joue. Si c'est au Joueur 1 alors est que le délai est actif alors affiché le nom de l'amélioration et le nombre de tour restant. Par contre si le délai est fini alors, affecté l'amélioration à toute les cartes de jeu du Joueur puis affecté l'amélioration à toute ces unités sur le terrain (ici l'amélioration consiste à une augmentation de la portée des unité zombies, on cherchent donc à savoir si la carte ou l'unite en question est un zombie, si c'est le cas on change la valeur de portee en "1-2").
Donc maintenant que la carte a été jouée, il faut remettre le jeu à "la normale" :
AfficheMain=false;
mousePressed=false;
Base[0].RessI-=Main_JI[C].Cout1;
Base[0].RessII-=Main_JI[C].Cout2;
MainV1[C]=false;
On règle la variable booléenne AfficheMain sur faux afin d'enlever les cartes de notre vue, la souris est désélectionné, on applique le coût de la carte sur les ressources du joueur, puis on désactive la carte de sorte à ce qu'elle ne soit plus rejouée.
On en a donc fini avec les cartes. Passons aux bases des Joueurs.
Les bases des Joueurs sont des objets nommés Commandant :
class Commandant{
int xperso;
int yperso;
int Taille=taille*3;
int RessI;
int RessII;
String Faction;
int VieMax;
int Vie;
int J;
Commandant(int Nxperso, int Nyperso, int NRessI, int NRessII, String NFaction, int NVieMax){
On a pour chaque base, leurs coordonnées (xperso et yperso), leur taille, leur vie et leur vie maximum du bâtiment. On rajoute à ça les ressources du Joueur, le numéro du Joueur et sa faction.
On rajoute dans l'instance, une fonction qui affiche les bases sur le terrain, à la différence qu'un rectangle est tracé en dessous de l'image du bâtiment (la couleur du rectangle dépend de la valeur de J) et que l'image du bâtiment dépend elle de la faction du Joueur comme on peu le voir ci-dessous :
void Affichage(){
strokeWeight(2);
if(J==1){
fill(100,0,0,63);
stroke(200,0,0); }
if(J==2){
fill(0,0,100,63);
stroke(0,0,200); }
rect(xperso,yperso,taille*3,taille*3);
if(Faction=="Mort-Vivant"){
image(IBase[0],xperso,yperso,taille*3,taille*3); }
noFill();
stroke(255);
strokeWeight(1); }
Contrairement aux unité où je mis la fonction de leur mort en dehors de leur instance d'objet, la fonction de la mort des bases se situe dans l'instance Commandant :
void Vie(){
if(Vie<=0){
textSize(30);
background(0);
fill(255,0,0,255);
if(J==1){
text("Victoire haut la main du Joueur 2.", taille*2,taille*7); }
if(J==2){
text("Victoire écrasante du Joueur 1.", taille*2,taille*7); } }
action=1;}
On cherche donc à savoir si la vie du bâtiment est inférieur ou égale à 0, si c'est le cas alors affichait un écran noir avec un texte. (Fin de partie). Il ne reste plus qu'à redémarrer la partie.
Je profite qu'on ai parlé des bases des joueurs et donc de leurs ressources pour introduire le changement de tour essentiel pour le jeu et gagné certaines ressources.
void Tour_De_Jeu(){
if(keyPressed==true){
if(key=='p'){
action=0;
for(int U=0; U<Tunite_JI.length;U++){
if(TuniteVivant_JI[U]==true){
Tunite_JI[U].Tour_action=0;
Tunite_JI[U].mouvement=0;
Tunite_JI[U].Phase_Perso=0; } }
tour+=0.8;
if(tour>=3){ tour=1;}
Deck();
//////////////Joueur 1////////////////////////
if(tour==1.1){
Base[0].RessI++;
for(int U=0; U<Tunite_JI.length;U++){
if(TuniteVivant_JI[U]==true){
Tunite_JI[U].Tour_action=1; } }
for(int B=0; B<Batiment_JI.length; B++){
if(BatimentVivant_JI[B]==true){
if(Batiment_JI[B].Temps==0){
if(Batiment_JI[B].Nom=="Ferme à Charnier"){
Base[0].RessI++; } }
if(Batiment_JI[B].Temps>0){
Batiment_JI[B].Temps--; } } }
if(Boyau1>=0){ Boyau1--;}
if(ProjAcide1>=0){ ProjAcide1--;}
if(Os_Dur1>=0){ Os_Dur1--;}
tour=1.2; }
keyPressed=false;
key=0; } } }
Pour reprendre du début avec pour exemple le joueur 1, quand le bouton 'p' est pressé, on met la variable action sur 0 (de la sorte toute action est annulée). Toute les unités du Joueur 1 (et du deuxième dans le programme) sont mise à la phase zéro afin qu'elle n'agisse pas lors du tour adverse. On augmente la variable tour de 0.8 ( ce qui rend la valeur entière). On appel la fonction deck() afin de faire tirer une carte au joueur en question. Puis on initialise le tour du joueur, on lui met rajoute des ressources, toute ses unités peuvent maintenant agir, si il a des bâtiment sur le terrain soit on avance leur construction (si elle n'est pas terminée) soit on joue le bonus du bâtiment (ici +1 de ressource I ). Après on voit si les variables relatif aux différentes améliorations sont supérieur à 0, si c'est le cas on les baisses d'un cran (on simule de la sorte un délai avant activation de l'amélioration). Puis on met les variables relatif au clavier à 0.
Bon on a toute nos mécaniques de base pour le jeu, il nous faut maintenant complémenter le jeu avec des cartes variées. Déjà pour les sorts, je dénombre actuellement 3 sort :
-Fauchage : sort consistant à supprimer ses unités afin de récolter des ressources. Pour ce faire, dans la fonction Fauchage(), je lance une boucle et met à 0 la vie de toute mes unités active et pour chacune de ces unités, je rajoute 1 de ressource II au Joueur.
-Récolte d'os : (à savoir, les unités squelette laisse un tas d'os sur la case de leur mort) ce sort permet de récolter tout les tas d'os d'une case choisie. Pour cela je lance une boucle pour chaque case du terrain, je compare les coordonnées de la case de la boucle avec celle de la souris, si les coordonnées concordent et que la souris est pressée, j'ajoute à la variable des ressource I du joueur le nombre de tas d'os de la case (tas d'os qui sont supprimé du terrain juste après).
-Nécromancie : Le sort sert à transformer un tas d'os du terrain en guerrier squelette. Le principe de la fonction est le même que le sort précédant, sauf qu'on n'agit pas sur les ressources, on créer une unité particulière (comme fait lors d'une invocation d'unité avec les cartes) et on enlève 1 tas d'os à la case.
Ensuite vienne les améliorations :
-Boyau ferme : On augmente la portée des archers de 1 (ils passent de 2 à 2-3). La même méthode que celle utilisé en exemple plus tôt.
-Projection acide : Augmentation de la portée des zombies (de 1 à 1-2). C'est l'amélioration qui est utilisé en exemple.
-Durcissement des Os : Augmente la défense de toute les unités squelettique. Même méthode que les deux précédent sauf qu'au lieu de changer la portée c'est la variable défense qui augmente d'un cran.
-Soin Nécrotique : Ici, on ne change rien aux unités ou aux cartes, on active juste une variable booléenne pour un joueur permettant à ces nécromancien de soigner ces unités (la méthode pour soigné sera expliqué lorsque j'évoquerais les nécromants).
Pour les bâtiments il n'y en a qu'un seul qui est déjà expliqué.
On passe maintenant aux unités (pour des infos précises veuillez vous référer au tableur des cartes) :
-Archer et Guerrier squelette : à leur mort ces unités laisse un tas d'os sur place. Ils ont besoin pour ça de la variable NumCase qui enregistre le numéro de la case sur laquelle ils sont et à leur mort on rajoute donc à cette case +1 dans la variable tas_d_os.
-Champion squelette : lorsqu'il tue une unité il gagne 0.5 d'attaque (les dégâts sont arrondie à l'entier inférieur). Pour ce faire dans la fonction attaque je rajoute une condition juste après l'affectation des dégâts sur la cible, cette condition est si la vie de l'attaqué est inférieur ou égale à 0, si c'est le cas on vérifie que l'unité attaquante est bien un champion squelette et on lui rajoute 0.5 de dégât en plus.
-Zombie et goule : lorsqu'il tue un ennemi, celui devient un zombie qui sert l'attaquant. On se sert de la même méthode que celle du champion sauf que ici à la place d'augmenter nos dégâts, on créer une unité zombie à l'emplacement de la victime.
-Liche : juste une unité à distance qui fait mal.
-Nécromancien : possède deux capacité, la première : celle de créer un guerrier squelette à partir d'un tas d'os sur le terrain. le fonctionnement est similaire que celui d'une attaque sauf qu'on demande au programme de chercher une case vide et possédant au moins 1 tas d'os le tout à proximité de l'unité. Après l'appel de fonction n'est pas degat(), mais Releve_Mort() qui agit de la même manière que le sort de nécromancie. La deuxième capacité du nécromant est celle que l'on débloque via une amélioration, elle permet de soigner une unité. Même fonctionnement que précédemment mais on fait appel à la fonction SoinNecro() qui marche pareil que la fonction degat() mais qui rajoute des PV au lieu d'en enlever.
-Fossoyeur : récolte un tas d'os au sol pour en faire une ressource. Un mixe entre le nécromancien et le sort récolte d'os.
-Chien Zombie : rien de particulier si ce n'est qu'il va vite.
