在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

OpenHarmony南向開發實例:【游戲手柄】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-17 10:21 ? 次閱讀

介紹

基于TS擴展的聲明式開發范式編程語言,以及OpenHarmony的分布式能力實現的一個手柄游戲。

完成本篇Codelab需要兩臺開發板,一臺開發板作為游戲端,一臺開發板作為手柄端,實現如下功能:

  • 游戲端呈現飛機移動、發射子彈等效果。
  • 游戲端分布式拉起手柄端FA。
  • 手柄端與游戲端建立連接,發送指令給游戲端,比如移動飛機,發射子彈和釋放技能等。

最終效果圖如下:

GamePlane1.gif

搭建OpenHarmony環境

完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:

  1. [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)。
    以3.1版本為例:
  2. 搭建燒錄環境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發板的燒錄]
    3. 鴻蒙開發指導:[qr23.cn/AKFP8k]
  3. 搭建開發環境。
    1. 開始前請參考[工具準備],完成DevEco Studio的安裝和開發環境配置。
    2. 開發環境配置完成后,請參考[使用工程向導]創建工程(模板選擇“Empty Ability”),選擇JS或者eTS語言開發。
    3. 工程創建完成后,選擇使用[真機進行調測]。
      2.鴻蒙next文檔籽料+mau123789直接去v拿取

搜狗高速瀏覽器截圖20240326151547.png

分布式組網

本章節以系統自帶的音樂播放器為例(具體以實際的應用為準),介紹如何完成兩臺設備的分布式組網。

  1. 硬件準備:準備兩臺燒錄相同的版本系統的RK3568開發板A、B。

  2. 開發板A、B連接同一個WiFi網絡。
    打開設置-->WLAN-->點擊右側WiFi開關-->點擊目標WiFi并輸入密碼。

  3. 將設備A,B設置為互相信任的設備。

    • 找到系統應用“音樂”。

    • 設備A打開音樂,點擊左下角流轉按鈕,彈出列表框,在列表中會展示遠端設備的id。
    • 選擇遠端設備B的id,另一臺開發板(設備B)會彈出驗證的選項框。
    • 設備B點擊允許,設備B將會彈出隨機PIN碼,將設備B的PIN碼輸入到設備A的PIN碼填入框中。


    配網完畢。

代碼結構解讀

  • [HandleEtsOpenHarmony]
  • [GameEtsOpenHarmony]

本篇Codelab只對核心代碼進行講解,對于完整代碼,我們會在參考章節中提供下載方式,首先介紹一下整個工程的代碼結構:

└── HandleGameApplication
	│── GameEtsOpenHarmony
	│  
	└── HandleEtsOpenHarmony

其中HandleEtsOpenHarmony為手柄端工程代碼,GameEtsOpenHarmony為游戲端工程代碼。

HandleEtsOpenHarmony

  • MainAbility:存放應用主頁面。
    • pages/index.ets:應用主頁面。
    • common/images:存放圖片資源的目錄。
  • ServiceAbility:存放ServiceAbility相關文件。
    • service.ts:service服務,用于跨設備連接后通訊。

GameEtsOpenHarmony

  • MainAbility:存放應用主頁面。
    • pages/index.ets:應用主頁面。
    • common/images:存放圖片資源。
  • model:存放獲取組網內的設備列表相關文件。
    • RemoteDeviceModel.ets:獲取組網內的設備列表。
    • GameElement.ets:游戲端界面元素的實體類,用于封裝子彈、飛機等元素的屬性。
  • ServiceAbility:存放ServiceAbility相關文件。
    • service.ts:service服務,用于跨設備連接后通訊。

實現手柄端功能

  1. 實現布局和樣式。
    手柄端有兩個功能:向游戲端發送指令和實時獲取游戲端得分數據。界面上有三個功能組件:藍色圖形組件用于控制游戲端飛機移動方向,黃色圖形組件用于發射子彈,綠色圖形組件用于釋放技能,效果圖如下:

    主要代碼如下:
    @Entry
    @Component
    struct Index {
    ...
      build() {
        Stack() {
    	...
    		Text('score:' + this.score)
    		...
          Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.SpaceBetween }) {
            Stack() {
              Image('/common/images/bigcircle.png')
                .width(300)
                .height(300)
              Image('/common/images/smallcircle.png')
                .width(140)
                .height(140)
                .position({ x: this.smallPosX, y: this.smallPosY }) // 30+75-35
            }
           ...
            Row() {
              Image('/common/images/a.png')
                .width(160)
                .height(160)
                .margin({ right: 20, bottom: 80 })
              Image('/common/images/b.png')
                .width(200)
                .height(200)
            }.alignItems(VerticalAlign.Bottom)
    		...
        }
      }
    }
    
  2. 實現搖桿功能。
    給搖桿(藍色小圓圖形)添加TouchEvent,動態改變搖桿position屬性使搖桿跟隨手指移動,主要代碼如下:
    onTouchEvent(event: TouchEvent) {
      switch (event.type) {
        case TouchType.Down:
          this.startX = event.touches[0].screenX;
          this.startY = event.touches[0].screenY;
          break;
        case TouchType.Move:
          this.curX = event.touches[0].screenX;
          this.curY = event.touches[0].screenY;
          this.getSmallCurrentPos(this.curX - this.smallR - 60, this.curY - this.smallR - 60)
          angle = Math.round(this.calculateAngle());
          break;
        default:
          break;
      }
    }
    
  3. 計算搖桿偏移角度。
    主要代碼如下:
    calculateAngle() {
      var angle = 0
      var degree = Math.atan(this.getDisAbsY() / this.getDisAbsX()) * 180 / Math.PI
      var quadrant = this.quadrant();
      switch (quadrant) {
        case this.QUADRANT_1:
        // 向右上移動
          angle = degree;
          break;
        case this.QUADRANT_2:
        // 向左上移動
          angle = 180 - degree;
          break;
        case this.QUADRANT_3:
        // 向左下移動
          angle = -180 + degree;
          break;
        case this.QUADRANT_4:
        // 向右下移動
          angle = -degree;
          break;
        default:
          angle = 0;
          break;
      }
      return angle;
    }
    
  4. 連接游戲端Service。
    當手柄端被游戲端拉起時,獲取游戲端傳遞的數據:游戲端deviceId和分數score。然后通過deviceId連接游戲端Service,主要代碼如下:
    aboutToAppear() {
      // 當被拉起時,通過want傳遞的參數同步對端界面UI
      await featureAbility.getWant((error, want) = > {
        // 遠端被拉起后,連接游戲端的service
        if (want.parameters.deviceId) {
          let remoteDeviceId = want.parameters.deviceId
          connectRemoteService(remoteDeviceId)
        }
      });
    }
    
    async function connectRemoteService(deviceId) {
    ...
      await featureAbility.connectAbility(
        {
          'deviceId': deviceId,
          'bundleName': "com.huawei.cookbook",
          'abilityName': "com.huawei.cookbook.ServiceAbility",
        },
        {
          onConnect: onConnectCallback,
          onDisconnect: onDisconnectCallback,
          onFailed: onFailedCallback,
        },
      );
    }
    
  5. 通過RPC發送數據到游戲端。
    連接游戲端Service之后,搖桿角度angle和操作類型actionType(1為發射子彈,2為釋放技能)發送給游戲端,主要代碼如下:
    async function sendMessageToRemoteService() {
    ...
      let option = new rpc.MessageOption();
      let data = new rpc.MessageParcel();
      let reply = new rpc.MessageParcel();
      data.writeInt(actionType);
      data.writeInt(angle);
      await mRemote.sendRequest(1, data, reply, option);
    }
    

實現游戲端功能

  1. 實現布局和樣式。
    游戲界面主要由玩家飛機、敵機、子彈和道具(降落傘)等組成,由于敵機和子彈都是多個的,所以使用ForEach來實現,主要代碼如下:
    @Entry
    @Component
    struct Index {
    
      build() {
        Stack() {
        ... 
    
          ForEach(this.bullets, item = > {
            Image(item.imgSrc)
              .width(item.imgWidth)
              .height(item.imgHeight)
              .position({ x: item.positionX, y: item.positionY })
          }, item = > item.timestamp.toString())
    
          ForEach(this.enemyPlanes, item = > {
            Image(item.imgSrc)
              .width(item.imgWidth)
              .height(item.imgHeight)
              .position({ x: item.positionX, y: item.positionY })
          }, item = > item.timestamp.toString())
    
          Image('/common/images/planeOne.png')
            .width(this.planeSize)
            .height(this.planeSize)
            .position({ x: this.planePosX, y: this.planePosY })
            .onTouch((event: TouchEvent) = > {
              this.onTouchEvent(event)
            })
    
          Image('/common/images/props.png')
            .width(this.propsSize)
            .height(this.propsSize)
            .position({ x: this.propsPosX, y: this.propsPosY })
        ...
        }
        .height('100%')
        .width('100%')
      }
    }
    
  2. 實現游戲端元素動畫效果。
    飛機、子彈和道具等元素的移動是通過動態改變Image的position屬性來實現的。使用定時器setInterval每隔16ms重新設置界面元素position屬性的值,主要實現代碼如下:
    startGame() {
        var that = this
        setInterval(function () {   
          // 每60*16ms創建一個敵機
          if (that.num % 60 == 0) {
            that.createEnemyPlane()
          }
          // 移動子彈
          var bulletsTemp: GameElement[] = []
          for (var i = 0; i < that.bullets.length; i++) {
            var bullet = that.bullets[i]
            bullet.positionY -= 8
            // 當子彈移除屏幕外的時候,釋放掉
            if (bullet.positionY > 0) {
              bulletsTemp.push(bullet)
            }
          }
          that.bullets = bulletsTemp
          // 移動飛機
          var enemyPlanesTemp: GameElement[] = []
          for (var j = 0; j < that.enemyPlanes.length; j++) {
            var enemyPlane = that.enemyPlanes[j]
            enemyPlane.positionY += 6
    
            // 當飛機移除屏幕外的時候,釋放掉
            if (enemyPlane.positionY < that.screenHeight) {
              enemyPlanesTemp.push(enemyPlane)
            }
          }
          that.enemyPlanes = enemyPlanesTemp
          // 每隔 500*16ms顯示降落傘
          if (that.num % 500 == 0) {
            that.getPropsFlag = true
            that.propsPosY = -that.propsSize
            that.propsPosX = Math.round((Math.random() * (that.screenWidth - that.propsSize)))
          }
          // 刷新道具位置
          if (that.propsPosY < that.screenHeight) {
            that.propsPosY += 6
          }
          that.checkCollision()
        }, 16);
      }
    
  3. 判斷元素是否發生碰撞。
    在setInterval中改變元素位置的時候同時檢測元素之間是否發生碰撞,子彈和敵機發生碰撞則分數值改變(摧毀小飛機加50分,摧毀大飛機加100分),玩家飛機和道具發生碰撞則道具加1,主要實現代碼如下:
    checkCollision() {
     ...
        for (var i = 0; i < this.enemyPlanes.length; i++) {
          var enemy = this.enemyPlanes[i];
          for (var j = 0; j < this.bullets.length; j++) {
            var bullet = this.bullets[j];
            var inside = this.isInside(bullet, enemy);
            // 發生碰撞
            if (inside) {
              enemy.imgSrc = '/common/images/boom.png'
              if (enemy.flag == 1) {
                this.score += 50
                sendMessageToRemoteService(that.score)
              } else if (enemy.flag == 2) {
                this.score += 100
                sendMessageToRemoteService(that.score)
              }
              // 清除子彈
              this.enemyPlanes.splice(i, 1);
              i--;
              enemy.flag = 3
              // 清除被子彈打中敵機
              that.bullets.splice(j, 1);
              j--;
            }
          }
        }
        // 飛機和降落傘是否發生碰撞
        var isGetProps = this.isInside(myPlane, props);
        if (isGetProps && this.getPropsFlag) {
          this.getPropsFlag = false
          this.bombNum++
          this.propsPosY = 2000
        }
      }
    
  4. 獲取設備列表。
    點擊界面右上角的“電腦”圖標,調用registerDeviceListCallback()發現設備列表,并彈出設備列表選擇框DeviceListDialog ,選擇設備后拉起遠端FA。DeviceListDialog 主要代碼如下:
    @CustomDialog
    export struct DeviceListDialog {
      controller: CustomDialogController
    
      build() {
        Column() {
          Text("選擇設備")
            .fontWeight(FontWeight.Bold)
            .fontSize(20)
            .margin({ top: 20, bottom: 10 })
    
          List() {
            ForEach(deviceList, item = > {
              ListItem() {
                Stack() {
                  Text(item)
                    .fontSize(12)
                    .margin({ top: 10 })
                }
                .onClick(() = > {
                  startRemoteAbility(item)
                  this.controller.close();
                })
                .padding({ left: 30, right: 30 })
              }
            }, item = > item.toString())
          }
          .height("30%")
          .align(Alignment.TopStart)
    ...
        }
      }
    }
    
  5. 拉起手柄端FA。
    點擊設備列表獲取遠程設備id后,拉起手柄端FA,代碼如下:
    function startRemoteAbility(deviceId) {
      var params = {
        deviceId: localDeviceId
      }
      var wantValue = {
        bundleName: 'com.huawei.cookbook',
        abilityName: 'com.huawei.cookbook.MainAbility',
        deviceId: deviceId,
        parameters: params
      };
      featureAbility.startAbility({
        want: wantValue
      }).then((data) = > {
        console.info('[game] featureAbility.startAbility finished, localDeviceId=' + localDeviceId + '----deviceId:' + deviceId);
        // 拉起遠端后,連接遠端service
        connectRemoteService(deviceId)
      });
    }
    
  6. 連接手柄端Service。
    拉起手柄端FA后,連接手柄端Service,代碼如下:
    async function connectRemoteService(deviceId) {
      // 連接成功的回調
      async function onConnectCallback(element, remote) {
        mRemote = remote;
      }
    ...
      if (remoteDeviceModel.deviceList.length === 0) {
        return;
      }
      await featureAbility.connectAbility(
        {
          'deviceId': deviceId,
          'bundleName': "com.huawei.cookbook",
          'abilityName': "com.huawei.cookbook.ServiceAbility",
        },
        {
          onConnect: onConnectCallback,
          onDisconnect: onDisconnectCallback,
          onFailed: onFailedCallback,
        },
      );
    }
    
  7. 通過RPC發送數據到手柄端。
    通過RPC將游戲分數發送給手柄端,主要代碼如下:
    async function sendMessageToRemoteService(score) {
      console.log('[game]connectRemoteService sendMessageToRemoteService:')
      if (mRemote == null) {
        return;
      }
      let option = new rpc.MessageOption();
      let data = new rpc.MessageParcel();
      let reply = new rpc.MessageParcel();
      data.writeInt(score);
      await mRemote.sendRequest(1, data, reply, option);
    }
    
  8. Service發布公共事件。
    通過Service接收手柄端數據,然后使用CommonEvent模塊將數據發送給FA,主要代碼如下:
    class GameServiceAbilityStub extends rpc.RemoteObject {
    ...
        onRemoteRequest(code, data, reply, option) {
            console.log('[game]Service onRemoteRequest');
            var publishCallBack;
            if (code === 1) {
                // 讀取手柄端發送的數據
                let actionType = data.readInt();
                let angle = data.readInt();
                reply.writeInt(100);
                var params = {
                    actionType: actionType,
                    angle: angle,
                }
                var options = {
                    code: 1,
                    data: 'init data',
                    isOrdered: true,
                    bundleName: 'com.huawei.cookbook',
                    parameters: params
                }
                publishCallBack = function () {}
                // 發布公共事件
                commonEvent.publish("publish_action", options, publishCallBack);
            } 
            return true;
        }
    }
    
  9. FA訂閱公共事件。
    訂閱公共事件,接收從Service發送的公共事件數據,actionType 為操作類型(1表示發送子彈指令,2表示釋放技能指令),angle 為飛機移動的角度。接收到數據后執行手柄端發送的指令:移動玩家飛機、發射子彈和釋放技能摧毀所有敵機,主要代碼如下:
    subscribeEvent() {
    ...
      // 訂閱公共事件回調
      function SubscribeCallBack(err, data) {
        let msgData = data.data;
        let code = data.code;
    ...
        // 處理接收到的數據data
        that.actionType = data.parameters.actionType;
        that.angle = data.parameters.angle;
    
        if (that.actionType == 1) {
          that.createBullet()
        }
        if (that.actionType == 2) {
          if (that.bombNum > 0) {
            that.bombNum--
            that.destroyAllEnemy()
          }
        }
        if (that.angle != 0) {
          that.movePlaneByHandle()
        }
      }
      //創建訂閱者回調
      function CreateSubscriberCallBack(err, data) {
        subscriber = data;
        //訂閱公共事件
        commonEvent.subscribe(subscriber, SubscribeCallBack);
      }
      //創建訂閱者
      commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
    }
    

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙
    +關注

    關注

    57

    文章

    2469

    瀏覽量

    43642
  • OpenHarmony
    +關注

    關注

    26

    文章

    3804

    瀏覽量

    17849
收藏 人收藏

    評論

    相關推薦

    北京迅為RK3568開發OpenHarmony系統南向驅動開發內核HDF驅動框架架構

    北京迅為RK3568開發OpenHarmony系統南向驅動開發內核HDF驅動框架架構
    的頭像 發表于 03-11 14:13 ?885次閱讀
    北京迅為RK3568<b class='flag-5'>開發</b>板<b class='flag-5'>OpenHarmony</b>系統<b class='flag-5'>南向</b>驅動<b class='flag-5'>開發</b>內核HDF驅動框架架構

    OpenHarmony南向能力征集令

    1、適配過程中缺少哪些接口能力或者南向能力,需要OpenHarmony去補齊的?例如內核、編譯、器件適配、單板適配等; 2、對標linux,需要OpenHarmony提供哪些能力?比如V4L2
    發表于 04-09 15:32

    鴻蒙OpenHarmony南向/北向快速開發教程-迅為RK3568開發

    P2_OpenHarmony功能框架 P3_OpenHarmony技術特性 P4_OpenHarmony支持設備類型 p5_南向開發和北向
    發表于 07-23 10:44

    求教 游戲手柄

    游戲手柄發出的信號是什么啊 ???不一樣的手柄一樣的不???
    發表于 12-01 18:37

    藍牙游戲手柄

    藍牙游戲手柄是怎樣實現控制智能手機的游戲的?請大神賜教!
    發表于 03-18 15:04

    vr藍牙手柄方案 藍牙游戲手柄方案

    。DayDream手柄,小米手柄方案開發,九軸體感手柄,隨心所欲體驗各類游戲視頻,10毫秒超低延時,待機電流0.6微安。優勢:VR
    發表于 04-23 16:47

    如何通過STM32來驅動FC游戲機手柄

    相信80后小時候都玩過FC游戲機(又稱:紅白機/小霸王游戲機),那是一代經典,給童年帶來了無限樂趣。本章,介紹如何通過STM32來驅動FC游戲機手柄,將FC游戲機的
    發表于 01-05 07:57

    基于 OpenHarmony 拳擊健康游戲應用

    樣例簡介拳擊健康游戲應用是基于OpenHarmony 3.2 Beta標準系統上開發的eTS應用,本應用運行于RK3568,游戲開始會隨著音樂播放會拳擊方庫進行隨機速度下落,樣例利用N
    發表于 08-31 11:20

    藍牙吃雞游戲手柄方案分解資料

    藍牙吃雞游戲手柄方案 藍牙吃雞游戲手柄方案開發游戲手柄
    發表于 03-31 10:54 ?4393次閱讀

    OpenHarmony Dev-Board-SIG專場:南向共建案例分享

    OpenHarmony南向共建案例分享: 審核編輯:金巧
    的頭像 發表于 12-28 14:16 ?1047次閱讀
    <b class='flag-5'>OpenHarmony</b> Dev-Board-SIG專場:<b class='flag-5'>南向</b>共建案例分享

    基于2.4G RF開發的無線游戲手柄解決方案

    平時喜歡玩游戲的朋友,肯定知道鍵鼠在某些類型的游戲適配和操作方面,不如手柄。作為一個游戲愛好者,還得配上一個游戲
    的頭像 發表于 08-08 18:02 ?1661次閱讀

    【北京迅為】iTOP-RK3568OpenHarmony系統南向驅動開發GPIO基礎知識

    【北京迅為】iTOP-RK3568OpenHarmony系統南向驅動開發GPIO基礎知識
    的頭像 發表于 03-06 11:23 ?424次閱讀
    【北京迅為】iTOP-RK3568<b class='flag-5'>OpenHarmony</b>系統<b class='flag-5'>南向</b>驅動<b class='flag-5'>開發</b>GPIO基礎知識

    北京迅為iTOP-RK3568開發OpenHarmony系統南向驅動開發實操-HDF驅動配置LED

    北京迅為iTOP-RK3568開發OpenHarmony系統南向驅動開發實操-HDF驅動配置LED
    的頭像 發表于 03-14 14:41 ?394次閱讀
    北京迅為iTOP-RK3568<b class='flag-5'>開發</b>板<b class='flag-5'>OpenHarmony</b>系統<b class='flag-5'>南向</b>驅動<b class='flag-5'>開發</b>實操-HDF驅動配置LED

    【北京迅為】iTOP-RK3568開發OpenHarmony系統南向驅動開發-第4章 UART基礎知識

    【北京迅為】iTOP-RK3568開發OpenHarmony系統南向驅動開發-第4章 UART基礎知識
    的頭像 發表于 03-17 15:50 ?312次閱讀
    【北京迅為】iTOP-RK3568<b class='flag-5'>開發</b>板<b class='flag-5'>OpenHarmony</b>系統<b class='flag-5'>南向</b>驅動<b class='flag-5'>開發</b>-第4章 UART基礎知識

    【北京迅為】iTOP-RK3568開發板鴻蒙OpenHarmony系統南向驅動開發實操-HDF驅動配置UART

    【北京迅為】iTOP-RK3568開發板鴻蒙OpenHarmony系統南向驅動開發實操-HDF驅動配置UART
    的頭像 發表于 03-25 11:02 ?451次閱讀
    【北京迅為】iTOP-RK3568<b class='flag-5'>開發</b>板鴻蒙<b class='flag-5'>OpenHarmony</b>系統<b class='flag-5'>南向</b>驅動<b class='flag-5'>開發</b>實操-HDF驅動配置UART
    主站蜘蛛池模板: 天天射天天干天天插 | 天天爱添天天爱添天天爱添 | 草草影院ccyy国产日本欧美 | 精品黄色片 | 国产小视频在线观看 | 国内自拍网红在综合图区 | 欧美日韩一区二区三区毛片 | 无遮挡很爽很污很黄在线网站 | 五月综合在线 | 日韩一级在线观看 | 四虎成人欧美精品在永久在线 | 久久国产精品99精品国产987 | 狠狠干夜夜 | 四虎亚洲国产成人久久精品 | 欧美激情综合 | 伊人福利视频 | 天天草天天爽 | 一本到中文字幕高清不卡在线 | 你懂的在线视频观看 | 激情综合网五月激情 | 亚洲男人的天堂在线播放 | 精品久久久久久久免费加勒比 | 国产激烈床戏无遮挡观看 | 亚洲色图在线视频 | 五月天婷婷视频在线观看 | 天天艹在线 | 欧美午夜视频在线 | 久操视频免费观看 | 在线播放免费人成毛片乱码 | 台湾三级毛片 | 五月天激情开心网 | 天天草天天 | 网站色小妹 | 天天看天天摸色天天综合网 | 韩国免费人成在线观看网站 | 亚洲人与牲动交xxxxbbbb | 又色又爽的视频 | 久久97精品久久久久久久看片 | 最新免费jlzzjlzz在线播放 | ww欧洲ww在线视频免费观看 | sss华人在线play |