Game.java 32 KB

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