123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685 |
- 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.supersnuvi.gamelogic.Level;
- import me.hammerle.supersnuvi.savegame.SimpleConfig;
- import me.hammerle.supersnuvi.tiles.*;
- import me.hammerle.supersnuvi.util.SoundUtils;
- 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[70];
-
- // levels
- private Level currentLevel = null;
- private final Level[] levels;
- private int levelIndex = 0;
-
- // 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);
- public Game()
- {
- instance = this;
- registerTiles();
-
- File[] files = new File("./levels").listFiles();
- Arrays.sort(files, (o1, o2) -> o1.compareTo(o2));
- ArrayList<Level> levelList = new ArrayList<>();
- for(File file : files)
- {
- if(file.isFile())
- {
- Level l = new Level(file);
- levelList.add(l);
- }
- }
- levels = levelList.toArray(new Level[levelList.size()]);
- }
-
- @Override
- public void init()
- {
- setMaxFps(120);
- 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);
-
- currentLevel.tick();
-
- // doing that here to prevent concurent modification
- if(currentLevel.shouldFinish())
- {
- 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.resetLevel();
- currentLevel = null;
- return;
- }
-
- if(currentLevel.shouldReset())
- {
- if(currentLevel.resetLevel())
- {
- currentLevel = null;
- }
- }
-
- if(Keys.ESCAPE.isReleased())
- {
- currentLevel = null;
- }
- }
- else
- {
- SoundUtils.playSound(SoundUtils.Sound.MENU_MUSIC);
- SoundUtils.stopSound(SoundUtils.Sound.SONG_1);
- 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 15: // save options
- Keys.write(config);
- config.set("sound", sound);
- config.save();
- optionsDirty = false;
- break;
- case 16: // 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_BROWN = 0xFF13458B;
- private final static int COLOR_OVERLAY = 0x77000000;
- private String getKeyName(KeyBinding key)
- {
- if(key.isRebinding())
- {
- return "[...]";
- }
- return key.getName();
- }
-
- @Override
- public void renderTick(float lag)
- {
- if(currentLevel != null)
- {
- currentLevel.renderTick(lag);
- return;
- }
- 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_OVERLAY);
- 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_OVERLAY);
- 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 * 21.0f) * 0.5f;
- float bottom = top + line * 21.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_OVERLAY);
- 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));
- fr.drawString(left, y, "K: Combat");
- y = fr.drawString(secLeft, y, getKeyName(Keys.COMBAT));
- fr.drawString(left, y, "K: Switch Face");
- y = fr.drawString(secLeft, y, getKeyName(Keys.COMBAT_SWITCH_FACE));
- fr.drawString(left, y, "K: Dash/Dodge");
- y = fr.drawString(secLeft, y, getKeyName(Keys.COMBAT_DASH));
- fr.drawString(left, y, "K: Dash/Dodge");
- y = fr.drawString(secLeft, y, getKeyName(Keys.COMBAT_DODGE));
- fr.drawString(left, y, "K: Block");
- y = fr.drawString(secLeft, y, getKeyName(Keys.COMBAT_BLOCK));
- fr.drawString(left, y, "K: Attack");
- y = fr.drawString(secLeft, y, getKeyName(Keys.COMBAT_ATTACK));
- 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_OVERLAY);
- 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, l.formatBottles(sc.getInt("level." + l.getFileName() + ".bottles", 0)));
- y = fr.drawString(thirdLeft, y, l.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, l.formatBottles(sc.getInt("level." + l.getFileName() + ".bottles", 0)));
- fr.drawString(thirdLeft, y, l.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 Ramp(0.375f, 0.0f, 0.4375f, 0.0625f, 0.0f, Tile.SIZE, Tile.SIZE, 0.0f);
- registeredTiles[37] = new Ramp(0.4375f, 0.0f, 0.5f, 0.0625f, 0.0f, Tile.SIZE, Tile.SIZE, Tile.SIZE * 0.5f);
- registeredTiles[38] = new Ramp(0.5f, 0.0f, 0.5625f, 0.0625f, 0.0f, Tile.SIZE * 0.5f, Tile.SIZE, 0.0f);
- registeredTiles[39] = new Ramp(0.375f, 0.0625f, 0.4375f, 0.125f, Tile.SIZE, Tile.SIZE, 0.0f, 0.0f);
- registeredTiles[40] = new Ramp(0.4375f, 0.0625f, 0.5f, 0.125f, Tile.SIZE, Tile.SIZE, 0.0f, Tile.SIZE * 0.5f);
- registeredTiles[41] = new Ramp(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));
- }
- }
- }
-
- public Tile getTile(int id)
- {
- if(id < 0 || id >= registeredTiles.length || registeredTiles[id] == null)
- {
- return FALLBACK_TILE;
- }
- return registeredTiles[id];
- }
-
- public void resetTiles(Level 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();
- }
- }
|