婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 基于 HTML5 的 WebGL 3D 版俄羅斯方塊的示例代碼

基于 HTML5 的 WebGL 3D 版俄羅斯方塊的示例代碼

熱門標簽:濟南辦理400電話 威海營銷外呼系統招商 中紳電銷智能機器人 漳州人工外呼系統排名 農村住宅地圖標注 鶴壁手機自動外呼系統怎么安裝 跟電銷機器人做同事 鄭州電銷外呼系統違法嗎 ai電銷機器人連接網關

前言

摘要:2D 的俄羅斯方塊已經被人玩爛了,突發奇想就做了個 3D 的游戲機,用來玩俄羅斯方塊。。。實現的基本想法是先在 2D 上實現俄羅斯方塊小游戲,然后使用 3D 建模功能創建一個 3D 街機模型,最后將 2D 小游戲貼到 3D 模型上。

(ps:最后拓展部分實現將視頻與3D模型的結合)

http://www.hightopo.com/demo/tetris/

代碼實現

首先,先完成 2D 小游戲

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

gameDM = new ht.DataModel(); //初始化數據模型
g2d = new ht.graph.GraphView(gameDM); //初始化2d視圖
g2d.addToDOM(); //在頁面上創建視圖

開始游戲模型的創建

第一步,先讓我們為游戲創建一個框體,為游戲限定范圍。在文檔中,我們可以知道 ht.Node 是 graphView 呈現節點圖元的基礎類,除了可以顯示圖片外,還能支持多種預定義的圖形。所以我打算使用該類創建4個長方形,用它們來做游戲的范圍限定。

var lineNode = new ht.Node();
lineNode.s({
  "shape": "rect", //矩形
  "shape.background": "#D8D8D8", //設置底色
  "shape.border.width": 1, //邊框寬度 1
  "shape.border.color": "#979797" // 邊框顏色
});

lineNode.setPosition(x, y); // 設置圖元展示位置,左上角為0, 0 圖元坐標指向它們的中心位置
lineNode.setSize(width, height); // 設置圖元寬、高屬性

gameDM.add(lineNode); // 將設置好后的圖元信息加入數據模型中

設置 x:552, y:111, width:704, height:22 后我們可以得到第一個圖形:

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

x:211, y:562, width:22, width:880
x:893, y:562, width:22, width:880
x:552, y:1013, width:704, width:22

得到效果如下:

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

lineNode.s({
  "shape": "rect", //矩形
  "shape.background": "#D8D8D8", //設置底色
  "shape.border.width": 1, //邊框寬度 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); //rotationNum 是一個計數器,保存已經旋轉次數,保證每次都是在上一次的基礎上旋轉90°

方塊有了,現在就該讓它動起來了。設置定時器,使方塊每隔一段時間下降一定距離,并添加鍵盤的監聽事件,以此實現 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,無法移動時返回:false
function 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街機上玩游戲的功能。

http://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);

實現上有什么問題可以直接留言或者私信或者直接去官網(https://hightopo.com/)上查閱相關的資料。

總結

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

標簽:蘇州 紅河 文山 惠州 甘南 咸陽 萍鄉 營口

巨人網絡通訊聲明:本文標題《基于 HTML5 的 WebGL 3D 版俄羅斯方塊的示例代碼》,本文關鍵詞  基于,HTML5,的,WebGL,版,俄羅斯,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《基于 HTML5 的 WebGL 3D 版俄羅斯方塊的示例代碼》相關的同類信息!
  • 本頁收集關于基于 HTML5 的 WebGL 3D 版俄羅斯方塊的示例代碼的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产精品成人一区二区三区夜夜夜| 亚洲成人精品一区二区| 一区二区三区在线免费视频| 国产精品乱码一区二三区小蝌蚪| 男女性色大片免费观看一区二区| 久久精品国产**网站演员| 成人黄色国产精品网站大全在线免费观看| 欧美一区二区三区电影| 久久狠狠亚洲综合| 精品国产一二三区| 亚洲成人av在线电影| 久久99精品国产麻豆婷婷| 成人av网址在线| 一区二区三区中文字幕在线观看| 亚洲第一综合色| 欧美精品一区二区蜜臀亚洲| av中文字幕亚洲| 亚洲影院在线观看| 欧美成人性福生活免费看| 成人免费视频视频| 亚洲一区二三区| 日韩欧美电影在线| 91色综合久久久久婷婷| 欧美96一区二区免费视频| 久久久另类综合| 91麻豆swag| 开心九九激情九九欧美日韩精美视频电影 | 91麻豆精品国产91久久久久| 久久国产精品色婷婷| 欧美国产综合一区二区| 欧美日韩一区二区欧美激情 | 国产一区二区三区久久悠悠色av| 亚洲图片激情小说| 亚洲精品一区二区三区影院 | 蜜臀av一区二区三区| 菠萝蜜视频在线观看一区| 亚洲国产精品久久人人爱| 精品精品欲导航| 色欧美乱欧美15图片| 国产一区在线观看麻豆| 亚洲成人一区二区| 亚洲国产精品成人综合色在线婷婷 | 国产偷国产偷亚洲高清人白洁| 色综合久久中文字幕综合网| 青草国产精品久久久久久| 欧美日韩久久一区| 成人激情午夜影院| 国产综合一区二区| 天天色 色综合| 亚洲精选免费视频| 国产精品久久一卡二卡| 精品福利二区三区| 欧美一区二区久久| 欧美人与性动xxxx| 欧美性色黄大片| 色综合中文字幕| 成人午夜精品一区二区三区| 精品一区二区三区免费播放| 午夜精品福利在线| 欧洲一区二区三区免费视频| a美女胸又www黄视频久久| 国内成人免费视频| 午夜精品久久久久影视| 亚洲女性喷水在线观看一区| 久久久无码精品亚洲日韩按摩| 欧美三级午夜理伦三级中视频| 色诱亚洲精品久久久久久| 不卡视频在线看| 国产精品一区三区| 狠狠色丁香久久婷婷综| 久久老女人爱爱| 欧美一区二区在线不卡| 91在线视频播放| 日韩av电影免费观看高清完整版在线观看 | 国产精品入口麻豆九色| 精品美女被调教视频大全网站| 欧美日韩国产不卡| 欧美日韩国产不卡| 欧美日韩大陆在线| 欧美一级一区二区| 欧美mv日韩mv| 久久久久国产精品人| 色婷婷久久综合| 成人综合婷婷国产精品久久蜜臀| 一区二区三区精品在线| 亚洲欧美另类久久久精品| 亚洲va中文字幕| 久久久久久久久久看片| 国产精品一二三区在线| 国产一区二区中文字幕| 樱花影视一区二区| 亚洲自拍偷拍九九九| 午夜精品福利在线| 麻豆精品视频在线观看免费| 国产精品色眯眯| 日本韩国欧美在线| 国产乱码字幕精品高清av| 蜜桃视频一区二区| 国产一区二区三区国产| 日韩亚洲欧美综合| 日韩中文字幕不卡| 一区二区成人在线观看| 蜜桃免费网站一区二区三区| 国产偷国产偷亚洲高清人白洁| 日韩精品一区国产麻豆| 欧美精品一区二区三区四区 | 91丨九色丨蝌蚪富婆spa| 不卡大黄网站免费看| 欧美午夜精品久久久久久孕妇| 在线日韩一区二区| 精品久久久久久综合日本欧美| 一本大道av伊人久久综合| 欧美伊人久久久久久久久影院 | 国产色产综合产在线视频| 国产亚洲精品中文字幕| 综合激情网...| 日韩成人av影视| 成人av网站免费观看| 欧美色偷偷大香| 国产一区二区三区| 国产ts人妖一区二区| 91蜜桃视频在线| 欧美一级一区二区| 中文字幕亚洲精品在线观看| 日韩在线卡一卡二| 一级特黄大欧美久久久| 国产成人av电影免费在线观看| 欧美色网一区二区| 欧美激情中文不卡| 亚洲欧美综合在线精品| 久久99久久99| 欧美丝袜丝交足nylons图片| 久久亚洲一区二区三区明星换脸| 91精品婷婷国产综合久久性色| 国产精品不卡在线| 国内精品不卡在线| 欧美剧在线免费观看网站| 欧美高清在线精品一区| 久久99久国产精品黄毛片色诱| 99国产麻豆精品| 精品动漫一区二区三区在线观看| 亚洲风情在线资源站| 麻豆91在线播放| 亚洲国产精品嫩草影院| 东方欧美亚洲色图在线| 99国内精品久久| 国产色一区二区| 美女诱惑一区二区| 欧美在线观看视频一区二区三区| 国产精品久久综合| 国产高清亚洲一区| 亚洲精品在线电影| 国产成人一区在线| 日韩一级在线观看| 欧美日韩国产综合一区二区 | 日本欧美在线看| 在线中文字幕不卡| 中文字幕中文字幕在线一区| 成人午夜视频网站| ●精品国产综合乱码久久久久| 成人av网站在线| 一本大道av伊人久久综合| 国产精品视频观看| 高清不卡一二三区| 欧美日韩精品电影| 午夜视频久久久久久| 国产99一区视频免费| 国产.欧美.日韩| 91精品国产色综合久久 | 国产成+人+日韩+欧美+亚洲| 国产精品免费网站在线观看| 日韩av电影免费观看高清完整版 | 国产日韩欧美麻豆| 国产网站一区二区三区| 国产精品中文字幕一区二区三区| 国产精品国产馆在线真实露脸 | 亚洲五月六月丁香激情| 国产aⅴ综合色| 久久成人免费电影| 一区二区三区国产豹纹内裤在线| 久久久久久久久久久久久夜| 欧美日本一道本在线视频| 国产精品一二三四区| 一区二区三区免费看视频| 精品999久久久| 777午夜精品免费视频| 色婷婷亚洲一区二区三区| 色婷婷综合激情| av在线不卡网| 国内精品自线一区二区三区视频| 亚洲国产精品v| 精品国产一区二区三区久久久蜜月 | 亚洲高清三级视频| 亚洲欧美色图小说| 婷婷中文字幕综合| 偷窥国产亚洲免费视频| 国产麻豆欧美日韩一区| 精品综合免费视频观看| 国产高清精品网站| 国产成人精品免费看|