|
@@ -0,0 +1,673 @@
|
|
|
|
+package me.hammerle.supersnuvi.gamelogic;
|
|
|
|
+
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.LinkedList;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Random;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+import me.hammerle.snuviengine.api.Shader;
|
|
|
|
+import me.hammerle.snuviengine.api.TextureRenderer;
|
|
|
|
+import me.hammerle.supersnuvi.Game;
|
|
|
|
+import me.hammerle.supersnuvi.entity.Entity;
|
|
|
|
+import me.hammerle.supersnuvi.entity.EntityBuilder;
|
|
|
|
+import me.hammerle.supersnuvi.tiles.Location;
|
|
|
|
+import me.hammerle.supersnuvi.tiles.Tile;
|
|
|
|
+import me.hammerle.supersnuvi.util.CollisionObject;
|
|
|
|
+import me.hammerle.supersnuvi.util.Utils;
|
|
|
|
+
|
|
|
|
+public final class StartScreenLevel implements ILevel
|
|
|
|
+{
|
|
|
|
+ private final LevelData data;
|
|
|
|
+
|
|
|
|
+ private final HashMap<Integer, Entity> entities = new HashMap<>();
|
|
|
|
+ private final LinkedList<Entity> spawnQueue = new LinkedList<>();
|
|
|
|
+ private final Entity hero;
|
|
|
|
+ private int entityCounter = 0;
|
|
|
|
+
|
|
|
|
+ private float cameraX = 0.0f;
|
|
|
|
+ private float cameraY = 0.0f;
|
|
|
|
+ private float oldCameraX = 0.0f;
|
|
|
|
+ private float oldCameraY = 0.0f;
|
|
|
|
+
|
|
|
|
+ private float heroSpawnX;
|
|
|
|
+ private float heroSpawnY;
|
|
|
|
+
|
|
|
|
+ private final int meshSize = 16;
|
|
|
|
+ private final int meshLayers;
|
|
|
|
+ private final int meshWidth;
|
|
|
|
+ private final int meshHeight;
|
|
|
|
+ private final TextureRenderer[][][] meshes;
|
|
|
|
+
|
|
|
|
+ public StartScreenLevel()
|
|
|
|
+ {
|
|
|
|
+ hero = EntityBuilder.buildStartScreenHero(this, 0.0f, 0.0f);
|
|
|
|
+ spawnEntity(hero);
|
|
|
|
+
|
|
|
|
+ this.data = generate();
|
|
|
|
+
|
|
|
|
+ meshLayers = data.getLayers() - 1;
|
|
|
|
+ meshWidth = (int) Math.ceil((double) data.getWidth() / meshSize);
|
|
|
|
+ meshHeight = (int) Math.ceil((double) data.getHeight() / meshSize);
|
|
|
|
+ meshes = new TextureRenderer[meshLayers][meshWidth][meshHeight];
|
|
|
|
+ for(int l = 0; l < meshLayers; l++)
|
|
|
|
+ {
|
|
|
|
+ for(int mx = 0; mx < meshWidth; mx++)
|
|
|
|
+ {
|
|
|
|
+ for(int my = 0; my < meshHeight; my++)
|
|
|
|
+ {
|
|
|
|
+ meshes[l][mx][my] = new TextureRenderer(meshSize * meshSize * 2);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ oldCameraX = -getViewX(hero.getCenterX());
|
|
|
|
+ oldCameraY = -getViewY(hero.getCenterY());
|
|
|
|
+ cameraX = oldCameraX;
|
|
|
|
+ cameraY = oldCameraY;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void placeLamp(LevelData ld, int ox, int oy)
|
|
|
|
+ {
|
|
|
|
+ ox -= 2;
|
|
|
|
+ oy -= 3;
|
|
|
|
+ for(int x = 0; x < 5; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < 5; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(3, ox + x, y + oy, 45 + 5 * y + x);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private LevelData generate()
|
|
|
|
+ {
|
|
|
|
+ int modules = 20;
|
|
|
|
+ int l = 4;
|
|
|
|
+ int w = modules * 10;
|
|
|
|
+ int h = 50;
|
|
|
|
+ int hh = h / 2;
|
|
|
|
+
|
|
|
|
+ heroSpawnX = 0;
|
|
|
|
+ heroSpawnY = (hh - 2) * Tile.SIZE;
|
|
|
|
+ hero.setPosition(heroSpawnX, heroSpawnY);
|
|
|
|
+
|
|
|
|
+ LevelData ld = new LevelData(null, 1, l, w, h);
|
|
|
|
+
|
|
|
|
+ // fill background with london background tile and clear foreground
|
|
|
|
+ for(int x = 0; x < w; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < h; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(0, x, y, 44);
|
|
|
|
+ ld.setTile(3, x, y, -1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // base interact layer
|
|
|
|
+ for(int x = 0; x < w; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < hh; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x, y, -1);
|
|
|
|
+ }
|
|
|
|
+ for(int y = hh; y < h; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x, y, 43);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // generate modules
|
|
|
|
+ Random r = new Random();
|
|
|
|
+ // base ground for start and end
|
|
|
|
+ for(int x = 0; x < 10; x++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x, hh, 42);
|
|
|
|
+ }
|
|
|
|
+ for(int x = 0; x < 10; x++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x + (modules - 1) * 10, hh, 42);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for(int i = 1; i < modules - 1; i++)
|
|
|
|
+ {
|
|
|
|
+ int ox = i * 10;
|
|
|
|
+ switch(r.nextInt(9))
|
|
|
|
+ {
|
|
|
|
+ case 0:
|
|
|
|
+ ld.setTile(1, ox, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 1, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 7, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 8, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 9, hh, 42);
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox + 2, hh - 1, 36);
|
|
|
|
+ ld.setTile(1, ox + 3, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 4, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 5, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 6, hh - 1, 43);
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox + 3, hh - 2, 36);
|
|
|
|
+ ld.setTile(1, ox + 4, hh - 2, 43);
|
|
|
|
+ ld.setTile(1, ox + 5, hh - 2, 43);
|
|
|
|
+ ld.setTile(1, ox + 6, hh - 2, 43);
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox + 4, hh - 3, 36);
|
|
|
|
+ ld.setTile(1, ox + 5, hh - 3, 42);
|
|
|
|
+ ld.setTile(1, ox + 6, hh - 3, 42);
|
|
|
|
+
|
|
|
|
+ placeLamp(ld, ox + 5, hh - 4);
|
|
|
|
+ break;
|
|
|
|
+ case 1:
|
|
|
|
+ ld.setTile(1, ox, hh - 1, 37);
|
|
|
|
+ ld.setTile(1, ox + 1, hh - 1, 38);
|
|
|
|
+ ld.setTile(1, ox + 2, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 3, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 4, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 5, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 6, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 7, hh - 1, 43);
|
|
|
|
+ ld.setTile(1, ox + 8, hh - 1, 41);
|
|
|
|
+ ld.setTile(1, ox + 9, hh - 1, 40);
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox + 2, hh - 2, 37);
|
|
|
|
+ ld.setTile(1, ox + 3, hh - 2, 38);
|
|
|
|
+ ld.setTile(1, ox + 4, hh - 2, 42);
|
|
|
|
+ ld.setTile(1, ox + 5, hh - 2, 42);
|
|
|
|
+ ld.setTile(1, ox + 6, hh - 2, 41);
|
|
|
|
+ ld.setTile(1, ox + 7, hh - 2, 40);
|
|
|
|
+
|
|
|
|
+ placeLamp(ld, ox + 4, hh - 3);
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ for(int x = 0; x < 5; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < 3; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, ox + x + 3, hh - y, 43);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for(int x = 0; x < 2; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < 3; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, ox + x + 6, hh - y - 3, 43);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 1, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 2, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 3, hh - 3, 42);
|
|
|
|
+ ld.setTile(1, ox + 4, hh - 3, 42);
|
|
|
|
+ ld.setTile(1, ox + 5, hh - 3, 42);
|
|
|
|
+ ld.setTile(1, ox + 6, hh - 6, 42);
|
|
|
|
+ ld.setTile(1, ox + 7, hh - 6, 42);
|
|
|
|
+ ld.setTile(1, ox + 8, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 9, hh, 42);
|
|
|
|
+
|
|
|
|
+ placeLamp(ld, ox + 3, hh - 4);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ ld.setTile(1, ox, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 1, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 2, hh + 1, 42);
|
|
|
|
+ ld.setTile(1, ox + 3, hh + 1, 42);
|
|
|
|
+ ld.setTile(1, ox + 4, hh + 2, 42);
|
|
|
|
+ ld.setTile(1, ox + 5, hh + 2, 42);
|
|
|
|
+ ld.setTile(1, ox + 6, hh + 3, 42);
|
|
|
|
+ ld.setTile(1, ox + 7, hh + 3, 42);
|
|
|
|
+ ld.setTile(1, ox + 8, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 9, hh, 42);
|
|
|
|
+
|
|
|
|
+ placeLamp(ld, ox + 6, hh + 2);
|
|
|
|
+
|
|
|
|
+ for(int x = 0; x < 6; x += 2)
|
|
|
|
+ {
|
|
|
|
+ for(int x2 = x; x2 < 6; x2++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, ox + x2 + 2, hh + (x / 2), -1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case 4:
|
|
|
|
+ for(int x = 0; x < 10; x++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x + ox, hh, 42);
|
|
|
|
+ }
|
|
|
|
+ placeLamp(ld, ox + 5, hh - 1);
|
|
|
|
+ break;
|
|
|
|
+ case 5:
|
|
|
|
+ for(int x = 0; x < 6; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < 4; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x + ox + 2, hh + y, -1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for(int x = 0; x < 2; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < 3; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x + ox + 4, hh + y + 4, -1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ld.setTile(1, ox, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 1, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 2, hh + 4, 42);
|
|
|
|
+ ld.setTile(1, ox + 3, hh + 4, 42);
|
|
|
|
+ ld.setTile(1, ox + 4, hh + 7, 42);
|
|
|
|
+ ld.setTile(1, ox + 5, hh + 7, 42);
|
|
|
|
+ ld.setTile(1, ox + 6, hh + 4, 42);
|
|
|
|
+ ld.setTile(1, ox + 7, hh + 4, 42);
|
|
|
|
+ ld.setTile(1, ox + 8, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 9, hh, 42);
|
|
|
|
+ placeLamp(ld, ox + 3, hh + 3);
|
|
|
|
+ break;
|
|
|
|
+ case 6:
|
|
|
|
+ {
|
|
|
|
+ int start = 0;
|
|
|
|
+ int end = 10;
|
|
|
|
+ int y = 0;
|
|
|
|
+ while(start < end)
|
|
|
|
+ {
|
|
|
|
+ for(int x = start; x < end; x++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x + ox, hh - y, 43);
|
|
|
|
+ }
|
|
|
|
+ ld.setTile(1, start + ox, hh - y, 42);
|
|
|
|
+ ld.setTile(1, end - 1 + ox, hh - y, 42);
|
|
|
|
+ y++;
|
|
|
|
+ start++;
|
|
|
|
+ end--;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case 7:
|
|
|
|
+ ld.setTile(1, ox, hh, 41);
|
|
|
|
+ ld.setTile(1, ox + 1, hh, 40);
|
|
|
|
+ ld.setTile(1, ox + 2, hh, -1);
|
|
|
|
+ ld.setTile(1, ox + 3, hh, -1);
|
|
|
|
+ ld.setTile(1, ox + 4, hh, -1);
|
|
|
|
+ ld.setTile(1, ox + 5, hh, -1);
|
|
|
|
+ ld.setTile(1, ox + 6, hh, -1);
|
|
|
|
+ ld.setTile(1, ox + 7, hh, -1);
|
|
|
|
+ ld.setTile(1, ox + 8, hh, 37);
|
|
|
|
+ ld.setTile(1, ox + 9, hh, 38);
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox + 2, hh + 1, 41);
|
|
|
|
+ ld.setTile(1, ox + 3, hh + 1, 40);
|
|
|
|
+ ld.setTile(1, ox + 4, hh + 1, -1);
|
|
|
|
+ ld.setTile(1, ox + 5, hh + 1, -1);
|
|
|
|
+ ld.setTile(1, ox + 6, hh + 1, 37);
|
|
|
|
+ ld.setTile(1, ox + 7, hh + 1, 38);
|
|
|
|
+
|
|
|
|
+ ld.setTile(1, ox + 4, hh + 2, 42);
|
|
|
|
+ ld.setTile(1, ox + 5, hh + 2, 42);
|
|
|
|
+
|
|
|
|
+ placeLamp(ld, ox + 4, hh + 1);
|
|
|
|
+ break;
|
|
|
|
+ case 8:
|
|
|
|
+ for(int x = 0; x < 8; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = 0; y < 7; y++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, x + ox + 1, hh + y, -1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ld.setTile(1, ox, hh, 42);
|
|
|
|
+ ld.setTile(1, ox + 9, hh, 42);
|
|
|
|
+ for(int x = 1; x < 9; x++)
|
|
|
|
+ {
|
|
|
|
+ ld.setTile(1, ox + x, hh + 7, 42);
|
|
|
|
+ }
|
|
|
|
+ placeLamp(ld, ox + 4, hh + 6);
|
|
|
|
+ ld.setTile(1, ox + 8, hh + 6,5);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ld;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
|
+ // basic stuff
|
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Entity getHero()
|
|
|
|
+ {
|
|
|
|
+ return hero;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void finishLevel()
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void scheduleReset()
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void spawnEntity(Entity ent)
|
|
|
|
+ {
|
|
|
|
+ spawnQueue.add(ent);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void increaseSouls(int score)
|
|
|
|
+ {
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public int getWidth()
|
|
|
|
+ {
|
|
|
|
+ return data.getWidth();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public int getHeight()
|
|
|
|
+ {
|
|
|
|
+ return data.getHeight();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
|
+ // tick
|
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+ public void tick()
|
|
|
|
+ {
|
|
|
|
+ Game.get().tickTiles();
|
|
|
|
+
|
|
|
|
+ // doing entity logic first
|
|
|
|
+ entities.values().removeIf(entity ->
|
|
|
|
+ {
|
|
|
|
+ entity.tick();
|
|
|
|
+ return entity.getHealth().shouldDespawn();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if(!spawnQueue.isEmpty())
|
|
|
|
+ {
|
|
|
|
+ spawnQueue.forEach(ent -> entities.put(entityCounter++, ent));
|
|
|
|
+ spawnQueue.clear();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(hero.getX() > data.getWidth() * Tile.SIZE)
|
|
|
|
+ {
|
|
|
|
+ hero.setPosition(heroSpawnX, heroSpawnY);
|
|
|
|
+ // calculate new camera position
|
|
|
|
+ cameraX = -getViewX(hero.getCenterX());
|
|
|
|
+ cameraY = -getViewY(hero.getCenterY());
|
|
|
|
+ oldCameraX = cameraX;
|
|
|
|
+ oldCameraY = cameraY;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ // calculate new camera position
|
|
|
|
+ oldCameraX = cameraX;
|
|
|
|
+ oldCameraY = cameraY;
|
|
|
|
+ cameraX = -getViewX(hero.getCenterX());
|
|
|
|
+ cameraY = -getViewY(hero.getCenterY());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // entity spawn layer after camera update
|
|
|
|
+ int startX = (int) (-cameraX / Tile.SIZE);
|
|
|
|
+ int startY = (int) (-cameraY / Tile.SIZE);
|
|
|
|
+ int endX = Math.min((int) Math.ceil((-cameraX + Shader.getViewWidth()) / Tile.SIZE), data.getWidth());
|
|
|
|
+ int endY = Math.min((int) Math.ceil((-cameraY + Shader.getViewHeight()) / Tile.SIZE), data.getWidth());
|
|
|
|
+ data.forEachEntity((x, y, tile) ->
|
|
|
|
+ {
|
|
|
|
+ if(tile > 0)
|
|
|
|
+ {
|
|
|
|
+ data.deactivateEntity(x, y);
|
|
|
|
+
|
|
|
|
+ Entity ent = EntityBuilder.fromId(tile, this, Utils.toCoord(x), Utils.toCoord(y));
|
|
|
|
+ if(ent != null)
|
|
|
|
+ {
|
|
|
|
+ entities.put(entityCounter++, ent);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, startX, endX, startY, endY);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private float getViewX(float x)
|
|
|
|
+ {
|
|
|
|
+ x -= Shader.getViewWidth() >> 1;
|
|
|
|
+ if(x < 0)
|
|
|
|
+ {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ float max = data.getWidth() * Tile.SIZE - Shader.getViewWidth();
|
|
|
|
+ if(x > max)
|
|
|
|
+ {
|
|
|
|
+ return max;
|
|
|
|
+ }
|
|
|
|
+ return x;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private float getViewY(float y)
|
|
|
|
+ {
|
|
|
|
+ y -= Shader.getViewHeight() >> 1;
|
|
|
|
+ if(y < 0)
|
|
|
|
+ {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ float max = data.getHeight() * Tile.SIZE - Shader.getViewHeight();
|
|
|
|
+ if(y > max)
|
|
|
|
+ {
|
|
|
|
+ return max;
|
|
|
|
+ }
|
|
|
|
+ return y;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void updateTile(int layer, int x, int y)
|
|
|
|
+ {
|
|
|
|
+ if(layer > data.getBackgroundIndex())
|
|
|
|
+ {
|
|
|
|
+ layer--;
|
|
|
|
+ }
|
|
|
|
+ meshes[layer][x / meshSize][y / meshSize].clear();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void updateTile(int x, int y)
|
|
|
|
+ {
|
|
|
|
+ updateTile(data.getBackgroundIndex(), x, y);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void drawMesh(int l, int tl, int mx, int my)
|
|
|
|
+ {
|
|
|
|
+ TextureRenderer tr = meshes[l][mx][my];
|
|
|
|
+ if(!tr.isBuilt())
|
|
|
|
+ {
|
|
|
|
+ int tsx = mx * meshSize;
|
|
|
|
+ int tsy = my * meshSize;
|
|
|
|
+ int tex = Math.min(tsx + meshSize, data.getWidth());
|
|
|
|
+ int tey = Math.min(tsy + meshSize, data.getHeight());
|
|
|
|
+ for(int x = tsx; x < tex; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = tsy; y < tey; y++)
|
|
|
|
+ {
|
|
|
|
+ Tile t = Game.get().getTile(data.getTile(tl, x, y));
|
|
|
|
+ if(t.shouldRender(x, y, this))
|
|
|
|
+ {
|
|
|
|
+ float minX = x * Tile.SIZE + t.getOffsetX();
|
|
|
|
+ float minY = y * Tile.SIZE + t.getOffsetY();
|
|
|
|
+ tr.addRectangle(minX, minY,
|
|
|
|
+ minX + t.getWidth(), minY + t.getHeight(),
|
|
|
|
+ t.getTextureMinX() + Level.ERROR, t.getTextureMinY() + Level.ERROR,
|
|
|
|
+ t.getTextureMaxX() - Level.ERROR, t.getTextureMaxY() - Level.ERROR);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ tr.build();
|
|
|
|
+ }
|
|
|
|
+ meshes[l][mx][my].draw();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void renderTick(float lag)
|
|
|
|
+ {
|
|
|
|
+ float camX = Utils.interpolate(oldCameraX, cameraX, lag);
|
|
|
|
+ float camY = Utils.interpolate(oldCameraY, cameraY, lag);
|
|
|
|
+
|
|
|
|
+ //System.out.println("CAM " + hero.getCenterX()+ " " + hero.getCenterY());
|
|
|
|
+ //System.out.println("CAM " + oldCameraX + " " + oldCameraY + " " + cameraX + " " + cameraY);
|
|
|
|
+
|
|
|
|
+ Shader.translateTo(camX, camY);
|
|
|
|
+ Shader.updateMatrix();
|
|
|
|
+
|
|
|
|
+ int startX = (int) (-camX / (meshSize * Tile.SIZE));
|
|
|
|
+ int startY = (int) (-camY / (meshSize * Tile.SIZE));
|
|
|
|
+ int endX = (int) Math.ceil((-camX + Shader.getViewWidth()) / (meshSize * Tile.SIZE));
|
|
|
|
+ int endY = (int) Math.ceil((-camY + Shader.getViewHeight()) / (meshSize * Tile.SIZE));
|
|
|
|
+
|
|
|
|
+ startX = Math.min(Math.max(startX, 0), meshWidth);
|
|
|
|
+ startY = Math.min(Math.max(startY, 0), meshHeight);
|
|
|
|
+ endX = Math.min(Math.max(endX, 0), meshWidth);
|
|
|
|
+ endY = Math.min(Math.max(endY, 0), meshHeight);
|
|
|
|
+
|
|
|
|
+ // background
|
|
|
|
+ Shader.setColorEnabled(false);
|
|
|
|
+ Shader.setTextureEnabled(true);
|
|
|
|
+ Shader.setBlendingEnabled(true);
|
|
|
|
+ Level.TILES.bind();
|
|
|
|
+
|
|
|
|
+ int fromLayer = 0;
|
|
|
|
+ int toLayer = data.getBackgroundIndex() + 1;
|
|
|
|
+
|
|
|
|
+ for(int l = fromLayer; l < toLayer; l++)
|
|
|
|
+ {
|
|
|
|
+ for(int mx = startX; mx < endX; mx++)
|
|
|
|
+ {
|
|
|
|
+ for(int my = startY; my < endY; my++)
|
|
|
|
+ {
|
|
|
|
+ drawMesh(l, l, mx, my);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // entities
|
|
|
|
+
|
|
|
|
+ entities.values().forEach(entity ->
|
|
|
|
+ {
|
|
|
|
+ entity.renderTick(lag);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // foreground
|
|
|
|
+ Shader.setColorEnabled(false);
|
|
|
|
+ Shader.setTextureEnabled(true);
|
|
|
|
+ Shader.setBlendingEnabled(true);
|
|
|
|
+ Level.TILES.bind();
|
|
|
|
+
|
|
|
|
+ fromLayer = toLayer + 1;
|
|
|
|
+ toLayer = data.getLayers();
|
|
|
|
+
|
|
|
|
+ for(int l = fromLayer; l < toLayer; l++)
|
|
|
|
+ {
|
|
|
|
+ for(int mx = startX; mx < endX; mx++)
|
|
|
|
+ {
|
|
|
|
+ for(int my = startY; my < endY; my++)
|
|
|
|
+ {
|
|
|
|
+ drawMesh(l - 1, l, mx, my);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
|
+ // collision box, interaction layer
|
|
|
|
+ // -------------------------------------------------------------------------
|
|
|
|
+
|
|
|
|
+ private Tile getInteractionTile(int x, int y)
|
|
|
|
+ {
|
|
|
|
+ int i = data.getInteractionTile(x, y);
|
|
|
|
+ if(i == -1)
|
|
|
|
+ {
|
|
|
|
+ return Game.FALLBACK_TILE;
|
|
|
|
+ }
|
|
|
|
+ return Game.get().getTile(i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private CollisionObject getMovementBox(int x, int y)
|
|
|
|
+ {
|
|
|
|
+ int i = data.getInteractionTile(x, y);
|
|
|
|
+ if(i == -1)
|
|
|
|
+ {
|
|
|
|
+ return CollisionObject.NULL_BOX;
|
|
|
|
+ }
|
|
|
|
+ return Game.get().getTile(i).getMovementBox(x, y, this).reset().offset(Utils.toCoord(x), Utils.toCoord(y));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<CollisionObject> getMovementBoxesAt(CollisionObject box, Entity not)
|
|
|
|
+ {
|
|
|
|
+ List<CollisionObject> boxes;
|
|
|
|
+ if(not != null)
|
|
|
|
+ {
|
|
|
|
+ boxes = getEntitiesCollidingWith(not, box).stream().map(ent -> ent.getBox()).collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ boxes = new LinkedList<>();
|
|
|
|
+ }
|
|
|
|
+ int startX = Utils.toBlock(box.getMinX());
|
|
|
|
+ int endX = Utils.toBlock(box.getMaxX());
|
|
|
|
+ int startY = Utils.toBlock(box.getMinY());
|
|
|
|
+ int endY = Utils.toBlock(box.getMaxY());
|
|
|
|
+
|
|
|
|
+ for(int x = startX; x <= endX; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = startY; y <= endY; y++)
|
|
|
|
+ {
|
|
|
|
+ CollisionObject cb = getMovementBox(x, y);
|
|
|
|
+ if(cb.mayCollide(box) && cb != CollisionObject.NULL_BOX)
|
|
|
|
+ {
|
|
|
|
+ boxes.add(cb.copy());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return boxes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private CollisionObject getCollisionBox(int x, int y)
|
|
|
|
+ {
|
|
|
|
+ int i = data.getInteractionTile(x, y);
|
|
|
|
+ if(i == -1)
|
|
|
|
+ {
|
|
|
|
+ return CollisionObject.NULL_BOX;
|
|
|
|
+ }
|
|
|
|
+ Tile tile = Game.get().getTile(i);
|
|
|
|
+ return tile.getCollisionBox(x, y, this).reset().offset(Utils.toCoord(x), Utils.toCoord(y));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<Location> getCollisionBoxesAt(CollisionObject cb)
|
|
|
|
+ {
|
|
|
|
+ LinkedList<Location> boxes = new LinkedList<>();
|
|
|
|
+ int startX = Utils.toBlock(cb.getMinX());
|
|
|
|
+ int endX = Utils.toBlock(cb.getMaxX());
|
|
|
|
+ int startY = Utils.toBlock(cb.getMinY());
|
|
|
|
+ int endY = Utils.toBlock(cb.getMaxY());
|
|
|
|
+
|
|
|
|
+ for(int x = startX; x <= endX; x++)
|
|
|
|
+ {
|
|
|
|
+ for(int y = startY; y <= endY; y++)
|
|
|
|
+ {
|
|
|
|
+ if(getCollisionBox(x, y).isColliding(cb))
|
|
|
|
+ {
|
|
|
|
+ boxes.add(new Location(getInteractionTile(x, y), this, x, y));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return boxes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<Entity> getEntitiesCollidingWith(Entity not, CollisionObject cb)
|
|
|
|
+ {
|
|
|
|
+ return entities.values().stream().filter(ent -> ent != not && ent.getBox().isColliding(cb)).collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+}
|