Level.java 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. package me.hammerle.supersnuvi.gamelogic;
  2. import java.util.Collection;
  3. import java.util.HashMap;
  4. import java.util.LinkedList;
  5. import java.util.function.Consumer;
  6. import me.hammerle.snuviscript.code.Script;
  7. import me.hammerle.supersnuvi.Game;
  8. import me.hammerle.supersnuvi.entity.Entity;
  9. import me.hammerle.supersnuvi.entity.EntityBuilder;
  10. import me.hammerle.supersnuvi.rendering.Light;
  11. import me.hammerle.supersnuvi.rendering.TileUpdater;
  12. import me.hammerle.supersnuvi.tiles.Tile;
  13. import me.hammerle.supersnuvi.util.Utils;
  14. public abstract class Level
  15. {
  16. // level data
  17. private final TileUpdater tileUpdater = new TileUpdater();
  18. // entity related
  19. private final HashMap<Integer, Entity> entities = new HashMap<>();
  20. private final LinkedList<Entity> spawnQueue = new LinkedList<>();
  21. private Entity hero = null;
  22. private int entityCounter = 0;
  23. // controlling
  24. private boolean shouldReset = false;
  25. private boolean done = false;
  26. // lighting
  27. private float red = 1.0f;
  28. private float green = 1.0f;
  29. private float blue = 1.0f;
  30. private final Light[] lights = new Light[32];
  31. public Level()
  32. {
  33. for(int i = 0; i < lights.length; i++)
  34. {
  35. lights[i] = new Light();
  36. }
  37. }
  38. // -------------------------------------------------------------------------
  39. // level data
  40. // -------------------------------------------------------------------------
  41. public abstract LevelData getData();
  42. public String getName()
  43. {
  44. return "Unknown";
  45. }
  46. public String getFileName()
  47. {
  48. return "Unknown";
  49. }
  50. public final TileUpdater getTileUpdater()
  51. {
  52. return tileUpdater;
  53. }
  54. // -------------------------------------------------------------------------
  55. // level stats
  56. // -------------------------------------------------------------------------
  57. public int getCurrentBottles()
  58. {
  59. return 0;
  60. }
  61. public int getMaxBottles()
  62. {
  63. return 0;
  64. }
  65. public void addBottles(int bottles)
  66. {
  67. }
  68. public float getTime()
  69. {
  70. return 0;
  71. }
  72. public void addMessage(String message)
  73. {
  74. }
  75. public String getMessage()
  76. {
  77. return null;
  78. }
  79. // -------------------------------------------------------------------------
  80. // entity related
  81. // -------------------------------------------------------------------------
  82. public final Entity getHero()
  83. {
  84. return hero;
  85. }
  86. public final void setHero(Entity hero)
  87. {
  88. this.hero = hero;
  89. }
  90. public final void removeEntities()
  91. {
  92. entities.clear();
  93. }
  94. public final void spawnEntity(Entity ent)
  95. {
  96. spawnQueue.add(ent);
  97. }
  98. public final void tickEntities()
  99. {
  100. entities.values().removeIf(ent ->
  101. {
  102. ent.tick(this);
  103. if((ent.getHealth().isDead() && !ent.isAnimated()) || (ent.getY() > getData().getHeight() * Tile.SIZE))
  104. {
  105. ent.onDespawn();
  106. callEvent("entity_despawn", (sc) ->
  107. {
  108. sc.setVar("entity", ent);
  109. }, null);
  110. return true;
  111. }
  112. return false;
  113. });
  114. entities.values().forEach(ent -> ent.tickCollision(this));
  115. int loops = 20;
  116. int changes = 1;
  117. while(changes > 0)
  118. {
  119. loops--;
  120. if(loops == 0)
  121. {
  122. System.out.println(System.nanoTime() + " Loop end reached ...");
  123. break;
  124. }
  125. changes = 0;
  126. for(Entity ent : entities.values())
  127. {
  128. changes += ent.move(this);
  129. }
  130. }
  131. if(!spawnQueue.isEmpty())
  132. {
  133. spawnQueue.forEach(ent ->
  134. {
  135. entities.put(entityCounter++, ent);
  136. callEvent("entity_spawn", (sc) ->
  137. {
  138. sc.setVar("entity", ent);
  139. }, null);
  140. });
  141. spawnQueue.clear();
  142. }
  143. }
  144. public final void forEachCollidingEntity(Entity ent, Consumer<Entity> c)
  145. {
  146. float minX = ent.getX() - Entity.STEP;
  147. float minY = ent.getY() - Entity.STEP;
  148. float maxX = ent.getX() + ent.getWidth() + Entity.STEP;
  149. float maxY = ent.getY() + ent.getHeight() + Entity.STEP;
  150. entities.values().stream().filter(other -> ent != other && other.isColliding(minX, minY, maxX, maxY)).forEach(c);
  151. }
  152. public final void forEachEntity(Consumer<Entity> c)
  153. {
  154. entities.values().forEach(c);
  155. }
  156. public final Collection<Entity> getEntities()
  157. {
  158. return entities.values();
  159. }
  160. public final Collection<Entity> getEntitiesInQueue()
  161. {
  162. return spawnQueue;
  163. }
  164. // -------------------------------------------------------------------------
  165. // controlling
  166. // -------------------------------------------------------------------------
  167. public abstract void tick();
  168. public final void finishLevel()
  169. {
  170. shouldReset = true;
  171. done = true;
  172. }
  173. public final boolean isFinished()
  174. {
  175. return done;
  176. }
  177. public final boolean shouldReset()
  178. {
  179. return shouldReset;
  180. }
  181. public final void scheduleReset()
  182. {
  183. shouldReset = true;
  184. }
  185. public final void reset()
  186. {
  187. // reset lights
  188. for(Light l : lights)
  189. {
  190. l.reset();
  191. }
  192. onReset();
  193. shouldReset = false;
  194. done = false;
  195. // spawn entities
  196. getData().forEachEntity((x, y, tile) ->
  197. {
  198. if(tile > 0)
  199. {
  200. Entity ent = EntityBuilder.fromId(tile, this, Utils.toCoord(x), Utils.toCoord(y));
  201. if(ent != null)
  202. {
  203. entities.put(entityCounter++, ent);
  204. }
  205. }
  206. }, 0, getData().getWidth(), 0, getData().getHeight());
  207. }
  208. protected void onReset()
  209. {
  210. };
  211. // -------------------------------------------------------------------------
  212. // collision
  213. // -------------------------------------------------------------------------
  214. public Tile getInteractionTile(int x, int y)
  215. {
  216. int i = getData().getInteractionTile(x, y);
  217. if(i == -1)
  218. {
  219. return Game.FALLBACK_TILE;
  220. }
  221. return Game.get().getTile(i);
  222. }
  223. // -------------------------------------------------------------------------
  224. // scripting
  225. // -------------------------------------------------------------------------
  226. public void callEvent(String name, Consumer<Script> before, Consumer<Script> after)
  227. {
  228. }
  229. public final void callEvent(String name)
  230. {
  231. callEvent(name, null, null);
  232. }
  233. // -------------------------------------------------------------------------
  234. // lighting
  235. // -------------------------------------------------------------------------
  236. public final void setAmbientLight(float r, float g, float b)
  237. {
  238. red = r;
  239. green = g;
  240. blue = b;
  241. }
  242. public final float getAmbientRed()
  243. {
  244. return red;
  245. }
  246. public final float getAmbientGreen()
  247. {
  248. return green;
  249. }
  250. public final float getAmbientBlue()
  251. {
  252. return blue;
  253. }
  254. public Light getLight(int index)
  255. {
  256. return lights[index];
  257. }
  258. }