这个是我很早之前就想写的,但是最近一直比较忙。知乎上有很多小伙伴留言或者私信问过我这个怎么做,但是一直没时间写,再加上个人比较懒,所以就拖更了。这次正好赶上五一假期,大概放三四个月吧(其实是暑假),就来写一下怎么搞。下面开始!
原理
目前这个只支持安卓设备,因为要用到ADB。主要的原理就是树莓派通过ADB向手机发送控制信号,手机端APP收到信号后就操作手机做出相应动作。比如说你按下W,对应的操作就是向上滑动,那么树莓派就会发送这个信号给手机,手机便会根据收到的数据做出滑动的动作。
方法
下载源码
git clone https://github.com/haoyeel/pubg-phone.git
cd pubg-phone
这是我同学的GitHub仓库,目前在华为南研所搬砖,单身狗一个,有想法的直接在下面留言,联系方式啥的私信要(限女生)!
树莓派端
#coding: utf-8
from websocket import create_connection
from evdev import InputDevice
from select import select
from threading import Thread
import queue
import json
import time
import sys
import os
#code of json, only @ACTION_DOWN,@ACTION_MOVE,@ACTION_UP related
#position @X,@y may need change according to your phone
#{"code": ,"action": ,"X": ,"Y": }
#may need change according to your system
keyboard_dev_position = '/dev/input/event1'
mouse_dev_position = '/dev/input/event4'
input_event_codes = {'type_keyboard_key':1, 'type_mouse_move':2, 'type_mouse_key':1}
#code, 4 contacts need most
g_motionCode = {'CODE_WASD':0, 'CODE_MOUSE':1, 'CODE_CLICK':2, 'CODE_VIEW':3, 'CODE_CLICK_2':4, 'CODE_LOCAL_EXIT':10}
#action, same int number with Android MotionEvent
g_motionEvent = {'ACTION_DOWN':0, 'ACTION_UP':1, 'ACTION_MOVE':2}
g_keyboard_mouse_status = {'wasd':0, 'mouse_key':0, 'mouse_move':0}
#mouse area limit
g_mouse_area = {'center_x':1900, 'center_y':490, 'top_y':90, 'bottom_y':890, 'left_x':1500, 'right_x':2300}
#mouse absolute position history
g_mouse_position_abs_his = {'hor':-1, 'ver':-1}
g_mouse_touchscreen_abs_his = {'x':g_mouse_area['center_x'], 'y':g_mouse_area['center_y']}
#game interface status
g_game_interface_status = {'gun_num':1, 'car':0, 'swim':0 }
def keyboardAction(tx_queue, k_event):
keyboard_mouse_status_old = {'wasd':g_keyboard_mouse_status['wasd']}
#first, update the @g_keyboard_mouse_status
if (k_event.value == 1): #key pressed
if k_event.code == 17: #W
if (g_keyboard_mouse_status['wasd'] == 0 or g_keyboard_mouse_status['wasd'] == 0x02 or g_keyboard_mouse_status['wasd'] == 0x08):
g_keyboard_mouse_status['wasd'] |= 0x01;
elif k_event.code == 30: #A
#if(g_keyboard_mouse_status['wasd'] == 0 or g_keyboard_mouse_status['wasd'] == 0x01 or g_keyboard_mouse_status['wasd'] == 0x04):
g_keyboard_mouse_status['wasd'] &= 0xF5;
g_keyboard_mouse_status['wasd'] |= 0x02;
elif k_event.code == 31: #S
if(g_keyboard_mouse_status['wasd'] == 0 or g_keyboard_mouse_status['wasd'] == 0x02 or g_keyboard_mouse_status['wasd'] == 0x08):
g_keyboard_mouse_status['wasd'] |= 0x04;
elif k_event.code == 32: #D
#if(g_keyboard_mouse_status['wasd'] == 0 or g_keyboard_mouse_status['wasd'] == 0x01 or g_keyboard_mouse_status['wasd'] == 0x04):
g_keyboard_mouse_status['wasd'] &= 0xF5;
g_keyboard_mouse_status['wasd'] |= 0x08;
elif k_event.code == 57: #space for jump
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 2256, 755 ])
elif k_event.code == 46: #C for
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 2038, 1003 ])
elif k_event.code == 44: #Z
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 2226, 971 ])
elif k_event.code == 16: #Q
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 357, 393 ])
elif k_event.code == 18: #E
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 515, 393 ])
elif k_event.code == 2: #1
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1085, 977 ])
elif k_event.code == 3: #2
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1340, 977 ])
elif k_event.code == 4: #3
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1574, 1012 ])
elif k_event.code == 5: #4
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 850, 1012 ])
elif k_event.code == 19: #R
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1883, 1015 ])
elif k_event.code == 33: #F
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1714, 457 ])
elif k_event.code == 15: #Tab for map
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 2295, 51 ])
elif k_event.code == 41: #` for bag
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 230, 980 ])
elif k_event.code == 45: #X for pick up close
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1798, 276 ])
tx_queue.put([ g_motionCode['CODE_CLICK_2'], g_motionEvent['ACTION_DOWN'], 1709, 276 ])
elif k_event.code == 42: #Shift
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1970, 838 ])
elif k_event.code == 48: #B
if g_game_interface_status['gun_num'] == 1:
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1085, 909 ])
elif g_game_interface_status['gun_num'] == 2:
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 1340, 909 ])
else:
print("Undefined key pressed.");
elif (k_event.value == 0): #key relessed
if k_event.code == 17: #W
g_keyboard_mouse_status['wasd'] &= 0xFE;
elif k_event.code == 30: #A
g_keyboard_mouse_status['wasd'] &= 0xFD;
elif k_event.code == 31: #S
g_keyboard_mouse_status['wasd'] &= 0xFB;
elif k_event.code == 32: #D
g_keyboard_mouse_status['wasd'] &= 0xF7;
elif k_event.code == 57: #space
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 2256, 755 ])
elif k_event.code == 46: #C for
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 2038, 1003 ])
elif k_event.code == 44: #Z
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 2226, 971 ])
elif k_event.code == 16: #Q
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 357, 393 ])
elif k_event.code == 18: #E
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 515, 393 ])
elif k_event.code == 2: #1
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1085, 977 ])
g_game_interface_status['gun_num'] = 1
elif k_event.code == 3: #2
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1340, 977 ])
g_game_interface_status['gun_num'] = 2
elif k_event.code == 4: #3
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1574, 1012 ])
elif k_event.code == 5: #4
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 850, 1012 ])
elif k_event.code == 19: #R
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1883, 1015 ])
elif k_event.code == 33: #F
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1714, 457])
elif k_event.code == 15: #Tab for map
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 2295, 51 ])
elif k_event.code == 41: #` for bag
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 230, 980 ])
elif k_event.code == 45: #X for pick up close
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1798, 276 ])
tx_queue.put([ g_motionCode['CODE_CLICK_2'], g_motionEvent['ACTION_UP'], 1709, 276 ])
elif k_event.code == 42: #Shift
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1970, 838 ])
elif k_event.code == 48: #B
if g_game_interface_status['gun_num'] == 1:
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1085, 909 ])
elif g_game_interface_status['gun_num'] == 2:
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 1340, 909 ])
else:
print("Undefined key relessed.")
else:
return
#then, determine the action
if g_keyboard_mouse_status['wasd'] != keyboard_mouse_status_old['wasd']: #new key event occurred
if (keyboard_mouse_status_old['wasd'] == 0 and g_keyboard_mouse_status['wasd'] != 0): #key pressed, need @ACTION_DOWN first, then we can @ACTION_MOVE
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_DOWN'], 450, 809 ])
if g_keyboard_mouse_status['wasd'] == 0x01: #W
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 450, 509 ])
elif g_keyboard_mouse_status['wasd'] == 0x03: #WA
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 200, 509 ])
elif g_keyboard_mouse_status['wasd'] == 0x02: #A
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 200, 809 ])
elif g_keyboard_mouse_status['wasd'] == 0x06: #AS
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 200, 1059 ])
elif g_keyboard_mouse_status['wasd'] == 0x04: #S
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 450, 1059 ])
elif g_keyboard_mouse_status['wasd'] == 0x0C: #SD
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 700, 1059 ])
elif g_keyboard_mouse_status['wasd'] == 0x08: #D
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 700, 809 ])
elif g_keyboard_mouse_status['wasd'] == 0x09: #DW
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_MOVE'], 700, 509 ])
elif g_keyboard_mouse_status['wasd'] == 0x00: #WASD UP
if keyboard_mouse_status_old['wasd'] != 0:
tx_queue.put([ g_motionCode['CODE_WASD'], g_motionEvent['ACTION_UP'], 450, 809 ])
def mouseActionMove(tx_queue, m_event):
keyboard_mouse_status_old = {'mouse_key':g_keyboard_mouse_status['mouse_key']}
hor_relative = 0
ver_relative = 0
#if "/dev/input/event2" data format is absolute, start here
'''if g_mouse_position_abs_his['hor'] == -1 or g_mouse_position_abs_his['ver'] == -1:
if m_event.code == 0:
g_mouse_position_abs_his['hor'] = int(m_event.value / 30)
if m_event.code == 1:
g_mouse_position_abs_his['ver'] = int(m_event.value /30)
return
if m_event.code == 0: #mouse move horizontal
hor_relative = int(m_event.value / 30) - g_mouse_position_abs_his['hor']
g_mouse_position_abs_his['hor'] += hor_relative
elif m_event.code == 1: #mouse move vertical
ver_relative = int(m_event.value / 30) - g_mouse_position_abs_his['ver']
g_mouse_position_abs_his['ver'] += ver_relative'''
#if "/dev/input/event2" data format is relative, start here
if m_event.code == 0: #mouse move horizontal
hor_relative = int(m_event.value)
elif m_event.code == 1: #mouse move vertical
ver_relative = int(m_event.value)
mouse_touchscreen_abs_x = g_mouse_touchscreen_abs_his['x'] + hor_relative
mouse_touchscreen_abs_y = g_mouse_touchscreen_abs_his['y'] + ver_relative
#make sure pos in limit area
if( mouse_touchscreen_abs_x < g_mouse_area['left_x'] or mouse_touchscreen_abs_x > g_mouse_area['right_x'] or mouse_touchscreen_abs_y < g_mouse_area['top_y'] or mouse_touchscreen_abs_y > g_mouse_area['bottom_y']):
print('area limit')
tx_queue.put([ g_motionCode['CODE_MOUSE'], g_motionEvent['ACTION_UP'], g_mouse_touchscreen_abs_his['x'], g_mouse_touchscreen_abs_his['y'] ])
g_mouse_touchscreen_abs_his['x'] = g_mouse_area['center_x']
g_mouse_touchscreen_abs_his['y'] = g_mouse_area['center_y']
mouse_touchscreen_abs_x = g_mouse_touchscreen_abs_his['x'] + hor_relative
mouse_touchscreen_abs_y = g_mouse_touchscreen_abs_his['y'] + ver_relative
g_keyboard_mouse_status['mouse_move'] = 0
if g_keyboard_mouse_status['mouse_move'] == 0: #mouse move not begain
g_keyboard_mouse_status['mouse_move'] = 1
tx_queue.put([ g_motionCode['CODE_MOUSE'], g_motionEvent['ACTION_DOWN'], g_mouse_area['center_x'], g_mouse_area['center_y'] ])
tx_queue.put([ g_motionCode['CODE_MOUSE'], g_motionEvent['ACTION_MOVE'], mouse_touchscreen_abs_x, mouse_touchscreen_abs_y ])
g_mouse_touchscreen_abs_his['x'] = mouse_touchscreen_abs_x
g_mouse_touchscreen_abs_his['y'] = mouse_touchscreen_abs_y
def mouseActionKey(tx_queue, m_event):
if m_event.code == 272:
if m_event.value == 1:
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_DOWN'], 215, 555 ])
elif m_event.value == 0:
tx_queue.put([ g_motionCode['CODE_CLICK'], g_motionEvent['ACTION_UP'], 555, 555 ])
if m_event.code == 273:
if m_event.value == 1:
tx_queue.put([ g_motionCode['CODE_CLICK_2'], g_motionEvent['ACTION_DOWN'], 2265, 563 ])
elif m_event.value == 0:
tx_queue.put([ g_motionCode['CODE_CLICK_2'], g_motionEvent['ACTION_UP'], 2265, 563 ])
elif m_event.code == 274: #roll for solve the false issue
tx_queue.put([ g_motionCode['CODE_MOUSE'], g_motionEvent['ACTION_UP'], g_mouse_touchscreen_abs_his['x'], g_mouse_touchscreen_abs_his['y'] ])
g_mouse_position_abs_his['hor'] = -1
g_mouse_position_abs_his['ver'] = -1
g_mouse_touchscreen_abs_his['x'] = g_mouse_area['center_x']
g_mouse_touchscreen_abs_his['y'] = g_mouse_area['center_y']
g_keyboard_mouse_status['mouse_move'] = 0
def threadKeyboard(tx_queue):
keyboard_dev = InputDevice(keyboard_dev_position)
while True:
select([keyboard_dev], [], [])
for keyboard_event in keyboard_dev.read():
#print("<K>type%s, code:%s, value:%s" % (keyboard_event.type, keyboard_event.code, keyboard_event.value))
if keyboard_event.type == input_event_codes['type_keyboard_key']:
keyboardAction(tx_queue, keyboard_event)
def threadMouse(tx_queue):
mouse_dev = InputDevice(mouse_dev_position)
while True:
select([mouse_dev], [], [])
for mouse_event in mouse_dev.read():
#print("<M>type%s, code:%s, value:%s" % (mouse_event.type, mouse_event.code, mouse_event.value))
if mouse_event.type == input_event_codes['type_mouse_move']:
mouseActionMove(tx_queue, mouse_event)
elif mouse_event.type == input_event_codes['type_mouse_key']:
mouseActionKey(tx_queue, mouse_event)
if __name__ == "__main__":
#res = os.system('sh ./start-server.sh &')
#if res != 0:
# print("Start app failed!")
# sys.exit()
#time.sleep(3)
tx_queue = queue.Queue(maxsize = 10)
thread_keyboard = Thread(target = threadKeyboard, args = (tx_queue, ))
thread_mouse = Thread(target = threadMouse, args = (tx_queue, ))
thread_keyboard.start()
thread_mouse.start()
ws = create_connection("ws://127.0.0.1:10000/input")
while True:
tx_data = tx_queue.get()
tx_data_json = json.dumps({'code':tx_data[0], 'action':tx_data[1], 'X':tx_data[2], 'Y':tx_data[3]})
ws.send(tx_data_json)
print("FUCKED.")
ws.close()
这个是树莓派端的代码,在python文件夹下,主要涉及两个方面:一是网络通信,里面我们可以看到使用了websocket,这部分很简单,就是发送数据到本机的10000号端口;二是接收键盘和鼠标的动作,这部分根据手机不同需要做一定调整,具体请看14-18行的注释。第二部分需要修改是因为不同的手机屏幕尺寸不一样,导致按键坐标不一样,这部分可以通过设置→开发者选项→指针位置确定每个按键的坐标。
其中,按键被分为按下以及滑动两种,WASD作为方向键,属于滑动组,而其余按键如偏头属于按下组。鼠标的动作同样分为按下和滑动,点击属于按下动作,指针的移动属于滑动。keyboardAction函数处理键盘的动作,mouseActionKey和mouseActionMove处理鼠标的动作。在主函数中分别通过两个线程处理键盘和鼠标的动作。
上图所示的代码根据手机屏幕大小需要修改(事实上代码里的数字基本上都要改动),红框处设置的是没有按下WASD时的方向转盘中心点的位置,这个地方必改。
手机端
手机端通过接收树莓派发送的JSON数组来决定如何做出动作。这部分代码不需要作出改动,因此不做过多的描述。
如何运行
为了能够正确的运行程序,首先需要安装adb:
sudo apt-get upgrade
sudo apt-get update
sudo apt-get install adb
在开始使用前需要通过ADB先连接手机,具体方法可以百度Linux下adb的使用方法,照着操作就行。完成后先启动手机端APP,然后在树莓派上执行以下命令:
cd python
sudo bash start-server.sh
至此,整个过程已经完成了,但是距离正常使用还有一些调试工作需要完成,具体就是按键的坐标需要对应,建议打开设置→开发者选项→指针位置以捕获树莓派的动作以确定目前的实际运动轨迹,并根据屏幕上按键的位置改动树莓派端代码中的数字。
有问题可以留言讨论!
留言
限女生?,女生怎么会看这种东西
难说
难说真的,难说。哈哈哈,这个是我的邮箱
可以要您的联系方式嘛
可以加群664605896