game.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. var canvas;
  2. var context;
  3. var lastTime;
  4. var updateIntervalId;
  5. var camera = { x: 0, y: 0, center: { x: 0, y: 0 }, movementSpeed: 3 };
  6. var isDragging = false;
  7. var dragCompleted = false;
  8. var startDrag = { x: 0, y: 0 };
  9. var dragDelta = { x: 0, y: 0 };
  10. var keys = [];
  11. var server;
  12. var socketHandler = {
  13. onmessage: (message) => { console.log(message);},
  14. onopen: (data) => { console.log(data);},
  15. onclose: (data) => { console.log(data);},
  16. onError: (data) => { console.error(data);},
  17. };
  18. var spritesheet;
  19. var sprites;
  20. var background;
  21. var room = {
  22. width: 2048,
  23. height: 1440,
  24. center: { x: 1024, y: 720 },
  25. tileSize: { width: 16, height: 16 },
  26. };
  27. var player = {
  28. x: 3 * room.tileSize.width,
  29. y: 3 * room.tileSize.height,
  30. width: room.tileSize.width,
  31. height: room.tileSize.height,
  32. center: { x: room.tileSize.width / 2, y: room.tileSize.height / 2 },
  33. angle: 90 * Math.PI / 180,
  34. rotationSpeed: 3 * Math.PI / 180,
  35. movementSpeed: 3,
  36. target: { x: 3 * room.tileSize.width, y: 3 * room.tileSize.height },
  37. };
  38. var floater = {
  39. position: {
  40. x: 0,
  41. y: 0,
  42. },
  43. width: room.tileSize.width,
  44. height: room.tileSize.height,
  45. center: { x: room.tileSize.width / 2, y: room.tileSize.height / 2 },
  46. };
  47. var tweenId = -1;
  48. function animate() {
  49. context.save();
  50. context.translate(0.5, 0.5);
  51. clearFrame(context);
  52. draw(context);
  53. context.restore();
  54. requestAnimationFrame(animate);
  55. }
  56. function clearFrame(context) {
  57. context.fillStyle = "#283848";
  58. context.beginPath();
  59. context.rect(0, 0, canvas.width, canvas.height);
  60. context.fill();
  61. }
  62. function init() {
  63. lastTime = new Date().getUTCMilliseconds();
  64. context = canvas.getContext('2d');
  65. keys = [];
  66. for (let i = 0; i < 256; i++) {
  67. keys[i] = false;
  68. }
  69. onResize();
  70. initBackground();
  71. initFloater();
  72. }
  73. function update(delta) {
  74. updateCamera(delta);
  75. updateBackground(delta);
  76. updatePlayer(delta);
  77. updateFloater(delta);
  78. Tween.update();
  79. }
  80. function draw(context) {
  81. context.save();
  82. context.translate(-camera.x + dragDelta.x, -camera.y + dragDelta.y);
  83. drawBackground(context);
  84. drawPlayer(context);
  85. drawFloater(context);
  86. context.restore();
  87. }
  88. function onResize() {
  89. let dpi = window.devicePixelRatio;
  90. canvas.width = canvas.clientWidth;
  91. canvas.height = canvas.clientHeight;
  92. context.width = canvas.clientWidth / dpi;
  93. context.height = canvas.clientHeight / dpi;
  94. let deltaX = camera.center.x - canvas.width / 2;
  95. let deltaY = camera.center.y - canvas.height / 2;
  96. camera.center.x = canvas.width / 2;
  97. camera.center.y = canvas.height / 2;
  98. camera.x += deltaX;
  99. camera.y += deltaY;
  100. }
  101. function onKeyDown(event) {
  102. keys[event.keyCode] = true;
  103. }
  104. function onKeyUp(event) {
  105. keys[event.keyCode] = false;
  106. }
  107. function onMouseMove(event) {
  108. if (isDragging) {
  109. dragDelta.x = event.clientX - startDrag.x;
  110. dragDelta.y = event.clientY - startDrag.y;
  111. }
  112. }
  113. function onMouseDown(event) {
  114. if (isDragging) {
  115. return;
  116. }
  117. dragCompleted = false;
  118. if (event.button == 0) {
  119. isDragging = true;
  120. }
  121. startDrag.x = event.clientX;
  122. startDrag.y = event.clientY;
  123. dragDelta.x = 0;
  124. dragDelta.y = 0;
  125. startDrag.time = new Date().getUTCMilliseconds();
  126. }
  127. function onMouseUp(event) {
  128. if (event.button == 2) { //startDrag.time + 100 >= new Date().getUTCMilliseconds()
  129. player.target.x = (Math.floor((camera.x + startDrag.x) / room.tileSize.width) * room.tileSize.width);
  130. player.target.y = (Math.floor((camera.y + startDrag.y) / room.tileSize.height) * room.tileSize.height);
  131. return;
  132. }
  133. if (isDragging) {
  134. isDragging = false;
  135. dragCompleted = true;
  136. }
  137. }
  138. function onRightClick(event) {
  139. event.preventDefault();
  140. }
  141. function onTouchStart(event) {
  142. if (event.touches.length == 2) {
  143. isDragging = true;
  144. startDrag.x = parseInt(event.targetTouches[0].clientX);
  145. startDrag.y = parseInt(event.targetTouches[0].clientY);
  146. dragDelta.x = 0;
  147. dragDelta.y = 0;
  148. startDrag.time = new Date().getUTCMilliseconds();
  149. }
  150. }
  151. function onTouchMove(event) {
  152. if (event.touches.length == 2) {
  153. dragDelta.x = parseInt(event.targetTouches[0].clientX) - startDrag.x;
  154. dragDelta.y = parseInt(event.targetTouches[0].clientY) - startDrag.y;
  155. }
  156. }
  157. function onTouchEnd(event) {
  158. if (isDragging) {
  159. isDragging = false;
  160. dragCompleted = true;
  161. return;
  162. }
  163. if (event.touches.length == 0) { //I've let go of all points
  164. if (!isDragging && !dragCompleted) {
  165. player.target.x = (Math.floor((camera.x + parseInt(event.changedTouches[0].clientX)) / room.tileSize.width) * room.tileSize.width);
  166. player.target.y = (Math.floor((camera.y + parseInt(event.changedTouches[0].clientY)) / room.tileSize.height) * room.tileSize.height);
  167. }
  168. }
  169. }
  170. document.addEventListener("DOMContentLoaded", event => {
  171. canvas = document.createElement("canvas");
  172. document.getElementById("game").appendChild(canvas);
  173. server = new Server(
  174. `http://roguelike.eyeofmidas.net:8080`,
  175. `ws://roguelike.eyeofmidas.net:14700`,
  176. );
  177. server.attachWebsocketHandler(socketHandler);
  178. spritesheet = new Spritesheet("./assets", "Tilesheet/monochrome_transparent_packed.png", room.tileSize.width, room.tileSize.height, 0);
  179. spritesheet.load().then(() => {
  180. sprites = new ColorSpriteCache(spritesheet);
  181. buildSprites();
  182. init();
  183. animate();
  184. server.websocketConnect();
  185. })
  186. updateIntervalId = setInterval(() => {
  187. let currentTime = new Date().getUTCMilliseconds();
  188. update(1 + ((currentTime - lastTime) / 1000));
  189. lastTime = currentTime;
  190. }, 16);
  191. });
  192. window.addEventListener("resize", onResize);
  193. window.addEventListener("keydown", onKeyDown);
  194. window.addEventListener("keyup", onKeyUp);
  195. window.addEventListener("mousedown", onMouseDown);
  196. window.addEventListener("mousemove", onMouseMove);
  197. window.addEventListener("mouseup", onMouseUp);
  198. window.addEventListener("contextmenu", onRightClick);
  199. window.addEventListener("touchstart", onTouchStart);
  200. window.addEventListener("touchmove", onTouchMove);
  201. window.addEventListener("touchend", onTouchEnd);
  202. function updateCamera(delta) {
  203. if (keys[KeyCode.Up]) {
  204. camera.y += -camera.movementSpeed * delta;
  205. }
  206. if (keys[KeyCode.Down]) {
  207. camera.y += camera.movementSpeed * delta;
  208. }
  209. if (keys[KeyCode.Left]) {
  210. camera.x += -camera.movementSpeed * delta;
  211. }
  212. if (keys[KeyCode.Right]) {
  213. camera.x += camera.movementSpeed * delta;
  214. }
  215. }
  216. function updateBackground(delta) {
  217. let isOutOfBounds = false;
  218. if (camera.y + canvas.height > (room.center.y * room.tileSize.height)) {
  219. camera.y = (room.center.y * room.tileSize.height) - canvas.height;
  220. }
  221. if (camera.y < -(room.center.y * room.tileSize.height)) {
  222. camera.y = -(room.center.y * room.tileSize.height);
  223. }
  224. if (camera.x + canvas.width > (room.center.x * room.tileSize.width)) {
  225. camera.x = (room.center.x * room.tileSize.width) - canvas.width;
  226. }
  227. if (camera.x < -(room.center.x * room.tileSize.width)) {
  228. camera.x = -(room.center.x * room.tileSize.width);
  229. }
  230. if ((camera.y + canvas.height) - dragDelta.y > (room.center.y * room.tileSize.height)) {
  231. isOutOfBounds = true;
  232. }
  233. if (camera.y - dragDelta.y < -(room.center.y * room.tileSize.height)) {
  234. isOutOfBounds = true;
  235. }
  236. if ((camera.x + canvas.width) - dragDelta.x > (room.center.x * room.tileSize.width)) {
  237. isOutOfBounds = true;
  238. }
  239. if (camera.x - dragDelta.x < -(room.center.x * room.tileSize.width)) {
  240. isOutOfBounds = true;
  241. }
  242. if (dragCompleted) {
  243. if (isOutOfBounds) {
  244. camera.x -= dragDelta.x * 0.1;
  245. camera.y -= dragDelta.y * 0.1;
  246. dragDelta.x = dragDelta.x * 0.90;
  247. dragDelta.y = dragDelta.y * 0.90;
  248. if (Math.abs(dragDelta.x) <= 1 && Math.abs(dragDelta.y) <= 1) {
  249. dragDelta.x = 0;
  250. dragDelta.y = 0;
  251. dragCompleted = false;
  252. }
  253. } else {
  254. camera.x -= dragDelta.x;
  255. camera.y -= dragDelta.y;
  256. dragDelta.x = 0;
  257. dragDelta.y = 0;
  258. dragCompleted = false;
  259. }
  260. }
  261. }
  262. SpriteKeys = {};
  263. SpriteKeys.Bat1 = 410;
  264. SpriteKeys.Hero1 = 25;
  265. SpriteKeys.Grass1 = 5;
  266. SpriteKeys.Grass2 = 6;
  267. SpriteKeys.Grass3 = 7;
  268. SpriteKeys.Floor1 = 2;
  269. SpriteKeys.Floor2 = 3;
  270. SpriteKeys.Floor3 = 4;
  271. SpriteKeys.OutsideWallNW = 640;
  272. SpriteKeys.OutsideWallN = 641;
  273. SpriteKeys.OutsideWallNE = 642;
  274. SpriteKeys.OutsideWallW = 688;
  275. SpriteKeys.OutsideWallE = 690;
  276. SpriteKeys.OutsideWallSW = 736;
  277. SpriteKeys.OutsideWallS = 737;
  278. SpriteKeys.OutsideWallSE = 738;
  279. ColorSprites = {};
  280. ColorSprites.GreenGrass1 = 1;
  281. ColorSprites.GreenGrass2 = 2;
  282. ColorSprites.GreenGrass3 = 3;
  283. ColorSprites.BrownDirt1 = 4;
  284. ColorSprites.BrownDirt2 = 5;
  285. ColorSprites.BrownDirt3 = 6;
  286. ColorSprites.BlackBat1 = 7;
  287. ColorSprites.YellowHero1 = 8;
  288. ColorSprites.GrayWallNW = 9;
  289. ColorSprites.GrayWallN = 10;
  290. ColorSprites.GrayWallNE = 11;
  291. ColorSprites.GrayWallW = 12;
  292. ColorSprites.GrayWallE = 13;
  293. ColorSprites.GrayWallSW = 14;
  294. ColorSprites.GrayWallS = 15;
  295. ColorSprites.GrayWallSE = 16;
  296. function buildSprites() {
  297. sprites.add(ColorSprites.GreenGrass1, room.tileSize.width, room.tileSize.height, SpriteKeys.Grass1, "#25591f");
  298. sprites.add(ColorSprites.GreenGrass2, room.tileSize.width, room.tileSize.height, SpriteKeys.Grass2, "#25591f");
  299. sprites.add(ColorSprites.GreenGrass3, room.tileSize.width, room.tileSize.height, SpriteKeys.Grass3, "#25591f");
  300. sprites.add(ColorSprites.BlackBat1, room.tileSize.width, room.tileSize.height, SpriteKeys.Bat1, "#080808");
  301. sprites.add(ColorSprites.YellowHero1, room.tileSize.width, room.tileSize.height, SpriteKeys.Hero1, "#DADA22");
  302. sprites.add(ColorSprites.BrownDirt1, room.tileSize.width, room.tileSize.height, SpriteKeys.Floor1, "#CD853F");
  303. sprites.add(ColorSprites.BrownDirt2, room.tileSize.width, room.tileSize.height, SpriteKeys.Floor2, "#CD853F");
  304. sprites.add(ColorSprites.BrownDirt3, room.tileSize.width, room.tileSize.height, SpriteKeys.Floor3, "#CD853F");
  305. sprites.add(ColorSprites.GrayWallNW, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallNW, "#868686");
  306. sprites.add(ColorSprites.GrayWallN, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallN, "#868686");
  307. sprites.add(ColorSprites.GrayWallNE, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallNE, "#868686");
  308. sprites.add(ColorSprites.GrayWallW, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallW, "#868686");
  309. sprites.add(ColorSprites.GrayWallE, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallE, "#868686");
  310. sprites.add(ColorSprites.GrayWallSW, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallSW, "#868686");
  311. sprites.add(ColorSprites.GrayWallS, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallS, "#868686");
  312. sprites.add(ColorSprites.GrayWallSE, room.tileSize.width, room.tileSize.height, SpriteKeys.OutsideWallSE, "#868686");
  313. }
  314. function initBackground() {
  315. background = document.createElement("canvas");
  316. background.width = room.width * room.tileSize.width;
  317. background.height = room.height * room.tileSize.height;
  318. loadRoom();
  319. }
  320. async function loadRoom(x = 0, y = 0, z = 0) {
  321. let roomData = await server.apiGet(`/room/${x},${y},${z}`);
  322. room = roomData.room;
  323. background = document.createElement("canvas");
  324. background.width = room.width * room.tileSize.width;
  325. background.height = room.height * room.tileSize.height;
  326. let backgroundContext = background.getContext("2d");
  327. roomData.backgroundRegions.forEach(region => {
  328. backgroundContext.fillStyle = region.color;
  329. backgroundContext.beginPath();
  330. backgroundContext.rect(region.x * room.tileSize.width, region.y * room.tileSize.height, region.width * room.tileSize.width, region.height * room.tileSize.height);
  331. backgroundContext.fill();
  332. });
  333. for(let x in roomData.backgroundTiles) {
  334. for(let y in roomData.backgroundTiles[x]) {
  335. sprites.drawOnGrid(backgroundContext, roomData.backgroundTiles[x][y], { x: x, y: y }, room.tileSize);
  336. }
  337. };
  338. }
  339. function drawBackground(context) {
  340. context.drawImage(background, -(room.center.x * room.tileSize.width), -(room.center.y * room.tileSize.height));
  341. }
  342. function updatePlayer(delta) {
  343. if (player.target.y == player.y) {
  344. if (keys[KeyCode.W]) {
  345. player.target.y += -room.tileSize.height;
  346. }
  347. if (keys[KeyCode.S]) {
  348. player.target.y += room.tileSize.height;
  349. }
  350. }
  351. if (player.target.x == player.x) {
  352. if (keys[KeyCode.A]) {
  353. player.target.x += -room.tileSize.width;
  354. }
  355. if (keys[KeyCode.D]) {
  356. player.target.x += room.tileSize.width;
  357. }
  358. }
  359. if (Math.abs(player.x - player.target.x) <= player.movementSpeed) {
  360. player.x = player.target.x;
  361. }
  362. if (Math.abs(player.y - player.target.y) <= player.movementSpeed) {
  363. player.y = player.target.y;
  364. }
  365. if (player.target.x != player.x || player.target.y != player.y) {
  366. let angle = (Math.atan2(player.target.y - player.y, player.target.x - player.x));
  367. player.x += player.movementSpeed * Math.cos(angle);
  368. player.y += player.movementSpeed * Math.sin(angle);
  369. }
  370. }
  371. function drawPlayer(context) {
  372. context.save();
  373. context.translate(player.x, player.y);
  374. let hero = sprites.get(ColorSprites.YellowHero1);
  375. context.drawImage(hero.image, 0, 0);
  376. context.restore();
  377. }
  378. function initFloater() {
  379. floaterToRandomPoint();
  380. }
  381. function floaterToRandomPoint() {
  382. let randomPoint = {position: { x: 0, y: 0 }};
  383. randomPoint.position.x = Math.floor(Math.floor((320 * Math.random() - 160) / room.tileSize.width) * room.tileSize.width);
  384. randomPoint.position.y = Math.floor(Math.floor((320 * Math.random() - 160) / room.tileSize.height) * room.tileSize.height);
  385. let distance = Math.sqrt(
  386. Math.pow(randomPoint.position.x - floater.position.x, 2) +
  387. Math.pow(randomPoint.position.y - floater.position.y, 2)
  388. );
  389. tweenId = Tween.create(floater, randomPoint, distance * 8, Tween.Easing.Cubic.EaseInOut, () => {
  390. setTimeout(floaterToRandomPoint, Math.floor(5 * Math.random() + 1) * 1000);
  391. });
  392. }
  393. function updateFloater(delta) {
  394. }
  395. function drawFloater(context) {
  396. context.save();
  397. context.translate(floater.position.x, floater.position.y);
  398. let bat = sprites.get(ColorSprites.BlackBat1);
  399. context.drawImage(bat.image, 0, 0);
  400. context.restore();
  401. }