🇬🇧 This gamedev article explains in french how to fix border artifact often called seams between tiles on OpenFL. Here is my tile scale hack
Description du problème
Dans le développement de jeux vidéo, si l'on place des tuiles côte à côte, il est alors possible selon le moteur de rendu utilisé d'avoir des artefacts disgracieux entre celles-ci qui prennent la forme de trou ou d'une bordure noire ou blanche. Ces artefacts appelés seams en anglais apparaissent ici ou là au grès du redimensionnement du jeu. On peut également parler de phénomène de tearing 😱.
Ici un autre exemple d'artefact entre les tiles sur GameMaker, ou là un problème de seams sur Unity ou encore une discussion sur le forum d'Unity pour éviter les seams.
Un problème similaire peut prendre la forme d'un fin trait appartenant dans l'atlas à une tuile adjacente de la tuile affichée, c'est ce qu'on appelle le texture bleeding. La solution développée ici devrait également fonctionner (cf point 3 alpha bleeding).
Quelles solutions ? 😌
Pour éviter ceci et obtenir le meilleur résultat possible, trois solutions sont à combiner.
-
1️⃣ Il faudra d'abord veiller à positionner les tuiles avec des nombres entiers.
-
2️⃣ Il faudra également légèrement surdimensionner les tuiles pour combler les trous. Il semble que nombre de développeurs redimensionnent avec un ratio de 1.01 (cf le framework HaxeFlixel1) ou même parfois légèrement plus quand parfois les résultats ne sont pas assez convaincants.
-
3️⃣ Pour openfl legacy2, il faudra de plus veiller à créer son atlas en cochant la case reduce border artifact (ou alpha bleeding) dans le logiciel TexturePacker.
Comment trouver le bon ratio ?
Pour éviter de chercher empiriquement le bon ratio, nous pouvons le calculer. Pour cela, il est indispensable de comprendre ce qui se produit. En effet, lorsqu'on redimensionne une application, il est alors possible que la taille réelle à l'écran de la tuile n'est pas un nombre entier. Il semblerait alors que la tuile soit tronquée et que l'espace entre les tuiles corresponde à peu près à la partie décimale.
Pour illustrer mon propos, voici deux exemples. L'un utilisant un nombre décimal et l'autre un nombre entier
Exemple en surimprimant un carré rouge dont la taille est un nombre décimal. Le carré recouvre parfaitement les trous.
graphics.beginFill(0xff0000);
graphics.drawRect(300, 200, 75 * 0.875, 75 * 0.875);
graphics.endFill();
Exemple en surimprimant un carré rouge dont la taille est un nombre entier. Le carré recouvre parfaitement la tuile.
graphics.beginFill(0xff0000);
graphics.drawRect(300, 200, Std.int(75 * 0.875), Std.int(75 * 0.875));
graphics.endFill();
Ainsi, avec une simple règle de trois, il est alors possible d'obtenir le ratio minimum pour combler les trous.
Il y a cependant quelques exceptions que j'ai mis en place dans le script que j'ai réalisé ci-dessous. En effet, les résultats ne semblent pas convaincants en utilisant un ratio inférieur à 1.01. Le script choisit donc le ratio en en tenant compte. Aussi, si les tuiles ne sont ni redimensionnées ni positionnées avec des nombres décimaux, il est inutile de corriger le redimensionnement de la tuile car cela pourrait rendre les contacts entre les tuiles visibles. Dans l'image suivante, on voit bien une sorte de coupure verticale dans la version redimensionnée (x1.01). A éviter donc.
Pour conclure, voici quelques images sur les résultats obtenus.
Avec openfl next. Le résultat est très bon.
Avec openfl legacy, il subsiste encore quelques artefacts, toutefois peu visibles.
Attention, avec openfl legacy, il ne faut pas oublier de cocher l'option reduce border artifact dans TexturePacker, sinon le résultat sera moins convaincant.
Script
Mon script à récupérer sur github : Fix tile trick to avoid border artifacts between tiles
- HaxeFlixel utilise désormais une autre technique pour éviter les seams↩
- OpenFL Legacy était l'ancien de moteur de rendu d'OpenFL jusqu'à 2015↩