25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 

459 satır
8.4 KiB

  1. define([
  2. 'misc/pathfinder'
  3. ], function(
  4. pathfinder
  5. ) {
  6. var sqrt = Math.sqrt.bind(Math);
  7. var ceil = Math.ceil.bind(Math);
  8. var random = Math.random.bind(Math);
  9. return {
  10. graph: null,
  11. collisionMap: null,
  12. cells: [],
  13. width: 0,
  14. height: 0,
  15. init: function(collisionMap) {
  16. this.collisionMap = collisionMap;
  17. this.width = collisionMap.length;
  18. this.height = collisionMap[0].length;
  19. this.cells = _.get2dArray(this.width, this.height, 'array');
  20. this.graph = new pathfinder.Graph(collisionMap, {
  21. diagonal: true
  22. });
  23. },
  24. addRegion: function(obj) {
  25. var lowX = obj.x;
  26. var lowY = obj.y;
  27. var highX = lowX + obj.width;
  28. var highY = lowY + obj.height;
  29. var cells = this.cells;
  30. for (var i = lowX; i < highX; i++) {
  31. var row = cells[i];
  32. for (var j = lowY; j < highY; j++) {
  33. if (!row[j])
  34. continue;
  35. row[j].push(obj);
  36. }
  37. }
  38. },
  39. addObject: function(obj, x, y, fromX, fromY) {
  40. var row = this.cells[x];
  41. if (!row)
  42. return;
  43. var cell = row[y];
  44. if (!cell)
  45. return;
  46. var cLen = cell.length;
  47. for (var i = 0; i < cLen; i++) {
  48. var c = cell[i];
  49. //If we have fromX and fromY, check if the target cell doesn't contain the same obj (like a notice area)
  50. if ((c.width) && (fromX)) {
  51. if ((fromX < c.x) || (fromY < c.y) || (fromX >= c.x + c.width) || (fromY >= c.y + c.height)) {
  52. c.collisionEnter(obj);
  53. obj.collisionEnter(c);
  54. }
  55. } else {
  56. //If a callback returns true, it means we collide
  57. if (c.collisionEnter(obj))
  58. return;
  59. obj.collisionEnter(c);
  60. }
  61. }
  62. cell.push(obj);
  63. return true;
  64. },
  65. removeObject: function(obj, x, y, toX, toY) {
  66. var row = this.cells[x];
  67. if (!row)
  68. return;
  69. var cell = row[y];
  70. if (!cell)
  71. return;
  72. var oId = obj.id;
  73. var cLen = cell.length;
  74. for (var i = 0; i < cLen; i++) {
  75. var c = cell[i];
  76. if (c.id != oId) {
  77. //If we have toX and toY, check if the target cell doesn't contain the same obj (like a notice area)
  78. if ((c.width) && (toX)) {
  79. if ((toX < c.x) || (toY < c.y) || (toX >= c.x + c.width) || (toY >= c.y + c.height)) {
  80. c.collisionExit(obj);
  81. obj.collisionExit(c);
  82. }
  83. } else {
  84. c.collisionExit(obj);
  85. obj.collisionExit(c);
  86. }
  87. } else {
  88. cell.splice(i, 1);
  89. i--;
  90. cLen--;
  91. }
  92. }
  93. },
  94. isValid: function(x, y) {
  95. var row = this.cells[x];
  96. if ((!row) || (row.length <= y) || (!this.graph.grid[x][y]))
  97. return false;
  98. else
  99. return true;
  100. },
  101. getCell: function(x, y) {
  102. var row = this.cells[x];
  103. if (!row)
  104. return [];
  105. var cell = row[y];
  106. if (!cell)
  107. return [];
  108. return cell;
  109. },
  110. getArea: function(x1, y1, x2, y2, filter) {
  111. var width = this.width;
  112. var height = this.height;
  113. x1 = ~~x1;
  114. y1 = ~~y1;
  115. x2 = ~~x2;
  116. y2 = ~~y2;
  117. if (x1 < 0)
  118. x1 = 0;
  119. if (x2 >= width)
  120. x2 = width - 1;
  121. if (y1 < 0)
  122. y1 = 0;
  123. if (y2 >= height)
  124. y2 = height - 1;
  125. var cells = this.cells;
  126. var grid = this.graph.grid;
  127. var result = [];
  128. for (var i = x1; i <= x2; i++) {
  129. var row = cells[i];
  130. var gridRow = grid[i];
  131. for (var j = y1; j <= y2; j++) {
  132. if (!gridRow[j])
  133. continue;
  134. var cell = row[j];
  135. var cLen = cell.length;
  136. for (var k = 0; k < cLen; k++) {
  137. var c = cell[k];
  138. if (filter) {
  139. if (filter(c))
  140. result.push(c);
  141. } else
  142. result.push(c);
  143. }
  144. }
  145. }
  146. return result;
  147. },
  148. getOpenCellInArea: function(x1, y1, x2, y2) {
  149. var width = this.width;
  150. var height = this.height;
  151. x1 = ~~x1;
  152. y1 = ~~y1;
  153. x2 = ~~x2;
  154. y2 = ~~y2;
  155. if (x1 < 0)
  156. x1 = 0;
  157. else if (x2 >= width)
  158. x2 = width - 1;
  159. if (y1 < 0)
  160. y1 = 0;
  161. else if (y2 >= height)
  162. y2 = height - 1;
  163. var cells = this.cells;
  164. var grid = this.graph.grid;
  165. var result = [];
  166. for (var i = x1; i <= x2; i++) {
  167. var row = cells[i];
  168. var gridRow = grid[i];
  169. for (var j = y1; j <= y2; j++) {
  170. if (!gridRow[j])
  171. continue;
  172. var cell = row[j];
  173. if (cell.length == 0) {
  174. return {
  175. x: i,
  176. y: j
  177. };
  178. }
  179. }
  180. }
  181. return result;
  182. },
  183. getPath: function(from, to) {
  184. var graph = this.graph;
  185. var grid = graph.grid;
  186. if (!to) {
  187. to = {
  188. x: ~~(random() * grid.length),
  189. y: ~~(random() * grid[0].length)
  190. };
  191. }
  192. var fromX = ~~from.x;
  193. var fromY = ~~from.y;
  194. if ((!grid[fromX]) || (grid[fromX].length <= fromY) || (fromX < 0) || (fromY < 0))
  195. return [];
  196. var toX = ~~to.x;
  197. var toY = ~~to.y;
  198. if ((!grid[toX]) || (grid[toX].length <= toY) || (toX < 0) || (toY < 0))
  199. return [];
  200. var path = pathfinder.astar.search(graph, {
  201. x: fromX,
  202. y: fromY
  203. }, {
  204. x: toX,
  205. y: toY
  206. }, {
  207. closest: true
  208. });
  209. return path;
  210. },
  211. isTileBlocking: function(x, y) {
  212. if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height))
  213. return true;
  214. x = ~~x;
  215. y = ~~y;
  216. var node = this.graph.grid[x][y];
  217. if (node)
  218. return node.isWall();
  219. else
  220. return true;
  221. },
  222. isCellOpen: function(x, y) {
  223. if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height))
  224. return true;
  225. var cells = this.cells[x][y];
  226. var cLen = cells.length;
  227. for (var i = 0; i < cLen; i++) {
  228. var c = cells[i];
  229. if (!c.notice)
  230. return false;
  231. }
  232. return true;
  233. },
  234. hasLos: function(fromX, fromY, toX, toY) {
  235. if ((fromX < 0) || (fromY < 0) || (fromX >= this.width) | (fromY >= this.height) || (toX < 0) || (toY < 0) || (toX >= this.width) | (toY >= this.height))
  236. return false;
  237. var graphGrid = this.graph.grid;
  238. if ((!graphGrid[fromX][fromY]) || (!graphGrid[toX][toY]))
  239. return false;
  240. var dx = toX - fromX;
  241. var dy = toY - fromY;
  242. var distance = sqrt((dx * dx) + (dy * dy));
  243. dx /= distance;
  244. dy /= distance;
  245. fromX += 0.5;
  246. fromY += 0.5;
  247. distance = ceil(distance);
  248. var x = 0;
  249. var y = 0;
  250. for (var i = 0; i < distance; i++) {
  251. fromX += dx;
  252. fromY += dy;
  253. x = ~~fromX;
  254. y = ~~fromY;
  255. if (!graphGrid[x][y])
  256. return false;
  257. else if ((x == toX) && (y == toY))
  258. return true;
  259. }
  260. return true;
  261. },
  262. getClosestPos: function(fromX, fromY, toX, toY, target) {
  263. var tried = {};
  264. var hasLos = this.hasLos.bind(this, toX, toY);
  265. var width = this.width;
  266. var height = this.height;
  267. var collisionMap = this.collisionMap;
  268. var cells = this.cells;
  269. var reverseX = (fromX > toX);
  270. var reverseY = (fromY > toY);
  271. for (var c = 1; c <= 10; c++) {
  272. var x1 = toX - c;
  273. var y1 = toY - c;
  274. var x2 = toX + c;
  275. var y2 = toY + c;
  276. var lowX, lowY, highX, highY, incX, incY;
  277. if (reverseX) {
  278. incX = -1;
  279. lowX = x2;
  280. highX = x1 - 1;
  281. }
  282. else {
  283. incX = 1;
  284. lowX = x1;
  285. highX = x2 + 1;
  286. }
  287. if (reverseY) {
  288. incY = -1;
  289. lowY = y2;
  290. highY = y1 - 1;
  291. }
  292. else {
  293. incY = 1;
  294. lowY = y1;
  295. highY = y2 + 1;
  296. }
  297. for (var i = lowX; i != highX; i += incX) {
  298. if ((i < 0) || (i >= width))
  299. continue;
  300. var row = collisionMap[i];
  301. var cellRow = cells[i];
  302. var t = tried[i];
  303. if (!t) {
  304. t = tried[i] = {};
  305. }
  306. for (var j = lowY; j != highY; j += incY) {
  307. if (t[j])
  308. continue;
  309. t[j] = 1;
  310. if (
  311. ((i == toX) && (j == toY)) ||
  312. ((j < 0) || (j >= height)) ||
  313. (row[j])
  314. )
  315. continue;
  316. var cell = cellRow[j];
  317. var cLen = cell.length;
  318. var blocking = false;
  319. for (var k = 0; k < cLen; k++) {
  320. var aggro = cell[k].aggro;
  321. if (aggro) {
  322. blocking = aggro.list.some(a => a.obj == target);
  323. if (blocking)
  324. break;
  325. }
  326. }
  327. if (blocking)
  328. continue;
  329. else if (!hasLos(i, j))
  330. continue;
  331. return {
  332. x: i,
  333. y: j
  334. };
  335. }
  336. }
  337. }
  338. },
  339. mobsCollide: function(x, y, obj) {
  340. if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height))
  341. return true;
  342. var cell = this.cells[x][y];
  343. var cLen = cell.length;
  344. if (cLen == 1)
  345. return false;
  346. var found = false;
  347. for (var i = 0; i < cLen; i++) {
  348. var c = cell[i];
  349. if (c.aggro) {
  350. if ((!found) && (c == obj))
  351. found = true;
  352. else
  353. return true;
  354. }
  355. }
  356. return false;
  357. },
  358. setCollision: function(x, y, collides) {
  359. var grid = this.graph.grid;
  360. if (!grid[x][y]) {
  361. grid[x][y] = new pathfinder.astar.GridNode(x, y, collides ? 0 : 1);
  362. }
  363. else {
  364. grid[x][y].weight = collides ? 0 : 1;
  365. pathfinder.astar.cleanNode(grid[x][y]);
  366. }
  367. }
  368. };
  369. });