Game.java 25 KB

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