19 nov. 2013

Barre de chargement interne en Flash

Si vous avez jeté un coup d’œil curieux à Rose in the Woods récemment, vous avez dû remarquer que, depuis la semaine dernière, le jeu s'est enfin enrichi d'une barre de chargement (preloader en anglais).

Une toute petite barre de chargement, pff... Anodin ? Facile ? Eh bien, sachez que de tout le développement de Rose in the Woods, c'est cette #$!%*& de barre de chargement qui a été mon pire cauchemar !


Maintenant que j'en suis venue à bout, on va pouvoir passer à la diffusion. J'ai envoyé le jeu final à Plug-in-Digital, notre diffuseur, qui va soumettre le jeu à ses partenaires. On devrait avoir de ses nouvelles la semaine prochaine. En attendant, laissez-moi vous expliquer pourquoi la barre de chargement a été une telle épreuve, et quelles solutions j'ai trouvées pour en venir à bout !

Pourquoi faut-il une barre de chargement ?

S'il n'y a pas de chargement, un jeu Flash reste tout blanc jusqu'au moment où il est prêt (ce qui peut prendre quelques secondes, voire quelques minutes). Pour éviter que le joueur s'en aille parce qu'il croit que c'est un bug ou parce qu'il n'a pas envie d'attendre, il est bien utile d'avoir une barre de chargement qui lui indique le temps d'attente restant.

En soi, faire une barre de chargement avec Flash, c'est facile. On va créer un premier fichier swf qui contient la barre de chargement et qui va charger un deuxième swf, celui du jeu.


Trois lignes de code, et voilà, le tour est joué !

Sauf que... sauf que cette méthode implique d'avoir deux fichiers, celui qui contient la barre de chargement et celui qui contient le jeu. Si le jeu n'est hébergé que sur mon site, pas de problèmes, je fais ce que je veux ; mais Rose in the Woods doit être diffusé sur Internet et la plupart des portails de jeux Flash exigent un seul et unique fichier.

Il faut donc bricoler un fichier qui se charge lui-même, et c'est là que se situe le problème ! Car Flash, je vous l'ai dit, attend que l'ensemble du fichier soit chargé (y compris la barre de chargement) avant de le lancer. Ce qui rend la barre de chargement inutile.

Voici donc notre challenge : expliquer à Flash que la barre de chargement doit être chargée avant tout le reste. Et vous verrez, Flash est une sacrée bourrique.

Comment charger la barre de chargement avant tout le reste ?

Avant d'expliquer la solution, il faut comprendre dans quel ordre Flash charge les éléments d'un jeu.

Flash charge les éléments dans l'ordre où ils sont placés dans la timeline principale : d'abord l'image 1, puis l'image 2, puis l'image 3, etc... Mais la plupart des éléments ne sont placés nulle part, c'est le code qui les "appelle". Prenez par exemple un ennemi : dans notre jeu, les monstres apparaissent en fonction de la musique, à un moment qui peut varier d'une partie à l'autre. Mais il faut quand même les charger en mémoire dès le début du jeu, pour qu'ils soient prêts à apparaître le moment venu ! On a donc coché la case "Exporter dans l'image 1", ce qui les charge avant l'image 1.

Le problème vient donc du fait que la grosse majorité de nos ressources (les musiques, les décors, les ennemis, les alliés, etc...) sont "exportés dans l'image 1", soit avant le début du jeu - et donc avant que la barre de chargement ait le temps d'apparaître.

Pour que la barre de chargement soit utile, il va falloir décocher "Exporter dans l'image 1" pour tous les éléments qui sont appelés par le code, et les placer manuellement dans l'image 2.

Barre de chargement interne Flash as3

Devoir décocher cette petite case pour chaque movieClip est une tâche fastidieuse et pénible, aussi prenez la bonne habitude de ranger correctement votre bibliothèque dès le début !

Reste ensuite à ajouter sur l'image 1 le code de la barre de chargement, et le tour est joué :

var total : Number;
var loaded : Number;

this.addEventListener(Event.ENTER_FRAME, progressionChargement);

function progression(e:Event):void
{
     //Récupérer le poids total du fichier, et ce qui a déjà été chargé
     total = stage.loaderInfo.bytesTotal;
  loaded = stage.loaderInfo.bytesLoaded;

     //Afficher le chargement (ici sous forme de texte)
     chargement.text = "chargement : " + total + " / " + loaded;

     //Chargement terminé
  if (loaded == total)
     {
          //La fonction "progression" n'est plus utile
          this.removeEventListener(Event.ENTER_FRAME, progression);
//On saute l'image 2 (stockage) pour aller à l'image 3 (jeu)
          this.gotoAndStop (3);
  }
}

La barre de chargement ne fonctionne pas en ligne

Ha ha ! moi aussi j'ai cru que ce serait aussi simple. Ce n'est pas la première fois que je réalisais une barre de chargement en AS3 et, les fois précédentes, cette manipulation (quoique longue et pénible) fonctionnait bien. D'ailleurs, elle fonctionnait bien cette fois aussi : tant que je testais en local (View > Simulate download), ça marchait.

Mais, bizarrement, quand j'ai fait le test dans mon navigateur, le jeu restait bloqué sur la barre de chargement vide (et pourtant, je n'étais même pas connectée à Internet : c'était un test hors-ligne).

Après moult recherches sur Internet, j'ai fini par comprendre que, sur certains navigateurs, Flash pense (par erreur) que la taille totale du fichier à charger est... 0. Or, si le fichier pèse 0 Ko, la condition if (loaded == total) ne peut jamais être remplie, d'où blocage.

J'ai donc suivi les conseils de ce site et j'ai modifié mon code en séparant l'affichage de la progression d'une part, et le passage au jeu une fois le chargement terminé d'autre part.

var total : Number;
var loaded : Number;

this.loaderInfo.addEventListener(Event.COMPLETE, chargerJeu);
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, affichageBarre);


// ----------------------- Affichage ------------------------------- \\

function affichageBarre(e:ProgressEvent):void
{
     total = e.bytesTotal;
     loaded = e.bytesLoaded;
     //Petite astuce pour quand même afficher le chargement si ça foire : je lui donne manuellement la taille du fichier
     if (total == 0)
     {
          total = 15534421;
     }

     //Afficher le chargement (ici sous forme de texte)
     chargement.text "chargement : " + total + " / " + loaded;
}

// ------------------- Chargement complet --------------------------- \\

function chargerJeu(e:Event) : void
{
     //Les fonctions "afficherBarre" et "chargerJeu" ne sont plus utiles
     this.loaderInfo.removeEventListener(Event.COMPLETE, loadComplete);
     this.loaderInfo.removeEventListener (ProgressEvent.PROGRESS, loadProgress);
//On saute l'image 2 (stockage) pour aller à l'image 3 (jeu)
     this.gotoAndStop(3);
}

Ce deuxième code fonctionne parfaitement. A noter que j'ai rajouté une petite tricherie pour lui "souffler" la taille totale du fichier quand il se trompe et croit qu'elle vaut 0 : ça me permet d'afficher quand même la progression du chargement.

Flash se fout de ma gueule

L'année dernière, mise en ligne
du jeu vidéo à 3h du matin...
(image de Paulapin)
J'ai parlé ci-dessus des deux principaux problèmes que j'ai résolus. Mais ce que je n'ai pas dit, c'est que j'ai eu plein d'autres problèmes, parfois carrément chelous, qui me sont tombés dessus. Et notamment ce fameux soir de la mise en ligne...

Le soir de la mise en ligne de Rose in the Woods, j'étais fière de moi car, contrairement à l'année dernière, tout se passait bien et j'étais même en avance. Il ne me restait plus qu'à rajouter la barre de chargement, et tout serait prêt. J'ai donc tranquillement réalisé la manip' : décocher la fameuse case, placer les movie clips dans l'image 2 du fichier, bref, tout comme je vous ai expliqué ci-dessus...

...et ça n'a pas marché. Il n'y avait absolument aucune raison valable, mais ça n'a pas marché. Pire : rien ne fonctionnait plus ! C'était comme si tout mon code avait mystérieusement disparu du fichier Flash : il ne "percevait" plus aucune ligne de code. Je me suis demandé si j'avais pu décocher quelque chose, faire une fausse manip sans m'en rendre compte... J'ai cherché partout sur Internet pour trouver une solution à mon problème, mais parmi tous ceux qui avaient eu le même problème, personne ne semblait avoir d'explication. Il était plus de minuit, j'étais fatiguée, les internautes attendaient, et je n'ai vu qu'une seule solution : tout recommencer depuis ma dernière sauvegarde.


Après coup, la seule explication que j'ai fini par trouver, c'est que Flash a déconné. Au-delà d'un certain volume d'informations, il arrive qu'il plante. Oui, tout seul. Et quand il plante, il arrive qu'il corrompe la sauvegarde. Dans ce cas, il n'y a plus rien à faire.

"Adobe Flash says fuck you"
(dessin de Trystan
d'après le fameux dragon
de mon tutoriel Flash)
Ça me rappelle une anecdote qu'on m'a racontée au sujet de Binding of Isaac, jeu indépendant développé en Flash lui aussi. Vers la fin du développement, leur jeu était si gros qu'il fallait 20 minutes à chaque fois pour le compiler. Et il avait une chance sur deux de crasher. Et s'il crashait, la sauvegarde était foutue. Les développeurs ont donc pris l'habitude de faire une copie de leur travail à chaque fois qu'ils modifiaient la moindre virgule, sous peine de voir disparaître des mois et des mois de travail suite à une erreur informatique...

Flash est un logiciel génial, mais il est avant tout prévu pour faire de petits jeux modestes, et Rose in the Woods commence à atteindre la limite de ce qu'il peut supporter. J'ai perdu un temps fou à essayer de comprendre des problèmes étranges qui n'en étaient pas. Maintenant je sais : dès que je modifie quelque chose, je me fais une copie de sauvegarde. Et je brûle des cierges pour implorer la clémence de Flash.

Une sacrée galère

Si j'ai pris le temps de vous raconter tous ces détails techniques, c'est pour que vous compreniez pourquoi j'ai mis quasiment un mois à implémenter la barre de chargement, et pourquoi la diffusion va commencer seulement maintenant.
Maintenant que c'est vraiment fini, on va attendre ensemble les retours de Plug-in-Digital ! Trouvera-t-il des partenaires intéressés par Rose in the Woods ? Sur quelles plate-formes sera-t-il publié ?

Je vous tiens au courant !

21 commentaires :

  1. hé bé ! Quel aventure ! mais bravo !

    RépondreSupprimer
  2. Moi je dis que le multi-thread (comprenez exécution simultanée de plusieurs codes en même temps), ça a toujours été compliqué.
    Donc chapeau pour avoir finalement trouvé une solution à ce problème de barre de chargement... que je trouve plus rapide que celle que j'avais vu la dernière fois au passage.

    RépondreSupprimer
  3. Ah ouais, une élève de mon école m'avait raconté que Flash était un gros bordel, mais j'étais loin de me douter que c'était à ce point !

    En tout cas, bravo pour être enfin arrivée à finaliser ce jeu.

    Heureusement que j'ai pris un cursus graphique, je n'aurais pas besoin de m'énerver avec les codes sous Flash. ^^"

    RépondreSupprimer
    Réponses
    1. Tu as tort, savoir coder ouvre le champ à d'énormes possibilités, et Flash est un logiciel facile à prendre en main (en dehors de quelques problèmes très spécifiques comme celui-ci).

      Supprimer
  4. Et ben, il faut vraiment avoir des nerfs d'acier pour arriver à dompter ce satané dragon capricieux qu'est Flash! Bravo Lou pour avoir réussit à en venir à bout!

    RépondreSupprimer
  5. Beau boulot ! J'ai toujours dit que flash était un démon sans âme o_o

    RépondreSupprimer
  6. Je trouves que pour l'instant on s'est très bien passé de Plug-in-Digital pour diffuser notre jeu.

    Donc est ce que ça vaut vraiment la peine de faire ça ? Si le jeu marche, on devra le compléter et même pire, le rendre payant. Ça serait dommage.

    RépondreSupprimer
    Réponses
    1. Hum... Et alors ? Ce n'est pas dramatique.
      On en avait déjà discuté dans un article il y a quelques mois, me semble-t-il. Si mes souvenirs sont bons, on avait conclu que la version actuelle gratuite existerait toujours, et qu'éventuellement on améliorerait le jeu et créerait une version payante, en cas de succès.
      Et puis je suis presque sûr que Lou Lubie serait ravie de pouvoir vivre de son travail.

      Supprimer
    2. Oui, nous nous plutôt bien débrouillés pour diffuser le jeu surtout grâce à la PGW, mais plus tard, la presse n'aura plus rien a dire sur nous.

      Donc ça vaut vraiment la peine de continuer le partenariat avec Plug-In-Digital.
      Et je te rappelle que la version payante (si on en fait une) sera de la version actuelle. Donc tu ne seras pas obligé de l'acheter pour continuer a jouer.

      Supprimer
    3. *la version payante sera en complément* de la version actuelle
      Désolé --'

      Supprimer
    4. Hé là, on ne peut pas juste retourner sa veste au dernier moment...!

      Quand je vous ai consultés au sujet de Plug-in-digital, vous avez dit oui, nous nous sommes engagés vis-à-vis d'eux, et j'ai signé un contrat. On ne peut pas les lâcher au dernier moment : un engagement, ça se respecte !

      D'autre part, bien sûr qu'on a besoin d'eux pour la diffusion ! Il ne faut pas confondre marketing et relations presse, d'une part - mon travail en tant qu' "éditeur" - et distribution d'autre part, c'est-à-dire rendre le jeu accessible au public sur des plate-formes diverses et variées. On n'a encore rien fait en terme de distribution !

      Troisièmement, ça va être extrêmement intéressant de découvrir le processus de distribution d'un jeu ! Poussons l'aventure jusqu'au bout, soyons ambitieux ! Et pour l'instant, il est seulement question de diffuser la version gratuite sur le web ; nous verrons plus tard s'il est judicieux d'en faire une version enrichie payante, ou une deuxième édition de la Petite Fabrique de Jeu Vidéo, ou rien du tout.

      Supprimer
    5. Oui mais la, on a tout nos objectifs, le jeu est sorti, il a été bien accueilli par la presse, on a même eu un article sur JVC. Je trouves ça dommage de se lancer dans du marketing alors que le jeu s'en passe très bien !

      Je pense que ce qui fait le succès des jeux indépendants, c'est justement qu'il s'en sort par lui même. On l'aime par ce qu'il est, pas par sa diffusion marketing...

      Supprimer
    6. Plug-in-digital ne fait PAS du marketing. Il fait de la distribution, c'est-à-dire qu'il rend le jeu disponible sur diverses plate-formes en ligne.

      Les jeux indépendants doivent être distribués. Prenons par exemple Super Meat Boy, dispo sur Steam et Xbox Live Arcade. Penses-tu que le fait d'être diffusé sur ces plateformes lui nuit ? Ou est-ce que, au contraire, ça lui a permis d'être découvert et apprécié par le public ?

      Je crois que tu confonds éditeur et distributeur. Un jeu indépendant est un jeu qui n'a pas d'éditeur, donc souvent pas, ou peu, de financements, et qui est créé par une petite équipe. Plug-in-Digital n'est pas notre éditeur et n'a aucun droit de regard sur le contenu de notre jeu, il ne fait que le placer sur des plate-formes dématérialisées. Nous restons donc bien indépendants.

      Supprimer
    7. Je sens le petit article dans 2 ou 3 jours sur ce qu'est un distributeur x)

      Supprimer
    8. Je vais attendre que Plug-in-Digital bouge ses pions, avant :)

      Supprimer
  7. Réponses
    1. J'me suis permis de lui trouver une petite place dans l'article : )

      Supprimer
    2. Oh, c'est sympa de ta part! :D Content de voir que tu aimes cette représentation... de la réalité la plus pure. Héhé.

      Supprimer

La participation à la Petite Fabrique de Jeu Vidéo est libre, gratuite et sans inscription. Elle ne vous donne droit à aucune contrepartie financière.

Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.