Game.java 31 KB

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