基於HTML5 的 WebGL 3D 版俄羅斯方塊

2020-12-13 IT小精英

溫馨提示

如果你喜歡本文,請分享到朋友圈,想要獲得更多信息,關注後免費領取價值3W的全套視頻學習資料。

前言

摘要:2D 的俄羅斯方塊已經被人玩爛了,突發奇想就做了個 3D 的遊戲機,用來玩俄羅斯方塊。。。實現的基本想法是先在 2D 上實現俄羅斯方塊小遊戲,然後使用 3D 建模功能創建一個 3D 街機模型,最後將 2D 小遊戲貼到 3D 模型上。(ps:最後拓展部分實現將視頻與3D模型的結合)

不再有藍色和紫色的記憶

www.hightopo.com/demo/tetris…

代碼實現

首先,先完成 2D 小遊戲

在查看官方文檔的過程中,了解到 HT 的組件參數都是保存在 ht.DataModel() 對象中,將數據模型在視圖中進行加載後呈現各種特效。

gameDM = new ht.DataModel(); g2d = new ht.graph.GraphView(gameDM); g2d.addToDOM();開始遊戲模型的創建

第一步,先讓我們為遊戲創建一個框體,為遊戲限定範圍。在文檔中,我們可以知道 ht.Node 是 graphView 呈現節點圖元的基礎類,除了可以顯示圖片外,還能支持多種預定義的圖形。所以我打算使用該類創建4個長方形,用它們來做遊戲的範圍限定。var lineNode = new ht.Node();lineNode.s({  "shape": "rect",   "shape.background": "#D8D8D8",   "shape.border.width": 1,   "shape.border.color": "#979797"   });  lineNode.setPosition(x, y);   lineNode.setSize(width, height);   gameDM.add(lineNode);設置 x:552, y:111, width:704, height:22 後我們可以得到第一個圖形:

邊框的top已經有了,現在讓我們再創建另外三條邊來組成一個框體:

x:211, y:562, width:22, width:880x:893, y:562, width:22, width:880x:552, y:1013, width:704, width:22得到效果如下:

邊框基本完成,在瀏覽的過程中發現4個邊框可以被拖拽。接下來對邊框初始化的方法進行調整:

lineNode.s({   "shape": "rect",   "shape.background": "#D8D8D8",  "shape.border.width": 1,  "shape.border.color": "#979797",  "2d.editable" : false,   "2d.movable" : false,   "2d.selectable" : false  });生成方塊,我的想法是生成多個正方形,將它們組合成我們需要的圖形,通過坐標的計算來將它們擺放在相應的位置:

方塊生成後,開始對圖形進行旋轉操作。這其中有兩個方案,第一種是將圖形的翻轉後的圖形坐標按順序保存在數組中,每次改變形狀時取數組中的前一組或後一組坐標來進行改變;第二種是使用 ht.Block() 對象將對應的圖元組合成一個整體,在變形時只需按對應的方向選擇 90° 即可。在這裡,我選擇了第二中方式,代碼如下:

function createUnit(x, y) { var node = new ht.Node(); node.s({ "shape": "rect", "shape.background": "#D8D8D8", "shape.border.width": 1, "shape.border.color": "#979797" }); node.setPosition(x, y); node.setSize(44, 44); gameDM.add(node); return node; } var block = new ht.Block(); block.addChild(createUnit(552, 133)); block.addChild(createUnit(552, 89)); block.addChild(createUnit(508, 133)); block.addChild(createUnit(596, 133)); block.setAnchor(0.5, 0.75); block.setPosition(552, 144);Block 設置中心點 Anchor 如下圖:

在設置旋轉時,只需使用 setRotation 函數對 block 進行旋轉即可:

block.setRotation(Math.PI*rotationNum/2);方塊有了,現在就該讓它動起來了。設置定時器,使方塊每隔一段時間下降一定距離,並添加鍵盤的監聽事件,以此實現 w:翻轉、s:左移動、d:右移動、s:下移的操作,同時為了不使方塊移動出邊界,在每次位移時都將對坐標進行一次驗證:var offset = 44;var intervalTime = 1000;var topX = 552;var topY = 111;var leftSize = 211,rightSize = 882,bottomSize = 1002;var rotationNum = 0;window.addEventListener('keydown', function(e){  var index = 0;  var maxY = null;  if(e.keyCode == 87){    // up w    rotationNum ++;    block.setRotation(Math.PI*rotationNum/2);    if (!checkRotation(block)) {      rotationNum --;      block.setRotation(Math.PI*rotationNum/2);    }  } else if (e.keyCode == 65) {    // left a    moveBlock('x', -offset, block);  } else if (e.keyCode == 68) {    // right d    moveBlock('x', offset, block);  } else if(e.keyCode == 83){    // down s    moveBlock('y', offset, block);  }}, false);setInterval(function(){  if(!moveBlock("y", offset, block)){    //無法進行位移,創建新的方塊    rotationNum = 0; //方塊翻轉次數歸0    block = createNode(blockType); //生成新的方塊    blockType = parseInt(Math.random()*100%5); //下一次生成的方塊圖形  }}, intervalTime); //執行間隔//移動方塊,移動成功時返回:true,無法移動時返回:falsefunction moveBlock(axis, offset, block){  // 移動方塊  var ids = [];  var yindexs = [];  var indexArr = new Array();  for(var i = 0; i < block.size(); i ++){    var childNode = block.getChildAt(i);    var childx = childNode.getPosition().x;    var childy = childNode.getPosition().y;    if (yindexs.indexOf(childy) == -1) {      yindexs.push(childy);    }    if(axis === 'x'){      childx += offset;    }else if (axis === 'y') {      childy += offset;    }    // 驗證方塊的移動是否超出邊界    if(childx < leftSize || childx > rightSize || childy > bottomSize){      return false;    }    var obj = new Object();    obj.x = childx;    obj.y = childy;    indexArr.push(obj);    ids.push(childNode.getId());  }  //判斷圖形位移過程中是否與其他方塊觸碰  for(var j = 0; j < yindexs.length; j ++){    var indexY = yindexs[j];    if (axis === 'y') {      indexY += offset;    }    //getDatasInRect 方法能獲取到一個範圍中的所有圖元信息    var nodeList = g2d.getDatasInRect({x:233, y:indexY, width:638, height:2}, true, false);    if(nodeList.length > 0){      // 觸碰      for(var i = 0; i < nodeList.length; i++){        var x = nodeList.get(i).getPosition().x;        var y = nodeList.get(i).getPosition().y;        var id = nodeList.get(i).getId();        if (ids.indexOf(id) > -1) {          // 位移的圖元          continue;        }        for (var k = 0; k < indexArr.length; k++) {          var obj = indexArr[k];          if (obj.x === x && obj.y === y){            // 該停下了            return false;          }        }      }    }  }  var blockX = block.getX();  var blockY = block.getY();  if (axis === 'x') {    blockX += offset;  }else if (axis === 'y') {    blockY += offset;  }  // 方塊移動到新的坐標  block.setPosition(blockX, blockY);  return true;}// 驗證方塊是否可以進行翻轉function checkRotation(block){  for(var i = 0; i < block.getChildren().length; i++){    var node = block.getChildAt(i);    var childx = node.getPosition().x;    var childy = node.getPosition().y;    // 判斷翻轉後的圖形是否會超出範圍    if(childx < leftSize || childx > rightSize || childy > bottomSize){      return false;    }  }  return true;}在完成方塊的位移與變形之後,我們的小遊戲就只差最後一步了:對填充滿的方塊進行消除。在開始的時候,我們就知道所有的信息都是保存在數據模型當中,所以我們要消除方塊。只需要將它們從數據模型中刪除即可,實現代碼如下:function deleteBlock(block){  // 消除已經填充滿的方格  var yindexs = []; // 要判斷的y軸坐標  var num = 0;  for(var i = 0; i < block.size(); i ++){    var childNode = block.getChildAt(i);    var childy = childNode.getPosition().y;    var nodeList = g2d.getDatasInRect({x:233, y:childy, width:638, height:2}, true, false);    if (nodeList.length == 15) {      for(var i = 0; i < nodeList.length; i++){        gameDM.remove(nodeList.get(i)); // 在數據模型中移除對應的圖元      }      num ++;      yindexs.push(childy);    }  }  if (yindexs.length > 0) {    for(var i = 0 ; i < yindexs.length; i++){      // 將被消除圖元上方的圖元進行組合,並整體向下移動一個位置      var yindex = yindexs[i];      var h = yindex - 133 - offset;      var moveList = g2d.getDatasInRect({x:233, y:133, width:638, height:h}, true, false);      var mblock = new ht.Block();      for(var i = 0; i < moveList.size(); i++){        mblock.addChild(moveList.get(i));      }      moveBlock('y', offset, mblock);    }  }}到此,一個簡單的俄羅斯方塊小遊戲就實現了。當然,這個遊戲還有很多可以拓展的地方,比如:更多的方塊類型,遊戲分數的統計,下一步預測窗體,遊戲背景修改等。這些先不考慮,我們先開始下一步。

創建 3D 模型

在 3D 建模文檔中了解到,HT 通過一個個三角形來組合模型。

首先,先將網絡上查找到的街機模型進行拆分,將其中的各個模塊拆分成三角形面:

如圖所示,將0所在位置設置為原點(0,0,0),我們打開畫圖工具根據標尺大概估計出每個坐標相對原點的位置,將計算好的坐標數組傳入 vs 中,同時在is頂點索引坐標中將每個三角圖形的組合傳入其中:

ht.Default.setShape3dModel('damBoard', { // 為新模型起名  vs: [    0, 0, 0, //0    0.23, 0, 0,    0.23, 0.27, 0,    0.27, 0.28, 0, //3    0.27, 0.32, 0,    0.20, 0.33, 0,    0.18, 0.51, 0, // 6    0.27, 0.57, 0,    0.27, 0.655, 0,    0.20, 0.67, 0, // 9    0, 0.535, 0  ],  is: [    0, 1, 2,    0, 2, 5,    2, 3, 4,    4, 2, 5,    5, 0, 10,    10, 5, 6,    6, 7, 8,    8, 6, 9,    9, 10, 6  ]});與 2D 一樣,我們創建一個 ht.Node() 的基礎圖元,類型設置為我們新註冊的3D模型名稱:

dataModel = new ht.DataModel();g3d = new ht.graph3d.Graph3dView(dataModel);g3d.addToDOM();var node = new ht.Node();node.s({  'shape3d': 'damBoard',  'shape3d.reverse.flip': true,  '3d.movable': false,  '3d.editable': false,  '3d.selectable': false});node.p3([0, 20, 0]);node.s3([100, 100, 100]);dataModel.add(node);

已經有個側邊了,我們可以將坐標系延z軸移動一定距離後得到另一個側邊的坐標數組同時再根據沒個面的不同,分別設置 is 數組,將所有的面組合起來後,我們就將初步得到一個街機模型:

vs: [  0, 0, 0, //0  0.23, 0, 0,  0.23, 0.27, 0,  0.27, 0.28, 0, //3  0.27, 0.32, 0,  0.20, 0.33, 0,  0.18, 0.51, 0, // 6  0.27, 0.57, 0,  0.27, 0.655, 0,  0.20, 0.67, 0, // 9  0, 0.535, 0,  0, 0, 0.4, //11  0.23, 0, 0.4,  0.23, 0.27, 0.4,  0.27, 0.28, 0.4, //14  0.27, 0.32, 0.4,  0.20, 0.33, 0.4,  0.18, 0.51, 0.4, // 17  0.27, 0.57, 0.4,  0.27, 0.655, 0.4,  0.20, 0.67, 0.4, // 20  0, 0.535, 0.4,]

模型不夠美觀,我們可以給模型的每個面進行貼圖,參考文檔中對模型 uv 參數的說明,我們可以知道 uv 對應的是模型中每個頂點在圖片中的偏移量,圖片的左上角為(0, 0)右下角為(1,1), 以此我們可以為每個面設置貼圖。如:

ht.Default.setShape3dModel('damBoard', {  vs: vsArr,  is: isArr,  uv: [    0, 1,    0.81, 1,    0.81, 0.42,    1, 0.4,    1, 0.36,    0.725, 0.34,    0.65, 0.26,    1, 0.16,    1, 0.03,    0.75, 0,    0, 0.22,  ], //uv中要將is中有使用到的點的偏移量都進行設值  image: '/image/side1.jpg' //圖片地址});同理,為其他面也分別設置 uv,最終效果如下:

3D 模型整體已經建好了, 還需要給模型加上遊戲按鈕。在官方文檔建模函數中,我們可以看到已經有大量封裝完畢的圖形供我們使用。在這裡我選擇使用 createRightTriangleModel 創建直角三角形的方法來創建操作按鈕,使用 createSmoothSphereModel 函數來創建開始按鈕:ht.Default.setShape3dModel('button', ht.Default.createRightTriangleModel(true, true));ht.Default.setShape3dModel('startButton', ht.Default.createSmoothSphereModel(20, 20, 0, Math.PI * 2, 0, Math.PI));根據註冊好的模型生成按鈕:

createKeyboard('up', [21.5, 52.5, 26], [0, -Math.PI / 4, 0]);createKeyboard('down', [25.5, 51.75, 26], [0, Math.PI * 3 / 4, 0]);createKeyboard('left', [23.5, 52, 28], [0, Math.PI / 4, 0]);createKeyboard('right', [23.5, 52, 24], [0, Math.PI * 5 / 4, 0]);// 創建開始按鈕function createStartButton() {  var node = new ht.Node();  node.setTag('restart');  node.s({    'shape3d': 'startButton',    'shape3d.reverse.flip': true,    'shape3d.color': '#7ED321',    '3d.movable': false,    '3d.editable': false  });  node.p3([23.5, 52.5, 11]); // 按擺放位置  node.s3([3, 3, 3]); // 按鈕放大倍數  dataModel.add(node);}// 創建操作按鈕function createKeyboard(tag, p3, r3) {  var node = new ht.Node();  node.setTag(tag);  node.s({    'shape3d': 'button',    'shape3d.reverse.flip': true,    'shape3d.color': 'red',    '3d.movable': false,    '3d.editable': false  });  node.p3(p3); // 按擺放位置  node.s3([1.5, 1.5, 1.5]); // 按鈕放大倍數  node.r3(r3); // 將按鈕按Y軸旋轉,已保存按鈕指向正確  dataModel.add(node);}最終效果如下:

將 2D 小遊戲貼到3D模型上,在文檔中我們可以發現 setImage 屬性不僅僅是只能設置正常的圖片,還可以使用它來註冊一個 canvas 圖形組件。而2D視圖可以通過 getCanvas() 來獲取畫布信息。ht.Default.setImage('gameScrn', g2d.getCanvas());ht.Default.setShape3dModel('scrn', {  vs: vsArr,  is: isArr,  uv: scrnUV,  image: 'gameScrn' // 將註冊的2d畫布信息當成屏幕的圖片貼圖信息});// 設置 2d 的畫布大小g2d.getWidth = function () { return 1000; }g2d.getHeight = function () { return 600; }g2d.getCanvas().dynamic = true;//設置這個是為了讓canvas能動態顯示// 設置計時器,讓2d畫布上的每次改變都能及時的在3D模型上進行展示setInterval(function () {  node.iv(); // 每次改變都需要對街機模型進行刷新,刷新時間為下一幀  g2d.validateImpl(); // 立即對2D上的圖元進行刷新}, 10);// 設置500毫秒後,縮放平移整個2D畫布以展示所有的圖元setTimeout(function () {  g2d.fitContent(true);}, 500);效果如下:

在 2D 畫布上,我們已經為遊戲添加了鍵盤事件,現在我們只需要為 3D 模型上的5個按鈕分別綁定對應方法即可:g3d.mi(function (e) { // addInteractorListener 交互事件監聽器的縮寫  if (e.kind === 'clickData') { // 判斷是否為點擊事件    var tag = e.data.getTag();    if (tag === 'restart') {      gameAgain(node);    }    if (start) {      if (tag === 'up') {        block.setRotation(Math.PI * (1 + rotationNum) / 2);        rotationNum++;        if (!checkRotation(block)) {          // 邊緣變形限制          rotationNum--;          block.setRotation(Math.PI * rotationNum / 2);        }      } else if (tag === 'down') {        moveBlock('y', offset, block);      } else if (tag === 'left') {        moveBlock('x', -offset, block);      } else if (tag === 'right') {        moveBlock('x', offset, block);      }    }  }});到此基本完成了在3D街機上玩遊戲的功能。

www.hightopo.com/demo/tetris…

拓展

上面只是一個簡單的運用,既然可以將 2D 的 canvas 貼到3D上,那麼是否也可以將視頻貼上去呢。

實現代碼如下:

<video id="video1" width="270" autoplay src="3D交互.mp4" style="display:none"></video>var v = document.getElementById("video1");var node = new ht.Node();node.setSize(2200, 1100);gameDM.add(node);v.addEventListener('play', function () {  var i = window.setInterval(function () {    node.setImage(v);//將視頻截圖貼在圖元上    g2d.validateImpl();//刷新2d畫布    g3d.invalidateData(box);//刷新3d圖紙中的街機模型    if (v.ended) {      clearInterval(i)    }  }, 20);}, false);實現上有什麼問題可以直接留言或者私信或者直接去官網(hightopo.com/)上查閱相關的資料。

總結

在 3D 模型上的視頻播放給予了我很大的興趣。如果能將攝像頭的畫面轉移到對應的 3D 場景中,那麼我相信像一些日常的機房監控,智能城市和智能樓宇中的視頻監控將更加的便捷與直觀。

一碼不掃,可以掃天下?

相關焦點

  • 八大瘋狂的 HTML5 Canvas 及 WebGL 動畫效果
    我們挑選了8個由WebGL、HTML5 Canvas和Javascript製作的絕妙效果。每一個都非常簡單但卻發人深省,瘋狂並且極具創意。 黏糊糊的東西 用滑鼠拖拽,然後扔出去,就會粘在網頁邊緣。
  • 俄羅斯方塊懷舊版下載_俄羅斯方塊懷舊版手機版下載【官方安卓版...
    俄羅斯方塊懷舊版 休閒益智 大小: 0.35M
  • 玩轉HTML5 下 WebGL 的 3D 模型交並補
    本例 Demo 地址:http://hightopo.com/guide/guide/plugin/modeling/examples/example_bookshelf.html先來看下效果圖:0, 200, 0); shelf.setName('shelf1'); shelf.s({ 'all.color': '#E5BB77' }); dm.add(shelf);接著向這個 shelf 中添加 10 個節點,做書架的格子效果,並設置依附關係和父子關係添加進數據模型中:for(var i=0; i<2; i++){ for(var j=0; j<5;
  • EA的手機版《俄羅斯方塊》涼了
    而數字版遊戲則每次都需要聯網認證,所以從操作層面來講,廠商方面是有可能收回授權,讓玩家的錢白花的。這不,EA發行的手遊版《俄羅斯方塊》就進行了這樣一波操作,雖然這款遊戲價格低廉,只有1.99美元甚至免費,但從4月份開始,玩家將無法進入手遊版《俄羅斯方塊》。
  • 漢字版俄羅斯方塊是什麼遊戲 方塊上的字組成一個字
    漢字版俄羅斯方塊是什麼遊戲 方塊上的字組成一個字 漢字版俄羅斯方塊是什麼遊戲?
  • WebGL 世界 matrix入門
    地址如下,可以直接查看源碼源碼地址:https://vorshen.github.io/3Dmaze/2.html結果展示:而左手坐標系和右手坐標系中的z軸正方向不同,一個是屏幕向內,一個是屏幕向外,所以可以認為如果左手坐標系下,B矩形(z=-0.8)小於A矩形(z=-0.5),那麼理應覆蓋了A矩形,右手坐標系的話恰恰相反
  • 永無止境的俄羅斯方塊
    4月份新電腦剛入手,5月份,帕基特諾夫就開始將自己最心愛的多格骨牌遊戲往電腦上搬了。當時,花上1盧布,就能在商店裡買到3副五格骨牌。不過,12種組合旋轉起來還是有點太複雜了,那麼,如何在保證趣味性的前提下刪繁就簡呢?帕基特諾夫的做法很簡單,那就是把五變成四,這樣一來,骨牌數量就從12銳減到了7,這就是現在俄羅斯方塊的I、J、L、O、S、T、Z七種組合形狀。
  • 基於HTML5的WebGL經典3D虛擬機房漫遊動畫
    http://www.hightopo.com/demo/room-walkthrough/index.html數據模型中,詳情請參考HT for Web 序列化手冊:var g3d = window.g3d = new ht.graph3d.Graph3dView(), dataModel = g3d.dm(), view = g3d.getView(), path = null; g3d.setMovableFunc(function(data) { return false; }); g3d.setVisibleFunc
  • WebGL淺入淺出,不深入了解一下嗎?
    簡而言之,CPU 基於低延時的設計,GPU是基於大的吞吐量設計。1.2 什麼是WebGL?2.5 繪製一個正方體2.5.1 關於三維世界二維圖形和三維圖形,最明顯的區別是:三維圖形有深度,也就是z軸。我們需要考慮兩個角度:1.觀察方向:觀察者在什麼位置,在看場景的哪一部分?
  • 《魔法氣泡俄羅斯方塊2》從入門到精通 俄羅斯方塊的正確玩法
    《魔法氣泡俄羅斯方塊2》這款遊戲真的需要教程嗎?相信很多玩家對此十分不屑,今天為大家製作了《魔法氣泡俄羅斯方塊2》的進階指南,將徹底顛覆你之前對這個小遊戲的理解。俄羅斯方塊基礎規則一整行滿了就會消除。Combo4、5:對方增加2行。Combo6、7:對方增加3行。Combo8、9、10:對方增加4行。Combo11+:對方增加5行。
  • 俄羅斯方塊_俄羅斯方塊新聞_3DM新聞
    經典遊戲《俄羅斯方塊》將登陸PS4與Xbox One平臺  在遊戲市場如此發達的今天,要找一款滿足不同玩家需求的遊戲還是非常容易。
  • 漢字版俄羅斯方塊攻略大全 新手上手指南[多圖]
    漢字版俄羅斯方塊這款遊戲真是非常的有意思,聽名字就知道是俄羅斯方塊的規則,但是俄羅斯方塊是一排沒有空當就可以取消,而這個漢字版的則是要用偏旁部首組成一個完整的字,一起來看看這款遊戲攻略吧。簡單說一下這個遊戲的規則,每次出來的漢字都可以當作一個偏旁部首,要讓能組成一個漢字的部首連在一起,就能組成一個漢字成功消掉其他部分。
  • 《魔法氣泡 特趣思 俄羅斯方塊 2》多平臺今日發售
    世嘉股份有限公司,於今天2020年12月10日(四)正式發售PlayStation5/PlayStation4/Nintendo Switch /Xbox Series X/Xbox One版《魔法氣泡 特趣思 俄羅斯方塊 2》。
  • EA推出新版《俄羅斯方塊》
    【IT168 資訊】EA本月初在AppStore上架了經過修改的新版《俄羅斯方塊》(Tetris),《俄羅斯方塊》版權持有公司BPS董事長HenkRogers在隨後IndustryGamers的採訪中表示,《俄羅斯方塊》就像一項運動,將會比《憤怒的小鳥》擁有更長的生命力。
  • 俄羅斯方塊經典如何誕生 Tetris的起源
    《俄羅斯方塊》原本是前蘇聯科學家阿列克謝·帕基特諾夫在1984年6月利用空閒時間所編寫的遊戲程序,據說遊戲的作者最喜歡網球(Tennis) 運動,於是
  • EA推出免費版手機遊戲《俄羅斯方塊》
    繼推出免費版本的Scrabble《拼字遊戲》後,EA於近日又推出了一款免費版本的遊戲Tetris《俄羅斯方塊》。  這款免費版本的Tetris《俄羅斯方塊》採用了 Marathon(馬拉松)遊戲模式。EA表示公司已經對這款遊戲的整體視覺效果和控制系統進了優化。同時公司還在遊戲中植入了一個統計頁面用以追蹤用戶的遊戲時間。
  • 《Slidey: Block Puzzle》評測:另類的俄羅斯方塊
    [摘要]俄羅斯方塊是每個人都熟悉的遊戲,而今天小編將為大家帶來一款不能變形的「俄羅斯方塊」!神奇的巫師呀,快來用消除拯救精靈們吧!【騰訊遊戲頻道出品,轉載請註明!】說起俄羅斯方塊,想必大夥都不會感到陌生。因為它不僅創造了9 項金氏世界紀錄,而且不經意間已經陪伴我們玩家走過了30多年的歷程,簡直可以用「一直被模仿,從未被超越」來形容。不過即便如此,依舊有不少的遊戲開發商以它作為創作的靈感,通過自己的腦洞,以及新鮮元素的加入,讓這種另類的俄羅斯方塊,玩起來獨具特色。
  • 他一時無聊設計出俄羅斯方塊,建築師、藝術家紛紛受啟,連你也曾被方塊美學俘虜
    在這追逐流量的群雄亂戰中,俄羅斯方塊卻異軍突起,推出了帶有「吃雞」特色的玩法。《俄羅斯方塊99》是任天堂Switch平臺在 2019 年發布的一款聯機消除遊戲,最多支持99名玩家同時在在線。玩家除了消除自己屏幕上的方塊,還可以用多餘的方塊給其他人的戰局製造垃圾。
  • 《俄羅斯方塊》誕生30周年 移動版下載量4.25億次_遊俠網 Ali213.net
    《俄羅斯方塊(Tetris)》在移動平臺的累計付費下載量已經達到了4.25億次。發布這條消息的是Henk Rogers,上世紀八十年代末,他從這款永恆的經典遊戲的發明人Alexey Pajitnov手中購得了發行權,之後把遊戲帶到了任天堂遊戲機上。
  • 3D可視化應用開發 WebGL 方向怎麼實現?
    只要了解webgl,熟悉js,有一定的前端開發經驗就可以在thingjs平臺自己動手搭建可視化場景,對接數據開發應用啦~WebGL方向開發3D可視化應用真心不難,用心總能做到!* 說明:* 示例用於演示 ThingJS 項目發布後* 以 iframe 的方式嵌入到用戶系統頁面中的應用場景* 由於ThingJS在線環境與用戶系統頁面是跨域關係* 因此需使用 HTML5