boxing-post.vue 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  1. <template>
  2. <view style="width: 90%; margin-bottom: 50rpx;">
  3. <!-- 计时器 -->
  4. <view class="boxingTimer flex justify-center">
  5. <boxingCountDown ref="boxingCountDownRef" :show-day="false" :second="showSportTime" color="#9695f7" background-color="#FFFFFF"
  6. border-color="#007AFF" splitorColor="#FFFFFF" />
  7. </view>
  8. <!-- 拳头特效 -->
  9. <!-- <efBone v-if="bGuideEF||(doubleHitCount>0&&doubleHitCount%doubleHitLimit == 0)" ref="refEfBone" @randomIndex="_efRandomIndex"></efBone> -->
  10. <!-- v-else 拳击部分 -->
  11. <view class="flex justify-around " style="margin-bottom: 16rpx; height: 300rpx;">
  12. <view class="flex flex-direction justify-between">
  13. <image :src="bLAnimation?'/static/modal/boxing-post/left-hook-h@2x.png':'/static/modal/boxing-post/left-hook-m@2x.png'"
  14. class="boxing-png " :class="bLAnimation?' boxing-change ':''" mode="aspectFit"></image>
  15. <view class="text-white text-13px" style="margin: 35rpx 0;">左勾拳</view>
  16. </view>
  17. <view class="flex flex-direction justify-between">
  18. <image :src="bMAnimation?'/static/modal/boxing-post/straight-h@2x.png':'/static/modal/boxing-post/straight-m@2x.png'"
  19. class="boxing-png " :class="bMAnimation?' boxing-change ':''" mode="aspectFit"></image>
  20. <view class="text-white text-13px" style="margin: 35rpx 0;">直拳</view>
  21. </view>
  22. <view class="flex flex-direction justify-between">
  23. <image :src="bRAnimation?'/static/modal/boxing-post/right-hook-h@2x.png':'/static/modal/boxing-post/right-hook-m@2x.png'"
  24. class="boxing-png " :class="bRAnimation?' boxing-change ':''" mode="aspectFit"></image>
  25. <view class="text-white text-13px" style="margin: 35rpx 0;">右勾拳</view>
  26. </view>
  27. </view>
  28. <!-- 显示数据 -->
  29. <view class="flex justify-around " style="margin-bottom: 16rpx;">
  30. <view class="flex flex-direction justify-between">
  31. <view class="boxing-count-bg">
  32. {{hitCount}}
  33. </view>
  34. <view class="text-white text-13px" style="margin: 10rpx 0;">击中</view>
  35. </view>
  36. <view class="flex flex-direction justify-between">
  37. <view class="boxing-count-bg">
  38. {{doubleHitCount}}
  39. </view>
  40. <view class="text-white text-13px" style="margin: 10rpx 0;">连</view>
  41. </view>
  42. <view class="flex flex-direction justify-between">
  43. <view class="boxing-count-bg">
  44. {{missCount}}
  45. </view>
  46. <view class="text-white text-13px" style="margin: 10rpx 0;">失误</view>
  47. </view>
  48. </view>
  49. <!-- 对话框 -->
  50. <view class="flex justify-center " style="margin-bottom: 32rpx;">
  51. <view class="boxing-post-talkbubble">
  52. 你离{{evaluateName}}还差{{evaluatePower}}公斤
  53. </view>
  54. </view>
  55. <!-- 步骤条 -->
  56. <!-- <customStep ref="customStepRef" @onCustomSetBasics="_customSetBasics"></customStep> -->
  57. <!-- 控制按钮 -->
  58. <controlButtons ref="customControlButtons" :showLeftRight='false' @onControlPlayTap="_customControlPlay"></controlButtons>
  59. <view class="vertical-container">
  60. <view class="vertical-bar">
  61. <view class="vertical-child" v-for="(item, index) in 20" :key="index">
  62. <view :class="powerCount>=index+1? 'vertical-active':'vertical-inactive'"></view>
  63. <view :class="index%5 == 0?'':'text-hidden'" class="vertical-text">{{index+1}}</view>
  64. </view>
  65. </view>
  66. <view class="vertical-bar">
  67. <view class="vertical-child" v-for="(item, index) in 20" :key="index">
  68. <view :class="index%5 == 0?'':'text-hidden'" class="vertical-text">{{index+21}}</view>
  69. <view :class="powerCount>=index+21? 'vertical-active':'vertical-inactive'"></view>
  70. </view>
  71. </view>
  72. </view>
  73. <button @tap="onTestHit('left')">左</button>
  74. <!-- <button @tap="onTestHit('mid')">中({{accHitCountAdd}})</button>
  75. <button @tap="onTestHit('right')">右</button> -->
  76. </view>
  77. </template>
  78. <script>
  79. import customStep from "@/components/my-custom-step/my-custom-step.vue"
  80. import controlButtons from "@/components/my-control-buttons/my-control-buttons.vue"
  81. import efBone from "./ef-bone.vue"
  82. import boxingCountDown from '@/components/uni-count-down/uni-count-down.vue'
  83. import puchConfig from "@/util/util-js/puchConfig.js"
  84. import EquipmentAction from "@/util/util-js/EquipmentAction.js"
  85. export default {
  86. components: {
  87. customStep,
  88. controlButtons,
  89. efBone,
  90. boxingCountDown
  91. },
  92. props: {
  93. bUpdate: {
  94. type: Boolean,
  95. default: false
  96. },
  97. // 默认男性
  98. bMan: {
  99. type: Boolean,
  100. default: true
  101. },
  102. showTime: {
  103. type: Number,
  104. default: 0
  105. },
  106. },
  107. data() {
  108. return {
  109. hitCount: 0,
  110. addCount: 0,
  111. missCount: 0,
  112. doubleHitCount: 0,
  113. powerCount: 0,
  114. //当前打击的最大值
  115. powerMaxCount: 0,
  116. //连击数的限制值
  117. doubleHitLimit: 10,
  118. bRAnimation: false,
  119. bLAnimation: false,
  120. bMAnimation: false,
  121. xA: 0,
  122. yA: 0,
  123. zA: 0,
  124. xO: 0,
  125. yO: 0,
  126. zO: 0,
  127. calZVector: 0,
  128. calXVector: 0,
  129. bCanXL: false,
  130. bCanXR: false,
  131. bCanZ: false,
  132. ZCount: 0,
  133. LCount: 0,
  134. RCount: 0,
  135. //临时值
  136. addZCount: 0,
  137. addLCount: 0,
  138. addRCount: 0,
  139. mass: 5,
  140. //大概消耗的卡路里
  141. calorie: 0,
  142. leftHookUrl: "/static/modal/boxing-post/left-hook.mp3",
  143. rightHookUrl: "/static/modal/boxing-post/right-hook.mp3",
  144. straightHookUrl: "/static/modal/boxing-post/straight-hook.mp3",
  145. hookAudioContext: null,
  146. //新手语音提示
  147. leftTipUrl: "/static/modal/boxing-post/tipLeft.mp3",
  148. rightTipUrl: "/static/modal/boxing-post/tipRight.mp3",
  149. straightTipUrl: "/static/modal/boxing-post/tipStraight.mp3",
  150. greatTipUrl: "/static/modal/boxing-post/tipGreat.mp3",
  151. giveGoTipUrl: "/static/modal/boxing-post/tipGiveItAGo.mp3",
  152. startTraining: "/static/modal/boxing-post/tipStartTraining.mp3",
  153. //击打状态音效
  154. hitUrl: "/static/elect/hit.mp3",
  155. missUrl: "/static/elect/miss.mp3",
  156. oldxA: 0,
  157. oldzA: 0,
  158. bUpdateOnce: false,
  159. bDelayOnce: false,
  160. autoBoxingTip: null,
  161. //播放时间
  162. autoDuration: 800,
  163. //是否在播放
  164. bPlay: false,
  165. //新手
  166. bGuide: false,
  167. //是否是特殊拳击
  168. bGuideEF: false,
  169. //动画
  170. powerInterval: null,
  171. //特殊一击
  172. powerEFTimeObj: null,
  173. evaluateName: "平民战五渣",
  174. evaluatePower: 5,
  175. //男拳击显示的名字
  176. manNameList: [
  177. '平民战五渣',
  178. '鹰眼侠',
  179. '蝙蝠侠',
  180. '金刚狼',
  181. '美国队长',
  182. '蜘蛛侠',
  183. '钢铁侠',
  184. '闪电侠',
  185. '毒液',
  186. '绿巨人',
  187. '超人',
  188. '雷神',
  189. '众神之王奥丁',
  190. '灭霸',
  191. '天启'
  192. ],
  193. //女拳击显示的名字
  194. womanNameList: [
  195. '平民战五渣',
  196. '豹女',
  197. '毒藤女',
  198. '猫女',
  199. '小丑女',
  200. '黑寡妇',
  201. '蜘蛛女',
  202. '暴风女',
  203. '美杜莎',
  204. '女浩克',
  205. '女武神',
  206. '雅典娜',
  207. '绯红女巫',
  208. '惊奇队长',
  209. '爱神维纳斯'
  210. ],
  211. //全力一击随机对象
  212. efRandomObj: null,
  213. bHitEFRandomObj: false,
  214. //运动时间
  215. showSportTime: this.showTime,
  216. sportTimeInterval: null,
  217. //下一个进行播放的对象
  218. endSetTimeout: null,
  219. //X轴的变化数组值
  220. xAccArray: [],
  221. xMax: 0,
  222. maxTimeoutId: null,
  223. bMaxPause: false,
  224. xMin: 0,
  225. minTimeoutId: null,
  226. bMinPause: false,
  227. bCalculation: false,
  228. calTimeout: null,
  229. //动态变化的角度比 z/x
  230. angleRatio: 1,
  231. //当前basic
  232. basic: 0,
  233. //拳击数据判断对象
  234. EquipmentActionObj: null,
  235. accHitCountAdd: 0
  236. }
  237. },
  238. watch: {
  239. bUpdate(val) {
  240. },
  241. showTime(val) {
  242. this.showSportTime = val;
  243. }
  244. },
  245. created() {
  246. let _self = this;
  247. _self.hookAudioContext = uni.createInnerAudioContext();
  248. _self.hookAudioContext.autoplay = false;
  249. _self.hookAudioContext.src = _self.straightHookUrl;
  250. _self.hookAudioContext.volume = 1;
  251. console.log(" ***** boxing-post created ******");
  252. _self.onBindAcc();
  253. // this.onBindOri();
  254. _self.EquipmentActionObj = new EquipmentAction();
  255. // console.warn("_self.EquipmentActionObj:", _self.EquipmentActionObj);
  256. _self.EquipmentActionObj.addEventListener("resultantHit", (e) => {
  257. // console.warn("_self.EquipmentActionObj11.addEventListener:", e);
  258. // this.accHitCountAdd = e.acc;
  259. if (((this.doubleHitCount > 0 && this.doubleHitCount % this.doubleHitLimit == 0) ||
  260. this.bGuide) && this.efRandomObj) {
  261. this.onHit(this.efRandomObj.direction, e.acc, e.power);
  262. } else {
  263. if (this.bLAnimation)
  264. this.onHit("xRCount", e.acc, e.power);
  265. else if (this.bRAnimation)
  266. this.onHit("xLCount", e.acc, e.power);
  267. else if (this.bMAnimation)
  268. this.onHit("zLCount", e.acc, e.power);
  269. }
  270. })
  271. },
  272. beforeDestroy() {
  273. console.log(" ***** boxing-post destroyed ******");
  274. this.onUnbindAcc();
  275. // this.onUnbindOri();
  276. let _self = this;
  277. if (_self.powerInterval) {
  278. clearInterval(_self.powerInterval);
  279. _self.powerInterval = null;
  280. }
  281. //停掉当前的随机播放
  282. if (_self.autoBoxingTip) {
  283. clearInterval(_self.autoBoxingTip);
  284. _self.autoBoxingTip = null;
  285. }
  286. if (_self.hookAudioContext)
  287. _self.hookAudioContext.destroy();
  288. if (_self.sportTimeInterval) {
  289. clearInterval(_self.sportTimeInterval);
  290. _self.sportTimeInterval = null;
  291. }
  292. if (_self.endSetTimeout) {
  293. clearTimeout(_self.endSetTimeout);
  294. _self.endSetTimeout = null;
  295. }
  296. },
  297. methods: {
  298. moveBoxingHandle() {
  299. return;
  300. },
  301. //测试打击
  302. onTestHit(data) {
  303. let _self = this;
  304. let maxPower = Math.floor(Math.random() * 300);
  305. console.log("maxPower:", maxPower);
  306. // if (data == "left")
  307. // this.onHit("xRCount", 0, maxPower);
  308. // else if (data == "right")
  309. // this.onHit("xLCount", 0, maxPower);
  310. // else if (data == "mid")
  311. // this.onHit("zLCount", 0, maxPower);
  312. if (this.bLAnimation)
  313. this.onHit("xRCount", 0, maxPower);
  314. else if (this.bRAnimation)
  315. this.onHit("xLCount", 0, maxPower);
  316. else if (this.bMAnimation)
  317. this.onHit("zLCount", 0, maxPower);
  318. },
  319. //平时击打的力量槽动画播放
  320. onPlayPowerAnimation(bGreat) {
  321. if (bGreat) {
  322. this.hookAudioContext.stop();
  323. this.hookAudioContext.src = this.greatTipUrl;
  324. this.hookAudioContext.play();
  325. } else {
  326. this.hookAudioContext.stop();
  327. this.hookAudioContext.src = this.hitUrl;
  328. this.hookAudioContext.play();
  329. }
  330. let _self = this;
  331. // if (_self.powerInterval) {
  332. // clearInterval(_self.powerInterval);
  333. // _self.powerInterval = null;
  334. // }
  335. // let bAdd = true;
  336. // _self.powerCount = 0;
  337. // let _duraciotn = 300 / _self.powerMaxCount;
  338. // _self.powerInterval = setInterval(function() {
  339. // // if (_self.powerCount >= _self.powerMaxCount) {
  340. // // bAdd = false;
  341. // // } else if (_self.powerCount == 0 && !bAdd) {
  342. // // clearInterval(_self.powerInterval);
  343. // // _self.powerInterval = null;
  344. // // return;
  345. // // }
  346. // // if (bAdd)
  347. // // _self.powerCount++;
  348. // // else
  349. // // _self.powerCount--;
  350. // //递增
  351. // if (_self.powerCount >= _self.powerMaxCount) {
  352. // clearInterval(_self.powerInterval);
  353. // _self.powerInterval = null;
  354. // return;
  355. // }
  356. // _self.powerCount++;
  357. // }, _duraciotn); //300ms/40格
  358. },
  359. //特殊一击时候力量槽
  360. onPlayEFHitAnimation() {
  361. let _self = this;
  362. if (_self.powerEFTimeObj) {
  363. clearTimeout(_self.powerEFTimeObj);
  364. _self.powerEFTimeObj = null;
  365. }
  366. let _duraciotn = 300 / (_self.powerMaxCount - _self.powerCount);
  367. if (_self.powerCount > _self.powerMaxCount - 2) {
  368. _duraciotn = 1000;
  369. } else if (_self.powerCount > _self.powerMaxCount / 2) {
  370. _duraciotn *= 5;
  371. }
  372. _self.powerEFTimeObj = setTimeout(() => {
  373. if (_self.powerCount == _self.powerMaxCount) {
  374. clearTimeout(_self.powerEFTimeObj);
  375. _self.powerEFTimeObj = null;
  376. _self.powerCount = 0;
  377. return;
  378. }
  379. _self.powerCount++;
  380. _self.onPlayEFHitAnimation();
  381. }, _duraciotn); //300ms/40格
  382. },
  383. onBindAcc(globalAcc) {
  384. uni.$on('watchAcceleration', this.updateAcc);
  385. },
  386. onUnbindAcc() {
  387. uni.$off('watchAcceleration', this.updateAcc);
  388. },
  389. onBindOri(globalOri) {
  390. uni.$on('watchOrientation', this.updateOri);
  391. },
  392. onUnbindOri() {
  393. uni.$off('watchOrientation', this.updateOri);
  394. },
  395. onResetCal() {
  396. this.xAccArray = [];
  397. this.xMax = 0;
  398. this.xMin = 0;
  399. this.bCalculation = false;
  400. this.oldxA = 0;
  401. this.oldzA = 0;
  402. this.calTimeout = null;
  403. },
  404. updateAcc(acc) {
  405. this.xA = acc.xAxis;
  406. this.yA = acc.yAxis;
  407. this.zA = acc.zAxis;
  408. //在acc 中更新数据
  409. // this.updateData();
  410. if (!this.bUpdate || !this.bPlay) return;
  411. this.EquipmentActionObj.updateAcc({
  412. xA: acc.xAxis,
  413. zA: acc.yAxis,
  414. yA: acc.zAxis
  415. })
  416. // if (Math.abs(this.xA) > 8 && this.oldxA != this.xA && !this.bCalculation) {
  417. // this.xAccArray.push(this.xA);
  418. // this.oldxA = this.xA;
  419. // if (this.calTimeout == null) {
  420. // this.calTimeout = setTimeout(() => {
  421. // this.bCalculation = true;
  422. // for (let i = 0; i < this.xAccArray.length; i++) {
  423. // if (this.xAccArray[i] < 0 && this.xAccArray[i] < this.xAccArray[this.xMin]) {
  424. // this.xMin = i;
  425. // } else if (this.xAccArray[i] > 0 && this.xAccArray[i] > this.xAccArray[this.xMax]) {
  426. // this.xMax = i;
  427. // }
  428. // }
  429. // console.log(this.xAccArray, "==", this.xMin, "==", this.xMax);
  430. // if (this.xAccArray[this.xMin] < 0 && this.xAccArray[this.xMax] > 0) {
  431. // if (this.xMin > this.xMax)
  432. // this.onHit("xRCount", this.xAccArray[this.xMin], Math.ceil(Math.abs(this.xAccArray[this.xMin]) * puchConfig.BOXING_MASS));
  433. // else if (this.xMin < this.xMax)
  434. // this.onHit("xLCount", this.xAccArray[this.xMax], Math.ceil(Math.abs(this.xAccArray[this.xMax]) * puchConfig.BOXING_MASS));
  435. // } else if (this.xAccArray[this.xMin] < 0) {
  436. // this.onHit("xLCount", this.xAccArray[this.xMin], Math.ceil(Math.abs(this.xAccArray[this.xMin]) * puchConfig.BOXING_MASS));
  437. // } else if (this.xAccArray[this.xMax] > 0) {
  438. // this.onHit("xRCount", this.xAccArray[this.xMax], Math.ceil(Math.abs(this.xAccArray[this.xMax]) * puchConfig.BOXING_MASS));
  439. // }
  440. // setTimeout(() => {
  441. // this.onResetCal();
  442. // }, 100);
  443. // this.calTimeout = null;
  444. // }, 200);
  445. // }
  446. // } else if (this.zA < -10 && this.oldzA != this.zA && this.xAccArray.length == 0) {
  447. // console.log("this.zA:", this.zA);
  448. // this.oldzA = this.zA;
  449. // setTimeout(() => {
  450. // this.onResetCal();
  451. // }, 200);
  452. // this.onHit("zLCount", this.zA, Math.ceil(Math.abs(this.zA) * puchConfig.BOXING_MASS));
  453. // }
  454. },
  455. updateOri(ori) {
  456. this.xO = ori.beta;
  457. this.zO = ori.alpha;
  458. this.yO = ori.gamma;
  459. },
  460. //步骤条调整速度
  461. _customSetBasics(data) {
  462. console.log(data);
  463. let _self = this;
  464. if (_self.autoBoxingTip) {
  465. clearInterval(_self.autoBoxingTip);
  466. _self.autoBoxingTip = null;
  467. }
  468. if (0 === data.basics)
  469. _self.autoDuration = 800;
  470. else
  471. _self.autoDuration = 3000 - data.basics * 260;
  472. console.log("_self.autoDuration:", _self.autoDuration);
  473. _self.basic = data.basics;
  474. if (!_self.bPlay || _self.bGuide) return;
  475. if (0 != _self.basic) {
  476. //自动调用拳击图标
  477. _self.autoBoxingTip = setInterval(function() {
  478. _self.onAutoPlayBoxingTip();
  479. }, _self.autoDuration);
  480. }
  481. },
  482. _customControlButton(data) {
  483. //修改步骤条,绑定回调 _customSetBasics
  484. this.$refs.customStepRef.onChangeBasicsFromDirection(data);
  485. },
  486. _customControlPlay(data) {
  487. let _self = this;
  488. //1.检查是否符合要求,再进行训练
  489. if (data.bControlRun) {
  490. //如果运行中直接停掉
  491. if (_self.autoBoxingTip) {
  492. clearInterval(_self.autoBoxingTip);
  493. _self.autoBoxingTip = null;
  494. }
  495. if (_self.sportTimeInterval) {
  496. clearInterval(_self.sportTimeInterval);
  497. _self.sportTimeInterval = null;
  498. }
  499. this.bPlay = false;
  500. this.$refs.customControlButtons.onPlay();
  501. //如果是新手教程,也直接停掉
  502. this.bGuide = false;
  503. this.bGuideEF = false;
  504. this.bRAnimation = false;
  505. this.bLAnimation = false;
  506. this.bMAnimation = false;
  507. this.$emit("boxingPostControlPlay", false);
  508. } else {
  509. this.$emit("boxingPostCheck");
  510. }
  511. },
  512. //新手引导
  513. onGuideBoxingPostPlay() {
  514. console.log("onGuideBoxingPostPlay");
  515. let _self = this;
  516. _self.bPlay = true;
  517. //
  518. _self.bGuide = true;
  519. // 按钮事件
  520. _self.$refs.customControlButtons.onPlay();
  521. // 右勾拳
  522. _self.onPlayBoxingTipIndex(0, () => {
  523. });
  524. },
  525. //训练退出时候,重新信息
  526. onBoxingPostStop() {
  527. this.addLCount = 0;
  528. this.addRCount = 0;
  529. this.addZCount = 0;
  530. // this.calorie = 0;
  531. this.powerCount = 0;
  532. },
  533. //调用播放
  534. onBoxingPostPlay(bPlaying) {
  535. let _self = this;
  536. if (bPlaying) {
  537. _self.bPlay = true;
  538. // 按钮事件
  539. _self.$refs.customControlButtons.onPlay(true);
  540. if (_self.sportTimeInterval) {
  541. clearInterval(_self.sportTimeInterval);
  542. _self.sportTimeInterval = null;
  543. }
  544. //play true 时候,开启时间计算
  545. _self.sportTimeInterval = setInterval(() => {
  546. _self.showSportTime++;
  547. if (_self.showSportTime >= 20 && _self.showSportTime % 20 == 0) {
  548. _self.$emit("updateSportTime", _self.showSportTime);
  549. }
  550. }, 1000)
  551. }
  552. if (_self.autoBoxingTip) {
  553. clearInterval(_self.autoBoxingTip);
  554. _self.autoBoxingTip = null;
  555. }
  556. //如果是0,打一拳调用一次
  557. if (0 == _self.basic) {
  558. _self.onAutoPlayBoxingTip();
  559. } else {
  560. _self.onAutoPlayBoxingTip();
  561. _self.autoBoxingTip = setInterval(function() {
  562. _self.onAutoPlayBoxingTip();
  563. }, _self.autoDuration);
  564. }
  565. },
  566. //新手定时播放
  567. onPlayBoxingTipIndex(_index, callback) {
  568. if (_index === 0) {
  569. //右勾拳
  570. this.bRAnimation = true;
  571. this.hookAudioContext.stop();
  572. this.hookAudioContext.src = this.rightTipUrl;
  573. this.hookAudioContext.play();
  574. if (callback)
  575. callback();
  576. //
  577. this.angleRatio = 10;
  578. } else if (_index === 1) {
  579. //左勾拳
  580. this.bLAnimation = true;
  581. this.hookAudioContext.stop();
  582. this.hookAudioContext.src = this.leftTipUrl;
  583. this.hookAudioContext.play();
  584. if (callback)
  585. callback();
  586. this.angleRatio = 10;
  587. } else if (_index === 2) {
  588. //直拳
  589. this.bMAnimation = true;
  590. this.hookAudioContext.stop();
  591. this.hookAudioContext.src = this.straightTipUrl;
  592. this.hookAudioContext.play();
  593. if (callback)
  594. callback();
  595. this.angleRatio = 0.5;
  596. } else if (_index === 3) {
  597. this.bGuideEF = true;
  598. this.hookAudioContext.stop();
  599. this.hookAudioContext.src = this.giveGoTipUrl;
  600. this.hookAudioContext.play();
  601. if (callback)
  602. callback();
  603. }
  604. console.log("this.hookAudioContext:", this.hookAudioContext);
  605. },
  606. //随机播放
  607. onAutoPlayBoxingTip() {
  608. // console.log("onAutoPlayBoxingTip .powerCount:",this.powerCount);
  609. //重置动画
  610. this.bRAnimation = false;
  611. this.bLAnimation = false;
  612. this.bMAnimation = false;
  613. let _index = Math.floor(Math.random() * 3);
  614. // console.log("_index==",_index);
  615. // return;
  616. if (_index === 0) {
  617. //右勾拳
  618. if (!this.bRAnimation) {
  619. this.bRAnimation = true;
  620. this.hookAudioContext.stop();
  621. this.hookAudioContext.src = this.rightHookUrl;
  622. this.hookAudioContext.play();
  623. }
  624. this.angleRatio = 10;
  625. } else if (_index === 1) {
  626. //左勾拳
  627. if (!this.bLAnimation) {
  628. this.bLAnimation = true;
  629. this.hookAudioContext.stop();
  630. this.hookAudioContext.src = this.leftHookUrl;
  631. this.hookAudioContext.play();
  632. }
  633. this.angleRatio = 10;
  634. } else if (_index === 2) {
  635. //直拳
  636. if (!this.bMAnimation) {
  637. this.bMAnimation = true;
  638. this.hookAudioContext.stop();
  639. this.hookAudioContext.src = this.straightHookUrl;
  640. this.hookAudioContext.play();
  641. }
  642. this.angleRatio = 0.5;
  643. }
  644. },
  645. onHit(direction, direValue, power) {
  646. // console.log(direction, direValue, power);
  647. let temp = {
  648. direction: direction,
  649. value: direValue,
  650. mass: this.mass, //质量
  651. hitPower: power //计算的力
  652. }
  653. //设置200 为最大值,最大值时候分为40份。即单位是 7.5
  654. let _maxPower = 200;
  655. if (power >= _maxPower) {
  656. this.powerMaxCount = 40;
  657. } else {
  658. this.powerMaxCount = Math.ceil(power / 5);
  659. }
  660. //如果是男性用户
  661. let _nameList = this.manNameList;
  662. if (!this.bMan) {
  663. _nameList = this.womanNameList;
  664. }
  665. //名字相对于最大力量 的 间隔单位
  666. let _nameUnit = _maxPower / _nameList.length;
  667. let _nameIndex = Math.ceil(power / _nameUnit);
  668. if (_nameIndex < _nameList.length - 1) {
  669. //console.log("名称下标:", _nameList[_nameIndex], "下一个目标:", _nameList[_nameIndex + 1]);
  670. this.evaluateName = _nameList[_nameIndex + 1];
  671. //下一个目标的公斤值
  672. let _nextPower = Math.ceil((_nameIndex + 1) * _nameUnit);
  673. //console.log("_nextPower:", _nextPower, power);
  674. this.evaluatePower = _nextPower - power;
  675. } else {
  676. this.evaluateName = _nameList[_nameList.length - 1];
  677. this.evaluatePower = 0;
  678. }
  679. //如果是新手流程
  680. if (this.bGuide) {
  681. // if (this.bGuideEF) {
  682. // if (!this.efRandomObj) return;
  683. // let bHitEF = false;
  684. // if (this.efRandomObj.direction == direction) {
  685. // // this.RCount++;
  686. // bHitEF = true;
  687. // } else if (this.efRandomObj.direction == direction) {
  688. // // this.LCount++;
  689. // bHitEF = true;
  690. // } else if (this.efRandomObj.direction == direction) {
  691. // // this.ZCount++;
  692. // bHitEF = true;
  693. // }
  694. // //播放全力一击特效,特效完成后回调
  695. // if (bHitEF) {
  696. // this.bHitEFRandomObj = true;
  697. // //播放进度动画
  698. // this.onPlayEFHitAnimation();
  699. // //爆炸同时抖动
  700. // this.$emit("shake");
  701. // this.$refs.refEfBone.onEFHit(() => {
  702. // // this.doubleHitCount++;
  703. // this.bGuideEF = false;
  704. // this.bGuide = false;
  705. // this.hookAudioContext.stop();
  706. // this.hookAudioContext.src = this.greatTipUrl;
  707. // this.hookAudioContext.play();
  708. // setTimeout(() => {
  709. // this.hookAudioContext.stop();
  710. // this.hookAudioContext.src = this.startTraining;
  711. // this.hookAudioContext.play();
  712. // setTimeout(() => {
  713. // this.$emit("boxingGuideFinish");
  714. // }, 3000);
  715. // }, 1000)
  716. // this.bHitEFRandomObj = false;
  717. // });
  718. // }
  719. // } else {
  720. //根据是否播放的拳击,来判断是否击中
  721. if (direction == "xLCount" && this.bRAnimation) {
  722. //右勾拳
  723. // this.RCount++;
  724. // this.doubleHitCount++;
  725. this.bRAnimation = false;
  726. //播放进度动画
  727. this.onPlayPowerAnimation(true);
  728. setTimeout(() => {
  729. //播放下一个拳击
  730. this.onPlayBoxingTipIndex(1);
  731. }, 1500)
  732. } else if (direction == "xRCount" && this.bLAnimation) {
  733. //左勾拳
  734. // this.LCount++;
  735. // this.doubleHitCount++;
  736. this.bLAnimation = false;
  737. //播放进度动画
  738. this.onPlayPowerAnimation(true);
  739. //播放下一个拳击
  740. setTimeout(() => {
  741. //播放下一个拳击
  742. this.onPlayBoxingTipIndex(2);
  743. }, 1500)
  744. } else if (direction == "zLCount" && this.bMAnimation) {
  745. //直拳
  746. // this.ZCount++;
  747. // this.doubleHitCount++;
  748. this.bMAnimation = false;
  749. //播放进度动画
  750. this.onPlayPowerAnimation(true);
  751. //全力一击
  752. setTimeout(() => {
  753. //播放下一个拳击
  754. // this.onPlayBoxingTipIndex(3);
  755. this.bGuide = false;
  756. this.$emit("boxingGuideFinish");
  757. }, 1500)
  758. }
  759. // }
  760. } else {
  761. // //如果单次是特殊一击
  762. // if (this.doubleHitCount > 0 && this.doubleHitCount % this.doubleHitLimit == 0) {
  763. // if (this.bHitEFRandomObj) return;
  764. // if (!this.efRandomObj) return;
  765. // let bHitEF = false;
  766. // if (this.efRandomObj.direction == direction) {
  767. // this.RCount++;
  768. // bHitEF = true;
  769. // } else if (this.efRandomObj.direction == direction) {
  770. // this.LCount++;
  771. // bHitEF = true;
  772. // } else if (this.efRandomObj.direction == direction) {
  773. // this.ZCount++;
  774. // bHitEF = true;
  775. // }
  776. // //播放全力一击特效,特效完成后回调
  777. // if (bHitEF) {
  778. // this.bHitEFRandomObj = true;
  779. // //播放进度动画
  780. // this.onPlayEFHitAnimation();
  781. // //爆炸同时抖动
  782. // this.$emit("shake");
  783. // this.$refs.refEfBone.onEFHit(() => {
  784. // this.doubleHitCount++;
  785. // setTimeout(() => {
  786. // //新手教程,恢复随机播放
  787. // this.onBoxingPostPlay();
  788. // }, 1000);
  789. // this.bHitEFRandomObj = false;
  790. // });
  791. // }
  792. // } else
  793. // {
  794. //如果没有显示动画,不能打击
  795. if (!this.bRAnimation && !this.bLAnimation && !this.bMAnimation)
  796. return;
  797. //如果力量槽达到最大值,同步卡路里,并且清空记录值
  798. if (this.powerCount >= 40) {
  799. console.log("同步卡路里");
  800. this.$emit('updateCalorie', this.calorie);
  801. this.addLCount = 0;
  802. this.addRCount = 0;
  803. this.addZCount = 0;
  804. }
  805. //根据是否播放的拳击,来判断是否击中
  806. if (direction == "xLCount" && this.bRAnimation) {
  807. //右勾拳
  808. this.RCount++;
  809. this.addRCount++;
  810. this.doubleHitCount++;
  811. this.bRAnimation = false;
  812. //播放进度动画
  813. this.onPlayPowerAnimation();
  814. } else if (direction == "xRCount" && this.bLAnimation) {
  815. //左勾拳
  816. this.LCount++;
  817. this.addLCount++;
  818. this.doubleHitCount++;
  819. this.bLAnimation = false;
  820. //播放进度动画
  821. this.onPlayPowerAnimation();
  822. // console.log("xRCount");
  823. } else if (direction == "zLCount" && this.bMAnimation) {
  824. //直拳
  825. this.ZCount++;
  826. this.addZCount++;
  827. this.doubleHitCount++;
  828. this.bMAnimation = false;
  829. //播放进度动画
  830. this.onPlayPowerAnimation();
  831. // console.log("zLCount");
  832. }
  833. // else if (this.bRAnimation || this.bLAnimation || this.bMAnimation) {
  834. // //如果没有击打的,设置miss
  835. // this.missCount++;
  836. // this.doubleHitCount = 0;
  837. // this.hookAudioContext.stop();
  838. // this.hookAudioContext.src = this.missUrl;
  839. // this.hookAudioContext.play();
  840. // console.log("miss");
  841. // this.bRAnimation = false;
  842. // this.bLAnimation = false;
  843. // this.bMAnimation = false;
  844. // }
  845. //停掉当前的随机播放
  846. if (this.autoBoxingTip) {
  847. clearInterval(this.autoBoxingTip);
  848. this.autoBoxingTip = null;
  849. }
  850. // console.log(11111);
  851. //判断当前连击数
  852. // if (this.doubleHitCount > 0 && this.doubleHitCount % this.doubleHitLimit == 0) {
  853. // this.hookAudioContext.stop();
  854. // this.hookAudioContext.src = this.giveGoTipUrl;
  855. // this.hookAudioContext.play();
  856. // } else {
  857. this.endSetTimeout = setTimeout(() => {
  858. // console.log("start");
  859. //更新随机播放
  860. this.onBoxingPostPlay();
  861. }, 400);
  862. // }
  863. // }
  864. //每10次更新一次卡路里
  865. // if (this.hitCount !==0 && 0 == this.hitCount % 10) {
  866. // //打一拳,大约消耗的热量,是450*4/60=1.875 焦耳。
  867. // //因为打拳一小时,需要消耗的热量是450大卡,而一分钟约打一下,一大卡是4焦耳。
  868. // //现在大概是2s 打一下,1.875/30
  869. // // this.calorie = Math.floor((10 * 1.875) / (4*30));
  870. // this.calorie = puchConfig.getBoxingCalorie(10);
  871. // console.log("更新卡路里======:", this.calorie);
  872. // this.$emit('updateCalorie', this.calorie);
  873. // }
  874. this.hitCount = this.ZCount + this.LCount + this.RCount;
  875. this.addCount = this.addZCount + this.addLCount + this.addRCount;
  876. this.calorie = puchConfig.getBoxingCalorie(this.addCount);
  877. //10 大卡,为一个周期 分40份
  878. console.log("this.calorie:", this.calorie, this.calorie * 4);
  879. this.powerCount = parseInt(this.calorie * 4);
  880. }
  881. },
  882. updateData() {
  883. if (!this.bUpdate || !this.bPlay) return;
  884. //1.求出z 和 x 的加速度矢量
  885. //z轴的重力加速度矢量分量
  886. // this.calZVector = (Math.cos(this.xO / 180 * Math.PI) * 9.8);
  887. //x轴的重力加速度的矢量分量
  888. // if (this.yA > 9.8)
  889. // this.yA = 9.8;
  890. // let tempXVector = Math.pow(9.8, 2) - (Math.pow(this.calZVector, 2) + Math.pow(this.yA, 2));
  891. // this.calXVector = Math.sqrt(Math.abs(tempXVector));
  892. //2.当前的加速度矢量减去分量,就是打击的加速度
  893. // let tempZ = Math.abs(this.zA) - Math.abs(this.calZVector);
  894. // let tempX = Math.abs(this.xA) - Math.abs(this.calXVector);
  895. let tempZ = Math.abs(this.zA);
  896. let tempX = Math.abs(this.xA);
  897. //3.判断 那个轴的打击方向,就走哪个轴的计算流程
  898. //直拳判断
  899. let zAcc = Math.abs(this.zA) - Math.abs(this.oldzA);
  900. let leftAcc = Math.abs(this.xA) - Math.abs(this.oldxA);
  901. let rightAcc = this.xA - this.oldxA;
  902. let tempLimit = puchConfig.SENDITIVITY; //灵敏度
  903. //判断方位,用比值 直拳方向 和 左右方向 比。
  904. //如果比值相同 等于约定的数值,以1为标准,则是正勾拳
  905. if (Math.abs(leftAcc) != 0) {
  906. let tempDirection = Math.abs(zAcc) / Math.abs(leftAcc);
  907. if (tempDirection > this.angleRatio) {
  908. if (zAcc > tempLimit && this.zA < -tempLimit) {
  909. if (this.bUpdateOnce)
  910. return;
  911. console.log("走直拳");
  912. this.bUpdateOnce = true;
  913. let _endPower = Math.abs(tempZ) * this.mass;
  914. this.onHit("zLCount", tempZ, Math.ceil(_endPower));
  915. // console.log("zLCount:", this.zA, leftAcc, rightAcc, zAcc);
  916. // console.log("xA:", this.xA, " zA:", this.zA, " leftAcc:", leftAcc, " rightAcc:", rightAcc, " zAcc:", zAcc);
  917. }
  918. } else {
  919. if ((leftAcc > tempLimit || zAcc > tempLimit) && this.xA > tempLimit) {
  920. if (this.bUpdateOnce)
  921. return;
  922. console.log("走左勾拳");
  923. this.bUpdateOnce = true;
  924. let _endPower = (Math.abs(tempX) + Math.abs(tempZ)) * this.mass;
  925. this.onHit("xRCount", tempX, Math.ceil(_endPower));
  926. // console.log("xRCount:", this.xA, leftAcc, rightAcc);
  927. // console.log("xA:", this.xA, " zA:", this.zA, " leftAcc:", leftAcc, " rightAcc:", rightAcc, " zAcc:", zAcc);
  928. }
  929. if ((rightAcc < -tempLimit || zAcc > tempLimit) && this.xA < -tempLimit) {
  930. if (this.bUpdateOnce)
  931. return;
  932. console.log("走右勾拳");
  933. this.bUpdateOnce = true;
  934. let _endPower = (Math.abs(tempX) + Math.abs(tempZ)) * this.mass;
  935. this.onHit("xLCount", tempX, Math.ceil(_endPower));
  936. // console.log("xLCount:", this.xA, leftAcc, rightAcc);
  937. // console.log("xA:", this.xA, " zA:", this.zA, " leftAcc:", leftAcc, " rightAcc:", rightAcc, " zAcc:", zAcc);
  938. }
  939. }
  940. }
  941. this.oldxA = this.xA;
  942. this.oldzA = this.zA;
  943. if (!this.bDelayOnce && this.bUpdateOnce) {
  944. this.bDelayOnce = true;
  945. setTimeout(() => {
  946. this.bUpdateOnce = false;
  947. this.bDelayOnce = false;
  948. }, 500);
  949. }
  950. },
  951. _efRandomIndex(res) {
  952. console.log("_efRandomIndex:", res);
  953. this.efRandomObj = res;
  954. if (res.direction == "xRCount") {
  955. //左勾拳音效
  956. this.angleRatio = 10;
  957. } else if (res.direction == "xLCount") {
  958. this.angleRatio = 10;
  959. } else if (res.direction == "zLCount") {
  960. this.angleRatio = 0.5;
  961. }
  962. setTimeout(() => {
  963. if (res.direction == "xRCount") {
  964. //左勾拳音效
  965. this.hookAudioContext.stop();
  966. this.hookAudioContext.src = this.leftHookUrl;
  967. this.hookAudioContext.play();
  968. } else if (res.direction == "xLCount") {
  969. this.hookAudioContext.stop();
  970. this.hookAudioContext.src = this.rightHookUrl;
  971. this.hookAudioContext.play();
  972. } else if (res.direction == "zLCount") {
  973. this.hookAudioContext.stop();
  974. this.hookAudioContext.src = this.straightHookUrl;
  975. this.hookAudioContext.play();
  976. }
  977. }, 2000);
  978. },
  979. }
  980. }
  981. </script>
  982. <style>
  983. /* Loader Bar */
  984. .vertical-container {
  985. position: absolute;
  986. top: -50px;
  987. left: 0;
  988. right: 0;
  989. /* bottom: 0; */
  990. display: flex;
  991. /* flex-direction: column; */
  992. justify-content: space-between;
  993. /* border: 1rpx solid #000000; */
  994. pointer-events: none;
  995. }
  996. .vertical-bar {
  997. /* list-style: none; */
  998. /* height: 570px; */
  999. /* width: 100%; */
  1000. /* border: 1rpx solid #007AFF; */
  1001. /* margin: 0 20rpx; */
  1002. display: flex;
  1003. flex-direction: column-reverse;
  1004. /* justify-content: space-between; */
  1005. }
  1006. .vertical-child {
  1007. /* position: relative; */
  1008. width: 70rpx;
  1009. height: 20rpx;
  1010. margin-top: 6px;
  1011. display: flex;
  1012. /* align-content: center; */
  1013. justify-content: space-between;
  1014. }
  1015. .vertical-text {
  1016. color: #FFFFFF;
  1017. font-size: 8px;
  1018. }
  1019. .text-hidden {
  1020. visibility: hidden;
  1021. }
  1022. .vertical-active {
  1023. background-color: #FFFFFF;
  1024. width: 30rpx;
  1025. height: 100%;
  1026. }
  1027. .vertical-inactive {
  1028. width: 30rpx;
  1029. height: 100%;
  1030. background: rgba(144, 141, 246, 1);
  1031. }
  1032. .boxing-count-bg {
  1033. border-radius: 45rpx;
  1034. background-color: rgba(0, 0, 0, 0.1);
  1035. width: 160rpx;
  1036. height: 60rpx;
  1037. font-size: 22px;
  1038. font-weight: bold;
  1039. color: #FFFFFF;
  1040. line-height: 60rpx;
  1041. }
  1042. #loadbar {
  1043. list-style: none;
  1044. width: 400rpx;
  1045. margin: 0 20rpx;
  1046. }
  1047. #loadbar-child {
  1048. float: left;
  1049. position: relative;
  1050. width: 60rpx;
  1051. height: 10rpx;
  1052. margin-left: 1px;
  1053. background: rgba(255, 255, 255, 0.5);
  1054. }
  1055. #loadbar-child:first-child {
  1056. margin-left: 0;
  1057. }
  1058. .bar {
  1059. background-color: #FFFFFF;
  1060. width: 60rpx;
  1061. height: 10rpx;
  1062. }
  1063. .show-png {
  1064. width: 78rpx;
  1065. height: 78rpx;
  1066. margin: 0 10px;
  1067. }
  1068. .boxing-png {
  1069. margin-top: 40rpx;
  1070. width: 133rpx;
  1071. height: 133rpx;
  1072. transition: transform 0.15s;
  1073. }
  1074. .boxing-change {
  1075. transform: scale(1.58);
  1076. }
  1077. .boxing-post-talkbubble {
  1078. margin-top: 30px;
  1079. width: 260px;
  1080. height: 40px;
  1081. background: rgba(255, 255, 255, 0.13);
  1082. position: relative;
  1083. border-radius: 4px;
  1084. font-size: 14px;
  1085. color: #FFFFFF;
  1086. line-height: 40px;
  1087. }
  1088. .boxing-post-talkbubble:before {
  1089. content: "";
  1090. position: absolute;
  1091. bottom: 100%;
  1092. left: 120px;
  1093. width: 0;
  1094. height: 0;
  1095. border-bottom: 13px solid rgba(255, 255, 255, 0.13);
  1096. border-right: 10px solid transparent;
  1097. border-left: 10px solid transparent;
  1098. }
  1099. .boxingTimer {
  1100. position: absolute;
  1101. top: -60rpx;
  1102. left: 0;
  1103. right: 0;
  1104. }
  1105. </style>