ordre de dessin isométrique avec des images plus grandes que sur une seule tuile - algorithme d'ordre de dessin?

8

J'ai une carte isométrique sur laquelle je place différentes images. La plupart des images tiendront sur une seule tuile, mais certaines images sont légèrement plus grandes. Par exemple, j'ai un lit de tuiles de taille 2x3.

Cela crée un problème lors du dessin de mes objets à l'écran car j'obtiens des tuiles qui chevauchent par erreur d'autres tuiles.

Les deux solutions que je connais consistent soit à diviser l'image en segments de tuiles 1x1, soit à implémenter mon propre algorithme d'ordre de dessin, par exemple en attribuant un numéro à chaque image. L'image avec le numéro 1 est dessinée en premier, puis 2, 3 etc.

Quelqu'un a-t-il des conseils sur ce que je dois faire?

Il me semble que le fractionnement d'une image isométrique n'est pas très évident. Comment décidez-vous quelles parties de l'image sont «dans» une tuile particulière? Je ne peux pas non plus me permettre de diviser toutes mes images manuellement.

L'algorithme de l'ordre de tirage semble être un meilleur choix, mais je ne sais pas s'il sera facile à mettre en œuvre. Je ne peux pas résoudre, dans ma tête, comment gérer les situations dans lesquelles vous modifiez l'index d'une image, ce qui provoque un effet de choc sur de nombreuses autres images. Si quelqu'un a des ressources / tutoriels à ce sujet, je serais très reconnaissant.

Roger Smith
la source

Réponses:

3

Ce dont vous avez besoin s'appelle l'algorithme d'un peintre.

Vous voulez d'abord dessiner la tuile la plus éloignée, y compris tous les doodads ou personnages dessus.

Ensuite, dessinez le prochain plus proche et répétez jusqu'à la fin.

Vos objets qui s'étendent sur plus d'une tuile doivent avoir un point d'ancrage / origine déclaré. Il s'agit de la cellule de la grille qui, lorsqu'elle est dessinée, entraînera également le dessin de votre plus grand objet. Le point d'origine est choisi de sorte qu'il soit dessiné après que toutes les cellules dans lesquelles l'objet saigne sont dessinées en premier.

En fonction de votre question, votre point d'origine sera la tuile la plus proche de la caméra. (Si vous utilisez des carreaux carrés, plutôt que des carreaux en forme de losange, choisissez le carreau en bas à gauche ou en bas à droite.)

Exemple de code pour une grille carrée. Modifiez la direction de la boucle pour votre grille de diamants.

for(int y = 0; y < GridHeight; ++y) {
    for(int x = GridWidth - 1; x > -1; --x) {
        MapCell cell = getMapCell(x,y);
        DrawTerrain(cell);
        if(cell.IsDoodadOrigin){
            DrawDoodad(cell);
        }
        if(cell.IsCharacterOrigin){
            DrawCharacter(cell);
        }
    }
}
Jim
la source
Je ne vois pas comment cela peut fonctionner? Imaginez un lit 2x3 entouré complètement de boîtes. Lors de l'itération à travers les cellules, au moment où vous atteignez l '«origine» de l'objet plus grand, vous auriez déjà dessiné des boîtes qui devraient être derrière et devant le lit.
Wozza
Vous avez raison, cette technique fonctionnera pour les grilles carrées. Cela fonctionnera également pour les grilles diagonales qui utilisent des doodads / caractères carrés. Cela ne fonctionnera pas pour la forme irrégulière 2x3 sur une grille diagonale.
Jim
3

Divisez vos objets en cubes 1 × 1 × 1, en attribuant à chaque cube une image des parties de l'objet qui se trouveraient physiquement dans ce cube.

C'est facile si vous commencez avec des objets 3D réels et les rendez en 2D. Si vous dessinez vos objets directement en 2D (ou si vous avez des illustrations existantes que vous devez fractionner), cela prend un certain effort manuel. Heureusement, la division n'a pas besoin d'être exacte, tant que vous vous assurez qu'aucune des parties d'image affectées à un cube donné ne déborde en dehors de la zone hexagonale qu'un cube solide 1 × 1 × 1 à cette position couvrirait. Il peut être utile de créer une superposition montrant les contours de chaque cube en tant que couche supplémentaire dans votre éditeur graphique.

Ensuite, vous attribuez simplement une priorité à chaque cube comme p = x + y + z (en supposant que les trois coordonnées augmentent vers la caméra) et rendez les cubes par ordre croissant par priorité.


Voici un exemple rapide basé sur cette image de Wikimedia Commons (par Phasmatinox / Allefant , utilisé sous la licence CC-By-SA 3.0 ):

        Projection isométrique d'un objet étendu divisé en cubes

La commode de l'image contient deux tuiles, et j'ai dessiné les limites de ces tuiles (les hexagones rouges) par-dessus. Les parties de l'image qui se trouvent à l'intérieur de chaque hexagone doivent être attribuées à la tuile correspondante; la partie où les hexagones se chevauchent peut être affectée à l'une ou l'autre des tuiles (ou même aux deux, si vous le souhaitez), car le choix n'affectera pas le résultat final.

Notez que vous devrez peut-être élaborer sur cet algorithme simple si vous pouvez avoir plusieurs objets dans une même tuile, des murs / sols entre les tuiles ou des objets (tels que des personnes) se déplaçant facilement entre les tuiles. Les murs et les sols sont assez simples à manipuler: ils peuvent être dessinés à tout moment après le contenu de la tuile devant laquelle ils se trouvent (du point de vue de la caméra) et avant la tuile derrière laquelle ils se trouvent. C'est également une règle de base utile pour les objets se déplaçant entre les tuiles; traitez-les comme vous le feriez pour un mur entre ces carreaux.

En ce qui concerne plusieurs objets dans une tuile, ceux-ci sont parfois assez simples: par exemple, si vous aviez un livre posé sur le dessus de la poitrine dans l'image, il devrait évidemment être dessiné après la surface sur laquelle il repose. Cependant, les choses peuvent devenir plus compliquées si, par exemple, vous avez des objets sur lesquels les gens peuvent s’asseoir. Par exemple, si une personne était assise sur un banc, à l'opposé de la caméra, le corps de la personne devrait être tiré après le banc mais ses jambes (qui sont derrière le banc de la caméra) doivent être tirées avant. Une solution, dans ce cas, serait de diviser les jambes d'une personne assise en un composant séparé avec sa propre position (soit dans la tuile adjacente, soit entre les tuiles).

Ilmari Karonen
la source
1

Cela peut vous aider à partitionner vos objets par type ou par altitude. Par exemple, le paysage (sols, murs) doit être dessiné avant les objets (lits). De plus, en raison de la perspective isométrique, les tuiles de basse altitude doivent être dessinées avant celles de plus haute altitude.

De plus, si vous allez avec l'index de numérotation (Z-commande, vraiment), je recommande d' utiliser les écarts entre les numéros - ne faites pas vos planchers 1et votre lit 2. Utilisez quelque chose comme des sols = 10et des lits = 20ou 100ou quelque chose d'autre, de sorte que vous pouvez "insérer" des trucs au milieu sans incrémenter le reste par le domino.

cendres999
la source
J'ai l'intention de faire ce que vous proposez dans le premier paragraphe. Le problème que j'ai est que les objets d'un type similaire se chevauchent incorrectement. par exemple, mon lit chevauche la table de chevet. Je suggérais que je donne à chaque instance d'une image un numéro différent, sans donner à tous les lits le numéro 20, par exemple?
Roger Smith
Ça dépend. Et si vous avez deux lits côte à côte? Les gens peuvent souvent contourner cela en ajoutant des objets dans l'ordre dans lequel ils doivent être dessinés, mais je ne sais pas si cela vous aidera.
ashes999
1
Si deux lits sont côte à côte, le lit qui a la valeur y la plus élevée doit être dessiné au-dessus de l'autre. S'ils ont la même coordonnée y, alors celle avec la valeur x la plus élevée (en supposant que le haut de la carte est (0,0).
Roger Smith