Game.java 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. package me.hammerle.supersnuvi;
  2. import java.io.File;
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import me.hammerle.snuviengine.api.ColorRenderer;
  6. import me.hammerle.snuviengine.api.Engine;
  7. import me.hammerle.snuviengine.api.FontRenderer;
  8. import me.hammerle.snuviengine.api.KeyBinding;
  9. import me.hammerle.snuviengine.api.Shader;
  10. import me.hammerle.snuviscript.code.SnuviParser;
  11. import me.hammerle.supersnuvi.entity.Entity;
  12. import me.hammerle.supersnuvi.entity.EntityBuilder;
  13. import me.hammerle.supersnuvi.gamelogic.Level;
  14. import me.hammerle.supersnuvi.gamelogic.StartScreenLevel;
  15. import me.hammerle.supersnuvi.savegame.SimpleConfig;
  16. import me.hammerle.supersnuvi.snuviscript.SnuviLogger;
  17. import me.hammerle.supersnuvi.snuviscript.SnuviScheduler;
  18. import me.hammerle.supersnuvi.tiles.*;
  19. import me.hammerle.supersnuvi.util.SoundUtils;
  20. import me.hammerle.supersnuvi.util.Utils;
  21. public class Game extends Engine
  22. {
  23. public static final int MS_PER_TICK = 50;
  24. public static final float SECS_PER_TICK = MS_PER_TICK / 1000.0f;
  25. public static int getTicksForMillis(int millis)
  26. {
  27. return millis / MS_PER_TICK;
  28. }
  29. private static Game instance;
  30. public static Game get()
  31. {
  32. return instance;
  33. }
  34. // constants
  35. public static final NullTile FALLBACK_TILE = new NullTile();
  36. // tiles
  37. private final Tile[] registeredTiles = new Tile[72];
  38. // levels
  39. private Level currentLevel = null;
  40. private final Level[] levels;
  41. private int levelIndex = 0;
  42. private final StartScreenLevel startScreenLevel = new StartScreenLevel();
  43. // scripting
  44. private final SnuviLogger snuviLogger = new SnuviLogger();
  45. private final SnuviScheduler snuviScheduler = new SnuviScheduler();
  46. private final SnuviParser snuviParser = new SnuviParser(snuviLogger, snuviScheduler);
  47. // config and savegames
  48. private final SimpleConfig config = new SimpleConfig("options.txt", true);
  49. private final SimpleConfig[] saveSlots = new SimpleConfig[]
  50. {
  51. new SimpleConfig("slot1.txt", true),
  52. new SimpleConfig("slot2.txt", true),
  53. new SimpleConfig("slot3.txt", true)
  54. };
  55. private int screen = 0;
  56. private int startScreenIndex = 0;
  57. private int optionScreenIndex = 0;
  58. private int slotScreenIndex = 0;
  59. private boolean optionsDirty = false;
  60. // sound
  61. private boolean sound = config.getBoolean("sound", false);
  62. public Game()
  63. {
  64. instance = this;
  65. registerTiles();
  66. addSnuviCommands();
  67. File[] files = new File("./levels").listFiles();
  68. Arrays.sort(files, (o1, o2) -> o1.compareTo(o2));
  69. ArrayList<Level> levelList = new ArrayList<>();
  70. for(File file : files)
  71. {
  72. if(file.isFile() && file.getName().endsWith(".map"))
  73. {
  74. Level l = new Level(file);
  75. levelList.add(l);
  76. }
  77. }
  78. levels = levelList.toArray(new Level[levelList.size()]);
  79. }
  80. @Override
  81. public void init()
  82. {
  83. setMaxFps(60);
  84. setNanosPerTick(MS_PER_TICK * 1_000_000);
  85. }
  86. // -------------------------------------------------------------------------
  87. // tick, rendering
  88. // -------------------------------------------------------------------------
  89. @Override
  90. public void tick()
  91. {
  92. if(currentLevel != null)
  93. {
  94. SoundUtils.playSound(SoundUtils.Sound.SONG_1);
  95. SoundUtils.stopSound(SoundUtils.Sound.MENU_MUSIC);
  96. snuviScheduler.setActiveLevel(currentLevel);
  97. snuviScheduler.tick(currentLevel);
  98. currentLevel.tick();
  99. // doing that here to prevent concurent modification
  100. if(currentLevel.shouldFinish())
  101. {
  102. String base = "level." + currentLevel.getFileName();
  103. SimpleConfig sp = saveSlots[slotScreenIndex];
  104. // save success
  105. sp.set(base, true);
  106. // update time, if a new highscore was scored
  107. double time = sp.getDouble(base + ".time", Integer.MAX_VALUE);
  108. if(currentLevel.getTime() < time)
  109. {
  110. sp.set(base + ".time", currentLevel.getTime());
  111. }
  112. // update bottles, if a new highscore was scored
  113. int bottles = sp.getInt(base + ".bottles", 0);
  114. if(currentLevel.getCurrentBottles() > bottles)
  115. {
  116. sp.set(base + ".bottles", currentLevel.getCurrentBottles());
  117. }
  118. // final save
  119. sp.save();
  120. currentLevel.resetLevel();
  121. currentLevel = null;
  122. return;
  123. }
  124. if(currentLevel.shouldReset())
  125. {
  126. if(currentLevel.resetLevel())
  127. {
  128. currentLevel = null;
  129. }
  130. }
  131. if(Keys.ESCAPE.isReleased())
  132. {
  133. currentLevel = null;
  134. }
  135. }
  136. else
  137. {
  138. SoundUtils.playSound(SoundUtils.Sound.MENU_MUSIC);
  139. SoundUtils.stopSound(SoundUtils.Sound.SONG_1);
  140. startScreenLevel.tick();
  141. switch(screen)
  142. {
  143. case 0: // start screen
  144. {
  145. menuMove(() ->
  146. {
  147. // do nothing on escape in start screen
  148. }, () ->
  149. {
  150. switch(startScreenIndex)
  151. {
  152. case 0:
  153. screen = 1;
  154. break;
  155. case 1:
  156. screen = 2;
  157. break;
  158. case 2:
  159. stop();
  160. break;
  161. }
  162. }, () -> startScreenIndex++, () -> startScreenIndex--, () ->
  163. {
  164. if(startScreenIndex < 0)
  165. {
  166. startScreenIndex = 0;
  167. }
  168. else if(startScreenIndex >= 3)
  169. {
  170. startScreenIndex = 2;
  171. }
  172. });
  173. break;
  174. }
  175. case 1: // slot screen
  176. {
  177. menuMove(() ->
  178. {
  179. screen = 0;
  180. }, () ->
  181. {
  182. if(slotScreenIndex == 3)
  183. {
  184. screen = 0;
  185. return;
  186. }
  187. screen = 3;
  188. }, () -> slotScreenIndex++, () -> slotScreenIndex--, () ->
  189. {
  190. if(slotScreenIndex < 0)
  191. {
  192. slotScreenIndex = 0;
  193. }
  194. else if(slotScreenIndex >= 4)
  195. {
  196. slotScreenIndex = 3;
  197. }
  198. });
  199. break;
  200. }
  201. case 2: // option screen
  202. {
  203. menuMove(() ->
  204. {
  205. screen = 0;
  206. }, () ->
  207. {
  208. switch(optionScreenIndex)
  209. {
  210. case 0: // toggle sound
  211. sound = !sound;
  212. if(!sound)
  213. {
  214. SoundUtils.turnSoundOff();
  215. }
  216. optionsDirty = true;
  217. break;
  218. case 9: // save options
  219. Keys.write(config);
  220. config.set("sound", sound);
  221. config.save();
  222. optionsDirty = false;
  223. break;
  224. case 10: // go back
  225. screen = 0;
  226. break;
  227. default: // rebind keys
  228. Keys.rebind(Keys.get(optionScreenIndex - 1));
  229. optionsDirty = true;
  230. break;
  231. }
  232. }, () -> optionScreenIndex++, () -> optionScreenIndex--, () ->
  233. {
  234. if(optionScreenIndex < 0)
  235. {
  236. optionScreenIndex = 0;
  237. }
  238. int options = Keys.getAmount() + 3;
  239. if(optionScreenIndex >= options)
  240. {
  241. optionScreenIndex = options - 1;
  242. }
  243. });
  244. break;
  245. }
  246. case 3: // level choose screen
  247. {
  248. menuMove(() ->
  249. {
  250. screen = 1;
  251. }, () -> currentLevel = levels[levelIndex], () -> levelIndex++, () -> levelIndex--, () ->
  252. {
  253. if(levelIndex < 0)
  254. {
  255. levelIndex = 0;
  256. }
  257. else if(levelIndex >= levels.length)
  258. {
  259. levelIndex = levels.length - 1;
  260. }
  261. });
  262. break;
  263. }
  264. }
  265. }
  266. }
  267. private final static int COLOR_BROWN = 0xFF13458B;
  268. private final static int COLOR_OVERLAY = 0x77000000;
  269. private String getKeyName(KeyBinding key)
  270. {
  271. if(key.isRebinding())
  272. {
  273. return "[...]";
  274. }
  275. return key.getName();
  276. }
  277. @Override
  278. public void renderTick(float lag)
  279. {
  280. if(currentLevel != null)
  281. {
  282. currentLevel.renderTick(lag);
  283. return;
  284. }
  285. startScreenLevel.renderTick(lag);
  286. Shader.translateTo(0.0f, 0.0f);
  287. Shader.updateMatrix();
  288. switch(screen)
  289. {
  290. case 0:
  291. {
  292. ColorRenderer cr = Shader.getColorRenderer();
  293. FontRenderer fr = Shader.getFontRenderer();
  294. float width = Shader.getViewWidth();
  295. float height = Shader.getViewHeight();
  296. float line = fr.getHeight();
  297. float left = width * 0.25f;
  298. float right = width * 0.75f;
  299. float top = (height - line * 7.0f) * 0.5f;
  300. float bottom = top + line * 7.0f;
  301. Shader.setTextureEnabled(false);
  302. Shader.setColorEnabled(true);
  303. // brown background
  304. //cr.drawRectangle(0, 0, width, height, COLOR_BROWN);
  305. Shader.setBlendingEnabled(true);
  306. cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY);
  307. float base = top + (3 + startScreenIndex) * line;
  308. cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY);
  309. Shader.setBlendingEnabled(false);
  310. Shader.setTextureEnabled(true);
  311. float y = top + line;
  312. y = fr.drawString(left + line, y, "Super Snuvi");
  313. y += line;
  314. y = fr.drawString(left + line, y, "Start Game");
  315. y = fr.drawString(left + line, y, "Options");
  316. fr.drawString(left + line, y, "Exit Game");
  317. break;
  318. }
  319. case 1:
  320. {
  321. ColorRenderer cr = Shader.getColorRenderer();
  322. FontRenderer fr = Shader.getFontRenderer();
  323. float width = Shader.getViewWidth();
  324. float height = Shader.getViewHeight();
  325. float line = fr.getHeight();
  326. float left = width * 0.25f;
  327. float right = width * 0.75f;
  328. float top = (height - line * 8.0f) * 0.5f;
  329. float bottom = top + line * 8.0f;
  330. Shader.setTextureEnabled(false);
  331. Shader.setColorEnabled(true);
  332. // brown background
  333. //cr.drawRectangle(0, 0, width, height, COLOR_BROWN);
  334. Shader.setBlendingEnabled(true);
  335. cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY);
  336. float base = top + (3 + slotScreenIndex) * line;
  337. cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY);
  338. Shader.setBlendingEnabled(false);
  339. Shader.setTextureEnabled(true);
  340. float y = top + line;
  341. y = fr.drawString(left + line, y, "Choose a Savegame");
  342. y += line;
  343. y = fr.drawString(left + line, y, "Slot 1");
  344. y = fr.drawString(left + line, y, "Slot 2");
  345. y = fr.drawString(left + line, y, "Slot 3");
  346. fr.drawString(left + line, y, "Back");
  347. break;
  348. }
  349. case 2:
  350. {
  351. ColorRenderer cr = Shader.getColorRenderer();
  352. FontRenderer fr = Shader.getFontRenderer();
  353. float width = Shader.getViewWidth();
  354. float height = Shader.getViewHeight();
  355. float line = fr.getHeight();
  356. float left = width * 0.2f;
  357. float right = width * 0.8f;
  358. float top = (height - line * 15.0f) * 0.5f;
  359. float bottom = top + line * 15.0f;
  360. Shader.setTextureEnabled(false);
  361. Shader.setColorEnabled(true);
  362. // brown background
  363. //cr.drawRectangle(0, 0, width, height, COLOR_BROWN);
  364. Shader.setBlendingEnabled(true);
  365. cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY);
  366. float base = top + (3 + optionScreenIndex) * line;
  367. cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY);
  368. Shader.setBlendingEnabled(false);
  369. Shader.setTextureEnabled(true);
  370. left += line;
  371. float secLeft = right - line * 11;
  372. float y = top + line;
  373. y = fr.drawString(left, y, "Options");
  374. y += line;
  375. fr.drawString(left, y, "Sound");
  376. y = fr.drawString(secLeft, y, sound ? "yes" : "no");
  377. fr.drawString(left, y, "K: Up");
  378. y = fr.drawString(secLeft, y, getKeyName(Keys.UP));
  379. fr.drawString(left, y, "K: Down");
  380. y = fr.drawString(secLeft, y, getKeyName(Keys.DOWN));
  381. fr.drawString(left, y, "K: Left");
  382. y = fr.drawString(secLeft, y, getKeyName(Keys.LEFT));
  383. fr.drawString(left, y, "K: Right");
  384. y = fr.drawString(secLeft, y, getKeyName(Keys.RIGHT));
  385. fr.drawString(left, y, "K: Jump");
  386. y = fr.drawString(secLeft, y, getKeyName(Keys.JUMP));
  387. fr.drawString(left, y, "K: Run");
  388. y = fr.drawString(secLeft, y, getKeyName(Keys.RUN));
  389. fr.drawString(left, y, "K: Back");
  390. y = fr.drawString(secLeft, y, getKeyName(Keys.ESCAPE));
  391. fr.drawString(left, y, "K: Enter");
  392. y = fr.drawString(secLeft, y, getKeyName(Keys.ENTER));
  393. if(optionsDirty)
  394. {
  395. y = fr.drawString(left, y, true, "&cSave");
  396. }
  397. else
  398. {
  399. y = fr.drawString(left, y, true, "Save");
  400. }
  401. fr.drawString(left, y, true, "Back");
  402. break;
  403. }
  404. case 3:
  405. {
  406. ColorRenderer cr = Shader.getColorRenderer();
  407. FontRenderer fr = Shader.getFontRenderer();
  408. float width = Shader.getViewWidth();
  409. float height = Shader.getViewHeight();
  410. float line = fr.getHeight();
  411. int maxView = 7; // only for odd numbers
  412. int half = maxView / 2;
  413. float left = width * 0.2f;
  414. float right = width * 0.8f;
  415. float top = (height - line * (maxView + 4)) * 0.5f;
  416. float bottom = top + line * (maxView + 4);
  417. Shader.setTextureEnabled(false);
  418. Shader.setColorEnabled(true);
  419. // brown background
  420. //cr.drawRectangle(0, 0, width, height, COLOR_BROWN);
  421. Shader.setBlendingEnabled(true);
  422. cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY);
  423. int firstIndex;
  424. int lastIndex;
  425. int baseIndex;
  426. if(levelIndex <= half) // first half
  427. {
  428. firstIndex = 0;
  429. lastIndex = Math.min(levels.length, maxView);
  430. baseIndex = levelIndex;
  431. }
  432. else if(levelIndex >= levels.length - half) // last half
  433. {
  434. lastIndex = levels.length;
  435. firstIndex = Math.max(lastIndex - maxView, 0);
  436. if(levels.length <= maxView)
  437. {
  438. baseIndex = levelIndex;
  439. }
  440. else
  441. {
  442. baseIndex = levelIndex - (levels.length - half - 1) + half;
  443. }
  444. }
  445. else // middle
  446. {
  447. firstIndex = levelIndex - half;
  448. lastIndex = firstIndex + maxView;
  449. baseIndex = half;
  450. }
  451. float base = top + (3 + baseIndex) * line;
  452. cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY);
  453. Shader.setBlendingEnabled(false);
  454. Shader.setTextureEnabled(true);
  455. left += line;
  456. float secLeft = right - line * 12;
  457. float thirdLeft = right - line * 6;
  458. float y = top + line;
  459. y = fr.drawString(left, y, "Choose a Level ...");
  460. y += line;
  461. if(firstIndex >= 1)
  462. {
  463. y = fr.drawString(left, y, "...");
  464. firstIndex++;
  465. }
  466. SimpleConfig sc = saveSlots[slotScreenIndex];
  467. for(int i = firstIndex; i < lastIndex - 1; i++)
  468. {
  469. Level l = levels[i];
  470. fr.drawString(left, y, l.getName());
  471. fr.drawString(secLeft, y, l.formatBottles(sc.getInt("level." + l.getFileName() + ".bottles", 0)));
  472. y = fr.drawString(thirdLeft, y, l.formatTime(sc.getFloat("level." + l.getFileName() + ".time", 0)));
  473. }
  474. if(lastIndex == levels.length)
  475. {
  476. Level l = levels[lastIndex - 1];
  477. fr.drawString(left, y, l.getName());
  478. fr.drawString(secLeft, y, l.formatBottles(sc.getInt("level." + l.getFileName() + ".bottles", 0)));
  479. fr.drawString(thirdLeft, y, l.formatTime(sc.getFloat("level." + l.getFileName() + ".time", 0)));
  480. }
  481. else
  482. {
  483. fr.drawString(left, y, "...");
  484. }
  485. break;
  486. }
  487. }
  488. }
  489. // -------------------------------------------------------------------------
  490. // config
  491. // -------------------------------------------------------------------------
  492. public boolean isSoundEnabled()
  493. {
  494. return sound;
  495. }
  496. // -------------------------------------------------------------------------
  497. // tile stuff
  498. // -------------------------------------------------------------------------
  499. private void registerTiles()
  500. {
  501. // dirt
  502. registeredTiles[0] = new BaseBoxTile(0.125f, 0.0f, 0.1875f, 0.0625f);
  503. // grass
  504. registeredTiles[1] = new BaseBoxTile(0.0625f, 0.0f, 0.125f, 0.0625f);
  505. // bottled soul
  506. registeredTiles[2] = new BottledSoulTile(1);
  507. registeredTiles[3] = new BottledSoulTile(2);
  508. registeredTiles[4] = new BottledSoulTile(3);
  509. // bounce shroom
  510. registeredTiles[5] = new TrampolinTile();
  511. // crumbling stones
  512. registeredTiles[6] = new CrumblingStoneTile();
  513. // spike trap
  514. registeredTiles[7] = new SpikeTile();
  515. // water
  516. for(int i = 0; i < 16; i++)
  517. {
  518. registeredTiles[8 + i] = new WaterTile(15 - i);
  519. }
  520. // snuvi start block
  521. registeredTiles[24] = new StartTile();
  522. // sky
  523. registeredTiles[25] = new BaseTile(0.0f, 0.0f, 0.0625f, 0.0625f);
  524. // slippery slime
  525. registeredTiles[26] = new SlipperyTile();
  526. // end level
  527. registeredTiles[27] = new GoalTile(0.25f, 0.125f, 0.3125f, 0.1875f);
  528. registeredTiles[28] = new GoalTile(0.25f, 0.0625f, 0.3125f, 0.125f);
  529. // thorns
  530. registeredTiles[29] = new KillTile(0.0f, 0.125f, 0.0625f, 0.1875f);
  531. registeredTiles[30] = new KillTile(0.0625f, 0.125f, 0.125f, 0.1875f);
  532. registeredTiles[31] = new KillTile(0.125f, 0.125f, 0.1875f, 0.1875f);
  533. // decoration shrooms
  534. registeredTiles[32] = new DecoShroomTile(0.0f, 0.21875f, 0.0625f, 0.25f);
  535. registeredTiles[33] = new DecoShroomTile(0.0f, 0.1875f, 0.0625f, 0.21875f);
  536. registeredTiles[34] = new DecoShroomTile(0.0625f, 0.21875f, 0.125f, 0.25f);
  537. registeredTiles[35] = new DecoShroomTile(0.0625f, 0.1875f, 0.125f, 0.21875f);
  538. // ramp
  539. registeredTiles[36] = new Ramp(0.375f, 0.0f, 0.4375f, 0.0625f, 0.0f, Tile.SIZE, Tile.SIZE, 0.0f);
  540. registeredTiles[37] = new Ramp(0.4375f, 0.0f, 0.5f, 0.0625f, 0.0f, Tile.SIZE, Tile.SIZE, Tile.SIZE * 0.5f);
  541. registeredTiles[38] = new Ramp(0.5f, 0.0f, 0.5625f, 0.0625f, 0.0f, Tile.SIZE * 0.5f, Tile.SIZE, 0.0f);
  542. registeredTiles[39] = new Ramp(0.375f, 0.0625f, 0.4375f, 0.125f, Tile.SIZE, Tile.SIZE, 0.0f, 0.0f);
  543. registeredTiles[40] = new Ramp(0.4375f, 0.0625f, 0.5f, 0.125f, Tile.SIZE, Tile.SIZE, 0.0f, Tile.SIZE * 0.5f);
  544. registeredTiles[41] = new Ramp(0.5f, 0.0625f, 0.5625f, 0.125f, Tile.SIZE, Tile.SIZE * 0.5f, 0.0f, 0.0f);
  545. // london stuff
  546. // street
  547. registeredTiles[42] = new BaseBoxTile(0.3125f, 0.125f, 0.375f, 0.1875f);
  548. // dirt
  549. registeredTiles[43] = new BaseBoxTile(0.375f, 0.125f, 0.4375f, 0.1875f);
  550. // background
  551. registeredTiles[44] = new BaseTile(0.3125f, 0.0625f, 0.375f, 0.125f);
  552. // street lamp
  553. for(int x = 0; x < 5; x++)
  554. {
  555. for(int y = 0; y < 5; y++)
  556. {
  557. registeredTiles[45 + 5 * y + x] = new BaseTile(0.0625f * x, 0.25f + 0.0625f * y, 0.0625f * (x + 1), 0.25f + 0.0625f * (y + 1));
  558. }
  559. }
  560. // test interact tile
  561. registeredTiles[70] = new InteractTile(0.5625f, 0.0f, 0.625f, 0.0625f);
  562. // test hit tile
  563. registeredTiles[71] = new HeadHitBlock(0.5625f, 0.0f, 0.625f, 0.0625f);
  564. }
  565. public Tile getTile(int id)
  566. {
  567. if(id < 0 || id >= registeredTiles.length || registeredTiles[id] == null)
  568. {
  569. return FALLBACK_TILE;
  570. }
  571. return registeredTiles[id];
  572. }
  573. public void resetTiles(Level l)
  574. {
  575. for(Tile t : registeredTiles)
  576. {
  577. t.reset(l);
  578. }
  579. }
  580. public void tickTiles()
  581. {
  582. for(Tile t : registeredTiles)
  583. {
  584. t.tick();
  585. }
  586. }
  587. private void menuMove(Runnable esc, Runnable enter, Runnable down, Runnable up, Runnable end)
  588. {
  589. if(Keys.ESCAPE.isReleased())
  590. {
  591. esc.run();
  592. return;
  593. }
  594. if(Keys.ENTER.isReleased())
  595. {
  596. enter.run();
  597. return;
  598. }
  599. if(Keys.DOWN.getTime() > 4)
  600. {
  601. Keys.DOWN.setTime(0);
  602. down.run();
  603. }
  604. else if(Keys.UP.getTime() > 4)
  605. {
  606. Keys.UP.setTime(0);
  607. up.run();
  608. }
  609. else if(Keys.DOWN.isReleased())
  610. {
  611. down.run();
  612. }
  613. else if(Keys.UP.isReleased())
  614. {
  615. up.run();
  616. }
  617. end.run();
  618. }
  619. @Override
  620. public void onStop()
  621. {
  622. SoundUtils.closeSounds();
  623. }
  624. public SnuviParser getParser()
  625. {
  626. return snuviParser;
  627. }
  628. public Level getCurrentLevel()
  629. {
  630. return currentLevel;
  631. }
  632. public void setCurrentLevel(Level l)
  633. {
  634. snuviScheduler.setActiveLevel(l);
  635. currentLevel = l;
  636. }
  637. private void addSnuviCommands()
  638. {
  639. snuviParser.registerFunction("level.getwidth", (sc, in) -> (double) currentLevel.getWidth());
  640. snuviParser.registerFunction("level.getheight", (sc, in) -> (double) currentLevel.getHeight());
  641. snuviParser.registerFunction("level.getlayers", (sc, in) -> (double) currentLevel.getData().getLayers());
  642. snuviParser.registerFunction("level.getbackgroundindex", (sc, in) -> (double) currentLevel.getData().getBackgroundIndex());
  643. snuviParser.registerFunction("level.gettile", (sc, in) -> currentLevel.getData().getTile(in[0].getInt(sc), in[1].getInt(sc), in[2].getInt(sc)));
  644. snuviParser.registerFunction("level.settile", (sc, in) ->
  645. {
  646. int layer = in[0].getInt(sc);
  647. int x = in[1].getInt(sc);
  648. int y = in[2].getInt(sc);
  649. int tile = in[3].getInt(sc);
  650. currentLevel.getData().setTile(layer, x, y, tile);
  651. currentLevel.updateTile(layer, x, y);
  652. Game.get().getTile(tile).reset(x, y, currentLevel);
  653. return Void.TYPE;
  654. });
  655. snuviParser.registerFunction("level.addmessage", (sc, in) ->
  656. {
  657. currentLevel.addMessage(in[0].getString(sc));
  658. return Void.TYPE;
  659. });
  660. snuviParser.registerFunction("tile.totilecoord", (sc, in) -> (double) Utils.toBlock(in[0].getFloat(sc)));
  661. snuviParser.registerFunction("tile.tolevelcoord", (sc, in) -> (double) Utils.toCoord(in[0].getInt(sc)));
  662. snuviParser.registerFunction("entity.gethero", (sc, in) -> currentLevel.getHero());
  663. snuviParser.registerFunction("entity.getx", (sc, in) -> (double) ((Entity) in[0].get(sc)).getX());
  664. snuviParser.registerFunction("entity.gety", (sc, in) -> (double) ((Entity) in[0].get(sc)).getY());
  665. snuviParser.registerFunction("entity.teleport", (sc, in) ->
  666. {
  667. Entity ent = (Entity) in[0].get(sc);
  668. float x = in[1].getFloat(sc);
  669. float y = in[2].getFloat(sc);
  670. ent.setPosition(x, y);
  671. ent.setPosition(x, y);
  672. return Void.TYPE;
  673. });
  674. snuviParser.registerFunction("entity.getmotionx", (sc, in) -> (double) ((Entity) in[0].get(sc)).getMotionX());
  675. snuviParser.registerFunction("entity.getmotiony", (sc, in) -> (double) ((Entity) in[0].get(sc)).getMotionY());
  676. snuviParser.registerFunction("entity.setmotionx", (sc, in) ->
  677. {
  678. ((Entity) in[0].get(sc)).setMotionX(in[1].getFloat(sc));
  679. return Void.TYPE;
  680. });
  681. snuviParser.registerFunction("entity.setmotiony", (sc, in) ->
  682. {
  683. ((Entity) in[0].get(sc)).setMotionY(in[1].getFloat(sc));
  684. return Void.TYPE;
  685. });
  686. snuviParser.registerFunction("entity.ishero", (sc, in) -> currentLevel.getHero() == in[0].get(sc));
  687. snuviParser.registerFunction("entity.gethealth", (sc, in) -> ((Entity) in[0].get(sc)).getHealth().getHealthPercent());
  688. snuviParser.registerFunction("entity.addhealth", (sc, in) ->
  689. {
  690. ((Entity) in[0].get(sc)).getHealth().addHealthPercent(in[1].getFloat(sc));
  691. return Void.TYPE;
  692. });
  693. snuviParser.registerFunction("entity.getenergy", (sc, in) -> ((Entity) in[0].get(sc)).getEnergy().getEnergyPercent());
  694. snuviParser.registerFunction("entity.addenergy", (sc, in) ->
  695. {
  696. ((Entity) in[0].get(sc)).getEnergy().addEnergyPercent(in[1].getFloat(sc));
  697. return Void.TYPE;
  698. });
  699. snuviParser.registerFunction("entity.spawn", (sc, in) ->
  700. {
  701. Entity ent = EntityBuilder.fromId(in[0].getInt(sc), currentLevel, in[1].getFloat(sc), in[2].getFloat(sc));
  702. if(ent != null)
  703. {
  704. currentLevel.spawnEntity(ent);
  705. }
  706. return ent;
  707. });
  708. }
  709. }