Identifiants de Tuile Globaux (Global IDs)

Plusieurs des formats de carte supportés par Tiled, notamment ses formats TMX, utilisent la même représentation des données pour les tuiles individuelles dans les calques : IDs de tuiles globaux avec flags d’inversion. Ces GIDs sont « globaux » parce qu’ils peuvent faire référence à une tuile de l’un quelconque des jeux de tuiles utilisés par la carte, plutôt que d’être locaux à un jeu de tuiles spécifique. Pour accéder à une tuile particulière à partir d’un GID, il vous faudra en premier extraire et effacer les flags d’inversion, puis il vous faudra déterminer à quel jeu de tuile la tuile appartient, and quelle tuile c’est dans le jeu de tuiles.

Note

Malgré le nom « global », les GIDs ne sont globaux que dans une seule carte. Une tuile donnée peut avoir un GID différent dans une carte différente, si cette carte a des jeux de tuiles différents, ou a ses jeux de tuiles dans un ordre différent.

Inversion de tuile

Les 4 bits de plus grand poids du GID de 32 bits sont les flags d’inversion, et il vous faudra les lire et les remettre à 0 avant de pouvoir accéder au GID lui-même pour identifier la tuile.

Le bit 32 est utilisé pour le stockage de si la tuile est inversée horizontalement, le bit 31 est utilisé pour les tuiles inversées verticalement. Dans les cartes orthogonales et isométriques, le bit 30 indique si la tuile est inversée (anti-) diagonalement, ce qui permet la rotation de la tuile, et le bit 29 peut être ignoré. Dans les cartes hexagonales, le bit 30 indique si la tuile est tournée de 60 degrés dans le sens des aiguilles d’une montre, et le bit 29 indique une rotation de 120 degrés dans ce même sens.

Note

Même si vous pasez une carte non-hexagonale, pensez à mettre le bit 29 à 0 après avoir lu les flags. Tiles conserve et ressort ce flag même si l’orientation de la carte est changée. S’il n’est pas mis à 0, vous pourriez avoir une ID de tuile invalide.

Quand vous faites un rendu d’une tuile orthographique ou isométrique, l’ordre des opérations importe. L’inversion diagonale est faite en premier, suivie pas les inversions horizontales et verticales. L’inversion diagonale devrait inverser les coins bas gauche et haut droite de la tuile, et on peut la voir comme une inversion des axes x/y. Pour les tuiles hexagonales, l’ordre n’importe pas.

Faire correspondre un GID à un ID de tuile local

Chaque jeu de tuiles a ses proprs IDs de tuiles indépendantes, commençant typiquement (mais pas toujours) à 0. Pour éviter les conflits entre des cartes utilisant des jeux de tuiles multiples, les GIDs sont assignés en séquence en fonction de la taille de chaque jeu de tuiles. A chacun est assigné un firstgid dans la carte, et c’est le GID qu’aurait la tuile ayant l’ID local 0 dans le jeu de tuiles.

Pour savoir à quel jeu de tuiles une tuile appartient, trouvez le jeu de tuiles ayant le plus grand firstgid qui est inférieur ou égal au GID de la tuile. Une fois le jeu de tuiles identifié, soustrayez son firstgid du GID de la tuile pour obtenir l’ID local de la tuile dans le jeu de tuiles.

Note

Le firstgid du premier tileset est toujours 1. Un GID de 0 dans un calque signifie que la cellule est vide.

Par exemple, voici un extrait d’un fichier TMX avec trois jeux de tuiles :

<tileset firstgid="1" source="TilesetA.tsx"/>
<tileset firstgid="65" source="TilesetB.tsx"/>
<tileset firstgid="115" source="TilesetC.tsx"/>

Dans cette carte, les tuiles avec les GISs de 1 à 64 feraient partie de TilesetA, les tuiles avec les GIDs 65 à 114 feraient partie de TilesetB, et celles avec des GIDs de 115 et au-dessus feraient partie de TilesetC. Une tuile avec un GID de 72 ferait partie de TilesetB puisqu’il a le plpus grand firstgid qui soit inférieur ou égal à 72, et son ID locale serait 7 (72-65).

Exemple de code

Le pseudo-code C++ ci-dessous, utilisant un TMX comme exemple, devrait éclaircir tout ceci, il gère les flags et déduit le jeu de tuiles approprié :

// Bits on the far end of the 32-bit global tile ID are used for tile flags
const unsigned FLIPPED_HORIZONTALLY_FLAG  = 0x80000000;
const unsigned FLIPPED_VERTICALLY_FLAG    = 0x40000000;
const unsigned FLIPPED_DIAGONALLY_FLAG    = 0x20000000;
const unsigned ROTATED_HEXAGONAL_120_FLAG = 0x10000000;

...

// Extract the contents of the <data> element
string tile_data = ...

// If the data is encoded and compressed, decode and decompress:
unsigned char *data = decompress(base64_decode(tile_data));

unsigned tile_index = 0;

// Here you should check that the data has the right size
// (map_width * map_height * 4)

for (int y = 0; y < map_height; ++y) {
  for (int x = 0; x < map_width; ++x) {
    //Read the GID in little-endian byte order:
    unsigned global_tile_id = data[tile_index] |
                              data[tile_index + 1] << 8 |
                              data[tile_index + 2] << 16 |
                              data[tile_index + 3] << 24;
    tile_index += 4;

    // Read out the flags
    bool flipped_horizontally = (global_tile_id & FLIPPED_HORIZONTALLY_FLAG);
    bool flipped_vertically = (global_tile_id & FLIPPED_VERTICALLY_FLAG);
    bool flipped_diagonally = (global_tile_id & FLIPPED_DIAGONALLY_FLAG);
    bool rotated_hex120 = (global_tile_id & ROTATED_HEXAGONAL_120_FLAG);

    // Clear all four flags
    global_tile_id &= ~(FLIPPED_HORIZONTALLY_FLAG |
                        FLIPPED_VERTICALLY_FLAG |
                        FLIPPED_DIAGONALLY_FLAG |
                        ROTATED_HEXAGONAL_120_FLAG);

    // Resolve the tile
    for (int i = tileset_count - 1; i >= 0; --i) {
      Tileset *tileset = tilesets[i];

      if (tileset->first_gid() <= global_tile_id) {
        tiles[y][x] = tileset->get_tile(global_tile_id - tileset->first_gid());
        break;
      }
    }
  }
}

(Etant donné que le code ci-dessus a été créé sur cette page du wiki et n’a pas pu être testé directement, veuillez s’il vous plaît signaler toute erreur que vous rencontrez si vous basez votre code d’analyse sur ceci. Merci !)