Forum d'entraide à la création de jeux d'aventure
 
PortailAccueilFAQRechercherS'enregistrerMembresConnexion

Partagez | 
 

 [Résolu]Du codage d'un While_KeyPressed.

Voir le sujet précédent Voir le sujet suivant Aller en bas 
AuteurMessage
Billbis
Disciple de la Grande Tasse Bleue
Disciple de la Grande Tasse Bleue


Nombre de messages : 1275

Date d'inscription : 10/05/2012


MessageSujet: [Résolu]Du codage d'un While_KeyPressed.   Mer 21 Nov 2012 - 18:40

Ou : De la meilleure façon d'afficher un Overlay TANT que la Barre d'espace est enfoncé.

Bonjour à tous,

Je me suis mis en tête de vouloir afficher un Overlay tant qu'une touche du clavier est enfoncé ; et de l'effacer après, donc. C'est pour un module, donc le code en question doit être relativement portable. Je me demandais donc quelle était la solution la plus élégante à cet amusant problème, et je me disait que je pouvais vous faire part et soumettre à votre jugement mes réflexions que voici :

La solution 1 : Tricher

Code:
function on_key_press(eKeyCode keycode)
{
  if (keycode == eKeySpace)
  {
    Overlay* siaoverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
    Wait(40);
    siaoverlay.Remove();
  }
}
Avantages : hyper portable, simple, ne consomme rien ni en ressources, ni en objets limités.
Inconvénients : on ne répond pas au problème donné. L'overlay est affiché une seconde à la pression de la barre d'espace, puis disparait. Si le joueur appuis plusieurs secondes sur la barre d'espace, l'overlay scintillera toute les secondes.

La solution 2 : rajouter un timer et du repeatedly_execute()

Code:
function on_key_press(eKeyCode keycode)
{
  if (keycode == eKeySpace)
  {
    Overlay* siaoverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
  }
}

function repeatedly_execute()
{
  if (IsKeyPressed(eKeySpace))
  {
    SetTimer(sia_TIMER_ID, 5); // J'ai mis 5 par sécurité, mais 1 ça devrais marcher aussi.
  }
 
  if (IsTimerExpired(sia_TIMER_ID))
  {
    siaoverlay.Remove();
  }
}
Avantages : relativement simple, élégant, répond au problème donné.
Inconvénients : Consomme un poil plus de ressource, et consomme un timer ! Ne fonctionne pas, AGS nous insulte car il n'arrive pas a accéder à siaoverlay dans le repeatedly_execute() car il est défini dans le function on_key_press

La solution 3 : Solution 2 + jouer avec les IMPORT / EXPORT

Avantages : pareille que 2 + AGS nous insulte plus
Inconvénients : Consomme un timer, et surtout j'y comprend rien aux Import / Export malgrès les tutos de Kitai et je ne sais pas comment coder ça.

La solution 4 : Solution 2 + Déclarer l'overlay dans le script header

Code:
Overlay* siaOverlay

function on_key_press(eKeyCode keycode)
{
  if (keycode == eKeySpace)
  {
    siaOverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
  }
}

function repeatedly_execute()
{
  if (IsKeyPressed(eKeySpace))
  {
    SetTimer(sia_TIMER_ID, 2); // J'ai mis 2 par sécurité, mais 1 ça devrais marcher aussi.
  }
 
  if (IsTimerExpired(20))
  {
    siaOverlay.Remove();
  }
}

Avantages : relativement simple, élégant, répond au problème donné, fonctionne sour AGS.
Inconvénients : Consomme un poil plus de ressource, et consomme un timer !

La solution 5 : remplacer les timers par des DateTime.Now() et faire tout un bazar pour que ça marche comme je veux que sa marche.

Code:
Overlay* siaOverlay
DateTime *siadt
DateTime *siadt1;
int siaButtonDownDT = 0;
DateTime *siadt2;
bool siaBool = false;

function on_key_press(eKeyCode keycode)
{
  if (keycode == eKeySpace)
  {
    siaOverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
  }
}

function repeatedly_execute()
{
  siadt1=DateTime.Now;
 
  if (IsKeyPressed(eKeySpace))
  {
    siadt2 = DateTime.Now;
    siaButtonDownDT = siadt2.RawTime;
    siaBool = true;
  }
 
  if ((siadt1.RawTime - siaButtonDownDT) == 1)
  {
    siaoverlay.Remove();
    siasprite.Delete();
    siaBool = false;
  }
}

Avantages : répond au problème donné, ne consomme pas de timer.
Inconvénients : Complexe, usine à gaz, consomme plein de ressources, laisse un délai d'une seconde avant disparition de l'overlay. Délai sans doute incompressible.

Personnellement, je pense que je vais plutôt partir sur la solution 4, mais je serais ravis d'avoir vos avis, vos conseils, vos optimisations...

EDIT : Hihi, en fait ma solution 4 ne fonctionne pas :
ShowInteractiveArea.asc(113): Error (line 113): undefined symbol 'sia_TIMER_ID'
il faut que je l'exporte. Je vais essayer de corriger ça.
(En fait, il faut juste mettre un nombre entre 1 et 20. J'avais oublié de définir cette variable dans mon .asc.)

_________________
Mon petit DevBlog


Dernière édition par Billbis le Ven 30 Nov 2012 - 16:24, édité 1 fois
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nothingaboutthedog.blogspot.fr/
Kitai
Délégué de la tasse bleue
Délégué de la tasse bleue


Nombre de messages : 2431

Date d'inscription : 01/08/2006


MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Jeu 22 Nov 2012 - 9:41

Billbis a écrit:
Inconvénients : on ne répond pas au problème donné. L'overlay est affiché une seconde à la pression de la barre d'espace, puis disparait. Si le joueur appuis plusieurs secondes sur la barre d'espace, l'overlay scintillera toute les secondes.
Concernant la solution 1, donc.
Je ne pense pas qu'il y aura scintillement : le calque s'effacera simplement après 40 cycles et ne se réaffichera que lorsque le joueur appuiera à nouveau sur la touche espace.
À noter que la commande Wait va bloquer le reste de l'exécution du jeu (à part reapeatedly_execute_always bien sûr) pendant 40 cycles.

Billbis a écrit:
La solution 3 : Solution 2 + jouer avec les IMPORT / EXPORT

Avantages : pareille que 2 + AGS nous insulte plus
Inconvénients : Consomme un timer, et surtout j'y comprend rien aux Import / Export malgrès les tutos de Kitai et je ne sais pas comment coder ça.
En fait je ne vois pas vraiment l'intérêt de jouer avec des IMPORT/EXPORT : l'intérêt de ces procédures est de partager des variables/fonctions avec d'autres scripts, et toi tu veux tout gérer depuis le script de ton module.

Billbis a écrit:
La solution 4 : Solution 2 + Déclarer l'overlay dans le script header

Code:
Overlay* siaOverlay

function on_key_press(eKeyCode keycode)
{
  if (keycode == eKeySpace)
  {
    siaOverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
  }
}

function repeatedly_execute()
{
  if (IsKeyPressed(eKeySpace))
  {
    SetTimer(sia_TIMER_ID, 2); // J'ai mis 2 par sécurité, mais 1 ça devrais marcher aussi.
  }
 
  if (IsTimerExpired(20))
  {
    siaOverlay.Remove();
  }
}
Là tu ne définis pas le calque dans l'en-tête, tu le définis simplement tout en haut du corps du script (le fichier .asc).
L'en-tête c'est justement là où tu places les commandes import. C'est un fichier (le .ash) dont le texte sera en gros "copié au début" de chaque fichier .asc qui se trouve plus bas que lui. C'est pour ça que ça n'a aucun intérêt si tu ne veux pas particulièrement donner accès hors de ton module aux variables que tu y manipules.

De plus ton utilisation des timers (pas forcément utile j'en ai peur) est un peu bizarre : tu lances le timer numéro sia_TIMER_ID et ensuite tu vérifies si le timer 20 est expiré. Es-tu sûr que sia_TIMER_ID vaut toujours 20 ?


Ma solution qui en effet ressemble bien à la solution 4 :
Code:
// Définition du calque hors de toute fonction, tout en haut du script
Overlay* siaOverlay // siaOverlay sera accessible partout dans la suite du script

function on_key_press(eKeyCode keycode)
{
  // On suppose qu'une variable "siasprite" a été définie plus haut dans le script
  if ((keycode == eKeySpace) && (siasprite != null))
    siaOverlay = Overlay.CreateGraphical(0, 0, siasprite.Graphic, true);
}

function repeatedly_execute()
{
  // Si le calque est affiché et que le joueur n'appuie plus sur espace
  if ((siaOverlay.Valid) && (!IsKeyPressed(eKeySpace)))
    siaOverlay.Remove(); // On efface le calque
}
J'ai utilisé la propriété Valid des calques, mais je sais que parfois ça déconne un peu...
Une autre solution plus radicale (mais efficace à mon avis) est d'utiliser le code suivant :
Code:
if ((siaOverlay != null) && (!IsKeyPressed(eKeySpace))) {
  siaOverlay.Remove(); // On efface le calque
  siaOverlay = null; // siaOverlay ne pointe plus sur rien
}

_________________
Ga is Ga
Vous pouvez consulter l'aide d'AGS 3.2 en français et contribuer à la traduction et à l'amélioration si le cœur vous en dit !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://admin.no.uchi.free.fr/dokuwiki-2008-05-05/doku.php En ligne
Billbis
Disciple de la Grande Tasse Bleue
Disciple de la Grande Tasse Bleue


Nombre de messages : 1275

Date d'inscription : 10/05/2012


MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Jeu 22 Nov 2012 - 13:32

Merci beaucoup Kitai pour ces explications. Ton savoir m'est très précieux, et ton aide inestimable. sourire

Kitai a écrit:
Je ne pense pas qu'il y aura scintillement : le calque s'effacera simplement après 40 cycles et ne se réaffichera que lorsque le joueur appuiera à nouveau sur la touche espace.
Bin en faite, si. Ça scintille. Je vais ré-essayer, mais si. Ça scintille.

Kitai a écrit:
Là tu ne définis pas le calque dans l'en-tête, tu le définis simplement tout en haut du corps du script (le fichier .asc).
Oui, j'ai des petits problèmes de vocabulaire. Merci pour ces précisions. Quel idée aussi, de mettre l'entête d'un script dans un autre fichier, du coup l'entête (=ce qui est en haut) du .asc n'est pas un entête de scipt, et un entête de script n'est pas l'entête du script.
zarb

Kitai a écrit:
tu lances le timer numéro sia_TIMER_ID et ensuite tu vérifies si le timer 20 est expiré. Es-tu sûr que sia_TIMER_ID vaut toujours 20 ?
Oui, nan. Je me suis encore totalement embrouillé dans mes copiés / collés. C'est bien soit 20 partout, soit sia_TIMER_ID partout. (sia_TIMER_ID étant défini dans le .ash par un #define sia_TIMER_ID 20, pour que les utilisateur du module puisse choisir le timer qu'ils veulent condamner).

Kitai a écrit:
J'ai utilisé la propriété Valid des calques, mais je sais que parfois ça déconne un peu...
Damned, quel logique ! Quel fulgurance ! Quel génie ! J'essaye ça ce soir.

Merci de ne pas avoir commenté la hideuse solution numéro 5. rougit

_________________
Mon petit DevBlog
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nothingaboutthedog.blogspot.fr/
Kitai
Délégué de la tasse bleue
Délégué de la tasse bleue


Nombre de messages : 2431

Date d'inscription : 01/08/2006


MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Jeu 22 Nov 2012 - 14:37

Billbis a écrit:
Merci beaucoup Kitai pour ces explications. Ton savoir m'est très précieux, et ton aide inestimable. sourire
N'en jette plus, vu qu'on est un peu les seuls à causer sur ce forum en ce moment, on va croire que les sujets sont lancés comme mes faire-valoirs clin d\\\\'oeil

Billbis a écrit:
Bin en faite, si. Ça scintille. Je vais ré-essayer, mais si. Ça scintille.
Tiens, marrant ça, j'aurais juré que on_key_press ne se déclenchait qu'à un nouvelle pression de la touche en question... Tu m'apprends quelque chose là, si c'est comme ça y'a peu d'intérêt à avoir une fonction dédiée par rapport à vérifier IsKeyPressed dans repeatedly_execute.

Billbis a écrit:
Quel idée aussi, de mettre l'entête d'un script dans un autre fichier, du coup l'entête (=ce qui est en haut) du .asc n'est pas un entête de scipt, et un entête de script n'est pas l'entête du script.
Bah, certes, mais où s'arrête "ce qui est en haut" du .asc ? Les programmeurs et les positivistes ont cette manie de supprimer le vague partout où ils le voient clin d\\\\'oeil

_________________
Ga is Ga
Vous pouvez consulter l'aide d'AGS 3.2 en français et contribuer à la traduction et à l'amélioration si le cœur vous en dit !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://admin.no.uchi.free.fr/dokuwiki-2008-05-05/doku.php En ligne
Billbis
Disciple de la Grande Tasse Bleue
Disciple de la Grande Tasse Bleue


Nombre de messages : 1275

Date d'inscription : 10/05/2012


MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Jeu 22 Nov 2012 - 18:47

Ta solution radicale fonctionne à merveille Kitai. Du coup, j'ai bien envie de complexifier un peu les choses. Admettons que tant que l'overlay en question est affiché, j'aimerais que le jeu soit en pause. J'ai essayé de faire ça :
Code:
// Définition du calque hors de toute fonction, tout en haut du script
Overlay* siaOverlay // siaOverlay sera accessible partout dans la suite du script

function on_key_press(eKeySpace)
{
    siaOverlay = Overlay.CreateGraphical(0, 0, 3, true);
    PauseGame();
}

function repeatedly_execute()
{
  // Si le calque est affiché et que le joueur n'appuie plus sur espace
  if ((siaOverlay != null) && (!IsKeyPressed(eKeySpace)))
 {
    UnPauseGame();
    siaOverlay.Remove(); // On efface le calque
    siaOverlay = null; // siaOverlay ne pointe plus sur rien
  }
}
Et de façon inexplicable, l'overlay est bien affiché TANT que le barre d'espace est enfoncé, il disparait bien lorsque la barre d'espace est relaché, MAIS le jeu reste en pause. J'ai essayer de passer en repeatedly_execute_always(), ça ne change rien. Chose étrange, avec un bon timing de pression de barre d'espace (pression assez rapide, mais pas trop), et lorsque le jeu n'est pas déjà bloqué en pause, j'arrive parfois à enlever la pause lorsque j'arrête d'appuyer sur cette maudite touche.
Bref, à mesure que le mystère s'éclaircit dans mon esprit, il s'obscurcit de plus en plus à nouveau. Remarque, c'est logique, n'est-ce pas là la définition même d'un mystère ?

_________________
Mon petit DevBlog
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nothingaboutthedog.blogspot.fr/
Kitai
Délégué de la tasse bleue
Délégué de la tasse bleue


Nombre de messages : 2431

Date d'inscription : 01/08/2006


MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Jeu 22 Nov 2012 - 19:38

Billbis a écrit:
Et de façon inexplicable, l'overlay est bien affiché TANT que le barre d'espace est enfoncé, il disparait bien lorsque la barre d'espace est relaché, MAIS le jeu reste en pause. J'ai essayer de passer en repeatedly_execute_always(), ça ne change rien. Chose étrange, avec un bon timing de pression de barre d'espace (pression assez rapide, mais pas trop), et lorsque le jeu n'est pas déjà bloqué en pause, j'arrive parfois à enlever la pause lorsque j'arrête d'appuyer sur cette maudite touche.
Alors ça c'est pas mal langue
À vrai dire je ne vois pas d'explication convaincante : puisque PauseGame suit directement l'affichage du calque et que UnPauseGame précède directement son effacement, il devrait y avoir correspondance parfaite...

Toutefois, étant donné qu'une façon de mettre le jeu en pause est d'utiliser la commande Wait (mais ce n'est pas le même type de pause, je te le concède), tu peux revenir vers ta solution 1 :
Code:
// Ça marche vraiment ça ? Passer eKeySpace en argument direct de la déclaration de la fonction ?
function on_key_press(eKeySpace)
{
    // Calque local
    Overlay* siaOverlay = Overlay.CreateGraphical(0, 0, 3, true);
    // Tant que la touche est pressée, on attend (pause)
    while (IsKeyPressed(eKeySpace)) Wait(1);
    // Une fois que la touche n'est plus pressée, on supprime le calque
    siaOverlay.Remove();
    siaOverlay = null;
}
Le problème étant bien sûr qu'aucun autre fonction à part repeatedly_execute_always ne peut être exécutée.

Sinon en gardant le code que tu as mis, essaye d'ajouter une condition sur IsGamePaused aussi bien dans on_key_press et dans repeatedly_execute_always (conditions "opposées" bien sûr). On ne sait jamais, ça peut toujours aider...

EDIT : ton problème ressemble un peu à ce que tu pourrais avoir si tu avais dupliqué le fichier script précédent pour modifier celui obtenu. Dans ce cas, la fonction repeatedly_execute du script original se chargerait bien d'effacer le calque, et le calque n'étant plus affiché, la condition dans repeatedly_execute du script dupliqué n'est pas validée et alors la commande UnPauseGame n'est pas exécutée.

_________________
Ga is Ga
Vous pouvez consulter l'aide d'AGS 3.2 en français et contribuer à la traduction et à l'amélioration si le cœur vous en dit !
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://admin.no.uchi.free.fr/dokuwiki-2008-05-05/doku.php En ligne
Billbis
Disciple de la Grande Tasse Bleue
Disciple de la Grande Tasse Bleue


Nombre de messages : 1275

Date d'inscription : 10/05/2012


MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Jeu 22 Nov 2012 - 20:14

Donc si je résume cette longue discussion, la meilleur façon de coder un while_key_press est de...
... mettre un while dans la fonction on_key_press.

Le pire, c'est que je savais que while existait sous AGS. Mais je n'ai pas pensé à l'utiliser ici. En plus, maintenant que tu me le rappel, je suis quasiment sûr d'avoir lu cette astuce sur le forum anglophone.
Sans rire, sa marche (presque) nickel. Merci Kitai !
(presque) seulement car si le joueur est en mouvement, il continu d'avancer pendant la pression sur le barre d'espace (normal), or j’aurais préféré qu'il s'arrête et reprenne ensuite. Mais bon, c'est un détail sans doute pas rédhibitoire.
Kitai a écrit:
// Ça marche vraiment ça ? Passer eKeySpace en argument direct de la déclaration de la fonction ?
Ah bin non. C'est encore moi qui ai du mal avec mes copiés collés. Je sais plus trop quoi laisser et quoi enlever.

EDIT : du coup je vais juste rajouter un petit if (!player.Moving), et sa ira bien.

_________________
Mon petit DevBlog
Revenir en haut Aller en bas
Voir le profil de l'utilisateur http://nothingaboutthedog.blogspot.fr/
Contenu sponsorisé




MessageSujet: Re: [Résolu]Du codage d'un While_KeyPressed.   Aujourd'hui à 17:22

Revenir en haut Aller en bas
 
[Résolu]Du codage d'un While_KeyPressed.
Voir le sujet précédent Voir le sujet suivant Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» [Résolu]Du codage d'un While_KeyPressed.
» [RÉSOLU]Lapin capricieux n'aime pas orange
» Besoin d'un tutoriel[résolu]
» [Résolu] Le mystère de la borne d'arcade !!
» [Résolu] Problème d'accès à http://192.168.0.1

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
Adventure Games Studio fr :: CREATION DE JEUX :: Questions / Réponses-
Sauter vers: