Quelques essais avec le moteur de jeu LÖVE en Lua

* This post is also available in English.

Dessiné avec Pencil2D et MyPaint, animé en utilisant un maillage dans le moteur de jeu LÖVE (enlangage Lua), J’ai également fait quelques essais en C avec libSDL, mais cela ma paraît plus rapide de prototyper en Lua avec LÖVE, quitte à ajouter des bibliothèques en FFI pour les parties ayant besoin de beaucoup de calcul (dans cet exemple, les calculs sont légers et GL est utilisé pour le rendu), ou de le porter en C/SDL dans un second temps. Tous ces logiciels sont des logiciels libres, utilisés sur un système GNU/Linux.

Ce premier exemple utilise un simple maillage sur une image, et la déforme en utilisant des mouvement circulaires, comme je l’avais fait sur TIC-80 en juillet 2021. Vous pouvez récupérer les sources, images, et le paquet LÖVE pré-assemblé ici: https://framagit.org/popolon/reforest

Voici l’image utilisée comme texture du maillage, réalisé avec la branche MyPaint de Pencil2D et affiné avec MyPaint lui même :

Voici une version modifiée avec un crâne rigide, comme il est anthropomorphe. Je garde les 2 versions de l’algorithme le premier restant intéressant pour représenter de façon plus réaliste des invertébrés.

Cet autre test agglomère différentes tests d’ombrage (shaders). J’applique un seuil sur certains, au dessus de ce seuil une couleur apparaît et en dessous une autre couleur, sans ce seuil il y aurait des dégradés. Cela permet d’avoir des effets 2 couleur dans un style très épurés. J’ai mis le code source de ces ombrages pour LÖVE à disposition sur Framagit (Fichier demo01.love depuis ce site).
.

Cet autre test utilise un maillage sur une image en 2 étapes pour la texture. Ces images sont interchangées permettant l’animation de la bouche. Contrairement à la première animation, il ne s’agit pas d’une déformation utilisant des fonctions sin() de façon relativement homogène et indépendante sur la courbe. Le maillage est courbé en incrémentant l’angle à chaque étape de sa construction. Une petite onde sinusoïdale est ajoutée pour simulé un déglutition au travers du corps, à la façon de serpents qui avalent une grosse proie.

Le liquide que le monstre rejette est une autre texture. Celle ci est copiée sur un Canvas (toile) intermédiaire, afin de permettre une rotation cyclique le long de la texture (comme un scrolling sur un ruban), Cette partie ma été inspiré par les boss de fin de niveau du jeu « Conan Chop Chop ». Mais j’ai amélioré un peu le principe : Un Ombrage est alors ajouté sur le canvas au moment dfe l’afficher à l’écran, il zoom le jet sur sa longueur et ajoute un légère onde sinusoïdale. L’éclaboussure à la fin est la superposition de plusieurs fois la même animation en 3 étapes faite sous Pencil2D.

Voici le monstre dessiné rapidement avec seulement 2 étapes, pour la mise à l’épreuve du concept. Cela pourrait être optimisé sur disque en n’ayant que les 2 têtes dans le fichier et en les dupliquant dans la texture au chargement de l’image, LÖVE ne me semble pas aussi pratique que libSDL pour les maillages texturés :
bidule spritesheet

L’image utilisée comme texture pour la partie sur laquelle est appliquée l’ombrage :
flux de vomit intense

L’éclaboussure au bout du jet, chaque partie est affiché séquentiellement en boucle, et a été animé à l’aide de Pencil2D (branche MyPaint):
Éclaboussure de vomit

L’animation est d’abord réalisée avec Pencil2D, puis sauvegarde avec une image (PNG avec transparence) par image temporelle, puis à l’aide de la commande « montage » du paquet ImageMagick assemblé dans une feuille de sprite de la façon suivante:

montage sprite0001.png sprite0006.png sprite0010.png -tile 3x1 -geometry 64x128 spritesheet.png

Mise à jour du 19 mars :

En se basant sur les mêmes méthodes, j’ai amélioré le code pour gérer des animations dessinées à main levée, de manière un peu plus générique, comme texture d’un maillage. J’ai donc fait un croquis animé de l’ouverture d’une fleur pour tester ce principe.

Fleur qui s'ouvre

Elle comporte 8 images distinctes, l’ordonnancement des images, dont le temps d’apparition peut varier pour la dynmique est gérée via une table comportant le nombre d’image temporelle par image :

table = {1,1,2,2,2,3,3,4,4,4,5,5,6,6,7,8,8,8,8,8}

Je peux cycler facilement dans la table en utilisant une fonction du type math.floor( (time()*fps) % #table) ou juste lire la table pour une animation unique, pulmonique a une fleur qu’il s’ouvre ici.

Je l’ai donc utilisé comme élément décoratif. Maintenant que je vois que cela fonctionne, l’animation peut être affinée, et le code également pour être encore plus générique et avoir le besoin d’ajouter de moins en moins d’information pour ajouter rapidement de nouvelles animations.

Après être satisfait du premier jet de l’animation au sein du programme, j’ai un peu plus nettoyé, amélioré les couleurs, et me suis aperçu qu’il manquait une frame dans mon animation, la dernière était dupliquée de l’avant dernière. Dans tous les cas, il faut que je supprime l’espace inutile et que je sépare la queue de la fleur, la feuille de sprite en png fait 180~200 Ko (150 Ko recompressée avec zopflipng), c’est trop gros, multiplié par le nombre d’image et d’objets on peut rapidement se retrouver avec des dizaines de Mo de PNG sur disque et encore pire en RAM, de quoi exploser tous les caches. Je pense donc que je vais séparer la fleur de sa tige, et essayer de la cadrer plus précisément, un 64×64 devrait faire l’affaire.

Fleur qui s'ouvre améliorée

 »’Mise à jour mai 2022  »’
* Vous pouvez tester la dernière version et voir les sources à l’adresse https://framagit.org/popolon/reforest
* Les fichiers LÖVE de la dernières version, prêts à l’emploi, sont disponibles à l’adresse https://framagit.org/popolon/reforest/-/releases (Version 0.2 depuis ce site).

capture d'écran de Reforest 0.2