|
| Lancer son premier jeu | |
| | |
Auteur | Message |
---|
Arlann Cliqueur Amateur
Nombre de messages : 286
Date d'inscription : 06/04/2016
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 7:51 | |
| Ne t’excuse pas de ne pas comprendre, si tu débutes complètement en développement c’est normal que ce soit « rude » et je ne suis pas un très bon formateur. La difficulté c’est que j’essaye de comprendre ton besoin pour y apporter une solution qui me parait adaptée. Cela dit il y a d’autres approches pour arriver à faire ce que tu veux, des solutions plus simples à mettre en oeuvre que l’utilisation de Sprites dynamiques et de structures.
C’est évident qu’il faut toujours partir du plus simple pour avoir des résultats rapidement et ne pas perdre en motivation. Je ne voulais pas te perdre et surtout pas te décourager. Si tu sens que mon approche n’est pas la bonne pour toi il faut faire différemment.
Le problème lorsqu’on utilise un moteur comme AGS c’est que l’on peut être limité par les fonctions qu’il propose de base. Pour sans détacher il faut réussir à les contourner ou à les utiliser différemment. C’est ce que tu fais en utilisant l’inventaire pour afficher des personnages, ce n’est pas prévu pour ça, mais si cela répond à tes besoins de game design rien ne l’interdit. Par contre cela va demander de bricoler un peu pour construire ton interface à ta façon. L’idéal est quand même de bien connaitre l’usage normal de toutes les fonctions existantes dans AGS pour ensuite les modifier, c’est pour cela qu’il est souvent conseillé de commencer par des petits projets de P N’ C, mais il n’y a pas d’obligation.
Voici plus d’explications :
L’idée du Sprite dynamique c’est de composer une image à partir de plusieurs images. Tu utilises donc l’image de base du personnage puis d’autres images pour représenter ses états que tu positionnes où tu veux sur l’image (tu peux aussi préparer des sprites de la bonne dimension et positionner les éléments en utilisant une couche alpha sur un logiciel de dessin, pour ensuite les afficher les uns sur les autres comme des calques sans trop t’embêter avec les positions). A chaque fois que tu as besoin de changer l’état du perso, son image se re-dessine entièrement en suivant l’ordre de tes calques avec des conditions (if) de variables booléennes (true/false) - le fond (facultatif) - le perso (toujours) - un bonus (si la condition est remplie) - un malus (idem) - une goutte de sang (idem) -… (tu peux aussi afficher du texte, faire des cercles de couleurs et autres primitives…) Ton Sprite est ensuite enregistré et utilisé comme image de ton item d’inventaire. Donc si tu enlèves une blessure tu dessines tout depuis le début mais sans la blessure.
C’est une solution polyvalente mais il y a beaucoup plus simple car tu pourrais dessiner autant de Sprites qu’il existe d’états pour un personnage sur ton logiciel de dessin et choisir le Sprite à afficher en temps voulu. Tout dépend du nombre de combinaisons d’états dont tu as besoin…
Tu peux aussi utiliser les éléments que propose les GUIs pour composer ton interface en activant/désactivant des boutons qui servent d’images ou des labels pour afficher du textes. De la même façon je ne sais pas jusqu’à combien d’éléments tu vas vouloir afficher et cela peut devenir fastidieux de gérer beaucoup d’éléments de gui. Et il y a certainement une limite imposée par AGS.
Il y a sans doute d’autres solutions possibles peut être que d'autres pourront t'aider. Je te conseille d’aller au plus simple pour commencer et d’y aller progressivement.
En ce qui concerne les variables de tes personnages le raisonnement est le même, il y a plusieurs approches plus ou moins complexes selon tes besoins. Le plus simple pour commencer est de créer autant de variables que de personnages. Effectivement tu peux utiliser une int par personnage (etatwanda==0) si quelques chiffres suffisent à couvrir la totalité des combinaisons d’états. Tu peux aussi choisir d’utiliser des booléennes pour chaque état (bonus, blessure, mort…) pour avoir beaucoup de combinaisons possibles en restant lisible. Le problème c’est qu’avec beaucoup de personnages tu multiplies le nombre de variables et que si en cours de dev tu décides d’en modifier une tu peux te retrouver face à une montagne…
La structure dont je parle sert à imiter le comportement de la programmation orienté objet en construisant une classe de personnage qui contient toutes les variables et plus encore. Il suffit ensuite d’instancié un nouveau personnage pour avoir tout à disposition sous la forme if (Wanda.blessure == true) … C’est un peu impressionnant quand on débute, car il y a plein de nouveaux mot clés à apprendre mais cela devient rapidement indispensable pour simplifier son code et limiter les bugs. Il y a beaucoup de documentations sur les forums et si tu en as besoin il y aura du monde pour t’aider. Pour le moment tu peux t’en passer pour prototyper ce que tu veux faire, mais garde à l’esprit que cela existe et que cela peut te servir quand tu seras plus à l’aise. |
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 8:08 | |
| Ah, je me connecte synchro avec ta réponse D'accord, j'y vois plus clair ! C'est juste que du coup, la structure dont tu parles, ça correspond à quoi concrètement ? Une fonction personnalisée du même type que ce que j'ai pu faire pour tirer aléatoirement les cartes ? En fait, c'est une fonction qui va programmer les sprite dynamique des personnages avec des noms génériques ? Je suis bosseur, donc c'est vrai que si ça peut simplifier le code, je veux bien prendre le temps d'aborder cette option EDIT : est-ce que c'est ce genre de choses ? https://www.adventuregamestudio.co.uk/wiki/Referencing_custom_struct_types |
| | | Arlann Cliqueur Amateur
Nombre de messages : 286
Date d'inscription : 06/04/2016
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 8:15 | |
| |
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 8:29 | |
| Ah, super ! Du français OK, j'ai en plus l'impression que ça peut m'aider à simplifier le code d'un autre aspect de mon jeu. Mais bon, restons sur les personnages vu que c'est le dernier "rempart" à abattre Concernant ce que je veux faire, il faudrait pour chaque personnage : - une image de base - une variable "blessure". Si blessure == 0, pas de blessure, si blessure == 3, le personnage meurt. (et les intermédiaires, blessé une fois, blessé deux fois) - une variable "malade", avec si malade == 0, pas malade, si malade == 1 malade stade 1, si malade == 3, malade stade 3 (et l'intermédiaire, malade stade 2) - plusieurs variables de bonus (je sais pas encore combien exactement, mais on peut dire qu'il y en aura 3 : bonus1, bonus2, bonus3) - chaque variable devra être représentée par un visuel qui se pose sur l'image de base du perso (avec canal alpha, fond transparent) - sous chaque personnage, si le personnage est dans l'inventaire, des boutons sont positionnés sous lui. Un bouton "malade", un bouton "guérit", un bouton "blessure", un bouton "soigné". Chaque bouton fait +1 ou -1 à la variable concernée. Pour les bonus, pas besoin de boutons, ils apparaîtront avec des événements (genre si bonus1==1, faire apparaître "bonus1" sur l'image du perso) Je me plonge dans cette riche documentation, et si jamais t'as le temps de m'illustrer un début de ce que ça pourrait être, ce sera TOP ! Vraiment merci !! EDIT : effectivement, ça a dû me remonter le moral, car je viens de tomber sur un sujet de @Kitai qui explique comment créer des fonctions personnalisées à des objets. Grâce à ça, j'ai pu économiser des centaines de ligne de code en automatisant le comportement de certains boutons qui ont peu ou prou le même comportement (juste de probas qui changent entre eux). Donc j'avance bien dans l'apprentissage d'AGS ! https://adventuregamestudio.1fr1.net/t1069-creer-des-fonctions-pour-persos-objets-etcJ'imagine que les structures vont être un peu similaires à ce genre de fonctions personnalisées ? |
| | | Arlann Cliqueur Amateur
Nombre de messages : 286
Date d'inscription : 06/04/2016
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 10:47 | |
| - Baguettator a écrit:
- Ah, super ! Du français
Alors non ce n’est pas forcement en français… Les struct permettent effectivement d’intégrer des fonctions personnalisées qui sont un peu l’équivalent de méthodes de classes… Mais bon je suis un peu autodidacte dans le domaine et je crains d’utiliser le mauvais vocabulaire entre les langages et de t’induire en erreur. Il faut que je me replonge un peu dans AGS pour te faire un exemple, car ça fait un moment que je ne l’ai pas utilisé. J’ai aussi un peu peur de t’orienter vers une solution par forcement très friendly car AGS propose aussi de créer des propriétés personnalisées via une interface qui peuvent finalement servir à faire la même chose pour gérer les variables de plusieurs personnages, ce qui est peut être plus lisible pour commencer. Je ne trouve pas forcement de doc complète mais je crois que ce tutoriel en parle un peu. N’hésite pas à y jeter un œil et demander d’autres avis. |
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 11:02 | |
| OK, je vais regarder ça ! Si jamais j'arrive à avancer de mon côté, je vous tiens au courant. Si tu as le temps (et l'envie !) de me faire un exemple avec quelques persos (genre wanda, amy et phil), je suis preneur ! Sinon, je suis preneur de toute solution, et de tout avis, de toute personne Je creuse aussi de mon côté, et j'expérimente, mais je suis toujours à la recherche d'aide, car effectivement, je n'ai pas trouvé non plus de véritable "doc complète" |
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 11:07 | |
| En attendant, si j'ai bien compris : cela reviendrait à faire une structure par personnage (donc 50 structures dans mon cas), ou une structure "générique" pour tous les personnages, qui est appellée pour chaque perso ? |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 11:45 | |
| Pour ton problème de personnage, ton idée d'utiliser les Characters reste tout-à-fait faisable hein (et à mon avis pertinente) ! Surtout si tu veux leur attribuer un inventaire. C'est surtout pour qu'ils se "décalent" quand un meurt qu'il faut se creuser un peu la tête,mais c'est valable aussi avec d'autres méthodes. _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 11:50 | |
| Oui j'imagine bien... malheureusement je vois pas trop encore comment le réaliser, et si c'est finalement plus simple. Il faudrait utiliser plusieurs fonctions dynamiques je pense ? EDIT : c'est vrai que leur donner un inventaire ça peut être sympa. Après, peu importe la solution, je pense qu'on trouvera un moyen de faire tout ce qu'il faut. Il faut juste savoir comment réaliser tout ça. C'est un sacré casse-tête, mais ça se précise ! EDIT 2 : @valoulef : Arlann m'a indiqué le lien d'un tuto que tu avais fait. Il aborde la notion de structures et ce genre de choses qui peuvent m'être utiles ? Si oui je le regarde dans l'après-midi |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 12:24 | |
| - Baguettator a écrit:
EDIT 2 : @valoulef : Arlann m'a indiqué le lien d'un tuto que tu avais fait. Il aborde la notion de structures et ce genre de choses qui peuvent m'être utiles ? Si oui je le regarde dans l'après-midi Non c'est qu'à la fin j'aborde les propriétés personnalisées. Je saurais pas trop dire dans quelle mesure ça peut t'aider là comme ça. _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 12:45 | |
| Oh... d'accord Bon, je continue le travail ! Déjà la découverte des fonctions personnalisées me permet de simplifier grandement certains scripts, que du coup je "modernise" Est-ce que le fait d'avoir des milliers de ligne de code dans le global script ou dans le script d'une room est grave ? Je veux dire : est-ce que ça peut rendre le jeu instable ou lent ? |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 13:03 | |
| Ça dépend du contenu mais globalement AGS peut traiter plusieurs millions de lignes de code par seconde (même si ça se compte pas vraiment comme ça), donc a priori en ce qui concerne ton projet tu ne devrais pas avoir trop de problèmes. En principe l'instabilité viendrait plutôt d'un mauvais codage que d'un code long. Il faut commencer à faire gaffe par exemple si tu utilises des fonctions de dessin comme DrawPixel plusieurs centaines (voire plutôt milliers) de fois par cycles. Mais sinon ça devrait aller, surtout si le gros de ton code n'est pas censé être exécuté en continu. _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 13:11 | |
| Bon alors ça va J'imagine que le jeu peut "légèrement" ralentir s'il y a beaucoup de sprites à afficher ? Notamment vu que la résolution de mon jeu est 1920*1080, j'ai l'impression que lorsque je suis à l'écran de choix des personnages (50 boutons avec leur visage, et leur bio qui apparaît en 800*600 à côté lorsqu'on clique sur eux), le jeu est légèrement plus lent (on voit la souris qui est moins fluide). Après c'est rien, mais je voulais juste savoir si ça avait pas un impact, ces lignes de code infernales... |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 14:09 | |
| Ça par contre je sais pas. Tu peux mettre un compteur de FPS pour vérifier les performances de ton jeu : - Code:
-
int cycles; int FPS; DateTime* date1; DateTime* date2;
function repeatedly_execute{ cycles++; date2 = date1; date1 = DateTime.Now; if (date1.Second != date2.Second){ FPS = cycles; cycles = 0; } } Après tu n'as plus qu'à afficher la variable "FPS" dans un label. Tu peux aussi faire varier SetGameSpeed pour vérifier si ton jeu peut monter au delà des 40 fps. _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 14:15 | |
| Je vais regarder ça. APrès c'est peut-être juste que lorsqu'on test le jeu via AGS, le jeu est plus lent ? Bon après quand je disais qu'il était "légèrement plus lent", c'était pas grand chose, mais je vérifierai, merci pour l'astuce !
Concernant le placement des personnages, si j'utilise des Characters, je devrai faire quelque chose de similaire à la sélection des cartes ? Un tableau dynamique qui place les personnages les uns après les autres, et si certains disparaissent, ça décale ceux d'après ? |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 14:30 | |
| Je ne crois pas avoir remarqué de baisse particulière de performance quand on lance le jeu via AGS. Concernant les personnages, je ne peux pas te répondre en détails maintenant parce qu'il faudrait que j'y réfléchisse plus, mais en gros si tu utilises les Characters je pense qu'il faut que tu détermines quel est le personnage 0 (le plus à gauche), puis le 1, le 2 etc... Et que tu définisse une valeur x pour chacun (toujours la même pour le 0, toujours la même pour le 1, etc). Ensuite il faut mettre à jour qui est le personnage situé à chaque position dès qu'il y en a un qui meurt. Pour ceux qui n'existent plus (par ex le personnage 5 après un mort), tu peux jouer avec la valeur "null", ou alors créer un personnage transparent qui représentera un personnage non existant, par exemple. Tu peux créer des tableaux (pas forcément dynamiques) de Characters en les déclarant comme ça (pour un tableau de 6 personnages) : - Code:
-
Character* persoJoueur[6]; L'idée d'utiliser une fenêtre d'inventaire marcherait bien pour se point là en le simplifiant mais ça me ferait un peu peur perso... Ça me semble moins souple (les clics sur les fenêtres d'inventaires sont gérés de manière spécifique et un peu bizarre par AGS, entre autres). Après peut-être que ça se teste, mais à la place de devoir gérer manuellement les positions, tu devras sûrement faire plus de programmation pour changer les sprites. _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 14:48 | |
| OK, je vais me pencher là-dessus, merci J'ai essayé de mettre en place le compteur de FPS, mais le jeu plante, il me dit que la ligne date1.Second != date2.Second) est une null reference... Tu as fait une erreur dans le code ? J'ai déclaré les int en haut du global script, le reste j'ai mis dans la function_repeatedly_execute. Peut-être j'ai mal fait quelque chose ? Les DateTime sont peut-être mal placés ? |
| | | Arlann Cliqueur Amateur
Nombre de messages : 286
Date d'inscription : 06/04/2016
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 14:53 | |
| J'ai fait un exemple avec une struct, je vais essayer de te le détailler au maximum pour que tu comprennes comment cela fonctionne. Dans un 1er temps j'ai fait un script Struct_Personnageavec dans le script header (l'entête lisible par tous les scripts) - Code:
-
// Struc_Personnage.ash
#define TOTAL_PERSONNAGES 50 // Une constante pour définir le nombre max de perso du jeu
struct Personnage { String Nom; // Pour avoir le nom sous forme de string bool bonus1, bonus2, bonus3; // des variables simples int CHAR_SPRITE_SLOT; // Le slot qui contient le sprite original du personnage DynamicSprite* spriteDynamic; // Si besoin pour composer une image avec plusieurs sprites
// un exemple de variables gérées par la struct grâce à des Get/Set import attribute int Blessure, Maladie; // L'usage de ces variables est protégé par la struct protected int blessure, maladie; import attribute bool Mort; protected bool mort; // les fonctions suivantes sont internes à la struct, elles ne peuvent pas être appeler directement import int get_Blessure(); // $AUTOCOMPLETESTATICONLY$ import void set_Blessure(int _blessure); // $AUTOCOMPLETESTATICONLY$ import int get_Maladie(); // $AUTOCOMPLETESTATICONLY$ import void set_Maladie(int _maladie); // $AUTOCOMPLETESTATICONLY$ import bool get_Mort(); // $AUTOCOMPLETESTATICONLY$ import bool set_Mort(); // $AUTOCOMPLETESTATICONLY$
// des exemples de fonctions personnalisées import void GagneUnBonus(); import void ResetVariables(); };
import Personnage personnage[TOTAL_PERSONNAGES]; puis dans le corps de script : - Code:
-
// Struct_Personnage.asc
// Instanciation d'un tableau de tous les personnages Personnage personnage[TOTAL_PERSONNAGES];
// retourne simplement la valeur de blessure int Personnage::get_Blessure() { return this.blessure ; }
// modifie la valeur de blessure selon tes propres règles void Personnage::set_Blessure(int _blessure) { this.blessure = _blessure; if ( this.blessure < 0 ) this.blessure = 0; // empêche la variable de passer en négatif if ( this.blessure >= 3 ) { this.blessure = 3; // Limite la variable à 3 maximum this.mort = true ; // déclenche la mort à ce nombre de blessure } else this.mort = false ; // S'assure que le perso n'est pas mort en dessous de 3 blessures }
// idem pour les maladies int Personnage::get_Maladie() { return this.maladie ; }
void Personnage::set_Maladie(int _maladie) { this.maladie = _maladie; if ( this.maladie <0 ) this.maladie = 0; if ( this.maladie >=3 ) this.maladie = 3; }
// retourne simplement la valeur de mort bool Personnage::get_Mort() { return this.mort ; } // ne fait rien, la mort est seulement déclenchée par une blessure de niveau 3 (c'est juste un exemple d'utilisation) bool Personnage::set_Mort() { }
// exemple d'une fonction à appeler d'un script pour gagner un bonus void Personnage::GagneUnBonus() { if (!this.bonus1) this.bonus1=true; else if (!this.bonus2) this.bonus2=true; else if (!this.bonus3) this.bonus3=true; }
// exemple d'une fonction à appeler d'un script pour faire un reset void Personnage::ResetVariables() { this.maladie = 0; this.blessure = 0; this.mort= false; this.bonus1 = false; this.bonus2 = false; this.bonus3 = false; }
// permet d’accéder au tableau "personnage" depuis les autres scripts export personnage; J'ai ensuite créé un autre script Fiche_Personnages juste en dessous (c'est important qu'il puisse hériter du script du dessus) J'utilise ce script pour créer les personnages avec dans le corps de script : - Code:
-
// Fiche_Personnages.asc
void CreationPersonnages(int ID) { // Pour l'exemple je reset toutes les variables, même si ce n'est pas vraiment utile au départ personnage[ID].ResetVariables(); personnage[ID].Nom = "UNKNOW"; // C'est juste pour éviter d'avoir un bug si le nom reste vide, car AGS utilises des pointeurs au lieu de string // Je donne ensuite les valeurs de tous les personnages if (ID==0){ personnage[ID].Nom = "Wanda"; personnage[ID].CHAR_SPRITE_SLOT = 1 ; // Le slot du sprite importé // toutes les autres caractéristiques du personnage sont à ajouter ici. } else if (ID==1){ personnage[ID].Nom = "Amy"; personnage[ID].CHAR_SPRITE_SLOT = 2 ; // Le slot du sprite importé } else if (ID==2){ personnage[ID].Nom = "Phil"; personnage[ID].CHAR_SPRITE_SLOT = 3 ; // Le slot du sprite importé } //....jusqu'à if (ID==49) }
//La fonction suivante est automatiquement lancée par AGS au lancement du jeu function game_start() { // Je parcours une boucle au départ du jeu pour initialiser tous les personnages for ( int i=0 ; i < TOTAL_PERSONNAGES ; i++) CreationPersonnages(i); } Maintenant je passe dans mon global script (ou dans un autre script dédié mais toujours en dessous des 2 autres) - Code:
-
// main global script file // Je créé une variable pour contenir l'ID d'un personnage int playerID = 0 ; // Tu peux donc changer cette ID à tout moment pour sélectionner un autre personnage dans le tableau des 50 créés. // Tu dois aussi créer d'autres variables du même type pour gérer plusieurs personnages en même temps.
// called when a key is pressed function on_key_press(eKeyCode keycode) { // je fais varier l'id du joueur en appuyant sur J if (keycode == 'J') { if ( playerID < TOTAL_PERSONNAGES-1 ) playerID++; else playerID=0; } // j'augmente la blessure avec b else if (keycode == 'B') { personnage[playerID].Blessure++; } // la maladie avec m else if (keycode == 'M') { personnage[playerID].Maladie++; } // pour faire un Reset (appel une fonction de la struct) else if (keycode == 'R') { personnage[playerID].ResetVariables(); } // pour gagner un bonus (appel une fonction de la struct) else if (keycode == 'G') { personnage[playerID].GagneUnBonus(); } } J'ai utilisé le clavier pour modifier les variables mais c'est le même principe avec des inputs de boutons. Toujours dans le global script, j'ai simplement créé un GUI avec un label et un button pour afficher le résultat : - Code:
-
// called on every game cycle, except when the game is blocked function repeatedly_execute() { // J'affiche toutes les variables du personnage joué dans un label Label1.Text = String.Format("%s blessure :%d maladie :%d mort :%d bonus1 :%d bonus1 :%d bonus1 :%d", personnage[playerID].Nom, personnage[playerID].Blessure, personnage[playerID].Maladie, personnage[playerID].Mort, personnage[playerID].bonus1, personnage[playerID].bonus2, personnage[playerID].bonus3 ); // J'affiche son image dans un bouton Button1.NormalGraphic = personnage[playerID].CHAR_SPRITE_SLOT; // ou dans un item c'est le même principe à toi de voir iInvItem1.Graphic = personnage[playerID].CHAR_SPRITE_SLOT; } Pour afficher l'image sur un character il faudra surement faire une petite manip car je crois qu'ils n'utilisent que des views. Cela dit tu peux peut utiliser une view au lieu d'un slot de sprite si tu ne veux pas t’embêter avec des sprites dynamiques et cela règle le problème. A noter que j'ai choisi d’utiliser un tableau personnage (en minuscule) pour créer des Personnage (en majuscule) par facilité car tu comptes utiliser beaucoup de personnages. Il te suffit de choisir une ID du tableau ou de le parcourir avec une boucle au besoin ce qui peut faire économiser beaucoup de lignes de code... Mais tu peux tout à fait utiliser des pointeurs avec des noms différents si tu en as peu à manipuler et que tu veux gagner en lisibilité par exemple: - Code:
-
Personnage Wanda; Personnage Amy; Personnage Phil; // Au lieu de Personnage personnage[TOTAL_PERSONNAGES];
Et tu peux créer ces Personnage en local dans un script sans les fonctions export/import si tu n'en as besoin qu'à cet endroit. J'espère que cela te donne une vision d'ensemble du potentiel, il y a peut être des erreurs de syntaxe dans mon exemple car c'est un peu loin mais c'est marrant de remettre les mains dans AGS ! Bon courage. |
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 15:26 | |
| Whaoo c'est TOP ! Merci beaucoup ! J'ai compris beaucoup de choses rien qu'en le lisant !
Quand tu dis : "Maintenant je passe dans mon global script (ou dans un autre script dédié mais toujours en dessous des 2 autres) ", qu'entends-tu par "en-dessous" ? Quand je déroule mon onglet "script", il y a "TwoClickHandler", puis "GlobalScript". Du coup je dois créer les deux scripts que tu as dis, et je les déplace pour qu'ils soient au-dessus de "Globalscript" dans la liste de l'onglet "Script" ? |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 15:35 | |
| - Baguettator a écrit:
- J'ai déclaré les int en haut du global script, le reste j'ai mis dans la function_repeatedly_execute. Peut-être j'ai mal fait quelque chose ? Les DateTime sont peut-être mal placés ?
Les DateTime doivent être déclarés en haut du script, tout comme les int. Edit : Ah et effectivement il faut définir "date1" la première fois, par exemple dans la fonction game_start : - Code:
-
function game_start(){ date1 = DateTime.Now; } _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 15:46 | |
| @valoulef : c'est bien ce que j'avais fait, donc merci ! Je vais définir date1 @Arlann (enfin à tout le monde quand même !) : Alors, après avoir réfléchi, je me demande une chose : si je fais en sorte que les personnages soient des Characters (et pas des inventory items comme on avait pu y réfléchir plus tôt), est-ce que je peux pas utiliser les différentes loops pour montrer leur état ? Si j'ai bien compris, un personnage utilise différents sprites selon les directions qu'il emprunte. Chaque direction de mouvement correspond à une loop, et on peut en avoir 8 maxi : droite, gauche, bas, haut, et les quatre diagonales. + la position sur place, qui est sa sprite "de base". Du coup, j'imagine qu'on pourrait faire une "simulation de mouvement sans mouvement" : on dit au personnage qu'il bouge alors qu'il ne bouge pas. Du coup, comme j'ai deux états blessures (la troisième blessure le tue) et deux états maladie : - sur place : bonne santé - haut : blessé 1 - bas : blessé 2 - gauche : malade 1 - droite : malade 2 - diagonale haut+gauche : blessé 1 ET malade 1 - diagonale haut + droite : blessé 1 ET malade 2 - diagonale bas + gauche : blessé 2 ET malade 1 - diagonale bas + droite : blessé 2 ET malade 2 A chaque direction correspond une sprite qui rend compte de l'état (ou des états) du personnage ! Il faudrait juste que ce soit possible de lui donner la sprite de déplacement, sans qu'il se déplace réellement... Et il ne change de direction que quand il change d'état ! Vous pensez que c'est possible ? |
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 16:06 | |
| @valoulef : de base, je tournai autour des 40 fps au menu principal (le premier truc qui apparaît quand on démarre le jeu), du coup j'ai fait varier le "GameSpeed", et je crois que ça ne monte pas au-dessus des 300 (j'ai mis GameSpeed à 500). Donc c'est beaucoup plus fluide qu'avant, ça tourne aux environs de 250 en moyenne, mais seul dommage : les transitions fondues sont ECLAIRS !!! EDIT : peut-être parce que j'ai changé le curseur de souris, et que j'ai mis une GRANDE image ! Elle fait 252*267 pixels, je l'ai mise pour tester le changement de curseur, et je l'ai laissée car je trouvais ça rigolo. Du coup, comme c'est une grande image, ça demande peut-être beaucoup d'efforts à gérer ? Bon, c'était prévu que j'en mette une plus petite au final |
| | | Arlann Cliqueur Amateur
Nombre de messages : 286
Date d'inscription : 06/04/2016
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 17:04 | |
| - Baguettator a écrit:
- Si j'ai bien compris, un personnage utilise différents sprites selon les directions qu'il emprunte. Chaque direction de mouvement correspond à une loop, et on peut en avoir 8 maxi : droite, gauche, bas, haut, et les quatre diagonales. + la position sur place, qui est sa sprite "de base".
En fait tu n’as quasiment aucune limitation à utiliser des views pour ce que tu veux faire, car tu peux créer plus de 8 loops par View, tu peux assigner n’importe quelle frame en image fixe depuis une loop et tu peux également changer de View si cela ne suffisait pas. EDIT : La fonction qui va bien LockViewFrame - Baguettator a écrit:
- Quand tu dis : "Maintenant je passe dans mon global script (ou dans un autre script dédié mais toujours en dessous des 2 autres) ", qu'entends-tu par "en-dessous" ? Quand je déroule mon onglet "script", il y a "TwoClickHandler", puis "GlobalScript". Du coup je dois créer les deux scripts que tu as dis, et je les déplace pour qu'ils soient au-dessus de "Globalscript" dans la liste de l'onglet "Script" ?
Oui c'est ça, tu peux créer autant de scripts que tu veux c’est même conseillé pour garder une bonne lisibilité sur ton projet. Pour l’organisation tu peux les ranger dans des dossiers. La seule limitation un peu embêtante d’AGS est qu’un script qui appelle un autre script doit forcement se trouver en dessous dans l’arborescence. Tu peux utiliser le drag and drop pour les organiser. Le global script est le seul qui est indispensable à AGS, il se situe forcement en dernier mais avant ceux des rooms (oui c’est un peu le bordel dit comme ça…) Le « TwoClickHandler » doit venir du template que tu as choisi pour ton projet.
Dernière édition par Arlann le Ven 5 Juin 2020 - 18:20, édité 1 fois |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 17:51 | |
| - Baguettator a écrit:
- @valoulef : de base, je tournai autour des 40 fps au menu principal (le premier truc qui apparaît quand on démarre le jeu), du coup j'ai fait varier le "GameSpeed", et je crois que ça ne monte pas au-dessus des 300 (j'ai mis GameSpeed à 500). Donc c'est beaucoup plus fluide qu'avant, ça tourne aux environs de 250 en moyenne, mais seul dommage : les transitions fondues sont ECLAIRS !!!
SetGameSpeed peut être réglé jusqu'à 1000 fps, mais c'est purement théorique. En pratique, je crois que je n'ai jamais beaucoup dépassé les 300 fps, et le fait d'avoir un PC plus puissant n'y a rien changé (à confirmer, je ne sais plus trop ce que j'ai testé). AGS reste relativement lent par rapport à du Python ou du C++ (de ce que j'ai compris). De toute façon je te conseille de ne pas aller au delà des 120 fps parce que la plupart des écrans n'en afficheront pas plus (la majorité est même limitée à 60*), et on ne devrait de toute façon pas voir la différence. Pour gérer la vitesse des transitions, tu peux utiliser FadeOut et FadeIn à la place, même si c'est un peu plus fastidieux. *Je parle ici d'images affichées à l'écran, cela n'empêchera pas le jeu de tourner sur 300 cycles par seconde, mais je ne pense pas que ça ait un intérêt dans ton cas (et risque de solliciter inutilement le processeur). _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Baguettator Cliqueur Amateur
Nombre de messages : 232
Date d'inscription : 21/05/2020
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 19:36 | |
| Merci pour vos réponses ! Il y a deux sujets en parallèle @Arlann : OK, je vois, effectivement, on dirait que celui qui a créé AGS a pensé à tout... Du coup, ça va peut-être m'obliger à créer une sprite par combinaison d'état du personnage, mais y en aura pas tant que ça, si je garde seulement 2 niveaux de blessures et 2 niveaux de maladie ! Par ailleurs, si je mets au point une fonction qui permet de placer les persos dans l'ordre en bas de l'écran, je vais peut-être pouvoir l'intégrer à la structure "personnage" pour qu'elle soit constamment mise à jour ? Je vais me pencher là-dessus et je te tiens au courant de mes "prouesses" ! @valoulef : OK, je vais par exemple la fixer à 120. Voire j'ai lu qu'on pouvait activer la Vsynch qui fixe automatiquement à la fréquence d'affichage de l'écran (60 dans la plupart des cas), c'est peut-être un moyen de "stabiliser" le jeu ? |
| | | valoulef Délégué de la tasse bleue
Nombre de messages : 1791
Age : 35
Localisation : Condate
Date d'inscription : 01/08/2011
| Sujet: Re: Lancer son premier jeu Ven 5 Juin 2020 - 20:01 | |
| La v-sync permet normalement d'éviter les problèmes d'affichage lié au fait que le débit du jeu est supérieur à celui de l'écran (ce qui peut engendrer un décalage où le haut de l'écran affiche l'image 0 tandis que le bas de l'écran affiche l'image 1, créant des sortes de lignes désagréables, par exemple lors d'un scrolling). Dans ton cas, où le jeu est peu ou pas animé, je ne pense pas que ça change grand chose. À noter que je ne suis pas sûr que ça fixe automatiquement à la fréquence d'affichage de l'écran, il me semble que généralement ça fixe la fréquence à 60, mais je peux me tromper. Je pense qu'il faut pas trop te tracasser avec ce genre de détails tant que le résultat te convient. _________________ Vous êtes déjà allés à Condate ? Ils ont un petit vin qui à un goût de pierre à catapulte. C'est Toutatis en culotte de velours si j'ose m'exprimer ainsi.
|
| | | Arlann Cliqueur Amateur
Nombre de messages : 286
Date d'inscription : 06/04/2016
| Sujet: Re: Lancer son premier jeu Sam 6 Juin 2020 - 12:03 | |
| Oui il y a 2 sujets qui ce sont superposés c'est un peu embêtant, désolé d'en ajouter une couche mais comme j'étais lancé autant que je partage la suite ! Je sais que tu comptes utiliser les views des characters pour afficher tes états de personnages, c'est une solution tout à fait viable donc ne te focalises pas si je suis un peu têtu avec mes sprites dynamiques Je voulais simplement te montrer qu'avec cette struct de personnages tu peux automatiser beaucoup de choses afin gérer les nombreuses combinaisons d'état et de personnages. Cela dit, si tu comprends comment cela fonctionne tu pourras appliquer le même principe avec des Views. J'ai donc ajouté une fonction dans la struct pour composer une image d'avatar, tu la vois à la fin du header : - Code:
-
// Struc_Personnage.ash
#define TOTAL_PERSONNAGES 50 // Une constante pour définir le nombre max de perso du jeu
struct Personnage { String Nom; // Pour avoir le nom sous forme de string bool bonus1, bonus2, bonus3; // des variables simples int CHAR_SPRITE_SLOT; // Le slot qui contient le sprite original du personnage
DynamicSprite* spriteDynamic; // Pour composer l'image des avatars
// un exemple de variables gérées par la struct grâce à des Get/Set import attribute int Blessure, Maladie; // L'usage de ces variables est protégé par la struct protected int blessure, maladie; writeprotected bool Mort; // EDIT : J'ai changé cette variable en "protégée en écriture" car elle ne peut être modifiée que par la struct elle même // les fonctions suivantes sont internes à la struct, elles ne peuvent pas être appelées directement import int get_Blessure(); // $AUTOCOMPLETESTATICONLY$ import void set_Blessure(int _blessure); // $AUTOCOMPLETESTATICONLY$ import int get_Maladie(); // $AUTOCOMPLETESTATICONLY$ import void set_Maladie(int _maladie); // $AUTOCOMPLETESTATICONLY$
// des exemples de fonctions personnalisées import void GagneUnBonus(); import void ResetVariables();
import void UpdateSprite(); // La nouvelle fonction pour mettre à jour les images des avatars };
import Personnage personnage[TOTAL_PERSONNAGES]; La fonction est détaillée dans le corps du script , tu peux voir que je l'appelle depuis les autres fonctions de la struct et depuis les "Setters" des variables Blessure et Maladie - Code:
-
// Struct_Personnage.asc
// Instanciation d'un tableau de tous les personnages Personnage personnage[TOTAL_PERSONNAGES];
// La nouvelle fonction pour mettre à jour les images des avatars void Personnage::UpdateSprite() { // Copie l'image originale du perso dans son sprite dynamique this.spriteDynamic = DynamicSprite.CreateFromExistingSprite(this.CHAR_SPRITE_SLOT); // ouvre une surface de dessin pour ajouter des logos par dessus l'image de base DrawingSurface *surface = this.spriteDynamic.GetDrawingSurface(); // Si le joueur est mort on affiche un logo pour le signifier if (this.Mort) { surface.DrawImage(POS_X, POS_Y, IMAGE_MORT); // Les positions et le slot du sprite sont à définir } else // s'il n'est pas mort on dessine un logo par état { // Ajoute un logo de blessure // Les positions et le slot du sprite sont à définir if ( this.blessure==1 ) surface.DrawImage(POS_X, POS_Y, IMAGE_BLESSURE1); else if ( this.blessure==2 ) surface.DrawImage(POS_X, POS_Y, IMAGE_BLESSURE2); else if ( this.blessure==3 ) surface.DrawImage(POS_X, POS_Y, IMAGE_BLESSURE3); // Ajoute un logo de maladie // Les positions et le slot du sprite sont à définir if ( this.maladie==1 ) surface.DrawImage(POS_X, POS_Y, IMAGE_MALADIE1); else if ( this.maladie==2 ) surface.DrawImage(POS_X, POS_Y, IMAGE_MALADIE2); else if ( this.maladie==3 ) surface.DrawImage(POS_X, POS_Y, IMAGE_MALADIE3); // Ajoute les logos de bonus // Les positions et le slot du sprite sont à définir if ( this.bonus1 ) surface.DrawImage(POS_X, POS_Y, IMAGE_BONUS1); if ( this.bonus2 ) surface.DrawImage(POS_X, POS_Y, IMAGE_BONUS2); if ( this.bonus3 ) surface.DrawImage(POS_X, POS_Y, IMAGE_BONUS3); } // On peut ajouter le nom du perso sur l'image // Les positions, la couleur et la police sont à définir surface.DrawingColor = COULEUR_DE_TEXTE; surface.DrawString(POS_X, POS_Y, Game.NormalFont, this.Nom );
// ferme la surface de dessin surface.Release(); }
// retourne simplement la valeur de blessure int Personnage::get_Blessure() { return this.blessure ; }
// modifie la valeur de blessure selon tes propres règles void Personnage::set_Blessure(int _blessure) { this.blessure = _blessure; if ( this.blessure < 0 ) this.blessure = 0; // empêche la variable de passer en négatif if ( this.blessure >= 3 ) { this.blessure = 3; // Limite la variable à 3 maximum this.Mort = true ; // déclenche la mort à ce nombre de blessure } else this.Mort = false ; // S'assure que le perso n'est pas mort en dessous de 3 blessures this.UpdateSprite(); // Met à jour l'avatar à chaque fois que la variable est modifiée }
// idem pour les maladies int Personnage::get_Maladie() { return this.maladie ; }
void Personnage::set_Maladie(int _maladie) { this.maladie = _maladie; if ( this.maladie <0 ) this.maladie = 0; if ( this.maladie >=3 ) this.maladie = 3; this.UpdateSprite(); // Met à jour l'avatar à chaque fois que la variable est modifiée }
// exemple d'une fonction à appeler d'un script pour gagner un bonus void Personnage::GagneUnBonus() { if (!this.bonus1) this.bonus1=true; else if (!this.bonus2) this.bonus2=true; else if (!this.bonus3) this.bonus3=true;
this.UpdateSprite(); // Met à jour l'avatar à chaque utilisation de cette fonction }
// exemple d'une fonction à appeler d'un script pour faire un reset void Personnage::ResetVariables() { this.maladie = 0; this.blessure = 0; this.Mort= false; this.bonus1 = false; this.bonus2 = false; this.bonus3 = false; if ( this.Nom==null ) this.Nom = "UNKNOW"; this.UpdateSprite(); // Met à jour le sprite dynamique }
// permet d’accéder au tableau "personnage" depuis les autres scripts export personnage; J'ai également besoin de l'appeler une première fois au début du jeu quand les personnages sont créés. - Code:
-
// Fiche_Personnages.asc
void CreationPersonnages(int ID) { // J'initialise toutes les variables une première fois personnage[ID].ResetVariables(); // Je donne ensuite les valeurs de tous les personnages if (ID==0){ personnage[ID].Nom = "Wanda"; personnage[ID].CHAR_SPRITE_SLOT = 1 ; // Le slot du sprite importé // toutes les autres caractéristiques du personnage sont à ajouter ici. } else if (ID==1){ personnage[ID].Nom = "Amy"; personnage[ID].CHAR_SPRITE_SLOT = 2 ; // Le slot du sprite importé } else if (ID==2){ personnage[ID].Nom = "Phil"; personnage[ID].CHAR_SPRITE_SLOT = 3 ; // Le slot du sprite importé } //....jusqu'à if (ID==49)
personnage[ID].UpdateSprite(); // J'appelle la fonction une première fois pour créer les sprites dynamiques des avatars }
//La fonction suivante est automatiquement lancée par AGS au lancement du jeu function game_start() { // Je parcours une boucle au départ du jeu pour initialiser tous les personnages for ( int i=0 ; i < TOTAL_PERSONNAGES ; i++) CreationPersonnages(i); } Désormais il faut utiliser le sprite dynamique comme image du bouton qui permet d'afficher l'avatar du personnage joué. - Code:
-
int playerID ; // l'ID du perso à afficher
// called on every game cycle, even when the game is blocked function late_repeatedly_execute_always() { Button1.NormalGraphic = personnage[playerID].spriteDynamic.Graphic; } L’intérêt de tout ça est dans un premier de temps de gagner du temps car tu n'as plus besoin de composer plusieurs sprites d'état multipliés par le nombre de personnages. C'est également de ne plus te soucier de chercher l'image qui correspond à ton état de joueur car il suffit de faire : - Code:
-
personnage[playerID].Blessure++; ou - Code:
-
personnage[playerID].Maladie--; pour que l'image de l'avatar change automatiquement et cela va te simplifier le reste de ton code. A noter que pour bien faire dans mon exemple il faudrait passer les variables de bonus en Attribute comme Blessure et Maladie, car actuellement l'image est mise à jour seulement par la fonction GagneUnBonus() mais pas si tu fais : - Code:
-
personnage[playerID].bonus1=true; Tu peux bien entendu utiliser la fonction UpdateSprite(); à la suite mais ce n'est pas vraiment le but... J'espère que tu comprends la différence et l’intérêt que cela apporte, si c'est le cas tu vas aussi pouvoir automatiser l'usage de tes views assez facilement. Bon courage avec tout ça !
Dernière édition par Arlann le Sam 6 Juin 2020 - 18:43, édité 1 fois |
| | | Contenu sponsorisé
| Sujet: Re: Lancer son premier jeu | |
| |
| | | | Lancer son premier jeu | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |