一、前言
隨着移動互聯網時代的深入發展,人們對電子產品的體驗效果要求越來越高,各種游戲體驗和效果都得到很大的提升。本文主要介紹使用手機或者平板作為游戲控制器,借助近距離通信(Nearby Service),通過藍牙和WIFI技術,實現控制大屏游戲的效果。
二、場景描述
在實際使用過程中,可以通過大屏游戲主頁提供的二維碼鏈接去下載控制器程序,游戲的所需操作都可以進行數據傳輸,本文主要演示如何將手機陀螺儀數據進行傳輸。
通過該方案,可以解決普通游戲控制器功能單一,使用成本高等問題。同時,由於無需Internet連接,不會造成額外流量消耗或者傳輸效果受到Internet網絡質量的影響。此外,允許手機控制器程序輕松地與附近的設備(大屏游戲)進行發現、連接及數據交換,靈活支持多人同時參與同一游戲。
三、整體流程
使用手機或者平板電腦作為游戲控制器,通過集成近距離通信能力,將手機或者平板電腦中的傳感器的實時數據,無線傳輸到顯示游戲的大屏設備上,實現對游戲角色的控制。
下圖中的發現端對應手機游戲控制器,廣播端對應大屏游戲。雙方對應的流程總體一致,都要經過:
廣播掃描 -> 建立連接 -> 傳輸數據 -> 斷開連接。
下圖中廣播掃描階段,進行設備發現,需要基於BLE(低功耗藍牙)雙向廣播技術。傳輸數據階段,設備之間的高速傳輸,直接基於傳統的P2P協議實現。

四、集成關鍵步驟說明和代碼
您需要按照流程來完成應用的開發工作,完整的開發流程可以參考鏈接。開發准備完成后,就可以進行編碼了,關鍵步驟及代碼如下:
步驟一、開始廣播
public void doStartBroadcast(View view) {
Context context = getApplicationContext();
mDiscoveryEngine = Nearby.getDiscoveryEngine(context);
BroadcastOption.Builder advBuilder = new BroadcastOption.Builder();
advBuilder.setPolicy(Policy.POLICY_STAR);
mDiscoveryEngine.startBroadcasting(myNameStr, myServiceId, mConnCb, advBuilder.build());
}
步驟二、開始掃描
public void doStartScan(View view) {
ScanOption.Builder discBuilder = new ScanOption.Builder();
discBuilder.setPolicy(Policy.POLICY_STAR);
mDiscoveryEngine.startScan(myServiceId, mDiscCb, discBuilder.build());
步驟三、請求連接
private void connect(View view) {
mDiscoveryEngine.requestConnect(myNameStr, mEndpointId, mConnCb)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(SensorActivity.this,"connect Success",Toast.LENGTH_SHORT).show();
Log.d(TAG, "connect Success:");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Toast.makeText(SensorActivity.this,"connect Failure",Toast.LENGTH_SHORT).show();
Log.d(TAG, "connect Failure");
}
步驟四、發送數據
控制器:發送陀螺儀獲取的實時數據
private void sendData(Data bytesData){ Nearby.getTransferEngine(getApplicationContext()).sendData(mEndpointId, bytesData);}
游戲大屏:接收數據
private DataCallback mDataCb =
new DataCallback() {
@Override
public void onReceived(String string, Data data) {
Log.d(TAG, "onReceived, Data.Type = " + data.getType());
Log.d(TAG, "onReceived, string ======== " + string);
switch (data.getType()) {
case Data.Type.BYTES:
String str = new String(data.asBytes(), UTF_8);
receiveMessage(data);
break;
default:
Log.i(TAG, "the other Unknown data type, please check the uploaded file.");
return;
}
}
@Override
public void onTransferUpdate(String string, TransferStateUpdate update) {
Log.d(TAG, "onTransferUpdate.Status=======" + update.getStatus());
return;
}
}
};
private void receiveMessage(Data data) {
msgStr = new String(data.asBytes(), UTF_8);
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
String dateStr = dateFormat.format(new Date());
tvData.append("\n" + dateStr + msgStr);
}
步驟五、斷開連接
private void disconnect(){
mDiscoveryEngine.disconnect(mEndpointId);
}
五、效果展示
由於硬件條件限制,使用兩台手機進行效果測試,一台手機用作控制器發送手機陀螺儀的實時數據,另一台設備作為游戲大屏進行數據的接收,在接收數據后,可以根據數據計算得出控制器的姿態等數據,實現對游戲的控制功能。
在兩台設備距離三米左右時,發送和接收數據的對比如下:


在設備間距離差距不大時(例如相距3米或4米),數據傳輸的時延變化不是很大,基本都在1s以內,數據傳輸依舊具有實時性;即使兩台手機都處在移動中,也能夠為用戶提供良好的使用體驗。
注意,當前大部分手機藍牙在兩台設備間無大的障礙物的情況下,距離7米遠時也能保證很好的傳輸質量,超過8米將會出現斷點,超過10米會斷開連接。
六、注意事項
1、此示例需要填寫接收雙方的設備名稱,進行連接。可以根據您的需要,掃描過程中,您可以向用戶展示發現的設備列表,並允許他們選擇連接哪些設備。
2、此示例顯示了一種掃描和連接方式(1-N或者星型連接拓撲的點到點策略)。根據您的需要,您可以使用其他兩種連接方式:M-N或者網狀連接拓撲的點到點連接策略,和1-1連接拓撲的點到點連接策略。三種策略適用的場景,可以參考該鏈接。
3、此示例傳輸的數據格式是字節序列(BYTES),該類型數據的長度大小不能超過32KB。可以根據您的需要,選擇其他另外兩種數據類型:文件(FILE)和流(STREAM)。
4、此示例手機控制器應用發送的數據是手機陀螺儀數據,未進行任何處理。可以根據您的需要,計算得出手機姿態等數據,實現對游戲角色的控制。
5、此示例中,接收雙方接收數據會存在時延,該時延僅供參考,不作為近距離通信的性能的標准。
原文鏈接:https://developer.huawei.com/consumer/cn/forum/topic/0204428876579660015?fid=18
原作者:胡椒
