sdk.ts 11 KB

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