基於WebGL HTML5 的場景小遊戲
為了實現一個基於 HTML5 的場景小遊戲,我採用了 HT for Web 來實現,短短200行程式碼,我就能實現用“第一人稱”來操作前進後退上下左右,並且實現了碰撞檢測。
先來看下實現的效果: http://www.hightopo.com/guide/guide/core/3d/examples/example_collision.html
或者 http://v.youku.com/v_show/id_XMzA5MzUzODc4NA==.html?spm=a2h3j.8428770.3416059.1 視訊中出現的幀的問題是我螢幕錄製器的問題,真正操作的時候不會有,建議用上面的連結自己操作玩玩,滑鼠或者觸屏都可以,不過我覺得最方便的還是操作鍵盤 wsad 控制上下左右。
我的想法是先把場景佈局好,程式碼如下:
createHT([100, -20, 100], '#E74C3C');
createHT([-100, -20, 100], '#1ABC9C');
createHT([100, -20, -100], '#3498DB');
createHT([-100, -20, -100], '#9B59B6');
createCurve([0, -20, 0]);
createCircle();
這幾個都是自定義的函式:
- createHT 為描繪 HT 形狀的圖,場景中有四個,所以呼叫了四次;
- createCurve 是描繪場景中間的黃色的曲線;
- createCircle 是描繪最外層的圓,因為不是全包的圓,所以也是描點畫的。
HT 中封裝了一個元件,ht.Shape(以下簡稱Shape),能夠根據描點來自由描繪圖形,可以通過 shape.setPoints(pointsArray) 將所有的點新增進陣列中,並且設定到shape中,然後通過 setSegments() 設定線段陣列資訊,也就是用什麼樣的方式來連線兩點,在Shape手冊中有著重描寫,感興趣的可以參考 HT for Web Shape 手冊。抽其中的一個描繪點的函式來看看:
function createHT(p3, color){
shape = new ht.Shape();
shape.s({
'shape.background': null,
'shape.border.width': 10,
'shape.border.color': color,
'all.color': color
});
shape.setTall(40);
shape.setThickness(5);
shape.setPoints([
// draw H
{x: 20, y: 0},
{x: 20, y: 100},
{x: 20, y: 50},
{x: 80, y: 50},
{x: 80, y: 0},
{x: 80, y: 100},
// draw T
{x: 120, y: 0},
{x: 180, y: 0},
{x: 150, y: 0},
{x: 150, y: 100}
]);
shape.setSegments([
// draw H
1, // moveTo
2, // lineTo
1, // moveTo
2, // lineTo
1, // moveTo
2, // lineTo
// draw T
1, // moveTo
2, // lineTo
1, // moveTo
2 // lineTo
]);
shape.p3(p3);
dataModel.add(shape);
return shape;
}
因為“HT”這個字眼要描繪的點比較多,所以程式碼看起來有點大,如果你看到如何描繪一個不完全的圓用20行程式碼來完成,而且包括樣式,還是會驚訝的:
shape = new ht.Shape();
shape.s({
'shape.background': null,
'shape.border.width': 10,
'shape.border.color': '#D26911',
'all.color': '#D26911'
});
shape.setTall(40);
shape.p3(0, -20, 0);
shape.setThickness(10);
var r = 300;
for(var i=0; i<36; i++){
var angle = Math.PI * 2 * i / 36;
shape.addPoint({
x: r * Math.cos(angle),
y: r * Math.sin(angle)
});
}
dataModel.add(shape);
return shape;
場景設定完畢,接下來要將在 3d 中“我”處於的位置在 2d 中也顯示出來。首先我得先設定“我”是“第一人稱漫遊模式”,直接將 g3d.setFirstPersonMode(true) 即可。第一人稱漫遊模式本質是控制 eye 和 center,如果沒有設定第一人稱漫遊模式,那麼滑鼠或者觸控板拖拽會繞著 center 旋轉。詳情參考 HT for Web 3D 手冊。
因為 HT 3D 中封裝了兩個方法 getEye 和 getCenter,這兩個方法分別是獲取 camera 的位置和目標中心點的位置,前者按照想象來說就比方你頭上有個攝像機,你走到哪裡它的中心點就拍攝到哪裡,可以很方便的記錄你的位置;後者就相當於你看出去的位置,但是這裡跟我們人不太一樣,因為人是可以廣度看到大範圍的,但是這個 center 相當於你眼球和都不能轉動,是正前方的某一點的位置就是你的視線聚焦位置。
瞭解了 getEye 和 getCenter 後我們就可以獲取當前位置和視線位置了:
g2d.addTopPainter(function(g){
var eye = g3d.getEye(),
center = g3d.getCenter();
g.fillStyle = 'red';
g.strokeStyle = 'black';
g.lineWidth = 1;
g.beginPath();
g.arc(eye[0], eye[2], 12, 0, Math.PI * 2, true); // 繪製圓,而且還能實時獲取 3d 中“我”的位置
g.fill();
g.stroke();
g.strokeStyle = 'black';
g.lineWidth = 2;
g.beginPath();
g.moveTo(eye[0], eye[2]);
g.lineTo(center[0], center[2]); // 繪製線,能實時更改“我”和“我的視線位置” 之間的線段
g.stroke();
});
但是在程式碼中我們發現,這個方法只被繪製了一次,如果不一直重繪,那麼 2d 介面的“我”的位置和移動也是不會變的,所以我們又監聽了 3d 中屬性的變化:
g3d.mp(function(e){ // 根據 3d 上的“我”的位置和視線來實時更新 2d 介面
if(e.property === 'eye' || e.property === 'center'){ // 如果 e 屬性變化為 get/setEye,get/setCenter,那麼重繪 2d 介面
g2d.redraw();
}
});
在 2D 中,我可以編輯圖元,移動它的點,變化某個圖元的大小等等功能,只要變化了圖元,那麼我的碰撞測試就得更新:
function updateBoundaries(){
boundaries = [];
dataModel.each(function(data){ // HT curve circle
// ht.Default.toBoundaries 將不連續曲線轉化成 Graph3dView#setBoundaries(bs) 需要的引數格式
boundaries = boundaries.concat(ht.Default.toBoundaries(data.getPoints(), data.getSegments()));
});
g3d.setBoundaries(boundaries); // setBoundary() 可指定碰撞邊界
}
那麼我們好奇的點在於,如何在拖拽圖元改變大小的時候還能保持碰撞檢測呢?
HT 中有一個對於屬性變化的監聽事件 addDataPropertyChangeListener(),可簡寫為md(),在我們拖拽圖元的時候,繪製這個圖元的基礎 points 就會被改變,所以我們只要監聽 points 有沒有被改變就行了,如何使用這個事件可以參考 HT for Web 資料模型手冊
dataModel.md(function(e){ // data 屬性變化事件
if(e.property === 'points'){ // 如果 data 屬性變化為 getPoints/setPoints,那麼更新邊界
updateBoundaries();
}
});
相關文章
- 基於 HTML5 WebGL 構建智慧城市 3D 場景HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 場景中的燈光效果HTMLWeb3D
- 基於 HTML5 的 WebGL 技術構建 3D 場景(一)HTMLWeb3D
- 基於 HTML5 + WebGL 的 3D 風力發電場HTMLWeb3D
- 基於 HTML5 WebGL 的智慧城市(一)HTMLWeb
- 基於 HTML5 WebGL 的垃圾分類系統HTMLWeb
- 基於 HTML5 WebGL 的 3D 挖掘機HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 機房HTMLWeb3D
- 基於 HTML5 WebGL 與 GIS 的智慧機場大資料視覺化分析HTMLWeb大資料視覺化
- 基於 HTML5 WebGL 的 3D 科幻風機HTMLWeb3D
- 基於 HTML5 的 WebGL 3D 隧道監控HTMLWeb3D
- 基於 HTML5 WebGL 智慧城市的模擬執行HTMLWeb
- 基於 HTML5 + WebGL 的 3D 風力發電場視覺化系統HTMLWeb3D視覺化
- 基於 WebGL 的 HTML5 3D 工控裙房系統WebHTML3D
- 基於 HTML5 WebGL 的 3D 模型斜面生成HTMLWeb3D模型
- 基於 WebGL HTML5 的 3D 模型分離控制WebHTML3D模型
- 基於 HTML5 WebGL 的 3D 工控裙房系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D “彈力”佈局HTMLWeb3D
- 基於場景的設計方法
- 基於HTML5 Canvas WebGL製作分離摩托車HTMLCanvasWeb
- 基於 HTML5 WebGL 的 3D 網路拓撲圖HTMLWeb3D
- 基於 HTML5 WebGL 的 智慧樓宇能源監控系統HTMLWeb
- 基於 WebGl HTML5 的 3D 視覺化機房WebHTML3D視覺化
- 基於 WebGL 的 HTML5 3D 網路拓撲圖WebHTML3D
- 基於 HTML5 WebGL 的 3D 倉儲管理系統HTMLWeb3D
- 基於HTML5的WebGL應用記憶體洩露分析HTMLWeb記憶體洩露
- 基於HTML5的WebGL設計漢諾塔3D遊戲HTMLWeb3D遊戲
- WEBGL學習【十二】滑鼠操作場景Web
- WebGL場景的兩種地面構造方法Web構造方法
- 基於 WebGL 實現的 HTML5 3D “彈力”佈局WebHTML3D
- 基於 HTML5 WebGL 實現的 3D “彈力”佈局HTMLWeb3D
- 基於 HTML5 + WebGL 的無人機 3D 視覺化系統HTMLWeb無人機3D視覺化
- 基於 HTML5 + WebGL 的太陽系 3D 展示系統HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 棉花加工監控系統WebHTML3D
- 基於 WebGL 的 HTML5 3D SCADA 主站系統WebHTML3D
- 基於 HTML5 WebGL 的 3D SCADA 主站系統HTMLWeb3D
- 基於 HTML5 WebGL 的 3D 棉花加工監控系統HTMLWeb3D
- 基於HTML5 WebGL的工業化3D電子圍欄HTMLWeb3D