Precise slither

Simplified client for slither.io

  1. // ==UserScript==
  2. // @name Precise slither
  3. // @namespace precise_slither
  4. // @version 0.2
  5. // @description Simplified client for slither.io
  6. // @author Sr_2_0
  7. // @match *://slither.com/io
  8. // @match *://slither.io/
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // you can change these values
  17. const serverIpAndPortForInputField_29 = '57.129.37.42:444';
  18. const maxFps_29 = 40;
  19.  
  20. // rewrite original slither client
  21. document.getElementsByTagName('html')[0].innerHTML = `
  22. <head>
  23. <title>precise slither</title>
  24. </head>
  25. <body>
  26. </body>
  27. `;
  28.  
  29. let ws_29;
  30.  
  31. let myId_29 = -1;
  32. let myIdWas_29 = false;
  33.  
  34. let snakes_29 = [];
  35. let preys_29 = [];
  36. let sectors_29 = [];
  37. let foods_29 = [];
  38. let foods_c_29 = 0;
  39.  
  40. let grd_29 = 16384;
  41. let mscps_29 = 0;
  42. let fmlts_29 = [];
  43. let fpsls_29 = [];
  44. let sector_size_29 = 480;
  45. let spangdv_29 = 4.8;
  46. let nsp1_29 = 4.25;
  47. let nsp2_29 = .5;
  48. let nsp3_29 = 12;
  49. let mamu_29 = .033;
  50. let mamu2_29 = .028;
  51. let cst_29 = .43;
  52. let protocol_version_29 = 2;
  53.  
  54. let real_flux_grd_29 = grd_29;
  55. let rfgrdForMinimap_29 = real_flux_grd_29;
  56.  
  57. let playersInfo_29 = "";
  58.  
  59. let minimapObjs_29 = [];
  60.  
  61. let vfr_29 = 0;
  62. let vfrb_29 = 0;
  63. let fr_29 = 0;
  64. let lfr_29 = 0;
  65.  
  66. let ltm_29 = Date.now();
  67.  
  68. let last_ping_mtm_29 = 0;
  69. let wfpr_29 = false;
  70.  
  71. let last_accel_mtm_29 = 0;
  72. let lstSnddAclState_29 = false;
  73. let acceleration_29 = false;
  74.  
  75. let last_e_mtm_29 = 0;
  76. let prevComndForEang_29 = -1;
  77. let whereMouseX_29 = -1;
  78. let whereMouseY_29 = -1;
  79.  
  80. let oefTimerId_29;
  81. let oefTimerStarted_29 = false;
  82.  
  83. let lastStartOtrisTime_29;
  84.  
  85. let currentFps_29 = 0;
  86. let currentFpsLastShowTime_29 = 0;
  87.  
  88. let gameExists_29 = false;
  89. let wantCloseCurrentGame_29 = false;
  90. let wantNewGame_29 = false;
  91. let buttonFunctionality_29 = true;
  92.  
  93. let xx_29 = 0;
  94. let yy_29 = 0;
  95. let cm1_29;
  96.  
  97. const pi2_29 = 2 * Math.PI;
  98.  
  99. function prepareNewGame_29() {
  100. gameExists_29 = true;
  101. myIdWas_29 = false;
  102. snakes_29 = [];
  103. preys_29 = [];
  104. sectors_29 = [];
  105. foods_29 = [];
  106. foods_c_29 = 0;
  107. xx_29 = 0;
  108. yy_29 = 0;
  109. playersInfo_29 = "";
  110. minimapObjs_29 = [];
  111. last_ping_mtm_29 = 0;
  112. wfpr_29 = false;
  113. last_accel_mtm_29 = 0;
  114. lstSnddAclState_29 = false;
  115. acceleration_29 = false;
  116. last_e_mtm_29 = 0;
  117. prevComndForEang_29 = -1;
  118. whereMouseX_29 = -1;
  119. whereMouseY_29 = -1;
  120. connect_29();
  121. }
  122.  
  123. function decodeSecret_29(sv, idba) {
  124. function qff9x_29(b) {
  125. eval(b);
  126. if (0 < idba.length) {
  127. b = 0;
  128. for (let d, a, e, c = 0; c < idba.length; c++) {
  129. d = 65,
  130. a = idba[c],
  131. 97 <= a && (d += 32, a -= 32),
  132. a -= 65,
  133. 0 == c && (b = 2 + a),
  134. e = a + b,
  135. e %= 26,
  136. b += 3 + a,
  137. idba[c] = e + d;
  138. }
  139. }
  140. };
  141. let a = "", b;
  142. for (let d = 0, e = 23, f = 0, g = 0; g < sv.length; ) {
  143. b = sv[g],
  144. g++,
  145. 96 >= b && (b += 32),
  146. b = (b - 97 - e) % 26,
  147. 0 > b && (b += 26),
  148. d *= 16,
  149. d += b,
  150. e += 17,
  151. 1 == f ? (a += String.fromCharCode(d), f = d = 0) : f++;
  152. }
  153. qff9x_29(a);
  154. for (a = 0; a < sv.length; a++)
  155. if (b = sv[a], 65 > b || 122 < b)
  156. return !1;
  157. return !0;
  158. };
  159.  
  160. // needed to calculate a score
  161. function setMscps_29(nmscps) {
  162. if (nmscps != mscps_29) {
  163. mscps_29 = nmscps;
  164. fmlts_29 = [];
  165. fpsls_29 = [];
  166. for (let i = 0; i <= mscps_29; i++) {
  167. if (i >= mscps_29)
  168. fmlts_29.push(fmlts_29[i - 1]);
  169. else
  170. fmlts_29.push(Math.pow(1 - i / mscps_29, 2.25));
  171. if (i == 0)
  172. fpsls_29.push(0);
  173. else
  174. fpsls_29.push(fpsls_29[i - 1] + 1 / fmlts_29[i - 1])
  175. }
  176. let t_fmlt = fmlts_29[fmlts_29.length - 1];
  177. let t_fpsl = fpsls_29[fpsls_29.length - 1];
  178. for (let i = 0; i < 2048; i++) {
  179. fmlts_29.push(t_fmlt);
  180. fpsls_29.push(t_fpsl)
  181. }
  182. }
  183. }
  184.  
  185. function newSnake_29(id, xx, yy, cv, ang, pts) {
  186. let o = {};
  187. o.id = id;
  188. o.xx = xx;
  189. o.yy = yy;
  190. o.chl = 0;
  191. o.tsp = 0;
  192. o.sc = 1;
  193. o.ssp = nsp1_29 + nsp2_29 * o.sc;
  194. o.fsp = o.ssp + .1;
  195. o.msp = nsp3_29;
  196. o.msl = 42;
  197. o.fam = 0;
  198. o.rsc = 0;
  199. o.ang = ang;
  200. o.eang = ang;
  201. o.wang = ang;
  202. o.sp = 2;
  203. if (pts) {
  204. o.pts = pts;
  205. o.sct = pts.length;
  206. } else {
  207. o.pts = [];
  208. o.sct = 0
  209. }
  210. o.tl = o.sct + o.fam;
  211. o.cfl = o.tl;
  212. o.scang = 1;
  213. snakes_29.push(o);
  214. return o;
  215. }
  216.  
  217. function newPrey_29(id, xx, yy, rad, dir, wang, ang, speed) {
  218. let pr = {};
  219. pr.id = id;
  220. pr.xx = xx;
  221. pr.yy = yy;
  222. pr.sz = rad;
  223. pr.dir = dir;
  224. pr.wang = wang;
  225. pr.ang = ang;
  226. pr.sp = speed;
  227. preys_29.push(pr);
  228. return pr;
  229. }
  230.  
  231. function newFood_29(id, xx, yy, rad) {
  232. let fo = {};
  233. fo.id = id;
  234. fo.xx = xx;
  235. fo.yy = yy;
  236. fo.sz = rad;
  237. foods_29[foods_c_29++] = fo;
  238. return fo;
  239. }
  240.  
  241. // function is executed before each frame is drawn
  242. function oef_29() {
  243. let ctm = Date.now();
  244. vfr_29 = (ctm - ltm_29) / 8;
  245. if (vfr_29 > 5)
  246. vfr_29 = 5;
  247. if (vfr_29 < 1.56)
  248. vfr_29 = 1.56;
  249. ltm_29 = ctm;
  250. lfr_29 = fr_29;
  251. fr_29 += vfr_29;
  252. vfrb_29 = Math.floor(fr_29) - Math.floor(lfr_29);
  253.  
  254. if (!wantCloseCurrentGame_29 && !wfpr_29) {
  255. if (ctm - last_ping_mtm_29 > 250) {
  256. last_ping_mtm_29 = ctm;
  257. wfpr_29 = true;
  258. const ba = new Uint8Array([251]);
  259. ws_29.send(ba);
  260. }
  261. }
  262. if (!wantCloseCurrentGame_29 && acceleration_29 != lstSnddAclState_29 && ctm - last_accel_mtm_29 > 150) {
  263. lstSnddAclState_29 = acceleration_29;
  264. last_accel_mtm_29 = ctm;
  265. let ba = new Uint8Array(1);
  266. if (acceleration_29)
  267. ba[0] = 253;
  268. else
  269. ba[0] = 254;
  270. ws_29.send(ba);
  271. }
  272. if (!wantCloseCurrentGame_29 && ctm - last_e_mtm_29 > 100 && whereMouseX_29 != -1 && whereMouseY_29 != -1) {
  273. let centerX = playingArenaWidth / 2;
  274. let centerY = playingArenaHeight / 2;
  275. let differeX = whereMouseX_29 - centerX;
  276. let differeY = whereMouseY_29 - centerY;
  277. let angle = Math.atan2(differeY, differeX);
  278. if (angle < 0)
  279. angle += Math.PI * 2;
  280. let angleInt = Math.round(angle / Math.PI / 2 * 256);
  281. if (angleInt == 51) {
  282. if (angle < Math.PI * 2 / 256 * 51)
  283. angleInt = 50;
  284. }
  285. else if (angleInt >= 52 && angleInt <= 101) {
  286. angleInt -= 1;
  287. }
  288. else if (angleInt == 102) {
  289. if (angle < Math.PI * 2 / 256 * 102)
  290. angleInt = 100;
  291. else
  292. angleInt = 101;
  293. }
  294. else if (angleInt >= 103 && angleInt <= 152) {
  295. angleInt -= 2;
  296. }
  297. else if (angleInt == 153) {
  298. if (angle < Math.PI * 2 / 256 * 153)
  299. angleInt = 150;
  300. else
  301. angleInt = 151;
  302. }
  303. else if (angleInt >= 154 && angleInt <= 203) {
  304. angleInt -= 3;
  305. }
  306. else if (angleInt == 204) {
  307. if (angle < Math.PI * 2 / 256 * 204)
  308. angleInt = 200;
  309. else
  310. angleInt = 201;
  311. }
  312. else if (angleInt >= 205 && angleInt <= 254) {
  313. angleInt -= 4;
  314. }
  315. else if (angleInt == 255) {
  316. if (angle < Math.PI * 2 / 256 * 255)
  317. angleInt = 250;
  318. else
  319. angleInt = 0;
  320. }
  321. else if (angleInt == 256) {
  322. angleInt = 0;
  323. }
  324. if (angleInt != prevComndForEang_29) {
  325. prevComndForEang_29 = angleInt;
  326. last_e_mtm_29 = ctm;
  327. let ba = new Uint8Array([angleInt]);
  328. ws_29.send(ba);
  329. }
  330. }
  331.  
  332. let mang, vang;
  333. for (let i = snakes_29.length - 1; i >= 0; i--) {
  334. let o = snakes_29[i];
  335. mang = mamu_29 * vfr_29 * o.scang * o.spang;
  336. let csp = o.sp * vfr_29 / 4;
  337. if (csp > o.msl)
  338. csp = o.msl;
  339. if (o.tsp != o.sp)
  340. if (o.tsp < o.sp) {
  341. o.tsp += .3 * vfr_29;
  342. if (o.tsp > o.sp)
  343. o.tsp = o.sp;
  344. } else {
  345. o.tsp -= .3 * vfr_29;
  346. if (o.tsp < o.sp)
  347. o.tsp = o.sp;
  348. }
  349. o.cfl = o.tl;
  350. if (o.dir == 1) {
  351. o.ang -= mang;
  352. if (o.ang < 0 || o.ang >= pi2_29)
  353. o.ang %= pi2_29;
  354. if (o.ang < 0)
  355. o.ang += pi2_29;
  356. vang = (o.wang - o.ang) % pi2_29;
  357. if (vang < 0)
  358. vang += pi2_29;
  359. if (vang > Math.PI)
  360. vang -= pi2_29;
  361. if (vang > 0) {
  362. o.ang = o.wang;
  363. o.dir = 0
  364. }
  365. } else if (o.dir == 2) {
  366. o.ang += mang;
  367. if (o.ang < 0 || o.ang >= pi2_29)
  368. o.ang %= pi2_29;
  369. if (o.ang < 0)
  370. o.ang += pi2_29;
  371. vang = (o.wang - o.ang) % pi2_29;
  372. if (vang < 0)
  373. vang += pi2_29;
  374. if (vang > Math.PI)
  375. vang -= pi2_29;
  376. if (vang < 0) {
  377. o.ang = o.wang;
  378. o.dir = 0
  379. }
  380. } else
  381. o.ang = o.wang;
  382. let po = o.pts[o.pts.length - 1];
  383. o.xx += Math.cos(o.ang) * csp;
  384. o.yy += Math.sin(o.ang) * csp;
  385. o.chl += csp / o.msl
  386. if (vfrb_29 > 0) {
  387. for (let j = o.pts.length - 1; j >= 0; j--) {
  388. let po = o.pts[j];
  389. if (po.dying) {
  390. po.da += .0015 * vfrb_29;
  391. if (po.da > 1) {
  392. o.pts.splice(j, 1);
  393. }
  394. }
  395. }
  396. }
  397. }
  398. for (let i = preys_29.length - 1; i >= 0; i--) {
  399. let pr = preys_29[i];
  400. mang = mamu2_29 * vfr_29;
  401. let csp = pr.sp * vfr_29 / 4;
  402. if (pr.dir == 1) {
  403. pr.ang -= mang;
  404. if (pr.ang < 0 || pr.ang >= pi2_29)
  405. pr.ang %= pi2_29;
  406. if (pr.ang < 0)
  407. pr.ang += pi2_29;
  408. vang = (pr.wang - pr.ang) % pi2_29;
  409. if (vang < 0)
  410. vang += pi2_29;
  411. if (vang > Math.PI)
  412. vang -= pi2_29;
  413. if (vang > 0) {
  414. pr.ang = pr.wang;
  415. pr.dir = 0
  416. }
  417. } else if (pr.dir == 2) {
  418. pr.ang += mang;
  419. if (pr.ang < 0 || pr.ang >= pi2_29)
  420. pr.ang %= pi2_29;
  421. if (pr.ang < 0)
  422. pr.ang += pi2_29;
  423. vang = (pr.wang - pr.ang) % pi2_29;
  424. if (vang < 0)
  425. vang += pi2_29;
  426. if (vang > Math.PI)
  427. vang -= pi2_29;
  428. if (vang < 0) {
  429. pr.ang = pr.wang;
  430. pr.dir = 0
  431. }
  432. } else
  433. pr.ang = pr.wang;
  434. pr.xx += Math.cos(pr.ang) * csp;
  435. pr.yy += Math.sin(pr.ang) * csp;
  436. }
  437. vfr_29 = 0;
  438. vfrb_29 = 0;
  439. drawFrame();
  440. oefTimerId_29 = setTimeout(oef_29, Math.max(lastStartOtrisTime_29 + (1000 / maxFps_29) - Date.now(), 0));
  441. if (wantCloseCurrentGame_29 && ws_29.readyState === WebSocket.OPEN)
  442. ws_29.close();
  443. }
  444.  
  445. function connect_29() {
  446. ws_29 = new WebSocket("ws://" + serverIpAndPortField.value + "/slither");
  447. ws_29.binaryType = "arraybuffer";
  448. ws_29.onopen = function() {
  449. const ba = new Uint8Array([99, 4]);
  450. ws_29.send(ba);
  451. };
  452. ws_29.onmessage = function(e) {
  453. let a = new Uint8Array(e.data);
  454. if (a.length >= 2) {
  455. let cmd = String.fromCharCode(a[2]);
  456. let m = 3;
  457. let alen = a.length;
  458. let plen = a.length - 2;
  459. let dlen = a.length - 3;
  460.  
  461. // initial setup
  462. if (cmd == "a") {
  463. grd_29 = a[m] << 16 | a[m + 1] << 8 | a[m + 2];
  464. m += 3;
  465. real_flux_grd_29 = grd_29;
  466. rfgrdForMinimap_29 = real_flux_grd_29;
  467. let nmscps = a[m] << 8 | a[m + 1];
  468. m += 2;
  469. sector_size_29 = a[m] << 8 | a[m + 1];
  470. m += 2;
  471. m += 2;
  472. spangdv_29 = a[m] / 10;
  473. m++;
  474. nsp1_29 = (a[m] << 8 | a[m + 1]) / 100;
  475. m += 2;
  476. nsp2_29 = (a[m] << 8 | a[m + 1]) / 100;
  477. m += 2;
  478. nsp3_29 = (a[m] << 8 | a[m + 1]) / 100;
  479. m += 2;
  480. mamu_29 = (a[m] << 8 | a[m + 1]) / 1E3;
  481. m += 2;
  482. mamu2_29 = (a[m] << 8 | a[m + 1]) / 1E3;
  483. m += 2;
  484. cst_29 = (a[m] << 8 | a[m + 1]) / 1E3;
  485. m += 2;
  486. if (m < alen) {
  487. protocol_version_29 = a[m];
  488. m++;
  489. if (protocol_version_29 != 13) {
  490. ws_29.close();
  491. }
  492. }
  493. setMscps_29(nmscps);
  494. }
  495. // snake rotation
  496. else if (cmd == "e" || cmd == "E" || cmd == "3" || cmd == "4" || cmd == "5") {
  497. let id = a[m] << 8 | a[m + 1];
  498. m += 2;
  499. let dir = -1;
  500. let ang = -1;
  501. let wang = -1;
  502. let speed = -1;
  503. if (protocol_version_29 >= 6)
  504. if (plen == 6) {
  505. if (cmd == "e")
  506. dir = 1;
  507. else
  508. dir = 2;
  509. ang = a[m] * 2 * Math.PI / 256;
  510. m++;
  511. wang = a[m] * 2 * Math.PI / 256;
  512. m++;
  513. speed = a[m] / 18;
  514. m++
  515. } else if (plen == 5)
  516. if (cmd == "e") {
  517. ang = a[m] * 2 * Math.PI / 256;
  518. m++;
  519. speed = a[m] / 18;
  520. m++
  521. } else if (cmd == "E") {
  522. dir = 1;
  523. wang = a[m] * 2 * Math.PI / 256;
  524. m++;
  525. speed = a[m] / 18;
  526. m++
  527. } else if (cmd == "4") {
  528. dir = 2;
  529. wang = a[m] * 2 * Math.PI / 256;
  530. m++;
  531. speed = a[m] / 18;
  532. m++
  533. } else if (cmd == "3") {
  534. dir = 1;
  535. ang = a[m] * 2 * Math.PI / 256;
  536. m++;
  537. wang = a[m] * 2 * Math.PI / 256;
  538. m++
  539. } else {
  540. if (cmd == "5") {
  541. dir = 2;
  542. ang = a[m] * 2 * Math.PI / 256;
  543. m++;
  544. wang = a[m] * 2 * Math.PI / 256;
  545. m++
  546. }
  547. }
  548. else {
  549. if (plen == 4)
  550. if (cmd == "e") {
  551. ang = a[m] * 2 * Math.PI / 256;
  552. m++
  553. } else if (cmd == "E") {
  554. dir = 1;
  555. wang = a[m] * 2 * Math.PI / 256;
  556. m++
  557. } else if (cmd == "4") {
  558. dir = 2;
  559. wang = a[m] * 2 * Math.PI / 256;
  560. m++
  561. } else if (cmd == "3") {
  562. speed = a[m] / 18;
  563. m++
  564. }
  565. }
  566. else if (protocol_version_29 >= 3) {
  567. if (cmd != "3")
  568. if (plen == 8 || plen == 7 || plen == 6 && cmd != "3" || plen == 5 && cmd != "3")
  569. if (cmd == "e")
  570. dir = 1;
  571. else
  572. dir = 2;
  573. if (plen == 8 || plen == 7 || plen == 5 && cmd == "3" || plen == 6 && cmd == "3") {
  574. ang = (a[m] << 8 | a[m + 1]) * 2 * Math.PI / 65535;
  575. m += 2
  576. }
  577. if (plen == 8 || plen == 7 || plen == 5 && cmd != "3" || plen == 6 && cmd != "3") {
  578. wang = (a[m] << 8 | a[m + 1]) * 2 * Math.PI / 65535;
  579. m += 2
  580. }
  581. if (plen == 8 || plen == 6 || plen == 4) {
  582. speed = a[m] / 18;
  583. m++
  584. }
  585. } else {
  586. if (dlen == 11 || dlen == 8 || dlen == 9 || dlen == 6) {
  587. dir = a[m] - 48;
  588. m++
  589. }
  590. if (dlen == 11 || dlen == 7 || dlen == 9 || dlen == 5) {
  591. ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  592. m += 3
  593. }
  594. if (dlen == 11 || dlen == 8 || dlen == 9 || dlen == 6) {
  595. wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  596. m += 3
  597. }
  598. if (dlen == 11 || dlen == 7 || dlen == 8 || dlen == 4) {
  599. speed = (a[m] << 8 | a[m + 1]) / 1E3;
  600. m += 2
  601. }
  602. }
  603. let o;
  604. for (let i = snakes_29.length - 1; i >= 0; i--) {
  605. if (snakes_29[i].id == id) {
  606. o = snakes_29[i];
  607. break;
  608. }
  609. }
  610. if (o) {
  611. if (dir != -1)
  612. o.dir = dir;
  613. if (ang != -1) {
  614. o.ang = ang
  615. }
  616. if (wang != -1) {
  617. o.wang = wang;
  618. o.eang = wang;
  619. }
  620. if (speed != -1) {
  621. o.sp = speed;
  622. o.spang = o.sp / spangdv_29;
  623. if (o.spang > 1)
  624. o.spang = 1;
  625. }
  626. }
  627. }
  628. // pre-init response
  629. else if (cmd == "6") {
  630. let server_version = new Uint8Array(alen - m);
  631. for (let i = 0; m < alen; i++) {
  632. server_version[i] = a[m];
  633. m++;
  634. }
  635. let idba = new Uint8Array(24);
  636. decodeSecret_29(server_version, idba);
  637. ws_29.send(idba);
  638.  
  639. const lgba = new Uint8Array([115, 12, 1, 2, 116, 116, 0, 255]);
  640. ws_29.send(lgba);
  641.  
  642. // send first ping
  643. last_ping_mtm_29 = Date.now();
  644. wfpr_29 = true;
  645. const ba = new Uint8Array([251]);
  646. ws_29.send(ba);
  647. }
  648. // update snake last body part fullness (fam)
  649. else if (cmd == "h") {
  650. let id = a[m] << 8 | a[m + 1];
  651. m += 2;
  652. let fam = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 16777215;
  653. m += 3;
  654. let o;
  655. for (let i = snakes_29.length - 1; i >= 0; i--) {
  656. if (snakes_29[i].id == id) {
  657. o = snakes_29[i];
  658. break;
  659. }
  660. }
  661. if (o) {
  662. o.fam = fam;
  663. o.tl = o.sct + o.fam;
  664. }
  665. }
  666. // remove snake part
  667. else if (cmd == "r") {
  668. let id = a[m] << 8 | a[m + 1];
  669. m += 2;
  670. let o;
  671. for (let i = snakes_29.length - 1; i >= 0; i--) {
  672. if (snakes_29[i].id == id) {
  673. o = snakes_29[i];
  674. break;
  675. }
  676. }
  677. if (o) {
  678. if (dlen >= 4) {
  679. o.fam = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 16777215;
  680. m += 3
  681. }
  682. for (let j = 0; j < o.pts.length; j++)
  683. if (!o.pts[j].dying) {
  684. o.pts[j].dying = true;
  685. o.sct--;
  686. o.sc = Math.min(6, 1 + (o.sct - 2) / 106);
  687. o.scang = .13 + .87 * Math.pow((7 - o.sc) / 6, 2);
  688. o.ssp = nsp1_29 + nsp2_29 * o.sc;
  689. o.fsp = o.ssp + .1;
  690. break;
  691. }
  692. o.tl = o.sct + o.fam;
  693. }
  694. }
  695. // update number of snake parts that you lost while spinning in a closed circle (rsc)
  696. else if (cmd == "R") {
  697. for (let i = snakes_29.length - 1; i >= 0; i--) {
  698. if (snakes_29[i].id == myId_29) {
  699. snakes_29[i].rsc = a[m];
  700. break;
  701. }
  702. }
  703. m++;
  704. }
  705. // move or increase snake
  706. else if (cmd == "g" || cmd == "n" || cmd == "G" || cmd == "N") {
  707. let adding_only = cmd == "n" || cmd == "N";
  708. let id = a[m] << 8 | a[m + 1];
  709. m += 2;
  710. let o;
  711. for (let i = snakes_29.length - 1; i >= 0; i--) {
  712. if (snakes_29[i].id == id) {
  713. o = snakes_29[i];
  714. break;
  715. }
  716. }
  717. if (o) {
  718. if (adding_only)
  719. o.sct++;
  720. else
  721. for (let j = 0; j < o.pts.length; j++)
  722. if (!o.pts[j].dying) {
  723. o.pts[j].dying = true;
  724. break
  725. }
  726. let po = o.pts[o.pts.length - 1];
  727. let lpo = po;
  728. let mpo;
  729. let mv;
  730. let lmpo;
  731. if (protocol_version_29 >= 3)
  732. if (cmd == "g" || cmd == "n") {
  733. xx_29 = a[m] << 8 | a[m + 1];
  734. m += 2;
  735. yy_29 = a[m] << 8 | a[m + 1];
  736. m += 2
  737. } else {
  738. xx_29 = lpo.xx + a[m] - 128;
  739. m++;
  740. yy_29 = lpo.yy + a[m] - 128;
  741. m++;
  742. }
  743. else {
  744. xx_29 = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  745. m += 3;
  746. yy_29 = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  747. m += 3
  748. }
  749. if (adding_only) {
  750. o.fam = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 16777215;
  751. m += 3
  752. }
  753. po = {};
  754. po.xx = xx_29;
  755. po.yy = yy_29;
  756. po.da = 0;
  757. o.pts.push(po);
  758. let k = o.pts.length - 3;
  759. let n;
  760. if (k >= 1) {
  761. lmpo = o.pts[k];
  762. n = 0;
  763. mv = 0;
  764. for (let j = k - 1; j >= 0; j--) {
  765. mpo = o.pts[j];
  766. n++;
  767. if (n <= 4)
  768. mv = cst_29 * n / 4;
  769. mpo.xx += (lmpo.xx - mpo.xx) * mv;
  770. mpo.yy += (lmpo.yy - mpo.yy) * mv;
  771. lmpo = mpo;
  772. }
  773. }
  774. o.sc = Math.min(6, 1 + (o.sct - 2) / 106);
  775. o.scang = .13 + .87 * Math.pow((7 - o.sc) / 6, 2);
  776. o.ssp = nsp1_29 + nsp2_29 * o.sc;
  777. o.fsp = o.ssp + .1;
  778. if (adding_only)
  779. o.tl = o.sct + o.fam;
  780. o.chl = 0;
  781. o.xx = xx_29;
  782. o.yy = yy_29;
  783. }
  784. }
  785. // leaderboard
  786. else if (cmd == "l") {
  787. playersInfo_29 = "";
  788. let nc = 0;
  789. let pos = 0;
  790. let v;
  791. let score;
  792. let my_pos = a[m];
  793. m++;
  794. let rank = a[m] << 8 | a[m + 1];
  795. m += 2;
  796. let snake_count = a[m] << 8 | a[m + 1];
  797. m += 2;
  798. while (m < alen) {
  799. let sct = a[m] << 8 | a[m + 1];
  800. m += 2;
  801. let fam = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 16777215;
  802. m += 3;
  803. m++;
  804. let nl = a[m];
  805. m++;
  806. pos++;
  807. let nk = "";
  808. for (let j = 0; j < nl; j++) {
  809. v = a[m];
  810. nk += String.fromCharCode(v);
  811. m++;
  812. }
  813. if (pos == my_pos) {
  814. nk = "tt";
  815. }
  816. nc++;
  817. score = Math.floor((fpsls_29[sct] + fam / fmlts_29[sct] - 1) * 15 - 5) / 1;
  818. playersInfo_29 += nc + " " + score + " " + nk + "\n";
  819. }
  820. playersInfo_29 += "\n " + rank + " / " + snake_count;
  821. }
  822. // add sector (for foods)
  823. else if (cmd == "W") {
  824. xx_29 = a[m];
  825. m++;
  826. yy_29 = a[m];
  827. m++;
  828. let o = {};
  829. o.xx = xx_29;
  830. o.yy = yy_29;
  831. sectors_29.push(o)
  832. }
  833. // remove sector (for foods)
  834. else if (cmd == "w") {
  835. xx_29 = a[m];
  836. m++;
  837. yy_29 = a[m];
  838. m++;
  839. cm1_29 = foods_c_29 - 1;
  840. for (let i = cm1_29; i >= 0; i--) {
  841. let fo = foods_29[i];
  842. if (fo.sx == xx_29)
  843. if (fo.sy == yy_29)
  844. if (i == cm1_29) {
  845. foods_29[i] = null;
  846. foods_c_29--;
  847. cm1_29--;
  848. } else {
  849. foods_29[i] = foods_29[cm1_29];
  850. foods_29[cm1_29] = null;
  851. foods_c_29--;
  852. cm1_29--;
  853. }
  854. }
  855. for (let i = sectors_29.length - 1; i >= 0; i--) {
  856. let o = sectors_29[i];
  857. if (o.xx == xx_29)
  858. if (o.yy == yy_29)
  859. sectors_29.splice(i, 1);
  860. }
  861. }
  862. // pong
  863. else if (cmd == "p") {
  864. wfpr_29 = false;
  865. }
  866. // update minimap
  867. else if (cmd == "M") {
  868. rfgrdForMinimap_29 = real_flux_grd_29;
  869. minimapObjs_29 = [];
  870. let moInd = 0;
  871. const u_m = [64, 32, 16, 8, 4, 2, 1];
  872. let sz = a[m] << 8 | a[m + 1];
  873. m += 2;
  874. if (sz > 512)
  875. sz = 512;
  876. minimapObjs_29[moInd] = {};
  877. minimapObjs_29[moInd].sz = sz;
  878. moInd++;
  879. let i;
  880. let k = 0;
  881. let xx = sz - 1;
  882. let yy = sz - 1;
  883. while (m < alen) {
  884. if (yy < 0)
  885. break;
  886. k = a[m++];
  887. if (k >= 128) {
  888. if (k == 255)
  889. k = 126 * a[m++];
  890. else
  891. k -= 128;
  892. for (i = 0; i < k; i++) {
  893. xx--;
  894. if (xx < 0) {
  895. xx = sz - 1;
  896. yy--;
  897. if (yy < 0)
  898. break;
  899. }
  900. }
  901. } else
  902. for (i = 0; i < 7; i++) {
  903. if ((k & u_m[i]) > 0) {
  904. minimapObjs_29[moInd] = {};
  905. minimapObjs_29[moInd].xx = xx;
  906. minimapObjs_29[moInd].yy = yy;
  907. moInd++;
  908. }
  909. xx--;
  910. if (xx < 0) {
  911. xx = sz - 1;
  912. yy--;
  913. if (yy < 0)
  914. break;
  915. }
  916. }
  917. }
  918. }
  919. // add/remove snake
  920. else if (cmd == "s") {
  921. let id = a[m] << 8 | a[m + 1];
  922. m += 2;
  923. if (myIdWas_29 == false) {
  924. myId_29 = id;
  925. myIdWas_29 = true;
  926. }
  927. if (dlen > 6) {
  928. let ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  929. m += 3;
  930. let dir = a[m] - 48;
  931. m++;
  932. let wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  933. m += 3;
  934. let speed = (a[m] << 8 | a[m + 1]) / 1E3;
  935. m += 2;
  936. let fam = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 16777215;
  937. m += 3;
  938. let cv = a[m];
  939. m++;
  940. let pts = [];
  941. let snx = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  942. m += 3;
  943. let sny = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  944. m += 3;
  945. let nl = a[m];
  946. m++;
  947. let nk = "";
  948. for (let j = 0; j < nl; j++) {
  949. nk += String.fromCharCode(a[m]);
  950. m++
  951. }
  952. let skl = a[m];
  953. m++;
  954. m += skl;
  955. m++;
  956. xx_29 = 0;
  957. yy_29 = 0;
  958. let fp = false;
  959. while (m < alen) {
  960. if (!fp) {
  961. xx_29 = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  962. m += 3;
  963. yy_29 = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  964. m += 3;
  965. fp = true
  966. } else {
  967. xx_29 += (a[m] - 127) / 2;
  968. m++;
  969. yy_29 += (a[m] - 127) / 2;
  970. m++
  971. }
  972. let po = {};
  973. po.dying = false;
  974. po.xx = xx_29;
  975. po.yy = yy_29;
  976. po.da = 0;
  977. pts.push(po)
  978. }
  979. let o = newSnake_29(id, snx, sny, cv, ang, pts);
  980. o.nk = nk;
  981. o.eang = o.wang = wang;
  982. o.sp = speed;
  983. o.spang = o.sp / spangdv_29;
  984. if (o.spang > 1)
  985. o.spang = 1;
  986. o.fam = fam;
  987. o.sc = Math.min(6, 1 + (o.sct - 2) / 106);
  988. o.scang = .13 + .87 * Math.pow((7 - o.sc) / 6, 2);
  989. o.ssp = nsp1_29 + nsp2_29 * o.sc;
  990. o.fsp = o.ssp + .1;
  991. o.tl = o.sct + o.fam;
  992. } else {
  993. m++;
  994. for (let i = snakes_29.length - 1; i >= 0; i--) {
  995. if (snakes_29[i].id == id) {
  996. snakes_29.splice(i, 1);
  997. break;
  998. }
  999. }
  1000. }
  1001. if (!oefTimerStarted_29) {
  1002. oefTimerStarted_29 = true;
  1003. oef_29();
  1004. }
  1005. buttonFunctionality_29 = true;
  1006. }
  1007. // add food
  1008. else if (cmd == "F") {
  1009. let gsi = false;
  1010. let sx, sy;
  1011. while (m < alen) {
  1012. m++;
  1013. xx_29 = a[m] << 8 | a[m + 1];
  1014. m += 2;
  1015. yy_29 = a[m] << 8 | a[m + 1];
  1016. m += 2;
  1017. let rad = a[m] / 5;
  1018. m++;
  1019. let id = yy_29 * grd_29 * 3 + xx_29;
  1020. if (rad > 0) {
  1021. let fo = newFood_29(id, xx_29, yy_29, rad);
  1022. if (!gsi) {
  1023. gsi = true;
  1024. sx = Math.floor(xx_29 / sector_size_29);
  1025. sy = Math.floor(yy_29 / sector_size_29);
  1026. }
  1027. fo.sx = sx;
  1028. fo.sy = sy;
  1029. }
  1030. else {
  1031. if (!gsi) {
  1032. gsi = true;
  1033. sx = Math.floor(xx_29 / sector_size_29);
  1034. sy = Math.floor(yy_29 / sector_size_29);
  1035. }
  1036. }
  1037. }
  1038. }
  1039. // add food
  1040. else if (cmd == "b" || cmd == "f") {
  1041. m++;
  1042. if (dlen > 4) {
  1043. xx_29 = a[m] << 8 | a[m + 1];
  1044. m += 2;
  1045. yy_29 = a[m] << 8 | a[m + 1];
  1046. m += 2;
  1047. let id = yy_29 * grd_29 * 3 + xx_29;
  1048. let rad = a[m] / 5;
  1049. m++;
  1050. if (rad > 0) {
  1051. let fo = newFood_29(id, xx_29, yy_29, rad);
  1052. fo.sx = Math.floor(xx_29 / sector_size_29);
  1053. fo.sy = Math.floor(yy_29 / sector_size_29);
  1054. }
  1055. }
  1056. }
  1057. // food eaten
  1058. else if (cmd == "c") {
  1059. let xx = a[m] << 8 | a[m + 1];
  1060. m += 2;
  1061. let yy = a[m] << 8 | a[m + 1];
  1062. m += 2;
  1063. let id = yy * grd_29 * 3 + xx
  1064. cm1_29 = foods_c_29 - 1;
  1065. for (let i = cm1_29; i >= 0; i--) {
  1066. let fo = foods_29[i];
  1067. if (fo.id == id) {
  1068. if (m + 2 <= alen) {
  1069. m += 2;
  1070. }
  1071. if (i == cm1_29) {
  1072. foods_29[i] = null;
  1073. foods_c_29--;
  1074. cm1_29--;
  1075. } else {
  1076. foods_29[i] = foods_29[cm1_29];
  1077. foods_29[cm1_29] = null;
  1078. foods_c_29--;
  1079. cm1_29--;
  1080. }
  1081. break;
  1082. }
  1083. }
  1084. }
  1085. // update prey
  1086. else if (cmd == "j") {
  1087. let id = a[m] << 8 | a[m + 1];
  1088. m += 2;
  1089. xx_29 = 1 + (a[m] << 8 | a[m + 1]) * 3;
  1090. m += 2;
  1091. yy_29 = 1 + (a[m] << 8 | a[m + 1]) * 3;
  1092. m += 2;
  1093. let pr = null;
  1094. for (let i = preys_29.length - 1; i >= 0; i--)
  1095. if (preys_29[i].id == id) {
  1096. pr = preys_29[i];
  1097. break;
  1098. }
  1099. if (pr) {
  1100. if (dlen == 15) {
  1101. pr.dir = a[m] - 48;
  1102. m++;
  1103. pr.ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1104. m += 3;
  1105. pr.wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1106. m += 3;
  1107. pr.sp = (a[m] << 8 | a[m + 1]) / 1E3;
  1108. m += 2
  1109. } else if (dlen == 11) {
  1110. pr.ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1111. m += 3;
  1112. pr.sp = (a[m] << 8 | a[m + 1]) / 1E3;
  1113. m += 2
  1114. } else if (dlen == 12) {
  1115. pr.dir = a[m] - 48;
  1116. m++;
  1117. pr.wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1118. m += 3;
  1119. pr.sp = (a[m] << 8 | a[m + 1]) / 1E3;
  1120. m += 2
  1121. } else if (dlen == 13) {
  1122. pr.dir = a[m] - 48;
  1123. m++;
  1124. pr.ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1125. m += 3;
  1126. pr.wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1127. m += 3
  1128. } else if (dlen == 9) {
  1129. pr.ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1130. m += 3
  1131. } else if (dlen == 10) {
  1132. pr.dir = a[m] - 48;
  1133. m++;
  1134. pr.wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1135. m += 3
  1136. } else if (dlen == 8) {
  1137. pr.sp = (a[m] << 8 | a[m + 1]) / 1E3;
  1138. m += 2
  1139. }
  1140. pr.xx = xx_29;
  1141. pr.yy = yy_29;
  1142. }
  1143. }
  1144. // add/remove prey
  1145. else if (cmd == "y") {
  1146. let id = a[m] << 8 | a[m + 1];
  1147. m += 2;
  1148. if (dlen == 2)
  1149. for (let i = preys_29.length - 1; i >= 0; i--) {
  1150. let pr = preys_29[i];
  1151. if (pr.id == id) {
  1152. preys_29.splice(i, 1);
  1153. break;
  1154. }
  1155. }
  1156. else if (dlen == 4) {
  1157. m += 2;
  1158. for (let i = preys_29.length - 1; i >= 0; i--) {
  1159. let pr = preys_29[i];
  1160. if (pr.id == id) {
  1161. preys_29.splice(i, 1);
  1162. break;
  1163. }
  1164. }
  1165. } else {
  1166. m++;
  1167. xx_29 = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  1168. m += 3;
  1169. yy_29 = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) / 5;
  1170. m += 3;
  1171. let rad = a[m] / 5;
  1172. m++;
  1173. let dir = a[m] - 48;
  1174. m++;
  1175. let wang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1176. m += 3;
  1177. let ang = (a[m] << 16 | a[m + 1] << 8 | a[m + 2]) * 2 * Math.PI / 16777215;
  1178. m += 3;
  1179. let speed = (a[m] << 8 | a[m + 1]) / 1E3;
  1180. m += 2;
  1181. newPrey_29(id, xx_29, yy_29, rad, dir, wang, ang, speed)
  1182. }
  1183. }
  1184. // update map border
  1185. else if (cmd == "z") {
  1186. real_flux_grd_29 = a[m] << 16 | a[m + 1] << 8 | a[m + 2];
  1187. }
  1188. }
  1189. };
  1190. ws_29.onerror = function(error) {
  1191. console.error('WebSocket error: ', error);
  1192. };
  1193. ws_29.onclose = function() {
  1194. if (oefTimerStarted_29) {
  1195. clearTimeout(oefTimerId_29);
  1196. }
  1197. oefTimerStarted_29 = false;
  1198. wantCloseCurrentGame_29 = false;
  1199. gameExists_29 = false;
  1200. buttonFunctionality_29 = true;
  1201.  
  1202. if (wantNewGame_29) {
  1203. buttonFunctionality_29 = false;
  1204. wantNewGame_29 = false;
  1205. prepareNewGame_29();
  1206. }
  1207. };
  1208. };
  1209.  
  1210.  
  1211. let playingArenaWidth = Math.ceil(window.innerWidth);
  1212. let playingArenaHeight = Math.ceil(window.innerHeight);
  1213. let plArCanv = document.createElement('canvas');
  1214. plArCanv.style.position = 'fixed';
  1215. plArCanv.style.left = '0px';
  1216. plArCanv.style.top = '0px';
  1217. plArCanv.width = playingArenaWidth;
  1218. plArCanv.height = playingArenaHeight;
  1219. plArCanv.style.zIndex = 1;
  1220. document.body.appendChild(plArCanv);
  1221. let ctx = plArCanv.getContext('2d');
  1222. let zoom = 0.3;
  1223. let centerSiX = 20000;
  1224. let centerSiY = 20000;
  1225. let strokeMoveWas;
  1226.  
  1227. function drawFrame() {
  1228. if (playingArenaWidth !== Math.ceil(window.innerWidth)) {
  1229. playingArenaWidth = Math.ceil(window.innerWidth);
  1230. plArCanv.width = playingArenaWidth;
  1231. }
  1232. if (playingArenaHeight !== Math.ceil(window.innerHeight)) {
  1233. playingArenaHeight = Math.ceil(window.innerHeight);
  1234. plArCanv.height = playingArenaHeight;
  1235. }
  1236. let mySnake;
  1237. let finded = false;
  1238. for (let i = 0; i < snakes_29.length; i++) {
  1239. if (snakes_29[i].id == myId_29 && snakes_29[i].pts.length >= 1) {
  1240. mySnake = snakes_29[i];
  1241. finded = true;
  1242. break;
  1243. }
  1244. }
  1245. if (!finded && gameExists_29) {
  1246. wantCloseCurrentGame_29 = true;
  1247. return;
  1248. }
  1249. if (mySnake) {
  1250. centerSiX = mySnake.xx;
  1251. centerSiY = mySnake.yy;
  1252. }
  1253. const leftSiX = centerSiX - ((playingArenaWidth / 2) / zoom);
  1254. const topSiY = centerSiY - ((playingArenaHeight / 2) / zoom);
  1255. const rightSiX = centerSiX + ((playingArenaWidth / 2) / zoom);
  1256. const bottomSiY = centerSiY + ((playingArenaHeight / 2) / zoom);
  1257.  
  1258. const currentTime = Date.now();
  1259. if (currentTime - currentFpsLastShowTime_29 > 200) {
  1260. currentFps_29 = Math.round(1000 / (currentTime - lastStartOtrisTime_29));
  1261. currentFpsLastShowTime_29 = currentTime;
  1262. }
  1263. lastStartOtrisTime_29 = currentTime;
  1264. // drawing background
  1265. const lightSquareColor = 'rgb(255,255,255)';
  1266. let darkSquareColor;
  1267. if (wfpr_29 && Date.now() - last_ping_mtm_29 > 500)
  1268. darkSquareColor = 'rgb(255,235,235)';
  1269. else
  1270. darkSquareColor = 'rgb(235,235,235)';
  1271. const smallSquareSizeSi = 220;
  1272. const smallSquareSizePi = smallSquareSizeSi * zoom;
  1273. const startCoordSiX = smallSquareSizeSi * Math.floor(leftSiX / smallSquareSizeSi);
  1274. const startCoordSiY = smallSquareSizeSi * Math.floor(topSiY / smallSquareSizeSi);
  1275. ctx.fillStyle = lightSquareColor;
  1276. ctx.fillRect(0, 0, playingArenaWidth, playingArenaHeight);
  1277. ctx.fillStyle = darkSquareColor;
  1278. for (let i = startCoordSiX; i < rightSiX; i += smallSquareSizeSi) {
  1279. for (let j = startCoordSiY; j < bottomSiY; j += smallSquareSizeSi) {
  1280. if ((i % (smallSquareSizeSi * 2) !== 0 && j % (smallSquareSizeSi * 2) === 0) || (i % (smallSquareSizeSi * 2) === 0 && j % (smallSquareSizeSi * 2) !== 0)) {
  1281. ctx.fillRect(playingArenaWidth / 2 - ((centerSiX - i) * zoom), playingArenaHeight / 2 - ((centerSiY - j) * zoom), smallSquareSizePi, smallSquareSizePi);
  1282. }
  1283. }
  1284. }
  1285.  
  1286. // drawing foods
  1287. ctx.fillStyle = 'blue';
  1288. let foodSide;
  1289. for (let i = 0; i < foods_c_29; i++) {
  1290. foodSide = foods_29[i].sz * 0.5 * zoom;
  1291. ctx.fillRect(siToPiX(foods_29[i].xx) - foodSide / 2, siToPiY(foods_29[i].yy) - foodSide / 2, foodSide, foodSide);
  1292. }
  1293.  
  1294. // drawing preys
  1295. ctx.fillStyle = 'rgba(165,42,42,0.7)';
  1296. let preyRad;
  1297. for (let i = 0; i < preys_29.length; i++) {
  1298. preyRad = preys_29[i].sz * 2;
  1299. ctx.beginPath();
  1300. ctx.arc(siToPiX(preys_29[i].xx), siToPiY(preys_29[i].yy), preyRad * zoom, 0, 2*Math.PI);
  1301. ctx.fill();
  1302. }
  1303. ctx.strokeStyle = 'rgb(36,255,255)';
  1304. ctx.lineWidth = 1;
  1305. let preyAngLineLen;
  1306. for (let i = 0; i < preys_29.length; i++) {
  1307. preyAngLineLen = preys_29[i].sp * 9.2;
  1308. strokeMoveWas = false;
  1309. ctx.beginPath();
  1310. addPointToPolyline(preys_29[i].xx + preyAngLineLen * Math.cos(preys_29[i].ang), preys_29[i].yy + preyAngLineLen * Math.sin(preys_29[i].ang));
  1311. addPointToPolyline(preys_29[i].xx, preys_29[i].yy);
  1312. ctx.stroke();
  1313. }
  1314. ctx.strokeStyle = 'red';
  1315. ctx.lineWidth = 1;
  1316. const preyWangLineLen = 25;
  1317. for (let i = 0; i < preys_29.length; i++) {
  1318. strokeMoveWas = false;
  1319. ctx.beginPath();
  1320. addPointToPolyline(preys_29[i].xx + preyWangLineLen * Math.cos(preys_29[i].wang), preys_29[i].yy + preyWangLineLen * Math.sin(preys_29[i].wang));
  1321. addPointToPolyline(preys_29[i].xx, preys_29[i].yy);
  1322. ctx.stroke();
  1323. }
  1324.  
  1325. // drawing snakes
  1326. ctx.lineCap = 'round';
  1327. ctx.lineJoin = 'round';
  1328. for (let i = 0; i < snakes_29.length; i++) {
  1329. if (snakes_29[i].pts.length >= 2) {
  1330. const lineNearHeadLen = distBetwCoords(snakes_29[i].xx, snakes_29[i].yy, snakes_29[i].pts[snakes_29[i].pts.length-1].xx, snakes_29[i].pts[snakes_29[i].pts.length-1].yy);
  1331. let oneFreshPartLen;
  1332. if (snakes_29[i].sct <= 1) oneFreshPartLen = 42.000;
  1333. if (snakes_29[i].sct == 2) oneFreshPartLen = 37.485;
  1334. if (snakes_29[i].sct == 3) oneFreshPartLen = 32.970;
  1335. if (snakes_29[i].sct == 4) oneFreshPartLen = 28.455;
  1336. if (snakes_29[i].sct >= 5) oneFreshPartLen = 23.940;
  1337. const lineNearHeadInFam = lineNearHeadLen / oneFreshPartLen;
  1338. const snakeLenghtInParts = Math.max(snakes_29[i].sct + snakes_29[i].fam - Math.max(lineNearHeadInFam, 0), 1);
  1339. let predSnakeLen = distBetwCoords(snakes_29[i].xx, snakes_29[i].yy, snakes_29[i].pts[snakes_29[i].pts.length - 1].xx, snakes_29[i].pts[snakes_29[i].pts.length - 1].yy);
  1340. let j;
  1341. for (j = snakes_29[i].pts.length - 2; j >= Math.max(snakes_29[i].pts.length - Math.floor(snakeLenghtInParts) - 2, 0); j--) {
  1342. predSnakeLen += distBetwCoords(snakes_29[i].pts[j].xx, snakes_29[i].pts[j].yy, snakes_29[i].pts[j+1].xx, snakes_29[i].pts[j+1].yy);
  1343. }
  1344. if (snakeLenghtInParts % 1 > 0 && j >= 0) {
  1345. let intermedX = snakes_29[i].pts[j+1].xx + (snakes_29[i].pts[j].xx - snakes_29[i].pts[j+1].xx) * (snakeLenghtInParts % 1) / 1;
  1346. let intermedY = snakes_29[i].pts[j+1].yy + (snakes_29[i].pts[j].yy - snakes_29[i].pts[j+1].yy) * (snakeLenghtInParts % 1) / 1;
  1347. predSnakeLen += distBetwCoords(intermedX, intermedY, snakes_29[i].pts[j+1].xx, snakes_29[i].pts[j+1].yy);
  1348. }
  1349. let newSnakeLen;
  1350. if (predSnakeLen <= 240) {
  1351. let bottomEdge = 80;
  1352. let topEdge = 240;
  1353. let newBottomEdge = predSnakeLen * 0.50;
  1354. let newTopEdge = predSnakeLen;
  1355. newSnakeLen = newBottomEdge + ((newTopEdge - newBottomEdge) * (predSnakeLen - bottomEdge) / (topEdge - bottomEdge));
  1356. }
  1357. else {
  1358. newSnakeLen = predSnakeLen;
  1359. }
  1360.  
  1361. if (snakes_29[i].id === myId_29)
  1362. ctx.strokeStyle = createRgbaStr(255, 0, 255, 0.8, 128, 0, 128, 0.8, snakes_29[i].sp);
  1363. else
  1364. ctx.strokeStyle = createRgbaStr(0, 128, 0, 0.9, 128, 0, 0, 0.9, snakes_29[i].sp);
  1365. ctx.lineWidth = snakes_29[i].sc * 31 * zoom;
  1366. strokeMoveWas = false;
  1367. ctx.beginPath();
  1368. addPointToPolyline(snakes_29[i].xx, snakes_29[i].yy);
  1369. if (newSnakeLen < lineNearHeadLen) {
  1370. const distKf = newSnakeLen / distBetwCoords(snakes_29[i].xx, snakes_29[i].yy, snakes_29[i].pts[snakes_29[i].pts.length - 1].xx, snakes_29[i].pts[snakes_29[i].pts.length - 1].yy);
  1371. addPointToPolyline(getIntermed(snakes_29[i].xx, snakes_29[i].pts[snakes_29[i].pts.length - 1].xx, distKf), getIntermed(snakes_29[i].yy, snakes_29[i].pts[snakes_29[i].pts.length - 1].yy, distKf));
  1372. }
  1373. else {
  1374. newSnakeLen -= lineNearHeadLen;
  1375. addPointToPolyline(snakes_29[i].pts[snakes_29[i].pts.length - 1].xx, snakes_29[i].pts[snakes_29[i].pts.length - 1].yy);
  1376. }
  1377. for (let j = snakes_29[i].pts.length - 2; j >= 0; j--) {
  1378. const temp = distBetwCoords(snakes_29[i].pts[j].xx, snakes_29[i].pts[j].yy, snakes_29[i].pts[j+1].xx, snakes_29[i].pts[j+1].yy);
  1379. if (newSnakeLen < temp) {
  1380. const distKf = newSnakeLen / distBetwCoords(snakes_29[i].pts[j+1].xx, snakes_29[i].pts[j+1].yy, snakes_29[i].pts[j].xx, snakes_29[i].pts[j].yy);
  1381. addPointToPolyline(getIntermed(snakes_29[i].pts[j+1].xx, snakes_29[i].pts[j].xx, distKf), getIntermed(snakes_29[i].pts[j+1].yy, snakes_29[i].pts[j].yy, distKf));
  1382. break;
  1383. }
  1384. addPointToPolyline(snakes_29[i].pts[j].xx, snakes_29[i].pts[j].yy);
  1385. newSnakeLen -= temp;
  1386. }
  1387. function getIntermed (X1orY1, X2orY2, distKoef) {
  1388. return X1orY1 + (X2orY2 - X1orY1) * distKoef;
  1389. }
  1390. ctx.stroke();
  1391. }
  1392. }
  1393. ctx.lineCap = 'butt';
  1394. ctx.lineJoin = 'miter';
  1395. ctx.strokeStyle = 'rgb(36,255,255)';
  1396. ctx.lineWidth = 1;
  1397. const snakeAngLineLen = 100;
  1398. for (let i = 0; i < snakes_29.length; i++) {
  1399. if (snakes_29[i].pts.length >= 2) {
  1400. strokeMoveWas = false;
  1401. ctx.beginPath();
  1402. addPointToPolyline(snakes_29[i].xx + snakeAngLineLen * Math.cos(snakes_29[i].ang), snakes_29[i].yy + snakeAngLineLen * Math.sin(snakes_29[i].ang));
  1403. addPointToPolyline(snakes_29[i].xx, snakes_29[i].yy);
  1404. ctx.stroke();
  1405. }
  1406. }
  1407. ctx.strokeStyle = 'red';
  1408. ctx.lineWidth = 1;
  1409. const snakeWangLineLen = 50;
  1410. for (let i = 0; i < snakes_29.length; i++) {
  1411. if (snakes_29[i].pts.length >= 2) {
  1412. if (snakes_29[i].id === myId_29)
  1413. ctx.strokeStyle = 'rgb(36,255,255)';
  1414. strokeMoveWas = false;
  1415. ctx.beginPath();
  1416. addPointToPolyline(snakes_29[i].xx + snakeWangLineLen * Math.cos(snakes_29[i].eang), snakes_29[i].yy + snakeWangLineLen * Math.sin(snakes_29[i].eang));
  1417. addPointToPolyline(snakes_29[i].xx, snakes_29[i].yy);
  1418. ctx.stroke();
  1419. if (snakes_29[i].id === myId_29)
  1420. ctx.strokeStyle = 'red';
  1421. }
  1422. }
  1423. ctx.fillStyle = 'rgba(0,0,0,0.5)';
  1424. ctx.textAlign = "center";
  1425. for (let i = 0; i < snakes_29.length; i++) {
  1426. if (snakes_29[i].pts.length >= 2) {
  1427. ctx.font = 37 * zoom + "px sans-serif";
  1428. ctx.fillText(snakes_29[i].nk, siToPiX(snakes_29[i].xx), siToPiY(snakes_29[i].yy) + 67 * zoom);
  1429. }
  1430. }
  1431.  
  1432. // drawing map border
  1433. if ((real_flux_grd_29 - distBetwCoords(0, 0, centerSiX - grd_29, centerSiY - grd_29)) * zoom < distBetwCoords(playingArenaWidth / 2, playingArenaHeight / 2, 0, 0)) {
  1434. ctx.strokeStyle = 'orange';
  1435. const edgeLineWidth = 30 * zoom;
  1436. ctx.lineWidth = edgeLineWidth;
  1437. ctx.beginPath();
  1438. ctx.arc(siToPiX(grd_29), siToPiY(grd_29), real_flux_grd_29 * zoom + edgeLineWidth / 2, 0, 2*Math.PI);
  1439. ctx.stroke();
  1440. }
  1441.  
  1442. // drawing minimap
  1443. const mmapScale = 2;
  1444. let mmapBeginX;
  1445. let mmapBeginY;
  1446. if (minimapObjs_29.length >= 1) {
  1447. mmapBeginX = playingArenaWidth - minimapObjs_29[0].sz * mmapScale + 0;
  1448. mmapBeginY = playingArenaHeight - minimapObjs_29[0].sz * mmapScale + 0;
  1449.  
  1450. const mmapEdgeLineWidth = 2.5;
  1451. ctx.lineWidth = mmapEdgeLineWidth;
  1452. ctx.beginPath();
  1453. ctx.arc(mmapBeginX + ((minimapObjs_29[0].sz - 0.5) * mmapScale) / 2, mmapBeginY + ((minimapObjs_29[0].sz - 0.5) * mmapScale) / 2, ((minimapObjs_29[0].sz - 1) / 2 * mmapScale) * real_flux_grd_29 / rfgrdForMinimap_29 + mmapEdgeLineWidth / 2, 0, 2*Math.PI);
  1454. ctx.fillStyle = 'rgba(255,255,255,0.2)';
  1455. ctx.fill();
  1456. ctx.strokeStyle = 'rgba(255,165,0,1)';
  1457. ctx.stroke();
  1458. }
  1459. ctx.fillStyle = 'rgba(0,0,0,0.8)';
  1460. for (let i = 1; i < minimapObjs_29.length; i++) {
  1461. ctx.fillRect(mmapBeginX + minimapObjs_29[i].xx * mmapScale, mmapBeginY + minimapObjs_29[i].yy * mmapScale, mmapScale, mmapScale);
  1462. }
  1463. if (minimapObjs_29.length >= 1 && mySnake) {
  1464. ctx.fillStyle = 'rgba(255,0,70,0.8)';
  1465. const radius = 3;
  1466. ctx.beginPath();
  1467. ctx.arc(mmapBeginX + ((minimapObjs_29[0].sz - 0.5) * mmapScale) / 2 + (mySnake.xx - grd_29) * ((minimapObjs_29[0].sz - 1) * mmapScale) / (rfgrdForMinimap_29 * 2), mmapBeginY + ((minimapObjs_29[0].sz - 0.5) * mmapScale) / 2 + (mySnake.yy - grd_29) * ((minimapObjs_29[0].sz - 1) * mmapScale) / (rfgrdForMinimap_29 * 2), radius, 0, 2*Math.PI);
  1468. ctx.fill();
  1469. }
  1470.  
  1471. // drawing fps and zoom info
  1472. ctx.fillStyle = 'rgb(0,0,0)';
  1473. ctx.font = "11px sans-serif";
  1474. ctx.fillText("fps: " + currentFps_29 + " zoom: " + zoom.toFixed(2), 310, 15);
  1475.  
  1476. // drawing leaderboard, rank, score
  1477. let myLenghtInfo = "";
  1478. if (mySnake) {
  1479. const sct = mySnake.sct + mySnake.rsc;
  1480. const score = Math.floor((fpsls_29[sct] + mySnake.fam / fmlts_29[sct] - 1) * 15 - 5) / 1;
  1481. myLenghtInfo = " " + score + " " + mySnake.rsc;
  1482. }
  1483. const infoText = playersInfo_29 == "" ? myLenghtInfo : playersInfo_29 + "\n" + myLenghtInfo;
  1484. ctx.textAlign = "left";
  1485. ctx.fillStyle = 'rgb(30,60,255)';
  1486. infoText.split('\n').forEach((line, index) => ctx.fillText(line, 10, 15 + index * 14));
  1487.  
  1488. function addPointToPolyline(slx, sly) {
  1489. const piX = (slx - leftSiX) * zoom;
  1490. const piY = (sly - topSiY) * zoom;
  1491. if (strokeMoveWas) {
  1492. ctx.lineTo(piX, piY);
  1493. }
  1494. else {
  1495. ctx.moveTo(piX, piY);
  1496. strokeMoveWas = true;
  1497. }
  1498. }
  1499. function siToPiX(siX) {
  1500. return (siX - leftSiX) * zoom;
  1501. }
  1502. function siToPiY(siY) {
  1503. return (siY - topSiY) * zoom;
  1504. }
  1505. function distBetwCoords(x1, y1, x2, y2) {
  1506. return Math.sqrt(Math.pow(Math.abs(x1-x2), 2) + Math.pow(Math.abs(y2-y1), 2));
  1507. }
  1508. function createRgbaStr(r1, g1, b1, a1, r2, g2, b2, a2, speed) {
  1509. function clcParam(paramDownPoint, paramUpPoint) {
  1510. const speedDownPoint = 5.5;
  1511. const speedUpPoint = 14;
  1512. const speDif = speedUpPoint - speedDownPoint;
  1513. const prmDif = paramUpPoint - paramDownPoint;
  1514. return paramDownPoint + (prmDif * (speed - speedDownPoint) / speDif);
  1515. }
  1516. return 'rgba(' + clcParam(r1, r2) + ',' + clcParam(g1, g2) + ',' + clcParam(b1, b2) + ',' + clcParam(a1, a2) + ')';
  1517. }
  1518. }
  1519.  
  1520. const serverIpAndPortField = document.createElement('input');
  1521. serverIpAndPortField.type = 'text';
  1522. serverIpAndPortField.placeholder = '57.129.37.42:444';
  1523. serverIpAndPortField.value = serverIpAndPortForInputField_29;
  1524. serverIpAndPortField.style.position = 'fixed';
  1525. serverIpAndPortField.style.right = '10px';
  1526. serverIpAndPortField.style.top = '7px';
  1527. serverIpAndPortField.style.width = '130px';
  1528. serverIpAndPortField.style.height = '20px';
  1529. serverIpAndPortField.style.background = 'rgba(255,255,255,0.2)';
  1530. serverIpAndPortField.style.border = '2px solid rgb(140,140,140)';
  1531. serverIpAndPortField.style.borderRadius = '5px';
  1532. serverIpAndPortField.style.color = 'rgb(50,50,50)';
  1533. serverIpAndPortField.style.zIndex = 2;
  1534. document.body.appendChild(serverIpAndPortField);
  1535.  
  1536. const stopGameBtn = document.createElement('button');
  1537. stopGameBtn.textContent = 'Stop the game';
  1538. stopGameBtn.style.position = 'fixed';
  1539. stopGameBtn.style.right = '10px';
  1540. stopGameBtn.style.top = '35px';
  1541. stopGameBtn.style.width = '130px';
  1542. stopGameBtn.style.height = '20px';
  1543. stopGameBtn.style.background = 'rgba(255,255,255,0.2)';
  1544. stopGameBtn.style.border = '2px solid rgb(140,140,140)';
  1545. stopGameBtn.style.borderRadius = '10px';
  1546. stopGameBtn.style.color = 'rgb(140,140,140)';
  1547. stopGameBtn.style.zIndex = 2;
  1548. document.body.appendChild(stopGameBtn);
  1549.  
  1550. const newGameBtn = document.createElement('button');
  1551. newGameBtn.textContent = 'New game';
  1552. newGameBtn.style.position = 'fixed';
  1553. newGameBtn.style.right = '10px';
  1554. newGameBtn.style.top = '63px';
  1555. newGameBtn.style.width = '130px';
  1556. newGameBtn.style.height = '20px';
  1557. newGameBtn.style.background = 'rgba(255,255,255,0.2)';
  1558. newGameBtn.style.border = '2px solid rgb(140,140,140)';
  1559. newGameBtn.style.borderRadius = '10px';
  1560. newGameBtn.style.color = 'rgb(140,140,140)';
  1561. newGameBtn.style.zIndex = 2;
  1562. document.body.appendChild(newGameBtn);
  1563.  
  1564. window.onwheel = function(e) {
  1565. const minZoom = 0.01;
  1566. const maxZoom = 5.0;
  1567. let consideredZoom;
  1568. if (e.deltaY > 0) {
  1569. consideredZoom = zoom - (zoom / 10.0);
  1570. if (consideredZoom >= minZoom)
  1571. zoom = consideredZoom;
  1572. }
  1573. else {
  1574. consideredZoom = zoom + (zoom / 9.0);
  1575. if (consideredZoom <= maxZoom)
  1576. zoom = consideredZoom;
  1577. }
  1578. };
  1579.  
  1580. window.onmousedown = function(e) {
  1581. acceleration_29 = true;
  1582. };
  1583.  
  1584. window.onmouseup = function(e) {
  1585. acceleration_29 = false;
  1586. };
  1587.  
  1588. window.onmousemove = function(e) {
  1589. whereMouseX_29 = e.clientX;
  1590. whereMouseY_29 = e.clientY;
  1591. };
  1592.  
  1593. stopGameBtn.onclick = function() {
  1594. if (buttonFunctionality_29) {
  1595. if (gameExists_29) {
  1596. wantCloseCurrentGame_29 = true;
  1597. }
  1598. }
  1599. };
  1600.  
  1601. newGameBtn.onclick = function() {
  1602. if (buttonFunctionality_29) {
  1603. buttonFunctionality_29 = false;
  1604. if (gameExists_29) {
  1605. wantCloseCurrentGame_29 = true;
  1606. wantNewGame_29 = true;
  1607. }
  1608. else {
  1609. prepareNewGame_29();
  1610. }
  1611. }
  1612. };
  1613.  
  1614. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址