Merci pour ces infos,
@Arlann !
- Baguettator a écrit:
La solution avec la baseline j'ai pas bien saisi... A quoi ça fait référence ?
C'est pour si tu utilise un objet pour contenir ton image, plutôt que la dessiner sur l'arrière plan de la room. Mais dans ton cas on va rester sur l'arrière plan, ça fera l'affaire (ceci dit c'est tout-à-fait faisable avec un objet à la place, c'est une simple question de choix).
Bon j'étais un peu frustré de te laisser dans l'expectative, donc finalement j'ai bûché sur une petite proposition détaillée.
Je vais faire ça sous forme de tuto pas-à-pas pour que tu comprenne au mieux le système, mais libre à toi de l'adapter à ta guise ou de faire autrement. La solution n'est sûrement pas parfaite et tu auras sûrement besoin de la rendre conforme aux petites subtilités supplémentaires de ton jeu, mais ça te donnera une base. Comme tu as déjà eu le temps d'y réfléchir, tu seras mieux armé.
Attention, ça va être un long post. Mais ça, tu le vois déjà.
Commençons par déclarer en haut du
global_script les variables et tableaux de variables dont on aura besoin (à ajouter à celles que tu as déjà créées) :
- Code:
-
// main global script file
int nbCartes; //Le nombre de cartes dont disposera le joueur, en fonction des extensions possédées
int nbExtensions; //Le nombre d'extensions au total (inclut le jeu de base)
int tailleExtension[]; //Le nombre de cartes contenu dans chaque extention
int carte[]; //La carte qu'on tirera au sort et affichera à l'écran
Attention : comme précisé ci-dessus, le jeu de base est considéré ici comme une extension (en l'occurrence, l'extension 0, mais on va y venir). Le terme "Extension" désigne ici tout simplement un groupe de cartes (un paquet de cartes qu'on achète en magasin et dont on connaît le contenu, en gros). Libre à toi de modifier le nom des variables comme tu l'entends. Il faudra en tout cas avoir ça en tête quand j'utiliserai le mot "extension" par la suite.
Note : Il est d'usage de considérer que le premier élément d'une liste (ou la première ligne d'un tableau) est l'élément 0. Il vaut mieux faire comme ça pour pas trop s'emmêler les pinceaux avec le fonctionnement du script, même s'il faut garder en tête certaines subtilités (le numéro du dernier élément = la taille de l'élément - 1; et non la taille de l'élément tout court).
Les crochets ne contenant rien dans la déclaration d'un int (ex : tailleExtension[]) indiquent la création d'un tableau dynamique, c'est à dire un tableau dont on ne connaît pas encore le nombre de lignes. La création d'un tableau signifie que l'on crée en fait autant de variables qu'il y'aura de lignes, et qui deviendront
tailleExtension[1], tailleExtension[2], etc... Ici on aurait aussi bien pu déclarer :
- Code:
-
int tailleExtension[3]; //Tableau contenant 3 lignes numérotées de 0 à 2
...car on sait que le nombre de lignes correspondra au nombre d'extensions. Mais plutôt que d'avoir à tout modifier à chaque fois qu'on rajoutera une nouvelle extension, autant l'automatiser.
Du coup, il faut maintenant initialiser la taille du tableau
tailleExtension (en ce qui concerne le tableau
carte, ça viendra un peu plus tard). On va faire ça au lancement du jeu, donc dans la fonction
game_start du
global_script:
- Code:
-
function game_start()
{
tailleExtension = new int[nbExtensions];
}
C'est comme ça qu'on déclare le nombre de lignes que contiendra notre tableau dynamique. La taille du tableau vaudra donc automatiquement
nbExtensions.
EDIT : J'ai légèrement changé d'approche en cours de rédaction, donc à ce stade on n'a pas encore défini cette valeur. Ce sera fait de manière dynamique avec ce qu'on va faire plus bas.Bon, maintenant il faut importer les cartes dans l'onglet
Sprites de l'arborescence, si ce n'est pas déjà fait. Je te conseille de créer un nouveau dossier pour contenir les cartes afin de mieux t'y retrouver, mais à toi de voir.
Le souci c'est que, en fonction des autres images que tu auras importé ou importera plus tard, le numéro des sprites correspondant aux cartes risque d'être un peu aléatoire (en tout cas peu de chances que ça aille de 0 à x) surtout si tu en ajoutes dans le futur. Pour gruger et mieux organiser tout ça, je te propose de créer une
view (vue) qui contiendra les cartes. Normalement il en existe déjà une par défaut, tu peux la renommer "VUECARTES" (les majuscules sont facultatives ici mais seront obligatoires dans le code) :
Maintenant que c'est fait, retourne dans ton dossier de sprites, et sélectionne les images représentant les cartes du jeu de base (s'il y a une discontinuité, tu peux les sélectionner une à une en maintenant ctrl enfoncé). Clic droit >> Assign Sprites to View, et cette fenêtre va s'ouvrir :
Sélectionne le numéro de la vue que tu as nommé "VUECARTES" (normalement c'est la 1 - une fois n'est pas coutume il n'y a normalement pas de vue 0). La
Loop, qui correspond normalement à une séquence d'animation, correspondra ici à une extension. Pour le jeu de base c'est l'extension 0, donc sélectionne la Loop 0.
Fais de même avec les autres extensions (extension 1 = Loop 1, etc.).
Si tu ouvre l'onglet "VUECARTES" tu devrais obtenir quelque chose comme ça avec 3 extensions de 3 cartes chacune :
Bon, moi j'ai rien trouvé de mieux à mettre que des screenshots de GTA V, mais c'est pour l'exemple.
Important : Pense à supprimer les loops en trop (loops ne contenant aucune image) si il y en a.
On a maintenant nos groupes de cartes bien organisés.
Sauf que le nombre d'extensions peut varier si tu en ajoute dans le futur. On va donc dire que le nombre d'extensions est le nombre de loops disponibles dans la view "VUECARTES" (eh oui, ça s'adaptera donc automatiquement, c'est pas magique ?
) Tu vas donc ajouter ça
au début de ta fonction
game_start (juste avant la ligne qu'on a entré précédemment) :
- Code:
-
nbExtensions = Game.GetLoopCountForView(VUECARTES);
Il va maintenant falloir que le joueur renseigne les extensions en sa possession.
Pour cela je te laisse faire ton interface à ta convenance, moi j'imagine un écran "sélectionnez vos extensions", avec des boutons pour cliquer sur les extensions correspondantes, et un petit marqueur (sûrement un bouton non cliquable) en dessous de chaque pour indiquer les extensions sélectionnées, et ensuite un bouton "valider". Dans ce cas là, tu vas créer un event
on_click pour quand le joueur sélectionne l'extension 0, par exemple. Ça va donner un truc comme ça :
- Code:
-
function btnExt0_OnClick(GUIControl *control, MouseButton button)
{
}
Si le joueur clique sur ce bouton, alors ça veut dire qu'il ajoute l'extension à sa collection de cartes à utiliser, ou bien, si elle est déjà sélectionnée, qu'il la retire. On va donc ajouter (ou retirer) le nombre de cartes correspondant à l'extension 0 :
- Code:
-
function btnExt0_OnClick(GUIControl *control, MouseButton button)
{
if (tailleExtension[0] == 0) {
tailleExtension[0] = Game.GetFrameCountForLoop(VUECARTES, 0);
btnSelectExt0.Visible = true;
}
else {
tailleExtension[0] = 0;
btnSelectExt0.Visilbe = false;
}
}
}
Par défaut, la taille de l'extension est 0 (ne contient pas de cartes). Si on la sélectionne alors la taille de l'extension doit correspondre au nombre de cartes disponibles, qui correspond à la
loop 0 de la
view VUECARTES. On fait apparaître le bouton qui indique que l'extension est sélectionnée. Si c'est déjà le cas on fait l'inverse.
Note : Peut-être que tu veux que le jeu de base soit obligatoire, et ce serait logique. Dans ce cas tu as juste à recopier cette ligne dans le
game_start, juste après ce qu'on y a déjà ajouté :
- Code:
-
tailleExtension[0] = Game.GetFrameCountForLoop(VUECARTES, 0);
Pour les autres boutons d'extensions eh bien tu n'as plus qu'à reproduire la même chose que précédemment, en remplaçant le numéro de l'extension 0 par le numéro correspondant à chaque fois (et sur toutes les lignes !). De cette manière, tu n'auras jamais à définir la taille de chaque extension manuellement ! Ce sera automatiquement mis à jour si tu ajoute ou supprime des cartes dans la Loop correspondante.
Tout va bien ? Parfait, passons à la suite.
Les choses vont maintenant se corser. Quand le joueur clique sur "Valider", il va falloir initialiser les cartes, c'est-à-dire non seulement déterminer avec combien de cartes on va jouer au total, mais faire correspondre les cartes 0 à nbCartes-1 à leurs images respectives.
Tout ce qui va suivre est à mettre dans la fonction
on_click du bouton "Valider".
Commençons déjà par déterminer le nombre de cartes. C'est simple, il suffit d'additionner la taille de chaque extension (étant donné que celles qui n'ont pas été sélectionnées sont égales à 0). On va donc dire à AGS d'additionner les extensions jusqu'à ce qu'on y soit arrivé à bout. Pour ça, il existe un mot-clé très pratique, le mot-clé
while. Celui-ci exécute en boucle des instructions tant que les conditions sont vérifiés. On va donc partir de 0, et ajouter le nombre de cartes contenues dans l'extension 0, puis passer à 1 pour ajouter le nombre de cartes contenues dans l'extension 1, etc, et quand la valeur dépasse la dernière extension, on s'arrête. En code, ça ressemble à ça :
- Code:
-
int i = 0; //la valeur de départ
while (i < nbExtensions){ //tant que la valeur est en dessous du nombre total d'extensions existantes
nbCartes = nbCartes + tailleExtension[i]; //on ajoute le nombre de cartes correspondante
i++; //on passe à la valeur suivante
}
carte = new int[nbCartes]; //on connaît maintenant le nombre de cartes à utiliser, alors on peut mettre à jour le tableau
Maintenant qu'on connaît la taille du tableau contenant les cartes, il va falloir le remplir. Il faut imaginer un tableau dont la première colonne sera le numéro de la carte, allant de 0 à la dernière carte (8, dans notre exemple à 9 cartes avec toutes les extensions cochées), et la deuxième colonne sera le sprite correspondant à ladite carte. Le programme va remplir la deuxième colonne ligne par ligne, et pour se faire, nous allons encore une fois utiliser une boucle
while. Pour la première ligne, on doit ajouter la première carte de la première extension, donc vérifier si le joueur utilise cette extension (normalement oui si la première est obligatoire mais peu importe) donc vérifier si cette extension contient des cartes. Si elle en contient, alors on met à la première ligne la première carte de l'extension. Sinon, on passe à l'extension suivante. Pour la deuxième ligne, on passe à la carte suivante de l'extension, et ainsi de suite. Quand on arrive au bout de l'extension, on passe encore une fois à l'extension suivante. On s'arrête quand il y a autant de lignes remplies qu'il y a de cartes utilisées par le joueur.
On va donc avoir besoin d'un peu plus de variables. Il faut déjà connaître le numéro de la ligne qu'on est en train de remplir, j'ai appelé ça "numCarte" (pour numéro de la carte). Il faut aussi avoir le numéro de l'extension correspondante, que j'ai appelé "numExtension". Enfin, il faut connaître la carte à laquelle on est rendu dans l'extension en cours (est-ce qu'on est à la première carte de l'extension, à la dernière ?) afin de savoir quelle carte attribuer et de pouvoir passer à l'extension suivante quand on a fini de "scanner" la précédente. On peut déclarer ces variables en une seule ligne, comme ça :
- Code:
-
int numCarte = 0, numExtension = 0, rang = 0;
(attribuer une valeur 0 est facultatif, car c'est la valeur par défaut, mais ça permet d'y voir un peu plus clair)
Bien, maintenant qu'on a vu la théorie (encore un peu abstraite, j'entends bien) et défini les variables, on peut se lancer :
- Code:
-
while (numCarte < nbCartes){
if ((numExtension < 0) || (numExtension > nbExtensions)) AbortGame("numExtension invalide (%d)", numExtension); //Message d'erreur si on a une valeur inattendue ici. Rappel : || signifie "ou".
if (rang >= tailleExtension[numExtension]) { //Si on a fini de "scanner" l'extension en cours, alors on passe au rang 0 de l'extension suivante
numExtension++;
rang = 0;
}
while (tailleExtension[numExtension] == 0) numExtension++; //Si l'extension n'est pas utilisée, alors on passe à la suivante, et on continue jusqu'à trouver une extension utilisée.
ViewFrame* frame = Game.GetViewFrame(VUECARTES, numExtension, rang); //La carte correspondante dans la vue VUECARTES (on vient de déclarer un pointeur qui renverra une image contenue dans une Loop elle même contenue dans une View).
carte[numCarte] = frame.Graphic; //On attribue à la carte le numéro du sprite correspondant
rang++; //On passe à la carte suivante dans l'extension
numCarte++; //On passe à la ligne suivante du tableau
}//et on remonte au début du "while"
J'espère ne pas avoir fait d'erreur là dedans parce que c'est pas gagné.
Mais dans mes tests rudimentaires ça fonctionnait.
On est arrivé à la fin du code de notre bouton valider ! Je remet ici à quoi ça doit ressembler dans son ensemble :
- Code:
-
function btnValiderExtensions_OnClick(GUIControl *control, MouseButton button){
nbExtensions = Game.GetLoopCountForView(VUECARTES);
int i = 0; //la valeur de départ
while (i < nbExtensions){ //tant que la valeur est en dessous du nombre total d'extensions existantes
nbCartes = nbCartes + tailleExtension[i]; //on ajoute le nombre de cartes correspondante
i++; //on passe à la valeur suivante
}
carte = new int[nbCartes]; //on connaît maintenant le nombre de cartes à utiliser, alors on peut mettre à jour le tableau
int numCarte = 0, numExtension = 0, rang = 0;
while (numCarte < nbCartes){
if ((numExtension < 0) || (numExtension > nbExtensions)) AbortGame("numExtension invalide (%d)", numExtension); //Message d'erreur si on a une valeur inattendue ici. Rappel : || signifie "ou".
if (rang >= tailleExtension[numExtension]) { //Si on a fini de "scanner" l'extension en cours, alors on passe au rang 0 de l'extension suivante
numExtension++;
rang = 0;
}
while (tailleExtension[numExtension] == 0) numExtension++; //Si l'extension n'est pas utilisée, alors on passe à la suivante, et on continue jusqu'à trouver une extension utilisée.
ViewFrame* frame = Game.GetViewFrame(VUECARTES, numExtension, rang); //La carte correspondante dans la vue VUECARTES (on vient de déclarer un pointeur qui renverra une image contenue dans une Loop elle même contenue dans une View).
carte[numCarte] = frame.Graphic; //On attribue à la carte le numéro du sprite correspondant
rang++; //On passe à la carte suivante dans l'extension
numCarte++; //On passe à la ligne suivante du tableau
}//et on remonte au début du "while"
}
Bien sûr, il faudra que tu ajoutes ce que tu veux qu'il se passe pour le joueur quand il appuiera sur le bouton, parce que tout ça se passe en tâche de fond et le joueur aura l'impression que cliquer sur le bouton n'aura eu aucun effet.
Bien. Il ne reste plus qu'à tirer au sort les cartes et à les afficher. Ça je ne sais pas exactement comment tu vas procéder. Moi, pour mes tests j'ai fait ça en appuyant sur la touche espace, mais tu pourras adapter comme tu veux. J'ai aussi déterminé que le tirage se passerait dans la room 2. Voici comment mettre à jour l'arrière plan de la pièce en fonction du tirage :
- Code:
-
else if (keycode == eKeySpace){
if (player.Room != 2) player.ChangeRoom(2); //Si on n'est pas déjà dans la room de tirage, on s'y rend
int tirage = Random(nbCartes - 1); //Si on a 9 cartes, alors on veut obtenir une valeur entre 0 et 8.
DrawingSurface* surface = Room.GetDrawingSurfaceForBackground(); //On crée une surface de dessin nommée "surface" contenant l'arrière plan de la room.
surface.DrawImage(0, 0, carte[tirage]); //On dessine au coordonnées x = 0, y = 0, le sprite correspondant à la carte qu'on vient de tirer
surface.Release(); //On indique qu'on a fini de dessiner et on met à jour le nouvel arrière plan.
}
Note : en fait on a pas forcément besoin de
DynamicSprite, la
DrawingSurface suffit.
Plusieurs choses importantes :
1. Le nouvel arrière plan doit avoir les mêmes propriétés de couleurs que l'ancien, aussi je te conseille de mettre une carte comme arrière plan par défaut. Mais si tu veux que l'écran soit noir avant de tirer la première carte, alors ajoute comme arrière plan de base une image noire en 32 bits (si tes cartes sont elles mêmes en 32 bits).
2. Par défaut, tu auras un fondu au noir au changement de room. Tu peux changer ça dans les General Settings >> Visual >> Default transition when changing room.
3. Si une même carte est tirée deux fois de suite, on aura l'impression qu'il ne s'est rien passé. Il faudra donc trouver un moyen de contourner le problème, au minimum en ajoutant une transition (oui car, en état, toutes les cartes sont remélangées à chaque fois, hein !).
Voilà, c'était assez massif, j'en conviens, j'espère ne pas t'avoir donné mal à la tête et surtout que ça te donnera des pistes pour arriver à tes fins, et apprendre des nouvelles choses sur le code.