精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用JavaScript和Canvas寫一個游戲框架

開發(fā) 前端
下面我們要介紹的JavaScript代碼使用面向?qū)ο蟮姆绞絹砭帉憽τ跊]有編寫過多少JavaScript代碼的人來說,恐怕第一眼看到它們會覺得有點奇怪。

4、寫一個游戲框架(一)

http://www.brighthub.com/internet/web-development/articles/40512.aspx

在知道了如何使用畫布元素之后,接下來我教大家寫一個框架,有了這個框架,我們就可以把它作為基礎(chǔ)來創(chuàng)建游戲。在這第一部分,我們會介紹前兩個文件/類。

編寫代碼之前,我們先來看一看隨后幾篇文章將致力于創(chuàng)建的示例Demo。表面上看起來,這個Demo跟第二篇文章里的那個沒啥區(qū)別,但如果你看看后臺(查看網(wǎng)頁源代碼)就會發(fā)現(xiàn),為了更方便地創(chuàng)建這個最終效果,一個凝聚不少心血的基礎(chǔ)框架已經(jīng)寫好了。

 

 

下面我們要介紹的JavaScript代碼使用面向?qū)ο蟮姆绞絹砭帉憽τ跊]有編寫過多少JavaScript代碼的人來說,恐怕第一眼看到它們會覺得有點奇怪。如果你真的不太熟悉JavaScript的面向?qū)ο缶幊蹋ㄗh通過Mozilla Developer Network的這個教程https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript來補(bǔ)補(bǔ)課。這篇教程里解釋了我們稍后會用到的一些編程技術(shù)。

從設(shè)計思想上來看,這個框架可以分成兩部分:與底層的2D引擎交互的類(用于操作畫布、控制渲染循環(huán)、處理輸入等的代碼)和用來創(chuàng)建對象以便構(gòu)成游戲的類。前者可以歸為引擎類,后者可以歸為應(yīng)用類。由于應(yīng)用類要構(gòu)建于引擎類之上,所以我們需要先來創(chuàng)建引擎類。

Main.js

如果你研究了前面例子中的代碼,就會發(fā)現(xiàn)Main.js文件中包含了不少代碼。

  1.  
  2. /** 每秒多少幀  
  3.     @type Number  
  4. */  
  5. var FPS = 30;  
  6. /** 兩幀間間隔的秒數(shù)  
  7.     @type Number  
  8. */  
  9. var SECONDS_BETWEEN_FRAMES = 1 / FPS;  
  10. /** GameObjectManager 實例的全局引用  
  11.     @type GameObjectManager  
  12. */  
  13. var g_GameObjectManager = null;  
  14. /** 應(yīng)用中用到的圖像  
  15.     @type Image  
  16. */  
  17. var g_image = new Image();  
  18. g_image.src = "jsplatformer3-smiley.jpg";  
  19.  
  20. // 將應(yīng)用的入口設(shè)置為init函數(shù)  
  21. window.onload = init;  
  22.  
  23. /**  
  24.     應(yīng)用的入口  
  25. */  
  26. function init()  
  27. {  
  28.     new GameObjectManager().startupGameObjectManager();  
  29. }  

首先是定義全局變量的代碼。然后,跟以前一樣,當(dāng)頁面加載完畢后立即運行init函數(shù)。在init函數(shù)里,創(chuàng)建GameObjectManager類的實例。

這里在GameObjectManager類的實例上調(diào)用了startupGameObjectManager函數(shù)。這篇文章以及后面的幾篇文章還將多次提到幾個命名上具有startupClassName形式的函數(shù)。這些函數(shù)實際上充當(dāng)了各自類的構(gòu)造函數(shù),這樣做有兩個原因。

首先,JavaScript不支持函數(shù)重載(至少不容易實現(xiàn))。如果你想讓一個類有多個構(gòu)造函數(shù),那么這就成了問題。而通過把構(gòu)造工作分配給另一組函數(shù)(如startupClassName1、startupClassName2),就可以比較容易地定義構(gòu)造類的不同方式了。

第二個原因(很大程度上也是個人的問題)是我經(jīng)常會在構(gòu)造函數(shù)中引用尚未定義的變量。這可能是我使用C++、Java和C#這些語言落下的毛病,在這些語言里,類變量在源代碼中的位置對其在構(gòu)造函數(shù)中的可見性沒有影響。拿下面這個C#類為例:

  1. class Test  
  2. {  
  3.     public void Test() {this.a = 5;}  
  4.     public int a;  
  5. }  

這些代碼是合乎語法的,可以正常工作。下面再看看JavaScript中一個相同的例子:

  1. function Test()  
  2. {  
  3.     this.a = 5;  
  4.     var a;  
  5. }  

這段代碼的問題在于,局部變量a在我們把數(shù)值5賦給它的時候還不存在。只有運行到var a;這一行,變量a才存在。盡管這個例子有點故意編排的意味,但的確能夠說明我所遇到的問題。通過把類的創(chuàng)建放到一個類似startupClassName這樣的函數(shù)中完成,并且在構(gòu)造函數(shù)中定義(但不初始化)局部變量,然后當(dāng)我在這些構(gòu)建函數(shù)中引用相應(yīng)的局部變量時,就能夠確保它們一定是存在的。

#p#

GameObjectManager.js

  1.  
  2. /**  
  3.     管理游戲中所有對象的管理器  
  4.     @class  
  5. */  
  6. function GameObjectManager()  
  7. {  
  8.     /** 保存游戲中對象的數(shù)組  
  9.         @type Arary  
  10.     */  
  11.     this.gameObjects = new Array();  
  12.     /** 上一次幀被渲染的時間  
  13.         @type Date  
  14.     */  
  15.     this.lastFrame = new Date().getTime();  
  16.     /** x軸的全局滾動值  
  17.         @type Number  
  18.     */  
  19.     this.xScroll = 0;  
  20.     /** y軸的全局滾動值  
  21.         @type Number  
  22.     */  
  23.     this.yScroll = 0;  
  24.     /** 對ApplicationManager實例的引用  
  25.         @type ApplicationManager  
  26.     */  
  27.     this.applicationManager = null;  
  28.     /** 對畫布元素的引用  
  29.         @type HTMLCanvasElement  
  30.     */  
  31.     this.canvas = null;  
  32.     /** 對畫布元素2D上下文的引用  
  33.         @type CanvasRenderingContext2D  
  34.     */  
  35.     this.context2D = null;  
  36.     /** 對內(nèi)存中用作后臺緩沖區(qū)的畫布的引用  
  37.         @type HTMLCanvasElement  
  38.     */  
  39.     this.backBuffer = null;  
  40.     /** 對后臺緩沖畫布的2D上下文的引用  
  41.         @type CanvasRenderingContext2D  
  42.     */  
  43.     this.backBufferContext2D = null;  
  44.  
  45.     /**  
  46.         初始化這個對象  
  47.         @return A reference to the initialised object  
  48.     */  
  49.     this.startupGameObjectManager = function()  
  50.     {  
  51.         // 設(shè)置引用this對象的全局指針  
  52.         g_GameObjectManager = this;  
  53.  
  54.         // 取得畫布元素及其2D上下文的引用  
  55.         this.canvas = document.getElementById('canvas');  
  56.         thisthis.context2D = this.canvas.getContext('2d');  
  57.         this.backBuffer = document.createElement('canvas');  
  58.         thisthis.backBuffer.width = this.canvas.width;  
  59.         thisthis.backBuffer.height = this.canvas.height;  
  60.         thisthis.backBufferContext2D = this.backBuffer.getContext('2d');  
  61.  
  62.         // 創(chuàng)建一個新的ApplicationManager  
  63.         this.applicationManager = new ApplicationManager().startupApplicationManager();  
  64.  
  65.         // 使用setInterval來調(diào)用draw函數(shù)  
  66.         setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);  
  67.  
  68.         return this;  
  69.     }  
  70.  
  71.     /**  
  72.         渲染循環(huán)  
  73.     */  
  74.     this.draw = function ()  
  75.     {  
  76.         // 計算從上一幀到現(xiàn)在的時間  
  77.         var thisFrame = new Date().getTime();  
  78.         var dt = (thisFrame - this.lastFrame)/1000;  
  79.         this.lastFrame = thisFrame;  
  80.  
  81.         // 清理繪制上下文  
  82.         this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);  
  83.         this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);  
  84.  
  85.         // 首先更新所有游戲?qū)ο? 
  86.         for (x in this.gameObjects)  
  87.         {  
  88.             if (this.gameObjects[x].update)  
  89.             {  
  90.                 this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);  
  91.             }  
  92.         }  
  93.  
  94.         // 然后繪制所有游戲?qū)ο? 
  95.         for (x in this.gameObjects)  
  96.         {  
  97.             if (this.gameObjects[x].draw)  
  98.             {  
  99.                 this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);  
  100.             }  
  101.         }  
  102.  
  103.         // 將后臺緩沖復(fù)制到當(dāng)前顯示的畫布  
  104.         this.context2D.drawImage(this.backBuffer, 0, 0);  
  105.     };  
  106.  
  107.     /**  
  108.         向gameObjects集合中添加一個GameObject  
  109.         @param gameObject The object to add  
  110.     */  
  111.     this.addGameObject = function(gameObject)  
  112.     {  
  113.         this.gameObjects.push(gameObject);  
  114.         this.gameObjects.sort(function(a,b){return a.zOrder - b.zOrder;})  
  115.     };  
  116.  
  117.     /**  
  118.         從gameObjects集合中刪除一個GameObject  
  119.         @param gameObject The object to remove  
  120.     */  
  121.     this.removeGameObject = function(gameObject)  
  122.     {  
  123.         this.gameObjects.removeObject(gameObject);  
  124.     }  
  125. }  

首先看一看GameObjectManager類。GameObjectManager是一個引擎類,用于管理畫布的繪制操作,還負(fù)責(zé)分派GameObject類(下一篇文章里介紹)的事件。

GameObjectManager類的startupGameObjectManager函數(shù)的代碼如下:

  1.  
  2. /**  
  3.     初始化這個對象  
  4.     @return A reference to the initialised object  
  5. */  
  6. this.startupGameObjectManager = function()  
  7. {  
  8.     // 設(shè)置引用this對象的全局指針  
  9.     g_GameObjectManager = this;  
  10.  
  11.     // 取得畫布元素及其2D上下文的引用  
  12.     this.canvas = document.getElementById('canvas');  
  13.     thisthis.context2D = this.canvas.getContext('2d');  
  14.     this.backBuffer = document.createElement('canvas');  
  15.     thisthis.backBuffer.width = this.canvas.width;  
  16.     thisthis.backBuffer.height = this.canvas.height;  
  17.     thisthis.backBufferContext2D = this.backBuffer.getContext('2d');  
  18.  
  19.     // 創(chuàng)建一個新的ApplicationManager  
  20.     this.applicationManager = new ApplicationManager().startupApplicationManager();  
  21.  
  22.     // 使用setInterval來調(diào)用draw函數(shù)  
  23.     setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);  
  24.  
  25.     return this;  
  26. }  

前面已經(jīng)說過,我們會把每個類的初始化工作放在startupClassName函數(shù)中來做。因此,GameObjectManager類將由startupGameObjectManager函數(shù)進(jìn)行初始化。

而引用這個GameObjectManager實例的全局變量g_GameObjectManager經(jīng)過重新賦值,指向了這個新實例。

  1. // 設(shè)置引用this對象的全局指針  
  2. g_GameObjectManager = this;  

對畫布元素及其繪圖上下文的引用也同樣保存起來:

  1. // 取得畫布元素及其2D上下文的引用  
  2. this.canvas = document.getElementById('canvas');  
  3. thisthis.context2D = this.canvas.getContext('2d');  

在前面的例子中,所有繪圖操作都是直接在畫布元素上完成的。這種風(fēng)格的渲染一般稱為單緩沖渲染。在此,我們要使用一種叫做雙緩沖渲染的技術(shù):任意游戲?qū)ο蟮乃欣L制操作,都將在一個內(nèi)存中的附加畫布元素(后臺緩沖)上完成,完成后再通過一次操作把它復(fù)制到網(wǎng)頁上的畫布元素(前臺緩沖)。

雙緩沖技術(shù)(http://www.brighthub.com/internet/web-development/articles/11012.aspx)通常用于減少畫面抖動。我自己在測試的時候從沒發(fā)現(xiàn)直接向畫布元素上繪制有抖動現(xiàn)象,但我在網(wǎng)上的確聽別人念叨過,使用單緩沖渲染會導(dǎo)致某些瀏覽器在渲染時發(fā)生抖動。

不管怎么說,雙緩沖還是能夠避免最終用戶看到每個游戲?qū)ο笤诶L制過程中最后一幀的組合過程。在通過JavaScript執(zhí)行某些復(fù)雜繪制操作時(例如透明度、反鋸齒及可編程紋理),這種情況是完全可能發(fā)生的。

使用附加緩沖技術(shù)占用的內(nèi)存非常少,多執(zhí)行一次圖像復(fù)制操作(把后臺緩沖繪制到前臺緩沖)導(dǎo)致的性能損失也可以忽略不計,可以說實現(xiàn)雙緩沖系統(tǒng)沒有什么缺點。

如果將在HTML頁面中定義的畫布元素作為前臺緩沖,那就需要再創(chuàng)建一個畫布來充當(dāng)后臺緩沖。為此,我們使用了document.createElement函數(shù)在內(nèi)存里創(chuàng)建了一個畫布元素,把它用作后臺緩沖。

  1. this.backBuffer = document.createElement('canvas');  
  2. thisthis.backBuffer.width = this.canvas.width;  
  3. thisthis.backBuffer.height = this.canvas.height;  
  4. thisthis.backBufferContext2D = this.backBuffer.getContext('2d');  

接下來,我們創(chuàng)建了ApplicationManager類的一個新實例,并調(diào)用startupApplicationManager來初始化它。這個ApplicationManager類將在下一篇文章中介紹。

  1. // 創(chuàng)建一個新的ApplicationManager  
  2. this.applicationManager = new ApplicationManager().startupApplicationManager();  

最后,使用setInterval函數(shù)重復(fù)調(diào)用draw函數(shù),這個函數(shù)是渲染循環(huán)的核心所在。

  1. // 使用setInterval來調(diào)用draw函數(shù)  
  2. setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);  

#p#

下面來看一看draw函數(shù)。

  1. /**  
  2.     渲染循環(huán)  
  3. */  
  4. this.draw = function ()  
  5. {  
  6.     // 計算從上一幀到現(xiàn)在的時間  
  7.     var thisFrame = new Date().getTime();  
  8.     var dt = (thisFrame - this.lastFrame)/1000;  
  9.     this.lastFrame = thisFrame;  
  10.  
  11.     // 清理繪制上下文  
  12.     this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);  
  13.     this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);  
  14.  
  15.     // 首先更新所有游戲?qū)ο? 
  16.     for (x in this.gameObjects)  
  17.     {  
  18.         if (this.gameObjects[x].update)  
  19.         {  
  20.             this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);  
  21.         }  
  22.     }  
  23.  
  24.     // 然后繪制所有游戲?qū)ο? 
  25.     for (x in this.gameObjects)  
  26.     {  
  27.         if (this.gameObjects[x].draw)  
  28.         {  
  29.             this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);  
  30.         }  
  31.     }  
  32.  
  33.     // 將后臺緩沖復(fù)制到當(dāng)前顯示的畫布  
  34.     this.context2D.drawImage(this.backBuffer, 0, 0);  
  35. };  

這個draw函數(shù)就是所有渲染循環(huán)的核心。在前面的例子中,渲染循環(huán)的函數(shù)會直接修改要繪制到屏幕上的對象(笑臉)。如果只需繪制一個對象,這樣做沒有問題。但是,一個游戲要由幾十個單獨的對象組成,所以這個draw函數(shù)并沒有直接在渲染循環(huán)中直接處理要繪制的對象,而是維護(hù)了一個保存著這些對象的數(shù)組,讓這些對象自己來更新和繪制自己。

首先,計算自上一幀渲染所經(jīng)過的時間。即便我們在代碼里寫了每秒鐘調(diào)用30次draw函數(shù),但誰也無法保證事實如此。通過計算自上一幀渲染所經(jīng)過的時間,可以做到盡可能讓游戲的執(zhí)行與幀速率無關(guān)。

  1. // 計算從上一幀到現(xiàn)在的時間  
  2. var thisFrame = new Date().getTime();  
  3. var dt = (thisFrame - this.lastFrame)/1000;  
  4. this.lastFrame = thisFrame;  

接著清理繪制上下文。

  1. // 清理繪制上下文  
  2. this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);  
  3. this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);  

然后,就是調(diào)用游戲?qū)ο?這些對象是由GameObject類定義的,下一篇文章將介紹該類)自己的更新(update)和繪制(draw)方法。注意,這兩個方法是可選的(這也是我們在調(diào)用它們之前先檢查它們是否存在的原因),但差不多每一個對象都需要更新和繪制自已。

  1. // 首先更新所有游戲?qū)ο? 
  2. for (x in this.gameObjects)  
  3. {  
  4.     if (this.gameObjects[x].update)  
  5.     {  
  6.         this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);  
  7.     }  
  8. }  
  9.  
  10. // 然后繪制所有游戲?qū)ο? 
  11. for (x in this.gameObjects)  
  12. {  
  13.     if (this.gameObjects[x].draw)  
  14.     {  
  15.         this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);  
  16.     }  
  17. }  

最后,把后臺緩沖復(fù)制到前臺緩沖,最終用戶就可以看到下一幀了。

  1. // 將后臺緩沖復(fù)制到當(dāng)前顯示的畫布  
  2. this.context2D.drawImage(this.backBuffer, 0, 0);  

理解了draw函數(shù),下面再分別講一講addGameObject和removeGameObject函數(shù)。

  1. /**  
  2.     向gameObjects集合中添加一個GameObject  
  3.     @param gameObject The object to add  
  4. */  
  5. this.addGameObject = function(gameObject)  
  6. {  
  7.     this.gameObjects.push(gameObject);  
  8.     this.gameObjects.sort(function(a,b){return a.zOrder - b.zOrder;})  
  9. };  
  10.  
  11. /**  
  12.     從gameObjects集合中刪除一個GameObject  
  13.     @param gameObject The object to remove  
  14. */  
  15. this.removeGameObject = function(gameObject)  
  16. {  
  17.     this.gameObjects.removeObject(gameObject);  
  18. }  

利用addGameObject和removeGameObject(在Utils.js文件里通過擴(kuò)展Array.prototype添加)函數(shù),可以在GameObjectManager所維護(hù)的GameObject集合(即gameObjects變量)中添加和刪除游戲?qū)ο蟆?/p>

GameObjectManager類是我們這個游戲框架中最復(fù)雜的一個類。在下一篇文章中,我們會講解游戲框架的另外幾個類:GameObject、VisualGameObject、Bounce和ApplicationManager。

好了,現(xiàn)在放松一下,看一看Demo吧

原文:http://www.brighthub.com/content/matthewcaspersonshubfoliohasmoved.aspx

譯文:http://www.cn-cuckoo.com/2011/08/14/game-development-with-javascript-and-the-canvas-element-3-2604.html

【編輯推薦】

  1. 使用JavaScript和Canvas開發(fā)游戲之認(rèn)識Canvas
  2. HTML 5 Canvas(畫布)教程之圖像處理
  3. HTML 5新特性Canvas入門秘籍
  4. 15個不可思議的HTML 5 Canvas應(yīng)用欣賞
  5. 使用JavaScript和Canvas開發(fā)游戲之使用Canvas
責(zé)任編輯:陳貽新 來源: 李松峰博客
相關(guān)推薦

2011-08-12 08:56:31

JavaScript

2011-08-11 09:16:50

JavaScript

2015-06-29 11:30:07

JavaScript小烏龜推箱子

2022-08-10 18:14:49

國際象棋游戲位字段C語言

2019-05-14 12:30:07

PythonPygame游戲框架

2011-11-03 09:13:27

JavaScript

2016-11-29 13:31:52

JavaScriptsetTimeout定時執(zhí)行

2011-10-21 09:10:12

JavaScript

2021-03-30 05:58:01

JavascriptCss3轉(zhuǎn)盤小游戲

2014-02-14 09:37:01

JavascriptDOM

2013-01-14 09:44:58

JavaScriptJSJS框架

2021-02-05 16:03:48

JavaScript游戲?qū)W習(xí)前端

2020-11-30 06:20:13

javascript

2017-06-08 15:53:38

PythonWeb框架

2021-09-08 08:36:50

ncursesLinux猜謎游戲

2015-06-02 04:13:23

Python乒乓球類游戲

2021-04-13 06:35:13

Elixir語言編程語言軟件開發(fā)

2023-03-01 10:19:23

2024-01-15 00:35:23

JavaScript框架HTML

2022-09-01 11:48:45

JavaScript框架
點贊
收藏

51CTO技術(shù)棧公眾號

日av在线播放中文不卡| 亚洲国产一区自拍| 中文字幕中文字幕99 | 欧美日韩一二三四| 欧美视频在线一区二区三区| 只有这里有精品| 日韩中文字幕观看| 日本va欧美va瓶| 欧美成人午夜激情在线| 久久久久国产精品无码免费看| 日本不卡免费高清视频在线| 亚洲国产岛国毛片在线| 97人人模人人爽人人喊38tv| 欧美黑人一区二区| 99久久激情| 亚洲精品国产精品国产自| 免费黄色一级网站| 国产丝袜视频在线播放| 国产亚洲精品bt天堂精选| 亚洲一区二区三区sesese| 日本一级一片免费视频| 97久久视频| 日韩av在线导航| 亚洲 国产 图片| 中文在线аv在线| 亚洲人123区| 欧美性bbwbbwbbwhd| japanese国产| 免费在线看成人av| 国产91精品高潮白浆喷水| 中文乱码字幕高清一区二区| 偷窥自拍亚洲色图精选| 精品久久久久久亚洲综合网 | 男女男精品视频网站| 都市激情久久| 91精品国产综合久久久久久久| www国产黄色| 国产盗摄在线视频网站| 国产精品传媒视频| 清纯唯美一区二区三区| 天天干天天干天天干| 精品伊人久久久久7777人| 欧美一级片在线播放| 久久综合综合久久| 亚洲mv大片欧洲mv大片| 国产亚洲综合久久| 免费a级黄色片| 国产精品一区二区三区美女| 欧美一区日本一区韩国一区| 欧美午夜aaaaaa免费视频| 超级碰碰久久| 午夜精品福利久久久| 日本免费黄色小视频| 一级毛片视频在线观看| 国产情人综合久久777777| 精品国产乱码久久久久久久软件 | 秋霞成人午夜伦在线观看| 91国语精品自产拍在线观看性色| 久久成人在线观看| 欧美激情综合色综合啪啪| 久久久国产在线视频| 亚洲欧洲综合网| 欧美激情黄色片| 色偷偷88888欧美精品久久久| 亚洲精品国产熟女久久久| 竹菊久久久久久久| 亚洲天堂男人天堂女人天堂| 免费中文字幕av| 婷婷成人影院| 亚洲欧美日韩国产中文| 自拍偷拍视频亚洲| 欧美一区二区三区激情视频| 亚洲欧美第一页| 免费毛片视频网站| 欧美中文一区二区| www国产亚洲精品久久网站| 懂色av蜜臀av粉嫩av永久| 999视频精品| 美女久久久久久久久久久| 一区二区三区四区五区| 欧美日韩亚洲一区二区三区在线| 欧美激情手机在线视频 | 午夜剧场高清版免费观看 | 不卡一卡2卡3卡4卡精品在| 国产精品伊人久久| 成人听书哪个软件好| 好吊色欧美一区二区三区视频| 午夜视频免费看| 久久精品综合网| 日日夜夜精品网站| 黄色网页在线看| 亚洲成人av一区| av免费网站观看| 亚洲aⅴ网站| 亚洲成人三级在线| www久久久久久久| 欧美大片一区| 欧美在线视频网| 亚洲一区二区影视| 丁香婷婷综合激情五月色| 久久综合九色欧美狠狠| 美女隐私在线观看| 午夜激情综合网| 污污的视频免费| 久久365资源| 日韩视频欧美视频| 日本网站免费观看| 激情五月激情综合网| 久久99九九| 欧美精品日韩少妇| 欧美日韩国产精品一区二区三区四区 | 青青久在线视频免费观看| 中文字幕av一区 二区| 日本一本中文字幕| 欧美黄色成人| 亚洲欧美在线免费| 免费三片在线播放| 轻轻草成人在线| 精品欧美一区二区三区久久久| 在线日本中文字幕| 狠狠色狠狠色综合日日小说| 精品国产午夜福利在线观看| 国产一区日韩| 91精品国产色综合久久不卡98| 一级全黄裸体免费视频| 91蜜桃婷婷狠狠久久综合9色| 男同互操gay射视频在线看| 最新欧美电影| 亚洲国产精品推荐| 欧美国产精品一二三| 日韩avvvv在线播放| 激情视频一区二区| 超碰97免费在线| 4438成人网| 五月天免费网站| 久久久久99| 精品国产二区在线| 96av在线| 精品久久久久久久久久久久久久久| 精品国产大片大片大片| 丝瓜av网站精品一区二区| 精品日韩欧美| √天堂8资源中文在线| 日韩一区二区在线观看视频| 国产中文字幕久久| 免费高清不卡av| 日本一区二区三区在线视频| 校园春色亚洲| 亚洲美女性视频| 日韩在线视频免费播放| 亚洲黄色片视频| 国产三级精品三级在线专区| 久久综合色视频| 麻豆传媒一区| 快射视频在线观看| 欧美日韩视频在线第一区| japanese中文字幕| 久久国产主播| 欧美午夜精品理论片a级大开眼界| 国产社区精品视频| 日韩激情在线视频| 日韩欧美成人一区二区三区| 91视频在线看| 国产精品第12页| 国产精品嫩模av在线| 国产99视频在线观看| www日韩tube| 51午夜精品国产| 国产精品丝袜一区二区| 国产精品1区2区| 欧美视频免费看欧美视频| 久久久亚洲欧洲日产| 日本精品久久久久久久| 国产福利免费在线观看| 欧美日韩五月天| 欧美又粗又大又长| 99视频一区二区三区| 丝袜老师办公室里做好紧好爽| 国产精品亚洲人成在99www| 国产精品高潮呻吟视频| 久久bbxx| 亚洲国产精品va在线| jizz国产在线观看| 亚洲欧洲三级电影| www.17c.com喷水少妇| 久久成人一区| www亚洲国产| 成人爽a毛片免费啪啪红桃视频| 欧美亚洲在线播放| 免费视频一二三区| 久久精品论坛| 国产精品99蜜臀久久不卡二区| 3d成人动漫在线| 日韩一区二区电影网| 日韩欧美视频在线免费观看| 国产亚洲精品精华液| 在线观看免费视频污| 亚洲三级免费| 亚洲欧美日韩不卡一区二区三区| 亚洲va欧美va人人爽成人影院| 91av在线播放视频| 免费av网站在线观看| 亚洲国产99精品国自产| 中文字幕制服诱惑| 亚洲制服丝袜在线| av永久免费观看| 丁香婷婷综合网| 中国黄色片免费看| 亚洲每日更新| 黄瓜视频免费观看在线观看www | 在线一区二区三区做爰视频网站| 日韩va亚洲va欧美va清高| 91一区二区三区在线播放| 在线观看日本www| 久久男女视频| 草草视频在线免费观看| 日本精品黄色| 国产日韩欧美亚洲一区| 祥仔av免费一区二区三区四区| 55夜色66夜色国产精品视频| a视频在线免费看| 正在播放欧美一区| 深夜视频在线免费| 欧美r级在线观看| 136福利视频导航| 在线视频观看一区| 天天操中文字幕| 夜夜精品视频一区二区| 老司机成人免费视频| 国产日韩视频一区二区三区| 免费看毛片的网站| 国产成人免费网站| 亚洲av无码久久精品色欲| 六月丁香综合在线视频| 男女曰b免费视频| 99精品福利视频| 欧美日韩国产免费| 久久亚洲AV成人无码国产野外 | 日批免费在线观看| 欧美一区二区美女| 国产精品欧美久久久久天天影视| 在线看国产一区| 国产无套丰满白嫩对白| 亚洲超碰精品一区二区| 免费人成视频在线| 亚洲宅男天堂在线观看无病毒| 中国毛片直接看| 1000部国产精品成人观看| 国产一级淫片久久久片a级| 国产欧美一区二区精品久导航 | 国产精品自拍合集| 欧美日韩午夜| 国产在线视频综合| 在线欧美日韩| 亚洲熟妇无码一区二区三区导航| 狠狠干综合网| 成人午夜免费在线| 性欧美videos另类喷潮| 国模杨依粉嫩蝴蝶150p| 日本免费在线视频不卡一不卡二| 男女啪啪网站视频| 奇米亚洲午夜久久精品| 亚洲一区日韩精品| 国产一区二区毛片| 潘金莲一级淫片aaaaa| 成人午夜在线播放| 添女人荫蒂视频| 久久久久九九视频| sm捆绑调教视频| 亚洲精选在线视频| 日韩伦理在线视频| 在线视频中文字幕一区二区| 中文字字幕在线中文乱码| 欧美精品第1页| 黄色美女一级片| 国产视频精品一区二区三区| 国产中文字幕在线观看| 色哟哟亚洲精品一区二区| 一级毛片视频在线观看| 欧美成人午夜激情| 亚洲精品永久免费视频| 国产精品丝袜一区二区三区| 国产亚洲观看| 久久久一本精品99久久精品66| 精品国产午夜| 永久免费网站视频在线观看| 99伊人成综合| 在线观看免费视频高清游戏推荐 | 久久久久国产精品无码免费看| 国产日韩欧美综合一区| 欧美一区免费观看| 欧美日韩国产精品一区二区三区四区 | 精品久久久久av| 国精品**一区二区三区在线蜜桃| 少妇丰满尤物大尺度写真| www一区二区| 麻豆精品一区二区三区视频| 欧美日韩免费观看中文| 国产一区二区三区在线观看 | 国产精品久久久久久av福利软件 | 黄色片免费在线观看| 久久久久久一区二区三区 | 成人午夜在线视频一区| 日本妇女一区| 国产精品亚洲天堂| 裸体一区二区| 性生交大片免费看l| 国产欧美精品一区| 日韩欧美亚洲一区二区三区| 欧美日韩一区二区三区视频| 天天干天天色天天| 久久国产天堂福利天堂| 天堂久久午夜av| 精品国产一区二区三区四区vr| 国产精品毛片久久| 欧美亚洲日本在线观看| a级精品国产片在线观看| 黄色录像一级片| 一本色道a无线码一区v| 亚洲成人77777| 久久精品99国产精品酒店日本| 亚洲精品一区| 久久国产精品高清| 亚洲欧美一区在线| 中文字幕第17页| 久久久综合网站| 日韩精品在线不卡| 精品伦理精品一区| a级毛片免费观看在线| 国产精品爽黄69天堂a| 精品国产91| 日本三级免费网站| 成人av在线资源网站| 激情综合五月网| 51午夜精品国产| 岛国成人毛片| 91精品久久久久久久久| av中文一区| 爱情岛论坛成人| 久久久久高清精品| 国产日产精品一区二区三区| 亚洲第一免费播放区| 男女视频在线| 成人女人免费毛片| 午夜国产精品视频| 国产又粗又猛又爽又黄| 亚洲欧美色图小说| 99久久精品日本一区二区免费| 色多多国产成人永久免费网站| 欧美色片在线观看| 亚洲精品成人a8198a| 蜜臀av在线播放一区二区三区| 丁香激情五月少妇| 欧美体内she精视频| 91官网在线| 国产免费亚洲高清| 久久久久久久久丰满| 红桃视频一区二区三区免费| 亚洲激情综合网| 黄片毛片在线看| 81精品国产乱码久久久久久| 色老板在线视频一区二区| www一区二区www免费| 久久久亚洲午夜电影| 日韩电影在线观看一区二区| 国产一区二区三区网站| 欧美一区=区三区| 中文视频一区视频二区视频三区| 国内精品写真在线观看| 五月婷婷一区二区| 亚洲精品电影在线| 日韩av福利| 中文字幕成人一区| 国产成人午夜99999| 国产九色在线播放九色| 亚洲系列中文字幕| 国产精品亚洲综合在线观看 | 91成人免费视频| 亚洲国产导航| 精品成人无码一区二区三区| 欧美浪妇xxxx高跟鞋交| 欧洲性视频在线播放| 免费看污久久久| 久久福利视频一区二区| 久久精品波多野结衣| 亚洲乱码国产乱码精品精天堂| 国产成人毛片| 97久久国产亚洲精品超碰热| 2024国产精品视频| 91丨porny丨在线中文| 欧美极品少妇全裸体| 国产日产精品一区二区三区四区的观看方式| 久久这里只精品| 亚洲影院理伦片| 九九热视频在线观看| 91亚洲精品一区二区| 亚洲一区免费| 欧美日韩在线国产| 亚洲一二在线观看| 最新国产一区二区|