parkour.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. var timerArray = [],
  2. userOpenid = '',
  3. speedNormal = 0,
  4. speedQuick = 0,
  5. speedSlow = 0,
  6. runSpeed = 0,
  7. runDistance = 0, //100米长度
  8. obstacleTimer = '', //障碍物作用的定时器
  9. startLineHeight = 0,
  10. swipeLock = true, //人物滑动锁定
  11. giftListLock = false, //礼品列表弹出锁定
  12. vertigoMs = 2000, //眩晕毫秒数
  13. manAnimateTimer = 0, //人物动画定时器
  14. isSubmitUserInfo = false, //是否提交过用户信息
  15. afId = '';
  16. //初始化AnimationFrame
  17. (function() {
  18. var lastTime = 0;
  19. var vendors = ['webkit', 'moz'];
  20. for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
  21. window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
  22. window.cancelAnimationFrame =
  23. window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
  24. }
  25. }());
  26. $(document).ready(function() {
  27. $('body').show();
  28. _initLoader();
  29. _initData();
  30. });
  31. var vm = avalon.define({
  32. $id: 'parkour',
  33. alertText: '',
  34. runwayPosition: 50, //跑到位置
  35. timeCount: 0, //计时毫秒数
  36. costSeconds: 0, //跑步时显示的时间
  37. manState: 'nm', //人物状态
  38. manToggleType: 1, //人物动画帧
  39. manToggleInterval: 100, //人物动画切换毫秒
  40. curIntegral: 0, //当前积分
  41. totalLife: 100, //总生命
  42. totalIntegral: 0, //总积分
  43. preloadPercent: 0, //预加载百分比
  44. friendsList: [], //帮助好友列表
  45. friendsNum: 0, //帮助好友人数
  46. userName: '', //用户名称
  47. vertigoTime: '2s', //眩晕作用剩余时间
  48. baseScore: 0, //基础分数
  49. timeScore: 0, //时间奖励
  50. giftList: [], //总共奖品列表
  51. myGiftList: [], //我的礼品列表
  52. broadcastList: [], //公告列表
  53. totalGameScore: 0, //本次游戏获得的总积分
  54. accidentPrompt: '', //意外提示
  55. frameRate: 0 //帧率
  56. });
  57. //跑步计时
  58. function _runTime() {
  59. var runTimerId = setInterval(function() {
  60. vm.timeCount += 31;
  61. vm.costSeconds = _formatSecond(vm.timeCount);
  62. }, 31);
  63. timerArray.push(runTimerId);
  64. }
  65. function _formatSecond(ms) {
  66. return Math.floor(ms / 1000) + '.' + Math.floor((ms % 1000) / 100) + ((ms % 10) > 0 ? (ms % 10) : 0);
  67. }
  68. //初始化跑步界面的组件尺寸
  69. function _initRunview() {
  70. $('#obstacle-prompt').height($('#obstacle-prompt').width() * 160 / 300);
  71. }
  72. //预加载图片
  73. function _initLoader() {
  74. var loader = new resLoader({
  75. resources : [
  76. './img/countdown_bg_1.png',
  77. './img/countdown_bg_2.png',
  78. './img/countdown_bg_3.png',
  79. './img/destination_bg.png',
  80. './img/new_bg1.jpg',
  81. './img/person_nm_1.png',
  82. './img/person_nm_2.png',
  83. './img/show.png',
  84. './img/show_btn.png',
  85. ],
  86. onProgress : function(current, total) {
  87. vm.preloadPercent = Math.floor(current / total * 100);
  88. },
  89. onComplete : function(total) {
  90. $('#load-progress').hide();
  91. $('#main-bottom').show();
  92. //图片加载完成后才能加载canvas
  93. gameMonitor.init();
  94. }
  95. });
  96. loader.start();
  97. }
  98. function _initData() {
  99. var deviceWidth = $(window).width();
  100. $('body').height($(window).height());
  101. }
  102. //初始化首页广播
  103. function _initBroadcast() {
  104. var marginLeft = 0,
  105. curIndex = 0;
  106. $('#broadcast').css('visibility', 'hidden');
  107. setTimeout(function () {
  108. $('#broadcast').css('visibility', 'visible');
  109. }, 500);
  110. var broadcastTimer = setInterval(function () {
  111. if ($('#broadcast .broadcast-slide').length < 1) {
  112. return false;
  113. }
  114. var wrapperWidth = 0;
  115. $('#broadcast .broadcast-slide').each(function () {
  116. //因为每个slide的margin-left为20px,所以这里要加20,outerWidth没生效
  117. wrapperWidth += ($(this).width() + 20);
  118. });
  119. $('#broadcast .broadcast-wrapper').width(wrapperWidth);
  120. marginLeft -= 3;
  121. $('#broadcast .broadcast-wrapper').css('margin-left', marginLeft + 'px');
  122. var secondSlideLeft = $('#broadcast .broadcast-slide').eq(curIndex + 1).offset().left;
  123. if (secondSlideLeft < 0) {
  124. var html = '<div class="broadcast-slide">' + $('#broadcast .broadcast-slide').eq(curIndex).html() + '</div>';
  125. $('#broadcast .broadcast-wrapper').append(html);
  126. var lastSlideWidth = $('#broadcast .broadcast-slide').eq(curIndex).width() + 20,
  127. curWrapperWidth = $('#broadcast .broadcast-wrapper').width();
  128. $('#broadcast .broadcast-wrapper').width(curWrapperWidth + lastSlideWidth);
  129. curIndex++;
  130. }
  131. }, 100);
  132. timerArray.push(broadcastTimer);
  133. }
  134. //结束游戏
  135. function _gameover() {
  136. $('#show').show();
  137. $('#popup-container').show();
  138. document.getElementById("mediaTwo").play()
  139. document.getElementById("mediaTwo").muted = false
  140. document.getElementById("mediaId").pause()
  141. document.getElementById("mediaId").muted = true
  142. _resizePopup();
  143. }
  144. function _resizePopup() {
  145. // $('#popup-rule').height($('#popup-rule').width() * 829 / 581);
  146. // $('#popup-friend').height($('#popup-friend').width() * 729 / 581);
  147. // $('#popup-lucky').height($('#popup-lucky').width() * 709 / 583);
  148. $('#popup-game-result').height($('#popup-game-result').width() * 709 / 583);
  149. $('#gift-list').height($('#gift-list').width() * 750 / 501);
  150. $('#draw-result').height($('#draw-result').width());
  151. $('#popup-my-gift').height($('#popup-my-gift').width() * 709 /583);
  152. $('#draw-failed').height($('#draw-failed').width() * 360 / 501);
  153. $('#draw-result-real').height($('#draw-result-real').width() * 841 / 581);
  154. }
  155. function _alert(content) {
  156. vm.alertText = content;
  157. $('#alert').show();
  158. setTimeout(function () {
  159. $('#alert').hide();
  160. }, 2000);
  161. }
  162. //游戏规则
  163. function handleShowRule() {
  164. $('#popup-rule').show();
  165. $('#popup-container').show();
  166. _resizePopup();
  167. }
  168. //帮助好友
  169. function handleShowFriends() {
  170. $('#popup-friend').show();
  171. $('#popup-container').show();
  172. _resizePopup();
  173. }
  174. //打开抽奖
  175. function handleShowLucky() {
  176. $('#popup-lucky').show();
  177. $('#popup-container').show();
  178. _resizePopup();
  179. }
  180. //返回首页,还原数据
  181. function handleReturnMain() {
  182. if (manAnimateTimer) {
  183. clearInterval(manAnimateTimer);
  184. manAnimateTimer = 0;
  185. }
  186. $('#running-man').removeClass('left').removeClass('right');
  187. $('#count-down').attr('class', 'bg-3');
  188. vm.manState = 'nm';
  189. vm.totalGameScore = vm.costSeconds = vm.timeCount = vm.runwayPosition = vm.baseScore = vm.curIntegral = vm.timeScore = 0;
  190. $('#view-main').show();
  191. $('#view-game').hide();
  192. handleClosePopup();
  193. _initBroadcast();
  194. gameMonitor.init();
  195. }
  196. var blockData = {
  197. star: {
  198. width: 0.4,
  199. height: 79 / 85,
  200. src: './img/article/star1.png'
  201. },
  202. speed: {
  203. width: 0.34,
  204. height: 78 / 70,
  205. src: './img/article/star1.png'
  206. },
  207. roadblock: {
  208. width: 0.4,
  209. height: 97 / 97,
  210. src: './img/article/bomb1.png'
  211. },
  212. bomb: {
  213. width: 0.5,
  214. height: 97 / 93,
  215. src: './img/article/bomb1.png'
  216. },
  217. pool: {
  218. width: 0.6,
  219. height: 90 / 98,
  220. src: './img/article/car1.png'
  221. },
  222. car: {
  223. width: 0.6,
  224. height: 90 / 98,
  225. src: './img/article/car1.png'
  226. }
  227. }
  228. var Block = function (type, left, top, width, height, src, id) {
  229. var blockImg = new Image();
  230. blockImg.src = src;
  231. this.type = type;
  232. this.left = left;
  233. this.top = top;
  234. this.width = width;
  235. this.height = height;
  236. this.src = blockImg;
  237. this.id = id;
  238. this.isShow = false;
  239. }
  240. Block.prototype.paint = function(ctx){
  241. var _this = this;
  242. this.src.onload = function () {
  243. ctx.drawImage(_this.src, _this.left, _this.top, _this.width, _this.height);
  244. }
  245. };
  246. Block.prototype.move = function(ctx) {
  247. this.top += gameMonitor.bgSpeed;
  248. if(this.top > gameMonitor.h){
  249. gameMonitor.blockList[this.id] = null;
  250. }
  251. else if (this.top > 0) {
  252. this.isShow = true;
  253. ctx.drawImage(this.src, this.left, this.top, this.width, this.height);
  254. }
  255. };
  256. var Scale = function (ordinate, num) {
  257. this.ordinate = ordinate;
  258. this.text = '-' + num + 'm';
  259. }
  260. Scale.prototype.move = function(ctx) {
  261. this.ordinate += gameMonitor.bgSpeed;
  262. if (this.ordinate > 0 && this.ordinate < gameMonitor.h) {
  263. ctx.fillText(this.text, 0, this.ordinate);
  264. }
  265. };
  266. var gameMonitor = {
  267. w: $(window).width(),
  268. h: $(window).height(),
  269. bgDistance: 0,
  270. bgAdditionHeight: 0, //bgAddition是跑道附加素材
  271. bgAdditionDistance: 0,
  272. runner: {},
  273. frameCount: 0,
  274. swipeLock: true,
  275. totalDistance: 0,
  276. runwayLength: 0,
  277. bgSpeed: 0,
  278. baseSpeed: 0, //基础速度,bgSpeed在此基础上根据帧率发生变化
  279. blockList: [],
  280. runActTimer: '',
  281. startLineHeight: 0,
  282. scaleHeight: 0,
  283. scaleList: [],
  284. isInit: false,
  285. speedNormal: 0,
  286. speedFast: 0,
  287. speedSlow: 0,
  288. collisionTimer: '',
  289. endLine: {},
  290. rafId: '',
  291. lastTime: 0,
  292. init: function () {
  293. var _this = this, html = '';
  294. this.lastTime = 0;
  295. this.w = $(window).width();
  296. this.h = $(window).height();
  297. if (!this.isInit) {
  298. html += '<canvas id="stage" width="' + this.w + '" height="' + this.h + '"></canvas>';
  299. $('#view-game').append(html);
  300. }
  301. var canvas = document.getElementById('stage');
  302. var ctx = canvas.getContext('2d');
  303. ctx.clearRect(0, 0, _this.w, _this.h);
  304. this.totalDistance = this.runwayLength = this.w * 15; //跑道长度是宽度15倍
  305. this.baseSpeed = this.speedNormal = this.bgSpeed = Math.round(this.runwayLength / 700); //25秒完成游戏,一秒60帧
  306. this.speedFast = Math.round(this.speedNormal * 7 / 4);
  307. this.speedSlow = Math.round(this.speedNormal / 4);
  308. this.startLineHeight = this.w * 120 / 640;
  309. this.scaleHeight = this.runwayLength / 20;
  310. this.initBg(ctx);
  311. this.initEndline();
  312. if (!this.isInit) {
  313. this.initListener(ctx);
  314. this.isInit = true;
  315. }
  316. },
  317. initBg: function (ctx) {
  318. var _this = this, bgAddition = new Image();
  319. this.bgDistance = 0;
  320. this.bg = new Image();
  321. this.bg.src = './img/new_bg1.jpg';
  322. this.bg.onload= function () {
  323. ctx.drawImage(_this.bg, 0, 0, _this.w, _this.h);
  324. }
  325. bgAddition.src = './img/new_bg1.jpg';
  326. this.bgAddition = bgAddition;
  327. this.bgAdditionHeight = this.w * 721 / 640;
  328. this.bgAdditionDistance = 0 - this.bgAdditionHeight;
  329. this.initScale(ctx);
  330. this.initBlock(ctx, function (ctx) {
  331. _this.initRunner(ctx);
  332. });
  333. },
  334. initEndline: function (ctx) {
  335. this.endLine = new Image();
  336. this.endLine.src = './img/destination_bg.png';
  337. this.endLine.height = this.w / 660 * 109;
  338. },
  339. initScale: function (ctx) {
  340. //刻度高度
  341. ctx.font = 'bold 18px 苹方';
  342. ctx.fillStyle = '#d26b60';
  343. ctx.fillText('-5m', 0, this.h - this.startLineHeight - this.scaleHeight);
  344. ctx.fillText('-10m', 0, this.h - this.startLineHeight - this.scaleHeight * 2);
  345. this.scaleList = [];
  346. for (var i = 1; i <= 20; i++) {
  347. var ordinate = this.h - this.startLineHeight - this.scaleHeight * i;
  348. var scaleItem = new Scale(ordinate, 5 * i);
  349. this.scaleList.push(scaleItem);
  350. }
  351. },
  352. initRunner: function (ctx) {
  353. var _this = this;
  354. this.runner = new Object();
  355. //按照图片尺寸设定人物宽高
  356. this.runner.size = [this.w * 0.2, this.w * 0.2 * 190 / 130];
  357. this.runner.centerPositon = (this.w - this.runner.size[0]) / 2;
  358. this.runner.leftPosition = (this.w / 3 - this.runner.size[0]) / 2;
  359. this.runner.rightPositon = this.w / 3 * 2 + (this.w / 3 - this.runner.size[0]) / 2;
  360. this.runner.positon = [this.runner.centerPositon, this.h - this.runner.size[1]];
  361. this.runner.animateState = 1;
  362. var runnerImg = {
  363. normal: './img/person_nm_'
  364. // fast: './img/person_sp_',
  365. // slow: './img/person_sl_',
  366. // stop: './img/person_st_',
  367. // die: './img/person_die_'
  368. }
  369. for (var key in runnerImg) {
  370. this.runner[key] = new Object();
  371. for (var i = 1; i < 3; i++) {
  372. this.runner[key][i] = new Image();
  373. this.runner[key][i].src = runnerImg[key] + i + '.png';
  374. }
  375. }
  376. this.runner.curState = 'normal';
  377. this.runner.normal[1].onload = function () {
  378. ctx.drawImage(_this.runner.normal[1], _this.runner.positon[0], _this.runner.positon[1], _this.runner.size[0], _this.runner.size[1]);
  379. }
  380. },
  381. initListener: function (ctx) {
  382. var _this = this;
  383. $('#btn-begin').click(function () {
  384. document.getElementById("mediaId").play()
  385. document.getElementById("mediaId").muted = false
  386. $('#view-main').hide();
  387. $('#view-game').show();
  388. $('#count-down').show();
  389. var readyCountNum = 3;
  390. var readyCountTimer = setInterval(function () {
  391. readyCountNum--;
  392. if (readyCountNum == 0) {
  393. clearInterval(readyCountTimer);
  394. $('#count-down').hide();
  395. _this.run(ctx);
  396. _runTime();
  397. } else {
  398. $('#count-down').attr('class', 'bg-' + readyCountNum);
  399. }
  400. }, 1000);
  401. });
  402. this.initTouchEvent();
  403. },
  404. initTouchEvent: function () {
  405. var _this = this;
  406. touch.on('#view-game', 'touchstart', function (ev) {
  407. ev.preventDefault();
  408. });
  409. touch.on('#view-game', 'swipeup', function(ev) {
  410. ev.preventDefault();
  411. });
  412. touch.on('#view-game', 'swipedown', function(ev) {
  413. ev.preventDefault();
  414. });
  415. touch.on('#view-game', 'swipeleft', function(ev) {
  416. ev.preventDefault();
  417. if (_this.swipeLock) {
  418. return false;
  419. }
  420. if (_this.runner.swipeState == 'left') {
  421. return false;
  422. } else if (_this.runner.swipeState == 'right') {
  423. _this.runner.swipeState = 'center';
  424. _this.runner.positon[0] = _this.runner.centerPositon;
  425. } else {
  426. _this.runner.swipeState = 'left';
  427. _this.runner.positon[0] = _this.runner.leftPosition;
  428. }
  429. });
  430. touch.on('#view-game', 'swiperight', function(ev) {
  431. ev.preventDefault();
  432. if (_this.swipeLock) {
  433. return false;
  434. }
  435. if (_this.runner.swipeState == 'left') {
  436. _this.runner.swipeState = 'center';
  437. _this.runner.positon[0] = _this.runner.centerPositon;
  438. } else if (_this.runner.swipeState == 'right') {
  439. return false;
  440. } else {
  441. _this.runner.swipeState = 'right';
  442. _this.runner.positon[0] = _this.runner.rightPositon;
  443. }
  444. });
  445. },
  446. initBlock: function (ctx, callback) {
  447. var _this = this;
  448. _this.blockList = [];
  449. var blockIndex = 0,
  450. runwayDataList = [];
  451. if (Math.random() > 0.5) {
  452. runwayDataList = [[{"type":"star","row":6},{"type":"roadblock","row":13},{"type":"star","row":22},{"type":"pool","row":26},{"type":"star","row":35},{"type":"speed","row":37},{"type":"speed","row":44},{"type":"star","row":56},{"type":"car","row":71},{"type":"speed","row":80},{"type":"star","row":83},{"type":"pool","row":88},{"type":"pool","row":97},{"type":"star","row":99}],[{"type":"star","row":1},{"type":"star","row":5},{"type":"star","row":8},{"type":"star","row":10},{"type":"star","row":16},{"type":"star","row":45},{"type":"star","row":51},{"type":"pool","row":58},{"type":"pool","row":65},{"type":"star","row":68},{"type":"star","row":73},{"type":"star","row":75},{"type":"star","row":76},{"type":"speed","row":77},{"type":"speed","row":84},{"type":"pool","row":90},{"type":"star","row":97}],[{"type":"roadblock","row":9},{"type":"roadblock","row":25},{"type":"star","row":28},{"type":"star","row":35},{"type":"star","row":37},{"type":"star","row":38},{"type":"speed","row":41},{"type":"star","row":42},{"type":"star","row":48},{"type":"roadblock","row":55},{"type":"star","row":58},{"type":"star","row":64},{"type":"pool","row":72},{"type":"star","row":74},{"type":"pool","row":78},{"type":"star","row":83},{"type":"bomb","row":86}]];
  453. } else {
  454. runwayDataList = [[{"type":"star","row":1},{"type":"star","row":15},{"type":"speed","row":31},{"type":"speed","row":39},{"type":"star","row":41},{"type":"star","row":45},{"type":"star","row":49},{"type":"star","row":55},{"type":"pool","row":61},{"type":"star","row":63},{"type":"speed","row":70},{"type":"star","row":73},{"type":"car","row":76},{"type":"star","row":79},{"type":"star","row":81},{"type":"roadblock","row":84},{"type":"star","row":88},{"type":"star","row":89},{"type":"speed","row":94}],[{"type":"star","row":1},{"type":"star","row":8},{"type":"star","row":30},{"type":"pool","row":34},{"type":"star","row":38},{"type":"star","row":39},{"type":"bomb","row":46},{"type":"star","row":49},{"type":"pool","row":52},{"type":"star","row":57},{"type":"speed","row":59},{"type":"star","row":61},{"type":"pool","row":75},{"type":"star","row":79},{"type":"star","row":82},{"type":"roadblock","row":87},{"type":"speed","row":96}],[{"type":"star","row":5},{"type":"star","row":8},{"type":"pool","row":21},{"type":"star","row":23},{"type":"star","row":25},{"type":"star","row":31},{"type":"pool","row":35},{"type":"roadblock","row":55},{"type":"roadblock","row":64},{"type":"pool","row":72},{"type":"star","row":76},{"type":"pool","row":82}]];
  455. }
  456. $.each(runwayDataList, function(runwayIndex, runwayData) {
  457. var baseLeftDistance = 0, lineWidth = _this.w / 3;
  458. if (runwayIndex == 0) {
  459. baseLeftDistance = 0;
  460. } else if (runwayIndex == 1) {
  461. baseLeftDistance = lineWidth;
  462. } else {
  463. baseLeftDistance = lineWidth * 2;
  464. }
  465. $.each(runwayData, function(index, val) {
  466. var curBlockData = blockData[val.type],
  467. itemWidth = curBlockData.width * lineWidth;
  468. var blockItem = new Block(
  469. val.type,
  470. (lineWidth - itemWidth) / 2 + baseLeftDistance,
  471. _this.h - (val.row / 100) * _this.runwayLength - _this.startLineHeight,
  472. curBlockData.width * lineWidth,
  473. itemWidth * curBlockData.height,
  474. curBlockData.src,
  475. blockIndex++
  476. );
  477. _this.blockList.push(blockItem);
  478. });
  479. });
  480. for (var i = 0; i < _this.blockList.length; i++) {
  481. var blockItem = _this.blockList[i];
  482. if (blockItem) {
  483. blockItem.paint(ctx);
  484. }
  485. }
  486. callback(ctx);
  487. },
  488. rollBg: function (ctx) {
  489. this.bgDistance += this.bgSpeed;
  490. if (this.bgDistance < this.h) {
  491. ctx.drawImage(this.bg, 0, this.bgDistance, this.w, this.h);
  492. }
  493. this.bgAdditionDistance += this.bgSpeed;
  494. for (var i = 0; i < 100; i++) {
  495. ctx.drawImage(this.bgAddition, 0, this.bgAdditionDistance - i * this.bgAdditionHeight, this.w, this.bgAdditionHeight);
  496. if (this.bgAdditionDistance - i * this.bgAdditionHeight <= 0) {
  497. break;
  498. }
  499. }
  500. },
  501. drawRunner: function (ctx) {
  502. if (this.frameCount % 10 == 0) {
  503. this.runner.animateState == 1 ? this.runner.animateState = 2 : this.runner.animateState = 1;
  504. }
  505. ctx.drawImage(this.runner[this.runner.curState][this.runner.animateState], this.runner.positon[0], this.runner.positon[1], this.runner.size[0], this.runner.size[1]);
  506. },
  507. drawScale: function () {
  508. ctx.fillText('-10m', 0, this.h - this.startLineHeight - this.scaleHeight * 2);
  509. },
  510. //碰撞检测
  511. collisionTest: function () {
  512. for (var i = 0; i < this.blockList.length; i++) {
  513. if (this.blockList[i] && this.blockList[i].isShow) {
  514. var blockItem = this.blockList[i],
  515. //小人中心点坐标
  516. runnerHoriCenterCord = [this.runner.positon[0] + this.runner.size[0] / 2, this.runner.positon[1] + this.runner.size[1] / 2],
  517. //障碍物中心点坐标
  518. blockHoriCenterCord = [blockItem.left + blockItem.width / 2, blockItem.top + blockItem.height / 2];
  519. if (Math.abs(runnerHoriCenterCord[0] - blockHoriCenterCord[0]) < (this.runner.size[0] + blockItem.width) / 2 && Math.abs(runnerHoriCenterCord[1] - blockHoriCenterCord[1]) < (this.runner.size[1] + blockItem.height) / 2) {
  520. this.handleCollision(blockItem.type);
  521. this.blockList[i] = null;
  522. }
  523. }
  524. }
  525. },
  526. handleCollision: function (type) {
  527. var _this = this;
  528. if (type == 'star') {
  529. vm.curIntegral++;
  530. } else if (type == 'speed') {
  531. vm.curIntegral++;
  532. // this.baseSpeed = this.speedFast;
  533. // this.runner.curState = 'fast';
  534. // this.collisionRecover();
  535. } else if (type == 'roadblock') {
  536. vm.curIntegral++;
  537. // this.baseSpeed = 0;
  538. // this.runner.curState = 'stop';
  539. // this.swipeLock = true;
  540. // $('#obstacle-prompt').show();
  541. // $('#obstacle-prompt').height($('#obstacle-prompt').width() * 160 / 300);
  542. // var vertigoTimer = setInterval(function () {
  543. // vertigoMs -= 100;
  544. // vm.vertigoTime = vertigoMs % 1000 > 0 ? vertigoMs / 1000 : vertigoMs / 1000 + '.0';
  545. // if (vertigoMs <= 0) {
  546. // vm.manState = 'nm';
  547. // _this.swipeLock = false;
  548. // $('#obstacle-prompt').hide();
  549. // vertigoMs = 2000;
  550. // clearInterval(vertigoTimer);
  551. // }
  552. // }, 100);
  553. // this.collisionRecover();
  554. } else if (type == 'pool') {
  555. vm.curIntegral++;
  556. // this.baseSpeed = this.speedSlow;
  557. // this.runner.curState = 'slow';
  558. // this.collisionRecover();
  559. } else if (type == 'car' || type == 'bomb') {
  560. vm.curIntegral+=5
  561. // this.baseSpeed = 0;
  562. // this.runner.size = [this.w * 0.2, this.w * 0.2 * 159 / 143];
  563. // this.runner.curState = 'die';
  564. // this.swipeLock = true;
  565. // setTimeout(function () {
  566. // _this.endRun();
  567. // }, 300);
  568. }
  569. },
  570. collisionRecover: function () {
  571. var _this = this;
  572. if (this.collisionTimer) {
  573. clearTimeout(this.collisionTimer);
  574. }
  575. this.collisionTimer = setTimeout(function () {
  576. _this.runner.curState = 'normal';
  577. _this.baseSpeed = _this.speedNormal;
  578. _this.swipeLock = false;
  579. }, 2000);
  580. },
  581. drawEndLine: function (ctx) {
  582. if (this.runwayLength + this.runner.size[1] + this.h > 0) {
  583. ctx.drawImage(this.endLine, 0, 0 - (this.runwayLength + this.runner.size[1]) + this.h, this.w, this.endLine.height);
  584. }
  585. },
  586. run: function (ctx) {
  587. var _this = this;
  588. _this.swipeLock = false;
  589. function animateRun () {
  590. var curTime = new Date().getTime();
  591. if (_this.lastTime > 0) {
  592. _this.bgSpeed = _this.baseSpeed * (60 * (curTime - _this.lastTime) / 1000);
  593. }
  594. _this.lastTime = curTime;
  595. //注意顺序,先画背景,再画终点线,再画刻度,再画障碍物,最后画人物
  596. ctx.clearRect(0, 0, _this.w, _this.h);
  597. _this.rollBg(ctx);
  598. _this.drawEndLine(ctx);
  599. for (var i = 0; i < _this.scaleList.length; i++) {
  600. var scaleItem = _this.scaleList[i];
  601. if (scaleItem) {
  602. scaleItem.move(ctx);
  603. }
  604. }
  605. for (var i = 0; i < _this.blockList.length; i++) {
  606. var blockItem = _this.blockList[i];
  607. if (blockItem) {
  608. blockItem.move(ctx);
  609. }
  610. }
  611. _this.frameCount++;
  612. _this.drawRunner(ctx);
  613. if (_this.frameCount % 5 == 0) {
  614. _this.collisionTest();
  615. }
  616. _this.runwayLength -= _this.bgSpeed;
  617. if (_this.runwayLength + _this.runner.size[1] <= 0) {
  618. _this.endRun();
  619. return false;
  620. }
  621. _this.rafId = window.requestAnimationFrame(animateRun);
  622. }
  623. animateRun();
  624. },
  625. endRun: function () {
  626. for (var i = 0; i < timerArray.length; i++) {
  627. clearInterval(timerArray[i]);
  628. }
  629. window.cancelAnimationFrame(this.rafId);
  630. this.swipeLock = true;
  631. //记录分数
  632. var surplusLength = this.runwayLength + this.runner.size[1] < 0 ? 0 : this.runwayLength + this.runner.size[1];
  633. vm.baseScore = Math.floor(80 * (1 - surplusLength / (this.totalDistance + this.runner.size[1])));
  634. if (surplusLength <= 0) {
  635. var totalTime = Math.ceil(parseFloat(vm.costSeconds));
  636. vm.timeScore = 20 - (totalTime > 25 ? totalTime - 25 : 0);
  637. }
  638. vm.totalGameScore = vm.baseScore + vm.curIntegral + vm.timeScore;
  639. vm.totalIntegral += vm.totalGameScore;
  640. _gameover();
  641. }
  642. }