package me.hammerle.supersnuvi; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import me.hammerle.snuviengine.api.ColorRenderer; import me.hammerle.snuviengine.api.Engine; import me.hammerle.snuviengine.api.FontRenderer; import me.hammerle.snuviengine.api.KeyBinding; import me.hammerle.snuviengine.api.Shader; import me.hammerle.snuviscript.code.SnuviParser; import me.hammerle.supersnuvi.entity.Entity; import me.hammerle.supersnuvi.entity.EntityBuilder; import me.hammerle.supersnuvi.entity.components.ai.PlatformController; import me.hammerle.supersnuvi.gamelogic.FileLevel; import me.hammerle.supersnuvi.gamelogic.Level; import me.hammerle.supersnuvi.gamelogic.StartScreenLevel; import me.hammerle.supersnuvi.rendering.LevelRenderer; import me.hammerle.supersnuvi.savegame.SimpleConfig; import me.hammerle.supersnuvi.snuviscript.SnuviLogger; import me.hammerle.supersnuvi.snuviscript.SnuviScheduler; import me.hammerle.supersnuvi.tiles.*; import me.hammerle.supersnuvi.util.SoundUtils; import me.hammerle.supersnuvi.util.Utils; public class Game extends Engine { public static final int MS_PER_TICK = 50; public static final float SECS_PER_TICK = MS_PER_TICK / 1000.0f; public static int getTicksForMillis(int millis) { return millis / MS_PER_TICK; } private static Game instance; public static Game get() { return instance; } // constants public static final NullTile FALLBACK_TILE = new NullTile(); // tiles private final Tile[] registeredTiles = new Tile[75]; // levels private Level currentLevel = null; private final Level[] levels; private int levelIndex = 0; private final StartScreenLevel startScreenLevel = new StartScreenLevel(); // scripting private final SnuviLogger snuviLogger = new SnuviLogger(); private final SnuviScheduler snuviScheduler = new SnuviScheduler(); private final SnuviParser snuviParser = new SnuviParser(snuviLogger, snuviScheduler); // config and savegames private final SimpleConfig config = new SimpleConfig("options.txt", true); private final SimpleConfig[] saveSlots = new SimpleConfig[] { new SimpleConfig("slot1.txt", true), new SimpleConfig("slot2.txt", true), new SimpleConfig("slot3.txt", true) }; private int screen = 0; private int startScreenIndex = 0; private int optionScreenIndex = 0; private int slotScreenIndex = 0; private boolean optionsDirty = false; // sound private boolean sound = config.getBoolean("sound", false); // renderer private final LevelRenderer levelRenderer = new LevelRenderer(); // this dummy will be removed later private final Shader dummy = new Shader(); public Game() { instance = this; registerTiles(); addSnuviCommands(); File[] files = new File("./levels").listFiles(); Arrays.sort(files, (o1, o2) -> o1.compareTo(o2)); ArrayList levelList = new ArrayList<>(); for(File file : files) { if(file.isFile() && file.getName().endsWith(".map")) { try { FileLevel l = new FileLevel(file); levelList.add(l); } catch(IllegalArgumentException ex) { //System.out.println(ex.getMessage()); } } } levels = levelList.toArray(new FileLevel[levelList.size()]); } @Override public void init() { setMaxFps(60); setNanosPerTick(MS_PER_TICK * 1_000_000); } // ------------------------------------------------------------------------- // tick, rendering // ------------------------------------------------------------------------- @Override public void tick() { if(currentLevel != null) { SoundUtils.playSound(SoundUtils.Sound.SONG_1); SoundUtils.stopSound(SoundUtils.Sound.MENU_MUSIC); snuviScheduler.setActiveLevel(currentLevel); //if(Keys.TEST.isReleased()) { currentLevel.tick(); } snuviScheduler.tick(currentLevel); // doing that here to prevent concurent modification if(currentLevel.isFinished()) { String base = "level." + currentLevel.getFileName(); SimpleConfig sp = saveSlots[slotScreenIndex]; // save success sp.set(base, true); // update time, if a new highscore was scored double time = sp.getDouble(base + ".time", Integer.MAX_VALUE); if(currentLevel.getTime() < time) { sp.set(base + ".time", currentLevel.getTime()); } // update bottles, if a new highscore was scored int bottles = sp.getInt(base + ".bottles", 0); if(currentLevel.getCurrentBottles() > bottles) { sp.set(base + ".bottles", currentLevel.getCurrentBottles()); } // final save sp.save(); currentLevel.reset(); currentLevel = null; return; } if(currentLevel.shouldReset()) { currentLevel.reset(); } if(Keys.ESCAPE.isReleased()) { currentLevel = null; } } else { SoundUtils.playSound(SoundUtils.Sound.MENU_MUSIC); SoundUtils.stopSound(SoundUtils.Sound.SONG_1); startScreenLevel.tick(); switch(screen) { case 0: // start screen { menuMove(() -> { // do nothing on escape in start screen }, () -> { switch(startScreenIndex) { case 0: screen = 1; break; case 1: screen = 2; break; case 2: stop(); break; } }, () -> startScreenIndex++, () -> startScreenIndex--, () -> { if(startScreenIndex < 0) { startScreenIndex = 0; } else if(startScreenIndex >= 3) { startScreenIndex = 2; } }); break; } case 1: // slot screen { menuMove(() -> { screen = 0; }, () -> { if(slotScreenIndex == 3) { screen = 0; return; } screen = 3; }, () -> slotScreenIndex++, () -> slotScreenIndex--, () -> { if(slotScreenIndex < 0) { slotScreenIndex = 0; } else if(slotScreenIndex >= 4) { slotScreenIndex = 3; } }); break; } case 2: // option screen { menuMove(() -> { screen = 0; }, () -> { switch(optionScreenIndex) { case 0: // toggle sound sound = !sound; if(!sound) { SoundUtils.turnSoundOff(); } optionsDirty = true; break; case 9: // save options Keys.write(config); config.set("sound", sound); config.save(); optionsDirty = false; break; case 10: // go back screen = 0; break; default: // rebind keys Keys.rebind(Keys.get(optionScreenIndex - 1)); optionsDirty = true; break; } }, () -> optionScreenIndex++, () -> optionScreenIndex--, () -> { if(optionScreenIndex < 0) { optionScreenIndex = 0; } int options = Keys.getAmount() + 3; if(optionScreenIndex >= options) { optionScreenIndex = options - 1; } }); break; } case 3: // level choose screen { menuMove(() -> { screen = 1; }, () -> currentLevel = levels[levelIndex], () -> levelIndex++, () -> levelIndex--, () -> { if(levelIndex < 0) { levelIndex = 0; } else if(levelIndex >= levels.length) { levelIndex = levels.length - 1; } }); break; } } } } private final static int COLOR_OVERLAY = 0x77808080; private final static int COLOR_OVERLAY2 = 0x77202020; private String getKeyName(KeyBinding key) { if(key.isRebinding()) { return "[...]"; } return key.getName(); } @Override public void renderTick(float lag) { if(currentLevel != null) { levelRenderer.renderTick(dummy, lag, currentLevel); //currentLevel.renderTick(lag); return; } levelRenderer.renderTick(dummy, lag, startScreenLevel); Shader.translateTo(0.0f, 0.0f); Shader.updateMatrix(); switch(screen) { case 0: { ColorRenderer cr = Shader.getColorRenderer(); FontRenderer fr = Shader.getFontRenderer(); float width = Shader.getViewWidth(); float height = Shader.getViewHeight(); float line = fr.getHeight(); float left = width * 0.25f; float right = width * 0.75f; float top = (height - line * 7.0f) * 0.5f; float bottom = top + line * 7.0f; Shader.setTextureEnabled(false); Shader.setColorEnabled(true); // brown background //cr.drawRectangle(0, 0, width, height, COLOR_BROWN); Shader.setBlendingEnabled(true); cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY); float base = top + (3 + startScreenIndex) * line; cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY2); Shader.setBlendingEnabled(false); Shader.setTextureEnabled(true); float y = top + line; y = fr.drawString(left + line, y, "Super Snuvi"); y += line; y = fr.drawString(left + line, y, "Start Game"); y = fr.drawString(left + line, y, "Options"); fr.drawString(left + line, y, "Exit Game"); break; } case 1: { ColorRenderer cr = Shader.getColorRenderer(); FontRenderer fr = Shader.getFontRenderer(); float width = Shader.getViewWidth(); float height = Shader.getViewHeight(); float line = fr.getHeight(); float left = width * 0.25f; float right = width * 0.75f; float top = (height - line * 8.0f) * 0.5f; float bottom = top + line * 8.0f; Shader.setTextureEnabled(false); Shader.setColorEnabled(true); // brown background //cr.drawRectangle(0, 0, width, height, COLOR_BROWN); Shader.setBlendingEnabled(true); cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY); float base = top + (3 + slotScreenIndex) * line; cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY2); Shader.setBlendingEnabled(false); Shader.setTextureEnabled(true); float y = top + line; y = fr.drawString(left + line, y, "Choose a Savegame"); y += line; y = fr.drawString(left + line, y, "Slot 1"); y = fr.drawString(left + line, y, "Slot 2"); y = fr.drawString(left + line, y, "Slot 3"); fr.drawString(left + line, y, "Back"); break; } case 2: { ColorRenderer cr = Shader.getColorRenderer(); FontRenderer fr = Shader.getFontRenderer(); float width = Shader.getViewWidth(); float height = Shader.getViewHeight(); float line = fr.getHeight(); float left = width * 0.2f; float right = width * 0.8f; float top = (height - line * 15.0f) * 0.5f; float bottom = top + line * 15.0f; Shader.setTextureEnabled(false); Shader.setColorEnabled(true); // brown background //cr.drawRectangle(0, 0, width, height, COLOR_BROWN); Shader.setBlendingEnabled(true); cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY); float base = top + (3 + optionScreenIndex) * line; cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY2); Shader.setBlendingEnabled(false); Shader.setTextureEnabled(true); left += line; float secLeft = right - line * 11; float y = top + line; y = fr.drawString(left, y, "Options"); y += line; fr.drawString(left, y, "Sound"); y = fr.drawString(secLeft, y, sound ? "yes" : "no"); fr.drawString(left, y, "K: Up"); y = fr.drawString(secLeft, y, getKeyName(Keys.UP)); fr.drawString(left, y, "K: Down"); y = fr.drawString(secLeft, y, getKeyName(Keys.DOWN)); fr.drawString(left, y, "K: Left"); y = fr.drawString(secLeft, y, getKeyName(Keys.LEFT)); fr.drawString(left, y, "K: Right"); y = fr.drawString(secLeft, y, getKeyName(Keys.RIGHT)); fr.drawString(left, y, "K: Jump"); y = fr.drawString(secLeft, y, getKeyName(Keys.JUMP)); fr.drawString(left, y, "K: Run"); y = fr.drawString(secLeft, y, getKeyName(Keys.RUN)); fr.drawString(left, y, "K: Back"); y = fr.drawString(secLeft, y, getKeyName(Keys.ESCAPE)); fr.drawString(left, y, "K: Enter"); y = fr.drawString(secLeft, y, getKeyName(Keys.ENTER)); if(optionsDirty) { y = fr.drawString(left, y, true, "&cSave"); } else { y = fr.drawString(left, y, true, "Save"); } fr.drawString(left, y, true, "Back"); break; } case 3: { ColorRenderer cr = Shader.getColorRenderer(); FontRenderer fr = Shader.getFontRenderer(); float width = Shader.getViewWidth(); float height = Shader.getViewHeight(); float line = fr.getHeight(); int maxView = 7; // only for odd numbers int half = maxView / 2; float left = width * 0.2f; float right = width * 0.8f; float top = (height - line * (maxView + 4)) * 0.5f; float bottom = top + line * (maxView + 4); Shader.setTextureEnabled(false); Shader.setColorEnabled(true); // brown background //cr.drawRectangle(0, 0, width, height, COLOR_BROWN); Shader.setBlendingEnabled(true); cr.drawRectangle(left, top, right, bottom, COLOR_OVERLAY); int firstIndex; int lastIndex; int baseIndex; if(levelIndex <= half) // first half { firstIndex = 0; lastIndex = Math.min(levels.length, maxView); baseIndex = levelIndex; } else if(levelIndex >= levels.length - half) // last half { lastIndex = levels.length; firstIndex = Math.max(lastIndex - maxView, 0); if(levels.length <= maxView) { baseIndex = levelIndex; } else { baseIndex = levelIndex - (levels.length - half - 1) + half; } } else // middle { firstIndex = levelIndex - half; lastIndex = firstIndex + maxView; baseIndex = half; } float base = top + (3 + baseIndex) * line; cr.drawRectangle(left, base, right, base + line, COLOR_OVERLAY2); Shader.setBlendingEnabled(false); Shader.setTextureEnabled(true); left += line; float secLeft = right - line * 12; float thirdLeft = right - line * 6; float y = top + line; y = fr.drawString(left, y, "Choose a Level ..."); y += line; if(firstIndex >= 1) { y = fr.drawString(left, y, "..."); firstIndex++; } SimpleConfig sc = saveSlots[slotScreenIndex]; for(int i = firstIndex; i < lastIndex - 1; i++) { Level l = levels[i]; fr.drawString(left, y, l.getName()); fr.drawString(secLeft, y, LevelRenderer.formatBottles(sc.getInt("level." + l.getFileName() + ".bottles", 0), l.getMaxBottles())); y = fr.drawString(thirdLeft, y, LevelRenderer.formatTime(sc.getFloat("level." + l.getFileName() + ".time", 0))); } if(lastIndex == levels.length) { Level l = levels[lastIndex - 1]; fr.drawString(left, y, l.getName()); fr.drawString(secLeft, y, LevelRenderer.formatBottles(sc.getInt("level." + l.getFileName() + ".bottles", 0), l.getMaxBottles())); fr.drawString(thirdLeft, y, LevelRenderer.formatTime(sc.getFloat("level." + l.getFileName() + ".time", 0))); } else { fr.drawString(left, y, "..."); } break; } } } // ------------------------------------------------------------------------- // config // ------------------------------------------------------------------------- public boolean isSoundEnabled() { return sound; } // ------------------------------------------------------------------------- // tile stuff // ------------------------------------------------------------------------- private void registerTiles() { // dirt registeredTiles[0] = new BaseBoxTile(0.125f, 0.0f, 0.1875f, 0.0625f); // grass registeredTiles[1] = new BaseBoxTile(0.0625f, 0.0f, 0.125f, 0.0625f); // bottled soul registeredTiles[2] = new BottledSoulTile(1); registeredTiles[3] = new BottledSoulTile(2); registeredTiles[4] = new BottledSoulTile(3); // bounce shroom registeredTiles[5] = new TrampolinTile(); // crumbling stones registeredTiles[6] = new CrumblingStoneTile(); // spike trap registeredTiles[7] = new SpikeTile(); // water for(int i = 0; i < 16; i++) { registeredTiles[8 + i] = new WaterTile(15 - i); } // snuvi start block registeredTiles[24] = new StartTile(); // sky registeredTiles[25] = new BaseTile(0.0f, 0.0f, 0.0625f, 0.0625f); // slippery slime registeredTiles[26] = new SlipperyTile(); // end level registeredTiles[27] = new GoalTile(0.25f, 0.125f, 0.3125f, 0.1875f); registeredTiles[28] = new GoalTile(0.25f, 0.0625f, 0.3125f, 0.125f); // thorns registeredTiles[29] = new KillTile(0.0f, 0.125f, 0.0625f, 0.1875f); registeredTiles[30] = new KillTile(0.0625f, 0.125f, 0.125f, 0.1875f); registeredTiles[31] = new KillTile(0.125f, 0.125f, 0.1875f, 0.1875f); // decoration shrooms registeredTiles[32] = new DecoShroomTile(0.0f, 0.21875f, 0.0625f, 0.25f); registeredTiles[33] = new DecoShroomTile(0.0f, 0.1875f, 0.0625f, 0.21875f); registeredTiles[34] = new DecoShroomTile(0.0625f, 0.21875f, 0.125f, 0.25f); registeredTiles[35] = new DecoShroomTile(0.0625f, 0.1875f, 0.125f, 0.21875f); // ramp registeredTiles[36] = new RampTile(0.375f, 0.0f, 0.4375f, 0.0625f, 0.0f, Tile.SIZE, Tile.SIZE, 0.0f); registeredTiles[37] = new RampTile(0.4375f, 0.0f, 0.5f, 0.0625f, 0.0f, Tile.SIZE, Tile.SIZE, Tile.SIZE * 0.5f); registeredTiles[38] = new RampTile(0.5f, 0.0f, 0.5625f, 0.0625f, 0.0f, Tile.SIZE * 0.5f, Tile.SIZE, 0.0f); registeredTiles[39] = new RampTile(0.375f, 0.0625f, 0.4375f, 0.125f, Tile.SIZE, Tile.SIZE, 0.0f, 0.0f); registeredTiles[40] = new RampTile(0.4375f, 0.0625f, 0.5f, 0.125f, Tile.SIZE, Tile.SIZE, 0.0f, Tile.SIZE * 0.5f); registeredTiles[41] = new RampTile(0.5f, 0.0625f, 0.5625f, 0.125f, Tile.SIZE, Tile.SIZE * 0.5f, 0.0f, 0.0f); // london stuff // street registeredTiles[42] = new BaseBoxTile(0.3125f, 0.125f, 0.375f, 0.1875f); // dirt registeredTiles[43] = new BaseBoxTile(0.375f, 0.125f, 0.4375f, 0.1875f); // background registeredTiles[44] = new BaseTile(0.3125f, 0.0625f, 0.375f, 0.125f); // street lamp for(int x = 0; x < 5; x++) { for(int y = 0; y < 5; y++) { 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)); } } // !-Tile registeredTiles[70] = new HeadHitTile(0.5625f, 0.0f, 0.625f, 0.0625f); // ?-Tile registeredTiles[71] = new HeadHitOnceTile(0.625f, 0.0f, 0.6875f, 0.0625f, 0.6875f, 0.0f, 0.75f, 0.0625f); // button registeredTiles[72] = new InteractTile(0.75f, 0.0f, 0.8125f, 0.0625f); // wooden pressure plate registeredTiles[73] = new PressureTile(0.568359375f, 0.072265625f, 0.619140625f, 0.078125f); // stone pressure plate registeredTiles[74] = new PressureTile(0.568359375f, 0.087890625f, 0.619140625f, 0.09375f); } public Tile getTile(int id) { if(id < 0 || id >= registeredTiles.length || registeredTiles[id] == null) { return FALLBACK_TILE; } return registeredTiles[id]; } public void resetTiles(FileLevel l) { for(Tile t : registeredTiles) { t.reset(l); } } public void tickTiles() { for(Tile t : registeredTiles) { t.tick(); } } private void menuMove(Runnable esc, Runnable enter, Runnable down, Runnable up, Runnable end) { if(Keys.ESCAPE.isReleased()) { esc.run(); return; } if(Keys.ENTER.isReleased()) { enter.run(); return; } if(Keys.DOWN.getTime() > 4) { Keys.DOWN.setTime(0); down.run(); } else if(Keys.UP.getTime() > 4) { Keys.UP.setTime(0); up.run(); } else if(Keys.DOWN.isReleased()) { down.run(); } else if(Keys.UP.isReleased()) { up.run(); } end.run(); } @Override public void onStop() { SoundUtils.closeSounds(); } public SnuviParser getParser() { return snuviParser; } public Level getCurrentLevel() { return currentLevel; } public void setCurrentLevel(Level l) { snuviScheduler.setActiveLevel(l); currentLevel = l; } private void addSnuviCommands() { snuviParser.registerFunction("level.getname", (sc, in) -> currentLevel.getName()); snuviParser.registerFunction("level.getwidth", (sc, in) -> (double) currentLevel.getData().getWidth()); snuviParser.registerFunction("level.getheight", (sc, in) -> (double) currentLevel.getData().getHeight()); snuviParser.registerFunction("level.getlayers", (sc, in) -> (double) currentLevel.getData().getLayers()); snuviParser.registerFunction("level.getbackgroundindex", (sc, in) -> (double) currentLevel.getData().getBackgroundIndex()); snuviParser.registerFunction("level.gettile", (sc, in) -> currentLevel.getData().getTile(in[0].getInt(sc), in[1].getInt(sc), in[2].getInt(sc))); snuviParser.registerFunction("level.settile", (sc, in) -> { int layer = in[0].getInt(sc); int x = in[1].getInt(sc); int y = in[2].getInt(sc); int tile = in[3].getInt(sc); currentLevel.getData().setTile(layer, x, y, tile); currentLevel.getTileUpdater().add(layer, x, y); Game.get().getTile(tile).reset(x, y, currentLevel); return Void.TYPE; }); snuviParser.registerFunction("level.addmessage", (sc, in) -> { currentLevel.addMessage(in[0].getString(sc)); return Void.TYPE; }); snuviParser.registerFunction("level.finish", (sc, in) -> { currentLevel.finishLevel(); return Void.TYPE; }); snuviParser.registerFunction("tile.totilecoord", (sc, in) -> (double) Utils.toBlock(in[0].getFloat(sc))); snuviParser.registerFunction("tile.tolevelcoord", (sc, in) -> (double) Utils.toCoord(in[0].getInt(sc))); snuviParser.registerFunction("tile.scale", (sc, in) -> in[0].getDouble(sc) * Tile.SIZE_SCALE); snuviParser.registerFunction("entity.gethero", (sc, in) -> currentLevel.getHero()); snuviParser.registerFunction("entity.getx", (sc, in) -> (double) ((Entity) in[0].get(sc)).getX()); snuviParser.registerFunction("entity.gety", (sc, in) -> (double) ((Entity) in[0].get(sc)).getY()); snuviParser.registerFunction("entity.teleport", (sc, in) -> { Entity ent = (Entity) in[0].get(sc); float x = in[1].getFloat(sc); float y = in[2].getFloat(sc); ent.setPosition(x, y); ent.setPosition(x, y); return Void.TYPE; }); snuviParser.registerFunction("entity.getmotionx", (sc, in) -> (double) ((Entity) in[0].get(sc)).getOwnForceX()); snuviParser.registerFunction("entity.getmotiony", (sc, in) -> (double) ((Entity) in[0].get(sc)).getOwnForceY()); snuviParser.registerFunction("entity.setmotionx", (sc, in) -> { ((Entity) in[0].get(sc)).applyForce(in[1].getFloat(sc), 0.0f); return Void.TYPE; }); snuviParser.registerFunction("entity.setmotiony", (sc, in) -> { ((Entity) in[0].get(sc)).applyForce(0.0f, in[1].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("entity.ishero", (sc, in) -> currentLevel.getHero() == in[0].get(sc)); snuviParser.registerFunction("entity.gethealth", (sc, in) -> ((Entity) in[0].get(sc)).getHealth().getHealthPercent()); snuviParser.registerFunction("entity.addhealth", (sc, in) -> { ((Entity) in[0].get(sc)).getHealth().addHealthPercent(in[1].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("entity.getenergy", (sc, in) -> ((Entity) in[0].get(sc)).getEnergy().getEnergyPercent()); snuviParser.registerFunction("entity.addenergy", (sc, in) -> { ((Entity) in[0].get(sc)).getEnergy().addEnergyPercent(in[1].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("entity.spawn", (sc, in) -> { Entity ent = EntityBuilder.fromId(in[0].getInt(sc), currentLevel, in[1].getFloat(sc), in[2].getFloat(sc)); if(ent != null) { currentLevel.spawnEntity(ent); } return ent; }); snuviParser.registerFunction("entity.remove", (sc, in) -> { Entity ent = (Entity) in[0].get(sc); // move entity out of world so it is removed ent.setPosition(0.0f, Float.MAX_VALUE * 0.5f); return Void.TYPE; }); snuviParser.registerFunction("entity.gettype", (sc, in) -> ((Entity) in[0].get(sc)).getType()); snuviParser.registerFunction("platform.spawn", (sc, in) -> { Entity ent = EntityBuilder.buildPlatform(currentLevel, in[0].getInt(sc), in[1].getFloat(sc), in[2].getInt(sc)); currentLevel.spawnEntity(ent); return ent; }); snuviParser.registerFunction("platform.addmove", (sc, in) -> { PlatformController controller = (PlatformController) ((Entity) in[0].get(sc)).getController(); 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)); return Void.TYPE; }); snuviParser.registerFunction("platform.clear", (sc, in) -> { ((PlatformController) ((Entity) in[0].get(sc)).getController()).clearMoveData(); return Void.TYPE; }); snuviParser.registerFunction("light.setambient", (sc, in) -> { currentLevel.setAmbientLight(in[0].getFloat(sc), in[1].getFloat(sc), in[2].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("light.setcolor", (sc, in) -> { currentLevel.getLight(in[0].getInt(sc)).setColor(in[1].getFloat(sc), in[2].getFloat(sc), in[3].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("light.setposition", (sc, in) -> { currentLevel.getLight(in[0].getInt(sc)).setPosition(in[1].getFloat(sc), in[2].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("light.setpositionsmooth", (sc, in) -> { currentLevel.getLight(in[0].getInt(sc)).setPositionSmooth(in[1].getFloat(sc), in[2].getFloat(sc)); return Void.TYPE; }); snuviParser.registerFunction("light.setstrength", (sc, in) -> { currentLevel.getLight(in[0].getInt(sc)).setStrength(in[1].getFloat(sc)); return Void.TYPE; }); } }