Advertisement
Guest User

Untitled

a guest
May 24th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.75 KB | None | 0 0
  1. //= ============================================================================
  2. // PONG
  3. //= ============================================================================
  4. let timer, mode, p1HighScore, p2HighScore, e, mobileControls
  5.  
  6. Pong = {
  7.  
  8. Defaults: {
  9. width: 640, // logical canvas width (browser will scale to physical canvas size - which is controlled by @media css queries)
  10. height: 480, // logical canvas height (ditto)
  11. wallWidth: 12,
  12. paddleWidth: 12,
  13. paddleHeight: 60,
  14. paddleSpeed: 2, // should be able to cross court vertically in 2 seconds
  15. ballSpeed: 4, // should be able to cross court horizontally in 4 seconds, at starting speed ...
  16. ballAccel: 8, // ... but accelerate as time passes
  17. ballRadius: 5,
  18. sound: true
  19. },
  20.  
  21. Colors: {
  22. walls: 'white',
  23. ball: 'white',
  24. score: 'white',
  25. footprint: '#333',
  26. predictionGuess: 'yellow',
  27. predictionExact: 'red'
  28. },
  29.  
  30. Images: [
  31. 'images/press1.png',
  32. 'images/press2.png',
  33. 'images/winner.png'
  34. ],
  35.  
  36. Levels: [
  37. {aiReaction: 0.2, aiError: 40}, // 0: ai is losing by 8
  38. {aiReaction: 0.3, aiError: 50}, // 1: ai is losing by 7
  39. {aiReaction: 0.4, aiError: 60}, // 2: ai is losing by 6
  40. {aiReaction: 0.5, aiError: 70}, // 3: ai is losing by 5
  41. {aiReaction: 0.6, aiError: 80}, // 4: ai is losing by 4
  42. {aiReaction: 0.7, aiError: 90}, // 5: ai is losing by 3
  43. {aiReaction: 0.8, aiError: 100}, // 6: ai is losing by 2
  44. {aiReaction: 0.9, aiError: 110}, // 7: ai is losing by 1
  45. {aiReaction: 1.0, aiError: 120}, // 8: tie
  46. {aiReaction: 1.1, aiError: 130}, // 9: ai is winning by 1
  47. {aiReaction: 1.2, aiError: 140}, // 10: ai is winning by 2
  48. {aiReaction: 1.3, aiError: 150}, // 11: ai is winning by 3
  49. {aiReaction: 1.4, aiError: 160}, // 12: ai is winning by 4
  50. {aiReaction: 1.5, aiError: 170}, // 13: ai is winning by 5
  51. {aiReaction: 1.6, aiError: 180}, // 14: ai is winning by 6
  52. {aiReaction: 1.7, aiError: 190}, // 15: ai is winning by 7
  53. {aiReaction: 1.8, aiError: 200} // 16: ai is winning by 8
  54. ],
  55.  
  56. // -----------------------------------------------------------------------------
  57. startDemo: function () { this.start(0) },
  58. startSinglePlayer: function () { this.start(1) },
  59. startDoublePlayer: function () { this.start(2) },
  60.  
  61. initialize: function (runner, cfg) {
  62. Game.loadImages(Pong.Images, function (images) {
  63. if (window.DeviceOrientationEvent) {
  64. mobileControls = 1
  65. window.addEventListener('deviceorientation', this.deviceOrientationListener)
  66. } else {
  67. mobileControls = 0
  68. }
  69. this.cfg = cfg
  70. this.runner = runner
  71. this.width = runner.width
  72. this.height = runner.height
  73. this.images = images
  74. this.playing = false
  75. this.scores = [0, 0]
  76. this.menu = Object.construct(Pong.Menu, this)
  77. this.court = Object.construct(Pong.Court, this)
  78. this.leftPaddle = Object.construct(Pong.Paddle, this)
  79. this.rightPaddle = Object.construct(Pong.Paddle, this, true)
  80. this.ball = Object.construct(Pong.Ball, this)
  81. this.sounds = Object.construct(Pong.Sounds, this)
  82. this.runner.start()
  83. localforage.getItem('p1HighScore').then(function (value) {
  84. this.p1HighScore = value
  85. p1HighScore = value
  86. this.p1HSspan = document.getElementById('p1HighScore')
  87. this.p1HSspan.innerHTML = this.p1HighScore
  88. })
  89. localforage.getItem('p2HighScore').then(function (value) {
  90. this.p2HighScore = value
  91. p2HighScore = value
  92. console.log(this.p2HighScore)
  93. this.p2HSspan = document.getElementById('p2HighScore')
  94. this.p2HSspan.innerHTML = this.p1HighScore
  95. })
  96. this.startTime = 0
  97. this.duration = 0
  98. document.getElementById('timer').innerHTML = secToMin(60)
  99. }.bind(this))
  100. },
  101. deviceOrientationListener: function (event) {
  102. if (event.gamma > 20) {
  103. if (e !== undefined) {
  104. if (e.keyCode === Game.KEY.A) {
  105. e = new Event('keyup')
  106. e.keyCode = Game.KEY.A
  107. document.dispatchEvent(e)
  108. }
  109. }
  110. e = new Event('keydown')
  111. e.keyCode = Game.KEY.Q
  112. document.dispatchEvent(e)
  113. } else if (event.gamma < -20) {
  114. if (e !== undefined) {
  115. if (e.keyCode === Game.KEY.Q) {
  116. e = new Event('keyup')
  117. e.keyCode = Game.KEY.Q
  118. document.dispatchEvent(e)
  119. }
  120. }
  121. e = new Event('keydown')
  122. e.keyCode = Game.KEY.A
  123. console.log('keydown a')
  124. document.dispatchEvent(e)
  125. } else {
  126. if (e.keyCode === Game.KEY.A) {
  127. e = new Event('keyup')
  128. e.keyCode = Game.KEY.A
  129. document.dispatchEvent(e)
  130. } else if (e.keyCode === Game.KEY.Q) {
  131. e = new Event('keyup')
  132. e.keyCode = Game.KEY.Q
  133. document.dispatchEvent(e)
  134. }
  135. }
  136. },
  137. start: function (numPlayers) {
  138. if (!this.playing) {
  139. this.scores = [0, 0]
  140. this.playing = true
  141. this.leftPaddle.setAuto(numPlayers < 1, this.level(0))
  142. this.rightPaddle.setAuto(numPlayers < 2, this.level(1))
  143. this.ball.reset()
  144. this.runner.hideCursor()
  145. this.startTime = Date.now() / 1000
  146. this.duration = parseFloat(document.getElementById('duration').value) * 60
  147. timer = this.duration
  148. document.getElementById('timer').innerHTML = secToMin(timer)
  149. console.log(this.duration)
  150. this.timer = setInterval(function () {
  151. timer = timer - 1
  152. console.log(timer)
  153. document.getElementById('timer').innerHTML = secToMin(timer)
  154. }, 1000)
  155. }
  156. },
  157.  
  158. stop: function (ask) {
  159. if (this.playing) {
  160. if (!ask || this.runner.confirm('Abandon game in progress ?')) {
  161. this.playing = false
  162. this.leftPaddle.setAuto(false)
  163. this.rightPaddle.setAuto(false)
  164. this.runner.showCursor()
  165. clearInterval(this.timer)
  166. // this.endTime = Date.new()
  167. console.log(this.p1HighScore)
  168. console.log(this.scores[0])
  169. let p1Score = this.scores[0]
  170. let p2Score = this.scores[1]
  171. if (p1Score > p1HighScore) {
  172. p1HighScore = p1Score
  173. console.log('p1HighScore updated: ' + p1HighScore)
  174. localforage.setItem('p1HighScore', p1HighScore)
  175. document.getElementById('p1HighScore').innerHTML = p1HighScore
  176. } else if (p1HighScore === undefined) {
  177. p1HighScore = p1Score
  178. console.log('p1HighScore updated: ' + p1HighScore)
  179. localforage.setItem('p1HighScore', p1HighScore)
  180. document.getElementById('p1HighScore').innerHTML = p1HighScore
  181. }
  182. if (p2Score > p2HighScore) {
  183. p2HighScore = p2Score
  184. console.log('p2HighScore updated: ' + p2HighScore)
  185. localforage.setItem('p2HighScore', p2HighScore)
  186. document.getElementById('p2HighScore').innerHTML = p2HighScore
  187. } else if (p2HighScore === undefined) {
  188. p2HighScore = p2Score
  189. console.log('p2HighScore updated: ' + p2HighScore)
  190. localforage.setItem('p2HighScore', p2HighScore)
  191. document.getElementById('p2HighScore').innerHTML = p2HighScore
  192. }
  193. localforage.setItem('playedGames', [mode, this.startTime, this.scores[0], this.scores[1]])
  194. }
  195. }
  196. },
  197.  
  198. level: function (playerNo) {
  199. return 8 + (this.scores[playerNo] - this.scores[playerNo ? 0 : 1])
  200. },
  201.  
  202. goal: function (playerNo) {
  203. this.sounds.goal()
  204. this.scores[playerNo] += 1
  205. if (this.scores[playerNo] == 9) {
  206. this.menu.declareWinner(playerNo)
  207. this.stop()
  208. } else {
  209. this.ball.reset(playerNo)
  210. this.leftPaddle.setLevel(this.level(0))
  211. this.rightPaddle.setLevel(this.level(1))
  212. }
  213. },
  214.  
  215. update: function (dt) {
  216. this.leftPaddle.update(dt, this.ball)
  217. this.rightPaddle.update(dt, this.ball)
  218. if (this.playing) {
  219. if (timer > 0) {
  220. var dx = this.ball.dx
  221. var dy = this.ball.dy
  222. this.ball.update(dt, this.leftPaddle, this.rightPaddle)
  223. if (this.ball.dx < 0 && dx > 0) { this.sounds.ping() } else if (this.ball.dx > 0 && dx < 0) { this.sounds.pong() } else if (this.ball.dy * dy < 0) { this.sounds.wall() }
  224.  
  225. if (this.ball.left > this.width) { this.goal(0) } else if (this.ball.right < 0) { this.goal(1) }
  226. } else {
  227. if (this.scores[0] > this.scores[1]) {
  228. this.menu.declareWinner(0)
  229. this.stop()
  230. } else if (this.scores[1] > this.scores[0]) {
  231. this.menu.declareWinner(1)
  232. this.stop()
  233. } else {
  234. timer += 1
  235. document.getElementById('timer').innerHTML = 'Sudden death'
  236. }
  237. }
  238. }
  239. },
  240.  
  241. draw: function (ctx) {
  242. this.court.draw(ctx, this.scores[0], this.scores[1])
  243. this.leftPaddle.draw(ctx)
  244. this.rightPaddle.draw(ctx)
  245. if (this.playing) { this.ball.draw(ctx) } else { this.menu.draw(ctx) }
  246. },
  247.  
  248. onkeydown: function (keyCode) {
  249. switch (keyCode) {
  250. case Game.KEY.Y:
  251. e = new Event('keydown')
  252. e.keyCode = Game.KEY.Y
  253. document.dispatchEvent(e)
  254. if (mode === 1) {
  255. this.startSinglePlayer()
  256. } else if (mode === 2) {
  257. this.startDoublePlayer()
  258. } else if (mode === 0) {
  259. this.startDemo()
  260. }
  261. break
  262. case Game.KEY.ESC: this.stop(true); break
  263. case Game.KEY.Q: if (!this.leftPaddle.auto) this.leftPaddle.moveUp(); break
  264. case Game.KEY.A: if (!this.leftPaddle.auto) this.leftPaddle.moveDown(); break
  265. case Game.KEY.P: if (!this.rightPaddle.auto) this.rightPaddle.moveUp(); break
  266. case Game.KEY.L: if (!this.rightPaddle.auto) this.rightPaddle.moveDown(); break
  267. }
  268. },
  269.  
  270. onkeyup: function (keyCode) {
  271. switch (keyCode) {
  272. case Game.KEY.Q: if (!this.leftPaddle.auto) this.leftPaddle.stopMovingUp(); break
  273. case Game.KEY.A: if (!this.leftPaddle.auto) this.leftPaddle.stopMovingDown(); break
  274. case Game.KEY.P: if (!this.rightPaddle.auto) this.rightPaddle.stopMovingUp(); break
  275. case Game.KEY.L: if (!this.rightPaddle.auto) this.rightPaddle.stopMovingDown(); break
  276. }
  277. },
  278.  
  279. showStats: function (on) { this.cfg.stats = on },
  280. showFootprints: function (on) { this.cfg.footprints = on; this.ball.footprints = [] },
  281. showPredictions: function (on) { this.cfg.predictions = on },
  282. enableSound: function (on) { this.cfg.sound = on },
  283.  
  284. //= ============================================================================
  285. // MENU
  286. //= ============================================================================
  287.  
  288. Menu: {
  289.  
  290. initialize: function (pong) {
  291. var press1 = pong.images['images/press1.png']
  292. var press2 = pong.images['images/press2.png']
  293. var winner = pong.images['images/winner.png']
  294. this.press1 = { image: press1, x: 10, y: pong.cfg.wallWidth }
  295. this.press2 = { image: press2, x: (pong.width - press2.width - 10), y: pong.cfg.wallWidth }
  296. this.winner1 = { image: winner, x: (pong.width / 2) - winner.width - pong.cfg.wallWidth, y: 6 * pong.cfg.wallWidth }
  297. this.winner2 = { image: winner, x: (pong.width / 2) + pong.cfg.wallWidth, y: 6 * pong.cfg.wallWidth }
  298. },
  299.  
  300. declareWinner: function (playerNo) {
  301. this.winner = playerNo
  302. },
  303. drawTimer: function (ctx, timer) {
  304. ctx.draw(timer, this.winner1.x, this.winner1.y)
  305. },
  306. draw: function (ctx) {
  307. if (this.winner === 0) { ctx.drawImage(this.winner1.image, this.winner1.x, this.winner1.y) } else if (this.winner == 1) { ctx.drawImage(this.winner2.image, this.winner2.x, this.winner2.y) }
  308. }
  309.  
  310. },
  311.  
  312. //= ============================================================================
  313. // SOUNDS
  314. //= ============================================================================
  315.  
  316. Sounds: {
  317.  
  318. initialize: function (pong) {
  319. this.game = pong
  320. this.supported = Game.ua.hasAudio
  321. if (this.supported) {
  322. this.files = {
  323. ping: Game.createAudio('sounds/ping.wav'),
  324. pong: Game.createAudio('sounds/pong.wav'),
  325. wall: Game.createAudio('sounds/wall.wav'),
  326. goal: Game.createAudio('sounds/goal.wav')
  327. }
  328. }
  329. },
  330.  
  331. play: function (name) {
  332. if (this.supported && this.game.cfg.sound && this.files[name]) { this.files[name].play() }
  333. },
  334.  
  335. ping: function () { this.play('ping') },
  336. pong: function () { this.play('pong') },
  337. wall: function () { /* this.play('wall'); */ },
  338. goal: function () { /* this.play('goal'); */ }
  339.  
  340. },
  341.  
  342. //= ============================================================================
  343. // COURT
  344. //= ============================================================================
  345.  
  346. Court: {
  347.  
  348. initialize: function (pong) {
  349. var w = pong.width
  350. var h = pong.height
  351. var ww = pong.cfg.wallWidth
  352.  
  353. this.ww = ww
  354. this.walls = []
  355. this.walls.push({x: 0, y: 0, width: w, height: ww})
  356. this.walls.push({x: 0, y: h - ww, width: w, height: ww})
  357. var nMax = (h / (ww * 2))
  358. for (var n = 0; n < nMax; n++) { // draw dashed halfway line
  359. this.walls.push({x: (w / 2) - (ww / 2),
  360. y: (ww / 2) + (ww * 2 * n),
  361. width: ww,
  362. height: ww})
  363. }
  364.  
  365. var sw = 3 * ww
  366. var sh = 4 * ww
  367. this.score1 = {x: 0.5 + (w / 2) - 1.5 * ww - sw, y: 2 * ww, w: sw, h: sh}
  368. this.score2 = {x: 0.5 + (w / 2) + 1.5 * ww, y: 2 * ww, w: sw, h: sh}
  369. },
  370.  
  371. draw: function (ctx, scorePlayer1, scorePlayer2) {
  372. ctx.fillStyle = Pong.Colors.walls
  373. for (var n = 0; n < this.walls.length; n++) { ctx.fillRect(this.walls[n].x, this.walls[n].y, this.walls[n].width, this.walls[n].height) }
  374. this.drawDigit(ctx, scorePlayer1, this.score1.x, this.score1.y, this.score1.w, this.score1.h)
  375. this.drawDigit(ctx, scorePlayer2, this.score2.x, this.score2.y, this.score2.w, this.score2.h)
  376. },
  377.  
  378. drawDigit: function (ctx, n, x, y, w, h) {
  379. ctx.fillStyle = Pong.Colors.score
  380. var dw = dh = this.ww * 4 / 5
  381. var blocks = Pong.Court.DIGITS[n]
  382. if (blocks[0]) { ctx.fillRect(x, y, w, dh) }
  383. if (blocks[1]) { ctx.fillRect(x, y, dw, h / 2) }
  384. if (blocks[2]) { ctx.fillRect(x + w - dw, y, dw, h / 2) }
  385. if (blocks[3]) { ctx.fillRect(x, y + h / 2 - dh / 2, w, dh) }
  386. if (blocks[4]) { ctx.fillRect(x, y + h / 2, dw, h / 2) }
  387. if (blocks[5]) { ctx.fillRect(x + w - dw, y + h / 2, dw, h / 2) }
  388. if (blocks[6]) { ctx.fillRect(x, y + h - dh, w, dh) }
  389. },
  390.  
  391. DIGITS: [
  392. [1, 1, 1, 0, 1, 1, 1], // 0
  393. [0, 0, 1, 0, 0, 1, 0], // 1
  394. [1, 0, 1, 1, 1, 0, 1], // 2
  395. [1, 0, 1, 1, 0, 1, 1], // 3
  396. [0, 1, 1, 1, 0, 1, 0], // 4
  397. [1, 1, 0, 1, 0, 1, 1], // 5
  398. [1, 1, 0, 1, 1, 1, 1], // 6
  399. [1, 0, 1, 0, 0, 1, 0], // 7
  400. [1, 1, 1, 1, 1, 1, 1], // 8
  401. [1, 1, 1, 1, 0, 1, 0] // 9
  402. ]
  403.  
  404. },
  405.  
  406. //= ============================================================================
  407. // PADDLE
  408. //= ============================================================================
  409.  
  410. Paddle: {
  411.  
  412. initialize: function (pong, rhs) {
  413. this.pong = pong
  414. this.width = pong.cfg.paddleWidth
  415. this.height = pong.cfg.paddleHeight
  416. this.minY = pong.cfg.wallWidth
  417. this.maxY = pong.height - pong.cfg.wallWidth - this.height
  418. this.speed = (this.maxY - this.minY) / pong.cfg.paddleSpeed
  419. this.setpos(rhs ? pong.width - this.width : 0, this.minY + (this.maxY - this.minY) / 2)
  420. this.setdir(0)
  421. },
  422.  
  423. setpos: function (x, y) {
  424. this.x = x
  425. this.y = y
  426. this.left = this.x
  427. this.right = this.left + this.width
  428. this.top = this.y
  429. this.bottom = this.y + this.height
  430. },
  431.  
  432. setdir: function (dy) {
  433. this.up = (dy < 0 ? -dy : 0)
  434. this.down = (dy > 0 ? dy : 0)
  435. },
  436.  
  437. setAuto: function (on, level) {
  438. if (on && !this.auto) {
  439. this.auto = true
  440. this.setLevel(level)
  441. } else if (!on && this.auto) {
  442. this.auto = false
  443. this.setdir(0)
  444. }
  445. },
  446.  
  447. setLevel: function (level) {
  448. if (this.auto) { this.level = Pong.Levels[level] }
  449. },
  450.  
  451. update: function (dt, ball) {
  452. if (this.auto) { this.ai(dt, ball) }
  453.  
  454. var amount = this.down - this.up
  455. if (amount != 0) {
  456. var y = this.y + (amount * dt * this.speed)
  457. if (y < this.minY) { y = this.minY } else if (y > this.maxY) { y = this.maxY }
  458. this.setpos(this.x, y)
  459. }
  460. },
  461.  
  462. ai: function (dt, ball) {
  463. if (((ball.x < this.left) && (ball.dx < 0)) ||
  464. ((ball.x > this.right) && (ball.dx > 0))) {
  465. this.stopMovingUp()
  466. this.stopMovingDown()
  467. return
  468. }
  469.  
  470. this.predict(ball, dt)
  471.  
  472. if (this.prediction) {
  473. if (this.prediction.y < (this.top + this.height / 2 - 5)) {
  474. this.stopMovingDown()
  475. this.moveUp()
  476. } else if (this.prediction.y > (this.bottom - this.height / 2 + 5)) {
  477. this.stopMovingUp()
  478. this.moveDown()
  479. } else {
  480. this.stopMovingUp()
  481. this.stopMovingDown()
  482. }
  483. }
  484. },
  485.  
  486. predict: function (ball, dt) {
  487. // only re-predict if the ball changed direction, or its been some amount of time since last prediction
  488. if (this.prediction &&
  489. ((this.prediction.dx * ball.dx) > 0) &&
  490. ((this.prediction.dy * ball.dy) > 0) &&
  491. (this.prediction.since < this.level.aiReaction)) {
  492. this.prediction.since += dt
  493. return
  494. }
  495.  
  496. var pt = Pong.Helper.ballIntercept(ball, {left: this.left, right: this.right, top: -10000, bottom: 10000}, ball.dx * 10, ball.dy * 10)
  497. if (pt) {
  498. var t = this.minY + ball.radius
  499. var b = this.maxY + this.height - ball.radius
  500.  
  501. while ((pt.y < t) || (pt.y > b)) {
  502. if (pt.y < t) {
  503. pt.y = t + (t - pt.y)
  504. } else if (pt.y > b) {
  505. pt.y = t + (b - t) - (pt.y - b)
  506. }
  507. }
  508. this.prediction = pt
  509. } else {
  510. this.prediction = null
  511. }
  512.  
  513. if (this.prediction) {
  514. this.prediction.since = 0
  515. this.prediction.dx = ball.dx
  516. this.prediction.dy = ball.dy
  517. this.prediction.radius = ball.radius
  518. this.prediction.exactX = this.prediction.x
  519. this.prediction.exactY = this.prediction.y
  520. var closeness = (ball.dx < 0 ? ball.x - this.right : this.left - ball.x) / this.pong.width
  521. var error = this.level.aiError * closeness
  522. this.prediction.y = this.prediction.y + Game.random(-error, error)
  523. }
  524. },
  525.  
  526. draw: function (ctx) {
  527. ctx.fillStyle = Pong.Colors.walls
  528. ctx.fillRect(this.x, this.y, this.width, this.height)
  529. if (this.prediction && this.pong.cfg.predictions) {
  530. ctx.strokeStyle = Pong.Colors.predictionExact
  531. ctx.strokeRect(this.prediction.x - this.prediction.radius, this.prediction.exactY - this.prediction.radius, this.prediction.radius * 2, this.prediction.radius * 2)
  532. ctx.strokeStyle = Pong.Colors.predictionGuess
  533. ctx.strokeRect(this.prediction.x - this.prediction.radius, this.prediction.y - this.prediction.radius, this.prediction.radius * 2, this.prediction.radius * 2)
  534. }
  535. },
  536.  
  537. moveUp: function () { this.up = 1 },
  538. moveDown: function () { this.down = 1 },
  539. stopMovingUp: function () { this.up = 0 },
  540. stopMovingDown: function () { this.down = 0 }
  541.  
  542. },
  543.  
  544. //= ============================================================================
  545. // BALL
  546. //= ============================================================================
  547.  
  548. Ball: {
  549.  
  550. initialize: function (pong) {
  551. this.pong = pong
  552. this.radius = pong.cfg.ballRadius
  553. this.minX = this.radius
  554. this.maxX = pong.width - this.radius
  555. this.minY = pong.cfg.wallWidth + this.radius
  556. this.maxY = pong.height - pong.cfg.wallWidth - this.radius
  557. this.speed = (this.maxX - this.minX) / pong.cfg.ballSpeed
  558. this.accel = pong.cfg.ballAccel
  559. },
  560.  
  561. reset: function (playerNo) {
  562. this.footprints = []
  563. this.setpos(playerNo == 1 ? this.maxX : this.minX, Game.random(this.minY, this.maxY))
  564. this.setdir(playerNo == 1 ? -this.speed : this.speed, this.speed)
  565. },
  566.  
  567. setpos: function (x, y) {
  568. this.x = x
  569. this.y = y
  570. this.left = this.x - this.radius
  571. this.top = this.y - this.radius
  572. this.right = this.x + this.radius
  573. this.bottom = this.y + this.radius
  574. },
  575.  
  576. setdir: function (dx, dy) {
  577. this.dxChanged = ((this.dx < 0) != (dx < 0)) // did horizontal direction change
  578. this.dyChanged = ((this.dy < 0) != (dy < 0)) // did vertical direction change
  579. this.dx = dx
  580. this.dy = dy
  581. },
  582.  
  583. footprint: function () {
  584. if (this.pong.cfg.footprints) {
  585. if (!this.footprintCount || this.dxChanged || this.dyChanged) {
  586. this.footprints.push({x: this.x, y: this.y})
  587. if (this.footprints.length > 50) { this.footprints.shift() }
  588. this.footprintCount = 5
  589. } else {
  590. this.footprintCount--
  591. }
  592. }
  593. },
  594.  
  595. update: function (dt, leftPaddle, rightPaddle) {
  596. pos = Pong.Helper.accelerate(this.x, this.y, this.dx, this.dy, this.accel, dt)
  597.  
  598. if ((pos.dy > 0) && (pos.y > this.maxY)) {
  599. pos.y = this.maxY
  600. pos.dy = -pos.dy
  601. } else if ((pos.dy < 0) && (pos.y < this.minY)) {
  602. pos.y = this.minY
  603. pos.dy = -pos.dy
  604. }
  605.  
  606. var paddle = (pos.dx < 0) ? leftPaddle : rightPaddle
  607. var pt = Pong.Helper.ballIntercept(this, paddle, pos.nx, pos.ny)
  608.  
  609. if (pt) {
  610. switch (pt.d) {
  611. case 'left':
  612. case 'right':
  613. pos.x = pt.x
  614. pos.dx = -pos.dx
  615. break
  616. case 'top':
  617. case 'bottom':
  618. pos.y = pt.y
  619. pos.dy = -pos.dy
  620. break
  621. }
  622.  
  623. // add/remove spin based on paddle direction
  624. if (paddle.up) { pos.dy = pos.dy * (pos.dy < 0 ? 0.5 : 1.5) } else if (paddle.down) { pos.dy = pos.dy * (pos.dy > 0 ? 0.5 : 1.5) }
  625. }
  626.  
  627. this.setpos(pos.x, pos.y)
  628. this.setdir(pos.dx, pos.dy)
  629. this.footprint()
  630. },
  631.  
  632. draw: function (ctx) {
  633. var w = h = this.radius * 2
  634. ctx.fillStyle = Pong.Colors.ball
  635. ctx.fillRect(this.x - this.radius, this.y - this.radius, w, h)
  636. if (this.pong.cfg.footprints) {
  637. var max = this.footprints.length
  638. ctx.strokeStyle = Pong.Colors.footprint
  639. for (var n = 0; n < max; n++) { ctx.strokeRect(this.footprints[n].x - this.radius, this.footprints[n].y - this.radius, w, h) }
  640. }
  641. }
  642.  
  643. },
  644.  
  645. //= ============================================================================
  646. // HELPER
  647. //= ============================================================================
  648.  
  649. Helper: {
  650.  
  651. accelerate: function (x, y, dx, dy, accel, dt) {
  652. var x2 = x + (dt * dx) + (accel * dt * dt * 0.5)
  653. var y2 = y + (dt * dy) + (accel * dt * dt * 0.5)
  654. var dx2 = dx + (accel * dt) * (dx > 0 ? 1 : -1)
  655. var dy2 = dy + (accel * dt) * (dy > 0 ? 1 : -1)
  656. return { nx: (x2 - x), ny: (y2 - y), x: x2, y: y2, dx: dx2, dy: dy2 }
  657. },
  658.  
  659. intercept: function (x1, y1, x2, y2, x3, y3, x4, y4, d) {
  660. var denom = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1))
  661. if (denom != 0) {
  662. var ua = (((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3))) / denom
  663. if ((ua >= 0) && (ua <= 1)) {
  664. var ub = (((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3))) / denom
  665. if ((ub >= 0) && (ub <= 1)) {
  666. var x = x1 + (ua * (x2 - x1))
  667. var y = y1 + (ua * (y2 - y1))
  668. return { x: x, y: y, d: d}
  669. }
  670. }
  671. }
  672. return null
  673. },
  674.  
  675. ballIntercept: function (ball, rect, nx, ny) {
  676. var pt
  677. if (nx < 0) {
  678. pt = Pong.Helper.intercept(ball.x, ball.y, ball.x + nx, ball.y + ny,
  679. rect.right + ball.radius,
  680. rect.top - ball.radius,
  681. rect.right + ball.radius,
  682. rect.bottom + ball.radius,
  683. 'right')
  684. } else if (nx > 0) {
  685. pt = Pong.Helper.intercept(ball.x, ball.y, ball.x + nx, ball.y + ny,
  686. rect.left - ball.radius,
  687. rect.top - ball.radius,
  688. rect.left - ball.radius,
  689. rect.bottom + ball.radius,
  690. 'left')
  691. }
  692. if (!pt) {
  693. if (ny < 0) {
  694. pt = Pong.Helper.intercept(ball.x, ball.y, ball.x + nx, ball.y + ny,
  695. rect.left - ball.radius,
  696. rect.bottom + ball.radius,
  697. rect.right + ball.radius,
  698. rect.bottom + ball.radius,
  699. 'bottom')
  700. } else if (ny > 0) {
  701. pt = Pong.Helper.intercept(ball.x, ball.y, ball.x + nx, ball.y + ny,
  702. rect.left - ball.radius,
  703. rect.top - ball.radius,
  704. rect.right + ball.radius,
  705. rect.top - ball.radius,
  706. 'top')
  707. }
  708. }
  709. return pt
  710. }
  711.  
  712. }
  713.  
  714. //= ============================================================================
  715.  
  716. } // Pong
  717. let modeSingle = document.getElementById('single')
  718. let modeDouble = document.getElementById('double')
  719. let modeDemo = document.getElementById('demo')
  720. modeSingle.addEventListener('click', function () {
  721. console.log('clicked 1')
  722. mode = 1
  723. console.log(mode)
  724. })
  725. modeDouble.addEventListener('click', function () {
  726. console.log('clicked 2')
  727. mode = 2
  728. console.log(mode)
  729. })
  730. modeDemo.addEventListener('click', function () {
  731. console.log('clicked 0')
  732. mode = 0
  733. console.log(mode)
  734. })
  735. function secToMin (seconds) {
  736. let minutes = Math.floor(seconds / 60)
  737. let secsLeft = seconds - minutes * 60
  738. if (secsLeft < 10) {
  739. secsLeft = '0' + secsLeft
  740. }
  741. let timer = minutes + ':' + secsLeft
  742. return timer
  743. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement