Up/Down stairs, transition fade, improved controls.

v5stable
Ondřej Hruška 11 years ago
parent 66adc1ffa9
commit c74869d3b7
  1. BIN
      res/img/tiles16.png
  2. BIN
      res/img/tiles16.xcf
  3. 2
      src/mightypork/gamecore/eventbus/EventBus.java
  4. 28
      src/mightypork/gamecore/util/math/algo/pathfinding/PathFinder.java
  5. 26
      src/mightypork/rogue/Res.java
  6. 12
      src/mightypork/rogue/screens/game/HudLayer.java
  7. 2
      src/mightypork/rogue/screens/game/NavItemSlot.java
  8. 2
      src/mightypork/rogue/screens/menu/MenuLayer.java
  9. 4
      src/mightypork/rogue/world/PlayerControl.java
  10. 48
      src/mightypork/rogue/world/World.java
  11. 6
      src/mightypork/rogue/world/WorldCreator.java
  12. 4
      src/mightypork/rogue/world/WorldProvider.java
  13. 6
      src/mightypork/rogue/world/WorldRenderer.java
  14. 8
      src/mightypork/rogue/world/entity/Entity.java
  15. 6
      src/mightypork/rogue/world/entity/entities/MonsterAi.java
  16. 2
      src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java
  17. 20
      src/mightypork/rogue/world/events/WorldAscendRequest.java
  18. 10
      src/mightypork/rogue/world/events/WorldAscendRequestListener.java
  19. 15
      src/mightypork/rogue/world/events/WorldDescendRequest.java
  20. 10
      src/mightypork/rogue/world/events/WorldDescendRequestListener.java
  21. 12
      src/mightypork/rogue/world/gen/LevelGenerator.java
  22. 6
      src/mightypork/rogue/world/gen/MapTheme.java
  23. 80
      src/mightypork/rogue/world/gen/ScratchMap.java
  24. 18
      src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java
  25. 60
      src/mightypork/rogue/world/gen/rooms/EntranceRoom.java
  26. 52
      src/mightypork/rogue/world/gen/rooms/ExitRoom.java
  27. 2
      src/mightypork/rogue/world/gen/rooms/Rooms.java
  28. 14
      src/mightypork/rogue/world/gen/themes/ThemeBrick.java
  29. 90
      src/mightypork/rogue/world/gui/MapView.java
  30. 6
      src/mightypork/rogue/world/gui/Minimap.java
  31. 18
      src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java
  32. 30
      src/mightypork/rogue/world/gui/interaction/MIPMouse.java
  33. 12
      src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java
  34. 2
      src/mightypork/rogue/world/item/items/ItemMeat.java
  35. 198
      src/mightypork/rogue/world/level/Level.java
  36. 109
      src/mightypork/rogue/world/level/LevelAccess.java
  37. 127
      src/mightypork/rogue/world/level/LevelReadAccess.java
  38. 4
      src/mightypork/rogue/world/level/render/EntityRenderContext.java
  39. 6
      src/mightypork/rogue/world/level/render/MapRenderContext.java
  40. 4
      src/mightypork/rogue/world/level/render/TileRenderContext.java
  41. 25
      src/mightypork/rogue/world/tile/Tile.java
  42. 34
      src/mightypork/rogue/world/tile/TileRenderer.java
  43. 4
      src/mightypork/rogue/world/tile/TileType.java
  44. 8
      src/mightypork/rogue/world/tile/Tiles.java
  45. 33
      src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java
  46. 35
      src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java
  47. 34
      src/mightypork/rogue/world/tile/tiles/TileBaseEntrance.java
  48. 34
      src/mightypork/rogue/world/tile/tiles/TileBaseExit.java
  49. 22
      src/mightypork/rogue/world/tile/tiles/TileBaseStairs.java
  50. 6
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickDoor.java
  51. 25
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickEntrance.java
  52. 25
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickExit.java
  53. 2
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickFloor.java
  54. 2
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickPassage.java
  55. 6
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickSecretDoor.java
  56. 2
      src/mightypork/rogue/world/tile/tiles/brick/TileBrickWall.java

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

@ -342,7 +342,7 @@ final public class EventBus implements Destroyable, BusAccess {
assertLive();
if (sendingDirect) {
Log.w("Cannot send a direct event in response to another.");
Log.w(logMark + "Already dispatching, adding event to queue instead: " + Log.str(event));
sendQueued(event);
return;
}

@ -25,16 +25,20 @@ public abstract class PathFinder {
public static final Heuristic CORNER_HEURISTIC = new ManhattanHeuristic();
public static final Heuristic DIAGONAL_HEURISTIC = new DiagonalHeuristic();
private boolean ignoreStart;
private boolean ignoreEnd;
public List<Step> findPathRelative(Coord start, Coord end)
{
return findPathRelative(start, end, false);
return findPathRelative(start, end, ignoreStart, ignoreEnd);
}
public List<Step> findPathRelative(Coord start, Coord end, boolean ignoreEnd)
public List<Step> findPathRelative(Coord start, Coord end, boolean ignoreStart, boolean ignoreEnd)
{
final List<Coord> path = findPath(start, end, ignoreEnd);
final List<Coord> path = findPath(start, end, ignoreStart, ignoreEnd);
if (path == null) return null;
final List<Step> out = new ArrayList<>();
@ -53,11 +57,11 @@ public abstract class PathFinder {
public List<Coord> findPath(Coord start, Coord end)
{
return findPath(start, end, false);
return findPath(start, end, ignoreStart, ignoreEnd);
}
public List<Coord> findPath(Coord start, Coord end, boolean ignoreEnd)
public List<Coord> findPath(Coord start, Coord end, boolean ignoreStart, boolean ignoreEnd)
{
final LinkedList<Node> open = new LinkedList<>();
final LinkedList<Node> closed = new LinkedList<>();
@ -92,7 +96,7 @@ public abstract class PathFinder {
for (final Step go : walkDirs) {
final Coord c = current.pos.add(go);
if (!isAccessible(c) && !(c.equals(end) && ignoreEnd)) continue;
if (!isAccessible(c) && !(c.equals(end) && ignoreEnd) && !(c.equals(start) && ignoreStart)) continue;
final Node a = new Node(c);
a.g_cost = current.g_cost + getCost(c, a.pos);
a.h_cost = (int) (heuristic.getCost(a.pos, end) * getMinCost());
@ -203,6 +207,18 @@ public abstract class PathFinder {
}
public void setIgnoreEnd(boolean ignoreEnd)
{
this.ignoreEnd = ignoreEnd;
}
public void setIgnoreStart(boolean ignoreStart)
{
this.ignoreStart = ignoreStart;
}
/**
* @return used heuristic
*/

@ -100,6 +100,8 @@ public final class Res {
textures.addSheet("tile.brick.door.secret", grid.makeSheet(0, 3, 2, 1));
textures.addSheet("tile.brick.passage", grid.makeSheet(3, 2, 4, 1));
textures.addQuad("tile.brick.stairs.up", grid.makeQuad(0, 6));
textures.addQuad("tile.brick.stairs.down", grid.makeQuad(1, 6));
textures.addQuad("tile.shadow.n", grid.makeQuad(0, 7));
textures.addQuad("tile.shadow.s", grid.makeQuad(0, 7).flipY());
@ -135,21 +137,33 @@ public final class Res {
}
public static TxQuad getTxQuad(String key)
public static GLTexture getTexture(String key)
{
return textures.getQuad(key);
return textures.getTexture(key);
}
public static GLTexture getTexture(String key)
/**
* Get a texture sheet by key
*
* @param key
* @return sheet
*/
public static TxSheet txs(String key)
{
return textures.getTexture(key);
return textures.getSheet(key);
}
public static TxSheet sheet(String key)
/**
* Get a texture quad by key
*
* @param key
* @return quad
*/
public static TxQuad txq(String key)
{
return textures.getSheet(key);
return textures.getQuad(key);
}

@ -44,7 +44,7 @@ public class HudLayer extends ScreenLayer {
final Num w = root.width();
final Num minWH = w.min(h).max(700); // avoid too small shrinking
final ImagePainter nav = new ImagePainter(Res.getTxQuad("panel"));
final ImagePainter nav = new ImagePainter(Res.txq("panel"));
nav.setRect(root.bottomEdge().growUp(minWH.perc(7)));
root.add(nav);
@ -52,8 +52,8 @@ public class HudLayer extends ScreenLayer {
itemSlots.setRect(nav.growUp(nav.height()).move(nav.height().mul(0.2), nav.height().mul(-0.2)));
root.add(itemSlots);
itemSlots.add(new NavItemSlot(Res.getTxQuad("meat")));
itemSlots.add(new NavItemSlot(Res.getTxQuad("sword")));
itemSlots.add(new NavItemSlot(Res.txq("meat")));
itemSlots.add(new NavItemSlot(Res.txq("sword")));
final Rect shrunk = root.shrink(minWH.perc(3));
final Num displays_height = minWH.perc(6);
@ -62,9 +62,9 @@ public class HudLayer extends ScreenLayer {
final HeartBar hearts = new HeartBar(
playerHealthTotal,
playerHealthActive,
Res.getTxQuad("heart_on"),
Res.getTxQuad("heart_half"),
Res.getTxQuad("heart_off"),
Res.txq("heart_on"),
Res.txq("heart_half"),
Res.txq("heart_off"),
AlignX.LEFT);
//@formatter:on

@ -28,7 +28,7 @@ public class NavItemSlot extends ClickableComponent implements MouseMotionListen
public NavItemSlot(TxQuad image)
{
this.image = image;
this.frame = Res.getTxQuad("item_frame");
this.frame = Res.txq("item_frame");
final Rect ref = shrink(height().perc(8));
yOffset = new NumAnimated(0, Easing.LINEAR);

@ -39,7 +39,7 @@ class MenuLayer extends ScreenLayer {
root.add(layout);
int r = 0;
final ImagePainter ip = new ImagePainter(Res.getTxQuad("logo"));
final ImagePainter ip = new ImagePainter(Res.txq("logo"));
ip.keepAspectRatio();
layout.put(ip, r, 0, 5, 1);
r += 6;

@ -8,7 +8,7 @@ import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.level.LevelAccess;
import mightypork.rogue.world.level.Level;
public abstract class PlayerControl {
@ -76,7 +76,7 @@ public abstract class PlayerControl {
}
public LevelAccess getLevel()
public Level getLevel()
{
return getWorld().getCurrentLevel();
}

@ -4,6 +4,7 @@ package mightypork.rogue.world;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus;
@ -15,7 +16,6 @@ import mightypork.gamecore.util.math.timing.Pauseable;
import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.LevelAccess;
/**
@ -134,7 +134,13 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
final Coord spawn = floor.getEnterPoint();
floor.forceFreeTile(spawn);
floor.addEntity(playerEntity, spawn);
final Random rand = new Random(seed + 71);
while (!floor.addEntity(playerEntity, spawn)) {
spawn.x += -1 + rand.nextInt(3);
spawn.y += -1 + rand.nextInt(3);
}
floor.explore(spawn);
playerInfo.setLevel(level);
@ -142,7 +148,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
}
public LevelAccess getCurrentLevel()
public Level getCurrentLevel()
{
return levels.get(playerInfo.getLevel());
}
@ -193,4 +199,40 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
return paused;
}
public boolean canAscend()
{
return playerInfo.getLevel() > 0;
}
public boolean canDescend()
{
return playerInfo.getLevel() < levels.size() - 1;
}
public void ascend()
{
if (!canAscend()) return;
int lvl_num = playerInfo.getLevel();
getCurrentLevel().removeEntity(playerEntity);
playerInfo.setLevel(lvl_num - 1);
getCurrentLevel().addEntity(playerEntity, getCurrentLevel().getExitPoint());
getCurrentLevel().explore(playerEntity.getCoord());
}
public void descend()
{
if (!canDescend()) return;
int lvl_num = playerInfo.getLevel();
getCurrentLevel().removeEntity(playerEntity);
playerInfo.setLevel(lvl_num + 1);
getCurrentLevel().addEntity(playerEntity, getCurrentLevel().getEnterPoint());
getCurrentLevel().explore(playerEntity.getCoord());
}
}

@ -20,8 +20,10 @@ public class WorldCreator {
final World w = new World();
w.setSeed(seed);
for (int i = 0; i < 7; i++) {
final Level l = LevelGenerator.build(w, rand.nextLong(), i, LevelGenerator.DUNGEON_THEME);
int count = 6;
for (int i = 1; i <= count; i++) {
final Level l = LevelGenerator.build(w, rand.nextLong(), i, LevelGenerator.DUNGEON_THEME, i == count);
w.addLevel(l);
}

@ -8,7 +8,7 @@ import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.clients.RootBusNode;
import mightypork.gamecore.util.ion.Ion;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.LevelAccess;
import mightypork.rogue.world.level.Level;
public class WorldProvider extends RootBusNode {
@ -85,7 +85,7 @@ public class WorldProvider extends RootBusNode {
}
public LevelAccess getCurrentLevel()
public Level getCurrentLevel()
{
return getWorld().getCurrentLevel();
}

@ -12,7 +12,7 @@ import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.math.constraints.vect.VectConst;
import mightypork.rogue.Res;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.LevelAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
@ -29,7 +29,7 @@ public class WorldRenderer extends RectProxy {
// can be changed
private RectConst mapRect;
private LevelAccess activeLevel;
private Level activeLevel;
private final Rect rightShadow;
private final Rect leftShadow;
@ -57,7 +57,7 @@ public class WorldRenderer extends RectProxy {
private void prepareRenderContextIfNeeded()
{
final LevelAccess level = WorldProvider.get().getCurrentLevel();
final Level level = WorldProvider.get().getCurrentLevel();
if (activeLevel == level) return;

@ -18,7 +18,7 @@ import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.modules.EntityModuleHealth;
import mightypork.rogue.world.entity.modules.EntityModulePosition;
import mightypork.rogue.world.entity.render.EntityRenderer;
import mightypork.rogue.world.level.LevelAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.MapRenderContext;
@ -29,7 +29,7 @@ import mightypork.rogue.world.level.render.MapRenderContext;
*/
public abstract class Entity implements IonObjBundled, Updateable {
private LevelAccess level;
private Level level;
private final EntityModel model;
protected final Random rand = new Random();
@ -120,7 +120,7 @@ public abstract class Entity implements IonObjBundled, Updateable {
}
public void setLevel(LevelAccess level)
public void setLevel(Level level)
{
if (level != null) level.freeTile(getCoord());
@ -130,7 +130,7 @@ public abstract class Entity implements IonObjBundled, Updateable {
}
public final LevelAccess getLevel()
public final Level getLevel()
{
return level;
}

@ -87,6 +87,8 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
};
noDoorPf.setIgnoreEnd(true);
timerAttack.start();
timerFindPrey.start();
timerSleepStart.start();
@ -211,7 +213,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
//System.out.println("-- path would be: " + entity.getCoord() + "->" + prey.getCoord());
// check if reachable without leaving room
final List<Coord> noDoorPath = noDoorPf.findPath(entity.getCoord(), prey.getCoord(), true);
final List<Coord> noDoorPath = noDoorPf.findPath(entity.getCoord(), prey.getCoord());
if (noDoorPath == null) {
//System.out.println("-- Could not navigate to prey, aborting.");
@ -273,7 +275,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
{
if (!isPreyValid(prey)) return null;
return entity.getPathFinder().findPathRelative(entity.getCoord(), prey.getCoord(), true);
return entity.getPathFinder().findPathRelative(entity.getCoord(), prey.getCoord(), false, true);
}

@ -35,7 +35,7 @@ public class EntityRendererMobLR extends EntityRenderer {
public EntityRendererMobLR(Entity entity, String sheetKey)
{
this.entity = entity;
this.sheet = Res.sheet(sheetKey);
this.sheet = Res.txs(sheetKey);
}

@ -0,0 +1,20 @@
package mightypork.rogue.world.events;
import mightypork.gamecore.eventbus.BusEvent;
/**
* Player wants to go up
*
* @author MightyPork
*/
public class WorldAscendRequest extends BusEvent<WorldAscendRequestListener> {
@Override
protected void handleBy(WorldAscendRequestListener handler)
{
handler.onAscendRequest();
}
}

@ -0,0 +1,10 @@
package mightypork.rogue.world.events;
public interface WorldAscendRequestListener {
/**
* Player clicked up-stairs
*/
void onAscendRequest();
}

@ -0,0 +1,15 @@
package mightypork.rogue.world.events;
import mightypork.gamecore.eventbus.BusEvent;
public class WorldDescendRequest extends BusEvent<WorldDescendRequestListener> {
@Override
protected void handleBy(WorldDescendRequestListener handler)
{
handler.onDescendRequest();
}
}

@ -0,0 +1,10 @@
package mightypork.rogue.world.events;
public interface WorldDescendRequestListener {
/**
* Player clicked down-stairs
*/
void onDescendRequest();
}

@ -21,7 +21,7 @@ public class LevelGenerator {
public static final MapTheme DUNGEON_THEME = new ThemeBrick();
public static Level build(World world, long seed, int complexity, MapTheme theme)
public static Level build(World world, long seed, int complexity, MapTheme theme, boolean lastLevel)
{
Log.f3("Generating level of complexity: " + complexity);
@ -32,14 +32,16 @@ public class LevelGenerator {
final ScratchMap map = new ScratchMap(max_size, theme, rand);
// start
map.addRoom(Rooms.BASIC);
map.addRoom(Rooms.ENTRANCE, true);
for (int i = 0; i < 1 + complexity / 2 + rand.nextInt((int) (1 + complexity * 0.3)); i++) {
map.addRoom(Rooms.BASIC);
if (rand.nextInt(7) > 0) map.addRoom(Rooms.SECRET);
if (rand.nextInt(6) > 0) map.addRoom(Rooms.DEAD_END);
map.addRoom(Rooms.BASIC, false);
if (rand.nextInt(7) > 0) map.addRoom(Rooms.SECRET, false);
if (rand.nextInt(6) > 0) map.addRoom(Rooms.DEAD_END, false);
}
if (!lastLevel) map.addRoom(Rooms.EXIT, true);
map.buildCorridors();
final Coord size = map.getNeededSize();

@ -24,4 +24,10 @@ public interface MapTheme {
TileModel secretDoor();
TileModel entrance();
TileModel exit();
}

@ -14,7 +14,7 @@ import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.algo.pathfinding.Heuristic;
import mightypork.gamecore.util.math.algo.pathfinding.PathFinder;
import mightypork.rogue.world.level.LevelAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.Tiles;
@ -43,6 +43,7 @@ public class ScratchMap {
{
if (!isIn(pos)) return false;
final Tile t = get(pos);
if (t.isStairs()) return false;
return t.isPotentiallyWalkable() || (t.genData.protection != TileProtectLevel.STRONG);
}
@ -60,6 +61,7 @@ public class ScratchMap {
case PASSAGE:
return 10;
case STAIRS:
case FLOOR:
return 20;
@ -96,12 +98,19 @@ public class ScratchMap {
};
{
// needed for when the path starts / ends at stairs.
pathf.setIgnoreEnd(true);
pathf.setIgnoreStart(true);
}
Coord genMin;
Coord genMax;
private final MapTheme theme;
private final Random rand;
private Coord enterPoint;
private final Coord enterPoint = new Coord();
private final Coord exitPoint = new Coord();
private static final boolean FIX_GLITCHES = true;
@ -122,12 +131,14 @@ public class ScratchMap {
}
public void addRoom(RoomBuilder rb)
public void addRoom(RoomBuilder rb, boolean critical)
{
final Coord center = Coord.make(0, 0);
int failed = 0;
int failed_total = 0;
while (true) {
final int sizeX = genMax.x - genMin.x;
@ -138,24 +149,20 @@ public class ScratchMap {
switch (rand.nextInt(4)) {
case 0:
center.x += 1 + rand.nextInt(4);
center.x += 1 + rand.nextInt(critical ? 6 : 4);
break;
case 1:
center.x -= 1 + rand.nextInt(4);
center.x -= 1 + rand.nextInt(critical ? 6 : 4);
break;
case 2:
center.y += 1 + rand.nextInt(4);
center.y += 1 + rand.nextInt(critical ? 6 : 4);
break;
case 3:
center.y -= 1 + rand.nextInt(4);
center.y -= 1 + rand.nextInt(critical ? 6 : 4);
}
final RoomDesc rd = rb.buildToFit(this, theme, rand, center);
if (rd != null) {
if (rooms.isEmpty()) {
enterPoint = center.copy();
}
rooms.add(rd);
genMin.x = Math.min(genMin.x, rd.min.x);
@ -163,6 +170,7 @@ public class ScratchMap {
genMax.x = Math.max(genMax.x, rd.max.x);
genMax.y = Math.max(genMax.y, rd.max.y);
clampBounds();
nodes.add(center);
Log.f3("placed room: " + rd.min + " -> " + rd.max);
@ -170,10 +178,28 @@ public class ScratchMap {
return;
} else {
failed++;
failed_total++;
if (failed > 200) {
Log.w("Faild to build room.");
return;
if (critical) {
genMin.x -= 5;
genMin.y -= 5;
genMax.x += 5;
genMax.y += 5;
clampBounds();
failed = 0;
continue;
} else {
return;
}
}
if (failed_total > 1000) {
throw new RuntimeException("Generation error - could not place critical room.");
}
}
}
@ -181,6 +207,15 @@ public class ScratchMap {
}
private void clampBounds()
{
genMin.x = Calc.clamp(genMin.x, 0, width - 1);
genMin.y = Calc.clamp(genMin.y, 0, height - 1);
genMax.x = Calc.clamp(genMax.x, 0, width - 1);
genMax.y = Calc.clamp(genMax.y, 0, height - 1);
}
public boolean isIn(Coord pos)
{
return pos.x >= 0 && pos.x < width && pos.y >= 0 && pos.y < height;
@ -320,9 +355,10 @@ public class ScratchMap {
genMax.x = Math.max(genMax.x, c.x);
genMax.y = Math.max(genMax.y, c.y);
clampBounds();
final Tile current = get(c);
if (!current.isNull() && (current.isPotentiallyWalkable())) continue; // floor already, let it be
if (!current.isNull() && (current.isPotentiallyWalkable() || current.isStairs())) continue; // floor already, let it be
if (i == 0 && j == 0) {
set(c, theme.floor());
@ -410,7 +446,7 @@ public class ScratchMap {
}
public void writeToLevel(LevelAccess level)
public void writeToLevel(Level level)
{
// make sure no walkable are at edges.
final Coord c = Coord.make(0, 0);
@ -503,5 +539,21 @@ public class ScratchMap {
final Coord entrance = new Coord(enterPoint.x - genMin.x, enterPoint.y - genMin.y);
level.setEnterPoint(entrance);
System.out.println("Entrance = " + entrance + ", original: " + enterPoint + ", minG=" + genMin + ", maxG=" + genMax);
final Coord exit = new Coord(exitPoint.x - genMin.x, exitPoint.y - genMin.y);
level.setExitPoint(exit);
}
public void setEntrance(Coord pos)
{
enterPoint.setTo(pos);
}
public void setExit(Coord pos)
{
exitPoint.setTo(pos);
}
}

@ -34,8 +34,8 @@ public abstract class AbstractRectRoom implements RoomBuilder {
if (!map.isClear(min.add(-1, -1), max)) return null;
map.fill(min, max, theme.floor());
map.border(min, max, theme.wall());
map.fill(min, max, getFloor(theme));
map.border(min, max, getWall(theme));
map.protect(min, max, getWallProtectionLevel());
placeDoors(map, theme, rand, min, max);
@ -46,12 +46,24 @@ public abstract class AbstractRectRoom implements RoomBuilder {
}
protected TileModel getWall(MapTheme theme)
{
return theme.wall();
}
protected TileModel getFloor(MapTheme theme)
{
return theme.floor();
}
protected void placeDoors(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max)
{
final int width = max.x - min.x;
final int height = max.y - min.y;
for (int i = 0, j = 0; i <= getDoorCount(rand) && j < 100; j++) { // j is to prevent inf loop
for (int i = 0, j = 0; i < getDoorCount(rand) && j < 100; j++) { // j is to prevent inf loop
final Coord door = min.copy();
switch (rand.nextInt(4)) {
case 0:

@ -0,0 +1,60 @@
package mightypork.rogue.world.gen.rooms;
import java.util.Random;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.gen.MapTheme;
import mightypork.rogue.world.gen.ScratchMap;
import mightypork.rogue.world.gen.TileProtectLevel;
import mightypork.rogue.world.tile.TileModel;
public class EntranceRoom extends AbstractRectRoom {
@Override
protected Coord getInnerSize(Random rand)
{
return Coord.make(3 + rand.nextInt(2) * 2, 3 + rand.nextInt(2) * 3);
}
@Override
protected TileProtectLevel getWallProtectionLevel()
{
return TileProtectLevel.WEAK;
}
@Override
protected TileModel getDoorType(MapTheme theme, Random rand)
{
switch (rand.nextInt(5)) {
case 0:
case 1:
return theme.passage();
case 2:
return theme.secretDoor();
default:
return theme.door();
}
}
@Override
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max)
{
final Coord c = Coord.make((max.x + min.x) / 2, (max.y + min.y) / 2);
map.set(c, theme.entrance());
map.protect(c, c, TileProtectLevel.STRONG);
map.setEntrance(c.add(1, 0));
}
@Override
protected int getDoorCount(Random rand)
{
return 1 + rand.nextInt(4);
}
}

@ -0,0 +1,52 @@
package mightypork.rogue.world.gen.rooms;
import java.util.Random;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.gen.MapTheme;
import mightypork.rogue.world.gen.ScratchMap;
import mightypork.rogue.world.gen.TileProtectLevel;
import mightypork.rogue.world.tile.TileModel;
public class ExitRoom extends AbstractRectRoom {
@Override
protected Coord getInnerSize(Random rand)
{
return Coord.make(3, 3);
}
@Override
protected TileProtectLevel getWallProtectionLevel()
{
return TileProtectLevel.NONE;
}
@Override
protected TileModel getDoorType(MapTheme theme, Random rand)
{
return null;
}
@Override
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max)
{
final Coord c = Coord.make((max.x + min.x) / 2, (max.y + min.y) / 2);
map.set(c, theme.exit());
map.protect(c, c, TileProtectLevel.STRONG);
map.setExit(c.add(-1, 0));
}
@Override
protected int getDoorCount(Random rand)
{
return 0;
}
}

@ -9,4 +9,6 @@ public class Rooms {
public static final RoomBuilder BASIC = new BasicRoom();
public static final RoomBuilder SECRET = new SecretRoom();
public static final RoomBuilder DEAD_END = new DeadEndRoom();
public static final RoomBuilder ENTRANCE = new EntranceRoom();
public static final RoomBuilder EXIT = new ExitRoom();
}

@ -42,4 +42,18 @@ public class ThemeBrick implements MapTheme {
{
return Tiles.BRICK_HIDDEN_DOOR;
}
@Override
public TileModel entrance()
{
return Tiles.BRICK_ENTRANCE;
}
@Override
public TileModel exit()
{
return Tiles.BRICK_EXIT;
}
}

@ -13,14 +13,21 @@ import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.KeyListener;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseButtonListener;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.color.pal.RGB;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.math.timing.TimedTask;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.World;
import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.WorldRenderer;
import mightypork.rogue.world.events.WorldAscendRequestListener;
import mightypork.rogue.world.events.WorldDescendRequestListener;
import mightypork.rogue.world.gui.interaction.MapInteractionPlugin;
@ -29,7 +36,10 @@ import mightypork.rogue.world.gui.interaction.MapInteractionPlugin;
*
* @author MightyPork
*/
public class MapView extends InputComponent implements DelegatingClient, KeyListener, MouseButtonListener, Updateable {
public class MapView extends InputComponent implements DelegatingClient, KeyListener, MouseButtonListener, Updateable, WorldAscendRequestListener,
WorldDescendRequestListener {
private static final double transition_time = 0.8;
protected final WorldRenderer worldRenderer;
public final PlayerControl playerControl;
@ -38,6 +48,36 @@ public class MapView extends InputComponent implements DelegatingClient, KeyList
private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH);
private boolean zoom_in = true;
private NumAnimated descFadeAnim = new NumAnimated(0);
private Color blackColor = RGB.BLACK.withAlpha(descFadeAnim);
private int descDir = 0;
private TimedTask timerDesc1 = new TimedTask() {
@Override
public void run()
{
descFadeAnim.fadeOut(transition_time);
timerDesc2.start(transition_time);
if (descDir == 1) {
WorldProvider.get().getWorld().descend();
} else {
WorldProvider.get().getWorld().ascend();
}
}
};
private TimedTask timerDesc2 = new TimedTask() {
@Override
public void run()
{
WorldProvider.get().getWorld().resume();
}
};
private final Num tileSize;
@ -70,6 +110,8 @@ public class MapView extends InputComponent implements DelegatingClient, KeyList
protected void renderComponent()
{
worldRenderer.render();
Render.quadColor(this, blackColor);
}
@ -114,10 +156,6 @@ public class MapView extends InputComponent implements DelegatingClient, KeyList
@Override
public void receive(KeyEvent event)
{
for (final MapInteractionPlugin p : plugins) {
if (p.onKey(event.getKey(), event.isDown())) break;
}
if (event.getKey() == Keys.Z && event.isDown()) {
if (zoom_in) {
zoom.fadeIn();
@ -147,5 +185,47 @@ public class MapView extends InputComponent implements DelegatingClient, KeyList
public void update(double delta)
{
zoom.update(delta);
descFadeAnim.update(delta);
timerDesc1.update(delta);
timerDesc2.update(delta);
}
@Override
public void onAscendRequest()
{
if(descFadeAnim.isInProgress()) return;
World w = WorldProvider.get().getWorld();
if (w.canAscend()) {
descDir = -1;
startDescAnim();
}
}
private void startDescAnim()
{
WorldProvider.get().getWorld().pause();
timerDesc2.stop();
timerDesc1.start(transition_time);
descFadeAnim.setTo(0);
descFadeAnim.fadeIn(transition_time);
}
@Override
public void onDescendRequest()
{
if(descFadeAnim.isInProgress()) return;
World w = WorldProvider.get().getWorld();
if (w.canDescend()) {
descDir = 1;
startDescAnim();
}
}
}

@ -14,7 +14,7 @@ import mightypork.gamecore.util.math.constraints.rect.mutable.RectMutable;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.LevelReadAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile;
import org.lwjgl.opengl.GL11;
@ -33,7 +33,7 @@ public class Minimap extends InputComponent implements MouseButtonListener {
{
Color.pushAlpha(translucency);
final LevelReadAccess lvl = WorldProvider.get().getCurrentLevel();
final Level lvl = WorldProvider.get().getCurrentLevel();
unit = (int) Math.min(Math.max(2, Math.ceil((height().value() / 2) / (lvl.getHeight() + 2))), 10);
final Entity e = WorldProvider.get().getPlayerEntity();
@ -89,7 +89,7 @@ public class Minimap extends InputComponent implements MouseButtonListener {
@Override
public void receive(MouseButtonEvent event)
{
if (event.isOver(bounds) && event.getButton() == 0) {
if (event.isOver(bounds) && event.getButton() == 1) {
if (event.isUp()) {
final Vect relative = event.getPos().sub(bounds.origin());
final Coord actual = Coord.make(relative.xi() / unit, relative.yi() / unit);

@ -1,16 +1,20 @@
package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.KeyListener;
import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.entity.entities.PlayerEntity;
import mightypork.rogue.world.events.PlayerStepEndListener;
import mightypork.rogue.world.gui.MapView;
public class MIPKeyboard extends MapInteractionPlugin {
public class MIPKeyboard extends MapInteractionPlugin implements PlayerStepEndListener, KeyListener, Updateable {
private static final int[] keys = { Keys.LEFT, Keys.RIGHT, Keys.UP, Keys.DOWN };
private static final Step[] sides = { Sides.W, Sides.E, Sides.N, Sides.S };
@ -37,23 +41,21 @@ public class MIPKeyboard extends MapInteractionPlugin {
@Override
public boolean onKey(int key, boolean down)
public void receive(KeyEvent evt)
{
if (down) return false; // not interested
if (evt.isDown() || mapView.playerControl.getPlayerEntity().pos.isMoving()) return; // not interested
for (int i = 0; i < 4; i++) {
if (key == keys[i]) {
return mapView.playerControl.clickTile(sides[i]);
if (evt.getKey() == keys[i]) {
mapView.playerControl.clickTile(sides[i]);
}
}
return false;
}
private boolean walkByKey()
{
if (mapView.playerControl.getPlayerEntity().pos.isMoving()) return false;
if (mapView.playerControl.getPlayerEntity().pos.getProgress()<0.8) return false;
for (int i = 0; i < 4; i++) {
if (InputSystem.isKeyDown(keys[i])) {

@ -1,19 +1,20 @@
package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.util.math.Calc.Deg;
import mightypork.gamecore.util.math.Polar;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.entity.entities.PlayerEntity;
import mightypork.rogue.world.events.PlayerStepEndListener;
import mightypork.rogue.world.gui.MapView;
import mightypork.rogue.world.tile.Tile;
public class MIPMouse extends MapInteractionPlugin {
public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListener, Updateable {
private static final int BTN = 0; // left
@ -27,13 +28,12 @@ public class MIPMouse extends MapInteractionPlugin {
@Override
public void update(double delta)
{
if (!InputSystem.isKeyDown(Keys.L_SHIFT)) return;
final Vect pos = InputSystem.getMousePos();
if (!pos.isInside(mapView)) return;
if (InputSystem.isMouseButtonDown(BTN)) {
if (mouseWalk(pos)) return;
if (troToNav(pos)) return;
if (mapView.playerControl.getPlayerEntity().pos.isMoving() && troToNav(pos)) return;
}
}
@ -41,13 +41,14 @@ public class MIPMouse extends MapInteractionPlugin {
@Override
public boolean onClick(Vect mouse, int button, boolean down)
{
if (button != BTN) return false;
final Coord pos = mapView.toWorldPos(mouse);
final Tile t = mapView.playerControl.getLevel().getTile(pos);
if (t.onClick()) return true;
if (button == BTN && !down && t.onClick()) {
return true;
}
if (!down && t.isWalkable()) {
if (button == 1 && !down && t.isWalkable()) {
if (troToNav(mouse)) return true;
return mouseWalk(mouse);
}
@ -97,24 +98,15 @@ public class MIPMouse extends MapInteractionPlugin {
return false;
}
@Override
public boolean onKey(int key, boolean down)
{
return false;
}
@Override
public void onStepFinished(PlayerEntity player)
{
if (!InputSystem.isKeyDown(Keys.L_SHIFT)) return;
final Vect pos = InputSystem.getMousePos();
if (!pos.isInside(mapView)) return;
if (InputSystem.isMouseButtonDown(BTN)) {
if (mouseWalk(pos)) return;
if (troToNav(pos)) return;
if (mapView.playerControl.getPlayerEntity().pos.isMoving() && troToNav(pos)) return;
}
}

@ -2,12 +2,14 @@ package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.KeyListener;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.events.PlayerStepEndListener;
import mightypork.rogue.world.gui.MapView;
public abstract class MapInteractionPlugin implements Updateable, PlayerStepEndListener {
public abstract class MapInteractionPlugin {
protected final MapView mapView;
@ -20,12 +22,4 @@ public abstract class MapInteractionPlugin implements Updateable, PlayerStepEndL
public abstract boolean onClick(Vect mouse, int button, boolean down);
public abstract boolean onKey(int key, boolean down);
@Override
public abstract void update(double delta);
}

@ -19,7 +19,7 @@ public class ItemMeat extends Item {
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(Res.getTxQuad("item.meat"));
return new QuadItemRenderer(Res.txq("item.meat"));
}
}

@ -8,6 +8,7 @@ import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.eventbus.clients.DelegatingClient;
import mightypork.gamecore.eventbus.clients.ToggleableClient;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonInput;
@ -34,7 +35,7 @@ import mightypork.rogue.world.tile.Tiles;
*
* @author MightyPork
*/
public class Level implements BusAccess, DelegatingClient, ToggleableClient, LevelAccess, IonObjBinary {
public class Level implements BusAccess, Updateable, DelegatingClient, ToggleableClient, IonObjBinary {
public static final int ION_MARK = 53;
@ -42,6 +43,7 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
private World world;
private final Coord enterPoint = Coord.zero();
private final Coord exitPoint = Coord.zero();
/** Array of tiles [y][x] */
private Tile[][] tiles;
@ -75,7 +77,11 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Fill whole map with tile type
*
* @param model tile model
*/
public void fill(TileModel model)
{
for (final Coord c = Coord.zero(); c.x < size.x; c.x++) {
@ -86,7 +92,12 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Ge tile at X,Y
*
* @param pos
* @return tile
*/
public final Tile getTile(Coord pos)
{
if (!pos.isInRange(0, 0, size.x - 1, size.y - 1)) return Tiles.NULL.createTile(); // out of range
@ -95,7 +106,12 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Set tile at pos
*
* @param pos tile pos
* @param tile the tile instance to set
*/
public final void setTile(Coord pos, Tile tile)
{
if (!pos.isInRange(0, 0, size.x - 1, size.y - 1)) {
@ -110,28 +126,38 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* @return map width in tiles
*/
public final int getWidth()
{
return size.x;
}
@Override
/**
* @return map height in tiles
*/
public final int getHeight()
{
return size.y;
}
@Override
/**
* Set level seed (used for visuals; the seed used for generation)
*
* @param seed seed
*/
public void setSeed(long seed)
{
this.seed = seed;
}
@Override
/**
* @return map seed
*/
public long getSeed()
{
return seed;
@ -146,6 +172,7 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
seed = ib.get("seed", 0L);
ib.loadBundled("size", size);
ib.loadBundled("enter_point", enterPoint);
ib.loadBundled("exit_point", exitPoint);
// -- binary data --
@ -178,6 +205,7 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
ib.put("seed", seed);
ib.putBundled("size", size);
ib.putBundled("enter_point", enterPoint);
ib.putBundled("exit_point", exitPoint);
out.writeBundle(ib);
// -- binary data --
@ -222,7 +250,9 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* @return level-specific noise generator
*/
public NoiseGen getNoiseGen()
{
if (noiseGen == null) {
@ -233,14 +263,25 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Get entity by ID
*
* @param eid entity ID
* @return the entity, or null
*/
public Entity getEntity(int eid)
{
return entityMap.get(eid);
}
@Override
/**
* Try to add entity at given pos
*
* @param entity the entity
* @param pos pos
* @return true if added (false if void, wall etc)
*/
public boolean addEntity(Entity entity, Coord pos)
{
final Tile t = getTile(pos);
@ -265,14 +306,22 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Remove an entity from the level, if present
*
* @param entity entity
*/
public void removeEntity(Entity entity)
{
removeEntity(entity.getEntityId());
}
@Override
/**
* Remove an entity from the level, if present
*
* @param eid entity id
*/
public void removeEntity(int eid)
{
final Entity removed = entityMap.remove(eid);
@ -283,7 +332,12 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Check tile walkability
*
* @param pos tile coord
* @return true if the tile is walkable by entity
*/
public boolean isWalkable(Coord pos)
{
final Tile t = getTile(pos);
@ -293,9 +347,10 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
/**
* Mark tile as occupied by an entity
* Mark tile as occupied (entity entered)
*
* @param pos tile pos
*/
@Override
public void occupyTile(Coord pos)
{
getTile(pos).setOccupied(true);
@ -303,58 +358,99 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
/**
* Mark tile as free (no longet occupied)
* Mark tile as free (entity left)
*
* @param pos tile pos
*/
@Override
public void freeTile(Coord pos)
{
getTile(pos).setOccupied(false);
}
@Override
/**
* Check entity on tile
*
* @param pos tile coord
* @return true if some entity is standing there
*/
public boolean isOccupied(Coord pos)
{
return getTile(pos).isOccupied();
}
@Override
public Collection<Entity> getEntities()
{
return entitySet;
}
@Override
/**
* Set level entry point
*
* @param pos pos where the player appears upon descending to this level
*/
public void setEnterPoint(Coord pos)
{
this.enterPoint.setTo(pos);
}
@Override
/**
* Get location where the player appears upon descending to this level
*
* @return pos
*/
public Coord getEnterPoint()
{
return enterPoint;
}
@Override
/**
* Set level exit point
*
* @param pos pos where the player appears upon ascending to this level
*/
public void setExitPoint(Coord pos)
{
this.exitPoint.setTo(pos);
}
/**
* Get location where the player appears upon ascending to this level
*
* @return pos
*/
public Coord getExitPoint()
{
return exitPoint;
}
/**
* Get the level's world
*
* @return world
*/
public World getWorld()
{
return world;
}
@Override
/**
* Assign a world
*
* @param world new world
*/
public void setWorld(World world)
{
this.world = world;
}
@Override
/**
* Mark tile and surrounding area as explored
*
* @param center center the explored tile
*/
public void explore(Coord center)
{
final Collection<Coord> filled = new HashSet<>();
@ -406,7 +502,15 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
};
@Override
/**
* Get entity of type closest to coord
*
* @param self the querying entity - to provide position, and to be excluded
* from the search.
* @param type wanted entity type
* @param radius search radius; -1 for unlimited.
* @return
*/
public Entity getClosestEntity(Entity self, EntityType type, double radius)
{
Entity closest = null;
@ -430,6 +534,11 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
/**
* Free a tile. If entity is present, remove it.
*
* @param pos the tile pos
*/
public void forceFreeTile(Coord pos)
{
if (getTile(pos).isOccupied()) {
@ -450,20 +559,41 @@ public class Level implements BusAccess, DelegatingClient, ToggleableClient, Lev
}
@Override
/**
* Check if entity is in the level
*
* @param entity entity
* @return is present
*/
public boolean isEntityPresent(Entity entity)
{
return entitySet.contains(entity);
}
@Override
/**
* Check if entity is in the level
*
* @param eid entity ID
* @return true if present
*/
public boolean isEntityPresent(int eid)
{
return entityMap.containsKey(eid);
}
/**
* Get entity collection (for rendering)
*
* @return entities
*/
public Collection<Entity> getEntities()
{
return entitySet;
}
@Override
public EventBus getEventBus()
{

@ -1,109 +0,0 @@
package mightypork.rogue.world.level;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
/**
* Level full access
*
* @author MightyPork
*/
public interface LevelAccess extends LevelReadAccess, Updateable {
/**
* Mark tile and surrounding area as explored
*
* @param center center the explored tile
*/
public abstract void explore(Coord center);
/**
* Assign a world
*
* @param world new world
*/
public abstract void setWorld(World world);
/**
* Set level entry point
*
* @param pos pos where the player enters
*/
public abstract void setEnterPoint(Coord pos);
/**
* Mark tile as free (entity left)
*
* @param pos tile pos
*/
public abstract void freeTile(Coord pos);
/**
* Mark tile as occupied (entity entered)
*
* @param pos tile pos
*/
public abstract void occupyTile(Coord pos);
/**
* Remove an entity from the level, if present
*
* @param eid entity id
*/
public abstract void removeEntity(int eid);
/**
* Remove an entity from the level, if present
*
* @param entity entity
*/
public abstract void removeEntity(Entity entity);
/**
* Set level seed (used for visuals; the seed used for generation)
*
* @param seed seed
*/
public abstract void setSeed(long seed);
/**
* Set tile at pos
*
* @param pos tile pos
* @param tile the tile instance to set
*/
public abstract void setTile(Coord pos, Tile tile);
/**
* Fill whole map with tile type
*
* @param model tile model
*/
public abstract void fill(TileModel model);
/**
* Try to add entity at given pos
*
* @param entity the entity
* @param pos pos
* @return true if added (false if void, wall etc)
*/
public abstract boolean addEntity(Entity entity, Coord pos);
}

@ -1,127 +0,0 @@
package mightypork.rogue.world.level;
import java.util.Collection;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.noise.NoiseGen;
import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityType;
import mightypork.rogue.world.tile.Tile;
public interface LevelReadAccess {
/**
* Ge tile at X,Y
*
* @param pos
* @return tile
*/
Tile getTile(Coord pos);
/**
* @return map width in tiles
*/
int getWidth();
/**
* @return map height in tiles
*/
int getHeight();
/**
* @return map seed
*/
long getSeed();
/**
* @return level-specific noise generator
*/
NoiseGen getNoiseGen();
/**
* Check if entity is in the level
*
* @param entity entity
* @return is present
*/
boolean isEntityPresent(Entity entity);
/**
* Check if entity is in the level
*
* @param eid entity ID
* @return true if present
*/
boolean isEntityPresent(int eid);
/**
* Get entity of type closest to coord
*
* @param self the querying entity - to provide position, and to be excluded
* from the search.
* @param type wanted entity type
* @param radius search radius; -1 for unlimited.
* @return
*/
Entity getClosestEntity(Entity self, EntityType type, double radius);
/**
* Get the level's world
*
* @return world
*/
World getWorld();
/**
* Get location where the player enters the level
*
* @return pos
*/
Coord getEnterPoint();
/**
* Check entity on tile
*
* @param pos tile coord
* @return true if some entity is standing there
*/
boolean isOccupied(Coord pos);
/**
* Check tile walkability
*
* @param pos tile coord
* @return true if the tile is walkable by entity
*/
boolean isWalkable(Coord pos);
/**
* Get entity by ID
*
* @param eid entity ID
* @return the entity, or null
*/
Entity getEntity(int eid);
/**
* @return all entities
*/
Collection<Entity> getEntities();
}

@ -2,12 +2,12 @@ package mightypork.rogue.world.level.render;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.world.level.LevelReadAccess;
import mightypork.rogue.world.level.Level;
public class EntityRenderContext extends MapRenderContext {
public EntityRenderContext(LevelReadAccess map, Rect drawArea)
public EntityRenderContext(Level map, Rect drawArea)
{
super(map, drawArea);
}

@ -4,18 +4,18 @@ package mightypork.rogue.world.level.render;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.builders.TiledRect;
import mightypork.rogue.world.level.LevelReadAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile;
public abstract class MapRenderContext {
protected final LevelReadAccess map;
protected final Level map;
protected final TiledRect tiler;
private final Rect mapRect;
public MapRenderContext(LevelReadAccess map, Rect drawArea)
public MapRenderContext(Level map, Rect drawArea)
{
this.map = map;

@ -6,7 +6,7 @@ import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
import mightypork.gamecore.util.math.noise.NoiseGen;
import mightypork.rogue.world.level.LevelReadAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile;
@ -21,7 +21,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
private final NoiseGen noise;
public TileRenderContext(LevelReadAccess map, Rect drawArea)
public TileRenderContext(Level map, Rect drawArea)
{
super(map, drawArea);

@ -4,6 +4,8 @@ package mightypork.rogue.world.tile;
import java.io.IOException;
import java.util.Random;
import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.ion.IonInput;
@ -12,7 +14,7 @@ import mightypork.gamecore.util.ion.IonOutput;
import mightypork.gamecore.util.math.color.Color;
import mightypork.rogue.world.World;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.LevelAccess;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
@ -21,7 +23,7 @@ import mightypork.rogue.world.level.render.TileRenderContext;
*
* @author MightyPork
*/
public abstract class Tile implements IonObjBlob {
public abstract class Tile implements BusAccess, IonObjBlob {
// tmp extras
public final TileGenData genData = new TileGenData();
@ -35,7 +37,7 @@ public abstract class Tile implements IonObjBlob {
protected boolean occupied;
protected boolean explored;
protected LevelAccess level;
protected Level level;
private TileRenderer renderer;
@ -157,6 +159,12 @@ public abstract class Tile implements IonObjBlob {
}
public final boolean isStairs()
{
return getType() == TileType.STAIRS;
}
@DefaultImpl
public void updateTile(double delta)
{
@ -244,13 +252,13 @@ public abstract class Tile implements IonObjBlob {
}
public void setLevel(LevelAccess level)
public void setLevel(Level level)
{
this.level = level;
}
public LevelAccess getLevel()
public Level getLevel()
{
return level;
}
@ -261,4 +269,11 @@ public abstract class Tile implements IonObjBlob {
return level.getWorld();
}
@Override
public EventBus getEventBus()
{
return level.getEventBus();
}
}

@ -44,23 +44,23 @@ public abstract class TileRenderer implements Updateable {
this.tile = tile;
if (!inited) {
SH_N = Res.getTxQuad("tile.shadow.n");
SH_S = Res.getTxQuad("tile.shadow.s");
SH_E = Res.getTxQuad("tile.shadow.e");
SH_W = Res.getTxQuad("tile.shadow.w");
SH_NW = Res.getTxQuad("tile.shadow.nw");
SH_NE = Res.getTxQuad("tile.shadow.ne");
SH_SW = Res.getTxQuad("tile.shadow.sw");
SH_SE = Res.getTxQuad("tile.shadow.se");
UFOG_N = Res.getTxQuad("tile.ufog.n");
UFOG_S = Res.getTxQuad("tile.ufog.s");
UFOG_E = Res.getTxQuad("tile.ufog.e");
UFOG_W = Res.getTxQuad("tile.ufog.w");
UFOG_NW = Res.getTxQuad("tile.ufog.nw");
UFOG_NE = Res.getTxQuad("tile.ufog.ne");
UFOG_SW = Res.getTxQuad("tile.ufog.sw");
UFOG_SE = Res.getTxQuad("tile.ufog.se");
SH_N = Res.txq("tile.shadow.n");
SH_S = Res.txq("tile.shadow.s");
SH_E = Res.txq("tile.shadow.e");
SH_W = Res.txq("tile.shadow.w");
SH_NW = Res.txq("tile.shadow.nw");
SH_NE = Res.txq("tile.shadow.ne");
SH_SW = Res.txq("tile.shadow.sw");
SH_SE = Res.txq("tile.shadow.se");
UFOG_N = Res.txq("tile.ufog.n");
UFOG_S = Res.txq("tile.ufog.s");
UFOG_E = Res.txq("tile.ufog.e");
UFOG_W = Res.txq("tile.ufog.w");
UFOG_NW = Res.txq("tile.ufog.nw");
UFOG_NE = Res.txq("tile.ufog.ne");
UFOG_SW = Res.txq("tile.ufog.sw");
UFOG_SE = Res.txq("tile.ufog.se");
}
}

@ -22,7 +22,9 @@ public enum TileType
/** Door/gate tile */
DOOR(PAL16.NEWPOOP, true),
/** Passage (ie secret door) */
PASSAGE(RGB.GRAY, true);
PASSAGE(RGB.GRAY, true),
/** Stairs */
STAIRS(RGB.CYAN, false);
private final Color mapColor;
private final boolean potentiallyWalkable;

@ -6,11 +6,7 @@ import java.io.IOException;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.world.tile.tiles.NullTile;
import mightypork.rogue.world.tile.tiles.brick.TileBrickDoor;
import mightypork.rogue.world.tile.tiles.brick.TileBrickFloor;
import mightypork.rogue.world.tile.tiles.brick.TileBrickPassage;
import mightypork.rogue.world.tile.tiles.brick.TileBrickSecretDoor;
import mightypork.rogue.world.tile.tiles.brick.TileBrickWall;
import mightypork.rogue.world.tile.tiles.brick.*;
/**
@ -29,6 +25,8 @@ public final class Tiles {
public static final TileModel BRICK_DOOR = new TileModel(12, TileBrickDoor.class);
public static final TileModel BRICK_PASSAGE = new TileModel(13, TileBrickPassage.class);
public static final TileModel BRICK_HIDDEN_DOOR = new TileModel(14, TileBrickSecretDoor.class);
public static final TileModel BRICK_ENTRANCE = new TileModel(15, TileBrickEntrance.class);
public static final TileModel BRICK_EXIT = new TileModel(16, TileBrickExit.class);
public static void register(int id, TileModel model)

@ -0,0 +1,33 @@
package mightypork.rogue.world.tile.render;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileRenderer;
/**
* Tile that spans across two tiles visually (two-high)
*
* @author MightyPork
*/
public class OneFrameTileRenderer extends TileRenderer {
private final TxQuad txq;
public OneFrameTileRenderer(Tile tile, TxQuad txq)
{
super(tile);
this.txq = txq;
}
@Override
public void renderTile(TileRenderContext context)
{
Render.quadTextured(context.getRect(), txq);
}
}

@ -0,0 +1,35 @@
package mightypork.rogue.world.tile.render;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileRenderer;
/**
* Tile that spans across two tiles visually (two-high)
*
* @author MightyPork
*/
public class TwoHighTileRenderer extends TileRenderer {
private final TxQuad txq;
public TwoHighTileRenderer(Tile tile, TxQuad txq)
{
super(tile);
this.txq = txq;
}
@Override
public void renderTile(TileRenderContext context)
{
final Rect rect = context.getRect();
Render.quadTextured(rect.growUp(rect.height()), txq);
}
}

@ -0,0 +1,34 @@
package mightypork.rogue.world.tile.tiles;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.events.WorldAscendRequest;
import mightypork.rogue.world.tile.TileModel;
public abstract class TileBaseEntrance extends TileBaseStairs {
public TileBaseEntrance(TileModel model)
{
super(model);
}
@Override
public boolean onClick()
{
Coord plpos = getWorld().getPlayerEntity().getCoord();
if(!plpos.equals(getLevel().getEnterPoint())) return false;
getEventBus().send(new WorldAscendRequest());
return true;
}
@Override
public boolean doesCastShadow()
{
return false;
}
}

@ -0,0 +1,34 @@
package mightypork.rogue.world.tile.tiles;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.events.WorldDescendRequest;
import mightypork.rogue.world.tile.TileModel;
public abstract class TileBaseExit extends TileBaseStairs {
public TileBaseExit(TileModel model)
{
super(model);
}
@Override
public boolean onClick()
{
Coord plpos = getWorld().getPlayerEntity().getCoord();
if(!plpos.equals(getLevel().getExitPoint())) return false;
getEventBus().send(new WorldDescendRequest());
return true;
}
@Override
public boolean doesCastShadow()
{
return false;
}
}

@ -0,0 +1,22 @@
package mightypork.rogue.world.tile.tiles;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.TileType;
public abstract class TileBaseStairs extends TileSolid {
public TileBaseStairs(TileModel model)
{
super(model);
}
@Override
public TileType getType()
{
return TileType.STAIRS;
}
}

@ -13,9 +13,9 @@ public class TileBrickDoor extends TileBaseDoor {
//@formatter:off
super(
model,
Res.sheet("tile.brick.door.locked"),
Res.sheet("tile.brick.door.closed"),
Res.sheet("tile.brick.door.open")
Res.txs("tile.brick.door.locked"),
Res.txs("tile.brick.door.closed"),
Res.txs("tile.brick.door.open")
);
//@formatter:on
}

@ -0,0 +1,25 @@
package mightypork.rogue.world.tile.tiles.brick;
import mightypork.rogue.Res;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.TileRenderer;
import mightypork.rogue.world.tile.render.OneFrameTileRenderer;
import mightypork.rogue.world.tile.tiles.TileBaseEntrance;
public class TileBrickEntrance extends TileBaseEntrance {
public TileBrickEntrance(TileModel model)
{
super(model);
}
@Override
protected TileRenderer makeRenderer()
{
return new OneFrameTileRenderer(this, Res.txq("tile.brick.stairs.up"));
}
}

@ -0,0 +1,25 @@
package mightypork.rogue.world.tile.tiles.brick;
import mightypork.rogue.Res;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.TileRenderer;
import mightypork.rogue.world.tile.render.OneFrameTileRenderer;
import mightypork.rogue.world.tile.tiles.TileBaseExit;
public class TileBrickExit extends TileBaseExit {
public TileBrickExit(TileModel model)
{
super(model);
}
@Override
protected TileRenderer makeRenderer()
{
return new OneFrameTileRenderer(this, Res.txq("tile.brick.stairs.down"));
}
}

@ -10,7 +10,7 @@ public class TileBrickFloor extends TileBaseFloor {
public TileBrickFloor(TileModel model)
{
super(model, Res.sheet("tile.brick.floor"));
super(model, Res.txs("tile.brick.floor"));
}
}

@ -10,7 +10,7 @@ public class TileBrickPassage extends TileBasePassage {
public TileBrickPassage(TileModel model)
{
super(model, Res.sheet("tile.brick.passage"));
super(model, Res.txs("tile.brick.passage"));
}
}

@ -13,9 +13,9 @@ public class TileBrickSecretDoor extends TileBaseSecretDoor {
//@formatter:off
super(
model,
Res.sheet("tile.brick.door.secret"),
Res.sheet("tile.brick.door.closed"),
Res.sheet("tile.brick.door.open")
Res.txs("tile.brick.door.secret"),
Res.txs("tile.brick.door.closed"),
Res.txs("tile.brick.door.open")
);
//@formatter:on

@ -10,7 +10,7 @@ public class TileBrickWall extends TileBaseWall {
public TileBrickWall(TileModel model)
{
super(model, Res.sheet("tile.brick.wall"));
super(model, Res.txs("tile.brick.wall"));
}
}

Loading…
Cancel
Save