123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- package me.hammerle.supersnuvi.gamelogic;
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.function.Consumer;
- import java.util.stream.Collectors;
- import me.hammerle.snuviscript.code.Script;
- import me.hammerle.supersnuvi.Game;
- import me.hammerle.supersnuvi.entity.Entity;
- import me.hammerle.supersnuvi.entity.EntityBuilder;
- import me.hammerle.supersnuvi.rendering.TileUpdater;
- 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 abstract class Level
- {
- // -------------------------------------------------------------------------
- // level data
- // -------------------------------------------------------------------------
-
- private final TileUpdater tileUpdater = new TileUpdater();
-
- public abstract LevelData getData();
-
- public String getName()
- {
- return "Unknown";
- }
-
- public String getFileName()
- {
- return "Unknown";
- }
-
- public final TileUpdater getTileUpdater()
- {
- return tileUpdater;
- }
-
- // -------------------------------------------------------------------------
- // level stats
- // -------------------------------------------------------------------------
-
- public int getCurrentBottles()
- {
- return 0;
- }
-
- public int getMaxBottles()
- {
- return 0;
- }
-
- public void addBottles(int bottles)
- {
- }
-
- public float getTime()
- {
- return 0;
- }
-
- public void addMessage(String message)
- {
- }
-
- public String getMessage()
- {
- return null;
- }
-
- // -------------------------------------------------------------------------
- // entity related
- // -------------------------------------------------------------------------
-
- private final HashMap<Integer, Entity> entities = new HashMap<>();
- private final LinkedList<Entity> spawnQueue = new LinkedList<>();
- private Entity hero = null;
- private int entityCounter = 0;
-
- public final Entity getHero()
- {
- return hero;
- }
-
- public final void setHero(Entity hero)
- {
- this.hero = hero;
- }
-
- public final void removeEntities()
- {
- entities.clear();
- }
-
- public final void spawnEntity(Entity ent)
- {
- spawnQueue.add(ent);
- }
-
- public final void tickEntities()
- {
- entities.values().removeIf(ent ->
- {
- ent.tick(this);
- if(ent.getHealth().shouldDespawn() || (ent.getY() > getData().getHeight() * Tile.SIZE))
- {
- ent.getHealth().onDespawn();
- callEvent("entity_despawn", (sc) ->
- {
- sc.setVar("entity", ent);
- }, null);
- return true;
- }
- return false;
- });
- if(!spawnQueue.isEmpty())
- {
- spawnQueue.forEach(ent ->
- {
- entities.put(entityCounter++, ent);
- callEvent("entity_spawn", (sc) ->
- {
- sc.setVar("entity", ent);
- }, null);
- });
- spawnQueue.clear();
- }
- }
-
- public final List<Entity> getEntitiesCollidingWith(Entity not, CollisionObject cb)
- {
- return entities.values().stream().filter(ent -> ent != not && ent.getBox().isColliding(cb)).collect(Collectors.toList());
- }
-
- public final void forEachEntity(Consumer<Entity> c)
- {
- entities.values().forEach(c);
- }
-
- // -------------------------------------------------------------------------
- // controlling
- // -------------------------------------------------------------------------
-
- private boolean shouldReset = false;
- private boolean done = false;
-
- public abstract void tick();
-
- public final void finishLevel()
- {
- shouldReset = true;
- done = true;
- }
-
- public final boolean isFinished()
- {
- return done;
- }
-
- public final boolean shouldReset()
- {
- return shouldReset;
- }
-
- public final void scheduleReset()
- {
- shouldReset = true;
- }
-
- public final void reset()
- {
- onReset();
- shouldReset = false;
- done = false;
-
- // spawn entities
- getData().forEachEntity((x, y, tile) ->
- {
- if(tile > 0)
- {
- Entity ent = EntityBuilder.fromId(tile, this, Utils.toCoord(x), Utils.toCoord(y));
- if(ent != null)
- {
- entities.put(entityCounter++, ent);
- }
- }
- }, 0, getData().getWidth(), 0, getData().getHeight());
- }
-
- protected void onReset()
- {
- };
-
- // -------------------------------------------------------------------------
- // collision
- // -------------------------------------------------------------------------
-
- private Tile getInteractionTile(int x, int y)
- {
- int i = getData().getInteractionTile(x, y);
- if(i == -1)
- {
- return Game.FALLBACK_TILE;
- }
- return Game.get().getTile(i);
- }
-
- private CollisionObject getMovementBox(int x, int y)
- {
- int i = getData().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));
- }
-
- public final 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 = getData().getInteractionTile(x, y);
- if(i == -1)
- {
- return CollisionObject.NULL_BOX;
- }
- return Game.get().getTile(i).getCollisionBox(x, y, this).reset().offset(Utils.toCoord(x), Utils.toCoord(y));
- }
-
- public final 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;
- }
-
- // -------------------------------------------------------------------------
- // scripting
- // -------------------------------------------------------------------------
-
- public void callEvent(String name, Consumer<Script> before, Consumer<Script> after)
- {
- }
-
- public final void callEvent(String name)
- {
- callEvent(name, null, null);
- }
- }
|