|
@@ -1,15 +1,20 @@
|
|
|
package me.hammerle.supersnuvi.gamelogic;
|
|
|
|
|
|
import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.LinkedList;
|
|
|
import java.util.List;
|
|
|
import java.util.TreeSet;
|
|
|
+import java.util.function.Consumer;
|
|
|
import java.util.stream.Collectors;
|
|
|
import me.hammerle.snuviengine.api.Shader;
|
|
|
import me.hammerle.snuviengine.api.Texture;
|
|
|
import me.hammerle.snuviengine.api.TextureRenderer;
|
|
|
+import me.hammerle.snuviengine.util.Rectangle;
|
|
|
+import me.hammerle.snuviscript.code.Script;
|
|
|
import me.hammerle.supersnuvi.Game;
|
|
|
+import me.hammerle.supersnuvi.Keys;
|
|
|
import me.hammerle.supersnuvi.entity.Entity;
|
|
|
import me.hammerle.supersnuvi.entity.EntityBuilder;
|
|
|
import me.hammerle.supersnuvi.tiles.Location;
|
|
@@ -59,6 +64,11 @@ public final class Level implements ILevel
|
|
|
|
|
|
private TreeSet<Point> spawns = new TreeSet<>();
|
|
|
|
|
|
+ private Script levelScript = null;
|
|
|
+ private final LinkedList<String> messages = new LinkedList<>();
|
|
|
+ private float lastFrameLag = 0;
|
|
|
+ private boolean removeMessageLock = false;
|
|
|
+
|
|
|
public Level(File f)
|
|
|
{
|
|
|
this.data = new LevelData(f);
|
|
@@ -131,7 +141,18 @@ public final class Level implements ILevel
|
|
|
spawns.add(new Point(5, 5));
|
|
|
}
|
|
|
|
|
|
+ // make sure hero is spawned before any script starts
|
|
|
resetLevel();
|
|
|
+
|
|
|
+ String scriptName = f.getPath().replace(".map", "");
|
|
|
+ // mark current level as active to make currentLevel calls work
|
|
|
+ Level l = Game.get().getCurrentLevel();
|
|
|
+ Game.get().setCurrentLevel(this);
|
|
|
+ levelScript = Game.get().getParser().startScript(false, ".snuvi", scriptName);
|
|
|
+ // call level reset here, because levelScript was null in resetLevel()
|
|
|
+ callEvent("level_reset");
|
|
|
+ // mark previous level as active
|
|
|
+ Game.get().setCurrentLevel(l);
|
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
@@ -179,16 +200,6 @@ public final class Level implements ILevel
|
|
|
|
|
|
public boolean resetLevel()
|
|
|
{
|
|
|
- /*boolean dead = false;
|
|
|
- if(!done) // hero just died
|
|
|
- {
|
|
|
- tries--;
|
|
|
- if(tries <= 0)
|
|
|
- {
|
|
|
- tries = 7;
|
|
|
- dead = true;
|
|
|
- }
|
|
|
- }*/
|
|
|
Game.get().resetTiles(this);
|
|
|
data.activateEntities();
|
|
|
souls = 0;
|
|
@@ -210,6 +221,8 @@ public final class Level implements ILevel
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ callEvent("level_reset");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -260,11 +273,6 @@ public final class Level implements ILevel
|
|
|
return souls;
|
|
|
}
|
|
|
|
|
|
- public int getMaxBottles()
|
|
|
- {
|
|
|
- return maxSouls;
|
|
|
- }
|
|
|
-
|
|
|
public LevelData getData()
|
|
|
{
|
|
|
return data;
|
|
@@ -295,6 +303,17 @@ public final class Level implements ILevel
|
|
|
{
|
|
|
if(worldLoaded)
|
|
|
{
|
|
|
+ if(!messages.isEmpty())
|
|
|
+ {
|
|
|
+ if(Keys.ENTER.getTime() == 1)
|
|
|
+ {
|
|
|
+ messages.removeFirst();
|
|
|
+ }
|
|
|
+ removeMessageLock = messages.isEmpty();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ removeMessageLock = false;
|
|
|
+
|
|
|
time += Game.SECS_PER_TICK;
|
|
|
Game.get().tickTiles();
|
|
|
|
|
@@ -357,20 +376,22 @@ public final class Level implements ILevel
|
|
|
c[1] = (char) ((bottles % 10) + '0');
|
|
|
}
|
|
|
c[2] = '/';
|
|
|
- if(maxSouls <= 9)
|
|
|
+
|
|
|
+ int currentMaxSouls = Math.max(bottles, maxSouls);
|
|
|
+ if(currentMaxSouls <= 9)
|
|
|
{
|
|
|
c[3] = '0';
|
|
|
- c[4] = (char) (maxSouls + '0');
|
|
|
+ c[4] = (char) (currentMaxSouls + '0');
|
|
|
}
|
|
|
- else if(maxSouls > 99)
|
|
|
+ else if(currentMaxSouls > 99)
|
|
|
{
|
|
|
c[3] = 'X';
|
|
|
c[4] = 'X';
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- c[3] = (char) ((maxSouls / 10) + '0');
|
|
|
- c[4] = (char) ((maxSouls % 10) + '0');
|
|
|
+ c[3] = (char) ((currentMaxSouls / 10) + '0');
|
|
|
+ c[4] = (char) ((currentMaxSouls % 10) + '0');
|
|
|
}
|
|
|
return new String(c);
|
|
|
}
|
|
@@ -421,6 +442,11 @@ public final class Level implements ILevel
|
|
|
@Override
|
|
|
public void updateTile(int layer, int x, int y)
|
|
|
{
|
|
|
+ if(layer == data.getBackgroundIndex() + 1)
|
|
|
+ {
|
|
|
+ // do not update changes on entity layer
|
|
|
+ return;
|
|
|
+ }
|
|
|
if(layer > data.getBackgroundIndex())
|
|
|
{
|
|
|
layer--;
|
|
@@ -464,10 +490,61 @@ public final class Level implements ILevel
|
|
|
meshes[l][mx][my].draw();
|
|
|
}
|
|
|
|
|
|
+ private String[] split(String s)
|
|
|
+ {
|
|
|
+ ArrayList<String> list = new ArrayList<>();
|
|
|
+ int old = 0;
|
|
|
+ int index = 0;
|
|
|
+ while(index < s.length())
|
|
|
+ {
|
|
|
+ switch(s.charAt(index))
|
|
|
+ {
|
|
|
+ case '\n':
|
|
|
+ list.add(s.substring(old, index));
|
|
|
+ list.add("\n");
|
|
|
+ old = index + 1;
|
|
|
+ break;
|
|
|
+ case ' ':
|
|
|
+ list.add(s.substring(old, index));
|
|
|
+ old = index + 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+ if(old < s.length())
|
|
|
+ {
|
|
|
+ list.add(s.substring(old, index));
|
|
|
+ }
|
|
|
+ return list.toArray(new String[list.size()]);
|
|
|
+ }
|
|
|
+
|
|
|
public void renderTick(float lag)
|
|
|
{
|
|
|
if(worldLoaded)
|
|
|
{
|
|
|
+ if(messages.isEmpty())
|
|
|
+ {
|
|
|
+ if(removeMessageLock)
|
|
|
+ {
|
|
|
+ if(lag > lastFrameLag)
|
|
|
+ {
|
|
|
+ removeMessageLock = false;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lag = lastFrameLag;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lastFrameLag = lag;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ lag = lastFrameLag;
|
|
|
+ }
|
|
|
+
|
|
|
float camX = Utils.interpolate(oldCameraX, cameraX, lag);
|
|
|
float camY = Utils.interpolate(oldCameraY, cameraY, lag);
|
|
|
|
|
@@ -506,10 +583,10 @@ public final class Level implements ILevel
|
|
|
|
|
|
// entities
|
|
|
|
|
|
- entities.values().forEach(entity ->
|
|
|
+ for(Entity entity : entities.values())
|
|
|
{
|
|
|
entity.renderTick(lag);
|
|
|
- });
|
|
|
+ }
|
|
|
|
|
|
// foreground
|
|
|
Shader.setColorEnabled(false);
|
|
@@ -547,7 +624,74 @@ public final class Level implements ILevel
|
|
|
Shader.getFontRenderer().drawString(13.0f, y, formatTime(time));
|
|
|
Shader.setColorEnabled(false);
|
|
|
|
|
|
- float w = Shader.getViewWidth();
|
|
|
+ // draw messages
|
|
|
+ if(!messages.isEmpty())
|
|
|
+ {
|
|
|
+ String[] message = split(messages.getFirst());
|
|
|
+ int index = 0;
|
|
|
+ ArrayList<StringBuilder> list = new ArrayList<>();
|
|
|
+ list.add(new StringBuilder());
|
|
|
+ float currentWidth = 0;
|
|
|
+
|
|
|
+ float w = Shader.getViewWidth() - 26;
|
|
|
+ for(String s : message)
|
|
|
+ {
|
|
|
+ if(s.equals("\n"))
|
|
|
+ {
|
|
|
+ currentWidth = w;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Rectangle rec = Shader.getFontRenderer().getSize(s);
|
|
|
+ // + lineWidth for the space
|
|
|
+ if(currentWidth + rec.getWidth() + lineWidth < w)
|
|
|
+ {
|
|
|
+ currentWidth += rec.getWidth();
|
|
|
+
|
|
|
+ StringBuilder sb = list.get(index);
|
|
|
+ if(sb.length() == 0)
|
|
|
+ {
|
|
|
+ sb.append(s);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sb.append(" ");
|
|
|
+ sb.append(s);
|
|
|
+
|
|
|
+ currentWidth += lineWidth;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ list.add(sb);
|
|
|
+ index++;
|
|
|
+ sb.append(s);
|
|
|
+ currentWidth = rec.getWidth();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ float height = list.size() * lineHeight;
|
|
|
+
|
|
|
+ Shader.setColorEnabled(true);
|
|
|
+ Shader.setTextureEnabled(false);
|
|
|
+ float messageY = Shader.getViewHeight() - height - 26;
|
|
|
+ Shader.getColorRenderer().drawRectangle(0.0f, messageY, Shader.getViewWidth(), Shader.getViewHeight(), 0x77000000);
|
|
|
+ messageY += 13;
|
|
|
+ Shader.setTextureEnabled(true);
|
|
|
+ for(StringBuilder sb : list)
|
|
|
+ {
|
|
|
+ messageY = Shader.getFontRenderer().drawString(13.0f, messageY, sb.toString());
|
|
|
+ }
|
|
|
+ Shader.setColorEnabled(false);
|
|
|
+ }
|
|
|
+ /*Shader.setColorEnabled(true);
|
|
|
+ Shader.setTextureEnabled(false);
|
|
|
+ Shader.getColorRenderer().drawRectangle(0.0f, 0.0f, (lineWidth * 6.0f) + 10.0f, (lineHeight * 2.0f + 10.0f), 0x77000000);
|
|
|
+ Shader.setTextureEnabled(true);
|
|
|
+ y = 5.0f;
|
|
|
+ y = Shader.getFontRenderer().drawString(13.0f, y, formatBottles(souls));
|
|
|
+ Shader.getFontRenderer().drawString(13.0f, y, formatTime(time));
|
|
|
+ Shader.setColorEnabled(false);*/
|
|
|
+
|
|
|
|
|
|
GUI.bind();
|
|
|
GUI_RENDERER.clear();
|
|
@@ -570,6 +714,8 @@ public final class Level implements ILevel
|
|
|
default: GUI_RENDERER.addRectangle(4.666666666f, y, 13.0f, y + 8.333333333f, 0.05078125f, 0.265625f, 0.099609375f, 0.314453125f); break;
|
|
|
}
|
|
|
|
|
|
+ float w = Shader.getViewWidth();
|
|
|
+
|
|
|
// gui background
|
|
|
GUI_RENDERER.addRectangle(w - 111.0f, 0.0f, w - 44.0f, 24.0f, 0.0f, 0.0f, 0.130859375f, 0.046875f);
|
|
|
GUI_RENDERER.addRectangle(w - 44.0f, 0.0f, w - 18.0f, 16.0f, 0.130859375f, 0.0f, 0.181640625f, 0.03125f);
|
|
@@ -705,4 +851,27 @@ public final class Level implements ILevel
|
|
|
{
|
|
|
return entities.values().stream().filter(ent -> ent != not && ent.getBox().isColliding(cb)).collect(Collectors.toList());
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void callEvent(String name, Consumer<Script> before, Consumer<Script> after)
|
|
|
+ {
|
|
|
+ if(levelScript != null)
|
|
|
+ {
|
|
|
+ //Level l = Game.get().getCurrentLevel();
|
|
|
+ //Game.get().setCurrentLevel(this);
|
|
|
+ Game.get().getParser().callEvent(name, levelScript, before, after);
|
|
|
+ //Game.get().setCurrentLevel(l);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void callEvent(String name)
|
|
|
+ {
|
|
|
+ callEvent(name, null, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void addMessage(String message)
|
|
|
+ {
|
|
|
+ messages.add(message);
|
|
|
+ }
|
|
|
}
|