o0Project.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. import o0 from "./o0.js"
  2. module.exports = {
  3. Filter: class {
  4. constructor() {
  5. this.stableAcceleration = null;
  6. this.maxrecordCount = 999999;
  7. this.frame = [];
  8. this.frameHit = []; //打击后的n帧
  9. for (var i = 0; i < 200; ++i) {
  10. var o = new Object();
  11. o.time = new Date().getTime();
  12. o.timeGap = 20;
  13. o.acc = new o0.Vector2(0, 0);
  14. o.gyr = new o0.Vector2(0, 0);
  15. o.accFixed = 0;
  16. o.accSlope = 0;
  17. o.pos = new o0.Vector2(0, 0);
  18. o.predict = new o0.Vector2(0, 0);
  19. o.shake = 0;
  20. o.shakeFixed = 1;
  21. o.shakeSlope = 0;
  22. o.reliable = 1;
  23. o.speed = new o0.Vector2(0, 0);
  24. o.hit = 0;
  25. this.frame.push(o);
  26. //this.frameHit.push(o);
  27. }
  28. this.frameSwing = this.frame[0];
  29. //this.frame = 0;
  30. this.force = new o0.Vector2(0, 0);
  31. this.forceChanged = 0;
  32. this.momentum = 999999;
  33. this.momentunTime = 0;
  34. this.momentunSeek = 0.1;
  35. this.momentunPunch = false;
  36. this.punchCount = 0;
  37. this.leftRight = false;
  38. this.forceRecord = [];
  39. for (var i = 0; i < 1; ++i) {
  40. this.forceRecord.push(new o0.Vector2(0, 0));
  41. } /** */
  42. this.angle = 0;
  43. this.quitHitCount = 0;
  44. }
  45. Update(vector3, timeGap, gyr, callback) {
  46. if (this.stableAcceleration == null) {
  47. this.stableAcceleration = vector3;
  48. this.recordCount = 1;
  49. } else {
  50. this.recordCount += 1;
  51. if (this.recordCount > this.maxrecordCount) {
  52. this.recordCount = this.maxrecordCount;
  53. }
  54. let recordCount = this.recordCount;
  55. this.stableAcceleration = this.stableAcceleration.multiply((recordCount - 1) / recordCount).plus(vector3.multiply(
  56. 1 / recordCount));
  57. }
  58. //++this.frame;
  59. var newForce = vector3.minus(this.stableAcceleration);
  60. var newFrame = new Object();
  61. newFrame.time = new Date().getTime();
  62. newFrame.timeGap = timeGap;
  63. newFrame.acc = new o0.Vector2(newForce.x, newForce.z);
  64. newFrame.gyr = new o0.Vector2(gyr.z, -gyr.x);
  65. let lastFrame = this.frame[this.frame.length - 1];
  66. let last2Frame = this.frame[this.frame.length - 2];
  67. let last3Frame = this.frame[this.frame.length - 3];
  68. let last4Frame = this.frame[this.frame.length - 4];
  69. let last5Frame = this.frame[this.frame.length - 5];
  70. //////////////////////////////////////////////////////////////////////
  71. newFrame.accFixed = newFrame.acc.length * 100;
  72. if (newFrame.accFixed < lastFrame.accFixed * 0.85) {
  73. newFrame.accFixed = lastFrame.accFixed * 0.85;
  74. }
  75. lastFrame.accFixed = Math.max(lastFrame.accFixed, Math.min(newFrame.accFixed, last2Frame.accFixed), Math.min(
  76. newFrame.accFixed, last3Frame.accFixed));
  77. ///////////////////////////////////////////////////////////////////////
  78. //newFrame.pos = lastFrame.pos.plus(lastFrame.acc.plus(newFrame.acc).multiply(timeGap/60)).multiply(Math.max(1-timeGap/200,0));
  79. newFrame.pos = lastFrame.pos.plus(newFrame.acc.multiply(timeGap / 30)).multiply(Math.max(1 - timeGap / 1000, 0));
  80. ////////////////////////////////////////////
  81. var accSlpoe1 = (newFrame.accFixed - lastFrame.accFixed);
  82. var accSlpoe2 = (newFrame.accFixed - last2Frame.accFixed);
  83. var accSlpoe3 = (newFrame.accFixed - last3Frame.accFixed);
  84. //newFrame.accSlope = accSlpoe1;
  85. //newFrame.accSlope = Math.min(accSlpoe1,accSlpoe2);
  86. //newFrame.accSlope = Math.min(accSlpoe1,accSlpoe2,accSlpoe3);
  87. newFrame.accSlope = Math.max(newFrame.accFixed - lastFrame.accFixed, 0);
  88. /*
  89. if(newFrame.accSlope > 8){
  90. newFrame.accSlope = 1;
  91. }else if(newFrame.accSlope <= 8){
  92. newFrame.accSlope = 0;
  93. }/** */
  94. /////////////////////////////////////////////////
  95. var lastI = this.frame.length - 1;
  96. var t2 = this.frame[lastI - 1].timeGap;
  97. var t3 = this.frame[lastI].timeGap + t2;
  98. var t4 = newFrame.timeGap + t3;
  99. /*newFrame.predict = new o0.Vector2(
  100. new o0.QuadraticEquation(0,this.frame[lastI-2].acc.x,t2,this.frame[lastI-1].acc.x,t3,this.frame[lastI].acc.x).y(t4),
  101. new o0.QuadraticEquation(0,this.frame[lastI-2].acc.y,t2,this.frame[lastI-1].acc.y,t3,this.frame[lastI].acc.y).y(t4));/** */
  102. /*
  103. newFrame.predict = new o0.Vector2(
  104. new o0.QuadraticEquation(0,this.frame[lastI-2].pos.x,t2,this.frame[lastI-1].pos.x,t3,this.frame[lastI].pos.x).y(t4),
  105. new o0.QuadraticEquation(0,this.frame[lastI-2].pos.y,t2,this.frame[lastI-1].pos.y,t3,this.frame[lastI].pos.y).y(t4));/** */
  106. newFrame.predict = new o0.Vector2(
  107. new o0.QuadraticEquation(0, this.frame[lastI - 2].pos.x, t2, this.frame[lastI - 1].pos.x, t3, this.frame[lastI]
  108. .pos.x).y(t4),
  109. new o0.QuadraticEquation(0, this.frame[lastI - 2].pos.y, t2, this.frame[lastI - 1].pos.y, t3, this.frame[lastI]
  110. .pos.y).y(t4)); /** */
  111. //console.log(newFrame.pos);
  112. //////////////////////////////////////////
  113. //newFrame.shake = o0.distance2(newFrame.predict,newFrame.pos) * 500;
  114. //console.log(newFrame.pos.minus(lastFrame.pos).mod.angle(newFrame.predict.minus(lastFrame.pos).mod));
  115. //newFrame.shake = o0.distance2(newFrame.predict,newFrame.acc) * 100;
  116. newFrame.shake = o0.distance2(newFrame.predict, newFrame.pos) * 100;
  117. //newFrame.shake = o0.distance2(newFrame.predict,lastFrame.pos) * newFrame.acc.length / timeGap * 2000;
  118. if (isNaN(newFrame.shake)) {
  119. newFrame.shake = 0.0;
  120. } /** */
  121. //newFrame.shake = Math.pow(o0.distance2(newFrame.predict,newFrame.pos) * newFrame.acc.length / timeGap,0.5) * 500;
  122. /////////////////////////////下面的代码有优化空间
  123. //newFrame.shakeFixed = lastFrame.shakeFixed * 0.9;
  124. //newFrame.shakeFixed = lastFrame.shakeFixed*(1.0+newFrame.shake)*0.9;
  125. //newFrame.shakeFixed = Math.pow(lastFrame.shakeFixed*(1.0+newFrame.shake),0.5)+1;
  126. //console.log(newFrame.shakeFixed+1);
  127. //newFrame.shakeFixed = newFrame.shake;
  128. newFrame.shakeFixed = lastFrame.shakeFixed * 0.85;
  129. if (newFrame.shake > newFrame.shakeFixed) {
  130. newFrame.shakeFixed = newFrame.shake;
  131. } /* */
  132. lastFrame.shakeFixed = Math.max(lastFrame.shakeFixed, Math.min(newFrame.shakeFixed, last2Frame.shakeFixed), Math.min(
  133. newFrame.shakeFixed, last3Frame.shakeFixed));
  134. ////////////////////////////////////////////////////////////////
  135. /*
  136. var shakeSlpoe1 = (newFrame.shakeFixed-lastFrame.shakeFixed);
  137. var shakeSlpoe2 = (newFrame.shakeFixed-last2Frame.shakeFixed);
  138. var shakeSlpoe3 = (newFrame.shakeFixed-last3Frame.shakeFixed);
  139. //newFrame.accSlope = accSlpoe1;
  140. //newFrame.accSlope = Math.min(accSlpoe1,accSlpoe2);
  141. newFrame.shakeSlope = Math.min(shakeSlpoe1,shakeSlpoe2,shakeSlpoe3);
  142. newFrame.shakeSlope = Math.max(newFrame.shakeSlope,0);/** */
  143. newFrame.shakeSlope = Math.max(newFrame.shakeFixed - lastFrame.shakeFixed, 0);
  144. /*
  145. if(newFrame.shakeSlope > 40){
  146. newFrame.shakeSlope = 1;
  147. }else{
  148. newFrame.shakeSlope = 0;
  149. }/** */
  150. //////////////////////////////////////////////
  151. /*
  152. var slopeChange = newFrame.shakeFixed - lastFrame.shakeFixed;
  153. if(slopeChange < 0){
  154. newFrame.slope = (lastFrame.slope + (newFrame.shakeFixed - lastFrame.shakeFixed) / timeGap * 100) * 0.8;
  155. }else{
  156. newFrame.slope = (lastFrame.slope + (newFrame.shakeFixed - lastFrame.shakeFixed) / timeGap * 20) * 0.8;
  157. }
  158. if(newFrame.slope<0){
  159. newFrame.slope = 0;
  160. }/** */
  161. /////////////////////////////下面的代码有很大优化空间
  162. if (lastFrame.hit == 0 &&
  163. last2Frame.hit == 0 &&
  164. last3Frame.hit == 0 &&
  165. last4Frame.hit == 0 &&
  166. last5Frame.hit == 0 &&
  167. (newFrame.accSlope >= 15 || lastFrame.accSlope >= 20) &&
  168. (newFrame.shakeSlope >= 20 || lastFrame.shakeSlope >= 40)) {
  169. newFrame.hit = newFrame.shake;
  170. this.frameHit = [];
  171. //this.frameSwing = last2Frame;
  172. for (var i = this.frame.length - 3; i >= 1; --i) {
  173. let io = this.frame[i];
  174. let pio = this.frame[i - 1];
  175. if (io.accFixed * 0.85 <= pio.accFixed && io.accFixed >= pio.accFixed * 0.85) {
  176. this.frameSwing = io;
  177. }
  178. }
  179. } else {
  180. newFrame.hit = 0;
  181. }
  182. /*
  183. if(lastFrame.hit == 0
  184. && this.frame[this.frame.length-2].hit == 0
  185. && this.frame[this.frame.length-3].hit == 0
  186. && newFrame.shakeFixed > 150
  187. && newFrame.shakeFixed > lastFrame.shakeFixed * 2){
  188. newFrame.hit = newFrame.shakeFixed;
  189. }else{
  190. newFrame.hit = 0;
  191. }/** */
  192. /////////////力量大小
  193. if (lastFrame.hit != 0) {
  194. lastFrame.hit = lastFrame.hit + newFrame.shake;
  195. } else if (last2Frame.hit != 0) {
  196. last2Frame.hit = last2Frame.hit + newFrame.shake;
  197. } else if (last3Frame.hit != 0) {
  198. last3Frame.hit = last3Frame.hit + newFrame.shake;
  199. } else if (last4Frame.hit != 0) {
  200. last4Frame.hit = last4Frame.hit + newFrame.shake;
  201. } else if (last5Frame.hit != 0) {
  202. last5Frame.hit = last5Frame.hit + newFrame.shake;
  203. this.getDirection(last5Frame.hit, callback);
  204. } /** */
  205. //newFrame.shake = o0.distance2(newFrame.predict,newFrame.pos) * o0.distance2(lastFrame.pos,newFrame.pos);
  206. //////////////////////////////////////////////////////////////////////////////////
  207. newFrame.reliable = Math.pow((Math.PI / 2 - Math.atan(newFrame.shakeFixed / 10000)) / (Math.PI / 2), 2000);
  208. let lastFrameAddSpeed = lastFrame.acc.multiply(lastFrame.timeGap / 20).multiply(lastFrame.reliable);
  209. let newFrameAddSpeed = newFrame.acc.multiply(newFrame.timeGap / 20).multiply(newFrame.reliable);
  210. newFrame.speed = lastFrame.speed.multiply(0.8);
  211. var lastFrameAngle = newFrame.speed.angle(lastFrameAddSpeed);
  212. if (isNaN(lastFrameAngle)) {
  213. lastFrameAngle = 180.0;
  214. }
  215. //newFrame.speed = newFrame.speed.plus(lastFrameAddSpeed.multiply(Math.max(1,lastFrameAngle/60.0 - 1)));
  216. //newFrame.speed = newFrame.speed.multiply(1).plus(lastFrameAddSpeed.multiply(Math.max(1,lastFrameAngle/60.0 - 1)));
  217. newFrame.speed = newFrame.speed.multiply(1 - lastFrameAngle / 360.0).plus(lastFrameAddSpeed.multiply(Math.max(1,
  218. lastFrameAngle / 60.0 - 1)));
  219. var newFrameAngle = newFrame.speed.angle(newFrameAddSpeed);
  220. if (isNaN(newFrameAngle)) {
  221. newFrameAngle = 180.0;
  222. }
  223. //newFrame.speed = newFrame.speed.plus(newFrameAddSpeed.multiply(Math.min(1,newFrameAngle/60.0-1)));
  224. newFrame.speed = newFrame.speed.multiply(1 - newFrameAngle / 360.0).plus(newFrameAddSpeed.multiply(Math.max(1,
  225. newFrameAngle / 60.0 - 1)));
  226. //////////////////////
  227. this.frame.shift();
  228. this.frame.push(newFrame);
  229. if (this.frameHit.length <= 10) {
  230. var o = new Object();
  231. o.time = newFrame.time;
  232. o.timeGap = newFrame.timeGap;
  233. o.acc = newFrame.acc;
  234. o.gyr = newFrame.gyr;
  235. let frameHitLength = this.frameHit.length + 1;
  236. let lastFrameHit = this.frameHit[this.frameHit.length - 1];
  237. if (frameHitLength == 1) {
  238. o.allShakeLength = newFrame.shakeFixed;
  239. } else {
  240. o.allShakeLength = lastFrameHit.allShakeLength + newFrame.shakeFixed;
  241. }
  242. o.accFixed = o.acc.multiply(Math.pow(Math.max(0, 1 - newFrame.shakeFixed * frameHitLength / o.allShakeLength), 5) *
  243. 20); //数字越大越忽略历史数据
  244. if (frameHitLength == 1) {
  245. o.pos = o.accFixed.multiply(o.timeGap / 60);
  246. } else {
  247. o.pos = lastFrameHit.pos.plus(lastFrameHit.accFixed.plus(o.accFixed).multiply(o.timeGap / 60));
  248. }
  249. this.frameHit.push(o);
  250. }
  251. var vectorChanged = newForce.minus(this.force);
  252. var forceLength = this.force.length;
  253. var ForceChanged = newForce.length - forceLength;
  254. this.force = newForce;
  255. var currentLeftRight;
  256. if (Math.abs(newForce.x + newForce.z) > Math.abs(newForce.x - newForce.z)) {
  257. currentLeftRight = Math.abs(newForce.x + newForce.z);
  258. } else {
  259. currentLeftRight = -Math.abs(newForce.x - newForce.z);
  260. }
  261. this.forceRecord.shift();
  262. this.forceRecord.push(newForce);
  263. if (this.forceChanged > 0 && ForceChanged < 0) { // && forceLength > 0.1
  264. //&& this.momentum * Math.pow(0.9,(new Date().getTime()-this.momentunTime)/1) < forceLength){
  265. /*console.log(forceLength.toFixed(2));
  266. if( forceLength > 0.1 && forceLength >= this.momentum * 1.5){
  267. console.log(this.frame+" "+forceLength);
  268. }/** */
  269. if (forceLength > 0.1 && this.momentum != 999999) {
  270. if (!this.momentunPunch) { //等待击打
  271. if (this.momentunSeek > this.momentum) {
  272. this.momentunSeek = this.momentum;
  273. } else {
  274. if (this.momentunSeek < this.momentum * 0.8 - 0.1) {
  275. this.momentunPunch = !this.momentunPunch;
  276. this.punchCount++;
  277. //this.leftRight = (newForce.x+this.force.x) < 0;
  278. /*
  279. var largestForce = new o0.Vector3(0,0,0)
  280. for(var i = 0;i<this.forceRecord.length;++i){
  281. var element = this.forceRecord[i];
  282. if(largestForce.length < element.length){
  283. largestForce = element;
  284. }
  285. }
  286. if(Math.abs(largestForce.x + largestForce.z) > Math.abs(largestForce.x - largestForce.z)){
  287. currentLeftRight = Math.abs(largestForce.x + largestForce.z);
  288. }else{
  289. currentLeftRight = -Math.abs(largestForce.x - largestForce.z);
  290. }/** */
  291. this.leftRight = currentLeftRight < 0 ? "Right" : "Left";
  292. this.angle = new o0.Vector2(newForce.x, newForce.z).mod.angle(new o0.Vector2(0, 1));
  293. if (this.angle > 90) {
  294. this.angle = 180 - this.angle;
  295. }
  296. if (currentLeftRight > 0) {
  297. this.angle = -this.angle;
  298. } /** */
  299. //this.leftRight = (largestChange.x > 0 && largestChange.z > 0) || (largestChange.x < 0 && largestChange.z < 0);
  300. /* */
  301. //console.log(this.momentum);
  302. }
  303. }
  304. } else { //打完了
  305. if (this.momentunSeek < this.momentum) {
  306. this.momentunSeek = this.momentum;
  307. } else if (this.momentunSeek > this.momentum * 1.2 + 0.1) {
  308. this.momentunPunch = !this.momentunPunch;
  309. }
  310. }
  311. }
  312. this.momentum = forceLength;
  313. this.momentunTime = new Date().getTime();
  314. }
  315. this.forceChanged = ForceChanged;
  316. //console.log(vector3.x);
  317. return [new o0.Vector3(newForce), currentLeftRight, this.momentum];
  318. }
  319. test() {
  320. return "123123131";
  321. }
  322. getDirection(hitValue, callback) {
  323. var direction = new o0.Vector2(0, 0);
  324. var directionDistance = 0;
  325. for (var fi = 1; fi < this.frameHit.length - 1; ++fi) {
  326. for (var li = fi + 1; li < this.frameHit.length; ++li) {
  327. let firstGyr = this.frameHit[fi].gyr;
  328. let lastGyr = this.frameHit[li].gyr;
  329. let newDirectionDistance = o0.distance2(firstGyr, lastGyr);
  330. if (directionDistance < newDirectionDistance) {
  331. directionDistance = newDirectionDistance;
  332. direction = lastGyr.minus(firstGyr);
  333. }
  334. }
  335. }
  336. let curAngle = new o0.Vector2(direction.x, direction.y).mod.angle(new o0.Vector2(0, 1));
  337. let directionPunch = "all",
  338. name = "击中",
  339. ename = "hit";
  340. let curAngleCeil = Math.ceil(curAngle);
  341. //已坐标 (0,1) 向量为参考
  342. if (direction.y < 0) {
  343. //相反方向击打
  344. //正方向
  345. if (curAngleCeil > 150) {
  346. directionPunch = "straightPunch";
  347. name = "负向的直拳";
  348. ename = "back-straight";
  349. } else if (direction.x > 0) {
  350. directionPunch = "rightPunch";
  351. name = "负向的右拳";
  352. ename = "back-right";
  353. } else if (direction.x < 0) {
  354. directionPunch = "leftPunch";
  355. name = "负向的左拳";
  356. ename = "back-left";
  357. }
  358. } else {
  359. // y 大于零 手柄正方向击打
  360. if (curAngleCeil < 30) {
  361. directionPunch = "straightPunch";
  362. name = "正向的直拳";
  363. ename = "front-straight";
  364. } else if (direction.x < 0) {
  365. directionPunch = "rightPunch";
  366. name = "正向的右拳";
  367. ename = "front-right";
  368. } else if (direction.x > 0) {
  369. directionPunch = "leftPunch";
  370. name = "正向的左拳";
  371. ename = "front-left";
  372. }
  373. }
  374. this.quitHitCount++;
  375. if (callback) {
  376. let temp = {
  377. type: 'hit',
  378. hit: hitValue / 5,
  379. hitCount: this.quitHitCount,
  380. direction: directionPunch,
  381. directionVect: {
  382. 'x': direction.x,
  383. 'y': direction.y
  384. },
  385. angle: curAngleCeil,
  386. name: name,
  387. ename: ename
  388. }
  389. callback(temp);
  390. }
  391. }
  392. }
  393. };