import o0 from "./o0.js" module.exports = { SandbagAlgorithm: class { constructor() { this.stableAcc = new o0.Vector2(0, 0); this.stableGyr = new o0.Vector2(0, 0); this.stableCount = 0; this.stableCountMax = 3000; this.frameCapacity = 6; this.frame = []; this.frameLength = 5; this.frameOffset = 0; this.frameHitCapacity = 11; this.frameHit = []; //打击后的n帧 for (var i = 0; i < this.frameCapacity; ++i) { var o = new Object(); o.acc = new o0.Vector2(0, 0); o.gyr = new o0.Vector2(0, 0); o.timeGap = 20; o.accFixed = 0; o.accSlope = 0; o.pos = new o0.Vector2(0, 0); o.predict = new o0.Vector2(0, 0); o.shake = 0; o.shakeFixed = 0; o.shakeSlope = 0; o.hit = 0; this.frame.push(o); } this.quitHitCount = 0; } //这个函数不建议外部调用 GetDirection() { var direction = new o0.Vector2(0, 0); var directionDistance = 0.0; for (var fi = 0; fi < this.frameHit.length - 1; ++fi) { for (var li = fi + 1; li < this.frameHit.length; ++li) { var newDirection = this.frameHit[li].gyr.minus(this.frameHit[fi].gyr); var newDirectionDistance = newDirection.length; if (directionDistance < newDirectionDistance) { directionDistance = newDirectionDistance; direction = newDirection.multiply(this.frameHit[this.frameHit.length - 1].time - this.frameHit[0].time); } else { //cout << "false" << endl; } } } return direction; } // 输入俯视的平面坐标系下的xy轴坐标 的 加速计向量/陀螺仪向量。 // timeGap 代表当前帧读取传感器与上一帧读取传感器 之间的时间差 Update(accX, accY, gyrX, gyrY, timeGap) { var rawAcc = new o0.Vector2(accX, accY); var rawGyr = new o0.Vector2(gyrX, gyrY); let lastFrame = this.frame[(this.frameOffset + this.frameLength - 1) % this.frameCapacity]; let last2Frame = this.frame[(this.frameOffset + this.frameLength - 2) % this.frameCapacity]; let last3Frame = this.frame[(this.frameOffset + this.frameLength - 3) % this.frameCapacity]; let last4Frame = this.frame[(this.frameOffset + this.frameLength - 4) % this.frameCapacity]; let last5Frame = this.frame[(this.frameOffset + this.frameLength - 5) % this.frameCapacity]; var newFrame = this.frame[(this.frameOffset + this.frameLength) % this.frameCapacity]; newFrame.timeGap = timeGap; newFrame.acc = rawAcc.minus(this.stableAcc); newFrame.gyr = rawGyr.minus(this.stableGyr); if (this.stableCount < this.stableCountMax) { this.stableCount += 1; } this.stableAcc = this.stableAcc.multiply((this.stableCount - 1.0) / this.stableCount).plus( rawAcc.multiply(1 / this.stableCount)); this.stableGyr = this.stableGyr.multiply((this.stableCount - 1.0) / this.stableCount).plus( rawGyr.multiply(1 / this.stableCount)); ////////////////////////////////////////////////////////////////////////////////// newFrame.accFixed = newFrame.acc.length * 100; if (newFrame.accFixed < lastFrame.accFixed * 0.85) { newFrame.accFixed = lastFrame.accFixed * 0.85; } lastFrame.accFixed = Math.max(lastFrame.accFixed, Math.min(newFrame.accFixed, last2Frame .accFixed), Math.min(newFrame.accFixed, last3Frame.accFixed)); /////////////////////////////////////////////////////////////////////// //newFrame.pos = lastFrame.pos.plus(lastFrame.acc.plus(newFrame.acc).multiply(timeGap/60)).multiply(Math.max(1-timeGap/200,0)); newFrame.pos = lastFrame.pos.plus(newFrame.acc.multiply(timeGap / 30)).multiply(Math.max(1 - timeGap / 1000, 0)); //////////////////////////////////////////// newFrame.accSlope = Math.max(newFrame.accFixed - lastFrame.accFixed, 0); var lastI = this.frame.length - 1; var t2 = this.frame[lastI - 1].timeGap; var t3 = this.frame[lastI].timeGap + t2; var t4 = newFrame.timeGap + t3; newFrame.predict = new o0.Vector2( 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), 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)); /** */ newFrame.shake = o0.distance2(newFrame.predict, newFrame.pos) * 100; if (isNaN(newFrame.shake)) { newFrame.shake = 0.0; } newFrame.shakeFixed = lastFrame.shakeFixed * 0.85; if (newFrame.shake > newFrame.shakeFixed) { newFrame.shakeFixed = newFrame.shake; } /* */ lastFrame.shakeFixed = Math.max(lastFrame.shakeFixed, Math.min(newFrame.shakeFixed, last2Frame .shakeFixed), Math.min(newFrame.shakeFixed, last3Frame.shakeFixed)); //////////////////////////////////////////////////////////////// newFrame.shakeSlope = Math.max(newFrame.shakeFixed - lastFrame.shakeFixed, 0); /////////////////////////////////////////////////////////////// // (newFrame.accSlope >= 15 || lastFrame.accSlope >= 20) && // (newFrame.shakeSlope >= 20 || lastFrame.shakeSlope >= 40) var direction = undefined; let _threshold = [15,20,20,40];//判定的阈值 if (lastFrame.hit == 0 && last2Frame.hit == 0 && last3Frame.hit == 0 && last4Frame.hit == 0 && last5Frame.hit == 0 && (newFrame.accSlope >= _threshold[0] || lastFrame.accSlope >= _threshold[1]) && (newFrame.shakeSlope >= _threshold[2] || lastFrame.shakeSlope >= _threshold[3])) { newFrame.hit = 1; if (this.frameHit.length < this.frameHitCapacity && this.frameHit.length != 0) { //判断到第二次hit,但还未输出第一次hit的方向,强制输出方向 direction = this.GetDirection(); } /**/ this.frameHit = []; /* var o3 = new Object(); o3.time = 0; o3.gyr = lastFrame3.gyr; this.frameHit.push(o3);/* */ var o2 = new Object(); o2.time = last2Frame.timeGap; o2.gyr = last2Frame.gyr; this.frameHit.push(o2); var o = new Object(); o.time = last2Frame.timeGap + lastFrame.timeGap; o.gyr = lastFrame.gyr; this.frameHit.push(o); } else { newFrame.hit = 0; } if (this.frameHit.length < this.frameHitCapacity && this.frameHit.length != 0) { var o = new Object(); o.time = this.frameHit[this.frameHit.length - 1].time + newFrame.timeGap; //o.gyr = this.frameHit[this.frameHit.length-1].gyr.plus(newFrame.gyr); o.gyr = newFrame.gyr; this.frameHit.push(o); if (this.frameHit.length == this.frameHitCapacity) { //累计达到设定的延迟帧数,输出方向 direction = this.GetDirection(); } } if ((this.frameOffset += 1) >= this.frameCapacity) { this.frameOffset -= this.frameCapacity; } return [newFrame.hit, direction]; } getTempValue(curDirection) { let result = Math.atan2(curDirection.y, curDirection.x) * 180 / (Math.PI); result = Math.round(result); let curAngle = result > 0 ? result : (360 + result); let directionPunch = "all", name = "击中", ename = "hit"; //min , max let pLeftBetween = [105, 180]; let pStraightBetween = [75, 105]; let pRightBetween = [0, 75]; if (curAngle >= pStraightBetween[0] && curAngle < pStraightBetween[1]) { directionPunch = "straightPunch"; name = "正向的直拳"; ename = "front-straight"; } else if (curAngle >= pRightBetween[0] && curAngle < pRightBetween[1]) { directionPunch = "rightPunch"; name = "正向的右拳"; ename = "front-right"; } else if (curAngle >= pLeftBetween[0] && curAngle <= pLeftBetween[1]) { directionPunch = "leftPunch"; name = "正向的左拳"; ename = "front-left"; } //相反方向击打 //正方向 else { let mAngle = curAngle - 180; if (mAngle > pRightBetween[0] && mAngle <= pRightBetween[1]) { directionPunch = "rightPunch"; name = "负向的右拳"; ename = "back-right"; } else if (mAngle > pStraightBetween[0] && mAngle <= pStraightBetween[1]) { directionPunch = "straightPunch"; name = "负向的直拳"; ename = "back-straight"; } else if (mAngle > pLeftBetween[0] && mAngle <= pLeftBetween[1]) { directionPunch = "leftPunch"; name = "负向的左拳"; ename = "back-left"; } } this.quitHitCount++; let temp = { type: 'hit', hit: curDirection.length, hitCount: this.quitHitCount, direction: directionPunch, directionVect: { 'x': curDirection.x, 'y': curDirection.y }, angle: curAngle, name: name, ename: ename } console.log("hit:" + JSON.stringify(temp)); return temp; } } };