Journal jnuit et la recette des mombolini

42
16
fév.
2014

Bonjour Nal,

Je t'écris pour te parler de mon nouveau projet, jnuit, une bibliothèque pour créer des interfaces graphiques pour les jeux avec Java/lwjgl et… Attends ne pars pas! Si tu restes je te donnerais une délicieuse recette italienne!

Maintenant que j'ai ton attention, revenons à nos moutons. Grâce à mes 42 journaux annuels, tu sais que je travaille sur deux jeux, Newton Adventure et Ned et les maki. Pour les créer, j'ai suivi le conseil d'un article célèbre dans le milieu, Write Games, Not Engines, qui explique en gros qu'il est beaucoup plus efficace de se concentrer sur la réalisation d'un jeu spécifique plutôt que de tenter de créer un moteur générique.

Ce principe m'a beaucoup aidé, mais aujourd'hui j'ai du mal à maintenir du code pour mes deux jeux, j'ai donc décidé de factoriser petits à petits leurs parties communes dans des bibliothèques réutilisables:

jnuit

jnuit est une bibliothèque de composant pour la création d'interfaces homme-machine pour les jeux vidéos. Elle tient compte des contraintes suivantes:

  • un joueur peut utiliser un clavier, une souris, un écran tactile, une manette ou une combinaison des quatre.
  • les manettes peuvent être très différentes: joystick, gamepad, stick arcade… Le nombre d'axes, leurs orientations, le nombre de boutons sont très divers.
  • il faut s'intégrer dans la boucle d'évènement d'un jeu.

Pour cela, j'ai réalisé jnuit suivant un modèle très simple avec seulement quelques concepts:

  • widget: l'élément de base de l'interface.
  • layout: des widgets destinés à en contenir d'autres.
  • curseur: un focus sur un widget qui peut être déplacé.
  • peu d'événements: déplacement du curseur, "ok", "annuler".

Sur cette base, j'ai implémenté des widgets génériques (select, toggle, label…) et spécifiques (configuration des clavier/souris/manettes, réglages du son, changement de la résolution, de la langue…).

Demo

Voici un exemple simple en image et en vidéo:

demo

Créer son propre jeu en une commande!

Cet exemple est ce que l'on obtient en utilisant l'archetype maven que j'ai créé pour l'occasion et qui permets de démarrer un projet de jeu vidéo moderne (injection de dépendances, système d'entités, GUI complète, génération de paquets/installeurs pour la plupart des OS…) avec une simple commande:

mvn archetype:generate -DarchetypeGroupId=im.bci -DarchetypeArtifactId=jnuit-archetype -DarchetypeVersion=LATEST -DgroupId=comycompagny.superbaryo2 -DartifactId=superbaryo2 -Dgame-name=superbaryo2 -Dgame-package=com.mycompagny.superbaryo2 -Dversion=1.0-SNAPSHOT

Ensuite pour apprendre l'api, il suffit de consulter les exemples et la javadoc (fournit avec les livrables récupérés par maven).

Exemples de code

Note: pour ces exemples, il faut considérer que l'on a déjà créé deux objets toolkit et root. Leur création étant dépendante de l'API graphique utilisée (pour l'instant seulement lwjgl, mais je prévoie des portages sur playn), je ne la détaille pas ici.

Hello world

Label hello = new Label(toolkit, "Hello world!");
root.show(hello);

Formulaire simple avec un layout de type "table"

    Table table = new Table(toolkit);
    table.setBackground(new ColoredBackground(0, 0, 0, 1));
    table.defaults().expand().fill();

    Label fruitsLabel = new Label(toolkit, "Do you like fruits?");
    table.cell(fruitsLabel);
    Toggle fruitsToggle = new Toggle(toolkit);
    table.cell(fruitsToggle);
    table.row();

    Label kindLabel = new Label(toolkit, "What kind?");
    table.cell(kindLabel);
    Select<String> kindSelect = new Select<String>(toolkit, Arrays.asList("banana", "apple", "orange"));
    table.cell(kindSelect);
    table.row();

    table.cell(new Button(toolkit, "quit") {

        @Override
        public void onOK() {
            System.exit(0);
        }
    }).colspan(2);

    table.layout();

    root.show(table);

La recette des mombolini

Nal, je vois que ça fait beaucoup de Java pour aujourd'hui, passons à la recette!

Pour réaliser les momboloni, il faut:

  • de minces lamelles de porc.
  • du jambon cru ou de la coppa.
  • du parmesan.
  • de l'huile d'olive.
  • des cures dents.
  1. faire chauffer l'huile dans une poêle.
  2. étaler les lamelles de porc.
  3. mettre la charcuterie sur les lamelles.
  4. saupoudrer de parmesans.
  5. rouler les lamelles et les maintenir avec un ou deux cure dents.
  6. faire cuire à la poêle quelques minutes en les tournant régulièrement.

Bon appétit et bon code, Nal!

  • # ça tombe bien !

    Posté par . Évalué à 6.

    Ton journal tombe bien parce que j'avais une question sur les interfaces que tu développes et tu y réponds en partie mais j'aimerais en être sûr.

    Ici, comme je le comprends, tu unifies toutes les interfaces en considérant qu'elles partagent toutes un ensemble d'actions simples (déplacement, «ok», «annuler»), c'est bien ça ? Et donc, tu fais tout pour ne pas avoir d'interaction spécifique à une interface particulière. Ma question est : est-ce que ce n'est pas handicapant ? Parce qu'avec une souris, tu pourrais avoir une interface bien plus riche qu'avec une manette, ou différente disons. Est-ce qu'on ne se prive pas de modes d'action possible dans un jeu à cause de cette unification ? Jusqu'où peut-on pousser l'unification sans que ça ne paraisse trop artificiel ?

    Dans mes réflexions préliminaires (en grande partie dû au fait que tu m'as dit vouloir jouer avec une manette au tout début, merci bien !), j'avais pensé à faire quelque chose dans ce genre là donc ça ne me paraît pas si dénué de bon sens. Mais je me demande vraiment si ça ne va pas être limitant en pratique.

    • [^] # Re: ça tombe bien !

      Posté par (page perso) . Évalué à 3.

      J'ai tout simplifié avec les notions suivantes:

      • contrôle: un input qui renvoie une valeur entre 0 (pas actif) et 1 (à fond) => ça sert à modéliser le déplacement d'un axe d'une manette ou l'appui sur un bouton (souris, clavier ou manette, ça reste des boutons!).
      • action: une action dans l'interface ou dans le jeu qui peut être activée via un ou plusieurs contrôles.
      • curseur: le focus sur le widget courant et peut être déplacé soit via une action (haut, bas, gauche, droite).
      • pointeur: point sur l'écran que l'on peut déplacer à la souris ou au touchpad et qui permets d'activer les widgets.

      Il y a donc bien un petit traitement de faveur pour certains inputs:

      • seuls la souris et le touchpad permettent de gérer le pointeur.
      • un mapping contrôle => action par défaut pour le clavier.

      J'espère pouvoir réalise un mapping par défaut pour les manettes mais c'est assez compliqué: par exemple on pourrait croire que toutes les manettes ont des axes 0 et 1, mais j'ai un stick arcade qui ne présentent par défaut que deux axes: 4 et 5…

      http://devnewton.bci.im

      • [^] # Re: ça tombe bien !

        Posté par . Évalué à 2.

        OK, c'est plus générique que ce que je pensais. Du coup, j'ai une question subsidiaire ;) En fait, je me dis que je ne pourrai pas échapper à la configuration de l'input, quel qu'il soit. J'ai vu que tu avais un widget prédéfini pour ça d'ailleurs. Ma question est : penses-tu que ce soit possible de le faire de manière plus interactive ? En fait, pour mon jeu, j'aimerais que le joueur puisse configurer son input au fur et à mesure, genre au début "appuyer sur la touche OK". Et ensuite, "appuyer sur Avancer", etc. Puis je fais bouger le joueur. Puis "appuyer sur Annuler", et je le fais utiliser cette nouvelle touche en jeu. Et du coup, la configuration se fait au fur et à mesure en montrant à quoi sert quelle touche façon tutoriel. Bon, ça c'est mon rêve, maintenant, pour toi qui a déjà mis les mains dedans, est-ce que ça te semble faisable et/ou facile ?

        • [^] # Re: ça tombe bien !

          Posté par (page perso) . Évalué à 4.

          C'est assez facile, il suffit de faire une sorte de wizard ou alors un popup à chaque nouvelle action, mais par contre ce n'est pas très agréable pour le joueur:

          • s'il se rate, il lui faut tout recommencer.
          • s'il connaît déjà le jeu, il n'a pas forcément envie de refaire le tutorial.

          http://devnewton.bci.im

          • [^] # Re: ça tombe bien !

            Posté par . Évalué à 3.

            Oui, donc tu dis en fait qu'il faudra de toute façon passer par un panneau de configuration pour l'input. Mais sur le tuto, j'hésite encore. Dans FF12 par exemple, dans mon souvenir, au début, il y a un tuto pour prendre en main le jeu, ce n'est pas très long (et d'autres aspects du jeu sont mis en tuto plus loin dans le jeu) et ça permet de bien introduire les mécaniques du jeu je trouve. Je voulais ajouter la configuration des touches mais bon, peut-être que ça fait trop du coup. Je vais continuer à réfléchir.

  • # Et la recette alors ?

    Posté par . Évalué à 1.

    En lisant le mot "recette" associé à linuxfr dans mes flux rss hier soir, je me suis dit qu'il était trop tard pour lire ça avec le nombre incroyable de commentaires que ça génèrerait.

    Je suis déçu…

    Enfin bref, ça a l'air bon.

  • # Autres libs ?

    Posté par (page perso) . Évalué à 3.

    Hello,

    Tout d'abord merci de prendre le temps de partager tes aventures depuis le début sur linuxfr :)

    Développant aussi à mes heures perdues de petits jeux en Java + LWJGL (parfois avec Slick2D aussi), je me posais la question suivante : si je comprends bien, l'intérêt principal de jnuit (sympa pour les dyslexiques, au passage ;) est de ne pas avoir à se préoccuper de la diversité/complexité des périphériques d'entrée pour l'UI. Par contre, en terme de composants purs, pourquoi ne pas t'appuyer sur une lib dédiée à ça, type TWL, en dehors de leur PNGDecoder ? (que tu connais sûrement, mais pour les autres : http://twl.l33tlabs.org/)

    Merci encore à toi.

    • [^] # Re: Autres libs ?

      Posté par (page perso) . Évalué à 3.

      Développant aussi à mes heures perdues de petits jeux en Java + LWJGL (parfois avec Slick2D aussi)

      N'hésite pas à faire plein de journaux pour en parler!

      l'intérêt principal de jnuit (sympa pour les dyslexiques, au passage ;) est de ne pas avoir à se préoccuper de la diversité/complexité des périphériques d'entrée pour l'UI

      L'intérêt principal de jnuit, c'est de partager du code entre mes jeux et de simplifier la vie des contributeurs :-)

      Pour les autres, la vraie valeur ajoutée n'est pas tant dans la bibliothèque que dans l'archetype maven: créer un projet de jeu avec une UI quasi complète, une architecture qui mélange système à entité et injection de dépendances et de quoi générer des paquets/installeurs pour les OS majeurs, c'est un énorme boulot. Là ça se fait en une commande.

      en terme de composants purs, pourquoi ne pas t'appuyer sur une lib dédiée à ça, type TWL

      J'utilise TWL pour le menu des options de Newton Adventure. Ça fait le boulot, mais:

      • créer un thème est horriblement compliqué.
      • j'ai passé beaucoup de temps sur des problèmes de layout qui se sont terminé en "ce sera moche et tant pis".
      • twl est fait pour être utiliser avec un clavier et une souris.
      • son auteur n'aime pas maven, donc ça fait une dépendance à gérer à la main…
      • il n'y a pas de portage playn et ce serait très compliqué pour le backend html5 (il faut utiliser un sous ensemble très minimal de Java).

      J'ai essayé les autres bibliothèques d'UI pour lwjgl et elles ont toutes à peu près les mêmes défauts en plus d'être moins documentées et maintenues que TWL.

      http://devnewton.bci.im

      • [^] # Re: Autres libs ?

        Posté par . Évalué à 3.

        Pour les autres, la vraie valeur ajoutée n'est pas tant dans la bibliothèque que dans l'archetype maven: créer un projet de jeu avec une UI quasi complète, une architecture qui mélange système à entité et injection de dépendances et de quoi générer des paquets/installeurs pour les OS majeurs, c'est un énorme boulot. Là ça se fait en une commande.

        C'est dommage l'utilisation du build.sh, il y a une raison qui empêche le plugin assembly de faire cette copie ? Ça permettrait d'être plus portable et de tout gérer avec un même système de build.

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: Autres libs ?

          Posté par (page perso) . Évalué à 2.

          Le build.sh est juste un petit script qui m'aide à préparer les releases sans avoir à me souvenir des paramètres maven :-)

          De toute façon la génération des paquets n'est pas portable, ça ne marche que sous linux avec certains paquets installés (il faut les bons outils pour construire les paquets rpm par exemple).

          Mais effectivement, je vais regarder le plugin assembly pour remplacer les copies de fichiers, ce sera déjà ça…

          http://devnewton.bci.im

          • [^] # Re: Autres libs ?

            Posté par . Évalué à 2.

            De toute façon la génération des paquets n'est pas portable, ça ne marche que sous linux avec certains paquets installés (il faut les bons outils pour construire les paquets rpm par exemple).

            Oui la portabilité est annexe. C'est juste que ça m'horripilerais toujours un peu d'avoir à faire mvn package -Dbidule && ./build.sh plutôt qu'un simple mvn package. :)

            Je n'ai pas d'exemple de projet avec cette architecture, si tu me dis où en trouver un je peux regarder si tu veux.

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: Autres libs ?

              Posté par (page perso) . Évalué à 2. Dernière modification le 17/02/14 à 18:23.

              Je n'ai pas d'exemple de projet avec cette architecture, si tu me dis où en trouver un je peux regarder si tu veux.

              Tu peux partir de l'archetype ou du code de Ned et les maki :-)

              http://devnewton.bci.im

      • [^] # Re: Autres libs ?

        Posté par (page perso) . Évalué à 2.

        Effectivement, faudrait que j'arrive à me bouger le *** pour faire poster de temps en temps des journaux à ce sujet.

        Pour TWL, j'en ai aussi essayé quelques autres libs d'UI, mais la doc m'a toujours fait revenir à TWL (et même quand la doc manque, les sources sont relativement clairs). Pour ce qui est des thèmes, c'est vrai qu'il y a un sacré ticket d'entrée (je ne compte pas les heures passées), mais au final j'ai trouvé ça vraiment sympa, même pour les composants custo (ça pourrait faire un sujet sympa de journal/article, d'ailleurs, parce-que sur ce sujet la doc est pour le moins évasive).

  • # Recette

    Posté par (page perso) . Évalué à 6.

    Ça a l'air bon, mais je trouve qu'il manque quelques précisions.

    Pour réaliser les momboloni, il faut:

    • de minces lamelles de porc.

    Des lamelles de quoi de porc ? Du lard ?

    1. faire chauffer l'huile dans une poêle.
    2. étaler les lamelles de porc.

    Vu la suite, il doit s'agir de les étaler sur un plan de travail, pas de les faire cuire tout de suite, tu confirmes ?

    1. mettre la charcuterie sur les lamelles.

    Empiler des tranches de jambon de porc sur d'autres tranches de porc en somme.

    1. saupoudrer de parmesans.
    2. rouler les lamelles et les maintenir avec un ou deux cure dents.
    3. faire cuire à la poêle quelques minutes en les tournant régulièrement.

    Faire cuire avec les cure-dents ? En mettant ces rouleaux avec le cure-dent à l'horizontale du coup, c'est ça ?

    • [^] # Re: Recette

      Posté par (page perso) . Évalué à 2.

      Des lamelles de quoi de porc ? Du lard ?

      Non, vraiment de la bidoche. Je ne trouve pas de photo, j'essayerai d'en prendre la prochaine fois que je fais la recette!

      Vu la suite, il doit s'agir de les étaler sur un plan de travail, pas de les faire cuire tout de suite, tu confirmes ?

      Oui.

      Faire cuire avec les cure-dents ? En mettant ces rouleaux avec le cure-dent à l'horizontale du coup, c'est ça ?

      Oui, il faut retourner de temps en temps pour que tout soit bien cuit.

      http://devnewton.bci.im

      • [^] # Re: Recette

        Posté par . Évalué à 3.

        Faire cuire avec les cure-dents ? En mettant ces rouleaux avec le cure-dent à l'horizontale du coup, c'est ça ?

        Oui, il faut retourner de temps en temps pour que tout soit bien cuit.

        Comment sait-on que le cure-dent est bien cuit ?

        • [^] # Re: Recette

          Posté par (page perso) . Évalué à 8.

          Comment sait-on que le cure-dent est bien cuit ?

          Quand il prends feu.

          http://devnewton.bci.im

      • [^] # Re: Recette

        Posté par . Évalué à 2.

        Non, vraiment de la bidoche. Je ne trouve pas de photo, j'essayerai d'en prendre la prochaine fois que je fais la recette!

        Genre escalope de porc? Ça ressemble à des saltimboccas sans veau, ton affaire ;)

        • [^] # Re: Recette

          Posté par (page perso) . Évalué à 2.

          Ça ressemble à des saltimboccas sans veau, ton affaire ;)

          Ou plus simplement à une lointaine variante de Brageole.

          * Ils vendront Usenet^W les boites noires quand on aura fini de les remplir.

          • [^] # Re: Recette

            Posté par (page perso) . Évalué à 3. Dernière modification le 17/02/14 à 16:37.

            Vraiment lointaine alors, parce qu'à ce compte-là, on peut aussi considérer ça comme une variante éloignée des nems, tant qu'à faire.

    • [^] # Re: Recette

      Posté par . Évalué à 2.

      En mettant ces rouleaux avec le cure-dent à l'horizontale du coup, c'est ça ?

      Oui. Désolé Captain Obvious a pas pu venir, un peu comme tu cuirais des mini-brochettes à la poêle quoi.

      Des lamelles de quoi de porc ? Du lard ?

      Vu que dedans tu y fout de la charcutaille moi je serais plutôt parti sur de bonnes lamelles d'échine, voir de filet… Assez épaisses (faudrait pas que ça craque à la cuisson hein).

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.