Level.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. package me.hammerle.supersnuvi.gamelogic;
  2. import java.io.File;
  3. import java.util.HashMap;
  4. import java.util.LinkedList;
  5. import java.util.List;
  6. import java.util.TreeSet;
  7. import java.util.stream.Collectors;
  8. import me.hammerle.snuviengine.api.Shader;
  9. import me.hammerle.snuviengine.api.Texture;
  10. import me.hammerle.snuviengine.api.TextureRenderer;
  11. import me.hammerle.supersnuvi.Game;
  12. import me.hammerle.supersnuvi.entity.Entity;
  13. import me.hammerle.supersnuvi.entity.EntityBuilder;
  14. import me.hammerle.supersnuvi.tiles.Location;
  15. import me.hammerle.supersnuvi.tiles.StartTile;
  16. import me.hammerle.supersnuvi.tiles.Tile;
  17. import me.hammerle.supersnuvi.util.CollisionBox;
  18. import me.hammerle.supersnuvi.util.Utils;
  19. public final class Level
  20. {
  21. private final static float ERROR = 1f / 65536f;
  22. public final static Texture TILES = new Texture("resources/tiles.png");
  23. private final static Texture GUI = new Texture("resources/gui.png");
  24. private final static TextureRenderer GUI_RENDERER = new TextureRenderer(60);
  25. private final boolean worldLoaded;
  26. private final LevelData data;
  27. private final String fileName;
  28. private final String name;
  29. private final HashMap<Integer, Entity> entities = new HashMap<>();
  30. private final LinkedList<Entity> spawnQueue = new LinkedList<>();
  31. private Entity hero;
  32. private int entityCounter = 0;
  33. private boolean shouldReset = false;
  34. private boolean done = true; // this will be reseted in resetLevel()
  35. private int souls;
  36. private int maxSouls;
  37. private float time = 0.0f;
  38. private float cameraX = 0.0f;
  39. private float cameraY = 0.0f;
  40. private float oldCameraX = 0.0f;
  41. private float oldCameraY = 0.0f;
  42. private final int meshSize = 16;
  43. private final int meshLayers;
  44. private final int meshWidth;
  45. private final int meshHeight;
  46. private final TextureRenderer[][][] meshes;
  47. //private int tries = 7;
  48. private TreeSet<Point> spawns = new TreeSet<>();
  49. public Level(File f)
  50. {
  51. this.data = new LevelData(f);
  52. this.worldLoaded = data.load();
  53. if(worldLoaded)
  54. {
  55. this.name = data.getString("name", "error");
  56. meshLayers = data.getLayers() - 1;
  57. meshWidth = (int) Math.ceil((double) data.getWidth() / meshSize);
  58. meshHeight = (int) Math.ceil((double) data.getHeight() / meshSize);
  59. meshes = new TextureRenderer[meshLayers][meshWidth][meshHeight];
  60. for(int l = 0; l < meshLayers; l++)
  61. {
  62. for(int mx = 0; mx < meshWidth; mx++)
  63. {
  64. for(int my = 0; my < meshHeight; my++)
  65. {
  66. meshes[l][mx][my] = new TextureRenderer(meshSize * meshSize * 2);
  67. }
  68. }
  69. }
  70. // debug stuff
  71. /*if(name.equals("00-Tech Demo"))
  72. {
  73. int index = data.getBackgroundIndex() + 1;
  74. data.setTile(index, 10, 6, 2);
  75. data.setTile(index, 11, 6, 1);
  76. /*for(int layer = 0; layer <= data.getBackgroundIndex(); layer++)
  77. {
  78. for(int x = 0; x < data.getWidth(); x++)
  79. {
  80. for(int y = 0; y < data.getHeight(); y++)
  81. {
  82. int t = data.getTile(layer, x, y);
  83. if(t < 16)
  84. {
  85. data.setTile(layer, x, y, t + 240);
  86. }
  87. else if(t < 32)
  88. {
  89. data.setTile(layer, x, y, t + 224);
  90. }
  91. }
  92. }
  93. }
  94. index--;
  95. for(int x = 0; x < data.getWidth(); x++)
  96. {
  97. for(int y = 0; y < data.getHeight(); y++)
  98. {
  99. if(data.getTile(index, x, y) == 128)
  100. {
  101. data.setTile(index, x, y, -1);
  102. }
  103. }
  104. }
  105. for(int x = 0; x < 5; x++)
  106. {
  107. for(int y = 0; y < 5; y++)
  108. {
  109. data.setTile(index, x + 6, y + 1, 256 + x + (4 - y) * 5);
  110. }
  111. }
  112. }*/
  113. // end debug stuff
  114. maxSouls = 0;
  115. data.forEachInteractTile((x, y, tile) ->
  116. {
  117. Tile t = Game.get().getTile(tile);
  118. if(t != null)
  119. {
  120. maxSouls += t.getBottleScore();
  121. }
  122. if(tile == StartTile.ID)
  123. {
  124. spawns.add(new Point(x, y - 1));
  125. }
  126. });
  127. data.forEachEntity((x, y, tile) ->
  128. {
  129. if(tile == 1)
  130. {
  131. maxSouls++;
  132. }
  133. }, 0, data.getWidth(), 0, data.getHeight());
  134. }
  135. else
  136. {
  137. this.name = f.getName();
  138. maxSouls = 0;
  139. meshLayers = 0;
  140. meshWidth = 0;
  141. meshHeight = 0;
  142. meshes = new TextureRenderer[0][0][0];
  143. }
  144. fileName = f.getName();
  145. // there must be at least one spawn
  146. if(spawns.isEmpty())
  147. {
  148. spawns.add(new Point(5, 5));
  149. }
  150. resetLevel();
  151. }
  152. // -------------------------------------------------------------------------
  153. // basic stuff
  154. // -------------------------------------------------------------------------
  155. public Entity getHero()
  156. {
  157. return hero;
  158. }
  159. public String getFileName()
  160. {
  161. return fileName;
  162. }
  163. public String getName()
  164. {
  165. return name;
  166. }
  167. public void finishLevel()
  168. {
  169. shouldReset = true;
  170. done = true;
  171. }
  172. public boolean shouldFinish()
  173. {
  174. return done;
  175. }
  176. public boolean shouldReset()
  177. {
  178. return shouldReset;
  179. }
  180. public void scheduleReset()
  181. {
  182. shouldReset = true;
  183. }
  184. public boolean resetLevel()
  185. {
  186. /*boolean dead = false;
  187. if(!done) // hero just died
  188. {
  189. tries--;
  190. if(tries <= 0)
  191. {
  192. tries = 7;
  193. dead = true;
  194. }
  195. }*/
  196. Game.get().resetTiles();
  197. data.activateEntities();
  198. souls = 0;
  199. time = 0.0f;
  200. shouldReset = false;
  201. done = false;
  202. Entity h = spawnHero(true);
  203. hero = h;
  204. entities.clear();
  205. entities.put(entityCounter++, h);
  206. return false;
  207. }
  208. public void spawnEntity(Entity ent)
  209. {
  210. spawnQueue.add(ent);
  211. }
  212. public Entity spawnHero(boolean first)
  213. {
  214. Entity h = hero;
  215. Point p;
  216. if(h == null || hero.getX() < 0 || first)
  217. {
  218. // first spawn or out of map, use first spawn
  219. p = spawns.first();
  220. }
  221. else
  222. {
  223. // hero is somewhere in the map, getting last spawn
  224. p = spawns.floor(new Point(Utils.toBlock(hero.getX()), Utils.toBlock(hero.getY())));
  225. if(p == null)
  226. {
  227. p = spawns.first();
  228. }
  229. }
  230. return EntityBuilder.buildHero(this, Utils.toCoord(p.getX()), Utils.toCoord(p.getY()));
  231. }
  232. public void increaseSouls(int score)
  233. {
  234. souls += score;
  235. }
  236. public int getCurrentBottles()
  237. {
  238. return souls;
  239. }
  240. public int getMaxBottles()
  241. {
  242. return maxSouls;
  243. }
  244. public LevelData getData()
  245. {
  246. return data;
  247. }
  248. public float getTime()
  249. {
  250. return time;
  251. }
  252. public int getWidth()
  253. {
  254. return data.getWidth();
  255. }
  256. public int getHeight()
  257. {
  258. return data.getHeight();
  259. }
  260. // -------------------------------------------------------------------------
  261. // tick
  262. // -------------------------------------------------------------------------
  263. public void tick()
  264. {
  265. if(worldLoaded)
  266. {
  267. time += Game.SECS_PER_TICK;
  268. Game.get().tickTiles();
  269. // entity spawn layer
  270. /*int startX = renderer.getFirstVisibleBlockX();
  271. int startY = renderer.getFirstVisibleBlockY();
  272. int endX = Math.min(renderer.getLastVisibleBlockX() + 1, data.getWidth());
  273. int endY = Math.min(renderer.getLastVisibleBlockY() + 1, data.getHeight());
  274. data.forEachEntity((x, y, tile) ->
  275. {
  276. if(tile > 0)
  277. {
  278. data.deactivateEntity(x, y);
  279. Entity ent = EntityBuilder.fromId(tile, this, Utils.toCoord(x), Utils.toCoord(y));
  280. if(ent != null)
  281. {
  282. entities.put(entityCounter++, ent);
  283. }
  284. }
  285. }, startX, endX, startY, endY);*/
  286. // doing entity logic first
  287. entities.values().removeIf(entity ->
  288. {
  289. entity.tick();
  290. return entity.getHealth().shouldDespawn();
  291. });
  292. if(!spawnQueue.isEmpty())
  293. {
  294. spawnQueue.forEach(ent -> entities.put(entityCounter++, ent));
  295. spawnQueue.clear();
  296. }
  297. // calculate new camera position
  298. oldCameraX = cameraX;
  299. oldCameraY = cameraY;
  300. cameraX = -getViewX(hero.getCenterX());
  301. cameraY = -getViewY(hero.getCenterY());
  302. }
  303. }
  304. public String formatBottles(int bottles)
  305. {
  306. char[] c = new char[5];
  307. if(bottles <= 9)
  308. {
  309. c[0] = '0';
  310. c[1] = (char) (bottles + '0');
  311. }
  312. else if(bottles > 99)
  313. {
  314. c[0] = 'X';
  315. c[1] = 'X';
  316. }
  317. else
  318. {
  319. c[0] = (char) ((bottles / 10) + '0');
  320. c[1] = (char) ((bottles % 10) + '0');
  321. }
  322. c[2] = '/';
  323. if(maxSouls <= 9)
  324. {
  325. c[3] = '0';
  326. c[4] = (char) (maxSouls + '0');
  327. }
  328. else if(maxSouls > 99)
  329. {
  330. c[3] = 'X';
  331. c[4] = 'X';
  332. }
  333. else
  334. {
  335. c[3] = (char) ((maxSouls / 10) + '0');
  336. c[4] = (char) ((maxSouls % 10) + '0');
  337. }
  338. return new String(c);
  339. }
  340. public String formatTime(float time)
  341. {
  342. if(time == -1.0f)
  343. {
  344. return "-----";
  345. }
  346. else if(time >= 999.9f)
  347. {
  348. return "999.9";
  349. }
  350. return String.format("%05.1f", time);
  351. }
  352. private float getViewX(float x)
  353. {
  354. x -= Shader.getViewWidth() >> 1;
  355. if(x < 0)
  356. {
  357. return 0;
  358. }
  359. float max = data.getWidth() * Tile.SIZE - Shader.getViewWidth();
  360. if(x > max)
  361. {
  362. return max;
  363. }
  364. return x;
  365. }
  366. private float getViewY(float y)
  367. {
  368. y -= Shader.getViewHeight() >> 1;
  369. if(y < 0)
  370. {
  371. return 0;
  372. }
  373. float max = data.getHeight() * Tile.SIZE - Shader.getViewHeight();
  374. if(y > max)
  375. {
  376. return max;
  377. }
  378. return y;
  379. }
  380. public void updateTile(int layer, int x, int y)
  381. {
  382. if(layer > data.getBackgroundIndex())
  383. {
  384. layer--;
  385. }
  386. meshes[layer][x / meshSize][y / meshSize].clear();
  387. }
  388. public void updateTile(int x, int y)
  389. {
  390. updateTile(data.getBackgroundIndex(), x, y);
  391. }
  392. private void drawMesh(int l, int tl, int mx, int my)
  393. {
  394. TextureRenderer tr = meshes[l][mx][my];
  395. if(!tr.isBuilt())
  396. {
  397. int tsx = mx * meshSize;
  398. int tsy = my * meshSize;
  399. int tex = Math.min(tsx + meshSize, data.getWidth());
  400. int tey = Math.min(tsy + meshSize, data.getHeight());
  401. for(int x = tsx; x < tex; x++)
  402. {
  403. for(int y = tsy; y < tey; y++)
  404. {
  405. Tile t = Game.get().getTile(data.getTile(tl, x, y));
  406. if(t.shouldRender(x, y))
  407. {
  408. float minX = x * Tile.SIZE + t.getOffsetX();
  409. float minY = y * Tile.SIZE + t.getOffsetY();
  410. tr.addRectangle(minX, minY,
  411. minX + t.getWidth(), minY + t.getHeight(),
  412. t.getTextureMinX() + ERROR, t.getTextureMinY() + ERROR,
  413. t.getTextureMaxX() - ERROR, t.getTextureMaxY() - ERROR);
  414. }
  415. }
  416. }
  417. tr.build();
  418. }
  419. meshes[l][mx][my].draw();
  420. }
  421. public void renderTick(float lag)
  422. {
  423. if(worldLoaded)
  424. {
  425. float camX = Utils.interpolate(oldCameraX, cameraX, lag);
  426. float camY = Utils.interpolate(oldCameraY, cameraY, lag);
  427. Shader.translateTo(camX, camY);
  428. Shader.updateMatrix();
  429. int startX = (int) (-camX / (meshSize * Tile.SIZE));
  430. int startY = (int) (-camY / (meshSize * Tile.SIZE));
  431. int endX = (int) Math.ceil((-camX + Shader.getViewWidth()) / (meshSize * Tile.SIZE));
  432. int endY = (int) Math.ceil((-camY + Shader.getViewHeight()) / (meshSize * Tile.SIZE));
  433. startX = Math.min(Math.max(startX, 0), meshWidth);
  434. startY = Math.min(Math.max(startY, 0), meshHeight);
  435. endX = Math.min(Math.max(endX, 0), meshWidth);
  436. endY = Math.min(Math.max(endY, 0), meshHeight);
  437. // background
  438. Shader.setColorEnabled(false);
  439. Shader.setTextureEnabled(true);
  440. Shader.setBlendingEnabled(true);
  441. TILES.bind();
  442. int fromLayer = 0;
  443. int toLayer = data.getBackgroundIndex() + 1;
  444. for(int l = fromLayer; l < toLayer; l++)
  445. {
  446. for(int mx = startX; mx < endX; mx++)
  447. {
  448. for(int my = startY; my < endY; my++)
  449. {
  450. drawMesh(l, l, mx, my);
  451. }
  452. }
  453. }
  454. // entities
  455. entities.values().forEach(entity ->
  456. {
  457. entity.renderTick(lag);
  458. });
  459. // foreground
  460. Shader.setColorEnabled(false);
  461. Shader.setTextureEnabled(true);
  462. Shader.setBlendingEnabled(true);
  463. TILES.bind();
  464. fromLayer = toLayer + 1;
  465. toLayer = data.getLayers();
  466. for(int l = fromLayer; l < toLayer; l++)
  467. {
  468. for(int mx = startX; mx < endX; mx++)
  469. {
  470. for(int my = startY; my < endY; my++)
  471. {
  472. drawMesh(l - 1, l, mx, my);
  473. }
  474. }
  475. }
  476. // menu rendering
  477. Shader.translateTo(0.0f, 0.0f);
  478. Shader.updateMatrix();
  479. // grey background of clock and bottles
  480. float lineHeight = Shader.getFontRenderer().getHeight();
  481. float lineWidth = Shader.getFontRenderer().getWidth();
  482. Shader.setColorEnabled(true);
  483. Shader.setTextureEnabled(false);
  484. Shader.getColorRenderer().drawRectangle(0.0f, 0.0f, (lineWidth * 6.0f) + 10.0f, (lineHeight * 2.0f + 10.0f), 0x77000000);
  485. Shader.setTextureEnabled(true);
  486. float y = 5.0f;
  487. y = Shader.getFontRenderer().drawString(13.0f, y, formatBottles(souls));
  488. Shader.getFontRenderer().drawString(13.0f, y, formatTime(time));
  489. Shader.setColorEnabled(false);
  490. float w = Shader.getViewWidth();
  491. GUI.bind();
  492. GUI_RENDERER.clear();
  493. int scale = Shader.getViewScale();
  494. // bottles
  495. switch(scale)
  496. {
  497. case 1: GUI_RENDERER.addRectangle(6.0f, 4.0f, 12.0f, 14.0f, 0.0f, 0.046875f, 0.01171875f, 0.068359375f); break;
  498. case 2: GUI_RENDERER.addRectangle(6.0f, 4.0f, 12.0f, 14.0f, 0.01171875f, 0.046875f, 0.037109375f, 0.0859375f); break;
  499. default: GUI_RENDERER.addRectangle(6.0f, 4.0f, 12.0f, 14.0f, 0.037109375f, 0.046875f, 0.06640625f, 0.10546875f); break;
  500. }
  501. // clock
  502. switch(scale)
  503. {
  504. case 1: GUI_RENDERER.addRectangle(4.0f, y, 13.0f, y + 9.0f, 0.0f, 0.265625f, 0.017578125f, 0.283203125f); break;
  505. case 2: GUI_RENDERER.addRectangle(4.5f, y, 13.0f, y + 8.5f, 0.017578125f, 0.265625f, 0.05078125f, 0.298828125f); break;
  506. default: GUI_RENDERER.addRectangle(4.666666666f, y, 13.0f, y + 8.333333333f, 0.05078125f, 0.265625f, 0.099609375f, 0.314453125f); break;
  507. }
  508. // gui background
  509. GUI_RENDERER.addRectangle(w - 111.0f, 0.0f, w - 44.0f, 24.0f, 0.0f, 0.0f, 0.130859375f, 0.046875f);
  510. GUI_RENDERER.addRectangle(w - 44.0f, 0.0f, w - 18.0f, 16.0f, 0.130859375f, 0.0f, 0.181640625f, 0.03125f);
  511. GUI_RENDERER.addRectangle(w - 76.0f, 24.0f, w - 45.0f, 57.0f, 0.068359375f, 0.046875f, 0.12890625f, 0.111328125f);
  512. // health mirror
  513. int healthFrame = (int) (hero.getHealth().getHealthPercent() * 7);
  514. float leftMirror = (7 - healthFrame) * 0.0625f;
  515. GUI_RENDERER.addRectangle(w - 39.0f, 8.0f, w - 7.0f, 46.0f, leftMirror, 0.15625f, leftMirror + 0.0625f, 0.23046875f);
  516. // energy
  517. float energy = hero.getEnergy().getEnergyPercent();
  518. float fullEnd = w - 109.0f + 64.0f * energy;
  519. GUI_RENDERER.addRectangle(w - 109.0f, 13.0f, fullEnd, 21.0f, 0.0f, 0.140625f, 0.125f * energy, 0.15625f);
  520. GUI_RENDERER.addRectangle(fullEnd, 13.0f, w - 45.0f, 21.0f, 0.125f * energy, 0.125f, 0.125f, 0.140625f);
  521. // gui foreground
  522. GUI_RENDERER.addRectangle(w - 49.0f, 0.0f, w, 64.0f, 0.201171875f, 0.0f, 0.296875f, 0.125f);
  523. GUI_RENDERER.addRectangle(w - 109.0f, 15.0f, w - 106.0f, 18.0f, 0.15625f, 0.03125f, 0.162109375f, 0.037109375f);
  524. GUI_RENDERER.addRectangle(w - 97.0f, 15.0f, w - 92.0f, 20.0f, 0.1796875f, 0.03125f, 0.189453125f, 0.041015625f);
  525. // health number overlay
  526. GUI_RENDERER.addRectangle(w - 30.0f, 53.0f, w - 12.0f, 62.0f, leftMirror, 0.23828125f, leftMirror + 0.03515625f, 0.255859375f);
  527. GUI_RENDERER.build();
  528. GUI_RENDERER.draw();
  529. // dynamic clock hand
  530. Shader.setColorEnabled(true);
  531. Shader.setTextureEnabled(false);
  532. switch(scale)
  533. {
  534. case 1: Shader.translateTo(8.5f, y + 4.5f); break;
  535. case 2: Shader.translateTo(8.75f, y + 4.25f); break;
  536. default: Shader.translateTo(8.8333333333f, y + 4.16666667f); break;
  537. }
  538. Shader.rotate(-time * 72.0f);
  539. Shader.updateMatrix();
  540. Shader.getColorRenderer().drawRectangle(-0.5f / scale, -0.5f / scale, 0.5f / scale, 4.0f - 0.5f * scale, 0xFF000000);
  541. }
  542. }
  543. // -------------------------------------------------------------------------
  544. // collision box, interaction layer
  545. // -------------------------------------------------------------------------
  546. private Tile getInteractionTile(int x, int y)
  547. {
  548. int i = data.getInteractionTile(x, y);
  549. if(i == -1)
  550. {
  551. return Game.FALLBACK_TILE;
  552. }
  553. return Game.get().getTile(i);
  554. }
  555. private CollisionBox getMovementBox(int x, int y)
  556. {
  557. int i = data.getInteractionTile(x, y);
  558. if(i == -1)
  559. {
  560. return CollisionBox.NULL_BOX;
  561. }
  562. return Game.get().getTile(i).getMovementBox(x, y).reset().offset(Utils.toCoord(x), Utils.toCoord(y));
  563. }
  564. public List<CollisionBox> getMovementBoxesAt(CollisionBox box, Entity not)
  565. {
  566. List<CollisionBox> boxes;
  567. if(not != null)
  568. {
  569. boxes = getEntitiesCollidingWith(not, box).stream().map(ent -> ent.getBox()).collect(Collectors.toList());
  570. }
  571. else
  572. {
  573. boxes = new LinkedList<>();
  574. }
  575. int startX = Utils.toBlock(box.getMinX());
  576. int endX = Utils.toBlock(box.getMaxX());
  577. int startY = Utils.toBlock(box.getMinY());
  578. int endY = Utils.toBlock(box.getMaxY());
  579. for(int x = startX; x <= endX; x++)
  580. {
  581. for(int y = startY; y <= endY; y++)
  582. {
  583. CollisionBox cb = getMovementBox(x, y);
  584. if(cb.isColliding(box) && cb != CollisionBox.NULL_BOX)
  585. {
  586. boxes.add(cb.copy());
  587. }
  588. }
  589. }
  590. return boxes;
  591. }
  592. private CollisionBox getCollisionBox(int x, int y)
  593. {
  594. int i = data.getInteractionTile(x, y);
  595. if(i == -1)
  596. {
  597. return CollisionBox.NULL_BOX;
  598. }
  599. Tile tile = Game.get().getTile(i);
  600. return tile.getCollisionBox(x, y).reset().offset(Utils.toCoord(x), Utils.toCoord(y));
  601. }
  602. public List<Location> getCollisionBoxesAt(CollisionBox cb)
  603. {
  604. LinkedList<Location> boxes = new LinkedList<>();
  605. int startX = Utils.toBlock(cb.getMinX());
  606. int endX = Utils.toBlock(cb.getMaxX());
  607. int startY = Utils.toBlock(cb.getMinY());
  608. int endY = Utils.toBlock(cb.getMaxY());
  609. for(int x = startX; x <= endX; x++)
  610. {
  611. for(int y = startY; y <= endY; y++)
  612. {
  613. if(getCollisionBox(x, y).isColliding(cb))
  614. {
  615. boxes.add(new Location(getInteractionTile(x, y), x, y));
  616. }
  617. }
  618. }
  619. return boxes;
  620. }
  621. public List<Entity> getEntitiesCollidingWith(Entity not, CollisionBox cb)
  622. {
  623. return entities.values().stream().filter(ent -> ent != not && ent.getBox().isColliding(cb)).collect(Collectors.toList());
  624. }
  625. }