Professeur

Les blocs

7 messages dans ce sujet

Sommaire

 

la folie des blocs ?

Dossier : Tout savoir sur ces petites bêtes.

 

Les modèles

Petits, Grands, Musclés, vous allez les aimer.

 

Les textures

Ellessont belles, elles sont chaudes, elles vont vous faire craquer.

 

Les textures transparentes

Ellessont belles, elles sont chaudes et elles découvrent le haut.

 

Le rendu

Terre en vu !

 

Que la lumière soit !

Il fait beau, il fait chaud, l'été arrive.

 

 


Vous pouvez proposer des améliorations sur ce topic

 

2

Partager ce message


Lien à poster
Partager sur d’autres sites

Cette partie n'est qu'un brouillon, pour vous montrer que l'on ne fait pas que se prélasser au bord de la piscine, je vous met en ligne une petite partie de notre travail actuel.

Il est fort probable que vous ne compreniez pas tout, vous pouvez proposer des améliorations sur

C'est quoi ?

Le concepts des Blocs dans Minecraft :

  • Le monde sur Minecraft est composé d'une grille tridimensionnelle de blocs. La grille du monde présente une hauteur de 256 blocs seulement, mais elle s'étend indéfiniment sur les deux axes horizontaux.
  • Les blocs sont regroupés en "Chunks". Ce sont des parallélépipède de 16x256x16 blocs.
  • Les chunks sont regroupés en région; chaque région est composé de 32x32 chunks. Les régions sont stockées sur le disque, un fichier par région.
  • L'objectif de tous ces regroupements est avant tout de réduire l'espace de stockage (Les parties du monde complètements vide ne sont pas stocké sur le disque) et d'un autre coté pour permettre au ckunks d'être créées et chargés en mémoire individuellement, en fonction des besoins, sans avoir à stocker les zone que le joueur n'a pas encore exploré.
  • Le système de coordonné utilisé dans Minecraft est présenté en image juste dessous:

systeme_coordonnees.png

Regardez la classe EnumFacing pour découvrir un certain nombre de constantes et des fonctons utiles liés au six directions (Par exemple getOpposite(), rotateX(), getFrontOffsetX(), etc).

Au minimum, chaque emplacement de grille [x, y,z] contient les informations suivantes:

  • Un IBlockState, qui spécifie le type de bloc à cet emplacement (par exemple un BlockDoor) ainsi que son état actuel (par exemple ouvert ou fermé).
  • Une valeur entière "SkyLight" de 0 à 15, qui spécifie la quantité de lumière ce bloc reçoit du ciel.
  • Une valeur entière "BlockLight" de 0 à 15, qui spécifie la quantité de lumière ce bloc reçoit des blocs voisins
  • Ces données ne sont pas stockées dans la classe Block. Ils sont stockés dans un tableau à l'intérieur des objets ExtendedBlockStorage, à l'intérieur des objets Chunk.

Ils sont accessibles via diverses méthodes monde tels que :

IBlockState blockAtXYZ = world.getBlockState( {x,y,z});
int lightFromSky = world.getLightFor(SKY, {x,y,z});
int lightFromBlocks = world.getLightFor(BLOCK, {x,y,z});

L'aspect le plus important pour le moddeur à comprendre est le IBlockState. Un IBlockState est composé de deux éléments, le Bloc et ses propriétés (son état)

  • La classe Block et les classes dérivées ne stockent pas des informations uniques sur chaque position dans le monde, ils ne stockent que des informations de type bloc. Les classes bloc sont essentiellement des classes composées de méthodes pour déterminer le comportement du bloc et comment il est dessiné à l'écran. Elles sont généralement indépendante et uniques, mais pas toujours (par exemple, différents types de bois provienne de la même instance de BlockOldLog). Les instances des blocs peuvent être trouvés dans la classe Blocks; par exemple Blocks.dirt, Blocks.sand, Blocks.water.
  • Chaque bloc peut aussi avoir une ou plusieurs propriétés qui décrivent les différents états que le bloc peut présenter. Par exemple BlockLadder possède une propriété appelée EXPOSITION qui a quatre valeurs admissibles (NORTH, SOUTH, EST ou WEST) en fonction de sa direction. BlockOldLog possède une propriété appelée VARIANT avec pour valeurs admissibles OAK, SPRUCE, BIRCH, JUNGLE. Certains blocs possèdent plusieurs propriétés, telles que BlockBed qui présente plusieurs proprietés, comme FACING, avec pour valeurs admissibles NORTH, SOUTH, EAST, WEST; PART avec pour valeurs admissibles HEAD or FOOT afin de determiner la partie du lit; OCCUPIED, avec pour valeurs admissibles TRUE or FALSE;

La combinaison d'un Bloc et de son état actuel est représenté par un IBlockState.
Par exemple, un état possible de BlockBed est block_bed [facing=east, part=head, occupied=false];

Cet état peut être manipulé en utilisant :

  • IBlockState.getValue(property) pour obtenir la valeur d'une proprieté particulière, par exemple bedFacingDirection = currentBedState.getValue(FACING); qui retourne EAST.
  • IBlockState.withProperty(property, new value) pour retourner un nouvel état avec une des proprieté modifié dans la nouvelle valeur stocké, exemple IBlockState newBedState = oldBedState.withProperty(FACING, NORTH);

Si vous souhaitez determiner l'état par une valeur particulière, vous avez besoin de partir de l'état base(default), par exemple IBlockState bedFacingNorth = Blocks.bed.getDefaultState().withProperty(FACING, NORTH);

C'est un peu verbeux, mais c'est comme ça que Minecraft fait.

Un bon nombre d'autres structures de données peuvent être utilisée pour stocker plus d'informations à propos de l'emplacement d'une grille particulière :

  • TileEntity,qui stocke des informations personnalisées telles que le texte sur les panneaux, la liste des éléments dans un coffre, etc. La plupart des emplacements de grille n'ont pas TileEntity correspondante. Chaque chunk contient une liste de TileEntities, avec une entrée pour chaque TileEntity et sa position [x, y, z] dans le chunk. La TileEntity à un endroit précis est accessible en utilisants TileEntity tileEntityAtXYZ = world.getTileEntity({x,y,z});
  • L'entité (Entity) est utilisé pour certains "blocs" spéciaux comme les blocs en chute libre (Sable, gravier), les peintures et les items dans les cadres.

Plus de détails :

Les principales IProperties utilisés par Minecraft sont :

  • PropertyEnum comme VARIANT (OAK, SPRUCE, BIRCH, JUNGLE) pour BlockOldLogs
  • PropertyDirection comme FACING (N, S, E, W) pour BlockDoor
  • PropertyInteger comme AGE de 0 à 7 pour BlockCrops (Exemple la maturation du blé)
  • PropertyBool comme OCCUPIED (true/false) pour BlockBed.

Le code de base de Minecraft contient des helpers pour créer vos propres propriétés avec des noms et des valeurs personnalisées; voir les blocs de base mentionnés ci-dessus pour l'inspiration.

Pour chaque bloc donné, une instance BlockState est utilisé pour définir les états valides que le bloc correspondant peut avoir. (Le nom est trompeur car BlockState n'implémente pas IBlockState !).
Le BlockState peut être accessible à l'aide de Block.getBlockState().

Par exemple, pour la BlockState BlockBed contient trois propriétés

  • FACING, avec pour valeurs possibles NORTH, SOUTH, EAST, WEST.
  • PART, avec pour valeurs possibles HEAD ou FOOT.
  • OCCUPIED, avec pour valeurs possibles TRUE ou FALSE.

Le BlockState pour votre bloc personnalisé est créé lors de la construction de bloc en remplaçant(Override) le Block.createBlockState(). Vous devez être prudent pour définir l'état par défaut dans le constructeur de votre bloc - voir BlockBed pour un exemple.

Comme pour les versions 1.7 et antérieures, minecraft utilise seulement un total de 16 bits pour IBlockState - 12 bits pour une BlockID plus 4 bits pour les informations d'état (précédemment appelé métadonnées). En général, cela signifie qu'un bloc doit pas avoir plus de 16 états uniques. Bien que certains blocs de base ait plus de 16 combinaisons de propriétés (par exemple BlockDoor en a 64), au plus 16 d'entre eux sont effectivement stockée par emplacement de la grille. Dans l'exemple de BlockBed, bien qu'il existe 16 combinaisons possibles de valeurs, seulement 12 sont utilisé- voir le tableau ci-dessous.


tableau_orientations_lit.png

Block.getMetaFromState() et Block.getStateFromMeta() sont utilisés pour convertir la valeur IBlockState en la valeur de métadonnées entière (de 0 à 15 inclus) correspondante, et vice-versa. Quand vous implementez des blocs avec des propriétés, vous devez faire attention à retourner des valeurs de métadonnées strictements comprise entre 0 et 15, sinon vous allez remplacer les correspondances d'autres blocs. De même, vous devez vous assurer que votre getMetaFromState() et getStateFromMeta() sont équivalents.

Certaines structures de multiblocs, comme BlockDoor (La porte) ou BlockBed (Le lit), utilisent une troisième méthode appelée Block.getActualState() qui vérifie le IBlockState des autres blocs dans le multibloc, ce qui permet au multibloc de :

  • synchroniser l'état de tous les blocs dans le multibloc (Exemple BlockBed - OCCUPIED)
  • stocker une valeur d'infos superieur à 4 bits, par exemple BlockDoor:
  • - le bloc supérieur de la porte stocke le HINGE position (LEFT/RIGHT), et si la porte est POWERED ou pas.
    - le bloc inférieur de la porte stocke le FACING (NORTH, SOUTH, EAST, WEST) et si la porte est OPEN ou pas.
  • La même méthode Block.getActualState() est égalements utilisée par les blocs qui changent d'aparence en fonction de leurs voisins. Par exemple BlockFence, BlockRedstoneWire. Block.getActualState() est généralement appelé juste avant un rendu, pour être sur que le bloc présente la bonne apparence.
  • Pendant la phase d'initialisation du jeu, une instance unique est créé pour chaque bloc, voir Block.registerBlocks() et la classe Blocks. Cela signifie que vous pouvez tester l'égalité en utilisant l'opérateur == au lieu d'avoir à utiliser .equals(), par exemple boolean thisBlockIsDirt = (blockAtCursor == Blocks.dirt);
  • De même, il existe une instance unique pour chaque IBlockState, ce qui permet par exemple
    boolean stateHasChanged = (newIBlockState != currentIBlockState); au lieu de boolean stateHasChanged = !newIBlockState.equals(currentIBlockState);



Pour toute question, avis, suggestion, merci de vous rendre sur

Merci à Nopoza973 pour sa contribution.

1

Partager ce message


Lien à poster
Partager sur d’autres sites

Les modèles.

La méthode de rendu des blocs dans Minecraft a énormément évoluée lors de la mise à jour 1.8. La forme des blocs a toujoursétédéfinie dans le code, mais ce n'est qu'un lointain souvenir.Désormais, Minecraft utilise un fichier de modèle en JSON pour définir la forme ainsi que la texture.Qu'est ce que ça change ?Nous pouvons maintenant avoir plusieurs modèles pour un seul et unique bloc mais également lesmodifier depuis un pack de ressource.
Variants.png

1- Le fichier des BlockStates

Chaque bloc a un fichier de configuration de ses états, portant le nom utilisé lors de son enregistrement et situé dans assets/votreModID/blockstates,votreModIDétant minecraft en Vanilla.

Extrait de blockstates/torch.json
{
 "variants": {
 "facing=up": { "model": "normal_torch" },
 "facing=east": { "model": "normal_torch_wall" },
 "facing=south": { "model": "normal_torch_wall", "y": 90 },
 "facing=west": { "model": "normal_torch_wall", "y": 180 },
 "facing=north": { "model": "normal_torch_wall", "y": 270 }
 }
}

La torche utilise deux fichiers de modèles différents : normal_torchetnormal_torch_wall, le premier lorsqu'elle est posée au sol (sur la partie haute du bloc en dessous) et le second lorsqu'elle se trouve sur un mur.

N'oubliez pas de préciser le modid lorsqu'il s'agit d'un mod.

"model": "modid:nomdufichiermodel"

2 - Le fichier de modèle

Les modèles sont fait d'un certain nombre de faces rectangulaires, appelées quads, basées sur des éléments cuboïdes.Un cuboïde est défini par les coordonnées de deux coins opposés, "de" [x,y,z], "à" [x,y,z]. Par défaut, un bloc se présente sous la forme [0, 0, 0], [16, 16, 16].

Chaque quad est ensuite recouvert par une texture. Les coordonnées UV sont les coordonnées de la texture à appliquer, dans l'ordre [u1, v1, u2, v2], où [0, 16, 0, 16] correspond à la texture entière. On notera que la coordonnée 0 estle coin en haut à gauche de la texture.
Chacun des modèles se situent dansassets/votreModID/models/block/,votreModIDétantminecraftenVanilla.

Extrait de models/block/half_slab.json:

"elements": [
  { "from": [ 0, 0, 0 ],
    "to": [ 16, 8, 16 ],
    "faces": {
      "down": {"uv": [ 0, 0, 16, 16 ], "texture": "#bottom", "cullface": "down" },
      "up":   {"uv": [ 0, 0, 16, 16 ], "texture": "#top" },
      "north":{"uv": [ 0, 8, 16, 16 ], "texture": "#side",   "cullface": "north" },
      "south":{"uv": [ 0, 8, 16, 16 ], "texture": "#side",   "cullface": "south" },
      "west": {"uv": [ 0, 8, 16, 16 ], "texture": "#side",   "cullface": "west" },
      "east": {"uv": [ 0, 8, 16, 16 ], "texture": "#side",   "cullface": "east" }
    }
  }
]

L'ordre des coordonnées est très important, si vous les inversez, par exemple [16, 0, 0, 16] au lieu de [0, 0, 16, 16], la texture sera alors elle aussi inversée (de la gauche à la droite dans notre exemple). Les quads ne sont visible que d'un seul coté, par exemple, la face Est d'un bloc sera invisible si vous êtes derrière elle (si vous regardez le bloc de l'Ouest).

Chacune des textures est définie dans une variable initialisée dans le champs texture. Vous ne pouvez pas définir le chemin directement sur la face concernée.

Je vous invite à lire la partie sur la texturisation des blocs.

Une valeurcullfaceest parfois présente, vous pouvez y définir une direction. Si un bloc est collé dans la direction désignée alors la face ne s'affichera pas.
Cullfaces.png
Quelques petites notes :

  • ambientocclusionactive/désactive l'occlusion ambiante lors du rendu de ce bloc. L'occlusion ambiante permet d'améliorer le rendu de la lumière et des ombres, elle est adaptée pour les blocs pleins, mais pas pour les petits ou pour les formes compliquées.
  • tintindexpermet de modifier la couleur du rendu via la méthode Block.colorMultiplier(). C'est utilisé par l'herbe pour changer sa couleur dans les différents biomes.
  • shadepermet de contrôler la luminosité du bloc. S'il estfalse, l'éclairage du bloc ne sera pas dépendant de la luminosité de la face.
  • particleest la représentation 2D du bloc, utilisé pour les particules volantes lorsque le bloc est cassé.
  • Minecraft vanilla a quelques blocs "tout fait", qui n'ont pas de fichiers de modèle, comme l'air, les coffres, ... définis dans BlockModelShapes.registerAllBlocks(). Il faut aussi définir les blocs qui ont des états qui affectent le rendu dans BlockModelShapes.registerAllBlocks(). Pour les blocs customs avec des états spéciaux, vous devez appeler BlockModelShapes.registerBlockWithStateMapper() pour définir leur rendus.

Pour plus d'informations, je vous invite à consulter la documentation de Minecraft(Anglais).



Pour toute question, avis, suggestion, merci de vous rendre sur

Merci à Zetsyog pour sa contribution.

1

Partager ce message


Lien à poster
Partager sur d’autres sites

Texturer les faces (quads)

Les models des blocs sont utilisés par Minecraft pour relier les textured quads. La texture suit un système relativement strict, ça peut être difficile à maîtriser mais ce n'est vraiment pas difficile.

Dans le diagramme ci-dessous, le bloc rouge pointe vers le sud (axe Z) et le bloc bleu pointe vers l'est (axe X).

diagramme.png

Texturer en utilisant les variables UV

Les variables UV servent à découper l'image que nous souhaitons appliquer à une face. Le format [u1, V1, U2, V2] est utiliser pour sélectionner la zone à appliquer, U étant les coordonnées du point de départ etVcelles du point d'arrivé.

grille_16x16_v2.png

Attention, Les faces sont toujours rendues dans le même sens, la direction dans laquelle vous regardez n'y change rien. Il vous faudra inverser U et V pour avoir une face opposée.

La texture sera toujours affichée en direction du ciel pour les faces 2 à 5, du nord pour la 1 et du sud pour la 0.

texture_mapping.png

Je vous invite vivement à tester ce pack de ressourcesafin de bien visualiser le fonctionnement, la Stone et la Cobblestone sont utilisés.

Il va de soit que le faire à la main pour un bloc complexe est difficilement réalisable, l'alternative consiste à utiliser un programme pour vous aider à faire ces models, BDcraft Cubik me semble le plus complet pour effectuer cette tâche mais il en existe d'autres.


Pour toute question, avis, suggestion, merci de vous rendre sur

Merci à TheShark34 pour sa contribution.

2

Partager ce message


Lien à poster
Partager sur d’autres sites

Le rendu dans le monde

Le rendu des blocs a considérablement changé par rapport aux versions antérieures. Cela a rendu la compréhension un peu plus compliquée mais a introduit beaucoup plus de flexibilité pour personnaliser l'apparence des blocs sans utiliser le code.

Il y a quelques points clés à comprendre :

  • Lorsque Minecraft rend un paysage, il faut d'abord rassembler les informations sur les blocs (emplacement, apparence, etc) dans une liste d'instructions que le moteur graphique peut exécuter. Typiquement, cela signifie une itération sur chaque bloc que le joueur pourrait voir et une conversion de chaque partie du bloc en une série de rectangles texturées. Un simple bloc comme la pierre dispose de six places, une pour chaque face. Les blocs plus complexes telles qu'une torche ou un piston sont constitués d'un plus grand nombre de faces rectangulaires, peut-être à des angles différents. Une fois la phase de rendu principale complète, Minecraft finit avec une liste d'instructions contenant la couleur, les coordonnées de texture et les informations d'éclairage qui peut être exécutée par le moteur graphique pour dessiner les blocs.
  • La plupart des blocs dans un paysage sont statiques, c'est à dire qu'ils ne changent pas de forme ou de position au fil du temps. Cela permet à Minecraft de pré-compiler une liste d'instructions de rendu puis d'appeler le moteur graphique pour l'exécuter à plusieurs reprises, une fois par trame. C'est beaucoup plus rapide que la compilation des instructions de rendu à partir de zéro chaque trame. En général, les instructions ne sont recompilées que lorsque des blocs changent.
  • Les blocs dans un paysage sont rendus de quatre manières différentes (voir photo ci-dessous).
    • SOLID - La texture est totalement opaque, la valeur alpha est ignorée.
    • CUTOUT_MIPPED - (test alpha) - Les textures du bloc ont des trous et le mip mapping est activé (Voir sur Google pour plus d'informations).
    • CUTOUT - (test alpha) - Les textures du bloc ont des troussauf que le mip mapping est éteint.
    • TRANSLUCENT- (mélange alpha) - Ces textures sont partiellement transparentes de sorte à voir d'autres blocs à travers. Si l'option graphique est sur "FAST", elles deviennent opaques. Les blocs blocs translucides sont relativement coûteux à rendre parce qu'ils doivent être pré-triés dans l'ordre de leur distance par rapport à la caméra, sinon ils ne rendront pas correctement.

solid-translucent-cutout.png

Un paysage est rendu en couches - tous les blocs SOLID sont établis en premier, puis les CUTOUT_MIPPED, puis CUTOUT, et enfin les TRANSLUCENT. Un bloc donné ne peut être rendu que dans l'une de ces quatre couches, spécifiée par Block.getBlockLayer().

Chaque bloc possède également un type de rendu, spécifié par Block.getRenderType() :

  • -1 = Ne rend rien du tout, par exemple le bloc 'air'.
  • 1 = Rend comme un liquide en écoulement (texture animée) en utilisant BlockFluidRenderer.genderFluid.
  • 2 = N'utilise aucune couche de rendu des blocs maisuneTileEntitySpecialRenderer associé, par exemple le bloc 'chest'.
  • 3 = Utilise unIBakedModel pour le rendu, BlockModelRenderer.renderModel. Ceci est décrit plus en détail ci-dessous.

Il y a deux classes qui mettent en uvre l'interfaceIBakedModel,SimpleBakedModel et WeightedBakedModel. Elles sont toutes deux essentiellement identiques, sauf que la seconde choisit un modèle aléatoire à partir d'une liste de modèles alternatifs pondéré, en utilisant la position du bloc en tant que 'seed'. Cela permet pour certains blocs d'avoir une apparence différente selon l'endroit où ils sont placés.

Le format BakedModel (utilisé par Minecraft pour presque tous ses blocs) est décrit ici.
Il y a quelques considérations spéciales pour rendre les blocs transparents comme décrit ici.
L'éclairage des blocs est décritici.

Note : Certains blocs comme les fleurs utilisent la méthode Block.getOffsettype() pour déplacer de façon aléatoire la position du modèle (jusqu'à +/- 0,25 blocs).



Pour toute question, avis, suggestion, merci de vous rendre sur

Merci à Dren pour sa contribution.

1

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !


Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.


Connectez-vous maintenant