sdk.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. declare global {
  2. interface Window {
  3. SHOES_SDK: any;
  4. }
  5. }
  6. const _delay = 1000 / 60.0; // 16 ms
  7. const LABEL = ["right pos x", "right pos y", "right pos z", "right att x", "right att y", "right att z", "right acc x", "right acc y", "right acc z", "right front mag", "right back mag ", "s zupt",
  8. "left pos x", "left pos y", "left pos z", "left att x", "left att y", "left att z", "left acc x", "left acc y", "left acc z", "left front mag", "left back mag", "h zupt",
  9. "down", "jump", "rssi", "timestamp", "right step", "left step", "rssi mobile"];
  10. enum CMD {
  11. NONE_INTERATION = 2000,
  12. FRONT_LEFT,//左上键
  13. FRONT_RIGHT,//右上键
  14. BACK_LEFT,//左下键
  15. BACK_RIGHT,//右下键
  16. ENTER_KEY,//确认键
  17. CANCLE_KEY,//取消键
  18. }
  19. enum MOTION {
  20. MOTION_STOP = 0,
  21. MOTION_RUN, // 跑
  22. MOTION_JUMP, // 跳
  23. MOTION_DOWN, // 蹲
  24. MOTION_LEFT, // 滑左
  25. MOTION_RIGHT, // 滑右
  26. MOTION_FRONT, // 滑前
  27. MOTION_BACK, // 滑后
  28. MOTION_LEFT_UP, // 点击-左上
  29. MOTION_LEFT_DOWN, // 点击-左下
  30. MOTION_RIGHT_UP, // 点击-右上
  31. MOTION_RIGHT_DOWN, // 点击-右下
  32. MOTION_STEP, // 点击-原地踩
  33. MOTION_JUMP_OC, // 开合跳
  34. MOTION_JUMP_VERTICAL, // 垂直跳
  35. MOTION_ROCK, //石头
  36. MOTION_SCISSORS, //剪刀
  37. MOTION_PAPER, //布
  38. MOTION_STRETCH_LEFT, //左伸腿
  39. MOTION_LIFT_LEFT, //左抬腿
  40. MOTION_STRETCH_RIGHT, //右伸腿
  41. MOTION_LIFT_RIGHT, //右抬腿
  42. MOTION_STRETCH_FRONT_LEFT, //左前踢
  43. MOTION_STRETCH_FRONT_RIGHT, //右前踢
  44. MOTION_DOWN_FRONT, //踮脚蹲
  45. MOTION_LEFT_ON_FLOOR, //左脚踩
  46. MOTION_RIGHT_ON_FLOOR, //左脚踩
  47. MOTION_BOTH_ON_FLOOR_CLOSE, //合脚踩
  48. MOTION_BOTH_ON_FLOOR_OPEN, //开脚踩
  49. NUMBERS_OF_MOTION,
  50. }
  51. enum STEP {
  52. FREQ= 1000,
  53. }
  54. class Subscriber {
  55. _target: Object;
  56. _fn: Function;
  57. constructor(target: Object, fn: Function) {
  58. this._target = target;
  59. this._fn = fn;
  60. }
  61. }
  62. class _SDK {
  63. _ver: number = 1;
  64. _events: { [key: string]: Subscriber[] } = {};
  65. _cmd: number;
  66. _cmdTime: number;
  67. _motion: Array<number> = [0, 0, 0, 0];
  68. _motionTime: Array<number> = [0, 0, 0, 0];
  69. _stepFreq: number;
  70. _stepCount: number;
  71. _velocity: number;
  72. _responseCallMap = {string:Function};
  73. _gameDataCallback:Function;
  74. _inited: boolean = false;
  75. constructor() {
  76. }
  77. callback(name:string, args:Object){
  78. console.log("callback " + name + " " + args);
  79. const func = this._responseCallMap[name];
  80. if(func)func.call(func, args)
  81. }
  82. /**
  83. * 是否在单位时间里动作
  84. * @param index
  85. * @param delay
  86. */
  87. isMotion(index: number, delay: number) {
  88. let ts = new Date();
  89. let result = (this._motion[index] > 0) && (ts.getTime() - this._motionTime[index]) <= delay;
  90. if(result){
  91. this._motion[index] = 0;
  92. }
  93. return result;
  94. }
  95. /**
  96. * 左脚
  97. * @param delay 延时时间,默认 1帧 = 16ms
  98. */
  99. isLeftFootDown(delay: number = _delay) {
  100. return this.isMotion(0, delay);
  101. }
  102. /**
  103. * 右脚
  104. * @param delay
  105. */
  106. isRightFootDown(delay: number = _delay) {
  107. return this.isMotion(1, delay);
  108. }
  109. /**
  110. * 获取操作指定
  111. */
  112. getCmd(): number {
  113. let result = this._cmd;
  114. if(result > 0){
  115. this._cmd = 0;
  116. }
  117. return result;
  118. }
  119. cmd(id: number, v0: number) {
  120. this._cmd = v0 + CMD.NONE_INTERATION;
  121. let ts = new Date().getTime();
  122. if(ts - this._cmdTime < 500) return;
  123. this._cmdTime = ts;
  124. console.log("cmd set " + v0 + " " + (this._cmd)) ;
  125. this.emit((this._cmd).toString(), ts);
  126. }
  127. /**
  128. * 获取运动数据 [0,0,0,0]
  129. */
  130. getMotion(): Array<number> {
  131. return this._motion;
  132. }
  133. motion(type: number, id: number, v0: number, v1: number, v2: number, v3: number) {
  134. this._motion[0] = v0;
  135. this._motion[1] = v1;
  136. this._motion[2] = v2;
  137. this._motion[3] = v3;
  138. console.log("motion set " + this._motion);
  139. let now = new Date();
  140. let ts = now.getTime();
  141. let arr = this._motion;
  142. for (let i = 0; i < arr.length; i++){
  143. if(arr[i] > 0){
  144. if(ts - this._motionTime[i] < 10) continue;
  145. this._motionTime[i] = ts;
  146. let motionIndex = arr[i];
  147. let motion = motionIndex.toString();
  148. this.emit(motion, ts);
  149. console.log("motion set " + motionIndex + " -> " + motion + " " + MOTION[motionIndex]);
  150. }
  151. }
  152. // if (v0 == 1) {
  153. // this._motionTime[0] = ts;
  154. // this.emit(MOTION.LEFT_DOWN.toString(), ts);
  155. // console.log("motion set left");
  156. // }
  157. // if (v1 == 1) {
  158. // this._motionTime[1] = ts;
  159. // this.emit(MOTION.RIGHT_DOWN.toString(), ts);
  160. // console.log("motion set right");
  161. // }
  162. // if (v2 > 0) {
  163. // this._motionTime[2] = ts;
  164. // let motion = MOTION[v2];
  165. // this.emit(motion, ts);
  166. // console.log("motion set " + motion);
  167. // }
  168. // if (v3 > 0) {
  169. // this._motionTime[3] = ts;
  170. // let motion = MOTION[v3];
  171. // this.emit(motion, ts);
  172. // console.log("motion set " + motion);
  173. // }
  174. }
  175. /**
  176. * 当前步频
  177. */
  178. getStepFreq(): number {
  179. return this._stepFreq;
  180. }
  181. /**
  182. * 开局后的步数
  183. */
  184. getStepCount(): number {
  185. return this._stepCount;
  186. }
  187. getVelocity(): number {
  188. return this._velocity;
  189. }
  190. stepFreq(freq: number) {
  191. this._stepFreq = freq;
  192. console.log("step freq " + freq);
  193. this.emit(STEP.FREQ.toString(), freq);
  194. }
  195. step(freq: number, count: number) {
  196. this.stepFreq(freq);
  197. this._stepCount = count;
  198. console.log("step count " + count);
  199. }
  200. stepData(freq: number, count: number, velocity: number) {
  201. this.stepFreq(freq);
  202. this._stepCount = count;
  203. this._velocity = velocity;
  204. }
  205. /**
  206. * 发布/ 触发
  207. * @param subscriber
  208. * @param args
  209. */
  210. emit(subscriber: string, ...args: any) {
  211. let callbackList = this._events[subscriber] || [];
  212. if(callbackList.length > 0){
  213. console.log("motion emit " + subscriber + ", " + callbackList.length);
  214. callbackList.forEach(item => item._fn.apply(item._target || item._fn, args));
  215. }
  216. return this;
  217. }
  218. /**
  219. * 订阅/监听
  220. * @param subscriber
  221. * @param callback
  222. * @param target
  223. */
  224. on(subscriber: string, callback?: Function, target?: Object) {
  225. if(!this._inited){
  226. this._inited = true;
  227. this.onSdkLoaded();
  228. }
  229. let callbackList = this._events[subscriber] || [];
  230. callback && callbackList.push(new Subscriber(target||this,callback));
  231. console.log("motion set on " + subscriber + ", " + callbackList.length);
  232. this._events[subscriber] = callbackList;
  233. return this;
  234. }
  235. /**
  236. * 只订阅一次/监听一次:
  237. * 思路:
  238. * 1. 重新包装一个回调函数(有名的),进行注册订阅/监听,
  239. * 2. 包装函数里面直接调用 once方法的第二个参数回调函数,然后调用off方法 卸载该包装函数
  240. * @param subscriber
  241. * @param callback
  242. * @param target
  243. */
  244. once(subscriber: string, callback?: Function, target?: Object) {
  245. let decor = (...args: any[]) => {
  246. callback && callback.apply(target || this, args);
  247. this.off(subscriber, decor);
  248. };
  249. this.on(subscriber, decor);
  250. return this;
  251. }
  252. /**
  253. * 卸载/取消 某一个回调监听(不是取消eventName的所有回调监听),主要配合once一起,实例单独调用,无意义
  254. * @param subscriber
  255. * @param callback
  256. */
  257. off(subscriber: string, callback: Function) {
  258. let callbackList = this._events[subscriber] || [];
  259. this._events[subscriber] = callbackList.filter(item => item._fn !== callback);
  260. return this;
  261. }
  262. /**
  263. * 卸载/取消 指定eventName 的所有订阅/监听
  264. * @param subscriber
  265. * @param callback
  266. */
  267. remove(subscriber: string, callback?: Function) {
  268. this._events[subscriber] = [];
  269. callback && callback();
  270. return this;
  271. }
  272. onSdkLoaded(){
  273. this._callsdk("onLoad", {ver: this._ver});
  274. }
  275. /**
  276. * 退出/后退事件
  277. */
  278. onBackPressed(foot:boolean = false){
  279. this._callsdk("onBackPressed", {foot: foot});
  280. }
  281. /**
  282. * 游戏开局调用事件
  283. */
  284. onGameStart(){
  285. this._callsdk("onGameStart", {});
  286. }
  287. /**
  288. * 游戏局结束调用事件
  289. * @param level 当局游戏级别
  290. * @param score 当局游戏评分
  291. * @param record 当局游戏战绩 0: 负, 1: 胜
  292. * @param mode 当局游戏模式 0: 单人, 1: 匹配, 2: 好友对战
  293. * @param opponentId 当局游戏对手ID
  294. * @param callback data
  295. * data = {
  296. * 'consume':$consume,
  297. * 'equivalent':$equivalent,
  298. * 'unit':'步'
  299. * }
  300. */
  301. onGameEnd(level: number = 0, score: number = 0.0, record: number = 0, mode: number = 0, opponentId: number = 0, callback?: Function) {
  302. if (callback) {
  303. let method = "onGameEnd_callback";
  304. this._responseCallMap[method] = callback;
  305. }
  306. this._callsdk("onGameEnd", {level: level, score:score, record:record,mode:mode, opponentId:opponentId});
  307. }
  308. /**
  309. * 获取当前用户信息
  310. * @param callback({"id": 1, "nickname":"nickname", "gender":1, "avatar":""})
  311. *
  312. * user用户信息结构
  313. * {
  314. * "id": 1,
  315. * "name":"nickname",
  316. * "gender":1,
  317. * "avatar":""
  318. * }
  319. */
  320. getUserInfo(callback:Function){
  321. let method = "getUserInfo_callback";
  322. this._responseCallMap[method] = callback;
  323. this._callsdk(method, {callback: method});
  324. }
  325. /**
  326. *
  327. * @param type, 0:世界,1:好友
  328. * @param callback(args)
  329. * args[0] = type
  330. * args[1] = {"list":[{"user":{"id": 1, "nickname":"nickname", "gender":1, "avatar":""}, "score":100, "rank":1}]}
  331. */
  332. getRank(type:number, callback:Function){
  333. let method = "getRank_callback";
  334. this._responseCallMap[method] = callback;
  335. this._callsdk(method, {callback: method, type: type});
  336. }
  337. /**
  338. * 震动反馈
  339. * @param duration 时长 ms [100 .. 1000]
  340. * @param leftOrRight [0:双,1:左,2:右]
  341. */
  342. vibrate(duration: number, leftOrRight:number = 0) {
  343. let method = "vibrate";
  344. this._callsdk(method, {duration:duration, leftOrRight: leftOrRight});
  345. }
  346. /**
  347. * 打开鞋子位移、加速度、姿态等数据传输
  348. * @param open
  349. * @param gameDataCallback
  350. */
  351. openGameData(open:boolean, gameDataCallback:Function){
  352. this._gameDataCallback = gameDataCallback;
  353. this._callsdk("openGameData", {open:open});
  354. }
  355. gameData(args:Object){
  356. if(this._gameDataCallback)this._gameDataCallback.call(this._gameDataCallback, args);
  357. }
  358. _callsdk(method:string, args:Object){
  359. console.log("sdk call " + method);
  360. if(window["SDKBridge"])window["SDKBridge"].postMessage(JSON.stringify({method:method, args:args}))
  361. }
  362. }
  363. const SDK = new _SDK();
  364. window.SHOES_SDK = SDK;
  365. export {SDK, MOTION, CMD}