今天郭先生又出來製作遊戲了,最近有小夥伴要做一個邏輯轉體小遊戲,我怎麼能不先來試試呢。玩法可以看上面的連線,下面附幾張圖。線案例請點選部落格原文。
遊戲規則不懂得可以看自行百度哈,其實玩起來還挺有難度的。關於這個問題,對於新手來說,主要需要克服兩個困難。一是這個模型的旋轉軸不是固定的,每一次的旋轉都是以不同的一個邊為軸進行的。二是需要根據關卡資料渲染終點位置和陷阱(這裡使用shader)。那麼我們今天就來完成第一個難點,如何讓幾何體動態的繞非定軸轉動。我們還是一步一步來。
1. 關卡資料以及其他變數的設定
對於一個闖關型別的遊戲,設定好關卡資料和結構是十分必要的,能夠讓程式碼簡介高效。
var boxes = [], group = new THREE.Group(), box3, uniforms var square = [ { start: [[-1, -1], [-1, -2]], end: [[-1, -4], [-1, -5]], trap: [[-1, -7], [-6, -2]], color: 0xDC210E }, { start: [[-2, -1], [-3, -1], [-2, -2], [-3, -2]], end: [[-5, -6], [-6, -6], [-5, -7], [-6, -7]], trap: [[-1, -7], [-6, -2]], color: 0x097A53 }, { start: [[-1, -1], [-1, -2], [-1, -3], [-2, -1], [-2, -3]], end: [[-1, -6], [-1, -8], [-2, -6], [-2, -7], [-2, -8]], trap: [[-1, -7], [-6, -2]], color: 0x1B2991 } ];
因為不同關卡使用的道具是不一樣的,boxes就是盛放每一關小方塊的盒子,而繞非定軸轉動的主角就是這個group,因為Object3D轉動都是繞穿過中心的軸轉動的,所以我們需要將小方塊放到一個組中,並且讓小方塊相對組中心產生偏移,這樣旋轉組,我們看小方格的轉動就是繞非定軸的轉動了。box3在3D空間中表示一個盒子或立方體。其主要用於表示物體在世界座標中的邊界框,我前面也講過,不會的也可以往前翻翻,它所能完成的功能,我們通過計算也都可以完成,但是它類似於一個方法類,可以極大的簡化我們的計算,稍後我會用到一些。uniforms是向著色器傳入一些變數值的,這篇暫時用不到。square儲存著每一關的資料,start是初始位置,end是結束位置,trap是陷阱位置,color是小方塊的顏色。位置座標我們稍後再研究。
2. 佈局和初始化小方塊
首先看一下我是我們們佈局的(這個因人而異)。
看這個圖大家就懂了,我是將邏輯轉體的面放在了XOZ面上,並將平面放在了x和z的負半軸,因此他們的座標都是負值,每一個格子的邊長都是10,所以關卡資料start: [[-1, -1], [-1, -2]]代表01格和08格,這樣我們就可以將座標對映到格子上。有了這個對映我們很容易根據資料初始化小方格。
initBox() { let geom = new THREE.BoxGeometry(10, 10, 10); let mate = new THREE.MeshBasicMaterial({color: square[this.game].color, transparent: true, opacity: .8}); let mesh = new THREE.Mesh(geom, mate); boxes = []; square[this.game].start.forEach((d,i) => { let meshCopy = mesh.clone(); meshCopy.position.set(d[0] * 10+ 10 / 2, 10 / 2, d[1] * 10 + 10 / 2); meshCopy.name = 'box-' + i; boxes.push(meshCopy); scene.add(meshCopy) }) this.computedBox3(); },
這段程式碼比較簡單,小做出一個小方塊的Mesh,然後根據對映關係,將方塊的拷貝放到該放的位置,並將小方塊都放在boxes中。在每一關初始化方塊後,我們都要計算一下這些小方塊集合的box3,因為有了小放塊集合很容易得到box3,而有了box3我們又很容易知道小方塊集合的邊界和中心。
3. 實現非定軸旋轉
現在我們有了所有小方塊的集合boxes和box3,現在我們就根據上下左右的點選事件實現非定軸轉動,先看下圖。
就拿這一關來說,假如我們讓它向右轉,圖一的圖形會以右下角那條邊旋轉到圖二,下面來看看向右轉的程式碼。
var offset = new THREE.Vector3(box3.max.x, 0, 0); group.position.copy(offset); boxes.forEach(d => { d.position.sub(offset); group.add(d); }) scene.add(group);
這裡是最難理解的地方,因為我們的小方格的之前的matrix就已經是matrixWorld了(因為在scene.children中)將他們新增到一個組,再旋轉組肯定得不到我們想要的結構(因為新加的組預設還是在原點),所以呢這裡我們來了一個乾坤大挪移,將小方格向右移,將組向左移動相同的向量。
這樣子小方塊就在這個位置了(將入組之後,就相當於在組的這個位置),這樣子旋轉後,就成了我們想要的樣子,而這個向量就是這個offset,box3.max.x是小方塊集boxes的x方向的上限。再旋轉完之後呢,我們又要把組去掉(這個組就像一個殼一樣,轉完了就脫掉哈哈)。
awayFromGroup() { boxes.forEach(d => { var trans = new THREE.Vector3(); d.matrixWorld.decompose(trans, new THREE.Quaternion(), new THREE.Vector3()); d.position.copy(trans); d.updateMatrixWorld(); scene.add(d) }) scene.remove(group); this.computedWin(); this.computedBox3(); },
這裡我們找到小方塊的世界矩陣,找到位置向量trans就可以,然後將小方格重新賦予位置,這裡將小方格直接新增到場景中。這樣子就完成了乾坤大挪移,其他的方向也都類似哦,別忘了在計算box3哦,因為下一步還要使用哦,
這一篇就先講繞非定軸轉動啦,對於新手來說,這確實需要理解一下,那就先講到這了,下一篇繼續。
轉載請註明地址:郭先生的部落格