Advertisement
Kirdneh

kathack repaste

Jan 14th, 2022
7
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.70 KB | None | 0 0
  1. /*
  2. Copyright Alex Leone, David Nufer, David Truong, 2011-03-11. kathack.com
  3.  
  4. javascript:var i,s,ss=['http://kathack.com/js/kh.js','http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js'];for(i=0;i!=ss.length;i++){s=document.createElement('script');s.src=ss[i];document.body.appendChild(s);}void(0);
  5.  
  6. */
  7. var BORDER_STYLE = "1px solid #bbb",
  8. CSS_TRANSFORM = null,
  9. CSS_TRANSFORM_ORIGIN = null,
  10. POSSIBLE_TRANSFORM_PREFIXES = ['-webkit-', '-moz-', '-o-', '-ms-', ''],
  11. khFirst = false;
  12.  
  13. /* When running twice on one page, update pick-uppable nodes instead of
  14. * creating more.
  15. */
  16. if (!window.khNodes) {
  17. khFirst = true;
  18. window.khNodes = new StickyNodes();
  19. }
  20.  
  21. function getCssTransform() {
  22. var i, d = document.createElement('div'), pre;
  23. for (i = 0; i < POSSIBLE_TRANSFORM_PREFIXES.length; i++) {
  24. pre = POSSIBLE_TRANSFORM_PREFIXES[i];
  25. d.style.setProperty(pre + 'transform', 'rotate(1rad) scaleX(2)', null);
  26. if (d.style.getPropertyValue(pre + 'transform')) {
  27. CSS_TRANSFORM = pre + 'transform';
  28. CSS_TRANSFORM_ORIGIN = pre + 'transform-origin';
  29. return;
  30. }
  31. }
  32. alert("Your browser doesn't support CSS tranforms!");
  33. throw "Your browser doesn't support CSS tranforms!";
  34. }
  35. getCssTransform();
  36.  
  37. /**
  38. * Returns true if the circle intersects the element rectangle.
  39. * 0 | 1 | 2
  40. * ------------------
  41. * 3 | 4 | 5
  42. * ------------------
  43. * 6 | 7 | 9
  44. */
  45. function circleGridObjInt(cx, cy, cr, cr2, go) {
  46. var dx, dy;
  47. if (cx < go.left) {
  48. dx = go.left - cx;
  49. if (cy < go.top) { /* zone 0. */
  50. dy = go.top - cy;
  51. return ((dx * dx + dy * dy) <= cr2);
  52. } else if (cy <= go.bottom) { /* zone 3. */
  53. return (dx <= cr);
  54. } else { /* zone 6. */
  55. dy = cy - go.bottom;
  56. return ((dx * dx + dy * dy) <= cr2);
  57. }
  58. } else if (cx <= go.right) {
  59. if (cy < go.top) { /* zone 1. */
  60. return ((go.top - cy) <= cr);
  61. } else if (cy <= go.bottom) { /* zone 4. */
  62. return true;
  63. } else { /* zone 7. */
  64. return ((cy - go.bottom) <= cr);
  65. }
  66. } else {
  67. dx = cx - go.right;
  68. if (cy < go.top) { /* zone 2. */
  69. dy = go.top - cy;
  70. return ((dx * dx + dy * dy) <= cr2);
  71. } else if (cy <= go.bottom) { /* zone 5. */
  72. return (dx <= cr);
  73. } else { /* zone 9. */
  74. dy = cy - go.bottom;
  75. return ((dx * dx + dy * dy) <= cr2);
  76. }
  77. }
  78. }
  79.  
  80. /**
  81. * Returns [x,y] where the rectangle is closest to (cx, cy).
  82. * 0 | 1 | 2
  83. * ------------------
  84. * 3 | 4 | 5
  85. * ------------------
  86. * 6 | 7 | 9
  87. */
  88. function getClosestPoint(cx, cy, go) {
  89. var dx, dy;
  90. if (cx < go.left) {
  91. dx = go.left - cx;
  92. if (cy < go.top) { /* zone 0. */
  93. return [go.left, go.top];
  94. } else if (cy <= go.bottom) { /* zone 3. */
  95. return [go.left, cy];
  96. } else { /* zone 6. */
  97. return [go.left, go.bottom];
  98. }
  99. } else if (cx <= go.right) {
  100. if (cy < go.top) { /* zone 1. */
  101. return [cx, go.top];
  102. } else if (cy <= go.bottom) { /* zone 4. */
  103. return [cx, cy];
  104. } else { /* zone 7. */
  105. return [cx, go.bottom];
  106. }
  107. } else {
  108. dx = cx - go.right;
  109. if (cy < go.top) { /* zone 2. */
  110. return [go.right, go.top];
  111. } else if (cy <= go.bottom) { /* zone 5. */
  112. return [go.right, cy];
  113. } else { /* zone 9. */
  114. return [go.right, go.bottom];
  115. }
  116. }
  117. }
  118.  
  119. /**
  120. * Returns the "volume" of the grid object.
  121. */
  122. function gridObjVol(go) {
  123. return go.w * go.h * Math.min(go.w, go.h);
  124. }
  125.  
  126. function StickyNodes() {
  127. var domNodes = [],
  128. grid = [],
  129. GRIDX = 100,
  130. GRIDY = 100,
  131. REPLACE_WORDS_IN = {
  132. a: 1, b: 1, big: 1, body: 1, cite:1, code: 1, dd: 1, div: 1,
  133. dt: 1, em: 1, font: 1, h1: 1, h2: 1, h3: 1, h4: 1, h5: 1, h6: 1,
  134. i: 1, label: 1, legend: 1, li: 1, p: 1, pre: 1, small: 1,
  135. span: 1, strong: 1, sub: 1, sup: 1, td: 1, th: 1, tt: 1
  136. };
  137.  
  138. function addDomNode(el) {
  139. if (el !== undefined && el !== null) {
  140. el.khIgnore = true;
  141. el.style.border = BORDER_STYLE;
  142. domNodes.push(el);
  143. }
  144. }
  145. this.addDomNode = addDomNode;
  146.  
  147. this.addWords = function (el) {
  148. var textEls = [];
  149.  
  150. function shouldAddChildren(el) {
  151. return el.tagName && REPLACE_WORDS_IN[el.tagName.toLowerCase()];
  152. }
  153.  
  154. function buildTextEls(el, shouldAdd) {
  155. var i, len;
  156. if (shouldAdd && el.nodeType === Node.TEXT_NODE &&
  157. el.nodeValue.trim().length > 0) {
  158. textEls.push(el);
  159. return;
  160. }
  161. if (!el.childNodes || el.khIgnore) {
  162. return;
  163. }
  164. shouldAdd = shouldAddChildren(el);
  165. for (i = 0, len = el.childNodes.length; i < len; i++) {
  166. buildTextEls(el.childNodes[i], shouldAdd);
  167. }
  168. }
  169.  
  170. function wordsToSpans(textEl) {
  171. var p = textEl.parentNode,
  172. words = textEl.nodeValue.split(/\s+/),
  173. ws = textEl.nodeValue.split(/\S+/),
  174. i, n, len = Math.max(words.length, ws.length);
  175. /* preserve whitespace for pre tags. */
  176. if (ws.length > 0 && ws[0].length === 0) {
  177. ws.shift();
  178. }
  179. for (i = 0; i < len; i++) {
  180. if (i < words.length && words[i].length > 0) {
  181. n = document.createElement('span');
  182. n.innerHTML = words[i];
  183. p.insertBefore(n, textEl);
  184. addDomNode(n);
  185. }
  186. if (i < ws.length && ws[i].length > 0) {
  187. n = document.createTextNode(ws[i]);
  188. p.insertBefore(n, textEl);
  189. }
  190. }
  191. p.removeChild(textEl);
  192. }
  193.  
  194. buildTextEls(el, shouldAddChildren(el));
  195. textEls.map(wordsToSpans);
  196. };
  197.  
  198. /* includes el. */
  199. this.addTagNames = function (el, tagNames) {
  200. var tname = el.tagName && el.tagName.toLowerCase(),
  201. i, j, els, len;
  202. if (el.khIgnore) {
  203. return;
  204. }
  205. if (tagNames.indexOf(tname) !== -1) {
  206. addDomNode(el);
  207. }
  208. if (!el.getElementsByTagName) {
  209. return;
  210. }
  211. for (i = 0; i < tagNames.length; i++) {
  212. els = el.getElementsByTagName(tagNames[i]);
  213. for (j = 0, len = els.length; j < len; j++) {
  214. if (!els[j].khIgnore) {
  215. addDomNode(els[j]);
  216. }
  217. }
  218. }
  219. };
  220.  
  221. this.finalize = function (docW, docH) {
  222. var xi, yi, i, len, startXI, startYI, el, go, off, w, h,
  223. endXI = Math.floor(docW / GRIDX) + 1,
  224. endYI = Math.floor(docH / GRIDY) + 1;
  225. /* initialize grid. */
  226. grid = new Array(endXI);
  227. for (xi = 0; xi < endXI; xi++) {
  228. grid[xi] = new Array(endYI);
  229. }
  230. /* add nodes into grid. */
  231. for (i = 0, len = domNodes.length; i < len; i++) {
  232. el = domNodes[i];
  233. if (el.khPicked) {
  234. continue;
  235. }
  236. off = jQuery(el).offset();
  237. w = jQuery(el).width();
  238. h = jQuery(el).height();
  239. go = {
  240. el: domNodes[i], /* dom element. */
  241. left: off.left,
  242. right: off.left + w,
  243. top: off.top,
  244. bottom: off.top + h,
  245. w: w,
  246. h: h,
  247. x: off.left + (w / 2), /* center x. */
  248. y: off.top + (h / 2), /* center y. */
  249. diag: Math.sqrt(((w * w) + (h * h)) / 4), /* center to corner */
  250.  
  251. /* these are for removing ourselves from the grid. */
  252. arrs: [], /* which arrays we're in (grid[x][y]). */
  253. idxs: [] /* what indexes. */
  254. };
  255. startXI = Math.floor(go.left / GRIDX);
  256. startYI = Math.floor(go.top / GRIDY);
  257. endXI = Math.floor((go.left + go.w) / GRIDX) + 1;
  258. endYI = Math.floor((go.top + go.h) / GRIDY) + 1;
  259. for (xi = startXI; xi < endXI; xi++) {
  260. for (yi = startYI; yi < endYI; yi++) {
  261. if (grid[xi] === undefined) {
  262. grid[xi] = [];
  263. }
  264. if (grid[xi][yi] === undefined) {
  265. grid[xi][yi] = [go];
  266. } else {
  267. grid[xi][yi].push(go);
  268. }
  269. go.arrs.push(grid[xi][yi]);
  270. go.idxs.push(grid[xi][yi].length - 1);
  271. }
  272. }
  273. }
  274. };
  275.  
  276. function removeGridObj(go) {
  277. var i;
  278. for (i = 0; i < go.arrs.length; i++) {
  279. go.arrs[i][go.idxs[i]] = undefined;
  280. }
  281. go.el.style.visibility = "hidden";
  282. go.el.khPicked = true;
  283. delete go.arrs;
  284. delete go.idxs;
  285. }
  286.  
  287. /**
  288. * cb(gridObj) -> boolean true if the object should be removed.
  289. */
  290. this.removeIntersecting = function (x, y, r, cb) {
  291. var xi, yi, arr, i, r2 = r * r, go,
  292. startXI = Math.floor((x - r) / GRIDX),
  293. startYI = Math.floor((y - r) / GRIDY),
  294. endXI = Math.floor((x + r) / GRIDX) + 1,
  295. endYI = Math.floor((y + r) / GRIDY) + 1;
  296. for (xi = startXI; xi < endXI; xi++) {
  297. if (grid[xi] === undefined) {
  298. continue;
  299. }
  300. for (yi = startYI; yi < endYI; yi++) {
  301. arr = grid[xi][yi];
  302. if (arr === undefined) {
  303. continue;
  304. }
  305. for (i = 0; i < arr.length; i++) {
  306. go = arr[i];
  307. if (go !== undefined &&
  308. circleGridObjInt(x, y, r, r2, go) &&
  309. cb(go)) {
  310. removeGridObj(go);
  311. }
  312. }
  313. }
  314. }
  315. };
  316. }
  317.  
  318. function PlayerBall(parentNode, stickyNodes, ballOpts, sounds) {
  319. var x = 300, y = 300,
  320. vx = 0, vy = 0,
  321. radius = 20,
  322. lastR = 0, /**< optimization: only resize when necessary. */
  323. docW = 10000, docH = 10000,
  324.  
  325. attached = [],
  326. attachedDiv, /* div to put attached nodes into. */
  327. canvas_el,
  328. canvas_ctx,
  329. color = ballOpts.color,
  330.  
  331. accelTargetX = 0, accelTargetY = 0,
  332. accel = false,
  333.  
  334. VOL_MULT = ballOpts.VOL_MULT,
  335. MAX_ATTACHED_VISIBLE = ballOpts.MAX_ATTACHED_VISIBLE,
  336. CHECK_VOLS = ballOpts.CHECK_VOLS,
  337.  
  338. /**
  339. * which direction the ball is facing in the xy axis, in radians.
  340. * th: 0 is facing dead East
  341. * th: 1/2 PI is facing dead South
  342. * note that this is like regular th on a graph with y inverted.
  343. * Same rotation as css transform.
  344. */
  345. th = 0,
  346.  
  347. /**
  348. * Ball angle in the rotation axis / z plane, in radians.
  349. * phi: 0 is pointing in the direction the ball is rolling.
  350. * phi: 1/2 PI is pointing straight up (out of the page).
  351. * note that forward rotation means phi -= 0.1.
  352. */
  353. phi = 0;
  354.  
  355. this.init = function () {
  356. canvas_el = document.createElement('canvas');
  357. canvas_el.width = radius * 2;
  358. canvas_el.height = radius * 2;
  359. canvas_el.style.cssText = 'position: absolute; z-index: 500;';
  360. parentNode.appendChild(canvas_el);
  361. canvas_ctx = canvas_el.getContext('2d');
  362.  
  363. attachedDiv = document.createElement('div');
  364. parentNode.appendChild(attachedDiv);
  365. };
  366.  
  367. this.setRadius = function (r) {
  368. radius = r;
  369. };
  370.  
  371. this.getState = function () {
  372. return {
  373. x: x,
  374. y: y,
  375. vx: vx,
  376. vy: vy,
  377. radius: radius,
  378. th: th,
  379. phi: phi,
  380. };
  381. };
  382.  
  383. this.setState = function (s) {
  384. x = s.x;
  385. y = s.y;
  386. vx = s.vx;
  387. vy = s.vy;
  388. radius = s.radius;
  389. th = s.th;
  390. phi = s.phi;
  391. };
  392.  
  393. this.setXY = function (sx, sy) {
  394. x = sx;
  395. y = sy;
  396. };
  397.  
  398. this.setTh = function (sth) {
  399. th = sth;
  400. };
  401.  
  402. this.setPhi = function (sphi) {
  403. phi = sphi;
  404. };
  405.  
  406. this.setColor = function (c) {
  407. color = c;
  408. };
  409.  
  410. this.setDocSize = function (w, h) {
  411. docW = w;
  412. docH = h;
  413. };
  414.  
  415. this.setAccel = function (bool) {
  416. accel = bool;
  417. };
  418.  
  419. this.setAccelTarget = function (tx, ty) {
  420. accelTargetX = tx;
  421. accelTargetY = ty;
  422. };
  423.  
  424. function getVol() {
  425. return (4 * Math.PI * radius * radius * radius / 3);
  426. }
  427.  
  428. function grow(go) {
  429. var newVol = getVol() + gridObjVol(go) * VOL_MULT;
  430. radius = Math.pow(newVol * 3 / (4 * Math.PI), 1 / 3);
  431. }
  432.  
  433. function attachGridObj(go) {
  434. var attXY = getClosestPoint(x, y, go),
  435. dx = attXY[0] - x,
  436. dy = attXY[1] - y,
  437. r = Math.sqrt(dx * dx + dy * dy),
  438. attTh = 0 - th,
  439. offLeft = attXY[0] - go.left,
  440. offTop = attXY[1] - go.top,
  441. offTh = Math.atan2(dy, dx) - th,
  442. attX = r * Math.cos(offTh),
  443. attY = r * Math.sin(offTh),
  444. el = go.el.cloneNode(true),
  445. go_jel = jQuery(go.el),
  446. newAtt = {
  447. el: el,
  448. attX: attX,
  449. attY: attY,
  450. attT: 'translate(' + Math.round(attX) + 'px,' +
  451. Math.round(attY) + 'px) ' +
  452. 'rotate(' + attTh + 'rad)',
  453. r: r,
  454. offTh: offTh,
  455. offPhi: 0 - phi,
  456. diag: go.diag,
  457. removeR: r + go.diag,
  458. visible: false,
  459. display: go_jel.css('display')
  460. };
  461. attached.push(newAtt);
  462. grow(go);
  463. el.style.position = 'absolute';
  464. el.style.left = (-offLeft) + 'px';
  465. el.style.top = (-offTop) + 'px';
  466. el.style.setProperty(CSS_TRANSFORM_ORIGIN,
  467. offLeft + 'px ' + offTop + 'px', null);
  468. el.style.display = 'none';
  469. /* copy computed styles from old object. */
  470. el.style.color = go_jel.css('color');
  471. el.style.textDecoration = go_jel.css('text-decoration');
  472. el.style.fontSize = go_jel.css('font-size');
  473. el.style.fontWeight = go_jel.css('font-weight');
  474. el.khIgnore = true;
  475. attachedDiv.appendChild(el);
  476. if (sounds) {
  477. sounds.play_pop();
  478. }
  479. }
  480.  
  481. /**
  482. * @return true if the object should be removed from stickyNodes.
  483. */
  484. function removeIntCb(go) {
  485. if (CHECK_VOLS && gridObjVol(go) > getVol()) {
  486. return false;
  487. }
  488. attachGridObj(go);
  489. return true;
  490. }
  491.  
  492. this.updatePhysics = function () {
  493. var oldX = x, oldY = y, dx, dy,
  494. bounce = false,
  495. accelTh;
  496. if (accel) {
  497. accelTh = Math.atan2(accelTargetY - y, accelTargetX - x);
  498. vx += Math.cos(accelTh) * 0.5;
  499. vy += Math.sin(accelTh) * 0.5;
  500. } else {
  501. vx *= 0.95;
  502. vy *= 0.95;
  503. }
  504. x += vx;
  505. y += vy;
  506. /* bounce ball on edges of document. */
  507. if (x - radius < 0) {
  508. bounce = true;
  509. x = radius + 1;
  510. vx = -vx;
  511. } else if (x + radius > docW) {
  512. bounce = true;
  513. x = docW - radius - 1;
  514. vx = -vx;
  515. }
  516. if (y - radius < 0) {
  517. bounce = true;
  518. y = radius + 1;
  519. vy = -vy;
  520. } else if (y + radius > docH) {
  521. bounce = true;
  522. y = docH - radius - 1;
  523. vy = -vy;
  524. }
  525. if (vx !== 0 || vy !== 0) {
  526. th = Math.atan2(vy, vx);
  527. dx = x - oldX;
  528. dy = y - oldY;
  529. /* arclen = th * r, so th = arclen / r. */
  530. phi -= Math.sqrt(dx * dx + dy * dy) / radius;
  531. }
  532. stickyNodes.removeIntersecting(x, y, radius, removeIntCb);
  533. this.draw();
  534. if (bounce && sounds) {
  535. sounds.play_bounce();
  536. }
  537. };
  538.  
  539. function drawBall() {
  540. var sx1, sy1, sx2, sy2, dx, dy, i, pct1, pct2, z1, z2;
  541. /* move/resize canvas element. */
  542. canvas_el.style.left = (x - radius) + 'px';
  543. canvas_el.style.top = (y - radius) + 'px';
  544. if (radius != lastR) {
  545. canvas_el.width = 2 * radius + 1;
  546. canvas_el.height = 2 * radius + 1;
  547. lastR = radius;
  548. }
  549. /* draw white circle. */
  550. canvas_ctx.clearRect(0, 0, 2 * radius, 2 * radius);
  551. canvas_ctx.fillStyle = "#fff";
  552. canvas_ctx.beginPath();
  553. canvas_ctx.arc(radius, radius, radius - 1, 0, Math.PI * 2, true);
  554. canvas_ctx.fill();
  555. /* draw outer border. */
  556. canvas_ctx.strokeStyle = color;
  557. canvas_ctx.beginPath();
  558. canvas_ctx.arc(radius, radius, radius - 1, 0, Math.PI * 2, true);
  559. canvas_ctx.stroke();
  560. /* draw stripes. */
  561. canvas_ctx.fillStyle = color;
  562. sx1 = radius + radius * Math.cos(th + Math.PI / 16);
  563. sy1 = radius + radius * Math.sin(th + Math.PI / 16);
  564. sx2 = radius + radius * Math.cos(th - Math.PI / 16);
  565. sy2 = radius + radius * Math.sin(th - Math.PI / 16);
  566. dx = (radius + radius * Math.cos(th + Math.PI * 15 / 16)) - sx1;
  567. dy = (radius + radius * Math.sin(th + Math.PI * 15 / 16)) - sy1;
  568. for (i = 0; i < Math.PI * 2; i += Math.PI / 7) {
  569. pct1 = (-Math.cos(phi + i) + 1) / 2;
  570. pct2 = (-Math.cos(phi + i + Math.PI / 32) + 1) / 2;
  571. z1 = Math.sin(phi + i);
  572. z2 = Math.sin(phi + i + Math.PI / 32);
  573. if (z1 > 0 && z2 > 0) {
  574. canvas_ctx.beginPath();
  575. canvas_ctx.moveTo(sx1 + pct1 * dx, sy1 + pct1 * dy);
  576. canvas_ctx.lineTo(sx1 + pct2 * dx, sy1 + pct2 * dy);
  577. canvas_ctx.lineTo(sx2 + pct2 * dx, sy2 + pct2 * dy);
  578. canvas_ctx.lineTo(sx2 + pct1 * dx, sy2 + pct1 * dy);
  579. canvas_ctx.fill();
  580. }
  581. }
  582. }
  583.  
  584. /**
  585. * @return true if the attached object is roughly visible.
  586. */
  587. function drawAttached(att) {
  588. var oth = th + att.offTh,
  589. ophi = phi + att.offPhi,
  590. ox = att.r * Math.cos(oth),
  591. oy = att.r * Math.sin(oth),
  592. dx = (att.r * Math.cos((th - att.offTh) + Math.PI)) - ox,
  593. dy = (att.r * Math.sin((th - att.offTh) + Math.PI)) - oy,
  594. pct = (-Math.cos(ophi) + 1) / 2,
  595. cx = ox + pct * dx,
  596. cy = oy + pct * dy,
  597. oz = att.r * Math.sin(ophi);
  598. if (oz < 0 && Math.sqrt(cx * cx + cy * cy) + att.diag < radius) {
  599. /* hidden behind circle. */
  600. if (att.visible) {
  601. att.visible = false;
  602. att.el.style.display = "none";
  603. }
  604. return false;
  605. }
  606. /* attached node is visible. */
  607. if (!att.visible) {
  608. att.visible = true;
  609. att.el.style.display = att.display;
  610. }
  611. //att.el.style.zIndex = 500 + Math.round(oz);
  612. att.el.style.zIndex = (oz > 0)? 501 : 499;
  613. att.el.style.setProperty(
  614. CSS_TRANSFORM,
  615. 'translate(' + x + 'px,' + y + 'px) ' +
  616. 'rotate(' + th + 'rad) ' +
  617. 'scaleX(' + Math.cos(ophi) + ') ' +
  618. att.attT, null);
  619. return true;
  620. }
  621.  
  622. function onAttachedRemoved(att) {
  623. attachedDiv.removeChild(att.el);
  624. delete att.el;
  625. }
  626.  
  627. this.draw = function () {
  628. var i, att, numAttachedVisible = 0;
  629. drawBall();
  630. for (i = attached.length; --i >= 0;) {
  631. att = attached[i];
  632. if (att.removeR < radius) {
  633. attached.splice(i, 1).map(onAttachedRemoved);
  634. } else if (drawAttached(att)) {
  635. if (++numAttachedVisible > MAX_ATTACHED_VISIBLE) {
  636. /* remove older items and stop. */
  637. attached.splice(0, i).map(onAttachedRemoved);
  638. break;
  639. }
  640. }
  641. }
  642. };
  643. }
  644.  
  645. function preventDefault(event) {
  646. event.preventDefault();
  647. event.returnValue = false;
  648. return false;
  649. }
  650.  
  651. function Game(gameDiv, stickyNodes, ballOpts) {
  652. var stickyNodes, player1, physicsInterval, resizeInterval, listeners = [];
  653. player1 = new PlayerBall(gameDiv, stickyNodes, ballOpts, false);
  654. player1.init();
  655. player1.setXY(300, 300);
  656. window.scrollTo(0, 200);
  657.  
  658. function on_resize() {
  659. player1.setDocSize(jQuery(document).width() - 5,
  660. jQuery(document).height() - 5);
  661. }
  662. on_resize();
  663.  
  664. /* touch events - always on? */
  665. document.addEventListener('touchstart', function (event) {
  666. if (event.touches.length === 1) {
  667. player1.setAccel(true);
  668. return preventDefault(event);
  669. }
  670. }, true);
  671. document.addEventListener('touchmove', function (event) {
  672. player1.setAccelTarget(event.touches[0].pageX,
  673. event.touches[0].pageY);
  674. }, true);
  675. document.addEventListener('touchend', function (event) {
  676. if (event.touches.length === 0) {
  677. player1.setAccel(false);
  678. return preventDefault(event);
  679. }
  680. }, true);
  681.  
  682. if (ballOpts.MOUSEB !== -5) {
  683. /* mouse buttons */
  684. document.addEventListener('mousemove', function (event) {
  685. player1.setAccelTarget(event.pageX, event.pageY);
  686. }, true);
  687. document.addEventListener('mousedown', function (event) {
  688. if (event.button === ballOpts.MOUSEB) {
  689. player1.setAccel(true);
  690. return preventDefault(event);
  691. }
  692. }, true);
  693. document.addEventListener('mouseup', function (event) {
  694. if (event.button === ballOpts.MOUSEB) {
  695. player1.setAccel(false);
  696. return preventDefault(event);
  697. }
  698. }, true);
  699.  
  700. if (ballOpts.MOUSEB === 0) {
  701. /* block click events. */
  702. document.addEventListener('click', function (event) {
  703. if (event.button === 0) {
  704. return preventDefault(event);
  705. }
  706. }, true);
  707. } else if (ballOpts.MOUSEB === 2) {
  708. /* block right-click context menu. */
  709. document.addEventListener('contextmenu', preventDefault, true);
  710. }
  711. }
  712.  
  713. physicsInterval = setInterval(function () {
  714. player1.updatePhysics();
  715. }, 25);
  716. resizeInterval = setInterval(on_resize, 1000);
  717. }
  718.  
  719. function whenAllLoaded(gameDiv, popup, stickyNodes) {
  720. stickyNodes.finalize(jQuery(document).width(), jQuery(document).height());
  721. jQuery('#loadingp').empty();
  722. jQuery('<button>Start!</button>').click(function () {
  723. var game, bgmusic, ballOpts;
  724. if (jQuery('#bgmusicc').attr('checked')) {
  725. if (!(bgmusic = document.getElementById('khbgmusic'))) {
  726. bgmusic = document.createElement('audio');
  727. bgmusic.id = 'khbgmusic';
  728. bgmusic.loop = 'loop';
  729. bgmusic.src = 'http://kathack.com/js/katamari.mp3';
  730. gameDiv.appendChild(bgmusic);
  731. }
  732. bgmusic.play();
  733. }
  734. ballOpts = {
  735. color: jQuery('#khcolor').val(),
  736. VOL_MULT: parseFloat(jQuery('#vol_mult').val()),
  737. MAX_ATTACHED_VISIBLE: parseInt(jQuery('#maxAtt').val(), 10),
  738. CHECK_VOLS: (jQuery('#checkv').attr('checked'))? true : false,
  739. MOUSEB: parseInt(jQuery('#mouseb').val(), 10)
  740. };
  741. gameDiv.removeChild(popup);
  742. game = new Game(gameDiv, stickyNodes, ballOpts);
  743. }).appendTo('#loadingp');
  744. }
  745.  
  746. function buildPopup(gameDiv) {
  747. var d = document.createElement('div'), b;
  748. d.style.cssText = '\
  749. position: fixed;\
  750. left: 50%;\
  751. top: 50%;\
  752. width: 400px;\
  753. margin-left:-200px;\
  754. margin-top:-150px;\
  755. border:1px solid black;\
  756. background-color:white;\
  757. color:black;\
  758. padding:20px;\
  759. font-size:13px;\
  760. text-align:left;\
  761. z-index:501;';
  762. d.innerHTML = '<h1 style="font-size:16pt">\
  763. <a href="http://kathack.com/" style="color:blue;text-decoration:none;">\
  764. Katamari!</a></h1>\
  765. <button style="position:absolute;top:0;right:0;">X</button>\
  766. <p>Controls: Hold down <b><select id="mouseb">\
  767. <option value="0">Left-Click</option>\
  768. <option value="2" selected="selected">Right-Click</option>\
  769. <option value="-5">Touch</option>\
  770. </select></b> to control the ball!</p>\
  771. <div><label>Background Music? \
  772. <input id="bgmusicc" type="checkbox" checked="checked" /></label></div>\
  773. <div style="text-align:right; color:gray;">\
  774. <label>Katamari Color: <select id="khcolor">\
  775. <option value="#ff0000" style="background-color:#ff0000;color:#ff0000"> r </option>\
  776. <option value="#00ff00" style="background-color:#00ff00;color:#00ff00"> g </option>\
  777. <option value="#0000ff" style="background-color:#0000ff;color:#0000ff"> b </option>\
  778. <option selected="selected" value="#7D26CD" style="background-color:#7D26CD;color:#7D26CD"> p \
  779. </option></select></label><br />\
  780. <label title="Lower this if the game gets slow.">\
  781. Max Attached Objects: <select id="maxAtt">\
  782. <option>25</option>\
  783. <option>50</option>\
  784. <option selected="selected">75</option>\
  785. <option>100</option>\
  786. <option>9000</option></select></label><br />\
  787. <label title="How much to grow when an object is picked up.">\
  788. Growth Speed: <input id="vol_mult" type="text" size="6" value="1.0" />\
  789. </label><br />\
  790. <label title="Bigger objects require a bigger katamari to pick up.">\
  791. Realistic Pickups? <input id="checkv" type="checkbox" checked="checked" />\
  792. </label></div>\
  793. <p id="loadingp">Loading!</p>';
  794. gameDiv.appendChild(d);
  795. d.getElementsByTagName('button')[0].addEventListener('click', function () {
  796. gameDiv.removeChild(d);
  797. }, true);
  798. return d;
  799. }
  800.  
  801. function main() {
  802. var gameDiv, checkInterval, stickyNodes, popup;
  803.  
  804. gameDiv = document.createElement('div');
  805. gameDiv.khIgnore = true;
  806. document.body.appendChild(gameDiv);
  807. popup = buildPopup(gameDiv);
  808.  
  809. /* setTimeout so that the popup displays before we freeze. */
  810. setTimeout(function () {
  811. var i, len, el;
  812. window.khNodes.addWords(document.body);
  813. for (i = 0, len = document.body.childNodes.length; i < len; i++) {
  814. el = document.body.childNodes[i];
  815. window.khNodes.addTagNames(el, [
  816. 'button', 'canvas', 'iframe', 'img', 'input', 'select',
  817. 'textarea'
  818. ]);
  819. }
  820.  
  821. checkInterval = setInterval(function () {
  822. if (window.jQuery) {
  823. clearInterval(checkInterval);
  824. whenAllLoaded(gameDiv, popup, window.khNodes);
  825. }
  826. }, 100);
  827. }, 0);
  828. }
  829.  
  830. if (!window.noMain) {
  831. main();
  832. }
  833.  
  834.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement