2017-03-08 33 views
0

我正在編程一個minecraft類型的遊戲。如何在Javascript中正確聲明和調用3維地圖?

基本上我有我的X,Y,Z和塊類型。

如何聲明這是最好的方式,所以當我輸入XYZ座標時,塊的類型被返回?

E.G

function block(x, y, z, type) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
    this.type = type; 
} 

var map = new Array(); 
map[0] = new Array(); 
map[0][0] = new Array(); 

map[0][0][0] = new Block(0,0,0,grass); 
map[0][0][1] = new Block(0,0,1,stone); 
.... 
//hundreds of times later 

ctx.drawImage(map[myPositionX][myPositionY][myPositionZ].type); 

我似乎無法滿腦子都在此就如何做到這一點沒有它越來越混亂。

我可以只用對象嗎?我必須擁有3D陣列嗎?我不明白這一點

UPDATE

這真的是這樣做的正確方法?

//Map 
function Block(x, y, z, type) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
    this.type = type; 
} 

var map = []; 

for(var i = 0; i < 100; i++){  
    map[i] = [];   
    for(var j = 0; j < 100; j++){ 
     map[i][j] = []; 

     for(var k = 0; k < 10; k++){ 
      map[i][j][k] = new Block(i,j,k,"neutral"); 
     } 
    } 
} 
+1

在您使用的陣列提供的代碼。這是做到這一點的一種方法。如果你覺得它舒適,去這個 – Weedoze

+0

我不喜歡做數組的原因之一是我必須從0,0,0開始,並且不能跳進,比如說142,156,123;只有當我定義了一切。定義這樣的事情需要很長的時間。沒有其他更好的方法嗎? –

回答

1

正在關注this answer。我創建了一個片段來展示如何將它集成到代碼中。

現在,您可以map[142][156][123]

function setPropertySafe(obj) { 
 
    function isObject(o) { 
 
    if (o === null) return false; 
 
    var type = typeof o; 
 
    return type === 'object' || type === 'function'; 
 
    } 
 
    if (!isObject(obj)) return; 
 
    var prop; 
 
    for (var i = 1; i < arguments.length - 1; i++) { 
 
    prop = arguments[i]; 
 
    if (!isObject(obj[prop])) obj[prop] = {}; 
 
    if (i < arguments.length - 2) obj = obj[prop]; 
 
    } 
 

 
    obj[prop] = arguments[i]; 
 
} 
 

 
function block(x, y, z, type) { 
 
    this.x = x; 
 
    this.y = y; 
 
    this.z = z; 
 
    this.type = type; 
 
} 
 

 
var map = {}; 
 
setPropertySafe(map, 142, 156, 123, new block(142, 156, 123, 'grass')); 
 

 
console.log(map); 
 
console.log(map[142][156][123].type);

+0

謝謝!我認爲這正是我需要的。雖然如果你可以澄清一下代碼的工作原理,我會非常感激它 –

+0

@ tery.blargh你可以按照問題的鏈接 – Weedoze

0

如今在Javascript數組是稀疏數組訪問你的位置。 您可以定義兩個幫助器方法來獲取和設置一個塊。 沒有理由保持塊座標塊本身,因此,一個塊的唯一屬性保持它的類型:

map = []; //array 

getBlock = function(x,y,z) { 
    if (map[x] == null) 
     return null; 
    if (map[x][y] == null) 
     return null; 

    return map[x][y][z]; 
} 

setBlock = function(x,y,z,type) { 
    if (map[x] == null) 
     map[x] = []; 
    if (map[x][y] == null) 
     map[x][y] = []; 

    map[x][y][z] = type; 
} 

這將讓你開始。
最終你會意識到將一個塊存儲爲Number會佔用太多內存。您必須將您的地圖拆分爲sectors,其中每個扇區將編碼多個塊作爲Number

0

在我看來,擁有一個三維位置數組並不是一個有效的方法,因爲它隨着O(xyz)的增長而增加。

是否有一個特定的原因,你會需要你的整個空間被覆蓋?每個可能的xyz組合都有一個塊嗎?

更好的方法是將塊存儲在散列表(對象)或數組中。

function getCubeIdFromLocation({ x, y, z }, { min, cubeSize }) { 
    const cubeX = Math.floor((x - min[0])/cubeSize[0]) 
    const cubeY = Math.floor((y - min[1])/cubeSize[1]) 
    const cubeZ = Math.floor((z - min[2])/cubeSize[2]) 

    return (`cube${cubeX}${cubeY}${cubeZ}`) 
} 

function getHashTableAndLookupCubes(...blocks) { 
    const hashBlocks = {} 
    const lookupCubes = {} 
    let min = [0, 0, 0] 
    let max = [0, 0, 0] 
    for (let i = 0; i < blocks.lenght; i++) { 
    const block = blocks[i] 
    hashBlocks[`block${i}`] = block 

    min = [ 
     block.x < min[0] ? block.x : min[0], 
     block.y < min[1] ? block.y : min[1], 
     block.z < min[2] ? block.z : min[2], 
    ] 

    max = [ 
     block.x > max[0] ? block.x : max[0], 
     block.y > max[1] ? block.y : max[1], 
     block.z > max[2] ? block.z : max[2], 
    ] 
    } 
    // lets say you divide the space in 10 for each dimension 
    const gridSize = [10, 10, 10] 
    const cubeSize = [ 
    (max[0] - min[0])/gridSize[0], 
    (max[1] - min[1])/gridSize[1], 
    (max[2] - min[2])/gridSize[2], 
    ] 

    const gridParameters = { min, max, gridSize, cubeSize } 

    for (let i = 0; i < hashBlocks.length; i++) { 
    const block = hashBlocks[i] 

    const cubeX = Math.floor((block.x - min[0])/cubeSize[0]) 
    const cubeY = Math.floor((block.y - min[1])/cubeSize[1]) 
    const cubeZ = Math.floor((block.z - min[2])/cubeSize[2]) 
    const cubeId = `cube${cubeX}${cubeY}${cubeZ}` 

    // You could also use 
    // const cubeId = getCubeIdFromLocation({ x: block.x, y: block.y, z: block.z }, gridParameters) 

    if (lookupCubes.hasOwnProperty(cubeId)) { 
     lookupCubes[cubeId].children.push(block) 
    } else { 
     lookupCubes[cubeId] = { x: cubeX, y: cubeY, z: cubeZ, children: [] } 
    } 
    } 

    return ({ hashBlocks, lookupCubes, gridParameters }) 
} 

getHashTableAndLookupCubes(blockList) 

如果你有很多塊,以限制需要搜索的,你可以緩存在有一個x,y,z位置,並且寬度高度深度「小方塊」塊的位置量,當在特定位置查找塊時,僅查找相應立方體內的塊。

你也可以在鄰居變量和樹搜索中緩存塊的鄰居。(在代碼中未示出)

另一種可能性是使用a Proxy

相關問題