Journal opensara: un nouveau jeu libre

Posté par  (site web personnel) . Licence CC By‑SA.
51
8
oct.
2021

Bonjour Nal,

Après Newton Adventure et Ned et les maki, je me lance dans le développement de nouveaux jeux libres.

Ayant plusieurs projets en tête, j'avais décidé de faire des prototypes pour tester mes idées de gameplay. Le premier était shmuprpg, le deuxième underthief et le troisième bomberned. L'excellent moteur de recherche de linuxfr te permettra de retrouver les journaux où j'en parle et tu peux toujours y jouer sur mon site.

Je reviens aujourd'hui avec un projet plus complet: opensara

opensara logo

Le jeu

Opensara met en scène des aventures de Sara, la mascotte du très bon site opengameart.org consacré au partage de ressources pour les jeux vidéo libres.

Il s'agit de petites aventures, à jouer pendant une pause café, un peu comme on lit une bande dessinée en une page à la fin d'un journal. Petites, mais pas de tout repos: Sara va être empoisonnée, faite prisonnière d'un vampire et forcée à combattre des monstres pour la République Populaire de Grande Asie.

On choisit son aventure et on recommence autant que l'on veut. Sans être du casual gaming, le jeu est fait pour être terminable par un (jeune) enfant sans trop de mal.

Selon l'aventure, le gameplay est celui d'un jeu de plateforme ou d'un shoot them up.

gameplay

Le code et les assets

Opensara est écrit en Javascript vanilla pour brouteur. Le rendu graphique est fait avec l'API Canvas et le son avec Web Audio.

Comme une quête secondaire de ce projet était de voir ce que le Javascript moderne a dans le bide, j'ai mélangé joyeusement les styles de programmation impératifs, fonctionnels et objets 🙈 🙉 🙊 .

Les sprites ont été fait majoritairement avec Libresprite, avec un soupçon de Gimp et de Krita.

libresprite

Les bruitages ont été créés avec jsfxr.

jsfxr

Les niveaux sont éditables avec Tiled.

tiled

Le code source est bien sûr sous licence libre (MIT). Les graphismes et les bruitages aussi, mais je vais les re-licencier bientôt en CC-BY et OGA-BY quand je les mettrais sur opengameart.

Les musiques sont "empruntées" (CC-BY) au génial Centurion_of_war.

Jouer !

A toi de jouer maintenant Nal* en utilisant les touches fléchées et la barre d'espace de ton clavier ou une bonne manette:

Jouer à opensara

*: soit patient le temps de chargement peut être long. Avec mon petit serveur, Sara est longue à venir.

  • # Nikita

    Posté par  (site web personnel) . Évalué à 3.

    Sara est longue à venir.

    Se faire attendre c’est se faire désirer.

    Sinon, chouette nouvelle, je m’en vais tester ça !

    ce commentaire est sous licence cc by 4 et précédentes

  • # We need more

    Posté par  (site web personnel) . Évalué à 3.

    Rien de révolutionnaire mais c'était chouette et plaisant à jouer ! Hâte de voir la suite !
    C'est codé directement en JS ?

    • [^] # Re: We need more

      Posté par  (site web personnel) . Évalué à 7.

      Oups j'avais oublié le lien vers le code: https://framagit.org/devnewton/opensara

      Oui c'est du javascript vanilla. Dans mes précédents jeux, j'utilisais Typescript, mais je trouve que ce dernier apporte autant de problèmes que de solutions.

      Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

      • [^] # Re: We need more

        Posté par  (site web personnel) . Évalué à 5.

        C'est à dire ? Que reproches-tu a typescript ?

        "La première sécurité est la liberté"

        • [^] # Re: We need more

          Posté par  (site web personnel) . Évalué à 10.

          Pour utiliser Typescript, il un compilateur, générer les source maps pour debugger, faire en sorte que son IDE le prenne en charge…

          Tout ça pour un peu plus de complétion et quelques vérifications que du javascript simplex.

          Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

          • [^] # Commentaire supprimé

            Posté par  . Évalué à 3.

            Ce commentaire a été supprimé par l’équipe de modération.

            • [^] # Re: We need more

              Posté par  (site web personnel) . Évalué à 10.

              Utiliser Typescript n'est pas une corvée, c'est juste qu'il ajoute une couche sans apporter suffisamment.

              Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

              • [^] # Commentaire supprimé

                Posté par  . Évalué à 3. Dernière modification le 09 octobre 2021 à 23:38.

                Ce commentaire a été supprimé par l’équipe de modération.

            • [^] # Re: We need more

              Posté par  . Évalué à 5.

              Donc c'est pas vraiment un argument ;)

              Si si justement c'en est un :)

              Voui. Et un bon IDE te masque cet état de fait, rendant complètement transparent le processus.

              Beaucoup de projets ont quoi qu'il arrive une étape de build pour éviter d'avoir une quarantaine de requêtes dès le premier chargement d'une page.

              https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

              • [^] # Re: We need more

                Posté par  (site web personnel) . Évalué à 1.

                Tu veux dire que des projets essaie de compiler / compresser les assets et sont emmerder par TypeScript (qui apporte très peu, je suis d'accord avec l'auteur du journal, quitte à perdre du temps, autant utiliser Kotlin, qui pose les mêmes problème mais apporte un vrai gain.).

                Ça alors !

                On pourrait aussi ajouter que certains projets ne se compile pas via l'IDE, mais que l'IDE supporte le système de build du projet.

                • [^] # Re: We need more

                  Posté par  . Évalué à 4.

                  Tu veux dire que des projets essaie de compiler / compresser les assets et sont emmerder par TypeScript

                  Non je parle d'avoir une étape de build. Mais je suis intéressé par les problèmes que pose typescript pour ça, tu as un lien ?

                  On pourrait aussi ajouter que certains projets ne se compile pas via l'IDE, mais que l'IDE supporte le système de build du projet.

                  Je ne comprends pas de quoi tu parle. Jusqu'au début des années 2010's beaucoup d'IDE venaient avec leur propre build et certains projet ne se construisaient qu'avec l'IDE. Aujourd'hui et particulièrement dans le monde du web ça n'existe pas. Tout le monde utilise npm ou yarn peut-être avec un bundler mais tous s'utilisent en cli. Je ne comprends pas ta remarque du coup. Les éditeurs s'appuient sur ces commandes pour produire les infos dont ils ont besoins.

                  https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                  • [^] # Re: We need more

                    Posté par  . Évalué à 3.

                    Et je ne comprends pas non plus ce qu'apporte kotlin en plus vu que typescript a un typage plus expressif.

                    https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                    • [^] # Re: We need more

                      Posté par  (site web personnel) . Évalué à 3. Dernière modification le 11 octobre 2021 à 01:39.

                      En quoi le typage de Typescript est plus "expressif" que Kotlin ? Est-ce l'héritage du JAvascript ?

                      Kotlin est un langage typé statiquement. Selon moi, il a pour lui de ne pas supporter le JSON (pour beaucoup c'est un inconvénient), et le support des DSLs. Et nous l'utilisons dans pas mal de domaine (applications Android ou avec Micronaut).

                      Concernant la gestion des assets, nous avions des assets en AngularJS, Angular 2 ou 4, à certains moment nous avions du reactJs, et même du Dart avec des WebComponents, en plus du Kotlin. Aujourd'hui nous sommes entrain de supprimer tous ces composants, la seule entorse au JS, c'est le Kotlin transpilé. Notre application est modulaire au sens Gradle, les modules ont leurs propres Assets (qui n'ont pas d'espace de nommage, en production, mais en ont en mode dev). La gestion des assets est vraiment très complexes dans notre cas : le Gantt, le BI, sont des composants Gradle, les applications que l'on distribue aussi. Comme la même instance est utilisée en Chine, au US et en Europe, on se doit de ne pas avoir plusieurs fichiers Js ou Css à charger, de les compresser, d'utiliser HTTP/2 (si tu regarde ma page ça charge plutôt rapidement, même si tout cela reste classique).

                      Perso, je n'ai jamais réussi à débuguer un fichier js issue d'une transpilation en utilisant le mapping associé sur notre version de dev (donc sans compression )… Mais je ne dis pas que c'est impossible, ni que Typescript est un mauvais choix (juste que je préfère Kotlin).

                      • [^] # Re: We need more

                        Posté par  . Évalué à 6. Dernière modification le 11 octobre 2021 à 07:55.

                        Typescript est un langage typé statiquement, 100% compatible avec JS. Exemple:
                        https://www.typescriptlang.org/docs/handbook/type-inference.html

                        Il se compile en JS.
                        Le pessage de JS à TS peut être graduel et introduit peu à peu dans un même fichier source.

                        Typescript permet aussi de reconnaître des interfaces de fait entre des types différents.
                        (là où en C# ou Java par exemple, si le type n'hérite pas de l'interface, il aura beau être de fait compatible, le compilateur ne sera pas d'accord)
                        -> https://www.typescriptlang.org/docs/handbook/type-compatibility.html

                        Il provient du même cerveau qui a chapeauté C# dès le début et pendant des années, et qui auparavant a travaillé sur Delphi :
                        https://fr.wikipedia.org/wiki/Anders_Hejlsberg

                        Il n'y a aucun prob pour déboguer du Typescript, ça n'a pas les bugs de coffeescript.

                        C'est JS, mais la version bien. :)

                        "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                        • [^] # Re: We need more

                          Posté par  (site web personnel) . Évalué à 5.

                          Typescript est à Javascript ce que Scala et Kotlin sont à Java: des futurs possibles :-)

                          Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

                      • [^] # Re: We need more

                        Posté par  . Évalué à 4.

                        En quoi le typage de Typescript est plus "expressif" que Kotlin ? Est-ce l'héritage du JAvascript ?

                        Kotlin est un langage typé statiquement. Selon moi, il a pour lui de ne pas supporter le JSON (pour beaucoup c'est un inconvénient), et le support des DSLs.

                        Typescript est typé statiquement aussi (au runtime ce sera du js), mais il fait du typage structural et il permet d'exprimer des types sommes. Ce ne sont que quelques exemples, il y a encore des aspects plus subtiles (avec key of entre autre).

                        Pour les assets de ce que je comprends vous utilisiez pleins de techno différentes et c'est compliqué de tout merger. Ça peut se comprendre, même si je trouve qu'en conclure que typescript est un problème en soit c'est allé très vite en besogne.

                        Perso, je n'ai jamais réussi à débuguer un fichier js issue d'une transpilation en utilisant le mapping associé sur notre version de dev (donc sans compression )… Mais je ne dis pas que c'est impossible, ni que Typescript est un mauvais choix (juste que je préfère Kotlin).

                        C'est exactement la même technique qu'avec kotlin. Je présume que le fait que tu utilise un écosystème plus kotlin friendly doit jouer. J'essaie perso de moins chercher à utiliser mon environnement dans des contexte différents et préfère embrasser les usages du contexte en question. Par exemple si je devais faire de l'embarquer je ne tenterais pas de voir si je peux faire un build natif de java/python si l'usage est plutôt d'utiliser du C.

                        https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                        • [^] # Re: We need more

                          Posté par  . Évalué à 2. Dernière modification le 15 octobre 2021 à 16:22.

                          Les types somme sont représentables en Kotlin via les sealed classes :

                          // Dans le même fichier
                          sealed class Player()
                          
                          class Warrior(var strength: Int): Player()
                          class Wizard(var mana: Int): Player()
                          
                          // Pattern matching exhaustif
                          when (player) {
                              is Warrior -> player.strength
                              is Wizard -> player.mana
                          }

                          Après, j'en conviens, c'est peut-être un chouïa moins élégant qu'en TypeScript :

                          type Warrior = { strength: number };
                          type Wizard = { mana: number };
                          type Player = Warrior | Wizard;

                          De façon plus générale, et bien qu'étant plus habitué au typage nominal, je trouve incroyablement expressif le typage structurel de TypeScript (je pense entre autres à toi, keyof) ; on a pu faire des choses vraiment sympas avec. Du genre :

                          type MyProtocol = {
                              someMessage: {
                                  payload: string,
                                  response: boolean,
                              }
                          }
                          
                          const receiver: Receiver<MyProtocol> = {
                              onSomeMessage: (payload) => {
                                  console.log(payload);
                                  return true;
                              }
                          }

                          Cela peut paraître tout bête, mais je trouve chouette de pouvoir exprimer le fait qu'une structure prenant en charge MyProtocol doive implémenter des handlers de la forme onLeNomDuMessage. Avec bien sûr la vérification des types d'entrée et de sortie.

                          • [^] # Re: We need more

                            Posté par  . Évalué à 1.

                            Je m'auto-corrige. Il ne s'agit pas de

                            const Receiver<MyProtocol> receiver = {
                                onSomeMessage: (payload) => {
                                    console.log(payload);
                                    return true;
                                }
                            }

                            Mais plutôt de :

                            const receiver: Receiver<MyProtocol> = {
                                onSomeMessage: (payload) => {
                                    console.log(payload);
                                    return true;
                                }
                            }

                            Si un gentil modo passait par ici ;)

                          • [^] # Re: We need more

                            Posté par  . Évalué à 3.

                            Les types somme sont représentables en Kotlin via les sealed classes :

                            C'est pas juste moins élégant, c'est drastiquement plus limité. Tu dois définir tes regroupement de types et un type ne peut appartenir qu'à un seul groupe. Ça change profondément l'utilisation et c'est bien plus limitant.

                            De façon plus générale, et bien qu'étant plus habitué au typage nominal, je trouve incroyablement expressif le typage structurel de TypeScript (je pense entre autres à toi, keyof) ; on a pu faire des choses vraiment sympas avec.

                            Je suis d'accord et ça permet de ne pas lier des chose que tu ne veut pas particulièrement lier. Tu peux créer une fonction qui va prendre en paramètre un objet qui a une référence sans qu'elle est besoin de connaitre ton Warrior sur des projets de bonnes dimensions quand c'est bien utilisé ça simplifie les dépendances.

                            https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                • [^] # Re: We need more

                  Posté par  (site web personnel) . Évalué à 7.

                  Pour profiter un peu de Typescript sans l'utiliser, on peut ajouter un fichier jsconfig.json à la racine du projet avec l'option checkJs: avec vscodium, cela passe les vérifications de Typescript en utilisant les annotations jsdoc.

                  Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

      • [^] # Re: We need more

        Posté par  (site web personnel) . Évalué à 8.

        Je suis en train de réimplémenter un jeu en javascript pour apprendre ledit langage. Merci pour le code, il est hyper clair et sobre. J'adore!

        N'ayant pas l'expérience des jeux ni du web ni du javascript, je suis parti sur Pixi au niveau lib graphique mais je vois que c'est pas si dur de faire du html canvas direct. Après, il y a surement des tas de difficultés qui sont habilement masquées.

        Côté son, je comptais me pencher sur la partie web/js correspondante, mais je vois que je vais surtout me pencher sur ton code et gagner du temps :-)

        • [^] # Re: We need more

          Posté par  (site web personnel) . Évalué à 7. Dernière modification le 10 octobre 2021 à 14:01.

          Je fais du canvas, car l'API est simple et gérée par tous les brouteurs et surtout tous les systèmes graphiques (même sans accélération matérielle).

          Par contre, ce n'est pas très performant :(

          Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

          • [^] # Re: We need more

            Posté par  (site web personnel) . Évalué à 4.

            Par contre, ce n'est pas très performant :(

            Pour des jeux au tour par tour où la plupart du contenu est statique une technique qui a bien marché pour moi avec le canvas, c'est de découper en rectangles plus petit et redessiner uniquement les parties où il se passe quelque chose. C'est peut-être plus compliqué à mettre en place ici vu le temps-réel et le nombre d'animations simultanées. Cela dit, pour Mountain 1, par exemple, une telle optimisation serait a priori possible, vu que le fond est statique (il suffirait de redessiner uniquement des sous-rectangles où il y a maintenant des entités et ceux où il y en avait une au frame précédent).

          • [^] # Re: We need more

            Posté par  (site web personnel) . Évalué à 2.

            De ce point de vue là, pixijs a l'air de tenir la route. Le rendu se fait prioritairement en OpenGL et en 2D Canvas s'il n'a rien trouvé d'autre. Du coup, j'imagine que c'est plus rapide.

            Il y a des jeux assez chiadés fait en pixijs.

            • [^] # Re: We need more

              Posté par  (site web personnel) . Évalué à 6. Dernière modification le 11 octobre 2021 à 10:56.

              La difficulté pour moi, c'est qu'une couche comme Pixijs me rajoute des tests à faire:

              • rendu WebGL avec accélération graphique ;
              • rendu Canvas avec accélération graphique ;
              • rendu WebGL sans accélération graphique ;
              • rendu Canvas sans accélération graphique.

              Il est probable que certaines fonctionnalités soient lentes dans un cas et rapide dans un autre…

              Les tests sont une sacré charge de travail sur un jeu. Idéalement à chaque changement, il faudrait refaire tous les écrans, tous les niveaux… Sur Newton Adventure qui a une petite soixantaine de niveaux, ça prends 3h.

              C'est pour ça que je fais des jeux très courts maintenant :-)

              Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

            • [^] # Re: We need more

              Posté par  . Évalué à 2.

              Pixijs rend très facile l'application d'effets visuels courants sur des images ou groupes d'images (en passant par webgl), ce qui est commode pour donner à peu de frais au joueur l'impression qu'il se passe quelque chose d'intéressant.

              Une conf à ce sujet : https://www.youtube.com/watch?v=Fy0aCDmgnxg

              Pour le reste canvas est vraiment simple, stable, et très pratique à utiliser et à spécialiser selon ses besoins : s'il est suffisant, il n'y a à mon avis aucune raison d'ajouter une dépendance à pixi ou encore de passer par webgl dont l'utilisation est plutôt complexe.

  • # Commentaire supprimé

    Posté par  . Évalué à 4.

    Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: Sympatique

      Posté par  (site web personnel) . Évalué à 4. Dernière modification le 09 octobre 2021 à 13:36.

      Il faut l'écrabouiller: en plein saut, appuyer sur la touche Bas pour déclencher une attaque.

      C'est une particularité d'opensara par rapport à d'autres jeux de plateforme: un personnage ne peut en blesser un autre qu'avec une attaque.

      Drakul a pas mal de points de vie, il faut s'accrocher.

      Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

      • [^] # Re: Sympatique

        Posté par  . Évalué à 10.

        Aaaaaaah! Un petit indice pour ça serait pas mal venu. J'ai passé bien du temps sur lui avant de laisser tomber.

        J'ai essayé de lui sauter dans la face en appuyant sur espace au contact, mais sans jamais trouver quoi faire.

        Finalement je me suis demandé si la discussion d'intro "je peux passer la nuit ici?" était un indice, et qu'il fallait tenir jusqu'au lever du jour. J'ai "tenu" longtemps tout en me disant que là aussi un indice aurait été bienvenu (mouvement des étoiles, éclaircissement progressif de l'arrière-plan, etc.). Évidemment ça n'a pas marché non plus.

        Bref, l'attaque en appuyant vers le bas, c'est pas évident à deviner.

        • [^] # Commentaire supprimé

          Posté par  . Évalué à 6.

          Ce commentaire a été supprimé par l’équipe de modération.

          • [^] # Commentaire supprimé

            Posté par  . Évalué à 4.

            Ce commentaire a été supprimé par l’équipe de modération.

            • [^] # Re: Sympatique

              Posté par  (site web personnel) . Évalué à 4.

              Fampire, c'est une référence au flim* de Mel Brooks Dracula: mort et heureux de l'être :-)

              Il y a d'autres références cachées dans le jeu :-)

              *: et flim, c'est une référence au flim La classe américaine qui lui même fait référence au doublage du flim La Cité de la joie.

              Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

              • [^] # Commentaire supprimé

                Posté par  . Évalué à 3. Dernière modification le 09 octobre 2021 à 20:35.

                Ce commentaire a été supprimé par l’équipe de modération.

        • [^] # Re: Sympatique

          Posté par  (site web personnel) . Évalué à 6. Dernière modification le 09 octobre 2021 à 15:15.

          Bref, l'attaque en appuyant vers le bas, c'est pas évident à deviner.

          Oui je vais sans doute le remapper sur la barre d'espace du clavier ou le bouton B de la manette.

          Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

          • [^] # Re: Sympatique

            Posté par  (site web personnel) . Évalué à 6.

            Finalement, j'ai préféré pouvoir continuer à jouer d'une seule main (pour tenir la tasse de café avec l'autre).

            J'ai ajouté un tutorial:

            tutorial

            Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

  • # opengameart.org

    Posté par  (site web personnel) . Évalué à 10.

    J'ai relicencié en CC-BY et OGA les sprites sur opengameart

    Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

  • # Remarques en vrac

    Posté par  . Évalué à 4.

    Bravo pour ces jeux.

    Voici quelques remarques subjectives.

    Niveau difficulté, le jeu de plateformes en tableaux m'a paru assez facile, idem celui de l'avion mais je n'ai pas pu finir celui du vampire.

    Je me dis qu'il faudrait peut-être parfois davantage de feedback (visuel ?). Par exemple, j'ai mis un petit moment à comprendre que toucher un tatou ou un vautour faisait perdre un point de vie.

    Dans ces mêmes niveaux, est-ce ça ne serait pas préférable de ne plus laisser le contrôle du personnage une fois une sortie atteinte ? Si je sors et que dans la seconde suivante, je percute un ennemi, ce qui se passe ne me paraît pas clair.

    Dans le jeu d'avion, les ennemis des forces de gauche clignotent longtemps quand on les touche. Du coup, on n'a pas d'indication pour les coups suivants au but (est-ce que ça sert de leur tirer dessus pendant qu'ils clignotent ?). Peut-être que ce serait plus clair en ajoutant des petites explosions aux points de collisions.

    Le tutoriel, sinon très bien fait, ne dit pas qu'il est possible de mettre le jeu en pause au moyen de la touche "entrée".

    Enfin, je vois à travers les sources de tes tableaux qu'il est possible d'animer des tuiles dans tiled, j'étais passé à côté.

    • [^] # Re: Remarques en vrac

      Posté par  (site web personnel) . Évalué à 4.

      C'est une chose que je mettrais en place sur de prochains jeux: beaucoup plus d'effets visuels pour faire comprendre ce qui se passe !

      Les tuiles animés de Tiled sont apparus bien après les premières versions, le logiciel est aujourd'hui très riche, voire un peu trop : peu de gens implémentent l'ensemble des fritures.

      Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

  • # Grammar nazi

    Posté par  . Évalué à 1.

    Salut, juste pour dire, si on peut remplacer, "jeux vidéos" -> "jeux vidéo". Ya aussi "Opensara mets" -> "Opensara met".

    Mis à part ça, ça donne envie de jouer un peu avec JavaScript :-)

Suivre le flux des commentaires

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