国产成人欧美一区二区三区vr_久久国产精品人人爽人人爽_国产精品永久免费播放_肉欲啪啪a∨无码精品一区二区_国产超短裙jk丝袜在线_亚洲AV片高清资源在线观看_国模无码一区二区三区久久_国产成年人未进视频_中文字幕无码精品夜_一区二区三区在线视频免费看_亚洲成AV人片在线观看网址_日本激情视频高清综合久久_亚洲午夜视频福利_国内大量揄拍人妻精品視_久久国产精品福利二区三区

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

用TypeScript類組織貪吃蛇:面向?qū)ο笥螒蜷_發(fā)實(shí)戰(zhàn)

用TypeScript類組織貪吃蛇:面向?qū)ο笥螒蜷_發(fā)實(shí)戰(zhàn) 1. 整體設(shè)計(jì)思路為什么用類來(lái)組織貪吃蛇我見過(guò)不少初學(xué)者寫貪吃蛇習(xí)慣把所有邏輯塞進(jìn)一個(gè) main 函數(shù)或者全用全局變量堆。全局變量一多代碼就成了一鍋粥。這次我們用 TypeScript 的類來(lái)組織但很多人會(huì)問(wèn)一句貪吃蛇這么小有必要搞類嗎我覺得有必要。不是小題大做而是貪吃蛇這個(gè)項(xiàng)目其實(shí)覆蓋了面向?qū)ο笤O(shè)計(jì)里最典型的幾個(gè)問(wèn)題誰(shuí)負(fù)責(zé)數(shù)據(jù)、誰(shuí)負(fù)責(zé)行為、誰(shuí)負(fù)責(zé)協(xié)調(diào)、誰(shuí)負(fù)責(zé)渲染。如果一開始就把職責(zé)劃清楚后面加計(jì)分、加速、障礙物這些功能都會(huì)順手很多。整款游戲的核心邏輯可以拆成三大塊。第一塊是蛇類負(fù)責(zé)蛇的狀態(tài)、移動(dòng)規(guī)則、碰撞自檢、以及自身的繪制。第二塊是食物類負(fù)責(zé)食物坐標(biāo)的隨機(jī)生成與繪制。第三塊是游戲控制器類負(fù)責(zé)把上面兩塊組合起來(lái)再承擔(dān)游戲循環(huán)、分?jǐn)?shù)結(jié)算、鍵盤監(jiān)聽、開始結(jié)束狀態(tài)的切換。project-root/ ├─ src/ │ ├─ type.ts # 共享類型定義 │ ├─ food.ts # 食物類 │ ├─ snake.ts # 蛇類 │ ├─ game.ts # 游戲控制器類 │ └─ index.ts # 入口文件 ├─ index.html └─ tsconfig.json這個(gè)拆分有一個(gè)好處每個(gè)文件只做一件事。type.ts 里沒有邏輯只放類型snake.ts 里不碰鍵盤事件game.ts 里不關(guān)心蛇身格子到底是什么顏色。將來(lái)你如果想換成貪吃蛇雙人對(duì)戰(zhàn)版基本只需要?jiǎng)?chuàng)建兩個(gè) Snake 實(shí)例再改一下控制器——這就是低耦合帶來(lái)的實(shí)際收益。1.1 類型先行先定義數(shù)據(jù)形狀再寫邏輯寫 TypeScript 項(xiàng)目我習(xí)慣的第一步永遠(yuǎn)是定義類型。別看類型定義只是幾行 interface它相當(dāng)于整個(gè)項(xiàng)目的地基。地基歪了上面蓋什么都是歪的。貪吃蛇這個(gè)項(xiàng)目我認(rèn)為最少需要這三樣類型/** 方向枚舉 */ export enum Direction { Up Up, Down Down, Left Left, Right Right } /** 坐標(biāo)結(jié)構(gòu) */ export interface Point { x: number y: number } /** 蛇身和食物的通用格子結(jié)構(gòu) */ export interface Cell { x: number y: number }方向用枚舉還是用字符串字面量聯(lián)合類型都可以但我個(gè)人更推薦枚舉。原因很實(shí)在枚舉給每個(gè)方向一個(gè)語(yǔ)義名字代碼里不會(huì)出現(xiàn)裸字符串。你想想如果有人寫snake.faceTo(left)一旦字母拼錯(cuò)整個(gè)方向判斷就廢了。用Direction.Left就完全沒這個(gè)問(wèn)題編輯器還能給你直接提示省去翻代碼確認(rèn)的麻煩。坐標(biāo)為什么要分開 Point 和 Cell嚴(yán)格來(lái)說(shuō)這兩個(gè)都是{ x: number; y: number }但語(yǔ)義完全不同。Point 強(qiáng)調(diào)空間上的一個(gè)點(diǎn)Cell 強(qiáng)調(diào)的是畫布上的一個(gè)格子。如果你在代碼里直接混用看moveTo(point)和moveTo(cell)的時(shí)候你很難一眼判斷參數(shù)到底是什么意思。TypeScript 是結(jié)構(gòu)化類型系統(tǒng)兩個(gè)形狀相同的接口是可以互相賦值的但它們的存在本身就在提醒你——這里的坐標(biāo)代表什么含義。1.2 配置參數(shù)集中管理別寫死魔法數(shù)字寫游戲最忌諱的就是各種數(shù)字散落在代碼的各個(gè)角落比如畫布寬度 400、格子大小 20、蛇初始長(zhǎng)度 3這些魔法數(shù)字如果你在每個(gè)方法里重復(fù)寫后期想要調(diào)整的時(shí)候得滿文件去搜。像我之前做某個(gè)項(xiàng)目時(shí)就吃過(guò)這種虧改一個(gè)參數(shù)要按三遍 CtrlF。我建議的做法是直接在 type.ts 里定一個(gè)配置對(duì)象/** 游戲參數(shù)配置 */ export const CONFIG { canvasWidth: 600, canvasHeight: 600, gridSize: 20, snakeInitLength: 4, snakeSpeed: 150, // 單位毫秒數(shù)值越大越慢 colorSnakeHead: #2d5016, colorSnakeBody: #4e8d3f, colorFood: #d1483b, colorBg: #f5f2e6 } as constas const會(huì)讓這些值的類型變成字面量類型比如canvasWidth的類型就是600而不是number。這有什么好處好處是如果你后續(xù)不小心寫了一個(gè)CONFIG.canvasWidth 800TypeScript 會(huì)直接在編譯階段報(bào)錯(cuò)提醒你正在篡改一個(gè)只讀配置。對(duì)游戲這類運(yùn)行時(shí)狀態(tài)變化頻繁的程序來(lái)說(shuō)這個(gè)保護(hù)很值。還有一個(gè)細(xì)節(jié)蛇的移動(dòng)速度我用snakeSpeed: 150表示每 150 毫秒走一格。這個(gè)值直接決定了游戲的難度。100 毫秒手感偏快200 毫秒手感偏慢150 毫秒是我調(diào)試下來(lái)比較舒服的檔位。如果你的玩家群體是小朋友建議放寬到 200。2. 食物類把地基打扎實(shí)很多人覺得食物類太簡(jiǎn)單了就是把一個(gè)點(diǎn)隨機(jī)放在畫布上然后畫個(gè)圓。但食類有幾個(gè)細(xì)節(jié)值得琢磨比如隨機(jī)生成的坐標(biāo)必須對(duì)齊網(wǎng)格否則蛇頭永遠(yuǎn)吃不到食物食物不能生成在蛇身上否則一開局就穿模食物被吃掉后要能重新生成。2.1 食物類的職責(zé)范圍食物類的職責(zé)我限定為兩件生成一個(gè)當(dāng)前場(chǎng)景內(nèi)有效的坐標(biāo)以及把自己畫在畫布上。它不關(guān)心蛇在哪里也不關(guān)心分?jǐn)?shù)怎么加。那我怎么保證食物不生成在蛇身上答案是通過(guò)生成方法接收一個(gè)不可用區(qū)域參數(shù)由調(diào)用方來(lái)告訴它哪些坐標(biāo)不能選。這個(gè)設(shè)計(jì)叫做依賴倒置。食物類并不直接引用 Snake 類型而是接收一個(gè)坐標(biāo)數(shù)組。這樣食物類就不依賴蛇類將來(lái)如果棋盤上有障礙物也只需要把障礙物的坐標(biāo)一并傳進(jìn)來(lái)食物類不需要改一個(gè)字符。import { CONFIG } from ./type /** 食物類 */ export class Food { position: { x: number; y: number } constructor() { this.position { x: 0, y: 0 } } /** * 生成一個(gè)不包含在 forbiddenCells 里的隨機(jī)坐標(biāo) * param forbiddenCells 不可選的坐標(biāo)蛇身等 */ generate(forbiddenCells: { x: number; y: number }[] []): void { // 計(jì)算行列數(shù)避免坐標(biāo)越界 const rowNum CONFIG.canvasHeight / CONFIG.gridSize const colNum CONFIG.canvasWidth / CONFIG.gridSize while (true) { // 隨機(jī)取 0 ~ rowNum-1 之間的整數(shù) const newX Math.floor(Math.random() * colNum) const newY Math.floor(Math.random() * rowNum) // 如果這個(gè)坐標(biāo)沒人占用則確定位置 const conflict forbiddenCells.some( cell cell.x newX cell.y newY ) if (!conflict) { this.position { x: newX, y: newY } return } } } /** 繪制食物 */ draw(ctx: CanvasRenderingContext2D): void { const { x, y } this.position // 給食物留一點(diǎn)內(nèi)邊距不然看起來(lái)像粘在一起 const radius CONFIG.gridSize / 2 - 3 ctx.save() ctx.shadowColor CONFIG.colorFood ctx.shadowBlur 6 ctx.fillStyle CONFIG.colorFood ctx.beginPath() // 注意這里換算的是像素中心點(diǎn) ctx.arc( x * CONFIG.gridSize CONFIG.gridSize / 2, y * CONFIG.gridSize CONFIG.gridSize / 2, radius, 0, Math.PI * 2 ) ctx.fill() ctx.restore() } }2.2 隨機(jī)生成算法為什么用 while(true)你看那個(gè)while (true)可能會(huì)有點(diǎn)慌這玩意兒不會(huì)死循環(huán)嗎理論上如果棋盤被蛇占滿了確實(shí)會(huì)死循環(huán)。但貪吃蛇的棋盤大小時(shí) 30 × 30一共 900 個(gè)格子蛇身要達(dá)到 900 格這個(gè)可能性在實(shí)際游戲中幾乎為零。就算真的發(fā)生了那也是勝利的場(chǎng)面——棋盤都被蛇占滿了游戲早該結(jié)束了。不過(guò)從工程嚴(yán)謹(jǐn)?shù)慕嵌葋?lái)說(shuō)我會(huì)給這個(gè)循環(huán)加一個(gè)最大嘗試次數(shù)。這個(gè)習(xí)慣是我自己后期養(yǎng)成的因?yàn)槟呐赂怕试俚鸵粋€(gè)無(wú)法終止的循環(huán)在代碼評(píng)審里都是個(gè)隱患。比如可以改成嘗試 1000 次還找不到空位就拋異常。但在教學(xué)項(xiàng)目里while(true)配合占位判斷已經(jīng)完全夠用注釋里寫清楚前提就行。2.3 食物的繪制技巧食物的繪制我用的是shadowBlur加光暈效果這是讓食物看起來(lái)有質(zhì)感的低成本方式。不透明度和陰影的配合讓它像一顆水果糖而不是一個(gè)干巴巴的色塊。這里有個(gè)繪制坐標(biāo)系容易混的地方。游戲邏輯里的坐標(biāo)是格子坐標(biāo)一格是 20 像素。比如{ x: 3, y: 5 }表示從左上角開始橫著數(shù)第 4 格、豎著數(shù)第 6 格。但 canvas 繪圖用的是像素坐標(biāo)所以繪制的時(shí)候必須做一個(gè)換算像素X 格子X × 格子大小 格子大小 / 2 像素Y 格子Y × 格子大小 格子大小 / 2加一半格子大小的原因是為了讓圓心落在格子的正中心。如果不加圖案會(huì)偏在格子的左上角視覺上看起來(lái)很別扭。這個(gè)換算方法在蛇類繪制里也會(huì)用到建議你把它當(dāng)成一個(gè)固定的心法記下來(lái)。3. 蛇類實(shí)現(xiàn)游戲的核心到重點(diǎn)了。蛇類是貪吃蛇整個(gè)代碼里最復(fù)雜的類核心就是那幾件事數(shù)據(jù)怎么存、移動(dòng)怎么做、碰撞怎么檢測(cè)、自己會(huì)不會(huì)咬到自己、吃到食物怎么變長(zhǎng)、以及怎么把自己畫出來(lái)。3.1 蛇的數(shù)據(jù)結(jié)構(gòu)怎么選蛇在棋盤上的形態(tài)是一連串連續(xù)格子而且隨時(shí)會(huì)在頭部新增一格尾部可能減少一格。這種頭部增、尾部減的操作典型的先進(jìn)先出邏輯天然適合用隊(duì)列。在 JavaScript 里數(shù)組的unshift在頭部插入、pop在尾部刪除剛好模擬了最自然的思路。但這里有一個(gè)性能上的點(diǎn)在教學(xué)里我會(huì)特意提一下unshift的時(shí)間復(fù)雜度是 O(n)因?yàn)閿?shù)組頭部插入會(huì)引發(fā)后續(xù)所有元素的內(nèi)存移動(dòng)。貪吃蛇的蛇身長(zhǎng)度通常在幾十格這個(gè)量級(jí)這一點(diǎn)性能損失完全可忽略。如果你貪吃蛇以后要做到 500 格以上可以考慮用雙向鏈表存儲(chǔ)蛇身。在教學(xué)項(xiàng)目里用數(shù)組就行容易理解也容易調(diào)試。蛇類還用一個(gè)direction字段記錄當(dāng)前朝向一個(gè)pendingDirection記錄下一次移動(dòng)的方向。為什么要兩個(gè)方向因?yàn)橥婕以谝粠畠?nèi)可能連續(xù)按兩個(gè)方向鍵如果不做緩沖第二個(gè)按鍵會(huì)覆蓋第一個(gè)按鍵導(dǎo)致蛇沒有按玩家的意圖轉(zhuǎn)向。而如果按下即生效又會(huì)出現(xiàn)一個(gè)經(jīng)典的 bug蛇正在向左走玩家按了向上再快速按了向右蛇會(huì)直接掉頭——蛇不允許直接 180 度轉(zhuǎn)向這個(gè)約束后面細(xì)說(shuō)。3.2 蛇類的 TypeScript 實(shí)現(xiàn)import { CONFIG, Direction } from ./type interface Cell { x: number y: number } /** 蛇類管理蛇身狀態(tài)、移動(dòng)規(guī)則與碰撞檢測(cè) */ export class Snake { /** 蛇身第 0 項(xiàng)為蛇頭 */ body: Cell[] /** 當(dāng)前移動(dòng)方向 */ direction: Direction /** 緩沖方向本輪移動(dòng)尚未消費(fèi)的最新轉(zhuǎn)向指令 */ private pendingDirection: Direction /** 本輪是否已經(jīng)移動(dòng)過(guò)防止一幀內(nèi)多次移動(dòng) */ private movedThisTurn: boolean constructor() { // 初始蛇身從中間向左延伸 const gridX CONFIG.canvasWidth / CONFIG.gridSize const gridY CONFIG.canvasHeight / CONFIG.gridSize const startX Math.floor(gridX / 2) const startY Math.floor(gridY / 2) this.body [] for (let i 0; i CONFIG.snakeInitLength; i) { this.body.push({ x: startX - i, y: startY }) } this.direction Direction.Right this.pendingDirection Direction.Right this.movedThisTurn false } /** 獲取蛇頭坐標(biāo) */ get head(): Cell { return this.body[0] } /** 設(shè)置下一次移動(dòng)的方向帶轉(zhuǎn)向合法性校驗(yàn) */ setDirection(newDir: Direction): void { // 左、右是橫向上、下是縱向 const isOpposite (this.direction Direction.Up newDir Direction.Down) || (this.direction Direction.Down newDir Direction.Up) || (this.direction Direction.Left newDir Direction.Right) || (this.direction Direction.Right newDir Direction.Left) // 如果是相反方向忽略 if (isOpposite) return // 如果相同方向忽略 if (this.direction newDir) return // 如果這一輪已經(jīng)移動(dòng)過(guò)只更新緩沖方向下一輪再消費(fèi) if (this.movedThisTurn) { this.pendingDirection newDir } else { // 這一輪還沒移動(dòng)直接生效 this.direction newDir this.pendingDirection newDir } } /** 蛇移動(dòng)一步 */ move(grow: boolean): void { const head this.body[0] let newHead: Cell { x: head.x, y: head.y } switch (this.direction) { case Direction.Up: newHead.y - 1 break case Direction.Down: newHead.y 1 break case Direction.Left: newHead.x - 1 break case Direction.Right: newHead.x 1 break } // 頭部插入新格子 this.body.unshift(newHead) // 只有吃到食物才保留尾部否則移除尾部 if (!grow) { this.body.pop() } // 修正蛇頭坐標(biāo)到棋盤范圍內(nèi)撞墻的場(chǎng)景留給控制器處理 const rowNum CONFIG.canvasHeight / CONFIG.gridSize const colNum CONFIG.canvasWidth / CONFIG.gridSize newHead.x (newHead.x colNum) % colNum newHead.y (newHead.y rowNum) % rowNum this.body[0] newHead // 移動(dòng)完成消費(fèi)緩沖方向 this.direction this.pendingDirection this.movedThisTurn true } /** 是否與自身發(fā)生碰撞 */ isHitSelf(): boolean { const head this.body[0] // 從索引 1 開始檢查因?yàn)樗饕?0 就是頭本身 return this.body.slice(1).some(segment segment.x head.x segment.y head.y) } /** 蛇頭是否撞到邊界 */ isHitWall(): boolean { const head this.body[0] const rowNum CONFIG.canvasHeight / CONFIG.gridSize const colNum CONFIG.canvasWidth / CONFIG.gridSize return head.x 0 || head.x colNum || head.y 0 || head.y rowNum } /** 判斷某個(gè)坐標(biāo)是否與蛇身重合 */ isOnSnake(x: number, y: number): boolean { return this.body.some(segment segment.x x segment.y y) } /** 重置蛇狀態(tài)重新開局用 */ reset(): void { const gridX CONFIG.canvasWidth / CONFIG.gridSize const gridY CONFIG.canvasHeight / CONFIG.gridSize const startX Math.floor(gridX / 2) const startY Math.floor(gridY / 2) this.body [] for (let i 0; i CONFIG.snakeInitLength; i) { this.body.push({ x: startX - i, y: startY }) } this.direction Direction.Right this.pendingDirection Direction.Right this.movedThisTurn false } /** 繪制蛇 */ draw(ctx: CanvasRenderingContext2D): void { const size CONFIG.gridSize this.body.forEach((segment, index) { const px segment.x * size const py segment.y * size // 是否蛇頭 const isHead index 0 // 內(nèi)邊距讓蛇身看起來(lái)是一節(jié)一節(jié)的 const padding isHead ? 1 : 3 ctx.fillStyle isHead ? CONFIG.colorSnakeHead : CONFIG.colorSnakeBody // 用圓角矩形或正方形繪制蛇身 ctx.fillRect(px padding, py padding, size - padding * 2, size - padding * 2) // 給蛇頭畫出兩個(gè)眼睛增強(qiáng)辨識(shí)度 if (isHead) { ctx.fillStyle #fff const eyeSize 3 if (this.direction Direction.Right) { ctx.fillRect(px size - 8, py 4, eyeSize, eyeSize) ctx.fillRect(px size - 8, py size - 8, eyeSize, eyeSize) } else if (this.direction Direction.Left) { ctx.fillRect(px 5, py 4, eyeSize, eyeSize) ctx.fillRect(px 5, py size - 8, eyeSize, eyeSize) } else if (this.direction Direction.Up) { ctx.fillRect(px 4, py 5, eyeSize, eyeSize) ctx.fillRect(px size - 8, py 5, eyeSize, eyeSize) } else { // Down ctx.fillRect(px 4, py size - 8, eyeSize, eyeSize) ctx.fillRect(px size - 8, py size - 8, eyeSize, eyeSize) } } }) } }3.3 移動(dòng)邏輯中的關(guān)鍵設(shè)計(jì)我在這里用了movedThisTurn這個(gè)標(biāo)志位它在游戲循環(huán)里承擔(dān)著重要的作用。requestAnimationFrame 是每幀都會(huì)回調(diào)的但貪吃蛇不需要每幀都移動(dòng)——它應(yīng)該按照snakeSpeed的節(jié)奏來(lái)走。于是我們只會(huì)每隔一段時(shí)間調(diào)用一次move()。但在一次移動(dòng)完成之后如果用戶在這一幀里連續(xù)按了兩次方向鍵第一次的轉(zhuǎn)向已經(jīng)生效第二次的轉(zhuǎn)向只能進(jìn)入 pendingDirection 緩沖區(qū)等下一輪移動(dòng)時(shí)再消費(fèi)。這個(gè)機(jī)制看起來(lái)簡(jiǎn)單實(shí)際解決了兩個(gè)大問(wèn)題。第一個(gè)問(wèn)題是反向瞬移蛇頭正在向右走玩家在下一次移動(dòng)前按了上又按了左如果沒有緩沖左方向會(huì)覆蓋上方向而左恰好是右的反方向蛇會(huì)瞬間穿過(guò)自己的身體。第二個(gè)問(wèn)題是輸入丟失如果只用一個(gè) direction而且每次鍵盤事件都直接覆蓋 direction那么玩家在短時(shí)間內(nèi)按的上和左只有最后一次生效看起來(lái)像是按鍵失靈。有了 pendingDirection按鍵就變成了隊(duì)列的感覺雖然只緩沖一個(gè)但手感已經(jīng)完全不同。還有就是move(grow: boolean)這個(gè)參數(shù)設(shè)計(jì)。grow 為 false 時(shí)移動(dòng)完要把尾巴 pop 掉這樣蛇身長(zhǎng)度保持不變。grow 為 true 時(shí)不 pop蛇身長(zhǎng)度加一。這比吃到食物后再調(diào)一個(gè)專門的方法來(lái)加一節(jié)更符合直覺因?yàn)樵鲩L(zhǎng)本來(lái)就應(yīng)該發(fā)生在移動(dòng)這個(gè)瞬間。3.4 撞墻策略不穿墻還是穿墻我在move里做了一個(gè)邊界取模的兜底newHead.x (newHead.x colNum) % colNum newHead.y (newHead.y rowNum) % rowNum這個(gè)東西的意思是如果你的坐標(biāo)到了 -1就把它修正成 colNum - 1如果到了 colNum就回到 0。也就是說(shuō)蛇頭會(huì)從左邊穿出去、右邊鉆出來(lái)類似環(huán)屏效果。這在早期貪吃蛇里是一種常見玩法。但你可能想問(wèn)既然蛇類里已經(jīng)做了邊界修正為什么還有一個(gè)isHitWall方法兩種玩法都存在經(jīng)典模式下蛇撞到邊界游戲結(jié)束穿墻模式則不然。把這個(gè)選擇交給控制器更合理——控制器知道當(dāng)前游戲該用哪種模式。在實(shí)際項(xiàng)目中我通常建議默認(rèn)使用撞墻結(jié)束因?yàn)榇δJ綍?huì)讓玩家的策略變得完全不同難度把控也更含糊。在這個(gè)項(xiàng)目里我選擇在控制器里檢查撞墻結(jié)束游戲move里的取模只是防御性代碼確保極端情況下蛇頭始終在畫布內(nèi)。4. 游戲控制器類把一切串起來(lái)控制器類的名字我起的是 Game整個(gè)游戲的主循環(huán)、狀態(tài)管理、事件監(jiān)聽、Canvas 上下文管理都集中在它身上。它操作蛇和食物這兩個(gè)業(yè)務(wù)類但自身不關(guān)心蛇的數(shù)據(jù)結(jié)構(gòu)也不關(guān)心食物怎么畫它的工作是決策。4.1 游戲狀態(tài)機(jī)貪吃蛇看起來(lái)是實(shí)時(shí)游戲但邏輯上是一個(gè)狀態(tài)機(jī)至少包含這幾種狀態(tài)等待開始、運(yùn)行中、暫停、結(jié)束。狀態(tài)不同事件處理和渲染行為完全不同。type GameStatus idle | running | paused | over export class Game { private canvas: HTMLCanvasElement private ctx: CanvasRenderingContext2D private snake: Snake private food: Food private status: GameStatus idle private score 0 private lastMoveTime 0 private animationId 0 constructor(canvas: HTMLCanvasElement) { this.canvas canvas // 這里在正式項(xiàng)目中應(yīng)該做空值處理但教學(xué)環(huán)節(jié)先保證存在 this.ctx canvas.getContext(2d)! this.snake new Snake() this.food new Food() this.food.generate() this.bindEvents() } }狀態(tài)機(jī)的好處在于任何外部輸入進(jìn)來(lái)先看狀態(tài)再?zèng)Q定要不要響應(yīng)。比如游戲結(jié)束狀態(tài)下按方向鍵沒有任何意義暫停狀態(tài)下按空格應(yīng)該恢復(fù)運(yùn)行中按空格應(yīng)該暫停。這個(gè)東西用 if 堆也能寫但狀態(tài)一多就會(huì)亂。我在項(xiàng)目里用狀態(tài)字符串加 switch 來(lái)處理。4.2 事件綁定與防止方向鍵滾動(dòng)頁(yè)面鍵盤事件綁在 document 上而不是 canvas 上。為什么因?yàn)橥婕野存I盤時(shí)焦點(diǎn)不一定在 canvas 上如果綁在 canvas 上很可能出現(xiàn)按了沒反應(yīng)。而綁 document 能保證無(wú)論焦點(diǎn)在哪都能響應(yīng)。方向鍵的默認(rèn)行為會(huì)讓頁(yè)面滾動(dòng)必須preventDefault()。這是新手最容易忽略的問(wèn)題不處理的話會(huì)出現(xiàn)按一下方向鍵蛇沒動(dòng)頁(yè)面先滾了。private bindEvents(): void { document.addEventListener(keydown, (e) { const keyMap: Recordstring, Direction { ArrowUp: Direction.Up, ArrowDown: Direction.Down, ArrowLeft: Direction.Left, ArrowRight: Direction.Right, w: Direction.Up, s: Direction.Down, a: Direction.Left, d: Direction.Right } const dir keyMap[e.key] if (dir) { // 防止方向鍵滾動(dòng)頁(yè)面 e.preventDefault() this.handleDirection(dir) } if (e.key || e.key Space) { e.preventDefault() this.handleSpace() } if (e.key Enter) { e.preventDefault() this.handleEnter() } }) }同時(shí)支持字母鍵和方向鍵這個(gè)體驗(yàn)細(xì)節(jié)很加分。很多玩家習(xí)慣左手控制 WASD右手可能還握著鼠標(biāo)。如果你只做了方向鍵會(huì)損失一部分玩家的舒適度。4.3 按鍵響應(yīng)與狀態(tài)流轉(zhuǎn)private handleDirection(dir: Direction): void { if (this.status ! running) return this.snake.setDirection(dir) } private handleSpace(): void { if (this.status running) { this.status paused } else if (this.status paused) { this.status running // 恢復(fù)時(shí)重置計(jì)時(shí)避免瞬間移動(dòng)一次 this.lastMoveTime performance.now() } } private handleEnter(): void { if (this.status idle || this.status over) { this.start() } }這里有一個(gè)細(xì)節(jié)暫?;謴?fù)后lastMoveTime要重置為當(dāng)前時(shí)間。如果不重置暫停期間過(guò)去的時(shí)間會(huì)計(jì)入移動(dòng)間隔恢復(fù)后瞬間就走一步玩家會(huì)感覺蛇跳了一下。類似的坑還有瀏覽器標(biāo)簽頁(yè)切換回來(lái)后的大間隔問(wèn)題也靠這個(gè)辦法解決。4.4 游戲循環(huán)用 requestAnimationFrame 加時(shí)間差控制游戲循環(huán)是控制器的靈魂。我用 requestAnimationFrame 驅(qū)動(dòng)渲染但移動(dòng)的節(jié)拍單獨(dú)用時(shí)間差控制。private loop (timestamp: number): void { // 記錄動(dòng)畫幀ID便于取消 this.animationId requestAnimationFrame(this.loop) if (this.status ! running) { // 不管暫停還是結(jié)束畫面不動(dòng)但為了方便顯示暫停文字還是重繪一次 this.draw() return } // 距離上次移動(dòng)是否達(dá)到設(shè)定間隔 if (timestamp - this.lastMoveTime CONFIG.snakeSpeed) { this.update() this.lastMoveTime timestamp } this.draw() }為什么不直接setInterval來(lái)控制蛇移動(dòng)誠(chéng)實(shí)地講setInterval在這個(gè)場(chǎng)景其實(shí)也能用但有個(gè)一致性問(wèn)題setInterval的回調(diào)可能會(huì)因?yàn)橹骶€程忙而出現(xiàn)積壓導(dǎo)致多次快速連續(xù)執(zhí)行而且它和渲染不同步可能出現(xiàn)蛇移動(dòng)了畫面卻沒更新。requestAnimationFrame 天然和瀏覽器渲染幀率同步在 60Hz 的屏幕上是 16.67ms 觸發(fā)一次移動(dòng)節(jié)奏通過(guò)時(shí)間差來(lái)卡穩(wěn)定且不掉幀。loop定義為箭頭函數(shù)的原因是requestAnimationFrame(this.loop)里的 this 上下文如果換成一個(gè)普通函數(shù)在回調(diào)執(zhí)行時(shí) this 會(huì)指向 window。箭頭函數(shù)則自動(dòng)綁定當(dāng)前實(shí)例。4.5 更新邏輯碰撞檢測(cè)的先后順序update()是整個(gè)單幀決策的集中地。我處理碰撞的順序是先吃食物再撞自己再撞墻。private update(): void { const head this.snake.body[0] const foodPos this.food.position // 吃了食物嗎 const isEating head.x foodPos.x head.y foodPos.y // 讓蛇移動(dòng)吃到食物就增長(zhǎng) this.snake.move(isEating) if (isEating) { this.score 10 this.food.generate(this.snake.body) } if (this.snake.isHitSelf()) { this.over() return } if (this.snake.isHitWall()) { this.over() return } }先判斷吃再調(diào)用 move。這里有個(gè)潛在的問(wèn)題如果先調(diào)用 move 再判斷吃此時(shí)蛇頭已經(jīng)移動(dòng)了就必須用移動(dòng)前的坐標(biāo)做判斷邏輯上更繞。先判斷再移動(dòng)代碼讀起來(lái)順暢得多。isHitWall之所以放在isHitSelf之后是因?yàn)槿绻哳^和墻壁重合時(shí)同時(shí)也和自己的身體重合報(bào)哪個(gè)錯(cuò)都合理。但實(shí)際游戲里蛇頭撞墻后不再移動(dòng)此時(shí)蛇身不可能超過(guò)邊界所以先后順序影響不大保持這個(gè)順序只是因?yàn)樽x代碼時(shí)先近后遠(yuǎn)更自然。4.6 開始、結(jié)束、重繪private start(): void { this.score 0 this.snake.reset() this.food.generate(this.snake.body) this.status running this.lastMoveTime performance.now() } private over(): void { this.status over } private draw(): void { const { ctx } this ctx.clearRect(0, 0, CONFIG.canvasWidth, CONFIG.canvasHeight) ctx.fillStyle CONFIG.colorBg ctx.fillRect(0, 0, CONFIG.canvasWidth, CONFIG.canvasHeight) this.food.draw(ctx) this.snake.draw(ctx) // 游戲狀態(tài)文字 if (this.status idle) { this.drawCenterText(按 Enter 開始游戲) } else if (this.status paused) { this.drawCenterText(暫停中按空格繼續(xù)) } else if (this.status over) { this.drawCenterText(游戲結(jié)束得分 ${this.score}按 Enter 重來(lái)) } } private drawCenterText(text: string): void { const { ctx } this ctx.save() ctx.fillStyle #333 ctx.font bold 24px sans-serif ctx.textAlign center ctx.textBaseline middle ctx.fillText(text, CONFIG.canvasWidth / 2, CONFIG.canvasHeight / 2) ctx.restore() }draw 里的一個(gè)細(xì)節(jié)是 clearRect 之后用背景色鋪底。如果不鋪底背景默認(rèn)是透明的看起來(lái)還行但如果你在 draw 里用了部分透明度的顏色比如半透明的蛇身下一幀繪制時(shí)會(huì)和上一幀殘留疊加形成拖影。先鋪一層不透明底色能徹底避免這個(gè)視覺錯(cuò)誤。還有一個(gè)容易忽略的點(diǎn)drawCenterText 里的ctx.save()和ctx.restore()。save 保存當(dāng)前的繪圖狀態(tài)到棧里restore 恢復(fù)。這里之所以必須用是因?yàn)槲腋牧藅extAlign和textBaseline。如果不恢復(fù)下一次繪制幾何圖形時(shí)這些文字對(duì)齊屬性會(huì)一直生效可能導(dǎo)致后續(xù)繪制出現(xiàn)莫名其妙的結(jié)果。但凡你在繪制過(guò)程中改了 Canvas 的全局狀態(tài)畫完就恢復(fù)是一個(gè)好習(xí)慣。5. 常見問(wèn)題與排查技巧實(shí)錄寫貪吃蛇的過(guò)程當(dāng)中有幾類問(wèn)題出現(xiàn)頻率極高。我把自己調(diào)試過(guò)程中踩過(guò)的坑整理一下按癥狀、原因、解法的方式列出來(lái)方便你對(duì)照排查。5.1 癥狀一蛇身顯示方向相反現(xiàn)象是蛇頭在最右但身體往右排看起來(lái)蛇在倒著走。排查后發(fā)現(xiàn)是初始化時(shí) push 的順序?qū)е碌摹H绻愕拇a寫成this.body.push({ x: startX i, y: startY })i 從 0 遞增那么第 0 項(xiàng)是 startX第 1 項(xiàng)是 startX 1第 2 項(xiàng)是 startX 2以此類推。但我們的設(shè)計(jì)是 body[0] 永遠(yuǎn)是蛇頭而蛇向右走時(shí)頭必須在最右邊。所以 body[0] 的 x 必須最大。正確的寫法是this.body.push({ x: startX - i, y: startY })這樣第 0 項(xiàng) x 最大向右走時(shí)頭部插入的新位置永遠(yuǎn)比原來(lái)大 1視覺和邏輯都是正確的。這個(gè)坑本質(zhì)上是數(shù)組第 0 項(xiàng)是蛇頭這個(gè)約定沒有貫徹到底。我建議在代碼注釋里寫上第 0 項(xiàng)為蛇頭以后自己看代碼也不會(huì)犯迷糊。5.2 癥狀二快速連按方向鍵導(dǎo)致蛇反向瞬移假設(shè)蛇向右移動(dòng)玩家按了一下上緊接著按了一下左。如果沒有 pendingDirection 緩沖第二次按鍵后 direction 變成左但蛇頭還在向右移動(dòng)下一次 move 時(shí) head.x - 1 就會(huì)讓蛇頭直接往左而蛇身第二節(jié)還在原來(lái)的位置蛇頭就直接撞進(jìn)了第二節(jié)的位置游戲可能瞬間判負(fù)。玩家會(huì)覺得莫名其妙。解法就是我在 Snake 類里實(shí)現(xiàn)的 setDirection 加 pendingDirection 機(jī)制。在設(shè)置方向時(shí)檢查新方向是否為當(dāng)前方向的反向或同向如果是就直接丟棄。然后再利用 movedThisTurn 做緩沖只允許方向變化一次多余的進(jìn)入末位等待。這是最穩(wěn)妥的做法。5.3 癥狀三方向鍵按下時(shí)頁(yè)面跟著滾動(dòng)如果你沒在 keydown 里調(diào) preventDefault方向鍵默認(rèn)會(huì)讓瀏覽器滾動(dòng)頁(yè)面尤其是你沒有給頁(yè)面設(shè)置 overflow hidden 的時(shí)候。用戶按下方向鍵游戲畫面沒反應(yīng)滾動(dòng)條倒是動(dòng)了。解決方式是 keydown 回調(diào)里對(duì)方向鍵統(tǒng)一調(diào)用 e.preventDefault()這在 bindEvents里已經(jīng)處理了。5.4 癥狀四游戲結(jié)束后蛇還在畫布上畫面有殘留游戲結(jié)束后 status 變成 overloop 里走的是 draw 分支draw 會(huì)先清空畫布再重繪食物和蛇所以畫面理論上不會(huì)殘留舊幀。如果你發(fā)現(xiàn)殘留多半是清屏寫錯(cuò)了比如ctx.clearRect(0, 0, 100, 100)clearRect 的區(qū)域小于畫布實(shí)際尺寸導(dǎo)致邊緣沒清掉。用 CONFIG.canvasWidth 和 CONFIG.canvasHeight 代替魔法數(shù)字可以解決。5.5 癥狀五食物生成到蛇身上食物重新生成時(shí)應(yīng)該把蛇身的所有坐標(biāo)傳給 generate 方法作為禁止區(qū)域。留意這個(gè)調(diào)用時(shí)機(jī)應(yīng)該在蛇移動(dòng)并且長(zhǎng)大完成之后調(diào)用否則傳的蛇身還是舊的缺少剛長(zhǎng)出來(lái)的那一節(jié)。這個(gè)順序我一般在 update 里固定為move - 分?jǐn)?shù) - 重新生成食物。5.6 癥狀六requestAnimationFrame 沒有啟動(dòng)或者被瀏覽器節(jié)流瀏覽器為了省電會(huì)對(duì)后臺(tái)標(biāo)簽頁(yè)的 requestAnimationFrame 做節(jié)流長(zhǎng)時(shí)間掛后臺(tái)可能完全停止回調(diào)。這會(huì)導(dǎo)致什么你切出去一分鐘再切回來(lái)發(fā)現(xiàn)蛇沒有按照時(shí)間戳累計(jì)跳躍移動(dòng)而是重新在這個(gè)位置繼續(xù)走。這不是 bug而是瀏覽器行為。如果你希望切回來(lái)時(shí)游戲立即補(bǔ)上這一分鐘的移動(dòng)可以在 loop 里檢測(cè) timestamp - lastMoveTime 如果大于某個(gè)閾值就只更新一次避免蛇一步跨出十萬(wàn)八千里。我試過(guò)這個(gè)方案效果不錯(cuò)帶來(lái)的問(wèn)題是游戲難度會(huì)在切回來(lái)瞬間拔高所以也可以選擇接受瀏覽器節(jié)流不做額外處理。5.7 關(guān)于獲取 canvas 上下文時(shí)的感嘆號(hào)代碼里出現(xiàn)了這樣的寫法this.ctx canvas.getContext(2d)!TypeScript 里getContext的返回值類型是CanvasRenderingContext2D | null。當(dāng)你非常確定 canvas 元素存在且能拿到 2d 上下文時(shí)可以用非空斷言!來(lái)消除 null。但如果 canvas 的 id 寫錯(cuò)了或者 canvas 元素還沒渲染到 DOM 就拿它這里會(huì)拋出運(yùn)行時(shí)錯(cuò)誤而不是編譯錯(cuò)誤。比較穩(wěn)妥的寫法是判空后拋出明確錯(cuò)誤const ctx canvas.getContext(2d) if (!ctx) throw new Error(無(wú)法獲取 canvas 上下文)這個(gè)寫法更安全錯(cuò)誤信息也更明確。教學(xué)項(xiàng)目里直接用非空斷言省事但心里要清楚它到底在做什么別在團(tuán)隊(duì)項(xiàng)目里隨手用感嘆號(hào)。5.8 關(guān)于分?jǐn)?shù)和速度的平衡最后聊一個(gè)很多人做完游戲后都會(huì)問(wèn)的問(wèn)題怎么讓游戲越來(lái)越難最常用的方法是分?jǐn)?shù)越高速度越快。我之前試過(guò)在 update 里動(dòng)態(tài)計(jì)算const BASE_SCORE 10 const EXTRA_SCORE this.score * 0.5 const LIMIT_SPEED 60 // 最快間隔毫秒 CONFIG.snakeSpeed Math.max(LIMIT_SPEED, BASE_SPEED - EXTRA_SCORE)但這么做有個(gè)副作用蛇速變快后玩家的反應(yīng)時(shí)間變短如果速度增長(zhǎng)過(guò)于陡峭游戲很快就變得不可玩。建議每次只減少 5 到 10 毫秒并且設(shè)置一個(gè)下限比如 60 毫秒保證游戲的可行性。具體閾值建議你在真機(jī)上調(diào)因?yàn)椴煌说姆磻?yīng)速度和顯示器刷新率會(huì)有差異。我自己的實(shí)測(cè)經(jīng)驗(yàn)60 毫秒是最快的極限再快人眼已經(jīng)很難判斷蛇頭位置了。80 毫秒到 100 毫秒是高手還能玩普通玩家勉強(qiáng)跟得上的甜點(diǎn)區(qū)。你也可以用累加得分的方式來(lái)分段提速比如每吃 5 個(gè)食物提升一檔速度這樣玩家有明顯的節(jié)奏感而不是每吃一個(gè)就變快一點(diǎn)那種體驗(yàn)反而很累。還有一個(gè)值得嘗試的擴(kuò)展方向食物得分可以多樣化。給普通食物 10 分偶爾出現(xiàn)一個(gè)特殊食物 50 分限時(shí)出現(xiàn)幾秒后消失。這會(huì)迫使玩家在追高分的風(fēng)險(xiǎn)和穩(wěn)定推進(jìn)之間做取舍。當(dāng)然這是進(jìn)階玩法了基礎(chǔ)版先把狀態(tài)機(jī)跑通再往上疊加復(fù)雜度。蛇向前的方向判斷我最后再?gòu)?qiáng)調(diào)一遍在 move 里方向的計(jì)算用 this.direction而不是 this.pendingDirection。this.pendingDirection 只是緩沖真正的移動(dòng)方向是在每次移動(dòng)完成時(shí)從 pendingDirection 同步過(guò)來(lái)的。如果搞反了會(huì)出現(xiàn)按一下方向鍵蛇立刻轉(zhuǎn)向但畫面還沒移動(dòng)視覺上非常割裂。這個(gè)順序我在調(diào)試時(shí)栽過(guò)跟頭所以拿出來(lái)單獨(dú)提醒你。代碼寫到這里貪吃蛇的核心類就全部完成了。你可以打開瀏覽器按 Enter 開始用方向鍵或 WASD 控制空格暫停死了按 Enter 重來(lái)。整個(gè)過(guò)程跑通之后再回頭去讀 snake.ts 和 game.ts 這兩個(gè)文件會(huì)發(fā)現(xiàn)所有的復(fù)雜性都被類的邊界切成了小塊。這個(gè)感覺就是面向?qū)ο笤O(shè)計(jì)在實(shí)戰(zhàn)項(xiàng)目中最直接的回報(bào)。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
超碰日本97美女人妻人人玩人人爱| 操死我干死我| 久久欧美性爱视频| 日本精品一区二区三| 亚洲色色探花| 久久久男人的天堂| 一个国产在线综合网站| 99re6在线视频精品免费完整版安卓版| A一区片| 五月色综合| 淫淫综合网| 亚洲天堂 视频你懂的| 人澡逼| 一本一道vs波多野结衣| 午夜在线播放| 四虎AV影视国产精品亚洲精品| 91丨人妻丨国产丨丝袜| 国产欧美美女免费观看视频| 自拍偷拍国产欧美日韩韩| 小草三级久久观看| 岛国爱情动作片在国产AV无码专区亚洲AV漫画 | 91被操| 性欧美天天| 不卡中文字幕aⅴ在线| 91色综合激情| 涩涩涩综合| 91久久堂| 国产 亚洲 丝袜 制服| 九九av| 国产剧情AV不卡在线观看| 国产日产欧产美韩系列麻豆免费| 亚洲素人综合| 志村玲子视频一区二区| 日韩兔费看黄片| 九九久久首页| 一类无码操逼视频| 中文字幕一品色图| 又大又白奶子| 久草尤物| 欧美激情总合网| 超碰碰碰碰| 精品人妻一区二区三区视频在线| 亚洲天堂,男人| 久久精品一区二区一8| 91天天综合网,天天综合网| 韩日性爱av| 久久风骚城市| 久久免费中文字幕在线观看| 国产男人又猛又粗又爽| 亚洲 日本 不卡| 久久99国产综合精品女同| 久久久久久国产成人| 亚洲揄拍网| a在线视频免费观看| 欧美天天射| 中文幕97| 狠狠色色| 亚洲国产婷婷在线播放| 天堂性色| 久久夜夜夜| 婷婷色在线| 国产成人欧美一区二区三区的国产| 色香综合天天影视综合 | 亚洲第一页综合在线| 五月综合久久| 欧美成人四级在线播放| 日本二三四区| 中日992视频| 夜夜高潮夜夜爽高清视频一| 天天视频综合在线观看视频| 色婷婷国产精品一区在线观看| 国产又大又粗又色生活片亚洲国产精品成人久久久综合免费 | 啪啪啪东京| 大香蕉国产中文自拍| 国产激情av女片自拍| 老熟女91| 这里只有97精品| AV天堂男人的天堂| 婷婷伊人綜合中文字幕| 艹少妇网站| 中文乱码字字幕在线第5页| 色偷综合| 欧美影音在线| 亚洲精品天天影视综合网 | 一级毛片久久久久久久女人18| 91美女片在线| 好一吊区二区| 伊人991| 精品久久視頻在线| 男人的天堂一区三区| 啊啊啊好多水| chaopen97久久| 欧美熟妇乱码在线一区| 色九月| 人妻 中文 日韩| 明星性猛交ⅹxxx乱大交| 日日摸日日碰夜夜爽视频| 99热日| 国产精品色哟哟| 亚洲色图大香| 久久婷婷五月综合| 999岛国大片| 岛国福利在线精品播放| 爱妃国产亚洲视频中文字幕| 青青草久草| 欧美综合色综合| 欧洲亚洲人妻无码中字久久三区四区| 天天日日舔舔| 天美欧美国产| 久草精品一区| 精品国产久久乱码| 天美传媒av在线| 大香蕉综合久久| av亚洲天堂资源网站| 久操九九九九| 91neishe| 九九九久千久久激情蜜桃在线看| 中文高清一区二区的| 亚洲性爱高潮影院| 精品人妻二区三区| 中文字幕国产精品1区| 欧美精品四区| 日韩/97| 少妇99成人麻豆| 青青草中文-久久青草精品一区二区三| 温婉少妇玩3p| 人、人、摸,人、人、草| 人人摸人人摸人人干| 久草视频观看视频在线| 操逼操逼逼操操逼91 | 9久9久9久9久视频网站| 人妻少妇精品无码专区二区密桃| 美女91网址| 欧美瑟综合| 97在线观看视频| 一二三卡欧美日韩人妻免费精品| 国产区在线| 一区二区中文| 五十路六十路素人熟女| 97人妻免费中文字幕| 日本操逼二区| 丁香五月激情综合国产| 久久精品亚洲婷婷| 伊人精品视频| 国产路线专区| 老司机天天操| 在线国产一区二区av| 国产亚洲精品自在线亚洲情侣| 日本网色| 人妻天天爽夜夜爽爽| 情色五月天久久久| 精品十三区| 国产精品熟妇一区二区三| 四虎在线免费视频| 中文字幕1区2区| 在线视频97| 国产福利电影| 午夜丁香| 综合激情97| 天天操人人操骚逼网站| 色逼综合| 亚洲精品xxx| aaa一级黄片| 91女在线观看| 试看60秒| 精品无码久久久久久久久果冻糖心| 国产在线综合网| 天天色天天干天天爱| 久久精品亚洲成a人天堂| 婷婷丁香久久| 欧美精品偷拍| 91网站在线播放| 99国产精品人妻人伦| 老司机老司机午夜影院| 亚洲少妇视频| 久久精品一区二区一8| 亚洲欧综合另类无码一区| 久久一级无码精品毛片6| 亚洲 日本 一 二 三| 国产乱弄免费在线视频。| 日韩A优精品在线观看| 中国女人内射6XXXXX| 中文字幕在线24| 国产女人9999| 男女日B国产| 在线看免费无码AV天堂的| 99热色这里只有精品| 60秒免费视频| 可以免费看黄片的视频| 九月色婷婷| 亚洲人妖网| 无码人妻1727| 色婷婷亚洲婷婷| 天天色踪合| 青娱乐休闲视频在线观看| 1禁看欧美黄片免费看| 天天干天天日天天射黄色| 欧美色吧综合| 夜夜影视四色| 国产亚洲色婷婷99精品91| 变态综合色| 人妻系列无码专区中文有码| 大香蕉 222| 亚洲色交| 激情五月天网站| 亚洲drav色图| 99视频这有这里有精品| 天天综合网国产| 男人天堂无码| 亚乱色| 欧美精品91| 久艹日日日| 九九aV| 91国精产品| 日欧操屄| 91欧美偷拍| 人妻三级在线中文字幕| 资源在线观一 二| 欧美色综合网| 色五月婷婷麻豆在| 日本Suv精品一区二区| 无色无码| 五月丁香婷婷啪啪| 性欧美999| 性色av网站| 国产成人精品午夜福利| 尤物黄色在线观看网站| 欧美日韩国产人人| 欧美顶级黄色大片免费| 中文字幕视频免费| 逼逼逼逼操操操操操操操操操午夜剧场 | 97jingpin| 久草免费福利在线播放| 精品久久艹| xxx0国产在线播放| 亚洲女人毛茸茸91| 综合婷婷| av亚欧| 久久久久9久久久久| 久久久999| 少妇免费视频| 人妻一区二区三区视频| 久久国99999| 熟妇的味道HD中文字幕| 色香91| 国产 三级自拍| 极品少妇久久久久| 天美国产精品| 日本三级网页| av天堂加勒比| 久久久久久久极品香蕉视频| 国产一区在线观看无码AV | 精品视频久久区| 在线观看精品国产免费| 欧美色九九| 青娱乐亚洲热| 亚洲天堂人妻熟妇视频| 国产美女高潮视频| 天美av在线观看| 超碰97人人cao| 老女人碰碰在线碰碰视频| 操操逼操操逼操操逼逼| 91国产丝袜白虎| 999狠狠综合| 黄色片A级一区二区三区| 999 久久久| 国内毛片免费h片在线| 日本天天干天天操一区| 欧美亚洲激情一二三| 国产视频一区二区免费| 91国产操逼视频| 国产AV人人夜夜澡人人爽麻豆| 亚洲AV永久无码一区仙野| 亚洲天堂2020| 日本加勒比无码专区一二三| 另类图片五月| 日本免费专区| 91国产操逼视频| 久久久久久久久久久久久女过产乱-少妇高潮一区二区三区喷水-成人AV | 伊人午夜福利视频| 国产怡红院| 夜间福利片1000无码| 国产精品一区二区密臀| 99精品伊人| 狠狠狠狠狠干| 午夜寂寞欧美| 欧美一区二区三区不卡高清视频 | 香蕉大久久久| 免费视频在线观看啊啊啊啊啊| 岛国激情视频在线观看| 欧美黑人极品高潮喷吹熟女黑人性暴力日韩在线欧美极品一区二区老师黑人潮喷一 | 99啪| 日本高清有码网址视频| 亚洲AV成人精品网站在AV| 91艹| 亚洲吊色| 91精品成人www| 国产女人操逼视频| 人人摸.人人色| 男人天堂新| 日日噜噜夜夜久久亚洲一区二区| 人妻少妇精品一区二区三区| 久久亚洲av成人无码国产| 麻豆性爱视频在线播放| 久久久97| 日韩成人精品视频自拍| 国产午夜福利专区综合| 人妻天堂网| 九九九九九九免费视频| 91天天爱| 99www.bibizy香蕉资源国产一区二区三区高清 | 久久香蕉综合一本到3atv| 国产精品人妻无码久久久老鸭窝| 91丝袜视频在线观看| 久久精品国产精品| 亚洲一区二区专区-国产丝袜精品丝袜-成人AV| 国产欧美美女免费观看视频| 少妇超碰在线| 亚洲高清无码免费观看视频| 婷婷视频在线免费观看| 成人a大片在线观看| 东京热一区二区中文字幕| 99超碰碰| 日韩精品一二三| 亚洲极品| 日本三级精品| 操熟女91| AV中亚| 狠狠爱夜夜| 欧美色交| 情色图区| 密臀在线一区尤物| 精品欧美乱码久| 亚洲欧美97√| 欧美性第一页| 久久久久久99AV无码免费网站| 欧美精品庄| 国产精品日日摸天天碰| 亚洲 欧美 日韩另类 麻豆| 操逼短片| 91狠狠狠| 999国产精品999久久久久久| 天天欧美| 啊啊啊好多水| 日韩性爱一级片| 麻豆性爱视频在线播放| 校园春色中文字幕AV| 色娱乐色呦呦夜夜夜夜av| 怡春苑东京热| 亚洲熟女乱色一区二区三区久久久| 91成人社区| 色天堂在线观看| 精彩久久中文| 色九久| 九色黄站| 国产高清视频无码在线| 多毛小伙内射老太婆 | 激情开心五月天| 丝袜 亚洲 偷拍| 欧美日日网| 9超碰免费| 伊人 俄罗斯 a v| 破处bbq| 超碰人妻97| 男人午夜天堂| 女人被男人桶爽视频网站| 日韩激情小说一区二区| 欧美 亚洲 偷拍自拍| 九九色综合| 久操B网| 极品粉嫩少妇视频| 欧美性少妇| 久久超碰日韩精品| 欧美一级特黄淫片在线观看| 最新日韩黄片| yazhousetuoumei| 天天射夜夜| 我爱操| 91综合在线| av在线播放国产一区| 99热只有这里有精品| 激情自拍 校园春色| 操b网站亚洲无码| 日本三级韩国三级美三级91| 91综合中文字幕| 操逼逼一区视频| 国产视频一区二区免费| 日本天天吊| 爱妻综合网| 久久9精品| 夜夜狠狠躁日日躁色视频| 日日骚精品视频| 蜜臀久久99精品久久久久久| 一二三四视频中文字幕在线看| 人人干人人操人人..com| 欧美老熟另类| 大香蕉2017| 51国产午夜精品视频| 插日本熟女视频| 日本有码影片下载| 亚洲第一页综合在线| 麻豆国产精品午夜视频| 99日韩| 伊人一区二区三区| 欧美 亚洲 在线| av在线一区二区三区| 综合网欧美在线| 一区二区三区色综合| 天天肏天天干| 另类天堂| 亚洲区小说| 国产成人99久久亚洲综合| 久草婷婷| 99超碰网| 一级久久性爱视频| 亚洲图片 激情小说| 欧美精品宗合| 五月天激情网图片| 亚洲素人综合| 综合操逼| 中文字幕女同在线| 亚洲av综合伊人久久| 日本免费中文一区二区三区四区| 少妇熟女视频一二三区| 人干人人人操人人摸| 啊啊啊好湿久久| 伊人麻豆传媒| 大香蕉人妻| 美国三级日本三级久久99| 乱操乱伦AV| 亚洲欧美激情另类色图| 久久久久久九| 亚洲精品丝袜-不卡成人免费…… 久久久久成人蜜桃精品 | 亚洲欧美另类激情小说| 99在线精品视频| chaopen97久久| 黑人嘿嘿嘿超爽免费视频| 欧美国产有色电影| 26uuu国产亚洲综合| 性色一线| 国产99热| 欧美视频在线第3页| 亚欧洲日韩国产精品| 凸凹视频在线观看| 999热日韩精品| 欧亚免费视频| 欧美大的香蕉有线电视视频| 国产精品色色| 97超碰欧美中文字幕| 婷婷在线播放| 97超碰欧美| 久久大香蕉手机高清| 诱惑网综合| 农村女一级毛卡片| 日韩精彩免费| av无线看| 日韩人妻精品| 亚洲国产一区二区三区四区国产| 日韩欧美中文字幕搭讪巨乳美人妻视频| 全免费a敌肛交毛片免费| 日本精品九九九| 免费的黄片wwwwww| 不卡视频一区蜜桃视频| 日本人体九九九九九九| 91精品国产91久久青草| 国产亚卅97| 亚洲精品一二区| 97天天插| 亚洲美乱| 在线播放免费av福利片| 国产欧美日产一区二区三区 - 国产欧美日 | 欧美日韩国产人人| 久久性爱免费送| 亚洲欲色| 国产天天看| 国产精品宅男免费| 黄页| 色噜噜人妻丝袜AV资源| 日韩一级成人毛片免费观看| 青青草好吊色| 日韩激情视频| 99精品成人免费看| 97视频在线播放| 神马午夜久久久| 亚洲97久久精品亚洲| 亚洲精品黄码久久久久| 一区 欧美 日韩 麻豆| 亚洲av影院在线观看| 精品人妻一区二区三区视频在线| 国产白嫩精品久久| 秋霞一级视频在线观看免费| 一区二区三| 国产精品久久久久久久久久久久久久久久 | 亚洲 综合 欧美| 天堂69亚洲精品中文字| 极品美女福利在线观看| 国产深夜福利| 天天日美女的B| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 99久久婷婷| 欧美成年人性爱视频免费观看| 日韩电影天堂视频一区二区| 五月综合激情网| 国产AAAAAABBBBB| 国产视频97| 亚洲妇色| 91黑丝露脚| 26UUU欧美激情一区二区| 色香av| 龙兴卡官方查询| 久操黄色视频| 精品一区二区亚洲国产| 免费av高清无码| 精品夜夜澡人妻无码AV| 亚洲少妇在线影音| 91色艳| 亚洲二区精品在线观看| 日韩特级毛片免费观看全集| 91高清欧美| 国产日韩人人| 久久99黄色卞西瓜| 婷婷色婷婷| 超碰在线香蕉| 国产精品人妻一区二区| 日韩啪啪视频| 精品人妻一区二区三区免费视频| 美女诱惑在线一区| 亚洲国产综合久久天堂| 啊啊啊操一区| 久久久夜夜嗨免费视频| 青娱乐国产精品| 可以免费看黄片的视频| 国产成年女黄特黄| 资源新线在线天堂| 狠狠爱夜夜| 男人的天堂三级| 天天操人人操骚逼网站| 午夜一级免费毛片| 精品无码欧美三级| 亚洲人天堂| 日本欧美不卡| 亚洲精品蜜桃久久久| 亚洲精品黑丝| 九九av| 怡红院成人av| 国产青青美女玩逼视频| 欧美 日韩 另类 亚洲| 伊人色综合超碰| 四虎AV无码| 久久久久久久久久久久久9999| 丁香五月偷拍| 成人五月香网在线| 91 手机在线播放 绯色| AV天天在线观看| 大奶啊啊好爽| 99青草| 超碰调教97| av优播| 91在线美女| 9/A片 | 五月天婷婷色| 亚洲 综合 欧美| 人妻少妇一区二区| 日韩av女优在线免费一区| 伊人天堂在线| 天天干天天日天天射黄色大片| 91精品人妻一区二区三区蜜桃臀| 91欧美偷拍| 天天看人人操屄犊摸阴| 999 久久久| 亚洲熟女偷拍在线观看| 日1区2区3区2020| 91欧| 欧美色偷偷| 偷拍综合网| 操国产逼| 伊人久久大香线蕉无码| 草莓精品视频| 首页亚洲国产高跟丝袜诱惑视频| 欧美少妇大量自拍视频在线观看| 亚洲熟妇熟在线电影视频| 色五月第四色| 欧美亚洲清纯| 欧美日韩资源| 天天躁日日躁AAAAXXXX国产| 国产亚洲精品农村妇女| 欧美顶级黄片AAAAA在线免费看| 久久亚洲婷婷| 亚洲限制级在线| 久干网| 大香蕉手机在线| 日本天天干天天操一区| 欧美呦呦性爱| 怡红院一区二区熟女人妻| www.狠狠| 日本一天色道久久久精品视频| 国产精品国产| 热热色中文无码| 国内精品久久人妻性色av| 综合影视国产无码| 台湾佬激情综合| 少妇内射www在线观看视频| 怡红院久久老司机| 日韩精品一区二区高清 | 99热免费| 国产丸一视频| 天天色图| 免费毛片在线播放| 色眯眯射| 一二三区精品视频| 另类TS人妖一区二区三区| 免费毛片在线播放| 色婷婷综合久久久久中文一区二区| 天天日熟妇| 91久久青青草原精品| 亚洲精品啪视频| 69AV女优男人的天堂| 一区二区不卡免费| 欧洲黄色网| 蜜乳av首页| 欧美在线l亚洲| 中文字幕成人乱码熟女精品国50 | 亚洲乱色视频一区、二区在线| 中文字幕免费看| 一级黄色性爱裸体视频| 日韩成人电影AV| 少妇内射www在线观看视频| 啪啪自拍九九综合| 日韩AV无码中文一区二区| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 精品人妻av区天天看片| 日韩亚洲Av人人夜夜澡人人爽| 亚洲AV乱码专区国产噜噜亚洲| 超碰这里有精品| 亚洲色欲天天天堂色欲网女| 久久久久13| 日本道人妻久久久在线不卡色视频| 成人26uuu| 中文字幕人妻丝袜| 日本布卡一区二三区| 色网在线视频观看免费| 四虎AV无码| 美女网站91| 国产小u女在线观看| 亚洲无限观看| 成人自拍三级在线观看| 91丝袜美女| 日韩在线电影| 色婷婷丁香五月| 视频在线97| 91成人久久| 欧美色日本| 高清国产精品无码| 影音综合网| 中英熟女操女| 97超级久久强资源| 色臀av| 欧美综合站| 后入国产| 校园春色制服丝袜中文字亚洲| 久久久久白虎| 色色色热| 国产熟女无套内射| 九九在线精品| 久久啊啊| 日韩精品.久久精品.AV女优.天美传媒| 亚洲色图日韩丝袜制服一区二区五月在线| 女同性恋久久| 老鸭窝成人| 色爱国产| 99热销国产这里有精品| 91美女中出| 99热在线播放| 色综合98| 久久久久亚洲熟妇熟女| 欧美五区| 日韩精品在线观看观看| 天天超级碰碰碰| aaaa少妇高潮大片| 久久国产精品视频| 狠狠色丁香| 91骚熟女| 佐山爱中文字幕| 人人看人人插| 无码操逼天堂| 国产精品成人无码av| 91日韩网站| 中出91| A级在线视频| 麻豆一区在线| 妺妺跟我一起洗澡没忍住| 九九操久久国产免费视频| 五月综合久久| 26UUU欧美日本| 天堂射| 欧美一级黄片免费播放| 久久αⅴ| 97在线欧洲| 操B在线观看| 亚洲图片小说欧洲| 中文字幕91综合| 亚洲好看强奸乱伦| 懂色av中文字幕| 日韩AV电影网站 | 中文字幕91综合| www.伪伪| 日韩99999| 无码人妻丰满熟妇奶水区毛片| 黄色AAAAA欧美| 亚洲精品97久久中文字幕| 啊啊啊啊嗯嗯嗯用力好爽| 啪啪性爱免费视频| 91女优在线观看 | 国产精品伦理| 双插在线| 91碰碰碰| 少妇一区二区三区精选| 91欧美少妇| 国产精品久久久久绯色| 亚洲精品啪视频| 久久久999| 天天天堂影视日韩亚洲91| 人妻加勒比东京热| 日韩卡一卡二卡三在线| 97超碰香蕉| 亚洲日韩久久精品一区| 亚州精人品大香蕉| 免费伦费视频在线观看| 91暧暧| 爱爱动态60秒| 日本一区二区三区精品| 国产高清成人mv在线观看| A V视频日本| 人人操人人精品影片| 91欧洲入口| 97国产精品在线观看| 都市激情人妻一区二区青青操视频| 日本黄色天堂| 精品一区二区三区18| 国产精品扒开腿做爽爽爽视频| 欧美日韩色| 亚洲极品| 东北少妇高潮zzzz| 免费久久一级毛片大黄| 做爱A级亚欧| 强免费黄色网址| 99热综合| 国产高清不卡视频| 久久夜色一区二区| 国产精品动态一区二区三区四四| 欧美综合传媒| 国产一区二区成人av在线播放| 超碰97欧美在线| 欧美,日韩,中文,另类| 成年人性爱日韩| 20cm女自慰在线日韩欧美| rivers-china.com| 亚洲 欧美 另类 日韩 人妻一区| 香蕉在线一区二区三区| www.av在线观看| 高清国产性猛交xxxx乱大交| 91爱| 久久久亚洲熟妇资源| 国产丰满少妇久久久精品影院| 欧美有码激情视频一区二区三区| 日韩激情啪啪| 成人aⅴ一区二区三区| 乱伦熟女论坛| 亚洲天天操| 国产农村妇女毛片精品久久| 韩国嫰模上门援交视频| 四虎AV影视国产精品亚洲精品| 校园春色之综合网| 97五月天| 噜噜噜狠狠色综合| 静品嫩模一区二区| 亚洲超碰AV| 国产操逼逼网| 欧美老妇曰批的视频| 精品日韩人妻视频| 超碰在线人妻中文字幕| 黄片www视频免费| 91综合网站| 久久啊啊| 91亚洲影视| 五月情色天| 中文字幕成人乱码熟女精品国50 | 九九久久首页| 中文字幕一区 二 区 三 四 五 区日 日 骚 | 91精品导航| 中文字幕丝袜| 麻豆视频一区二区| 另类图片天天影视| 91天天| 人妻少妇久久中文字幕一区二区 麻豆| 久久久91| 中文字幕三四区| 国产成年女黄特黄| 女人与公拘交酡2020视频| 人妻9117c| 人人看人人插| 国产毛片在线| 亚洲五码一区二区三区| 偷看洗澡一二三区美女| 国产高潮AA片免费看| 日本福利二区视频| 中出91| 九九无码久久精品视频| 大香蕉欧美伊| 欧美天堂第二区| 伊人在线大香蕉视频久久| 久热网| 超碰人妻久久| 成人性爱免费播放| 巨爆乳一区二区爆乳区 | 久久性爱城| 精品视频久久久久九九九九9999| 校园春色 男人天堂| 九九热免费在线国产视频伊人五月| 91九九九逼| 日韩综合97P| 天天射天天色成人| 国产真实子伦对白| 中文字幕一二区二三区人妻专区| 亚洲av影院在线观看| 日本99热| 日产中文字幕2020| 亚州色阁| 亚洲图片欧美| 香蕉热人人精品| 亚洲一区日韩| 成人女人国产| 亚洲影视第一页| 亚洲国产精品成人久久蜜臀| 久久久久久久久久久免费精品| 性爱乱伦一区| 日韩中字av一区| 蜜桃久久久久久久久久久久| 懂色AV网| 在线亚洲 欧美 日本专区| 亚洲最大AV网| 偷拍欧美激情| 四虎影视永久在线观看精品免费网站| 日韩图色| 精品国产人成在线| 亚洲 欧美都市激情| 欧美97视频| 欧美性性性| 久久美女国产| 日本韩国一本产品小视频日本韩国一本产品久久久产品小视频日本韩国一本产品久 | 操美女人妻| 啊啊啊轻点在线观看| 免费无码婬片AAAA片直播色戒| 强奸乱伦av电影| 大香蕉AV丝袜| 五十路熟女,国产欧美精品区一区二区三区| 97国产精品一区二区传媒公司| 天天操夜夜操狠很操| 婷婷中文字幕| 天天摸天天舔天天操| 99爱爱| 欧美少妇第一页| 精品少妇高潮久久| 人人妻人人爽 97人人看碰人免费公开视频| 亚洲砖码砖专无区2023| 日日干夜夜操视频h| 亚洲精品国产拍免费91在线| 国产日逼视频| www.超碰| 亚洲影视第一页| 操操逼视频| 激情自拍 校园春色| 久久久久久免费电影| A一区片| 99成人| 青青草中日韩在线| 操B视频日韩无码| 国产成人资源| 超碰久久.com| 天天日B夜夜干B时时操B| 日本97久久久精品| 久久区| 久久香蕉影院| 骚货 中文字幕 av| 国产传媒操逼视频| 国产综合久久久鬼色| 超碰免费人妻在线| 91啪啪| 美女天天干| 日逼国产| 色悠久久久av| 天天激情干| 久久AV无码1区2区3区| 激情小说亚洲| 久久天堂婷婷网| 精品国产a∨一区天美传媒| 在线无码操| 91超碰在线播放| 人人艹亚洲| 蜜臀99999| 日韩av免费一级电影| AV天堂电影网| 人妻夜夜爽天天爽三区麻豆AV网站| 人妻av在线| 国产精品另类| 色婷久久| 青青五月天| 五月激情影院| 色色九区| 天堂蜜桃无码视频一区二区| 蜜臀久久久99久久久久| 亚洲人人操| 中文 人妻 制服| 日韩人妻精品久久久久| 久久午夜色播影院免费高清| 6080yy午夜理论三级一区二区三区无码| 美女黄页网站| 91色情黑丝搞鸡在线观看一区二区三区三州| 亚洲影视高清三级-草1024榴社区入口-品爱AV| 性做久久久久久久| 中文字幕精品亚洲熟女| 欧美网站免费| 日本幼女18+| 色综合99| 91欧美亚洲| 天天干2区3区| 一区操逼| 久久综合久色欧美综合狠狠| 欧美性爱十八禁| 国产丁香精品露脸视频| 五月婷婷色| 亚洲色图亚洲| 熟女中出视频| 亚洲av综合色| 超碰97极品9| 天美AV片| 操操操五月天婷婷丁香影院| 福利在线视频一区二区| 在线精品福利免费播放| 91美女视频直播| 精品久久視頻在线| 久久丁香久草综合网| 久久99精品九九久久久婷婷| 精品国产乱码久久久久久口爆网站| 久久久天美| 四虎AV在线观看| 秋霞操逼片| 亚州图片第一页| 婷婷综合五月天| 青娱乐老司机视频| 大屁股熟女一区二区三区| 亚洲人妻av| 性无码专区2020| 亚洲 综合 第一页| 99热婷婷| 18禁止看精品中文字幕| 欲色啪| 夜夜肏2021| 6080YYY午夜理论片在线观看| 天天综合网合集91| 日韩情色视频| 日韩 欧美 视频 在线 一区| AV女资源| 激情文学欧美| 妺妺跟我一起洗澡没忍住| 男人的天堂网页| 国产女人9999| 深夜啪啪啪视频免费| 日韩综合无码色欲vv| 风间由美日韩欧美久久| 九九九综合精品| 欧美亚洲日本视频久久久| 久久久久久久9| 91强在线播放| 色综合98| 在线性黄高清免费视频| 五月丁香激情四射| 91美女视频电影| 亚洲免费精品一区| 人、人、摸,人、人、草| 五月亭亭六月丁香| www欧美性爱| 97在线观看| 夜夜爽夜夜摸夜夜操免费视频| 精品视频123区小说区| 国产精品无码论坛| 另类图片欧美激情综合| 97在线公开视频| 精品性爱久久视频| 欧美熟爽综合| 视频分类 国内精品| 亚洲国产精品无码AV久久久| 床戏久久久av一区二区麻豆| 亚洲情色在线| 天天操女人| 日本午夜久久电影| 久久人人爽爽人人爽人人片αV| 天天综合中文字幕 91| 男女性扦B| 中文字幕免费观看| 天美传媒国产原创中文字幕亚洲欧美另类| 色嗨嗨在线| 欧美在线永久天堂| 97超碰人妻| 91亚洲最新在线| 97就爱干| 人人妻人人色| av在线人气| 亚洲男人天堂Av| www.人人cao| 成人三一级一片aaa| 国产女s强制榨精视频| 91亚洲人| 久久久久久加勒比| 人妻丰满熟妇av无码区蜜桃| 日韩欧美水蜜桃人妻| 蜜臀久久99精品久久久久免费观| 夜夜一区二区| 五月丁香综合| 成年女人18级毛片毛片免费观看| 国产精品爽爽v| 亚洲欧洲无码bt精品合集| 久久久9999| 中文字幕乱码在线观看| 亚洲一区二区中文字幕| 热久久无毒不卡| 操淫穴亚洲五月丁香| 蜜桃精品视频一区| 丰满搜索结果 -第18页- 久久高清无码| 在线观看AV不卡| 欧美色图天堂在线| 婷婷久久综合| 婷婷色在线| 99久在线精品99re8热| 国产AV超爽| 国模吧 一区二区三区| 性爱乱伦网址| 无码在线亚洲| 日本熟妇人妻中出视频| av午夜影院在线播放| 午夜男人av| 久久久久久久亚洲Av无码| 欧美综合娱乐久久| 日本无码1| 久久亚洲精品成人av| 国产粉嫩出水在线播放| 91|九色|国产熟女| 婷婷五月天成人| 91粉芽高清在线一区二区| 国产丝袜视频| 精品无码一区二区| 97色欧州| 91欧美性| 99热线麻豆| 欧美色图亚洲色| 天天看天天日天天操| 亚洲男人综合| 亚洲囯产精品女人久久久| 大香蕉久| 国产激情片在线观看| 亚洲丁香花色| 九色 人妻 大香蕉| 色综合加勒比四四季| 330dv亚洲成年视频网| 亚洲91综合| 亚洲欧美91| 国产精品久久久啊| 91性高朝久久久久久久久| 无码人妻精品一区二区中文 | 色五月婷婷网| 北条麻妃99精品青青久久| 操B久久| 欧洲亚洲人人爽爽视频| 91狠狠狠| 久久少妇| 天天操人人操狠狠插| 日本欧美亚洲高清在线看| 五月丁香色色网| 77777亚洲蜜臀精品久久综合蜜臀| 欧美亚洲第1页| 久久精品视频一区三区小泽玛利亚| 欧美综合自拍亚洲综合图| 人爽不卡视频| 久久久久久亚洲Av无码| 欧美日韩香蕉| 67914亚洲精品| 欧美日韩大陆黑人少妇99| 另类老少妇| 亚洲在线| 日本性爱网址| 欧美黑人XXXⅩ高潮交| a人欧美综合天堂麻豆| 欧亚日本情色| 国产精品精品系列在线观看| 欧美一级黄片视频在线| 久久五月视频| 九九久久国产精品| 疯操AV| 日产操逼| 91黑人无码激情在线| 91暧暧| 久久久青草青青国产亚洲免观精品高清完整版_97久久综合区小说区图片区,国精品 | 亚洲黄网在哪免费看| 欧美性爱97超碰| 大香蕉青青9| 国产精品96| 国产麻豆福利av在线播放| 熟女人妻久久中文字幕一二区| 美女主播色欲91抠b在线播放| 欧洲亚洲人妻无码高清久久三区四区| 欧美福利视频啊啊啊啊| 操逼日韩无码 | 欧美极品性爱天天射| 亚洲色图超碰在线| 任我爽在线视频免费观看| 91精片| 久久久 国产精品| 九九成人精品| 欧美78P| 免费观看的黄色的网站| 久久综合18p| 九九九偷拍| 91在线视频免费播放| 日韩pv中文| 综合熟妇一区二区三区| 国产一区二区三区免费视频在性观看 | 超碰2017| 熟女突然公开看18禁影片| 久久精9| 欧美一级在线观看成人| www.久久久久| 精品国产久久乱码| 夜夜草天天| 国产女人高潮视频| 97欧美色| 日韩久久.一级黄色片| 玖玖爱综合| 玖玖爱影院| 色婷婷av在线观看| 夜夜免费视频| 2017人人操,人人摸| 日韩97视频!在线| 久久精品无码专区| 色色色色网站| 一二视频神马久久传媒| 1人人看人人摸人人操| 熟女啪啪视频| 国语少妇精| 久99热| 中文字幕国产| WWW黄片COM| 操逼短片| 国产精品久久99日日| 91久久18禁| 自拍偷拍 日韩欧美| 国产精品91一样| 天天噜| 天天欧美欧美亚洲网| 久久久四区| 欧美日韩m|