Partagez
Aller en bas
avatar
tonyryu
Membre

Nombre de messages : 895
Age : 38
Localisation : Près de Nantes
Distinction : aucune
Date d'inscription : 27/05/2010
http://www.tonyryudev.com

Note technique : les Tile ID et leur décodage pour affichage

le Jeu 19 Nov 2015 - 21:14
Attention : Cette note peut donner mal au crane!!

Sommaire :
- 1) Présentation
- 2) Entrons dans le détail
- 3) Tile normal et automatique
- 4) La fonction _drawNormalTile
- 5) La fonction _drawAutotile


1 - Présentation

Vous vous demandez certainement a quoi une telle note peut servir? Globalement, dans la communauté francophone de RMMV, je pense qu'elle va intéressé une, voir 2 personnes. Je la fait, car, j'ai passé tellement de temps à analyser ce module pour mon générateur de map procédural, que je souhaite que cette analyse profite à d'autre.

Si vous avez déjà été curieux sur le contenu des fichiers MapXYZ.json, vous avez du vous du remarquer le bloc "data":[2048,2240,2432,2816,2816,...]
Ce tableau contient les Identifiants des Tiles qui constitue votre carte. Pour faire un exemple simple, j'ai créé une nouvelle carte de 2*2 tiles, avec juste le tileset 'World_A1' en couche A1 (animation)



Ce qui me donne :
"data":[2048,2048,2432,2576,0,2144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],

Alors oui, c'est imbitable!! Et c'est bien pour cela que je fait cette note! ^_^, pour y voir plus clair!!


2 - Entrons dans le détail

Comme j'ai créé une carte de 2 Tiles de large sur 2 Tiles de haut, les Id sont rangés par paquet de 4 pour chaque couche. 5 couches d'images et une couche d'id de région (onglet R dans l'éditeur de map)
- Couche 1 : 2048,2048,2432,2576
- Couche 2 : 0,2144,0,0
- Couche 3 : 0,0,0,0
- Couche 4 : 0,0,0,0
- Couche 5 : 0,0,0,0

Sachant que c'est rangé dans cet ordre :
| 1 | 2 |
| 3 | 4 |

La mécanique est la même pour chaque couche. Le programme qui sert a récupérer les fragments des fichiers images des tilesets pour les construire la map se trouve dan le fichier rpg_core.js. Et pour plus de simplicité, voici le code qui nous intéresse :

Code:
/**
 * @method _drawTile
 * @param {Bitmap} bitmap
 * @param {Number} tileId
 * @param {Number} dx
 * @param {Number} dy
 * @private
 */
Tilemap.prototype._drawTile = function(bitmap, tileId, dx, dy) {
    if (Tilemap.isVisibleTile(tileId)) {
        if (Tilemap.isAutotile(tileId)) {
            this._drawAutotile(bitmap, tileId, dx, dy);
        } else {
            this._drawNormalTile(bitmap, tileId, dx, dy);
        }
    }
};

/**
 * @method _drawNormalTile
 * @param {Bitmap} bitmap
 * @param {Number} tileId
 * @param {Number} dx
 * @param {Number} dy
 * @private
 */
Tilemap.prototype._drawNormalTile = function(bitmap, tileId, dx, dy) {
    var setNumber = 0;

    if (Tilemap.isTileA5(tileId)) {
        setNumber = 4;
    } else {
        setNumber = 5 + Math.floor(tileId / 256);
    }

    var w = this._tileWidth;
    var h = this._tileHeight;
    var sx = (Math.floor(tileId / 128) % 2 * 8 + tileId % 8 ) * w;
    var sy = (Math.floor(tileId % 256 / 8 ) % 16) * h;

    var source = this.bitmaps[setNumber];
    if (source) {
        bitmap.blt(source, sx, sy, w, h, dx, dy, w, h);
    }
};

/**
 * @method _drawAutotile
 * @param {Bitmap} bitmap
 * @param {Number} tileId
 * @param {Number} dx
 * @param {Number} dy
 * @private
 */
Tilemap.prototype._drawAutotile = function(bitmap, tileId, dx, dy) {
    var autotileTable = Tilemap.FLOOR_AUTOTILE_TABLE;
    var kind = Tilemap.getAutotileKind(tileId);
    var shape = Tilemap.getAutotileShape(tileId);
    var tx = kind % 8;
    var ty = Math.floor(kind / 8);
    var bx = 0;
    var by = 0;
    var setNumber = 0;
    var isTable = false;

    if (Tilemap.isTileA1(tileId)) {
        var waterSurfaceIndex = [0, 1, 2, 1][this._animationFrame % 4];
        setNumber = 0;
        if (kind === 0) {
            bx = waterSurfaceIndex * 2;
            by = 0;
        } else if (kind === 1) {
            bx = waterSurfaceIndex * 2;
            by = 3;
        } else if (kind === 2) {
            bx = 6;
            by = 0;
        } else if (kind === 3) {
            bx = 6;
            by = 3;
        } else {
            bx = Math.floor(tx / 4) * 8;
            by = ty * 6 + Math.floor(tx / 2) % 2 * 3;
            if (kind % 2 === 0) {
                bx += waterSurfaceIndex * 2;
            }
            else {
                bx += 6;
                autotileTable = Tilemap.WATERFALL_AUTOTILE_TABLE;
                by += this._animationFrame % 3;
            }
        }
    } else if (Tilemap.isTileA2(tileId)) {
        setNumber = 1;
        bx = tx * 2;
        by = (ty - 2) * 3;
        isTable = this._isTableTile(tileId);
    } else if (Tilemap.isTileA3(tileId)) {
        setNumber = 2;
        bx = tx * 2;
        by = (ty - 6) * 2;
        autotileTable = Tilemap.WALL_AUTOTILE_TABLE;
    } else if (Tilemap.isTileA4(tileId)) {
        setNumber = 3;
        bx = tx * 2;
        by = Math.floor((ty - 10) * 2.5 + (ty % 2 === 1 ? 0.5 : 0));
        if (ty % 2 === 1) {
            autotileTable = Tilemap.WALL_AUTOTILE_TABLE;
        }
    }

    var table = autotileTable[shape];
    var source = this.bitmaps[setNumber];

    if (table && source) {
        var w1 = this._tileWidth / 2;
        var h1 = this._tileHeight / 2;
        for (var i = 0; i < 4; i++) {
            var qsx = table[i][0];
            var qsy = table[i][1];
            var sx1 = (bx * 2 + qsx) * w1;
            var sy1 = (by * 2 + qsy) * h1;
            var dx1 = dx + (i % 2) * w1;
            var dy1 = dy + Math.floor(i / 2) * h1;
            if (isTable && (qsy === 1 || qsy === 5)) {
                var qsx2 = qsx;
                var qsy2 = 3;
                if (qsy === 1) {
                    qsx2 = [0,3,2,1][qsx];
                }
                var sx2 = (bx * 2 + qsx2) * w1;
                var sy2 = (by * 2 + qsy2) * h1;
                bitmap.blt(source, sx2, sy2, w1, h1, dx1, dy1, w1, h1);
                dy1 += h1/2;
                bitmap.blt(source, sx1, sy1, w1, h1/2, dx1, dy1, w1, h1/2);
            } else {
                bitmap.blt(source, sx1, sy1, w1, h1, dx1, dy1, w1, h1);
            }
        }
    }
};

3 fonctions de Tilemap :
- _drawTile
- _drawAutotile
- _drawNormalTile

Passons rapidement sur la fonction Tilemap.prototype._drawTile qui prend en paramètre le bitmap sur lequel on doit transférer le fragment de tileset, donc ça correspond au bitmap que l'on va afficher sur la map, l'Id du tile que l'on a récupéré dans le fichier MapXYZ.json, et les coordonnées de destination du fragment dx, dy vers le bitmap. La source est le bitmap du fichier image du tileset, et la destination le bitmap qui contiendra l'assemblage de la carte.
Cette fonction vérifie si le Tile est automatique ou normal via la fonction Tilemap.isAutotile(tileId). Pas de panique, cette fonction retourne vrai si l'id est supérieur ou égale à 2048.

Si on récapitule :
- ID >= 2048 : C'est un tile automatique, on appel la fonction _drawAutotile
- ID < 2048 : c'est un tile normal, on appel la fonction _drawNormalTile


3 - Tile normal et automatique

La question légitime que vous vous posez certainement, c'est quelle est la différence entre les 2. Pour cela, il faut faire un test relativement simple.
- Allez dans la base de données de votre projet, onglet tilesets, et ajoutez un nouveau tileset, mettez simplement l'image Outside_A2 dans A2 (terre) et Outside_A5 dans A5 (Normal). Les images A1 à A4 sont des autotiles.
- Créez une nouvelle map de 10 sur 10 utilisant ce nouveau tileset et vous allez la remplir avec un élément de Outside_A5, la grille (2éme élément de la 5éme ligne), vous voyez bien que c'est toujours le même dessin répliqué sur chaque case

- Maintenant, prenez la muraille (4éme élément dans le première ligne), et placez en un seul au milieu de la map. Rien de particulier, le dessin ajouté sur la map correspond bien au tile choisi.

- Placez une autre muraille à coté de la précédente. C'est là que ça devient intéressant, les 2 tiles cote à cote ont changé d'apparence pour qu'ils soient liés, et c'est ça qui fait que c'est un tile automatique, si l'on regarde le fichier source, la muraille est défini ainsi :


Sachant qu'un tile sur MV fait 48*48 pxl, on serait amener à penser qu'il ya 6 fragments possibles sur cette image. Et bien non, il y a 24 fragments :


Et c'est pour cela que la fonction _drawAutoTile est bien plus complexe, surtout qu'en fonction du tile utilisé, l'assemblage des fragments peut se faire de façon différente.


Dernière édition par tonyryu le Ven 20 Nov 2015 - 10:01, édité 1 fois
avatar
tonyryu
Membre

Nombre de messages : 895
Age : 38
Localisation : Près de Nantes
Distinction : aucune
Date d'inscription : 27/05/2010
http://www.tonyryudev.com

Re: Note technique : les Tile ID et leur décodage pour affichage

le Ven 20 Nov 2015 - 9:46

4 - La fonction _drawNormalTile

Code:
Tilemap.prototype._drawNormalTile = function(bitmap, tileId, dx, dy) {
    var setNumber = 0;

    if (Tilemap.isTileA5(tileId)) {
        setNumber = 4;
    } else {
        setNumber = 5 + Math.floor(tileId / 256);
    }

    var w = this._tileWidth;
    var h = this._tileHeight;
    var sx = (Math.floor(tileId / 128) % 2 * 8 + tileId % 8 ) * w;
    var sy = (Math.floor(tileId % 256 / 8 ) % 16) * h;

    var source = this.bitmaps[setNumber];
    if (source) {
        bitmap.blt(source, sx, sy, w, h, dx, dy, w, h);
    }
};

On va commencer par la plus simple, les paramètres sont les mêmes que _drawTile :
- bitmap : Bitmap dans lequel le transfert va être effectué, il représente la map en cours de construction
- tileId : Identifiant du tile a dessiner
- dx : Coordonnées X de destination en pxl
- dy : Coordonnées Y de destination en pxl

Si l'on prend l'ID du tile de la grille ci-dessus, il s'agit de : 1537.
La fonction va d'abord vérifier sur quel bitmap du tableau de bitmap source source est l'image, si il s'agit d'une image A5 (ID entre 1536 et 2048), la transfert se fera sur le bitmap 4, sinon ce sera le bitmap qui vaudra 5 + la valeur entière de la division de l'id du tile par 256. Math.floor est la fonction mathématique d'arrondi à l'entier inférieur.
Pour notre Grille 1537 est une image A5 de notre tileset, donc le bitmap source est le 4. Si on avait pour Tile ID 365, le calque serait 5 + (365 / 256) = 6

et les formules intéressantes :

   var w = this._tileWidth;
   var h = this._tileHeight;
   var sx = (Math.floor(tileId / 128) % 2 * 8 + tileId % 8 ) * w;
   var sy = (Math.floor(tileId % 256 / 8 ) % 16) * h;

toujours avec le tile ID = 1537 :

<=> w = 48
<=> h = 48

<=> sx = (Math.floor(1537 / 128) % 2 * 8 + 1537 % 8 ) * 48
<=> sx = ( 12 % 2 * 8 + 1)*48
<=> sx = ( 0 * 8 + 1)*48
<=> sx = ( 1 )*48
<=> sx = 48

<=> sy = (Math.floor(1537 % 256 / 8 ) % 16) * 48
<=> sy = (Math.floor(1 / 8 ) % 16) * 48
<=> sy = (0 % 16) * 48
<=> sy = ( 0 ) * 48
<=> sy = 0

et si l'image source existe bien, on fait le transfert du fragment de l'image source, se trouvant à la coordonnée x = 48, y = 0, avec une largeur de 48pxl et hauteur 48pxl, vers dx et dy du bitmap de destination.

Mais le plus important dans l'histoire c'est pas de comprendre comment ça fonctionne dans un sens, mais de pourvoir remonter à l'ID, quant on sait quel image on veut utiliser.

Supposons que j'ai dans mon tileset, paramétré l'image Outside_C en C. Et que je souhaite intégrer sur ma map, le petit tas d'or se trouvant en position 144, 672 sur l'image
=> (x / 48 / 8 * 128 ) + (x / 48 % 8 ) + ( y / 48 * 8 )
<=> (144 / 48 / 8 * 128 ) + (144 / 48 % 8 ) + ( 672 / 48 * 8 )
<=> 0 + 3 + 112
<=> 115

Pour chaque palette d'image, il y a un décalage :
Tilemap.TILE_ID_B      = 0;
Tilemap.TILE_ID_C      = 256;
Tilemap.TILE_ID_D      = 512;
Tilemap.TILE_ID_E      = 768;
Tilemap.TILE_ID_A5     = 1536;

Donc on ajoute 256 à 115, ce qui nous donne le Tile ID = 371. Fermez votre projet, placez cette valeur quelque part dans la table data de votre map, sauvegardez le fichier json et recharger le projet et réouvrez le projet. Si votre tileset contient l'image Outside_C en C, vous aurez un tas d'or quelque part sur la carte.

Et pour ceux qui n'aiment pas les mathématique, ya plus simple pour retrouver l'id. Ils sont numérotés les uns à la suites des autres comme cela :
[0][2][3][4][5][6][7][128][129][131][132][133][134][135][136]
[8][9][10][11][12][13][14][137][138][139][140][141][142][143][144]
etc...
Et on y ajoute la valeur de décalage.


5 - La fonction _drawAutotile

Vous aviez les cheveux qui poussaient à l'envers sur la fonction précédente? Alors, accrochez-vous à votre slip, car celle-ci c'est du costaud!!

Code:
Tilemap.prototype._drawAutotile = function(bitmap, tileId, dx, dy) {
    var autotileTable = Tilemap.FLOOR_AUTOTILE_TABLE;
    var kind = Tilemap.getAutotileKind(tileId);
    var shape = Tilemap.getAutotileShape(tileId);
    var tx = kind % 8;
    var ty = Math.floor(kind / 8);
    var bx = 0;
    var by = 0;
    var setNumber = 0;
    var isTable = false;

    if (Tilemap.isTileA1(tileId)) {
        var waterSurfaceIndex = [0, 1, 2, 1][this._animationFrame % 4];
        setNumber = 0;
        if (kind === 0) {
            bx = waterSurfaceIndex * 2;
            by = 0;
        } else if (kind === 1) {
            bx = waterSurfaceIndex * 2;
            by = 3;
        } else if (kind === 2) {
            bx = 6;
            by = 0;
        } else if (kind === 3) {
            bx = 6;
            by = 3;
        } else {
            bx = Math.floor(tx / 4) * 8;
            by = ty * 6 + Math.floor(tx / 2) % 2 * 3;
            if (kind % 2 === 0) {
                bx += waterSurfaceIndex * 2;
            }
            else {
                bx += 6;
                autotileTable = Tilemap.WATERFALL_AUTOTILE_TABLE;
                by += this._animationFrame % 3;
            }
        }
    } else if (Tilemap.isTileA2(tileId)) {
        setNumber = 1;
        bx = tx * 2;
        by = (ty - 2) * 3;
        isTable = this._isTableTile(tileId);
    } else if (Tilemap.isTileA3(tileId)) {
        setNumber = 2;
        bx = tx * 2;
        by = (ty - 6) * 2;
        autotileTable = Tilemap.WALL_AUTOTILE_TABLE;
    } else if (Tilemap.isTileA4(tileId)) {
        setNumber = 3;
        bx = tx * 2;
        by = Math.floor((ty - 10) * 2.5 + (ty % 2 === 1 ? 0.5 : 0));
        if (ty % 2 === 1) {
            autotileTable = Tilemap.WALL_AUTOTILE_TABLE;
        }
    }

    var table = autotileTable[shape];
    var source = this.bitmaps[setNumber];

    if (table && source) {
        var w1 = this._tileWidth / 2;
        var h1 = this._tileHeight / 2;
        for (var i = 0; i < 4; i++) {
            var qsx = table[i][0];
            var qsy = table[i][1];
            var sx1 = (bx * 2 + qsx) * w1;
            var sy1 = (by * 2 + qsy) * h1;
            var dx1 = dx + (i % 2) * w1;
            var dy1 = dy + Math.floor(i / 2) * h1;
            if (isTable && (qsy === 1 || qsy === 5)) {
                var qsx2 = qsx;
                var qsy2 = 3;
                if (qsy === 1) {
                    qsx2 = [0,3,2,1][qsx];
                }
                var sx2 = (bx * 2 + qsx2) * w1;
                var sy2 = (by * 2 + qsy2) * h1;
                bitmap.blt(source, sx2, sy2, w1, h1, dx1, dy1, w1, h1);
                dy1 += h1/2;
                bitmap.blt(source, sx1, sy1, w1, h1/2, dx1, dy1, w1, h1/2);
            } else {
                bitmap.blt(source, sx1, sy1, w1, h1, dx1, dy1, w1, h1);
            }
        }
    }
};

Je dois avouer que les concepteurs n'ont pas franchement fait dans le pratique pour ces autotiles, même si je comprend le souhait de vouloir mettre le plus de chose possible sur une même image, ça devient vraiment un sac de noeud a détricoter dans le programme. Je m'explique les images géré par cette fonction, sont celles que l'on place dans les compartiments suivants :
- A1 : Animation
- A2 : Terre
- A3 : Bâtiments
- A4 : Murs

Si l'on regarde la structure des images A1 :



On voit bien qu'il y déjà 3 traitements d'image possible.

Pour les images A2, c'est plus simple ce ne sont que des blocs de 96*144pxl
Pour les images A3, c'est encore plus simple ce ne sont que des blocs de 96*96pxl
Pour les images A4, ce sont une répétition de 2 lignes, une de blocs 96*144pxl et une de blocs 96*96pxl

Et tout ce petit monde est géré dans cette même fonction. Donc, oui, je vais expliquer comment elle fonctionne, mais pour le reverse, faudra attendre un petit peu, car très honnêtement je galère à mort pour y arriver. Quant j'y serais arrivé, je mettrai à la suite la fonction qui le permet, mais je ne l'expliquerai pas en détail.

Déjà, la table de décalage pour les Tiles Automatique :
Tilemap.TILE_ID_A1     = 2048;
Tilemap.TILE_ID_A2     = 2816;
Tilemap.TILE_ID_A3     = 4352;
Tilemap.TILE_ID_A4     = 5888;

On va essayer de faire simple, déjà, chaque assemblage se réserve une plage de 48 ID (shape), ça veut dire que pour le premier Tile automatique en A1 (kind = 0), l'ID sera compris entre 2048 et 2095. Et pour chaque valeur dans cette plage, correspond un assemblage de fragment (Shape).  Soyons, curieux, on va créer une nouvelle carte de 8 de large sur 6 de haut, avec un tileset contenant une image en A1, on enregistre et on ferme l'application.
Allons chercher le fichier MapXYZ.json correspondant, et on va directement modifier les data, en spécifiant, les IDs de 2048 à 2095 à la place des 0. En rouvrant le logiciel, voila ce que l'on peut obtenir (en fonction de l'image choisi en A1) :



Comme indiqué dans le chapitre 3, les planches d'autotiles sont découpées en fragment de 24*24pxl et en fonction du type d'autotile (taille de la planche, grand 96*144 pxl, moyen 96*96 pxl, petit 96*48 (cascade)), un tableau définit les coordonnées des fragments à récupérer en fonction du shape :

Code:
Tilemap.FLOOR_AUTOTILE_TABLE = [
    [[2,4],[1,4],[2,3],[1,3]],[[2,0],[1,4],[2,3],[1,3]],
    [[2,4],[3,0],[2,3],[1,3]],[[2,0],[3,0],[2,3],[1,3]],
    [[2,4],[1,4],[2,3],[3,1]],[[2,0],[1,4],[2,3],[3,1]],
    [[2,4],[3,0],[2,3],[3,1]],[[2,0],[3,0],[2,3],[3,1]],
    [[2,4],[1,4],[2,1],[1,3]],[[2,0],[1,4],[2,1],[1,3]],
    [[2,4],[3,0],[2,1],[1,3]],[[2,0],[3,0],[2,1],[1,3]],
    [[2,4],[1,4],[2,1],[3,1]],[[2,0],[1,4],[2,1],[3,1]],
    [[2,4],[3,0],[2,1],[3,1]],[[2,0],[3,0],[2,1],[3,1]],
    [[0,4],[1,4],[0,3],[1,3]],[[0,4],[3,0],[0,3],[1,3]],
    [[0,4],[1,4],[0,3],[3,1]],[[0,4],[3,0],[0,3],[3,1]],
    [[2,2],[1,2],[2,3],[1,3]],[[2,2],[1,2],[2,3],[3,1]],
    [[2,2],[1,2],[2,1],[1,3]],[[2,2],[1,2],[2,1],[3,1]],
    [[2,4],[3,4],[2,3],[3,3]],[[2,4],[3,4],[2,1],[3,3]],
    [[2,0],[3,4],[2,3],[3,3]],[[2,0],[3,4],[2,1],[3,3]],
    [[2,4],[1,4],[2,5],[1,5]],[[2,0],[1,4],[2,5],[1,5]],
    [[2,4],[3,0],[2,5],[1,5]],[[2,0],[3,0],[2,5],[1,5]],
    [[0,4],[3,4],[0,3],[3,3]],[[2,2],[1,2],[2,5],[1,5]],
    [[0,2],[1,2],[0,3],[1,3]],[[0,2],[1,2],[0,3],[3,1]],
    [[2,2],[3,2],[2,3],[3,3]],[[2,2],[3,2],[2,1],[3,3]],
    [[2,4],[3,4],[2,5],[3,5]],[[2,0],[3,4],[2,5],[3,5]],
    [[0,4],[1,4],[0,5],[1,5]],[[0,4],[3,0],[0,5],[1,5]],
    [[0,2],[3,2],[0,3],[3,3]],[[0,2],[1,2],[0,5],[1,5]],
    [[0,4],[3,4],[0,5],[3,5]],[[2,2],[3,2],[2,5],[3,5]],
    [[0,2],[3,2],[0,5],[3,5]],[[0,0],[1,0],[0,1],[1,1]]
];

Tilemap.WALL_AUTOTILE_TABLE = [
    [[2,2],[1,2],[2,1],[1,1]],[[0,2],[1,2],[0,1],[1,1]],
    [[2,0],[1,0],[2,1],[1,1]],[[0,0],[1,0],[0,1],[1,1]],
    [[2,2],[3,2],[2,1],[3,1]],[[0,2],[3,2],[0,1],[3,1]],
    [[2,0],[3,0],[2,1],[3,1]],[[0,0],[3,0],[0,1],[3,1]],
    [[2,2],[1,2],[2,3],[1,3]],[[0,2],[1,2],[0,3],[1,3]],
    [[2,0],[1,0],[2,3],[1,3]],[[0,0],[1,0],[0,3],[1,3]],
    [[2,2],[3,2],[2,3],[3,3]],[[0,2],[3,2],[0,3],[3,3]],
    [[2,0],[3,0],[2,3],[3,3]],[[0,0],[3,0],[0,3],[3,3]]
];

Tilemap.WATERFALL_AUTOTILE_TABLE = [
    [[2,0],[1,0],[2,1],[1,1]],[[0,0],[1,0],[0,1],[1,1]],
    [[2,0],[3,0],[2,1],[3,1]],[[0,0],[3,0],[0,1],[3,1]]
];

- FLOOR_AUTOTILE_TABLE : les grands de 96*144pxl, généralement pour le sol (4 fragments de large sur 6 fragments de haut)
- WALL_AUTOTILE_TABLE : les moyens de 96*96pxl, généralement pour les murs et les toitures (4 fragments de large sur 4 fragments de haut)
- WATERFALL_AUTOTILE_TABLE : les petits de 96*44pxl, généralement pour les cascades. (4 fragments de large sur 2 fragments de haut)

Ces tableaux sont à 3 dimensions, pour le FLOOR (48,4,2), le WALL (16,4,2), WATERFALL (2,4,2).
Si l'on prend le shape 0, pour le kind 0 de A1 (ID = 2048 ), l'image a afficher contient cette assemblage : [[2,4],[1,4],[2,3],[1,3]], ce qui correspond au coordonnées x et y des 4 fragments composant cette image.

Sur le même principe, je fais rapidement une carte de 4 de large sur 4 de haut, avec un tileset ayant une image de paramétré en A3. Et je veux afficher tous les assemblage possible du 10eme élément :
- Décalage de A3 : 4352
- kind du 10eme élément : 9

Ce qui nous donne un plage d'id : 4352 + (9*48 ) à 4352 + (9*48 ) + 15 <=> 4784 à 4799  (que 16 shapes possibles sur les murs)
Je remplis la table data de MapXYZ.json correspondant avec cette plage d'ID :

Revenir en haut
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum