Minecraft地形生成分析(1)-世界本原

Minecraft地形生成分析(1)-世界本原

來自專欄心愛的 Code House6 人贊了文章

Now the earth was formless and empty, darkness was over the surface of the deep, and the Spirit of God was hovering over the waters.

在介紹地形生成前,我覺得有必要介紹一下minecraft中和地形相關的基本概念

基本概念

minecraft數據基本存儲結構

我們知道minecraft的地圖是由一個一個block組成,16x16x16個block組成一個section,16個section垂直排列組成一個chunk,chunk也就是我們常說的區塊,區塊的大小是16x16x256。已經生成的chunk數據存儲在文件中,未生成的不會被存儲。

block數據

每個block數據主要包括block id和meta數據,當然在傳輸過程中還會有skylight數據。

blockid用來區分區分不同種類的方塊,metavalue用來區分每一大類方塊具體數值,例如燃燒著的熔爐和普通熔爐。例如方塊的朝向。

在mc源碼中,IBlockState是BlockState的interface。主要負責表示block的屬性的抽象。

Block類則表示某一個具體的方塊。

chunk數據

每個chunk的數據包含了16x16x256的block,它也是地圖傳輸與存儲的基本單位。用戶登入伺服器後,伺服器會將user所在點周圍chunk傳給客戶端。

Minecraft中chunk有兩種表示方式,一種是Chunk,一種是ChunkPrimer。

ChunkPrimer包含的內容比較簡單,僅僅包含方塊ID。

Chunk包含的這個chunk幾乎所有數據。

ChunkPrimer

public class ChunkPrimer{ private static final IBlockState DEFAULT_STATE = Blocks.AIR.getDefaultState(); private final char[] data = new char[65536]; public IBlockState getBlockState(int x, int y, int z); public void setBlockState(int x, int y, int z, IBlockState state); private static int getBlockIndex(int x, int y, int z); /** * 從天空中的最高方塊倒數,找到第一個非空氣方塊 */ public int findGroundBlockIdx(int x, int z);}

Chunk大概這樣子

public class Chunk{ private static final Logger LOGGER = LogManager.getLogger(); public static final ExtendedBlockStorage NULL_BLOCK_STORAGE = null; /** * 用於存儲方塊ID,方塊MSB,天光圖,方塊塊亮度圖和元數據。 每個條目對應一個 * 16x16x16方塊垂直堆疊的邏輯段。 */ private final ExtendedBlockStorage[] storageArrays; /**包含每個區塊的生物群系ID,XZ平面上的16x16個ID。 */ private final byte[] blockBiomeArray; /** A map, similar to heightMap, that tracks how far down precipitation can fall. */ private final int[] precipitationHeightMap; /** 哪些列需要更新skylightMaps */ private final boolean[] updateSkylightColumns; /** 此Chunk當前是否已載入到World */ private boolean loaded; /** World 對象的引用 */ private final World world; private final int[] heightMap; /** 區塊的x坐標 */ public final int x; /** 區塊的z坐標 */ public final int z; private boolean isGapLightingUpdated; /** 這個區塊中的ChunkPositions到TileEntities的映射 */ private final Map<BlockPos, TileEntity> tileEntities; /** 包含此區塊中的實體的數組。 每個List代表一個16個方塊的子區塊。 */ private final ClassInheritanceMultiMap<Entity>[] entityLists; /** 指示是否地形被填充。 */ private boolean isTerrainPopulated; private boolean isLightPopulated; private boolean ticked; /** 如果塊已被修改並且需要在內部更新,則設置為true */ private boolean dirty; /** 這個Chunk是否有任何實體,並因此需要每tick進行保存 */ private boolean hasEntities; /** World.worldTime上次保存此區塊時的時間 */ private long lastSaveTime; /** 高度圖中的最小值 */ private int heightMapMinimum; /** 玩家在此塊中的累計tick數 */ private long inhabitedTime; /** Contains the current round-robin relight check index, and is implied as the relight check location as well. */ private int queuedLightChecks; /** 包含等待創建的tile entity的位置的隊列 */ private final ConcurrentLinkedQueue<BlockPos> tileEntityPosQueue; public boolean unloadQueued;}

我就不貼全了,Chunk類的方法實在太多了。

一般mc會在地形生成的過程中先用ChunkPrimer生成基本的方塊數據,然後用ChunkPrimer構造Chunk放入World中。

minecraft坐標系統

對於minecraft中坐標,玩家們應該都很熟悉。

  • X - 顯示你在地圖上的 東/西 位置. 正數表示東.負數表示西.
  • Y - 顯示你在地圖上的海拔高度. 整數表示位於地面上.負數表示位於地面下.
  • Z - 顯示你在地圖上的 南/北 位置. 正數表示南.負數表示北.

Minecraft的源碼中有BlockPos和ChunkPos兩個類,分別表示Block在World中的坐標,Chunk在World中的坐標。chunk在world中的坐標相當於chunk內xz負半軸方向角落上方塊的坐標除16(此處不準確,負數減一)。

最後,希望大家關注並支持我們開發的minecraft伺服器Minecase。


推薦閱讀:

TAG:沙盒遊戲 | Minecraft | 遊戲地形 |