diff --git a/src/mightypork/rogue/Const.java b/src/mightypork/rogue/Const.java index 260dd67..c5d61aa 100644 --- a/src/mightypork/rogue/Const.java +++ b/src/mightypork/rogue/Const.java @@ -3,24 +3,24 @@ package mightypork.rogue; /** * Application constants - * + * * @author Ondřej Hruška (MightyPork) */ public final class Const { - + // STRINGS public static final int VERSION = 6; - + public static final String APP_NAME = "Rogue: Savage Rats"; public static final String TITLEBAR = APP_NAME + ", v" + VERSION; - + // AUDIO public static final int FPS_RENDER = 120; // max - + // INITIAL WINDOW SIZE public static final int WINDOW_W = 640; public static final int WINDOW_H = 480; - + /** Render dark in unknown area & skip invisible stuff */ public static boolean RENDER_UFOG = true; } diff --git a/src/mightypork/rogue/Launcher.java b/src/mightypork/rogue/Launcher.java index 9655bd5..f86fc49 100644 --- a/src/mightypork/rogue/Launcher.java +++ b/src/mightypork/rogue/Launcher.java @@ -4,101 +4,100 @@ package mightypork.rogue; import java.io.File; import java.util.logging.Level; -import junk.BaseApp; import mightypork.gamecore.core.App; import mightypork.utils.files.OsUtils; public class Launcher { - + /** * Launcher - * + * * @param args */ public static void main(String[] args) { // System.out.println("argv = " + Arrays.toString(args)+"\n"); - + Level llSyso = Level.FINER; final Level llFile = Level.ALL; - + File workdir = null; boolean logBus = false; - + try { boolean localWorkdir = false; String lwdDir = null; - + for (int i = 0; i < args.length; i++) { final String arg = args[i]; - + if (arg.equals("--workdir") || arg.equals("-w")) { localWorkdir = true; lwdDir = args[i + 1]; i++; continue; - + } else if (arg.equals("--silent") || arg.equals("-s")) { llSyso = Level.OFF; continue; - + } else if (arg.equals("--warn") || arg.equals("-e")) { llSyso = Level.WARNING; continue; - + } else if (arg.equals("--verbose") || arg.equals("-v")) { llSyso = Level.ALL; continue; - + } else if (arg.equals("--help") || arg.equals("-h")) { printHelp(); System.exit(0); - + } else if (arg.equals("--debug-bus")) { logBus = true; - + } else { System.err.println("Unknown argument: " + arg); printHelp(); System.exit(1); } } - + if (!localWorkdir) { workdir = OsUtils.getHomeWorkDir(".rogue"); } else { workdir = new File(lwdDir); } - + } catch (final Exception e) { System.out.println("Error parsing arguments:"); e.printStackTrace(); printHelp(); System.exit(1); } - + final App app = new RogueApp(); - + app.getInitOptions().setWorkdir(workdir); app.getInitOptions().setSigleInstance(true); - + app.getInitOptions().setLogLevel(llFile, llSyso); app.getInitOptions().setBusLogging(logBus); - + app.start(); } - - + + private static void printHelp() { //@formatter:off System.out.println( "Arguments:\n" + - "\t--workdir , -w .... specify working directory\n" + - "\t--verbose, --debug, -v ......... print all messages\n" + - "\t--silent, -s ................... print no messages\n" + - "\t--warnings, -e ................. print only warning and error messages\n" + + "\t--workdir , -w .... specify working directory\n" + + "\t--verbose, --debug, -v ......... print all messages\n" + + "\t--silent, -s ................... print no messages\n" + + "\t--warnings, -e ................. print only warning and error messages\n" + "\t--help, -h ..................... show this help\n"); //@formatter:on } diff --git a/src/mightypork/rogue/RogueApp.java b/src/mightypork/rogue/RogueApp.java index 89766a2..a31fee5 100644 --- a/src/mightypork/rogue/RogueApp.java +++ b/src/mightypork/rogue/RogueApp.java @@ -2,7 +2,6 @@ package mightypork.rogue; import junk.AppInitOptions; -import junk.BaseApp; import mightypork.gamecore.backends.lwjgl.LwjglBackend; import mightypork.gamecore.backends.lwjgl.LwjglInputModule; import mightypork.gamecore.core.App; @@ -35,37 +34,38 @@ import mightypork.utils.logging.Log; /** * Main class - * + * * @author Ondřej Hruška (MightyPork) */ public final class RogueApp extends App implements ViewportChangeListener { - - public RogueApp() { + + public RogueApp() + { super(new LwjglBackend()); - - AppInitOptions opt = getInitOptions(); - + + final AppInitOptions opt = getInitOptions(); + opt.addRoutes(new RogueRoutes()); opt.addResources(new RogueResources()); opt.addKeys(new RogueKeys()); opt.addConfig(new RogueConfig()); opt.setBusLogging(true); - + opt.setConfigFile("config.ini", "Rogue config file"); opt.setLogOptions("logs", "runtime", 5, java.util.logging.Level.ALL); } - - + + @Override protected void registerIonizables() { super.registerIonizables(); - + Ion.register(Level.class); Ion.register(Inventory.class); } - - + + @Override protected void initDisplay(GraphicsModule gfx) { @@ -73,52 +73,52 @@ public final class RogueApp extends App implements ViewportChangeListener { final int w = Config.getValue("display.width"); final int h = Config.getValue("display.height"); final boolean fs = Config.getValue("display.fullscreen"); - + gfx.setSize(w, h); gfx.setResizable(true); gfx.setFullscreen(fs); gfx.setTitle(Const.TITLEBAR); gfx.setTargetFps(Const.FPS_RENDER); - + gfx.createDisplay(); } - - + + @Override protected void initScreens(ScreenRegistry screens) { super.initScreens(screens); - + /* game screen references world provider instance */ - WorldProvider.init(this); + WorldProvider.setBaseDir(this); getEventBus().subscribe(new RogueStateManager(this)); - + screens.addScreen("main_menu", new ScreenMainMenu(this)); screens.addScreen("select_world", new ScreenSelectWorld(this)); screens.addScreen("game", new ScreenGame(this)); screens.addScreen("story", new ScreenStory(this)); - + screens.addOverlay(new FpsOverlay(this)); screens.addOverlay(new LoadingOverlay(this)); } - - + + @Override protected void initInputSystem(LwjglInputModule input) { // this will work only with reusable events (such as requests) bindEventToKey(new FullscreenToggleRequest(), "global.fullscreen"); bindEventToKey(new ScreenshotRequest(), "global.screenshot"); - + bindEventToKey(new ShutdownEvent(), "global.quit"); bindEventToKey(new ShutdownEvent(), "global.quit_force"); } - - + + private void bindEventToKey(final BusEvent event, String strokeName) { getInput().bindKey(Config.getKeyStroke(strokeName), Trigger.RISING, new Runnable() { - + @Override public void run() { @@ -126,14 +126,14 @@ public final class RogueApp extends App implements ViewportChangeListener { } }); } - - + + @Override protected void postInit() { - + getEventBus().send(new MainLoopRequest(new Runnable() { - + @Override public void run() { @@ -146,31 +146,31 @@ public final class RogueApp extends App implements ViewportChangeListener { } }, false)); } - - + + @Override public void onViewportChanged(ViewportChangeEvent event) { // save viewport size to config file final boolean fs = gfx().isFullscreen(); - + Config.setValue("display.fullscreen", fs); - + if (!fs) { Config.setValue("display.width", gfx().getWidth()); Config.setValue("display.height", gfx().getHeight()); } } - - + + @Override public void onScreenshotRequest() { // screenshot sound Res.getSoundEffect("gui.shutter").play(0.8); } - - + + @Override protected void writeLogHeader() { diff --git a/src/mightypork/rogue/RogueConfig.java b/src/mightypork/rogue/RogueConfig.java index 805f5b0..6760abc 100644 --- a/src/mightypork/rogue/RogueConfig.java +++ b/src/mightypork/rogue/RogueConfig.java @@ -5,15 +5,15 @@ import mightypork.utils.config.propmgr.PropertyManager; public class RogueConfig implements ConfigSetup { - + @Override public void addOptions(PropertyManager prop) { prop.addBoolean("display.fullscreen", false, "Start in fullscreen (remembers state at exit)"); prop.addInteger("display.width", 1024, "Initial width (remembers from last time)"); prop.addInteger("display.height", 768, "Initial height (remembers from last time)"); - + prop.addBoolean("opt.show_story", true, "Show story on start-up."); } - + } diff --git a/src/mightypork/rogue/RogueKeys.java b/src/mightypork/rogue/RogueKeys.java index bb895fe..f483724 100644 --- a/src/mightypork/rogue/RogueKeys.java +++ b/src/mightypork/rogue/RogueKeys.java @@ -2,23 +2,23 @@ package mightypork.rogue; public class RogueKeys implements KeySetup { - + @Override public void addKeys(KeyOpts keys) { keys.addKey("global.quit", "CTRL+Q", "Quit the game"); keys.addKey("global.quit_force", "CTRL+SHIFT+Q", "Quit the game without asking, low-level"); - + keys.addKey("global.screenshot", "F2", "Take screenshot (save into working directory)"); keys.addKey("global.fullscreen", "F11", "Toggle fullscreen"); keys.addKey("global.fps_meter", "F3", "Toggle FPS meter overlay"); - + keys.addKey("general.close", "ESC", "Leave a dialog or screen"); keys.addKey("general.cancel", "ESC", "\"Cancel\" option in dialogs"); keys.addKey("general.confirm", "ENTER", "\"Confirm\" option in dialogs"); keys.addKey("general.yes", "Y", "\"Yes\" option in dialogs"); keys.addKey("general.no", "N", "\"No\" option in dialogs"); - + keys.addKey("game.quit", "ESC", "Quit to menu"); keys.addKey("game.save", "CTRL+S", "Save to file"); keys.addKey("game.load", "CTRL+L", "Load from file"); @@ -28,14 +28,14 @@ public class RogueKeys implements KeySetup { keys.addKey("game.drop", "D", "Drop last picked item"); keys.addKey("game.inventory", "I", "Toggle inventory view"); keys.addKey("game.pause", "P", "Pause the game"); - + keys.addKey("game.walk.up", "UP", "Walk north"); keys.addKey("game.walk.down", "DOWN", "Walk south"); keys.addKey("game.walk.left", "LEFT", "Walk west"); keys.addKey("game.walk.right", "RIGHT", "Walk east"); - + keys.addKey("game.cheat.xray", "CTRL+SHIFT+X", "Cheat to see unexplored tiles"); - + keys.addKey("game.inv.use", "E", "Use (eat or equip) the selected item"); keys.addKey("game.inv.drop", "D", "Drop the selected item"); keys.addKey("game.inv.move.left", "LEFT", "Move inventory cursor left"); diff --git a/src/mightypork/rogue/RogueResources.java b/src/mightypork/rogue/RogueResources.java index 2c78b3d..ee0c73e 100644 --- a/src/mightypork/rogue/RogueResources.java +++ b/src/mightypork/rogue/RogueResources.java @@ -2,7 +2,7 @@ package mightypork.rogue; import mightypork.gamecore.audio.SoundRegistry; -import mightypork.gamecore.backends.lwjgl.graphics.font.DeferredLwjglFont; +import mightypork.gamecore.backends.lwjgl.graphics.font.LwjglFont; import mightypork.gamecore.graphics.fonts.DeferredFont; import mightypork.gamecore.graphics.fonts.FontRegistry; import mightypork.gamecore.graphics.fonts.Glyphs; @@ -16,72 +16,72 @@ import mightypork.utils.math.constraints.rect.Rect; public class RogueResources implements ResourceSetup { - + @Override public void addFonts(FontRegistry fonts) { DeferredFont font; - + //fonts.loadFont("polygon_pixel", new DeferredFont("/res/font/PolygonPixel5x7Standard.ttf", Glyphs.basic, 16)); - fonts.addFont("press_start", font = new DeferredLwjglFont("/res/font/PressStart2P.ttf", Glyphs.basic, 16)); - - fonts.addFont("battlenet", font = new DeferredLwjglFont("/res/font/battlenet.ttf", Glyphs.basic, 16)); + fonts.addFont("press_start", font = new LwjglFont("/res/font/PressStart2P.ttf", Glyphs.basic, 16)); + + fonts.addFont("battlenet", font = new LwjglFont("/res/font/battlenet.ttf", Glyphs.basic, 16)); font.setDiscardRatio(3 / 16D, 2 / 16D); - - fonts.addFont("tinyutf", font = new DeferredLwjglFont("/res/font/TinyUnicode2.ttf", Glyphs.basic, 16)); + + fonts.addFont("tinyutf", font = new LwjglFont("/res/font/TinyUnicode2.ttf", Glyphs.basic, 16)); font.setDiscardRatio(5 / 16D, 3 / 16D); - + // aliases fonts.addAlias("thick", "press_start"); fonts.addAlias("thin", "battlenet"); fonts.addAlias("tiny", "tinyutf"); } - - + + @Override public void addSounds(SoundRegistry sounds) { - + //sounds.addLoop("music.dungeon", "/res/audio/music/Lightless_Dawn.ogg", 1, 1, 3, 1.5); sounds.addLoop("music.menu", "/res/audio/music/Home_Base_Groove.ogg", 1, 0.7, 3, 1.5); sounds.addLoop("music.dungeon", "/res/audio/music/8bit_Dungeon_Level.ogg", 1, 0.6, 3, 1.5); //sounds.addLoop("music.dungeon2.boss", "/res/audio/music/8bit_Dungeon_Boss.ogg", 1, 0.6, 3, 1.5); - + sounds.addEffect("gui.shutter", "/res/audio/effects/shutter.ogg", 1, 1); sounds.addEffect("gui.click", "/res/audio/effects/click.ogg", 1, 1); - + sounds.addEffect("game.win", "/res/audio/effects/win.ogg", 1, 0.7); sounds.addEffect("game.lose", "/res/audio/effects/lose.ogg", 1, 1); - + sounds.addEffect("item.drop", "/res/audio/effects/drop.ogg", 1, 1); sounds.addEffect("item.pickup", "/res/audio/effects/pickup.ogg", 1, 1); sounds.addEffect("item.break", "/res/audio/effects/break.ogg", 1, 1); - + sounds.addEffect("player.eat", "/res/audio/effects/eat.ogg", 1, 1); sounds.addEffect("player.hurt", "/res/audio/effects/hurt.ogg", 1, 1); - + sounds.addEffect("crate.open", "/res/audio/effects/crate.ogg", 1, 1); - + sounds.addEffect("door.open", "/res/audio/effects/door.ogg", 1, 1); sounds.addEffect("door.close", "/res/audio/effects/door.ogg", 0.8, 1); - + sounds.addEffect("rat.sqeak1", "/res/audio/effects/mouse1.ogg", 1, 1); sounds.addEffect("rat.sqeak2", "/res/audio/effects/mouse2.ogg", 1, 1); sounds.addEffect("rat.sqeak3", "/res/audio/effects/mouse3.ogg", 1, 1); sounds.addEffect("rat.sqeak4", "/res/audio/effects/mouse4.ogg", 1, 1); sounds.addEffect("rat.sqeak5", "/res/audio/effects/mouse5.ogg", 1, 1); } - - + + @Override public void addTextures(TextureRegistry textures) { ITexture texture; QuadGrid grid; - + // gui texture = textures.addTexture("/res/img/gui.png", FilterMode.NEAREST, WrapMode.CLAMP); - + // small gui elements grid = texture.grid(32, 32); textures.add("hud.heart.on", grid.makeQuad(0, 0)); @@ -89,14 +89,14 @@ public class RogueResources implements ResourceSetup { textures.add("hud.heart.half", grid.makeQuad(2, 0)); textures.add("hud.xp.on", grid.makeQuad(0, 1)); textures.add("hud.xp.off", grid.makeQuad(1, 1)); - + // nav grid = texture.grid(8, 8); textures.add("nav.bg", grid.makeQuad(0, 7, 4, 1)); textures.add("nav.button.bg.base", grid.makeQuad(4, 7)); textures.add("nav.button.bg.hover", grid.makeQuad(5, 7)); textures.add("nav.button.bg.down", grid.makeQuad(6, 7)); - + textures.add("nav.button.fg.eat", grid.makeQuad(0, 6)); textures.add("nav.button.fg.inventory", grid.makeQuad(1, 6)); textures.add("nav.button.fg.attack", grid.makeQuad(2, 6)); @@ -107,10 +107,10 @@ public class RogueResources implements ResourceSetup { textures.add("nav.button.fg.magnify", grid.makeQuad(7, 6)); textures.add("nav.button.fg.save", grid.makeQuad(7, 5)); textures.add("nav.button.fg.load", grid.makeQuad(6, 5)); - + textures.add("inv.slot.base", grid.makeQuad(0, 5)); textures.add("inv.slot.selected", grid.makeQuad(1, 5)); - + // sprites texture = textures.addTexture("/res/img/sprites.png", FilterMode.NEAREST, WrapMode.CLAMP); grid = texture.grid(8, 8); @@ -119,7 +119,7 @@ public class RogueResources implements ResourceSetup { textures.add("sprite.rat.brown", grid.makeSheet(0, 2, 4, 1)); textures.add("sprite.rat.boss", grid.makeSheet(0, 3, 4, 1)); textures.add("sprite.zzz", grid.makeQuad(0, 7)); // sleep thingy - + // logo texture = textures.addTexture("/res/img/logo.png", FilterMode.NEAREST, WrapMode.CLAMP); textures.add("logo", texture.makeQuad(Rect.make(0, 0, 0.543, 0.203))); @@ -127,52 +127,52 @@ public class RogueResources implements ResourceSetup { textures.add("death", grid.makeQuad(0, 2)); textures.add("death2", grid.makeQuad(1, 2, 1.5, 1)); textures.add("win", grid.makeQuad(2.5, 2, 1.5, 1)); - + grid = texture.grid(8, 4); textures.add("story_1", grid.makeQuad(0, 2, 3, 1)); textures.add("story_2", grid.makeQuad(3, 2, 3, 1)); textures.add("story_3", grid.makeQuad(0, 3, 3, 1)); - + // tiles texture = textures.addTexture("tiles", "/res/img/tiles.png", FilterMode.NEAREST, WrapMode.CLAMP); grid = texture.grid(8, 8); - + textures.add("tile.brick.floor", grid.makeSheet(0, 1, 5, 1)); textures.add("tile.brick.wall", grid.makeSheet(0, 0, 8, 1)); - + textures.add("tile.brick.door.closed", grid.makeQuad(1, 2)); textures.add("tile.brick.door.open", grid.makeQuad(2, 2)); textures.add("tile.brick.door.secret", grid.makeSheet(0, 3, 2, 1)); - + textures.add("tile.brick.passage", grid.makeSheet(3, 2, 4, 1)); textures.add("tile.brick.stairs.up", grid.makeQuad(0, 6)); textures.add("tile.brick.stairs.down", grid.makeQuad(1, 6)); textures.add("tile.extra.chest.closed", grid.makeQuad(0, 4)); textures.add("tile.extra.chest.open", grid.makeQuad(1, 4)); - + // shadows textures.add("tile.shadow.n", grid.makeQuad(0, 7)); textures.add("tile.shadow.s", grid.makeQuad(0, 7).flipY()); textures.add("tile.shadow.w", grid.makeQuad(1, 7)); textures.add("tile.shadow.e", grid.makeQuad(1, 7).flipX()); - + textures.add("tile.shadow.nw", grid.makeQuad(2, 7)); textures.add("tile.shadow.ne", grid.makeQuad(2, 7).flipX()); textures.add("tile.shadow.sw", grid.makeQuad(2, 7).flipY()); textures.add("tile.shadow.se", grid.makeQuad(2, 7).flipY().flipX()); - + // unexplored fog textures.add("tile.ufog.n", grid.makeQuad(3, 7)); textures.add("tile.ufog.s", grid.makeQuad(3, 7).flipY()); textures.add("tile.ufog.w", grid.makeQuad(4, 7)); textures.add("tile.ufog.e", grid.makeQuad(4, 7).flipX()); - + textures.add("tile.ufog.nw", grid.makeQuad(5, 7)); textures.add("tile.ufog.ne", grid.makeQuad(5, 7).flipX()); textures.add("tile.ufog.sw", grid.makeQuad(5, 7).flipY()); textures.add("tile.ufog.se", grid.makeQuad(5, 7).flipY().flipX()); textures.add("tile.ufog.full", grid.makeQuad(6, 7)); - + texture = textures.addTexture("items", "/res/img/items.png", FilterMode.NEAREST, WrapMode.CLAMP); grid = texture.grid(8, 8); textures.add("item.meat", grid.makeQuad(0, 0)); @@ -187,5 +187,5 @@ public class RogueResources implements ResourceSetup { textures.add("item.knife", grid.makeQuad(1, 1)); textures.add("item.twig", grid.makeQuad(2, 1)); } - + } diff --git a/src/mightypork/rogue/RogueRoutes.java b/src/mightypork/rogue/RogueRoutes.java index 5c62a05..03ca5a1 100644 --- a/src/mightypork/rogue/RogueRoutes.java +++ b/src/mightypork/rogue/RogueRoutes.java @@ -2,7 +2,7 @@ package mightypork.rogue; public class RogueRoutes implements RouteSetup { - + @Override public void addRoutes(RouteOpts routeOpts) { @@ -10,5 +10,5 @@ public class RogueRoutes implements RouteSetup { routeOpts.addPath("slot2", "saves/slot_2.ion"); routeOpts.addPath("slot3", "saves/slot_3.ion"); } - + } diff --git a/src/mightypork/rogue/RogueStateManager.java b/src/mightypork/rogue/RogueStateManager.java index 586fef0..cd063e2 100644 --- a/src/mightypork/rogue/RogueStateManager.java +++ b/src/mightypork/rogue/RogueStateManager.java @@ -8,40 +8,40 @@ import mightypork.utils.logging.Log; public class RogueStateManager extends BusNode { - + public static enum RogueState { MAIN_MENU, SELECT_WORLD, PLAY_WORLD, EXIT, STORY } - - + + public void triggerAction(RogueState state, boolean fromDark) { switch (state) { case MAIN_MENU: App.bus().send(new CrossfadeRequest("main_menu", fromDark)); break; - + case SELECT_WORLD: App.bus().send(new CrossfadeRequest("select_world", fromDark)); break; - + case PLAY_WORLD: App.bus().send(new CrossfadeRequest("game", fromDark)); break; - + case STORY: App.bus().send(new CrossfadeRequest("story", fromDark)); break; - + case EXIT: App.bus().send(new CrossfadeRequest(null)); break; - + default: Log.w("Unknown action: " + state); break; } } - + } diff --git a/src/mightypork/rogue/events/LoadingOverlayRequest.java b/src/mightypork/rogue/events/LoadingOverlayRequest.java index 1b503fd..b56e9fb 100644 --- a/src/mightypork/rogue/events/LoadingOverlayRequest.java +++ b/src/mightypork/rogue/events/LoadingOverlayRequest.java @@ -8,30 +8,31 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; /** * Request to execute a given task in a loading overlay - * + * * @author Ondřej Hruška (MightyPork) */ @SingleReceiverEvent public class LoadingOverlayRequest extends BusEvent { - + private final String msg; private final Runnable task; - - + + /** * @param msg task description * @param task task runnable */ - public LoadingOverlayRequest(String msg, Runnable task) { + public LoadingOverlayRequest(String msg, Runnable task) + { this.task = task; this.msg = msg; } - - + + @Override protected void handleBy(LoadingOverlay handler) { handler.show(msg, task); } - + } diff --git a/src/mightypork/rogue/events/RogueStateRequest.java b/src/mightypork/rogue/events/RogueStateRequest.java index 611c41a..33867a3 100644 --- a/src/mightypork/rogue/events/RogueStateRequest.java +++ b/src/mightypork/rogue/events/RogueStateRequest.java @@ -8,27 +8,29 @@ import mightypork.utils.eventbus.BusEvent; /** * Request for a game state change - * + * * @author Ondřej Hruška (MightyPork) */ public class RogueStateRequest extends BusEvent { - + final private RogueState requested; private final boolean fromDark; - - - public RogueStateRequest(RogueState requested) { + + + public RogueStateRequest(RogueState requested) + { this.requested = requested; this.fromDark = false; } - - - public RogueStateRequest(RogueState requested, boolean fromDark) { + + + public RogueStateRequest(RogueState requested, boolean fromDark) + { this.requested = requested; this.fromDark = fromDark; } - - + + @Override protected void handleBy(RogueStateManager handler) { diff --git a/src/mightypork/rogue/screens/FpsOverlay.java b/src/mightypork/rogue/screens/FpsOverlay.java index c7182ae..12c147c 100644 --- a/src/mightypork/rogue/screens/FpsOverlay.java +++ b/src/mightypork/rogue/screens/FpsOverlay.java @@ -2,7 +2,6 @@ package mightypork.rogue.screens; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.config.Config; import mightypork.gamecore.graphics.fonts.IFont; import mightypork.gamecore.gui.Action; import mightypork.gamecore.gui.components.painters.TextPainter; @@ -19,51 +18,52 @@ import mightypork.utils.string.StringProvider; /** * FPS indicator overlay - * + * * @author Ondřej Hruška (MightyPork) */ public class FpsOverlay extends Overlay { - + TextPainter tp; - - - public FpsOverlay() { - + + + public FpsOverlay() + { + /* * Toggle key: F3 */ bindKey(App.cfg().getKeyStroke("global.fps_meter"), Trigger.RISING, new Action() { - + @Override public void execute() { setVisible(!isVisible()); } }); - + final IFont font = Res.getFont("thin"); - + final Num h = root.height(); final RectBound constraint = root.shrink(h.perc(3)).topRight().startRect().growDown(h.perc(5).max(16)); - + tp = new TextPainter(font, AlignX.RIGHT, RGB.YELLOW, new StringProvider() { - + @Override public String getString() { return App.gfx().getFps() + " fps"; } }); - + tp.setRect(constraint); tp.setShadow(RGB.BLACK_60, Vect.make(tp.height().div(8).round())); - + root.add(tp); - + setVisible(false); // initially hide. } - - + + @Override public int getZIndex() { diff --git a/src/mightypork/rogue/screens/LoadingOverlay.java b/src/mightypork/rogue/screens/LoadingOverlay.java index 68326de..9a524db 100644 --- a/src/mightypork/rogue/screens/LoadingOverlay.java +++ b/src/mightypork/rogue/screens/LoadingOverlay.java @@ -20,36 +20,36 @@ import mightypork.utils.string.StringProvider; /** * Overlay with blue background and loading-info text, that accompanies an async * task. - * + * * @author Ondřej Hruška (MightyPork) */ public class LoadingOverlay extends Overlay { - + private static final double T_IN = 0.5; private static final double T_OUT = 1; - + private final NumAnimated alpha = new NumAnimated(0); - + private final StringProvider msgStrProv = new StringProvider() { - + @Override public String getString() { return msg == null ? "" : msg; } }; - + private boolean busy; private String msg; private Runnable task; - + private final TimedTask tt = new TimedTask() { - + @Override public void run() { Support.runAsThread(new Runnable() { - + @Override public void run() { @@ -61,54 +61,55 @@ public class LoadingOverlay extends Overlay { }); } }; - - - public LoadingOverlay() { - + + + public LoadingOverlay() + { + final QuadPainter qp = new QuadPainter(PAL16.SEABLUE); qp.setRect(root); root.add(qp); - + updated.add(alpha); updated.add(tt); - + Rect textRect = root.shrink(Num.ZERO, root.height().perc(48)); textRect = textRect.moveY(root.height().perc(-10)); - + final TextPainter tp = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.WHITE, msgStrProv); - + tp.setRect(textRect); tp.setShadow(RGB.BLACK_60, tp.height().mul(1 / 8D).toVectXY()); root.add(tp); - + setAlpha(alpha); } - - + + @Override public int getZIndex() { return 10001; // not too high, so app can put something on top } - - + + /** * Show for a task - * + * * @param message task description * @param task task */ public void show(String message, Runnable task) { if (busy) throw new IllegalStateException("Loader is busy with another task."); - + this.msg = message; this.task = task; this.busy = true; - + alpha.setEasing(Easing.SINE_IN); alpha.fadeIn(T_IN); - + tt.start(T_IN); } } diff --git a/src/mightypork/rogue/screens/RogueScreen.java b/src/mightypork/rogue/screens/RogueScreen.java index 7053d89..c2d0601 100644 --- a/src/mightypork/rogue/screens/RogueScreen.java +++ b/src/mightypork/rogue/screens/RogueScreen.java @@ -11,8 +11,8 @@ import mightypork.utils.annotations.Stub; public class RogueScreen extends LayeredScreen implements ShutdownListener { - - + + @Override @Stub public void onShutdown(ShutdownEvent event) diff --git a/src/mightypork/rogue/screens/game/HeartBar.java b/src/mightypork/rogue/screens/game/HeartBar.java index acb6649..9af79a5 100644 --- a/src/mightypork/rogue/screens/game/HeartBar.java +++ b/src/mightypork/rogue/screens/game/HeartBar.java @@ -11,28 +11,29 @@ import mightypork.utils.math.constraints.rect.Rect; public class HeartBar extends BaseComponent { - + private final TxQuad img_on; private final TxQuad img_off; private final TxQuad img_half; private final Num total; private final Num active; - + private final NumVar index = new NumVar(0); private final Rect heart; - - - public HeartBar(Num total, Num active, TxQuad img_on, TxQuad img_half, TxQuad img_off, AlignX align) { + + + public HeartBar(Num total, Num active, TxQuad img_on, TxQuad img_half, TxQuad img_off, AlignX align) + { super(); this.total = total; this.active = active; this.img_on = img_on; this.img_off = img_off; this.img_half = img_half; - + final Num h = height(); final Num w = width(); - + switch (align) { case LEFT: heart = leftEdge().growRight(h).moveX(index.mul(h)); @@ -46,19 +47,19 @@ public class HeartBar extends BaseComponent { default: heart = null; // impossible } - + } - - + + @Override protected void renderComponent() { for (int i = 0; i < total.value(); i++) { index.setTo(i); - + final double rem = active.value() - i; App.gfx().quad(heart, (rem > 0.6 ? img_on : rem > 0.25 ? img_half : img_off)); } } - + } diff --git a/src/mightypork/rogue/screens/game/IngameNav.java b/src/mightypork/rogue/screens/game/IngameNav.java index 95a3e76..5199457 100644 --- a/src/mightypork/rogue/screens/game/IngameNav.java +++ b/src/mightypork/rogue/screens/game/IngameNav.java @@ -12,49 +12,51 @@ import mightypork.utils.math.constraints.rect.RectBound; public class IngameNav extends LayoutComponent { - + private final FlowColumnLayout leftFlow; private final FlowColumnLayout rightFlow; private final Rect paintHelper; - + private final TxQuad bg; - - - public IngameNav() { + + + public IngameNav() + { this(null); } - - - public IngameNav(RectBound context) { + + + public IngameNav(RectBound context) + { super(context); - + final Rect shr = this.shrink(height().perc(5)); leftFlow = new FlowColumnLayout(context, shr.height(), AlignX.LEFT); rightFlow = new FlowColumnLayout(context, shr.height(), AlignX.RIGHT); - + leftFlow.setRect(shr); rightFlow.setRect(shr); attach(leftFlow); attach(rightFlow); - + paintHelper = leftEdge().growRight(height().mul(4)); - + bg = Res.getTxQuad("nav.bg"); } - - + + public void addLeft(NavButton comp) { leftFlow.add(comp); } - - + + public void addRight(NavButton comp) { rightFlow.add(comp); } - - + + @Override public void renderComponent() { @@ -62,8 +64,8 @@ public class IngameNav extends LayoutComponent { for (int i = 0; i < Math.ceil(width().value() / paintHelper.width().value()); i++) { App.gfx().quad(paintHelper.moveX(paintHelper.width().value() * i), bg); } - + super.renderComponent(); } - + } diff --git a/src/mightypork/rogue/screens/game/InvSlot.java b/src/mightypork/rogue/screens/game/InvSlot.java index 71c83b9..d02307e 100644 --- a/src/mightypork/rogue/screens/game/InvSlot.java +++ b/src/mightypork/rogue/screens/game/InvSlot.java @@ -22,79 +22,80 @@ import mightypork.utils.math.constraints.rect.caching.RectCache; /** * Button in the ingame nav - * + * * @author Ondřej Hruška (MightyPork) */ public class InvSlot extends ClickableComponent { - + private final TxQuad txBase, txSelected; - + protected boolean selected = false; protected int index; - + private final RectCache itemRect; private final RectCache uiRect; - + private final InvSlot[] slots; - + private final TextPainter rbTxP; private final TextPainter rtTxP; - + private final RectCache rbTxRect; private final RectCache rtTxRect; - + private final Rect usesRect; private final Num hAlpha = Num.make(0.7); - - - public InvSlot(int index, InvSlot[] allSlots) { + + + public InvSlot(int index, InvSlot[] allSlots) + { super(); this.txBase = Res.getTxQuad("inv.slot.base"); this.txSelected = Res.getTxQuad("inv.slot.selected"); - + this.index = index; this.slots = allSlots; - + this.uiRect = getRect().shrink(height().perc(16)).cached(); this.itemRect = uiRect.shrink(Num.ZERO, height().perc(14), height().perc(14), Num.ZERO).cached(); - + this.usesRect = uiRect.topLeft().startRect().grow(Num.ZERO, uiRect.width().perc(40), Num.ZERO, uiRect.height().perc(8)); - + //@formatter:off this.rbTxRect = uiRect.bottomEdge() .moveY(uiRect.height().perc(1*(30/7D))) .growUp(uiRect.height().perc(30)).cached(); //@formatter:on - + rbTxP = new TextPainter(Res.getFont("tiny"), AlignX.RIGHT, RGB.WHITE); rbTxP.setRect(rbTxRect); rbTxP.setShadow(RGB.BLACK_70, rbTxP.getRect().height().div(7).toVectXY()); - + //@formatter:off this.rtTxRect = uiRect.topEdge() .growDown(uiRect.height().perc(30)).cached(); //@formatter:on - + rtTxP = new TextPainter(Res.getFont("tiny"), AlignX.RIGHT, RGB.GREEN); rtTxP.setRect(rtTxRect); rtTxP.setShadow(RGB.BLACK_70, rtTxP.getRect().height().div(7).toVectXY()); - + setAction(new Action() { - + @Override protected void execute() { for (final InvSlot sl : slots) { sl.selected = false; } - + selected = true; } - + }); } - - + + @Override public void updateLayout() { @@ -103,23 +104,23 @@ public class InvSlot extends ClickableComponent { rbTxRect.poll(); rtTxRect.poll(); } - - + + @Override protected void renderComponent() { TxQuad bg; - + if (selected) { bg = txSelected; } else { bg = txBase; } - + App.gfx().quad(this, bg); - + final PlayerFacade pl = WorldProvider.get().getPlayer(); - + final Item itm = pl.getInventory().getItem(index); if (itm != null && !itm.isEmpty()) { itm.render(itemRect); @@ -128,39 +129,39 @@ public class InvSlot extends ClickableComponent { rbTxP.setColor(RGB.WHITE); rbTxP.render(); } - + if (pl.getSelectedWeaponIndex() == index) { rbTxP.setText("*"); rbTxP.setColor(RGB.YELLOW); rbTxP.render(); } - + if (itm.getType() == ItemType.FOOD) { rtTxP.setText(Support.str(itm.getFoodPoints() / 2D)); rtTxP.setColor(RGB.GREEN); rtTxP.render(); } else if (itm.getType() == ItemType.WEAPON) { - + final int atk = itm.getAttackPoints(); rtTxP.setText((atk >= 0 ? "+" : "") + atk); rtTxP.setColor(RGB.CYAN); rtTxP.render(); } - + if (itm.isDamageable()) { Color.pushAlpha(hAlpha); - + App.gfx().quad(usesRect, RGB.BLACK); - + final double useRatio = (itm.getRemainingUses() / (double) itm.getMaxUses()); - + final Color barColor = (useRatio > 0.6 ? RGB.GREEN : useRatio > 0.2 ? RGB.ORANGE : RGB.RED); - + App.gfx().quad(usesRect.shrinkRight(usesRect.width().value() * (1 - useRatio)), barColor); - + Color.popAlpha(); } } } - + } diff --git a/src/mightypork/rogue/screens/game/LayerAskSave.java b/src/mightypork/rogue/screens/game/LayerAskSave.java index d6198bf..090caa5 100644 --- a/src/mightypork/rogue/screens/game/LayerAskSave.java +++ b/src/mightypork/rogue/screens/game/LayerAskSave.java @@ -24,18 +24,18 @@ import mightypork.utils.math.constraints.num.Num; public class LayerAskSave extends FadingLayer { - + public Runnable task; - + private final ScreenGame gscreen; - - + + public void setTask(Runnable task) { this.task = task; } - - + + @Override protected void onHideFinished() { @@ -43,61 +43,61 @@ public class LayerAskSave extends FadingLayer { gscreen.setState(GScrState.WORLD); // go back.. } } - - + + public LayerAskSave(final ScreenGame screen) { super(screen); this.gscreen = screen; - + // darker down to cover console. final QuadPainter qp = new QuadPainter(RGB.BLACK_80); qp.setRect(root); root.add(qp); - + final IFont thick_font = Res.getFont("thick"); - + final RowLayout rl = new RowLayout(root, 2); rl.setRect(root.shrink(Num.ZERO, root.height().perc(40)).moveY(root.height().perc(-10))); root.add(rl); - + final TextPainter txp = new TextPainter(thick_font, AlignX.CENTER, RGB.WHITE, "Save the game?"); rl.add(txp, 1); txp.setVPaddingPercent(25); - + final LinearLayout ll = new LinearLayout(root, AlignX.CENTER); rl.add(ll); - + final double vPadPerc = 20; - + final TextButton btn1 = new TextButton(thick_font, "Yes", ScreenGame.COLOR_BTN_GOOD); btn1.textPainter.setAlign(AlignX.RIGHT); btn1.textPainter.setVPaddingPercent(vPadPerc); ll.add(btn1); ll.gap(50); - + final TextButton btn2 = new TextButton(thick_font, "No", ScreenGame.COLOR_BTN_BAD); btn2.textPainter.setAlign(AlignX.CENTER); btn2.textPainter.setVPaddingPercent(vPadPerc); ll.add(btn2); ll.gap(50); - + final TextButton btn3 = new TextButton(thick_font, "Cancel", ScreenGame.COLOR_BTN_CANCEL); btn3.textPainter.setAlign(AlignX.LEFT); btn3.textPainter.setVPaddingPercent(vPadPerc); ll.add(btn3); - + final Action cancel = new Action() { - + @Override protected void execute() { hide(); } }; - + final Action save = new Action() { - + @Override protected void execute() { @@ -109,39 +109,39 @@ public class LayerAskSave extends FadingLayer { } } }; - + final Action discard = new Action() { - + @Override protected void execute() { if (task != null) task.run(); } }; - + btn1.setAction(save); btn2.setAction(discard); btn3.setAction(cancel); - - Config cfg = App.cfg(); - + + final Config cfg = App.cfg(); + bindKey(cfg.getKeyStroke("general.close"), Trigger.RISING, cancel); bindKey(cfg.getKeyStroke("general.cancel"), Trigger.RISING, cancel); - + bindKey(cfg.getKeyStroke("general.yes"), Trigger.RISING, save); bindKey(cfg.getKeyStroke("general.confirm"), Trigger.RISING, save); - + bindKey(cfg.getKeyStroke("general.no"), Trigger.RISING, discard); } - - + + @Override public int getZIndex() { return 300; } - - + + @Override public void update(double delta) { diff --git a/src/mightypork/rogue/screens/game/LayerDeath.java b/src/mightypork/rogue/screens/game/LayerDeath.java index db9a1f8..197c203 100644 --- a/src/mightypork/rogue/screens/game/LayerDeath.java +++ b/src/mightypork/rogue/screens/game/LayerDeath.java @@ -28,44 +28,45 @@ import mightypork.utils.math.constraints.num.Num; public class LayerDeath extends FadingLayer { - - public LayerDeath(final ScreenGame screen) { + + public LayerDeath(final ScreenGame screen) + { super(screen); - + // darker down to cover console. final QuadPainter qp = new QuadPainter(RGB.BLACK_80); qp.setRect(root); root.add(qp); - + final IFont thick_font = Res.getFont("thick"); - + final RowLayout rl = new RowLayout(root, 5); rl.setRect(root.shrink(Num.ZERO, root.height().perc(15))); root.add(rl); - + final TextPainter txp = new TextPainter(thick_font, AlignX.CENTER, RGB.YELLOW, "Rats won!"); rl.add(txp, 1); txp.setVPaddingPercent(13); - + LinearLayout linl = new LinearLayout(root, AlignX.CENTER); linl.add(new ImagePainter(Res.getTxQuad("death2"))); rl.add(linl, 3); - + linl = new LinearLayout(root, AlignX.CENTER); rl.add(linl); - + final TextButton btn1 = new TextButton(thick_font, "Retry", ScreenGame.COLOR_BTN_GOOD); btn1.textPainter.setVPaddingPercent(25); linl.add(btn1); - + linl.add(new LinearGap(50)); - + final TextButton btn2 = new TextButton(thick_font, "Leave", ScreenGame.COLOR_BTN_BAD); btn2.textPainter.setVPaddingPercent(25); linl.add(btn2); - + final Action load = new Action() { - + @Override protected void execute() { @@ -77,31 +78,31 @@ public class LayerDeath extends FadingLayer { } } }; - + final Action quit = new Action() { - + @Override protected void execute() { App.bus().send(new RogueStateRequest(RogueState.MAIN_MENU)); } }; - + btn1.setAction(load); btn2.setAction(quit); - - Config cfg = App.cfg(); - + + final Config cfg = App.cfg(); + bindKey(cfg.getKeyStroke("game.load"), Trigger.RISING, load); bindKey(cfg.getKeyStroke("general.confirm"), Trigger.RISING, load); bindKey(cfg.getKeyStroke("general.close"), Trigger.RISING, quit); } - - + + @Override public int getZIndex() { return 300; } - + } diff --git a/src/mightypork/rogue/screens/game/LayerGameUi.java b/src/mightypork/rogue/screens/game/LayerGameUi.java index 6f6dbaa..f066fec 100644 --- a/src/mightypork/rogue/screens/game/LayerGameUi.java +++ b/src/mightypork/rogue/screens/game/LayerGameUi.java @@ -16,70 +16,71 @@ import mightypork.utils.string.StringProvider; public class LayerGameUi extends ScreenLayer { - + private final Num playerHealthTotal = new Num() { - + @Override public double value() { return WorldProvider.get().getPlayer().getHealthMax() / 2D; } }; - + private final Num playerHealthActive = new Num() { - + @Override public double value() { return WorldProvider.get().getPlayer().getHealth() / 2D; } }; - + protected Minimap miniMap; - + private final ScreenGame gameScreen; - - - public LayerGameUi(ScreenGame screen) { + + + public LayerGameUi(ScreenGame screen) + { super(screen); this.gameScreen = screen; - + buildNav(); - + buildDisplays(); - + buildMinimap(); - + buildConsole(); } - - + + private void buildConsole() { final Num rh = root.height(); final Num rw = root.width(); final Rect consoleRect = root.shrink(rw.perc(2), Num.ZERO, rh.perc(6), rh.perc(16)); - + final Num perRow = consoleRect.height().div(20).max(12).min(32); - + final WorldConsoleRenderer wcr = new WorldConsoleRenderer(perRow); wcr.setRect(consoleRect); root.add(wcr); } - - + + private void buildMinimap() { miniMap = new Minimap(); miniMap.setRect(root.shrink(root.width().perc(5), root.height().perc(15))); root.add(miniMap); } - - + + private void buildDisplays() { final Num h = root.height(); - + //@formatter:off final HeartBar hearts = new HeartBar( playerHealthTotal, @@ -89,13 +90,13 @@ public class LayerGameUi extends ScreenLayer { Res.getTxQuad("hud.heart.off"), AlignX.LEFT); //@formatter:on - + final Rect hearts_box = root.shrink(h.perc(3)).topEdge().growDown(h.perc(6)); hearts.setRect(hearts_box); root.add(hearts); - + final TextPainter levelText = new TextPainter(Res.getFont("tiny"), AlignX.RIGHT, RGB.WHITE, new StringProvider() { - + @Override public String getString() { @@ -103,62 +104,62 @@ public class LayerGameUi extends ScreenLayer { return (w.isPaused() ? "[P] " : "") + "Floor " + (1 + w.getPlayer().getLevelNumber()); } }); - + levelText.setRect(hearts_box.moveY(hearts_box.height().mul(1 / 7D))); root.add(levelText); } - - + + private void buildNav() { final IngameNav nav = new IngameNav(); nav.setRect(root.bottomEdge().growUp(root.height().perc(12))); root.add(nav); - + NavButton btn; - + nav.addRight(btn = new NavButton(Res.getTxQuad("nav.button.fg.inventory"))); btn.setAction(gameScreen.actionToggleInv); - + nav.addRight(btn = new NavButton(Res.getTxQuad("nav.button.fg.eat"))); btn.setAction(gameScreen.actionEat); - + nav.addRight(btn = new NavButton(Res.getTxQuad("nav.button.fg.pause"))); btn.setAction(gameScreen.actionTogglePause); - + // TODO actions //nav.addLeft(new NavButton(Res.txq("nav.button.fg.options"))); //nav.addLeft(new NavButton(Res.txq("nav.button.fg.help"))); - + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.menu"))); btn.setAction(gameScreen.actionMenu); - + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.save"))); btn.setAction(gameScreen.actionSave); - + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.load"))); btn.setAction(gameScreen.actionLoad); - + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.map"))); btn.setAction(gameScreen.actionToggleMinimap); - + nav.addLeft(btn = new NavButton(Res.getTxQuad("nav.button.fg.magnify"))); btn.setAction(gameScreen.actionToggleZoom); - + } - - + + @Override public int getZIndex() { return 101; } - - + + @Override public int getEventPriority() { return 400; } - + } diff --git a/src/mightypork/rogue/screens/game/LayerInv.java b/src/mightypork/rogue/screens/game/LayerInv.java index d26d4bf..16809d6 100644 --- a/src/mightypork/rogue/screens/game/LayerInv.java +++ b/src/mightypork/rogue/screens/game/LayerInv.java @@ -26,34 +26,34 @@ import mightypork.utils.string.StringProvider; public class LayerInv extends FadingLayer { - + private static final int SLOT_COUNT = 8; private static final int SLOT_ROW = 4; - + private final KeyStroke keyUse = App.cfg().getKeyStroke("game.inv.use"); private final KeyStroke keyDrop = App.cfg().getKeyStroke("game.inv.drop"); private final KeyStroke keyClose = App.cfg().getKeyStroke("general.close"); - + private final StringProvider contextStrProv = new StringProvider() { - + @Override public String getString() { String s = keyClose + "-close"; - + final int selected = getSelectedSlot(); if (selected != -1) { - + final PlayerFacade pl = WorldProvider.get().getPlayer(); - + final Item itm = pl.getInventory().getItem(selected); if (itm != null && !itm.isEmpty()) { s = keyDrop + "-drop," + s; - + if (itm.getType() == ItemType.FOOD) { s = keyUse + "-eat," + s; } - + if (itm.getType() == ItemType.WEAPON) { s = keyUse + "-equip," + s; } @@ -61,15 +61,15 @@ public class LayerInv extends FadingLayer { } else { s = "Click-select," + s; } - + return s; } }; - + private final InvSlot[] slots = new InvSlot[SLOT_COUNT]; private ScreenGame gscreen; - - + + private int getSelectedSlot() { for (final InvSlot sl : slots) { @@ -80,20 +80,20 @@ public class LayerInv extends FadingLayer { } return -1; } - - + + private void selectSlot(int i) { for (final InvSlot sl : slots) { sl.selected = false; } - + if (i >= 0 && i < SLOT_COUNT) { slots[i].selected = true; } } - - + + @Override protected void onHideFinished() { @@ -101,44 +101,45 @@ public class LayerInv extends FadingLayer { gscreen.actionToggleInv.run(); } } - - - public LayerInv(final ScreenGame screen) { + + + public LayerInv(final ScreenGame screen) + { super(screen); this.gscreen = screen; - + final Rect fg = root.shrink(root.height().perc(15)); - + // darker down to cover console. final QuadPainter qp = new QuadPainter(RGB.BLACK_30, RGB.BLACK_30, RGB.BLACK_90, RGB.BLACK_90); - + qp.setRect(root); root.add(qp); - + int pos = 0; - + final GridLayout gl = new GridLayout(fg, 10, 1); root.add(gl); - + final TextPainter txp = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.YELLOW, "Inventory"); gl.put(txp, pos, 0, 1, 1); txp.setVPaddingPercent(5); pos += 1; - + final FlowColumnLayout row1 = new FlowColumnLayout(root, null, AlignX.LEFT); row1.setElementWidth(row1.height()); final ConstraintLayout cl1 = new ConstraintLayout(root); row1.setRect(cl1.axisV().grow(cl1.height().mul(2), Num.ZERO)); cl1.add(row1); - + gl.put(cl1, pos, 0, 4, 1); pos += 4; - + row1.add(slots[0] = new InvSlot(0, slots)); row1.add(slots[1] = new InvSlot(1, slots)); row1.add(slots[2] = new InvSlot(2, slots)); row1.add(slots[3] = new InvSlot(3, slots)); - + final FlowColumnLayout row2 = new FlowColumnLayout(root, null, AlignX.LEFT); row2.setElementWidth(row2.height()); final ConstraintLayout cl2 = new ConstraintLayout(root); @@ -146,18 +147,18 @@ public class LayerInv extends FadingLayer { cl2.add(row2); gl.put(cl2, pos, 0, 4, 1); pos += 4; - + row2.add(slots[4] = new InvSlot(4, slots)); row2.add(slots[5] = new InvSlot(5, slots)); row2.add(slots[6] = new InvSlot(6, slots)); row2.add(slots[7] = new InvSlot(7, slots)); - + final TextPainter txp2 = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.WHITE, contextStrProv); gl.put(txp2, pos, 0, 1, 1); txp2.setVPaddingPercent(25); - + bindKey(keyClose, Trigger.RISING, new Runnable() { - + @Override public void run() { @@ -165,150 +166,150 @@ public class LayerInv extends FadingLayer { hide(); } }); - + bindKey(keyUse, Trigger.RISING, new Runnable() { - + @Override public void run() { if (!isEnabled()) return; - + if (WorldProvider.get().getPlayer().isDead()) return; - + useSelectedItem(); } }); - + bindKey(keyDrop, Trigger.RISING, new Runnable() { - + @Override public void run() { if (!isEnabled()) return; - + final int selected = getSelectedSlot(); if (selected != -1) { WorldProvider.get().getPlayer().dropItem(selected); } } }); - + setupGridWalkKeys(); } - - + + protected void useSelectedItem() { final int selected = getSelectedSlot(); if (selected != -1) { - + final World world = WorldProvider.get().getWorld(); final PlayerFacade pl = WorldProvider.get().getPlayer(); final Item itm = pl.getInventory().getItem(selected); - + if (itm != null && !itm.isEmpty()) { - + final ItemType type = itm.getType(); - + if (type == ItemType.FOOD) { - + if (pl.eatFood(itm)) { pl.getInventory().clean(); } - + } else if (type == ItemType.WEAPON) { - + if (pl.getSelectedWeaponIndex() == selected) { pl.selectWeapon(-1); } else { pl.selectWeapon(selected); } world.getConsole().msgEquipWeapon(pl.getSelectedWeapon()); - + } } } } - - + + private void setupGridWalkKeys() { - Config cfg = App.cfg(); - + final Config cfg = App.cfg(); + bindKey(cfg.getKeyStroke("game.inv.move.left"), Trigger.RISING, new Runnable() { - + @Override public void run() { if (!isEnabled()) return; - + final int sel = getSelectedSlot(); if (sel == -1) { selectSlot(0); return; } - + selectSlot((SLOT_COUNT + (sel - 1)) % SLOT_COUNT); } }); - + bindKey(cfg.getKeyStroke("game.inv.move.right"), Trigger.RISING, new Runnable() { - + @Override public void run() { if (!isEnabled()) return; - + final int sel = getSelectedSlot(); if (sel == -1) { selectSlot(0); return; } - + selectSlot((SLOT_COUNT + (sel + 1)) % SLOT_COUNT); } }); - + bindKey(cfg.getKeyStroke("game.inv.move.up"), Trigger.RISING, new Runnable() { - + @Override public void run() { if (!isEnabled()) return; - + final int sel = getSelectedSlot(); if (sel == -1) { selectSlot(0); return; } - + selectSlot((SLOT_COUNT + (sel - SLOT_ROW)) % SLOT_COUNT); } }); - + bindKey(cfg.getKeyStroke("game.inv.move.down"), Trigger.RISING, new Runnable() { - + @Override public void run() { if (!isEnabled()) return; - + final int sel = getSelectedSlot(); if (sel == -1) { selectSlot(0); return; } - + selectSlot((sel + SLOT_ROW) % SLOT_COUNT); } }); } - - + + @Override public int getZIndex() { return 300; } - + } diff --git a/src/mightypork/rogue/screens/game/LayerMapView.java b/src/mightypork/rogue/screens/game/LayerMapView.java index 43d7a61..5f02809 100644 --- a/src/mightypork/rogue/screens/game/LayerMapView.java +++ b/src/mightypork/rogue/screens/game/LayerMapView.java @@ -10,40 +10,41 @@ import mightypork.utils.math.constraints.num.Num; public class LayerMapView extends ScreenLayer { - + protected final MapView map; - - - public LayerMapView(Screen screen) { + + + public LayerMapView(Screen screen) + { super(screen); - + // render component - + map = new MapView(); - + // map input plugins map.addPlugin(new MIPKeyboard(map)); map.addPlugin(new MIPMouse(map)); - + // size of lower navbar final Num lownav = root.height().perc(12); map.setRect(root.shrinkBottom(lownav)); - + root.add(map); } - - + + @Override public int getZIndex() { return 0; // stay down } - - + + @Override public int getEventPriority() { return 100; } - + } diff --git a/src/mightypork/rogue/screens/game/LayerWin.java b/src/mightypork/rogue/screens/game/LayerWin.java index 99784fd..dee85ba 100644 --- a/src/mightypork/rogue/screens/game/LayerWin.java +++ b/src/mightypork/rogue/screens/game/LayerWin.java @@ -4,7 +4,6 @@ package mightypork.rogue.screens.game; import java.io.File; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.config.Config; import mightypork.gamecore.graphics.fonts.IFont; import mightypork.gamecore.gui.Action; import mightypork.gamecore.gui.components.input.TextButton; @@ -25,68 +24,69 @@ import mightypork.utils.math.constraints.num.Num; public class LayerWin extends FadingLayer { - - public LayerWin(final ScreenGame screen) { + + public LayerWin(final ScreenGame screen) + { super(screen); - + // darker down to cover console. final QuadPainter qp = new QuadPainter(RGB.BLACK_80); qp.setRect(root); root.add(qp); - + final IFont thick_font = Res.getFont("thick"); - + final RowLayout rl = new RowLayout(root, 5); rl.setRect(root.shrink(Num.ZERO, root.height().perc(15))); root.add(rl); - + final TextPainter txp = new TextPainter(thick_font, AlignX.CENTER, RGB.YELLOW, "You won!"); rl.add(txp, 1); txp.setVPaddingPercent(13); - + LinearLayout linl = new LinearLayout(root, AlignX.CENTER); linl.add(new ImagePainter(Res.getTxQuad("win"))); rl.add(linl, 3); - + linl = new LinearLayout(root, AlignX.CENTER); rl.add(linl); - + final TextButton btn1 = new TextButton(thick_font, "Leave", ScreenGame.COLOR_BTN_GOOD); btn1.textPainter.setVPaddingPercent(25); linl.add(btn1); - + final Action quit = new Action() { - + @Override protected void execute() { // delete the save file final File f = WorldProvider.get().getWorld().getSaveFile(); f.delete(); - + App.bus().send(new RogueStateRequest(RogueState.MAIN_MENU)); } }; - + btn1.setAction(quit); - + bindKey(App.cfg().getKeyStroke("general.confirm"), Trigger.RISING, quit); bindKey(App.cfg().getKeyStroke("general.close"), Trigger.RISING, quit); } - - + + @Override public int getZIndex() { return 300; } - - + + @Override protected void onShowFinished() { App.audio().fadeOutAllLoops(); Res.getSoundEffect("game.win").play(1); } - + } diff --git a/src/mightypork/rogue/screens/game/NavButton.java b/src/mightypork/rogue/screens/game/NavButton.java index 3332254..bd28c0b 100644 --- a/src/mightypork/rogue/screens/game/NavButton.java +++ b/src/mightypork/rogue/screens/game/NavButton.java @@ -9,28 +9,29 @@ import mightypork.gamecore.resources.Res; /** * Button in the ingame nav - * + * * @author Ondřej Hruška (MightyPork) */ public class NavButton extends ClickableComponent { - + private final TxQuad base, hover, down, fg; - - - public NavButton(TxQuad fg) { + + + public NavButton(TxQuad fg) + { super(); this.base = Res.getTxQuad("nav.button.bg.base"); this.hover = Res.getTxQuad("nav.button.bg.hover"); this.down = Res.getTxQuad("nav.button.bg.down"); this.fg = fg; } - - + + @Override protected void renderComponent() { TxQuad bg; - + if (btnDownOver) { bg = down; } else if (isMouseOver()) { @@ -38,11 +39,11 @@ public class NavButton extends ClickableComponent { } else { bg = base; } - + if (!isEnabled()) bg = base; // override effects - + App.gfx().quad(this, bg); App.gfx().quad(this, fg); } - + } diff --git a/src/mightypork/rogue/screens/game/ScreenGame.java b/src/mightypork/rogue/screens/game/ScreenGame.java index 34c9df9..4d185d2 100644 --- a/src/mightypork/rogue/screens/game/ScreenGame.java +++ b/src/mightypork/rogue/screens/game/ScreenGame.java @@ -25,34 +25,34 @@ import mightypork.utils.math.color.Color; public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameWinHandler { - + public static final Color COLOR_BTN_GOOD = Color.fromHex(0x28CB2D); public static final Color COLOR_BTN_BAD = Color.fromHex(0xCB2828); public static final Color COLOR_BTN_CANCEL = Color.fromHex(0xFFFB55); - + /** * Game gui state. - * + * * @author Ondřej Hruška (MightyPork) */ public enum GScrState { WORLD, INV, DEATH, WIN, GOTO_MENU, GOTO_QUIT; } - + private LayerInv invLayer; private LayerGameUi hudLayer; private LayerDeath deathLayer; private LayerWin winLayer; - + private LayerMapView worldLayer; - + private GScrState state = null; - + private final ActionGroup worldActions = new ActionGroup(); - + public Action actionEat = new Action() { - + @Override public void execute() { @@ -61,50 +61,50 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW pl.tryToEatSomeFood(); } }; - + public Action actionToggleInv = new Action() { - + @Override public void execute() { setState(getState() == GScrState.INV ? GScrState.WORLD : GScrState.INV); } }; - + public Action actionToggleMinimap = new Action() { - + @Override public void execute() { hudLayer.miniMap.setVisible(!hudLayer.miniMap.isVisible()); } }; - + public Action actionTogglePause = new Action() { - + @Override public void execute() { App.bus().send(new WorldPauseRequest(PauseAction.TOGGLE)); } }; - + public Action actionToggleZoom = new Action() { - + @Override public void execute() { worldLayer.map.toggleMag(); } }; - + public Action actionSave = new Action() { - + @Override public void execute() { if (WorldProvider.get().getWorld().isGameOver()) return; - + try { WorldProvider.get().saveWorld(); WorldProvider.get().getWorld().getConsole().msgWorldSaved(); @@ -114,46 +114,46 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW } } }; - + public Action actionLoad = new Action() { - + @Override public void execute() { if (WorldProvider.get().getWorld().isGameOver()) return; - + try { final File f = WorldProvider.get().getWorld().getSaveFile(); WorldProvider.get().loadWorld(f); WorldProvider.get().getWorld().getConsole().msgReloaded(); - + } catch (final Exception e) { Log.e("Could not load the world.", e); WorldProvider.get().getWorld().getConsole().msgLoadFailed(); } } }; - + public Action actionMenu = new Action() { - + @Override public void execute() { setState(GScrState.GOTO_MENU); } }; - + public Action actionQuit = new Action() { - + @Override public void execute() { setState(GScrState.GOTO_QUIT); } }; - + public Action actionDropLastPickedItem = new Action() { - + @Override public void execute() { @@ -163,62 +163,62 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW } }; private LayerAskSave askSaveLayer; - - + + /** * Set gui state (overlay) - * + * * @param nstate new state */ public void setState(GScrState nstate) { if (this.state == nstate) return; - + final boolean gameOver = WorldProvider.get().getWorld().isGameOver(); - + if (nstate != GScrState.WORLD && state == GScrState.WORLD) { // leaving world. App.bus().send(new WorldPauseRequest(PauseAction.PAUSE)); - + worldActions.setEnabled(false); // disable world actions } - + if (nstate != GScrState.DEATH) deathLayer.hide(); if (nstate != GScrState.WIN) winLayer.hide(); if (nstate != GScrState.INV) invLayer.hide(); if (nstate != GScrState.GOTO_MENU && nstate != GScrState.GOTO_QUIT) askSaveLayer.hide(); - + Runnable task; switch (nstate) { case WORLD: App.bus().send(new WorldPauseRequest(PauseAction.RESUME)); worldActions.setEnabled(true); break; - + case INV: invLayer.show(); break; - + case DEATH: deathLayer.show(); break; - + case WIN: winLayer.show(); break; - + case GOTO_MENU: case GOTO_QUIT: final RogueState goal = (nstate == GScrState.GOTO_MENU) ? RogueState.MAIN_MENU : RogueState.EXIT; - + task = new Runnable() { - + @Override public void run() { App.bus().send(new RogueStateRequest(goal)); } }; - + if (gameOver) { task.run(); } else { @@ -226,68 +226,69 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW askSaveLayer.show(); } } - + this.state = nstate; } - - + + public GScrState getState() { return state; } - - - public ScreenGame() { - + + + public ScreenGame() + { + addLayer(invLayer = new LayerInv(this)); addLayer(deathLayer = new LayerDeath(this)); addLayer(winLayer = new LayerWin(this)); addLayer(hudLayer = new LayerGameUi(this)); addLayer(worldLayer = new LayerMapView(this)); addLayer(askSaveLayer = new LayerAskSave(this)); - - Config cfg = App.cfg(); - + + final Config cfg = App.cfg(); + bindKey(cfg.getKeyStroke("game.pause"), Trigger.RISING, actionTogglePause); - + bindKey(cfg.getKeyStroke("game.inventory"), Trigger.RISING, actionToggleInv); bindKey(cfg.getKeyStroke("game.drop"), Trigger.RISING, actionDropLastPickedItem); bindKey(cfg.getKeyStroke("game.eat"), Trigger.RISING, actionEat); bindKey(cfg.getKeyStroke("game.minimap"), Trigger.RISING, actionToggleMinimap); bindKey(cfg.getKeyStroke("game.zoom"), Trigger.RISING, actionToggleZoom); - + bindKey(cfg.getKeyStroke("game.load"), Trigger.RISING, actionLoad); bindKey(cfg.getKeyStroke("game.save"), Trigger.RISING, actionSave); bindKey(cfg.getKeyStroke("game.quit"), Trigger.RISING, actionMenu); - + // bindKey(new KeyStroke(Keys.W), Edge.RISING, new Runnable() { -// +// // @Override // public void run() // { // setState(GScrState.WIN); // } // }); - + // add as actions - enableables. worldActions.add(worldLayer); worldActions.add(hudLayer); - + worldActions.add(actionEat); worldActions.add(actionToggleMinimap); worldActions.add(actionTogglePause); worldActions.add(actionToggleZoom); - + worldActions.add(actionSave); worldActions.add(actionLoad); worldActions.add(actionMenu); worldActions.add(actionDropLastPickedItem); - + worldActions.setEnabled(true); - + // CHEAT - X-ray bindKey(cfg.getKeyStroke("game.cheat.xray"), Trigger.RISING, new Runnable() { - + @Override public void run() { @@ -295,32 +296,32 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW } }); } - - + + @Override protected void onScreenEnter() { super.onScreenEnter(); WorldProvider.get().setListening(true); - + setState(GScrState.WORLD); hideAllPopups(); - + App.audio().fadeOutAllLoops(); Res.getSoundLoop("music.dungeon").fadeIn(); } - - + + @Override protected void onScreenLeave() { super.onScreenLeave(); WorldProvider.get().setListening(false); - + Res.getSoundLoop("music.dungeon").fadeOut(); } - - + + private void hideAllPopups() { invLayer.hideImmediate(); @@ -328,29 +329,29 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW winLayer.hideImmediate(); askSaveLayer.hideImmediate(); } - - + + @Override public void onPlayerKilled() { setState(GScrState.DEATH); } - - + + @Override public void onGameWon() { setState(GScrState.WIN); } - - + + @Override public void onShutdown(ShutdownEvent event) { - // if player is dead, don't ask don't ask for save + // if player is dead, don't ask don't ask for save final PlayerFacade pl = WorldProvider.get().getPlayer(); if (pl.isDead()) return; - + actionQuit.run(); event.consume(); } diff --git a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java index ad5cb4a..8fc1058 100644 --- a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java +++ b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java @@ -2,8 +2,6 @@ package mightypork.rogue.screens.menu; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.config.Config; -import mightypork.gamecore.core.events.ShutdownEvent; import mightypork.gamecore.graphics.fonts.IFont; import mightypork.gamecore.gui.Action; import mightypork.gamecore.gui.components.input.TextButton; @@ -27,51 +25,51 @@ import mightypork.utils.math.constraints.rect.Rect; /** * Main menu screen - * + * * @author Ondřej Hruška (MightyPork) */ public class ScreenMainMenu extends RogueScreen { - + /** * The layer - * + * * @author Ondřej Hruška (MightyPork) */ class MenuLayer extends ScreenLayer { - + public MenuLayer(Screen screen) { super(screen); - + init(); } - - + + private void init() { final Rect menuBox = root.shrink(Num.ZERO, root.height().perc(15)).moveY(root.height().perc(-4)); - + final QuadPainter bg = QuadPainter.gradV(Color.fromHex(0x007eb3), PAL16.SEABLUE); bg.setRect(root); root.add(bg); - + final RowLayout rows = new RowLayout(menuBox, 13); rows.enableCaching(true); root.add(rows); - + final LinearLayout linlayout = new LinearLayout(root, AlignX.CENTER); linlayout.add(new ImagePainter(Res.getTxQuad("logo"))); rows.add(linlayout, 4); rows.skip(1); - + TextButton btn; - + final IFont btnFont = Res.getFont("thick"); - + // world button btn = new TextButton(btnFont, "Play", PAL16.SLIMEGREEN); btn.setAction(new Action() { - + @Override protected void execute() { @@ -80,10 +78,10 @@ public class ScreenMainMenu extends RogueScreen { }); rows.add(btn, 2); rows.skip(1); - + btn = new TextButton(btnFont, "Story", PAL16.CLOUDBLUE); btn.setAction(new Action() { - + @Override protected void execute() { @@ -92,11 +90,11 @@ public class ScreenMainMenu extends RogueScreen { }); rows.add(btn, 2); rows.skip(1); - + // quit button btn = new TextButton(btnFont, "Exit", PAL16.BLOODRED); btn.setAction(new Action() { - + @Override protected void execute() { @@ -104,9 +102,9 @@ public class ScreenMainMenu extends RogueScreen { } }); rows.add(btn, 2); - + bindKey(App.cfg().getKeyStroke("general.close"), Trigger.RISING, new Runnable() { - + @Override public void run() { @@ -114,28 +112,28 @@ public class ScreenMainMenu extends RogueScreen { } }); } - - + + @Override public int getZIndex() { return 2; } - + } - - + + public ScreenMainMenu() { addLayer(new MenuLayer(this)); } - - + + @Override protected void onScreenEnter() { super.onScreenEnter(); - + App.audio().fadeOutAllLoops(); Res.getSoundLoop("music.menu").fadeIn(); } diff --git a/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java b/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java index fc8f10d..66cdf78 100644 --- a/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java +++ b/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java @@ -2,8 +2,6 @@ package mightypork.rogue.screens.select_world; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.WorkDir; -import mightypork.gamecore.core.config.Config; import mightypork.gamecore.gui.components.layout.RowLayout; import mightypork.gamecore.gui.components.painters.QuadPainter; import mightypork.gamecore.gui.components.painters.TextPainter; @@ -14,6 +12,7 @@ import mightypork.gamecore.resources.Res; import mightypork.rogue.RogueStateManager.RogueState; import mightypork.rogue.events.RogueStateRequest; import mightypork.rogue.screens.RogueScreen; +import mightypork.utils.files.WorkDir; import mightypork.utils.logging.Log; import mightypork.utils.math.AlignX; import mightypork.utils.math.color.Color; @@ -24,59 +23,61 @@ import mightypork.utils.math.constraints.rect.Rect; /** * Main menu screen - * + * * @author Ondřej Hruška (MightyPork) */ public class ScreenSelectWorld extends RogueScreen { - - public ScreenSelectWorld() { + + public ScreenSelectWorld() + { addLayer(new WorldsLayer(this)); } - + class WorldsLayer extends ScreenLayer { - + private WorldSlot slot1; private WorldSlot slot2; private WorldSlot slot3; - - - public WorldsLayer(Screen screen) { + + + public WorldsLayer(Screen screen) + { super(screen); - + init(); } - - + + private void init() { final Rect menuBox = root.shrink(root.width().perc(25), root.height().perc(30)).moveY(root.height().perc(-10)); - + final QuadPainter bg = QuadPainter.gradV(Color.fromHex(0x007eb3), PAL16.SEABLUE); bg.setRect(root); root.add(bg); - + final RowLayout rows = new RowLayout(menuBox, 4); rows.enableCaching(true); root.add(rows); - + TextPainter tp; - + rows.add(tp = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.YELLOW, "Save slot:")); tp.setVPaddingPercent(20); tp.setShadow(RGB.BLACK_50, tp.height().mul(0.6 / 8D).toVectXY()); - + slot1 = new WorldSlot(WorkDir.getFile("slot1")); rows.add(slot1); - + slot2 = new WorldSlot(WorkDir.getFile("slot2")); rows.add(slot2); - + slot3 = new WorldSlot(WorkDir.getFile("slot3")); rows.add(slot3); - + // escape to quitn from here bindKey(App.cfg().getKeyStroke("general.close"), Trigger.RISING, new Runnable() { - + @Override public void run() { @@ -84,20 +85,20 @@ public class ScreenSelectWorld extends RogueScreen { } }); } - - + + @Override public int getZIndex() { return 2; } - - + + @Override protected void onScreenEnter() { super.onScreenEnter(); - + Log.f3("Refreshing save slots"); slot1.refresh(); slot2.refresh(); diff --git a/src/mightypork/rogue/screens/select_world/WorldSlot.java b/src/mightypork/rogue/screens/select_world/WorldSlot.java index f4abbd5..3196786 100644 --- a/src/mightypork/rogue/screens/select_world/WorldSlot.java +++ b/src/mightypork/rogue/screens/select_world/WorldSlot.java @@ -26,120 +26,121 @@ import mightypork.utils.string.StringProvider; public class WorldSlot extends ConstraintLayout { - + private final StringProvider lblStrp = new StringProvider() { - + @Override public String getString() { return label; } }; - + private File file; private String label; - + private IonDataBundle worldBundle; - + private TextButton loadBtn; - + private TextButton delBtn; - - - public WorldSlot(File worldFile) { - + + + public WorldSlot(File worldFile) + { + this.file = worldFile; - + final Rect innerRect = shrink(height().perc(5)); - + final QuadPainter qp = new QuadPainter(RGB.BLACK.withAlpha(new Num() { - + @Override public double value() { return isMouseOver() ? 0.15 : 0.1; } })); - + qp.setRect(innerRect); add(qp); - + final GridLayout gridl = new GridLayout(1, 8); final Num shrinkH = width().perc(8); final Num shrinkV = height().perc(10); gridl.setRect(innerRect.shrink(shrinkH, shrinkH, shrinkV, shrinkV.half())); add(gridl); - + final IFont font = Res.getFont("thick"); - + gridl.put(loadBtn = new TextButton(font, "", RGB.WHITE), 0, 0, 1, 7); loadBtn.textPainter.setVPaddingPercent(20); loadBtn.textPainter.setAlign(AlignX.LEFT); loadBtn.textPainter.setText(lblStrp); loadBtn.disableHoverEffect(); - + loadBtn.setAction(new Action() { - + @Override protected void execute() { String msg; - + if (worldBundle != null) { msg = "Loading world..."; } else { msg = "Creating world..."; } - + App.bus().send(new LoadingOverlayRequest(msg, new Runnable() { - + @Override public void run() { World w; - + if (worldBundle == null) { - + try { w = WorldProvider.get().createWorld(Double.doubleToLongBits(Math.random())); w.setSaveFile(file); - + WorldProvider.get().saveWorld(); - + App.bus().send(new ScreenRequest("game")); - + } catch (final Exception t) { Log.e("Could not create & save the world.", t); } - + } else { - + try { w = new World(); w.setSaveFile(file); w.load((IonDataBundle) worldBundle.get("world")); WorldProvider.get().setWorld(w); - + App.bus().send(new ScreenRequest("game")); - + } catch (final Exception e) { Log.e("Could not load the world.", e); } } - + } })); - + } }); - + gridl.put(delBtn = new TextButton(font, "X", RGB.RED), 0, 7, 1, 1); delBtn.textPainter.setVPaddingPercent(20); delBtn.textPainter.setAlign(AlignX.RIGHT); delBtn.disableHoverEffect(); - + delBtn.setAction(new Action() { - + @Override protected void execute() { @@ -148,30 +149,30 @@ public class WorldSlot extends ConstraintLayout { refresh(); } }); - + refresh(); } - - + + public void refresh() { delBtn.setVisible(false); delBtn.setEnabled(false); - + if (!file.exists()) { label = ""; worldBundle = null; } else { - + delBtn.setVisible(true); delBtn.setEnabled(true); - + try { worldBundle = Ion.fromFile(file); final int lvl = worldBundle.get("level", -1); - + if (lvl == -1) throw new RuntimeException("Invalid save format."); // let the catch block handle it - + label = "Level " + (lvl + 1); } catch (final Exception e) { Log.w("Error loading world save.", e); @@ -179,5 +180,5 @@ public class WorldSlot extends ConstraintLayout { } } } - + } diff --git a/src/mightypork/rogue/screens/story/ScreenStory.java b/src/mightypork/rogue/screens/story/ScreenStory.java index 3be1b42..04ae1e0 100644 --- a/src/mightypork/rogue/screens/story/ScreenStory.java +++ b/src/mightypork/rogue/screens/story/ScreenStory.java @@ -2,7 +2,6 @@ package mightypork.rogue.screens.story; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.config.Config; import mightypork.gamecore.gui.Action; import mightypork.gamecore.gui.components.layout.RowLayout; import mightypork.gamecore.gui.components.layout.linear.LinearLayout; @@ -31,9 +30,9 @@ import mightypork.utils.math.timing.TimedTask; public class ScreenStory extends RogueScreen implements MouseButtonHandler { - + private class LayerSlide extends ScreenLayer { - + private final TextPainter tp1; private final TextPainter tp2; private final ImagePainter img; @@ -41,30 +40,30 @@ public class ScreenStory extends RogueScreen implements MouseButtonHandler { private final NumAnimated tx1alpha = new NumAnimated(0, Easing.BOUNCE_OUT, 1); private final NumAnimated tx2alpha = new NumAnimated(0, Easing.BOUNCE_OUT, 1); private final NumAnimated txProceedAlpha = new NumAnimated(0, Easing.CIRC_OUT, 1); - + private String nextImg, nextT1, nextT2; - + private final TimedTask ttNextSlide = new TimedTask() { - + @Override public void run() { img.setTxQuad(Res.getTxQuad(nextImg)); if (nextT1 != null) tp1.setText(nextT1); if (nextT2 != null) tp2.setText(nextT2); - + tx1alpha.setTo(0); tx2alpha.setTo(0); txProceedAlpha.setTo(0); - + layerAlpha.setTo(0); layerAlpha.fadeIn(); ttText1.start(1.5); } }; - + private final TimedTask ttText1 = new TimedTask() { - + @Override public void run() { @@ -76,9 +75,9 @@ public class ScreenStory extends RogueScreen implements MouseButtonHandler { } } }; - + private final TimedTask ttText2 = new TimedTask() { - + @Override public void run() { @@ -90,106 +89,108 @@ public class ScreenStory extends RogueScreen implements MouseButtonHandler { } } }; - + private final TimedTask ttFinish = new TimedTask() { - + @Override public void run() { txProceedAlpha.fadeIn(); } }; - + private final Color textColor = Color.fromHex(0x7ad8ff); - - - public LayerSlide(Screen screen) { + + + public LayerSlide(Screen screen) + { super(screen); - - final TextPainter help = new TextPainter(Res.getFont("tiny"), AlignX.CENTER, RGB.WHITE.withAlpha(txProceedAlpha.mul(0.3)), "Space / click to proceed."); + + final TextPainter help = new TextPainter(Res.getFont("tiny"), AlignX.CENTER, RGB.WHITE.withAlpha(txProceedAlpha.mul(0.3)), + "Space / click to proceed."); help.setRect(root.bottomEdge().growUp(root.height().perc(4))); help.setVPaddingPercent(5); root.add(help); - + final Rect contentRect = root.shrink(Num.ZERO, Num.ZERO, root.height().perc(2), root.height().perc(6)); final RowLayout rl = new RowLayout(root, 9); rl.setRect(contentRect); root.add(rl); - + final LinearLayout ll = new LinearLayout(root, AlignX.CENTER); rl.add(ll, 7); img = new ImagePainter(Res.getTxQuad("story_1")); ll.add(img); - + tp1 = new TextPainter(Res.getFont("tiny"), AlignX.CENTER, textColor.withAlpha(tx1alpha), ""); rl.add(tp1); tp1.setVPaddingPercent(19); - + tp2 = new TextPainter(Res.getFont("tiny"), AlignX.CENTER, textColor.withAlpha(tx2alpha), ""); rl.add(tp2); tp2.setVPaddingPercent(19); - + updated.add(layerAlpha); updated.add(txProceedAlpha); updated.add(tx1alpha); updated.add(tx2alpha); - + updated.add(ttText1); updated.add(ttText2); updated.add(ttFinish); updated.add(ttNextSlide); - + setAlpha(layerAlpha); } - - + + @Override public int getZIndex() { return 1; } - - + + public void showSlide(String image, String text1, String text2) { ttFinish.stop(); ttNextSlide.stop(); ttText1.stop(); ttText2.stop(); - + this.nextImg = image; this.nextT1 = text1; this.nextT2 = text2; - + layerAlpha.fadeOut(); ttNextSlide.start(1); } - - + + public void reset() { ttFinish.stop(); ttNextSlide.stop(); ttText1.stop(); ttText2.stop(); - + layerAlpha.setTo(0); } } - + private LayerSlide slideLayer; - + private final Action next = new Action() { - + @Override protected void execute() { showSlide(++slide); } }; - + private final Action prev = new Action() { - + @Override protected void execute() { @@ -197,32 +198,33 @@ public class ScreenStory extends RogueScreen implements MouseButtonHandler { showSlide(slide); } }; - + private final Action close = new Action() { - + @Override protected void execute() { App.bus().send(new RogueStateRequest(RogueState.MAIN_MENU)); } }; - - - public ScreenStory() { - + + + public ScreenStory() + { + addLayer(new LayerColor(this, Color.fromHex(0x040c1e), 0)); addLayer(slideLayer = new LayerSlide(this)); - + bindKey(new KeyStroke(Keys.SPACE), Trigger.RISING, next); bindKey(new KeyStroke(Keys.RIGHT), Trigger.RISING, next); bindKey(new KeyStroke(Keys.BACKSPACE), Trigger.RISING, prev); bindKey(new KeyStroke(Keys.LEFT), Trigger.RISING, prev); bindKey(App.cfg().getKeyStroke("general.close"), Trigger.RISING, close); } - + private int slide = 0; - - + + @Override protected void onScreenEnter() { @@ -230,29 +232,29 @@ public class ScreenStory extends RogueScreen implements MouseButtonHandler { slideLayer.reset(); showSlide(slide); } - - + + private void showSlide(int slide) { switch (slide) { case 0: slideLayer.showSlide("story_1", "Man, it's so hot today!", "Makes me real thirsty, ya know."); break; - + case 1: slideLayer.showSlide("story_2", "'Guess I'll go get some beer", "from the cellar."); break; - + case 2: slideLayer.showSlide("story_3", "Here we go.. HEY GIVE IT BACK!", "I'll hunt you down, thieves!"); break; - + case 3: App.bus().send(new RogueStateRequest(RogueState.MAIN_MENU)); } } - - + + @Override public void receive(MouseButtonEvent event) { diff --git a/src/mightypork/rogue/world/Inventory.java b/src/mightypork/rogue/world/Inventory.java index ab9af32..10026b7 100644 --- a/src/mightypork/rogue/world/Inventory.java +++ b/src/mightypork/rogue/world/Inventory.java @@ -11,57 +11,59 @@ import mightypork.utils.ion.IonOutput; public class Inventory implements IonBinary { - + public static final short ION_MARK = 54; private Item[] items; private int lastAddIndex = 0; - - - public Inventory(int size) { + + + public Inventory(int size) + { this.items = new Item[size]; } - - - public Inventory() { + + + public Inventory() + { // ION constructor } - - + + @Override public void load(IonInput in) throws IOException { final int size = in.readIntByte(); items = new Item[size]; - + // for all items in sequence while (in.hasNextEntry()) { - + // load item index final int i = in.readIntByte(); - + // load item setItem(i, Items.loadItem(in)); } } - - + + @Override public void save(IonOutput out) throws IOException { // write length out.writeIntByte(getSize()); - + // find items that are writable for (int i = 0; i < getSize(); i++) { final Item item = getItem(i); if (item != null && !item.isEmpty()) { - + // start sequence entry out.startEntry(); - + // write index out.writeIntByte(i); - + // write item at index Items.saveItem(out, item); } @@ -69,36 +71,36 @@ public class Inventory implements IonBinary { // close sequence out.endSequence(); } - - + + /** * Get item in a slot - * + * * @param i slot number * @return item in the slot; can be null. */ public Item getItem(int i) { if (i < 0 || i > getSize()) return null; - + verifyIndex(i); final Item itm = items[i]; if (itm == null || itm.isEmpty()) return null; return itm; } - - + + private void verifyIndex(int i) { if (i < 0 || i > getSize()) { throw new IndexOutOfBoundsException("Invalid inventory index: " + i + ", size: " + getSize()); } } - - + + /** * Put item in a slot - * + * * @param i slot number * @param item item to store */ @@ -108,8 +110,8 @@ public class Inventory implements IonBinary { items[i] = item; lastAddIndex = i; } - - + + /** * @return inventory size */ @@ -117,11 +119,11 @@ public class Inventory implements IonBinary { { return items.length; } - - + + /** * Add an item, try to merge first. - * + * * @param stored stored item * @return true if the item was entirely added, and is now empty. */ @@ -137,7 +139,7 @@ public class Inventory implements IonBinary { } } } - + // try to place in a free slot for (int i = 0; i < getSize(); i++) { final Item itm = getItem(i); @@ -147,12 +149,12 @@ public class Inventory implements IonBinary { return true; } } - + // could not insert. return false; } - - + + /** * Clean empty items */ @@ -164,28 +166,26 @@ public class Inventory implements IonBinary { if (itm.isEmpty()) setItem(i, null); } } - - + + public int getLastAddIndex() { return lastAddIndex; } - - + + @Override public String toString() { String s = "Inv["; - + for (int i = 0; i < getSize(); i++) { if (i > 0) s += ", "; s += i + ": "; final Item itm = getItem(i); - - if (itm == null) - s += ""; - else - s += itm; + + if (itm == null) s += ""; + else s += itm; } s += "]"; return s; diff --git a/src/mightypork/rogue/world/PlayerControl.java b/src/mightypork/rogue/world/PlayerControl.java index da4e60b..2018e77 100644 --- a/src/mightypork/rogue/world/PlayerControl.java +++ b/src/mightypork/rogue/world/PlayerControl.java @@ -15,85 +15,85 @@ import mightypork.utils.math.constraints.vect.Vect; public abstract class PlayerControl { - + protected Set playerMoveListeners = new HashSet<>(); - + private World lastWorld; - - + + /** * Implementing classes should return a world instance from this method. - * + * * @return */ protected abstract World provideWorld(); - - + + public World getWorld() { final World newWorld = provideWorld(); - + lastWorld = newWorld; - + return newWorld; - + } - - + + public PlayerFacade getPlayer() { if (getWorld() == null) return null; - + return getWorld().getPlayer(); } - - + + public void goNorth() { go(Move.NORTH); } - - + + public void goSouth() { go(Move.SOUTH); } - - + + public void goEast() { go(Move.EAST); } - - + + public void goWest() { go(Move.WEST); } - - + + public void navigateTo(Coord pos) { if (!getLevel().getTile(pos).isExplored()) return; getPlayer().navigateTo(pos); } - - + + public Level getLevel() { return getWorld().getPlayer().getLevel(); } - - + + public boolean canGo(Move side) { return getPlayer().canGoTo(side); } - - + + /** * Click tile on player's side - * + * * @param side * @return */ @@ -101,44 +101,44 @@ public abstract class PlayerControl { { return doClickTile(getPlayer().getCoord().add(side).toVect()); } - - + + public boolean clickTile(Vect pos) { if (pos.dist(getPlayer().getVisualPos().add(0.5, 0.5)).value() < 1.5) { return doClickTile(pos); } - + return false; } - - + + private boolean doClickTile(Vect pos) { //try to click tile if (getLevel().getTile(Coord.fromVect(pos)).onClick()) return true; - + final Tile t = getLevel().getTile(Coord.fromVect(pos)); if (!t.isPotentiallyWalkable()) return false; // no point in attacking entity thru wall, right? - + //try to hit entity final Entity prey = getLevel().getClosestEntity(pos, EntityType.MONSTER, 1); if (prey != null) { getPlayer().attack(prey); return true; } - + return false; } - - + + public void go(Move side) { getPlayer().cancelPath(); getPlayer().addPathStep(side); } - - + + public boolean tryGo(Move e) { if (!canGo(e)) return false; diff --git a/src/mightypork/rogue/world/PlayerData.java b/src/mightypork/rogue/world/PlayerData.java index fd57455..11676bf 100644 --- a/src/mightypork/rogue/world/PlayerData.java +++ b/src/mightypork/rogue/world/PlayerData.java @@ -8,36 +8,36 @@ import mightypork.utils.ion.IonDataBundle; /** * Player information stored in world. - * + * * @author Ondřej Hruška (MightyPork) */ public class PlayerData implements IonBundled { - + /** Player inventory size */ private static final int INV_SIZE = 8; - + /** Attack str with bare hands */ public static final int BARE_ATTACK = 1; - + private int eid = -1; // marks not initialized private int level; - + private Inventory inventory = new Inventory(INV_SIZE); - + private int selectedWeapon = -1; - - + + @Override public void load(IonDataBundle bundle) { eid = bundle.get("eid", -1); level = bundle.get("floor", -1); selectedWeapon = bundle.get("weapon", -1); - + inventory = bundle.get("inv", inventory); } - - + + @Override public void save(IonDataBundle bundle) { @@ -46,69 +46,69 @@ public class PlayerData implements IonBundled { bundle.put("weapon", selectedWeapon); bundle.put("inv", inventory); } - - + + public void setEID(int eid) { if (isInitialized()) throw new RuntimeException("Cannot change player EID."); this.eid = eid; } - - + + public void setLevelNumber(int level) { this.level = level; } - - + + public int getEID() { return eid; } - - + + public int getLevelNumber() { return level; } - - + + public boolean isInitialized() { return eid != -1; } - - + + public Inventory getInventory() { return inventory; } - - + + public int getSelectedWeaponIndex() { return selectedWeapon; } - - + + public boolean hasWeaponSelected() { return !(selectedWeapon < 0 || selectedWeapon >= getInventory().getSize()); } - - + + public Item getSelectedWeapon() { if (!hasWeaponSelected()) return null; return inventory.getItem(selectedWeapon); } - - + + public void selectWeapon(int selectedWeapon) { this.selectedWeapon = selectedWeapon; - + if (!hasWeaponSelected()) selectedWeapon = -1; // normalize } - + } diff --git a/src/mightypork/rogue/world/PlayerFacade.java b/src/mightypork/rogue/world/PlayerFacade.java index 758d238..0e08024 100644 --- a/src/mightypork/rogue/world/PlayerFacade.java +++ b/src/mightypork/rogue/world/PlayerFacade.java @@ -17,15 +17,15 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Convenient access to player-related methods and data in world. - * + * * @author Ondřej Hruška (MightyPork) */ public class PlayerFacade { - + /** a world */ private final World world; - - + + /** * @return true if can go up */ @@ -33,16 +33,17 @@ public class PlayerFacade { { return world.playerData.getLevelNumber() > 0; } - - + + /** * @param world */ - PlayerFacade(World world) { + PlayerFacade(World world) + { this.world = world; } - - + + /** * @return true if can go down */ @@ -50,48 +51,48 @@ public class PlayerFacade { { return world.playerData.getLevelNumber() < world.levels.size() - 1; } - - + + /** * Go one level down if applicable */ public void descend() { if (!canDescend()) return; - + final int lvl_num = getLevelNumber(); getLevel().removeEntity(world.playerEntity); - + world.playerData.setLevelNumber(lvl_num + 1); - + getLevel().forceFreeTile(getLevel().getEnterPoint()); getLevel().addEntity(world.playerEntity, getLevel().getEnterPoint()); getLevel().explore(getCoord()); - + world.console.msgEnterFloor(getLevelNumber()); } - - + + /** * Go one level up if applicable */ public void ascend() { if (!canAscend()) return; - + final int lvl_num = getLevelNumber(); getLevel().removeEntity(world.playerEntity); - + world.playerData.setLevelNumber(lvl_num - 1); - + getLevel().forceFreeTile(getLevel().getExitPoint()); getLevel().addEntity(world.playerEntity, getLevel().getExitPoint()); getLevel().explore(getCoord()); - + world.console.msgEnterFloor(getLevelNumber()); } - - + + /** * @return current level number, zero based. */ @@ -99,8 +100,8 @@ public class PlayerFacade { { return world.playerData.getLevelNumber(); } - - + + /** * @return current level */ @@ -108,8 +109,8 @@ public class PlayerFacade { { return world.levels.get(world.playerData.getLevelNumber()); } - - + + /** * @return entity ID */ @@ -117,8 +118,8 @@ public class PlayerFacade { { return world.playerData.getEID(); } - - + + /** * @return entity coordinate in level */ @@ -126,8 +127,8 @@ public class PlayerFacade { { return world.playerEntity.getCoord(); } - - + + /** * @return entity visual pos in level */ @@ -135,19 +136,19 @@ public class PlayerFacade { { return world.playerEntity.pos.getVisualPos(); } - - + + /** * Find path to - * + * * @param pos */ public void navigateTo(Coord pos) { world.playerEntity.pos.navigateTo(pos); } - - + + /** * Discard steps in buffer */ @@ -155,108 +156,108 @@ public class PlayerFacade { { world.playerEntity.pos.cancelPath(); } - - + + public void addPathStep(Move step) { world.playerEntity.pos.addStep(step); } - - + + public boolean isMoving() { return world.playerEntity.pos.isMoving(); } - - + + public double getMoveProgress() { return world.playerEntity.pos.getProgress(); } - - + + public boolean isDead() { return world.playerEntity.isDead(); } - - + + public int getHealth() { return world.playerEntity.health.getHealth(); } - - + + public int getHealthMax() { return world.playerEntity.health.getHealthMax(); } - - + + public Inventory getInventory() { return world.playerData.getInventory(); } - - + + public Entity getEntity() { return world.playerEntity; } - - + + public int getAttackStrength() { final Item weapon = world.playerData.getSelectedWeapon(); - + if (weapon == null) return PlayerData.BARE_ATTACK; - + return PlayerData.BARE_ATTACK + weapon.getAttackPoints(); } - - + + /** * Eat food. - * + * * @param itm food item * @return if something was eaten */ public boolean eatFood(Item itm) { if (itm == null || itm.isEmpty() || itm.getType() != ItemType.FOOD) return false; - + if (getHealth() < getHealthMax()) { - + world.playerEntity.health.addHealth(itm.getFoodPoints()); itm.consume(); - + world.console.msgEat(itm); - + return true; } - + return false; } - - + + public void selectWeapon(int selected) { world.playerData.selectWeapon(selected); } - - + + public Item getSelectedWeapon() { return world.playerData.getSelectedWeapon(); } - - + + public int getSelectedWeaponIndex() { return world.playerData.getSelectedWeaponIndex(); } - - + + public void tryToEatSomeFood() { final List foods = new ArrayList<>(); @@ -266,63 +267,63 @@ public class PlayerFacade { foods.add(itm); } } - + // sort from smallest to biggest foods Collections.sort(foods, new Comparator() { - + @Override public int compare(Item o1, Item o2) { return (o1.getFoodPoints() - o2.getFoodPoints()); } }); - + for (final Item itm : foods) { if (eatFood(itm)) { getInventory().clean(); return; } } - + if (getHealth() < getHealthMax()) { world.console.msgNoMoreFood(); } else { world.console.msgNotHungry(); } } - - + + public void attack(Entity prey) { final int attackPoints = getAttackStrength(); - + prey.receiveAttack(world.getPlayer().getEntity(), attackPoints); - + if (prey.isDead()) { world.console.msgKill(prey); } - + final Item wpn = getSelectedWeapon(); - + if (wpn != null) { wpn.use(); if (wpn.isEmpty()) { world.console.msgWeaponBreak(wpn); - + getInventory().clean(); selectWeapon(-1); - + pickBestWeaponIfNoneSelected(); } } - + } - - + + private void pickBestWeaponIfNoneSelected() { if (getSelectedWeapon() != null) return; - + final List wpns = new ArrayList<>(); for (int i = 0; i < getInventory().getSize(); i++) { final Item itm = getInventory().getItem(i); @@ -330,17 +331,17 @@ public class PlayerFacade { wpns.add(itm); } } - + // sort from smallest to biggest foods Collections.sort(wpns, new Comparator() { - + @Override public int compare(Item o1, Item o2) { return (o2.getAttackPoints() - o1.getAttackPoints()); } }); - + for (final Item itm : wpns) { for (int i = 0; i < getInventory().getSize(); i++) { final Item itm2 = getInventory().getItem(i); @@ -351,75 +352,75 @@ public class PlayerFacade { } break; // just one cycle } - + world.console.msgEquipWeapon(getSelectedWeapon()); } - - + + public boolean addItem(Item item) { if (!getInventory().addItem(item)) { - + world.console.msgCannotPick(); - + return false; } - + world.console.msgPick(item); - + if (item.getType() == ItemType.WEAPON) { if (getSelectedWeapon() != null) { if (item.getAttackPoints() > getSelectedWeapon().getAttackPoints()) { selectWeapon(-1); // unselect to grab the best one } } - + pickBestWeaponIfNoneSelected(); } - + return true; } - - + + public void setHealth(int health) { world.playerEntity.health.setHealth(health); } - - + + public void setHealthMax(int health) { world.playerEntity.health.setHealthMax(health); } - - + + public World getWorld() { return world; } - - + + public boolean canGoTo(Move side) { return getEntity().pos.canGoTo(side); } - - + + public void dropItem(int itemIndex) { final Item itm = getInventory().getItem(itemIndex); if (itm != null && !itm.isEmpty()) { - + final Item piece = itm.split(1); getInventory().clean(); - + Coord dropPos; if (world.playerEntity.pos.isMoving()) { dropPos = world.playerEntity.pos.getLastPos(); } else { dropPos = getCoord(); } - + if (!getLevel().getTile(dropPos).dropItem(piece)) { getInventory().addItem(piece); // add back } else { diff --git a/src/mightypork/rogue/world/World.java b/src/mightypork/rogue/world/World.java index d5363d7..f72b161 100644 --- a/src/mightypork/rogue/world/World.java +++ b/src/mightypork/rogue/world/World.java @@ -11,7 +11,6 @@ import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.events.GameWinHandler; import mightypork.rogue.world.events.PlayerDeathHandler; import mightypork.rogue.world.level.Level; -import mightypork.utils.eventbus.EventBus; import mightypork.utils.eventbus.clients.DelegatingClient; import mightypork.utils.interfaces.Pauseable; import mightypork.utils.interfaces.Updateable; @@ -23,71 +22,71 @@ import mightypork.utils.math.algo.Coord; /** * World object. - * + * * @author Ondřej Hruška (MightyPork) */ public class World implements DelegatingClient, IonBundled, Pauseable, Updateable, PlayerDeathHandler, GameWinHandler { - + // not saved stuffs private final PlayerFacade playerFacade = new PlayerFacade(this); - + final WorldConsole console = new WorldConsole(); Entity playerEntity; private int pauseDepth = 0; private boolean gameOver = false; - + /** List of world's levels */ final ArrayList levels = new ArrayList<>(); - + /** Player data saved together with world */ final PlayerData playerData = new PlayerData(); - + /** World seed */ private long seed; - + /** Next entity ID */ private int eid; - + private File saveFile; - - + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Collection getChildClients() { return levels; } - - + + @Override public boolean doesDelegate() { return !isPaused(); } - - + + @Override public void load(IonDataBundle in) { seed = in.get("seed", seed); eid = in.get("next_eid", eid); in.loadSequence("levels", levels); - + // join levels to world for (final Level lvl : levels) { lvl.setWorld(this); } - + in.loadBundled("player", playerData); - + final int eid = playerData.getEID(); final int lvl = playerData.getLevelNumber(); - + playerEntity = levels.get(lvl).getEntity(eid); if (playerEntity == null) { - + Log.e("Player entity not found in the world: " + eid + " on floor " + lvl); - + for (int i = 0; i < levels.size(); i++) { final Entity ent = levels.get(i).getEntity(eid); if (ent != null) { @@ -95,12 +94,12 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl break; } } - + throw new RuntimeException("Player not found in world."); } } - - + + @Override public void save(IonDataBundle out) { @@ -108,31 +107,31 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl out.put("next_eid", eid); out.putSequence("levels", levels); out.putBundled("player", playerData); - + // used for peking in before actually loading the world. out.put("meta.last_level", playerData.getLevelNumber()); } - - + + public void addLevel(Level level) { levels.add(level); level.setWorld(this); } - - + + public void setSeed(long seed) { this.seed = seed; } - - + + public long getSeed() { return seed; } - - + + /** * @return new entity ID */ @@ -140,79 +139,79 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl { return eid++; } - - + + public void createPlayer() { if (playerData.isInitialized()) { throw new RuntimeException("Player already created."); } - + // make entity final int playerEid = getNewEID(); - + final Level floor = levels.get(0); - + playerEntity = Entities.PLAYER.createEntity(playerEid); - + final Coord spawn = floor.getEnterPoint(); - + floor.forceFreeTile(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); - + playerData.setLevelNumber(0); playerData.setEID(playerEid); - + console.msgEnterFloor(0); } - - + + @Override public void pause() { pauseDepth++; } - - + + @Override public void resume() { if (pauseDepth > 0) pauseDepth--; } - - + + @Override public boolean isPaused() { return pauseDepth > 0; } - - + + public PlayerFacade getPlayer() { return playerFacade; } - - + + @Override public void update(double delta) { if (isPaused()) return; - + // update console timing - not as child client console.update(delta); - + if (saveFile == null) Log.w("World has no save file."); } - - + + /** * @return world console */ @@ -220,19 +219,19 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl { return console; } - - + + /** * Set file for saving - * + * * @param file save file */ public void setSaveFile(File file) { this.saveFile = file; } - - + + /** * @return assigned file fro saving */ @@ -240,22 +239,22 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl { return saveFile; } - - + + @Override public void onGameWon() { gameOver = true; } - - + + @Override public void onPlayerKilled() { gameOver = true; } - - + + public boolean isGameOver() { return gameOver || getPlayer().isDead(); diff --git a/src/mightypork/rogue/world/WorldConsole.java b/src/mightypork/rogue/world/WorldConsole.java index 8fc4f75..377e820 100644 --- a/src/mightypork/rogue/world/WorldConsole.java +++ b/src/mightypork/rogue/world/WorldConsole.java @@ -15,222 +15,223 @@ import mightypork.utils.math.animation.NumAnimated; /** * Message log in world view - * + * * @author Ondřej Hruška (MightyPork) */ public class WorldConsole implements Updateable { - + /** Used only for display */ public Item lastPickupItem; public double timeSinceLastPickup = Integer.MAX_VALUE; - + private static final double DURATION = 5; - + public class Entry implements Updateable { - + private final String text; private final NumAnimated fadeout; private boolean fading = false; private double elapsed = 0; - - - private Entry(String text) { + + + private Entry(String text) + { this.text = text; this.fadeout = new NumAnimated(1, Easing.LINEAR); this.fadeout.setDefaultDuration(0.5); } - - + + @Override public void update(double delta) { elapsed += delta; - + if (fading) { fadeout.update(delta); return; } - + if (elapsed > DURATION) { fading = true; fadeout.fadeOut(); } } - - + + private boolean canRemove() { return fading && fadeout.isFinished(); } - - + + public double getAlpha() { return !fading ? 1 : fadeout.value(); } - - + + public String getMessage() { return text; } - - + + public double getAge() { return elapsed; } } - + private final Deque entries = new LinkedBlockingDeque<>(); - - + + @Override public void update(double delta) { for (final Iterator iter = entries.iterator(); iter.hasNext();) { final Entry e = iter.next(); - + e.update(delta); - + if (e.canRemove()) { iter.remove(); } } - + timeSinceLastPickup += delta; } - - + + public void addMessage(String message) { entries.addFirst(new Entry(message)); } - - + + public Collection getEntries() { return entries; } - - + + public void clear() { entries.clear(); } - - + + public void msgCannotPick() { addMessage("Can't collect items, inventory is full."); } - - + + public void msgDie(Entity attacker) { addMessage("You've been defeated by " + addArticle(attacker.getVisualName()) + "!"); } - - + + public void msgDiscoverSecretDoor() { addMessage("You've discovered a secret door."); } - - + + public void msgEat(Item item) { addMessage("You've eaten " + addArticle(item.getVisualName()) + "."); } - - + + public void msgEnterFloor(int floor) { addMessage("~ Floor " + (1 + floor) + " ~"); } - - + + public void msgEquipWeapon(Item item) { addMessage("You're now wielding " + (item == null ? "NOTHING" : addArticle(item.getVisualName())) + "."); } - - + + public void msgHeartPiece() { addMessage("Your health capacity has been increased."); } - - + + public void msgKill(Entity prey) { addMessage("You've killed " + addArticle(prey.getVisualName()) + "."); } - - + + public void msgNoMoreFood() { addMessage("You don't have any food!"); } - - + + public void msgNotHungry() { addMessage("You are not hungry."); } - - + + public void msgPick(Item item) { addMessage("You've picked up " + addArticle(item.getVisualName()) + "."); lastPickupItem = item; timeSinceLastPickup = 0; } - - + + public void msgDroppedItem(Item item) { addMessage("You've dropped " + addArticle(item.getVisualName()) + "."); lastPickupItem = null; } - - + + public void msgWeaponBreak(Item item) { addMessage("Your " + item.getVisualName() + " has broken!"); } - - + + public void msgWorldSaved() { addMessage("Game saved to file."); } - - + + public void msgWorldSaveError() { addMessage("Error while saving; See the log for details."); } - - + + public void msgReloaded() { addMessage("World loaded from file."); } - - + + public void msgLoadFailed() { addMessage("Error while loading; See the log for details."); } - - + + public void msgOpenChest() { addMessage("You've opened a treasure chest!"); } - - + + private String addArticle(String name) { switch (Character.toLowerCase(name.charAt(0))) { diff --git a/src/mightypork/rogue/world/WorldProvider.java b/src/mightypork/rogue/world/WorldProvider.java index 24d5c95..1264df5 100644 --- a/src/mightypork/rogue/world/WorldProvider.java +++ b/src/mightypork/rogue/world/WorldProvider.java @@ -14,50 +14,50 @@ import mightypork.utils.logging.Log; /** * Global singleton world holder and storage - * + * * @author Ondřej Hruška (MightyPork) */ public class WorldProvider extends BusNode { - + public static synchronized void init() { if (inst == null) { inst = new WorldProvider(); } } - - + + public WorldProvider() { setListening(false); } - + private static WorldProvider inst; - - + + public static WorldProvider get() { if (inst == null) { throw new IllegalStateException("World provider not initialized."); } - + return inst; } - + private World world; private final PlayerControl playerControl = new PlayerControl() { - + @Override protected World provideWorld() { return world; } }; - - + + /** * Create and register a world based on a seed - * + * * @param seed random seed * @return the world */ @@ -68,35 +68,35 @@ public class WorldProvider extends BusNode { setWorld(w); return w; } - - + + public World getWorld() { return world; } - - + + public void setWorld(World newWorld) { if (world != null) removeChildClient(world); world = newWorld; - + if (newWorld == null) return; - + addChildClient(world); } - - + + public void loadWorld(File file) throws IOException { Log.f2("Loading world from: " + file); - + final IonDataBundle bu = Ion.fromFile(file); setWorld(bu.loadBundled("world", new World())); world.setSaveFile(file); } - - + + public void saveWorld(File file) throws IOException { if (world == null) { @@ -105,44 +105,44 @@ public class WorldProvider extends BusNode { if (file == null) { throw new IllegalStateException("Trying to save world to a NULL file."); } - + if (world.isGameOver()) { throw new IllegalStateException("Cannot save, player is dead."); } - + Log.f2("Saving world to: " + file); - + final IonDataBundle bu = new IonDataBundle(); bu.put("level", world.getPlayer().getLevelNumber()); bu.putBundled("world", world); - + Ion.toFile(file, bu); } - - + + /** * Save to world's assigned save file. - * + * * @throws IOException */ public void saveWorld() throws IOException { saveWorld(world.getSaveFile()); } - - + + public Level getCurrentLevel() { return getWorld().getPlayer().getLevel(); } - - + + public PlayerFacade getPlayer() { return getWorld().getPlayer(); } - - + + /** * @return constant player control (world independent) */ @@ -150,5 +150,5 @@ public class WorldProvider extends BusNode { { return playerControl; } - + } diff --git a/src/mightypork/rogue/world/WorldRenderer.java b/src/mightypork/rogue/world/WorldRenderer.java index 4a10bf4..e3bec39 100644 --- a/src/mightypork/rogue/world/WorldRenderer.java +++ b/src/mightypork/rogue/world/WorldRenderer.java @@ -20,92 +20,93 @@ import mightypork.utils.math.constraints.vect.VectConst; /** * World rendering untility - * + * * @author Ondřej Hruška (MightyPork) */ public class WorldRenderer extends RectProxy { - + private static final boolean USE_BATCH_RENDERING = true; - + private final Num tileSize; - + // can be changed private RectConst mapRect; private Level activeLevel; - + private final Rect rightShadow; private final Rect leftShadow; private final Rect topShadow; private final Rect bottomShadow; - + private TileRenderContext trc; - - - public WorldRenderer(Rect viewport, Num tileSize) { + + + public WorldRenderer(Rect viewport, Num tileSize) + { super(viewport); - + this.tileSize = tileSize; - + final Num grX = width().perc(30); leftShadow = leftEdge().growRight(grX); rightShadow = rightEdge().growLeft(grX); - + final Num grY = height().perc(20); topShadow = topEdge().growDown(grY); bottomShadow = bottomEdge().growUp(grY); } - - + + private void prepareRenderContextIfNeeded() { final Level level = WorldProvider.get().getCurrentLevel(); - + if (activeLevel == level) return; - + activeLevel = level; - + mapRect = Rect.make(0, 0, level.getWidth(), level.getHeight()); - + trc = new TileRenderContext(activeLevel, mapRect); } - - + + private VectConst getOffset() { return Vect.make(WorldProvider.get().getPlayer().getVisualPos().neg().sub(0.5, 0.5)).freeze(); } - - + + public void render() { prepareRenderContextIfNeeded(); - + final GraphicsModule gfx = App.gfx(); - + gfx.pushGeometry(); gfx.setColor(RGB.WHITE); gfx.translate(center()); gfx.scaleXY(tileSize.value()); gfx.translate(getOffset()); - + // tiles to render - + final Coord pos = WorldProvider.get().getPlayer().getCoord(); final double w = width().value(); final double h = height().value(); - + final double ts = tileSize.value(); - + final int xtilesh = (int) (w / (ts * 2)) + 1; final int ytilesh = (int) (h / (ts * 2)) + 1; - + final int x1 = pos.x - xtilesh; final int y1 = pos.y - ytilesh; final int x2 = pos.x + xtilesh; final int y2 = pos.y + ytilesh; - + // === TILES === - + // batch rendering of the tiles // TODO // if (USE_BATCH_RENDERING) { @@ -120,32 +121,32 @@ public class WorldRenderer extends RectProxy { // if (USE_BATCH_RENDERING) { // gfx.leaveBatchTexturedQuadMode(); // } - + // === ITEMS ON TILES === - + for (trc.pos.x = x1; trc.pos.x <= x2; trc.pos.x++) { for (trc.pos.y = y1; trc.pos.y <= y2; trc.pos.y++) { trc.renderItems(); } } - + // === ENTITIES === - + for (final Entity e : activeLevel.getEntities()) { - + // avoid entities out of view rect final Vect entPos = e.pos.getVisualPos(); final int x = (int) Math.round(entPos.x()); final int y = (int) Math.round(entPos.y()); - + if (x < x1 - ts || x > x2 + ts) continue; if (y < y1 - ts || y > y2 + ts) continue; - + e.render(trc); } - + // === unexplored fog === - + // batch rendering of the tiles // TODO // if (USE_BATCH_RENDERING) { @@ -162,24 +163,24 @@ public class WorldRenderer extends RectProxy { // if (USE_BATCH_RENDERING) { // gfx.leaveBatchTexturedQuadMode(); // } - + // === OVERLAY SHADOW === - + gfx.popGeometry(); - + gfx.quad(leftShadow, new GradH(RGB.BLACK, RGB.NONE)); gfx.quad(rightShadow, new GradH(RGB.NONE, RGB.BLACK)); - + gfx.quad(topShadow, new GradV(RGB.BLACK, RGB.NONE)); gfx.quad(bottomShadow, new GradV(RGB.NONE, RGB.BLACK)); } - - + + public Vect getClickedTile(Vect clickPos) { final int ts = (int) tileSize.value(); final Vect v = clickPos.sub(center().add(getOffset().mul(ts))); return Vect.make(v.x() / ts, v.y() / ts); } - + } diff --git a/src/mightypork/rogue/world/entity/AiTimer.java b/src/mightypork/rogue/world/entity/AiTimer.java index d73baf6..c4d2ae0 100644 --- a/src/mightypork/rogue/world/entity/AiTimer.java +++ b/src/mightypork/rogue/world/entity/AiTimer.java @@ -7,16 +7,17 @@ import mightypork.utils.math.timing.TaskRepeater; public abstract class AiTimer extends TaskRepeater implements IonBundled { - - public AiTimer(double duration) { + + public AiTimer(double duration) + { super(duration); } - - + + @Override public abstract void run(); - - + + @Override public void load(IonDataBundle bundle) { @@ -26,12 +27,12 @@ public abstract class AiTimer extends TaskRepeater implements IonBundled { } else { resume(); } - + setProgress(bundle.get("progress", getProgress())); setDuration(bundle.get("duration", getDuration())); } - - + + @Override public void save(IonDataBundle bundle) { @@ -39,5 +40,5 @@ public abstract class AiTimer extends TaskRepeater implements IonBundled { bundle.put("progress", getProgress()); bundle.put("duration", getDuration()); } - + } diff --git a/src/mightypork/rogue/world/entity/Entities.java b/src/mightypork/rogue/world/entity/Entities.java index 7d7d7fd..e105156 100644 --- a/src/mightypork/rogue/world/entity/Entities.java +++ b/src/mightypork/rogue/world/entity/Entities.java @@ -14,45 +14,45 @@ import mightypork.utils.ion.IonOutput; /** * Entity registry - * + * * @author Ondřej Hruška (MightyPork) */ public final class Entities { - + private static final EntityModel[] entities = new EntityModel[256]; - + public static final EntityModel PLAYER = new EntityModel(1, EntityPlayer.class); public static final EntityModel RAT_GRAY = new EntityModel(2, EntityGrayRat.class); public static final EntityModel RAT_BROWN = new EntityModel(3, EntityBrownRat.class); public static final EntityModel RAT_BOSS = new EntityModel(4, EntityBossRat.class); - - + + public static void register(int id, EntityModel model) { if (id < 0 || id >= entities.length) { throw new IllegalArgumentException("Entity model ID " + id + " is out of range."); } - + if (entities[id] != null) { throw new IllegalArgumentException("Entity model ID " + id + " already in use."); } - + entities[id] = model; } - - + + public static EntityModel get(int id) { final EntityModel e = entities[id]; - + if (e == null) { throw new IllegalArgumentException("No entity model with ID " + id + "."); } - + return e; } - - + + public static void loadEntities(IonInput in, Collection entities) throws IOException { entities.clear(); @@ -60,34 +60,34 @@ public final class Entities { entities.add(loadEntity(in)); } } - - + + public static void saveEntities(IonOutput out, Collection entities) throws IOException { for (final Entity entity : entities) { out.startEntry(); saveEntity(out, entity); } - + out.endSequence(); } - - + + public static Entity loadEntity(IonInput in) throws IOException { final int id = in.readIntByte(); - + final EntityModel model = get(id); return model.loadEntity(in); } - - + + public static void saveEntity(IonOutput out, Entity entity) throws IOException { final EntityModel model = entity.getModel(); - + out.writeIntByte(model.id); - + model.saveEntity(out, entity); } } diff --git a/src/mightypork/rogue/world/entity/Entity.java b/src/mightypork/rogue/world/entity/Entity.java index 87f9fdf..d571fc9 100644 --- a/src/mightypork/rogue/world/entity/Entity.java +++ b/src/mightypork/rogue/world/entity/Entity.java @@ -23,83 +23,84 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; /** * World entity (mob or player). Entities are attached to the event bus. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { - + private Level level; private final EntityModel model; - + /** Entity ID */ private int entityId = -1; - + private final Map modules = new HashMap<>(); - + // default modules public final EntityModulePosition pos = new EntityModulePosition(this); public final EntityModuleHealth health = new EntityModuleHealth(this); private double despawnDelay = 1; protected Entity lastAttacker; private boolean freed; - - - public Entity(EntityModel model, int eid) { + + + public Entity(EntityModel model, int eid) + { this.entityId = eid; this.model = model; - + // register modules addModule("pos", pos); addModule("health", health); } - - + + @Override public final void save(IonDataBundle bundle) { bundle.put("eid", entityId); - + final IonDataBundle modulesBundle = new IonDataBundle(); for (final Entry entry : modules.entrySet()) { modulesBundle.putBundled(entry.getKey(), entry.getValue()); } bundle.put("modules", modulesBundle); - + final IonDataBundle extra = new IonDataBundle(); saveExtra(extra); bundle.put("extra", extra); } - - + + @Stub protected void saveExtra(IonDataBundle bundle) { } - - + + @Override public final void load(IonDataBundle bundle) { entityId = bundle.get("eid", -1); if (entityId < 0) throw new IllegalValueException("Bad entity id: " + entityId); - + final IonDataBundle modulesBundle = bundle.get("modules", new IonDataBundle()); - + for (final Entry entry : modules.entrySet()) { modulesBundle.loadBundled(entry.getKey(), entry.getValue()); } - + final IonDataBundle extra = bundle.get("extra", new IonDataBundle()); loadExtra(extra); } - - + + @Stub protected void loadExtra(IonDataBundle bundle) { } - - + + protected final void addModule(String key, EntityModule module) { if (modules.containsKey(key)) { @@ -107,8 +108,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient } modules.put(key, module); } - - + + /** * @return unique entity id */ @@ -116,53 +117,53 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { return entityId; } - - + + public void setLevel(Level level) { if (level != null && entityId < 0) { entityId = level.getWorld().getNewEID(); } - + if (level != null) level.freeTile(getCoord()); - + this.level = level; - + if (level != null) level.occupyTile(getCoord()); } - - + + public final Level getLevel() { return level; } - - + + public final World getWorld() { return level.getWorld(); } - - + + public final EntityModel getModel() { return model; } - - + + public abstract PathFinder getPathFinder(); - - + + @Stub public final void render(MapRenderContext context) { getRenderer().render(context); } - - + + protected abstract EntityRenderer getRenderer(); - - + + @Override public void update(double delta) { @@ -171,14 +172,14 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient freed = true; } } - - + + /** * @return entity type (used for AI targeting) */ public abstract EntityType getType(); - - + + /** * @return entity coord in level */ @@ -186,18 +187,18 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { return pos.getCoord(); } - - + + public void setCoord(Coord coord) { if (level != null) level.freeTile(getCoord()); - + pos.setCoord(coord); - + if (level != null) level.occupyTile(getCoord()); } - - + + /** * Called right after the entity's health reaches zero. */ @@ -205,8 +206,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient public void onKilled() { } - - + + /** * @return true if dead */ @@ -214,8 +215,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { return health.isDead(); } - - + + /** * @return whether this dead entity can be removed from level */ @@ -224,8 +225,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { return isDead() && health.getTimeSinceLastDamage() > despawnDelay; } - - + + /** * Called after the corpse has been cleaned from level. */ @@ -233,12 +234,12 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient public void onCorpseRemoved() { } - - + + /** * Receive damage from an attacker.
* The entity can decide whether to dodge, reduce damage etc. - * + * * @param attacker the entity attacking. Can be null for environmental * damage. * @param attackStrength attack strength in health points to take @@ -248,48 +249,48 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient this.lastAttacker = attacker; health.receiveDamage(attackStrength); } - - + + /** * Set how long after being killed is the corpse elligible for removal - * + * * @param despawnDelay (secs) */ public void setDespawnDelay(double despawnDelay) { this.despawnDelay = despawnDelay; } - - + + public double getDespawnDelay() { return despawnDelay; } - - + + public abstract String getVisualName(); - - + + @Override public boolean doesDelegate() { return true; } - - + + @Override public Collection getChildClients() { return modules.values(); } - - + + public Entity getLastAttacker() { return lastAttacker; } - - + + public double getLastAttackTime() { return health.getTimeSinceLastDamage(); diff --git a/src/mightypork/rogue/world/entity/EntityModel.java b/src/mightypork/rogue/world/entity/EntityModel.java index 10ea1c5..91af070 100644 --- a/src/mightypork/rogue/world/entity/EntityModel.java +++ b/src/mightypork/rogue/world/entity/EntityModel.java @@ -11,29 +11,30 @@ import mightypork.utils.ion.IonOutput; /** * Entity model - builder - * + * * @author Ondřej Hruška (MightyPork) */ public final class EntityModel { - + /** Model ID */ public final int id; public final Class tileClass; - - - public EntityModel(int id, Class entity) { + + + public EntityModel(int id, Class entity) + { Entities.register(id, this); this.id = id; this.tileClass = entity; } - - + + public Entity createEntity(World world) { return createEntity(world.getNewEID()); } - - + + public Entity createEntity(int eid) { try { @@ -42,20 +43,20 @@ public final class EntityModel { throw new RuntimeException("Could not instantiate a tile.", e); } } - - + + /** * Create entitiy without EID. EID will be assigned when the entity is added * to a level. - * + * * @return entity. */ public Entity createEntity() { return createEntity(-1); } - - + + public Entity loadEntity(IonInput in) throws IOException { final IonDataBundle bundle = in.readBundle(); @@ -63,8 +64,8 @@ public final class EntityModel { ent.load(bundle); return ent; } - - + + public void saveEntity(IonOutput out, Entity entity) throws IOException { final IonDataBundle bundle = new IonDataBundle(); diff --git a/src/mightypork/rogue/world/entity/EntityModule.java b/src/mightypork/rogue/world/entity/EntityModule.java index 38e910f..754d2cb 100644 --- a/src/mightypork/rogue/world/entity/EntityModule.java +++ b/src/mightypork/rogue/world/entity/EntityModule.java @@ -10,39 +10,40 @@ import mightypork.utils.ion.IonDataBundle; /** * Abstract entity module
* Modules make up an entity AI and behavior. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class EntityModule implements IonBundled, Updateable { - + protected final Entity entity; - - - public EntityModule(Entity entity) { + + + public EntityModule(Entity entity) + { this.entity = entity; } - - + + /** * @return whether the module should be saved into a world file */ public abstract boolean isModuleSaved(); - - + + @Override @Stub public void load(IonDataBundle bundle) { } - - + + @Override @Stub public void save(IonDataBundle bundle) { } - - + + @Override @Stub public void update(double delta) diff --git a/src/mightypork/rogue/world/entity/EntityPathFinder.java b/src/mightypork/rogue/world/entity/EntityPathFinder.java index 29a336a..5891089 100644 --- a/src/mightypork/rogue/world/entity/EntityPathFinder.java +++ b/src/mightypork/rogue/world/entity/EntityPathFinder.java @@ -12,51 +12,52 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; /** * Basic Pathfinder implementation for entities - * + * * @author Ondřej Hruška (MightyPork) */ public class EntityPathFinder extends PathFinder { - + protected final Entity entity; - - - public EntityPathFinder(Entity entity) { + + + public EntityPathFinder(Entity entity) + { this.entity = entity; } - - + + @Override public boolean isAccessible(Coord pos) { return entity.getLevel().isWalkable(pos); } - - + + @Override public int getCost(Coord from, Coord to) { return 10; } - - + + @Override public int getMinCost() { return 10; } - - + + @Override public Heuristic getHeuristic() { return PathFinder.CORNER_HEURISTIC; } - - + + @Override public List getWalkSides() { return Moves.CARDINAL_SIDES; } - + } diff --git a/src/mightypork/rogue/world/entity/EntityRenderer.java b/src/mightypork/rogue/world/entity/EntityRenderer.java index 43144ec..80670db 100644 --- a/src/mightypork/rogue/world/entity/EntityRenderer.java +++ b/src/mightypork/rogue/world/entity/EntityRenderer.java @@ -6,11 +6,11 @@ import mightypork.rogue.world.level.render.MapRenderContext; /** * Entity renderer - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class EntityRenderer { - + public abstract void render(MapRenderContext context); - + } diff --git a/src/mightypork/rogue/world/entity/EntityType.java b/src/mightypork/rogue/world/entity/EntityType.java index 9e07b92..fa94e7d 100644 --- a/src/mightypork/rogue/world/entity/EntityType.java +++ b/src/mightypork/rogue/world/entity/EntityType.java @@ -3,7 +3,7 @@ package mightypork.rogue.world.entity; /** * Type of an entity - * + * * @author Ondřej Hruška (MightyPork) */ public enum EntityType diff --git a/src/mightypork/rogue/world/entity/impl/BossRatAi.java b/src/mightypork/rogue/world/entity/impl/BossRatAi.java index 46cce11..beb76fb 100644 --- a/src/mightypork/rogue/world/entity/impl/BossRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/BossRatAi.java @@ -7,47 +7,48 @@ import mightypork.utils.math.Calc; public class BossRatAi extends GrayRatAi { - + private final AiTimer healTimer = new AiTimer(0.5) { - + @Override public void run() { entity.health.addHealth(1); // heal } }; - - - public BossRatAi(Entity entity) { + + + public BossRatAi(Entity entity) + { super(entity); - + setAttackTime(0.3); } - - + + @Override protected int getAttackStrength() { return Calc.randInt(2, 3); } - - + + @Override protected int getPreyAbandonDistance() { return Calc.randInt(12, 18); } - - + + @Override public void update(double delta) { super.update(delta); - + healTimer.update(delta); } - - + + @Override protected double getStepTime() { diff --git a/src/mightypork/rogue/world/entity/impl/BrownRatAi.java b/src/mightypork/rogue/world/entity/impl/BrownRatAi.java index 39b9f3a..5b79d3b 100644 --- a/src/mightypork/rogue/world/entity/impl/BrownRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/BrownRatAi.java @@ -6,36 +6,37 @@ import mightypork.utils.math.Calc; public class BrownRatAi extends GrayRatAi { - - public BrownRatAi(Entity entity) { + + public BrownRatAi(Entity entity) + { super(entity); - + setAttackTime(1.2); setScanTime(1.3); } - - + + @Override protected double getScanRadius() { return isIdle() ? Calc.randInt(2, 4) : Calc.randInt(5, 8); } - - + + @Override protected int getAttackStrength() { return Calc.randInt(2, 4); } - - + + @Override protected int getPreyAbandonDistance() { return Calc.randInt(7, 12); } - - + + @Override protected double getStepTime() { diff --git a/src/mightypork/rogue/world/entity/impl/EntityBossRat.java b/src/mightypork/rogue/world/entity/impl/EntityBossRat.java index f39317a..f9dca09 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityBossRat.java +++ b/src/mightypork/rogue/world/entity/impl/EntityBossRat.java @@ -13,62 +13,63 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; public class EntityBossRat extends Entity { - + private EntityRenderer renderer; - + /** Navigation PFC */ private final PathFinder pathf = new EntityPathFinder(this); - + private final BossRatAi ai = new BossRatAi(this); - - - public EntityBossRat(EntityModel model, int eid) { + + + public EntityBossRat(EntityModel model, int eid) + { super(model, eid); - + addModule("ai", ai); pos.addMoveListener(ai); - + setDespawnDelay(1); - + health.setHealthMax(80); health.setHealth(80); health.setHitCooldownTime(0.33); } - - + + @Override protected EntityRenderer getRenderer() { if (renderer == null) { renderer = new EntityRendererMobLR(this, "sprite.rat.boss"); } - + return renderer; } - - + + @Override public EntityType getType() { return EntityType.MONSTER; } - - + + @Override public PathFinder getPathFinder() { return pathf; } - - + + @Override public void onKilled() { // send kill event to listeners, after the entity has despawned (disappeared) App.bus().sendDelayed(new GameWinEvent(), getDespawnDelay() * 1.5); // dramatic pause } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/entity/impl/EntityBrownRat.java b/src/mightypork/rogue/world/entity/impl/EntityBrownRat.java index 080e792..9667fd6 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityBrownRat.java +++ b/src/mightypork/rogue/world/entity/impl/EntityBrownRat.java @@ -13,69 +13,70 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; public class EntityBrownRat extends Entity { - + private EntityRenderer renderer; - + private final PathFinder pathf = new EntityPathFinder(this); - + private final BrownRatAi ai = new BrownRatAi(this); - - - public EntityBrownRat(EntityModel model, int eid) { + + + public EntityBrownRat(EntityModel model, int eid) + { super(model, eid); - + addModule("ai", ai); pos.addMoveListener(ai); - + setDespawnDelay(1); - + health.setHealthMax(16); health.setHealth(Calc.randInt(10, 16)); // tougher to kill } - - + + @Override protected EntityRenderer getRenderer() { if (renderer == null) { renderer = new EntityRendererMobLR(this, "sprite.rat.brown"); } - + return renderer; } - - + + @Override public EntityType getType() { return EntityType.MONSTER; } - - + + @Override public PathFinder getPathFinder() { return pathf; } - - + + @Override public void onKilled() { // drop rat stuff - + if (Calc.rand.nextInt(2) != 0) { getLevel().dropNear(getCoord(), Items.MEAT.createItem()); return; } - + if (Calc.rand.nextInt(3) == 0) { getLevel().dropNear(getCoord(), Items.CHEESE.createItem()); return; } } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/entity/impl/EntityGrayRat.java b/src/mightypork/rogue/world/entity/impl/EntityGrayRat.java index 6efe03a..caceefd 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityGrayRat.java +++ b/src/mightypork/rogue/world/entity/impl/EntityGrayRat.java @@ -13,74 +13,75 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; public class EntityGrayRat extends Entity { - + private final PathFinder pathf = new EntityPathFinder(this); - + private final GrayRatAi ai = new GrayRatAi(this); - + private EntityRenderer renderer; - - - public EntityGrayRat(EntityModel model, int eid) { + + + public EntityGrayRat(EntityModel model, int eid) + { super(model, eid); - + addModule("ai", ai); pos.addMoveListener(ai); - + setDespawnDelay(1); - + health.setHealthMax(7); health.setHealth(Calc.randInt(4, 7)); } - - + + @Override public PathFinder getPathFinder() { return pathf; } - - + + @Override public EntityType getType() { return EntityType.MONSTER; } - - + + @Override protected EntityRenderer getRenderer() { if (renderer == null) { renderer = new EntityRendererMobLR(this, "sprite.rat.gray"); } - + return renderer; } - - + + @Override public void onKilled() { // drop rat stuff - + if (Calc.rand.nextInt(6) == 0) { getLevel().dropNear(getCoord(), Items.BONE.createItemDamaged(40)); return; } - + if (Calc.rand.nextInt(3) == 0) { getLevel().dropNear(getCoord(), Items.CHEESE.createItem()); return; } - + if (Calc.rand.nextInt(3) == 0) { getLevel().dropNear(getCoord(), Items.MEAT.createItem()); return; } } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/entity/impl/EntityPlayer.java b/src/mightypork/rogue/world/entity/impl/EntityPlayer.java index 1ef14c6..c4c0d9d 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityPlayer.java +++ b/src/mightypork/rogue/world/entity/impl/EntityPlayer.java @@ -2,7 +2,12 @@ package mightypork.rogue.world.entity.impl; import mightypork.gamecore.core.App; -import mightypork.rogue.world.entity.*; +import mightypork.rogue.world.entity.Entity; +import mightypork.rogue.world.entity.EntityModel; +import mightypork.rogue.world.entity.EntityModule; +import mightypork.rogue.world.entity.EntityPathFinder; +import mightypork.rogue.world.entity.EntityRenderer; +import mightypork.rogue.world.entity.EntityType; import mightypork.rogue.world.entity.modules.EntityMoveListener; import mightypork.rogue.world.entity.render.EntityRendererMobLR; import mightypork.rogue.world.events.PlayerKilledEvent; @@ -14,31 +19,32 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; public class EntityPlayer extends Entity { - + class PlayerAi extends EntityModule implements EntityMoveListener { - - public PlayerAi(Entity entity) { + + public PlayerAi(Entity entity) + { super(entity); setDespawnDelay(2); - + health.setHealthMax(6); // 3 hearts health.fill(); // fill health bar to max health.setHitCooldownTime(0.5); } - - + + @Override public void onStepFinished() { entity.getLevel().explore(entity.pos.getCoord()); fireEvt(); - + // try to pickup items - + final Tile t = getLevel().getTile(getCoord()); if (t.hasItem()) { final Item item = t.pickItem(); - + if (item.pickUp(getWorld().getPlayer())) { // player picked item } else { @@ -46,101 +52,102 @@ public class EntityPlayer extends Entity { } } } - - + + @Override public void onPathFinished() { fireEvt(); } - - + + @Override public void onPathInterrupted() { } - - + + private void fireEvt() { App.bus().send(new PlayerStepEndEvent(EntityPlayer.this)); } - - + + @Override public boolean isModuleSaved() { return false; } - + } - + private PathFinder pathf; private EntityRenderer renderer; - + private final PlayerAi ai = new PlayerAi(this); - - - public EntityPlayer(EntityModel model, int eid) { + + + public EntityPlayer(EntityModel model, int eid) + { super(model, eid); - + pos.setStepTime(0.25); - + addModule("ai", ai); pos.addMoveListener(ai); } - - + + @Override public PathFinder getPathFinder() { if (pathf == null) { pathf = new EntityPathFinder(this) { - + @Override public int getCost(Coord from, Coord to) { if (!getLevel().getTile(pos.getCoord()).isExplored()) { return 1000; // avoid unexplored, but allow them if there's no other way } - + return super.getCost(from, to); } }; } - + return pathf; } - - + + @Override protected EntityRenderer getRenderer() { if (renderer == null) { renderer = new EntityRendererMobLR(this, "sprite.player"); } - + return renderer; } - - + + @Override public EntityType getType() { return EntityType.PLAYER; } - - + + @Override public void onKilled() { // send kill event to listeners, after the entity has despawned (disappeared) App.bus().sendDelayed(new PlayerKilledEvent(), getDespawnDelay()); - + getWorld().getConsole().msgDie(lastAttacker); } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/entity/impl/GrayRatAi.java b/src/mightypork/rogue/world/entity/impl/GrayRatAi.java index 8fbb4b0..a427f85 100644 --- a/src/mightypork/rogue/world/entity/impl/GrayRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/GrayRatAi.java @@ -6,43 +6,44 @@ import mightypork.utils.math.Calc; public class GrayRatAi extends MonsterAi { - - public GrayRatAi(Entity entity) { + + public GrayRatAi(Entity entity) + { super(entity); - + setAttackTime(1.2); setScanTime(1.5); } - - + + @Override protected double getScanRadius() { return isIdle() ? Calc.randInt(2, 3) : Calc.randInt(4, 6); } - - + + @Override protected double getAttackDistance() { return 1.1; } - - + + @Override protected int getAttackStrength() { return Calc.randInt(1, 2); } - - + + @Override protected int getPreyAbandonDistance() { return Calc.randInt(7, 11); } - - + + @Override protected double getStepTime() { diff --git a/src/mightypork/rogue/world/entity/impl/MonsterAi.java b/src/mightypork/rogue/world/entity/impl/MonsterAi.java index d99c910..cab8ac4 100644 --- a/src/mightypork/rogue/world/entity/impl/MonsterAi.java +++ b/src/mightypork/rogue/world/entity/impl/MonsterAi.java @@ -20,11 +20,11 @@ import mightypork.utils.math.algo.pathfinding.PathFinderProxy; public class MonsterAi extends EntityModule implements EntityMoveListener { - + private boolean chasing = false; - + private final AiTimer timerFindPrey = new AiTimer(3) { - + @Override public void run() { @@ -32,143 +32,144 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { lookForTarget(); } }; - + private final AiTimer timerAttack = new AiTimer(1) { - + @Override public void run() { if (!isChasing()) return; - + final Entity prey = getPreyEntity(); - + if (prey == null || prey.isDead()) return; - + attackPrey(prey); } }; - + private final AiTimer timerRandomWalk = new AiTimer(0.2) { - + @Override public void run() { if (!isIdle()) return; - + // annoyed by attacking. if (entity.getLastAttackTime() < 0.5) { lookForTarget(); return; } - + if (entity.pos.isMoving()) return; - + if (Calc.rand.nextInt(10) == 0) { entity.pos.addStep(Moves.randomCardinal()); } } }; - + private PathFinder noDoorPf; - + /** Prey id */ private int preyId = -1; - - - public MonsterAi(final Entity entity) { + + + public MonsterAi(final Entity entity) + { super(entity); - + noDoorPf = new PathFinderProxy(entity.getPathFinder()) { - + @Override public boolean isAccessible(Coord pos) { final Tile t = entity.getLevel().getTile(pos); if (t.isDoor()) return false; - + return super.isAccessible(pos); } - + }; - + noDoorPf.setIgnoreEnd(true); - + timerAttack.start(); timerFindPrey.start(); } - - + + @Override public void onStepFinished() { if (entity.isDead()) return; - + if (isChasing()) { final Entity prey = getPreyEntity(); if (!isPreyValid(prey)) { stopChasing(); return; } - + if (!isPreyInAttackRange(prey)) { stepTowardsPrey(prey); } } } - - + + @Override public void onPathFinished() { } - - + + @Override public void onPathInterrupted() { } - - + + @Override public void save(IonDataBundle bundle) { bundle.putBundled("tscan", timerFindPrey); bundle.putBundled("tattack", timerAttack); - + bundle.put("chasing", chasing); - + bundle.put("prey", preyId); } - - + + @Override public void load(IonDataBundle bundle) { bundle.loadBundled("tscan", timerFindPrey); bundle.loadBundled("tattack", timerAttack); - + chasing = bundle.get("chasing", chasing); - + preyId = bundle.get("prey", preyId); } - - + + @Override public boolean isModuleSaved() { return true; } - - + + @Override public void update(double delta) { if (entity.isDead()) return; - + timerFindPrey.update(delta); timerAttack.update(delta); timerRandomWalk.update(delta); - + // go after the prey if (isChasing() && !entity.pos.isMoving()) { final Entity prey = getPreyEntity(); @@ -176,170 +177,170 @@ public class MonsterAi extends EntityModule implements EntityMoveListener { // prey killed and cleaned from level stopChasing(); } - + if (!isPreyInAttackRange(prey)) { stepTowardsPrey(prey); } } } - - + + public boolean isIdle() { return !chasing; } - - + + public boolean isChasing() { return chasing; } - - + + private void lookForTarget() { if (entity.isDead()) return; - + final Entity prey = entity.getLevel().getClosestEntity(entity.pos.getVisualPos(), EntityType.PLAYER, getScanRadius()); if (prey != null) { - + // check if reachable without leaving room final List noDoorPath = noDoorPf.findPath(entity.getCoord(), prey.getCoord()); - + if (noDoorPath == null) return; // cant reach, give up - + startChasing(prey); } } - - + + private Entity getPreyEntity() { return entity.getLevel().getEntity(preyId); } - - + + private boolean isPreyInAttackRange(Entity prey) { return prey.getCoord().dist(entity.getCoord()) <= getAttackDistance(); } - - + + private boolean isPreyValid(Entity prey) { return prey != null && !prey.isDead(); } - - + + private void startChasing(Entity prey) { if (entity.isDead()) return; - + preyId = prey.getEntityId(); chasing = true; - + entity.pos.setStepTime(getStepTime()); - + // follow this one prey timerFindPrey.pause(); - + onStepFinished(); // go towards prey } - - + + private void stopChasing() { chasing = false; - + entity.pos.setStepTime(getStepTime()); - + preyId = -1; timerFindPrey.restart(); } - - + + private List getPathToPrey(Entity prey) { if (!isPreyValid(prey)) return null; - + return entity.getPathFinder().findPathRelative(entity.getCoord(), prey.getCoord(), false, true); } - - + + private void stepTowardsPrey(Entity prey) { if (entity.isDead()) return; - + if (!isPreyValid(prey)) return; - + // if close enough if (isPreyInAttackRange(prey)) { // attack using the timed loop return; } - + final List preyPath = getPathToPrey(prey); - + if (preyPath == null || preyPath.size() > getPreyAbandonDistance()) { stopChasing(); return; } - + entity.pos.cancelPath(); entity.pos.addSteps(preyPath); } - - + + private void attackPrey(Entity prey) { if (entity.isDead()) return; - + if (!isPreyInAttackRange(prey)) return; - + prey.receiveAttack(entity, getAttackStrength()); } - - + + protected void setAttackTime(double secs) { timerAttack.setDuration(secs); } - - + + protected void setScanTime(double secs) { timerFindPrey.setDuration(secs); } - - + + @Stub protected double getScanRadius() { return isIdle() ? Calc.randInt(1, 3) : Calc.randInt(4, 8); // For override } - - + + @Stub protected int getPreyAbandonDistance() { return Calc.randInt(5, 8); // For override } - - + + @Stub protected double getAttackDistance() { return 1; } - - + + @Stub protected int getAttackStrength() { return 1; // For override } - - + + @Stub protected double getStepTime() { diff --git a/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java b/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java index fecc629..afab649 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java @@ -9,19 +9,20 @@ import mightypork.utils.math.Calc; public class EntityModuleHealth extends EntityModule { - - public EntityModuleHealth(Entity entity) { + + public EntityModuleHealth(Entity entity) + { super(entity); } - + protected int health = 1; protected int maxHealth = 1; private double hitCooldownTime = 0.36; protected boolean dead = false; - + private double timeSinceLastDamage = Integer.MAX_VALUE; - - + + @Override public void load(IonDataBundle bundle) { @@ -29,8 +30,8 @@ public class EntityModuleHealth extends EntityModule { maxHealth = bundle.get("max_health", maxHealth); dead = bundle.get("dead", dead); } - - + + @Override public void save(IonDataBundle bundle) { @@ -38,86 +39,86 @@ public class EntityModuleHealth extends EntityModule { bundle.put("max_health", maxHealth); bundle.put("dead", dead); } - - + + @Override public boolean isModuleSaved() { return true; } - - + + public int getHealth() { return health; } - - + + public void setHealth(int health) { - + this.health = Calc.clamp(health, 0, maxHealth); - + if (health <= 0) { setDead(true); entity.onKilled(); } } - - + + public int getHealthMax() { return maxHealth; } - - + + public void setHealthMax(int maxHealth) { if (maxHealth <= 0) throw new IllegalValueException("Max health out of allowed range: " + maxHealth); this.maxHealth = maxHealth; } - - + + public boolean isDead() { return dead; } - - + + public void setDead(boolean dead) { this.dead = dead; } - - + + public void receiveDamage(int attackStrength) { if (timeSinceLastDamage < hitCooldownTime) return; - + setHealth(health - attackStrength); timeSinceLastDamage = 0; } - - + + public void addHealth(int healthPoints) { setHealth(health + healthPoints); } - - + + public void fill() { setHealth(maxHealth); } - - + + @Override public void update(double delta) { if (timeSinceLastDamage < 3600) timeSinceLastDamage += delta; } - - + + /** * @return seconds since last attack received (can be used for rendering) */ @@ -125,11 +126,11 @@ public class EntityModuleHealth extends EntityModule { { return timeSinceLastDamage; } - - + + /** * Set how long after hit another hit can be received. - * + * * @param secs */ public void setHitCooldownTime(double secs) diff --git a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java index c7bb5c5..cb31df4 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java @@ -16,27 +16,28 @@ import mightypork.utils.math.constraints.vect.VectConst; public class EntityModulePosition extends EntityModule { - + /** Last pos, will be freed upon finishing move */ private Coord lastPos = new Coord(0, 0); private boolean walking = false; - + private final Queue path = new LinkedList<>(); private final EntityPos entityPos = new EntityPos(); private double stepTime = 0.5; - + // marks for simple renderers public int lastXDir = 1; public int lastYDir = 1; - + private final Set moveListeners = new LinkedHashSet<>(); - - - public EntityModulePosition(Entity entity) { + + + public EntityModulePosition(Entity entity) + { super(entity); } - - + + @Override public void save(IonDataBundle bundle) { @@ -45,43 +46,43 @@ public class EntityModulePosition extends EntityModule { bundle.putBundled("pos", entityPos); bundle.put("step_time", stepTime); } - - + + @Override public void load(IonDataBundle bundle) { bundle.loadSequence("path", path); lastPos = bundle.get("lpos", lastPos); bundle.loadBundled("pos", entityPos); - + stepTime = bundle.get("step_time", stepTime); } - - + + @Override public boolean isModuleSaved() { return true; } - - + + /** * Set coord without animation - * + * * @param coord coord */ public void setCoord(Coord coord) { freeTile(); // release old tile - + entityPos.setTo(coord); lastPos.setTo(coord); cancelPath(); // discard remaining steps - + occupyTile(); } - - + + /** * Occupy current tile in level */ @@ -91,8 +92,8 @@ public class EntityModulePosition extends EntityModule { entity.getLevel().occupyTile(getCoord()); } } - - + + /** * free current tile in level */ @@ -102,8 +103,8 @@ public class EntityModulePosition extends EntityModule { entity.getLevel().freeTile(getCoord()); } } - - + + /** * @param delta delta time */ @@ -111,47 +112,47 @@ public class EntityModulePosition extends EntityModule { public void update(double delta) { if (entity.isDead()) return; // corpses dont walk - + if (!entityPos.isFinished()) { entityPos.update(delta); } - + if (walking && entityPos.isFinished()) { walking = false; - + for (final EntityMoveListener l : moveListeners) { l.onStepFinished(); } - + if (path.isEmpty()) { for (final EntityMoveListener l : moveListeners) { l.onPathFinished(); } } } - + if (!walking && !path.isEmpty()) { - + walking = true; - + final Move step = path.poll(); - + final Coord planned = entityPos.getCoord().add(step.toCoord()); - + if (!entity.getLevel().isWalkable(planned)) { cancelPath(); - + for (final EntityMoveListener l : moveListeners) { l.onPathInterrupted(); } - + walking = false; } else { - + // tmp for renderer if (step.x() != 0) this.lastXDir = step.x(); if (step.y() != 0) this.lastYDir = step.y(); - + freeTile(); lastPos.setTo(entityPos.getCoord()); entityPos.walk(step, stepTime); @@ -159,8 +160,8 @@ public class EntityModulePosition extends EntityModule { } } } - - + + /** * @return true if path buffer is empty */ @@ -168,21 +169,21 @@ public class EntityModulePosition extends EntityModule { { return entityPos.isFinished() && path.isEmpty(); } - - + + /** * Add a step to path buffer - * + * * @param step */ public void addStep(Move step) { if (path.isEmpty() && !canGoTo(step)) return; - + path.add(step); } - - + + /** * Discard steps in buffer */ @@ -190,11 +191,11 @@ public class EntityModulePosition extends EntityModule { { path.clear(); } - - + + /** * Find path to - * + * * @param target * @return path found */ @@ -202,36 +203,36 @@ public class EntityModulePosition extends EntityModule { { if (target.equals(getCoord())) return true; final List newPath = entity.getPathFinder().findPathRelative(entityPos.getCoord(), target); - + if (newPath == null) return false; cancelPath(); addSteps(newPath); return true; } - - + + /** * Add a move listener. If already present, do nothing. - * + * * @param listener the listener */ public void addMoveListener(EntityMoveListener listener) { moveListeners.add(listener); } - - + + /** * Add steps to path buffer - * + * * @param path steps */ public void addSteps(List path) { this.path.addAll(path); } - - + + /** * @return coord in level */ @@ -239,19 +240,19 @@ public class EntityModulePosition extends EntityModule { { return entityPos.getCoord(); } - - + + /** * Set step time (seconds) - * + * * @param stepTime step time */ public void setStepTime(double stepTime) { this.stepTime = stepTime; } - - + + /** * @return step progress 0..1 */ @@ -259,8 +260,8 @@ public class EntityModulePosition extends EntityModule { { return entityPos.getProgress(); } - - + + /** * @return visual pos in level; interpolated from last to new coord */ @@ -268,29 +269,29 @@ public class EntityModulePosition extends EntityModule { { return entityPos.getVisualPos(); } - - + + public boolean isMoving() { return walking; } - - + + public boolean hasPath() { return isMoving() || !path.isEmpty(); } - - + + public boolean canGoTo(Move side) { return entity.getPathFinder().isAccessible(getCoord().add(side)); } - - + + public Coord getLastPos() { return lastPos; } - + } diff --git a/src/mightypork/rogue/world/entity/modules/EntityMoveListener.java b/src/mightypork/rogue/world/entity/modules/EntityMoveListener.java index c5701d4..f305e5f 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityMoveListener.java +++ b/src/mightypork/rogue/world/entity/modules/EntityMoveListener.java @@ -2,22 +2,22 @@ package mightypork.rogue.world.entity.modules; public interface EntityMoveListener { - + /** * One step of a path finished */ void onStepFinished(); - - + + /** * Scheduled path finished */ void onPathFinished(); - - + + /** * Path was interrupted (bumped into a wall or entity) */ void onPathInterrupted(); - + } diff --git a/src/mightypork/rogue/world/entity/modules/EntityPos.java b/src/mightypork/rogue/world/entity/modules/EntityPos.java index 0106475..db4cb08 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityPos.java +++ b/src/mightypork/rogue/world/entity/modules/EntityPos.java @@ -14,142 +14,145 @@ import mightypork.utils.math.constraints.vect.VectConst; /** * Entity position - * + * * @author Ondřej Hruška (MightyPork) */ class EntityPos implements IonBundled, Updateable { - + private Coord coord = new Coord(0, 0); private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR); - - - public EntityPos(Coord pos) { + + + public EntityPos(Coord pos) + { this.coord.setTo(pos); } - - - public EntityPos(int x, int y) { + + + public EntityPos(int x, int y) + { this.coord.setTo(x, y); } - - - public EntityPos() { + + + public EntityPos() + { } - - + + public double getProgress() { return walkOffset.getProgress(); } - - + + @Override public void load(IonDataBundle in) { coord = in.get("pos", coord); walkOffset.reset(); } - - + + @Override public void save(IonDataBundle out) { out.put("pos", coord); } - - + + public int x() { return coord.x; } - - + + public int y() { return coord.y; } - - + + public double visualX() { return coord.x + walkOffset.x(); } - - + + public double visualY() { return coord.y + walkOffset.y(); } - - + + public double visualXOffset() { return walkOffset.x(); } - - + + public double visualYOffset() { return walkOffset.y(); } - - + + public void setTo(int x, int y) { coord.setTo(x, y); walkOffset.reset(); } - - + + public void setTo(EntityPos pos) { - + setTo(pos.getCoord()); - + } - - + + public void setTo(Coord c) { coord.setTo(c); walkOffset.reset(); } - - + + @Override public String toString() { return "EntityPos{" + coord + "}"; } - - + + public void walk(Move step, double secs) { setTo(coord.x + step.x(), coord.y + step.y()); walkOffset.setTo(-step.x(), -step.y()); walkOffset.animate(0, 0, 0, secs); } - - + + @Override public void update(double delta) { walkOffset.update(delta); } - - + + public boolean isFinished() { return walkOffset.isFinished(); } - - + + public Coord getCoord() { return coord; } - - + + @Override public int hashCode() { @@ -158,8 +161,8 @@ class EntityPos implements IonBundled, Updateable { result = prime * result + ((coord == null) ? 0 : coord.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { @@ -172,8 +175,8 @@ class EntityPos implements IonBundled, Updateable { } else if (!coord.equals(other.coord)) return false; return true; } - - + + public VectConst getVisualPos() { return Vect.make(walkOffset.x() + coord.x, walkOffset.y() + coord.y); diff --git a/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java b/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java index 85a069a..e654ca5 100644 --- a/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java +++ b/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java @@ -20,56 +20,57 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Renderer for a walking mob with only one strip (right sided), which is * flipped for walking left. - * + * * @author Ondřej Hruška (MightyPork) */ public class EntityRendererMobLR extends EntityRenderer { - + private final TxSheet sheet; - + protected final Entity entity; - + private final NumVar animRedVar = Num.makeVar(0); - + private final Color hue = Color.rgb(Num.ONE, animRedVar, animRedVar); - - - public EntityRendererMobLR(Entity entity, String sheetKey) { + + + public EntityRendererMobLR(Entity entity, String sheetKey) + { this.entity = entity; this.sheet = Res.getTxSheet(sheetKey); } - - + + @Override public void render(MapRenderContext context) { final double hurtTime = entity.health.getTimeSinceLastDamage(); - + TxQuad q = sheet.getQuad(Calc.frag(entity.pos.getProgress())); - + if (entity.pos.lastXDir == -1) q = q.flipX(); - + final Rect tileRect = context.getRectForTile(entity.pos.getCoord()); final double w = tileRect.width().value(); final Vect visualPos = entity.pos.getVisualPos(); - + final double hurtOffset = (1 - Calc.clamp(hurtTime / 0.1, 0, 1)) * (entity.isDead() ? 0.3 : 0.05); - + Rect spriteRect = Rect.make(visualPos.x() * w, (visualPos.y() - hurtOffset) * w, w, w); spriteRect = spriteRect.shrink(w * 0.05); - + animRedVar.setTo(hurtTime / 0.3); - + App.gfx().pushGeometry(); - + App.gfx().translate(spriteRect.center()); - + if (entity.isDead()) { App.gfx().rotateZ(Calc.clamp(hurtTime / 0.3, 0, 1) * 90); } - + final double hw = spriteRect.width().half().value(); - + App.gfx().quad(Vect.ZERO.expand(hw, hw, hw, hw), q, hue.withAlpha(entity.isDead() ? 1 - Easing.CIRC_IN.get(hurtTime / entity.getDespawnDelay()) : 1)); App.gfx().popGeometry(); } diff --git a/src/mightypork/rogue/world/events/GameWinEvent.java b/src/mightypork/rogue/world/events/GameWinEvent.java index 4d544fc..8e88cfa 100644 --- a/src/mightypork/rogue/world/events/GameWinEvent.java +++ b/src/mightypork/rogue/world/events/GameWinEvent.java @@ -5,7 +5,7 @@ import mightypork.utils.eventbus.BusEvent; public class GameWinEvent extends BusEvent { - + @Override protected void handleBy(GameWinHandler handler) { diff --git a/src/mightypork/rogue/world/events/GameWinHandler.java b/src/mightypork/rogue/world/events/GameWinHandler.java index c724288..e655219 100644 --- a/src/mightypork/rogue/world/events/GameWinHandler.java +++ b/src/mightypork/rogue/world/events/GameWinHandler.java @@ -2,7 +2,7 @@ package mightypork.rogue.world.events; public interface GameWinHandler { - + void onGameWon(); - + } diff --git a/src/mightypork/rogue/world/events/PlayerDeathHandler.java b/src/mightypork/rogue/world/events/PlayerDeathHandler.java index dc3da48..91c9e10 100644 --- a/src/mightypork/rogue/world/events/PlayerDeathHandler.java +++ b/src/mightypork/rogue/world/events/PlayerDeathHandler.java @@ -2,6 +2,6 @@ package mightypork.rogue.world.events; public interface PlayerDeathHandler { - + void onPlayerKilled(); } diff --git a/src/mightypork/rogue/world/events/PlayerKilledEvent.java b/src/mightypork/rogue/world/events/PlayerKilledEvent.java index 50c00e2..95e5a32 100644 --- a/src/mightypork/rogue/world/events/PlayerKilledEvent.java +++ b/src/mightypork/rogue/world/events/PlayerKilledEvent.java @@ -6,13 +6,13 @@ import mightypork.utils.eventbus.BusEvent; public class PlayerKilledEvent extends BusEvent { - + @Override protected void handleBy(PlayerDeathHandler handler) { // not dead, discard event. if (!WorldProvider.get().getPlayer().isDead()) return; - + handler.onPlayerKilled(); } } diff --git a/src/mightypork/rogue/world/events/PlayerStepEndEvent.java b/src/mightypork/rogue/world/events/PlayerStepEndEvent.java index 910b4b8..1055de3 100644 --- a/src/mightypork/rogue/world/events/PlayerStepEndEvent.java +++ b/src/mightypork/rogue/world/events/PlayerStepEndEvent.java @@ -8,20 +8,21 @@ import mightypork.utils.eventbus.events.flags.NotLoggedEvent; @NotLoggedEvent public class PlayerStepEndEvent extends BusEvent { - + private final EntityPlayer player; - - - public PlayerStepEndEvent(EntityPlayer player) { + + + public PlayerStepEndEvent(EntityPlayer player) + { super(); this.player = player; } - - + + @Override protected void handleBy(PlayerStepEndListener handler) { handler.onStepFinished(player); } - + } diff --git a/src/mightypork/rogue/world/events/PlayerStepEndListener.java b/src/mightypork/rogue/world/events/PlayerStepEndListener.java index de5e49c..8dd4697 100644 --- a/src/mightypork/rogue/world/events/PlayerStepEndListener.java +++ b/src/mightypork/rogue/world/events/PlayerStepEndListener.java @@ -5,6 +5,6 @@ import mightypork.rogue.world.entity.impl.EntityPlayer; public interface PlayerStepEndListener { - + void onStepFinished(EntityPlayer player); } diff --git a/src/mightypork/rogue/world/events/WorldAscendRequest.java b/src/mightypork/rogue/world/events/WorldAscendRequest.java index 3a35b87..a0abb18 100644 --- a/src/mightypork/rogue/world/events/WorldAscendRequest.java +++ b/src/mightypork/rogue/world/events/WorldAscendRequest.java @@ -6,15 +6,15 @@ import mightypork.utils.eventbus.BusEvent; /** * Player wants to go up - * + * * @author Ondřej Hruška (MightyPork) */ public class WorldAscendRequest extends BusEvent { - + @Override protected void handleBy(WorldAscendRequestListener handler) { handler.onAscendRequest(); } - + } diff --git a/src/mightypork/rogue/world/events/WorldAscendRequestListener.java b/src/mightypork/rogue/world/events/WorldAscendRequestListener.java index 94ed86f..e67c969 100644 --- a/src/mightypork/rogue/world/events/WorldAscendRequestListener.java +++ b/src/mightypork/rogue/world/events/WorldAscendRequestListener.java @@ -2,7 +2,7 @@ package mightypork.rogue.world.events; public interface WorldAscendRequestListener { - + /** * Player clicked up-stairs */ diff --git a/src/mightypork/rogue/world/events/WorldDescendRequest.java b/src/mightypork/rogue/world/events/WorldDescendRequest.java index 0a18dc8..21a0f80 100644 --- a/src/mightypork/rogue/world/events/WorldDescendRequest.java +++ b/src/mightypork/rogue/world/events/WorldDescendRequest.java @@ -5,11 +5,11 @@ import mightypork.utils.eventbus.BusEvent; public class WorldDescendRequest extends BusEvent { - + @Override protected void handleBy(WorldDescendRequestListener handler) { handler.onDescendRequest(); } - + } diff --git a/src/mightypork/rogue/world/events/WorldDescendRequestListener.java b/src/mightypork/rogue/world/events/WorldDescendRequestListener.java index a71a496..59ffc58 100644 --- a/src/mightypork/rogue/world/events/WorldDescendRequestListener.java +++ b/src/mightypork/rogue/world/events/WorldDescendRequestListener.java @@ -2,7 +2,7 @@ package mightypork.rogue.world.events; public interface WorldDescendRequestListener { - + /** * Player clicked down-stairs */ diff --git a/src/mightypork/rogue/world/events/WorldPauseRequest.java b/src/mightypork/rogue/world/events/WorldPauseRequest.java index cb1ac19..e452da9 100644 --- a/src/mightypork/rogue/world/events/WorldPauseRequest.java +++ b/src/mightypork/rogue/world/events/WorldPauseRequest.java @@ -7,25 +7,26 @@ import mightypork.utils.eventbus.BusEvent; /** * Toggle world pause state - * + * * @author Ondřej Hruška (MightyPork) */ public class WorldPauseRequest extends BusEvent { - + public static enum PauseAction { PAUSE, RESUME, TOGGLE; } - + private final PauseAction op; - - - public WorldPauseRequest(PauseAction op) { + + + public WorldPauseRequest(PauseAction op) + { super(); this.op = op; } - - + + @Override protected void handleBy(World handler) { @@ -33,14 +34,14 @@ public class WorldPauseRequest extends BusEvent { handler.pause(); return; } - + if (op == PauseAction.RESUME) { handler.resume(); return; } - + // else - + // toggle paused state if (!handler.isPaused()) { handler.pause(); @@ -48,5 +49,5 @@ public class WorldPauseRequest extends BusEvent { handler.resume(); } } - + } diff --git a/src/mightypork/rogue/world/gen/LevelBuilder.java b/src/mightypork/rogue/world/gen/LevelBuilder.java index 261983e..f74e6e0 100644 --- a/src/mightypork/rogue/world/gen/LevelBuilder.java +++ b/src/mightypork/rogue/world/gen/LevelBuilder.java @@ -16,78 +16,82 @@ import mightypork.utils.math.algo.Coord; public class LevelBuilder { - + public static enum BuildOrder { FIRST, MIDDLE, LAST } - + private class RoomEntry { - + int count; RoomBuilder room; boolean important; - - - public RoomEntry(RoomBuilder room, int count, boolean important) { + + + public RoomEntry(RoomBuilder room, int count, boolean important) + { this.count = count; this.room = room; this.important = important; } } - + private class ItemEntry { - + Item item; boolean important; - - - public ItemEntry(Item item, boolean important) { + + + public ItemEntry(Item item, boolean important) + { this.item = item; this.important = important; } } - + private class EntityEntry { - + Entity entity; boolean important; - - - public EntityEntry(Entity item, boolean important) { + + + public EntityEntry(Entity item, boolean important) + { this.entity = item; this.important = important; } } - + private final ScratchMap map; private final Random rand; private boolean built; - + private final LinkedList roomsFirst = new LinkedList<>(); private final LinkedList roomsMiddle = new LinkedList<>(); private final LinkedList roomsLast = new LinkedList<>(); - + private final LinkedList items = new LinkedList<>(); private final LinkedList entities = new LinkedList<>(); - - + + /** * make a new level builder instance. - * + * * @param max_size max map size (square side - tiles) * @param theme tiles theme * @param seed level seed */ - public LevelBuilder(int max_size, MapTheme theme, long seed) { + public LevelBuilder(int max_size, MapTheme theme, long seed) + { this.rand = new Random(seed); this.map = new ScratchMap(max_size, theme, rand); } - - + + /** * Add a single room to the room buffer. - * + * * @param room room builder * @param order build order * @param important try harder and throw error on fail @@ -96,11 +100,11 @@ public class LevelBuilder { { addRoom(room, Range.make(1, 1), order, important); } - - + + /** * Add multiple rooms of the type to the room buffer. - * + * * @param room room builder * @param count number of rooms to build * @param order build order @@ -109,94 +113,94 @@ public class LevelBuilder { public void addRoom(RoomBuilder room, Range count, BuildOrder order, boolean important) { final List list; - + switch (order) { case FIRST: list = roomsFirst; break; - + default: case MIDDLE: list = roomsMiddle; break; - + case LAST: list = roomsLast; break; } - + list.add(new RoomEntry(room, count.randInt(rand), important)); } - - + + private void buildRooms(LinkedList list) { while (!list.isEmpty()) { - + Collections.shuffle(list, rand); - + for (final Iterator iter = list.iterator(); iter.hasNext();) { final RoomEntry rge = iter.next(); - + map.addRoom(rge.room, rge.important); - + if ((--rge.count) <= 0) { iter.remove(); } } } } - - + + private void buildCorridors() throws WorldGenError { map.buildCorridors(); } - - + + private void buildEntities() { for (final EntityEntry entry : entities) { final int tries = entry.important ? 200 : 50; final boolean success = map.addEntityInMap(entry.entity, tries); - + if (entry.important && !success) { throw new WorldGenError("Could not place an important entity: " + entry.entity); } } } - - + + private void buildItems() { for (final ItemEntry entry : items) { final int tries = entry.important ? 200 : 50; final boolean success = map.addItemInMap(entry.item, tries); - + if (entry.important && !success) { throw new WorldGenError("Could not place an important item: " + entry.item); } } } - - + + private void writeToMap() { buildRooms(roomsFirst); buildRooms(roomsMiddle); buildRooms(roomsLast); buildCorridors(); - + map.fixGlitches(); - + buildItems(); buildEntities(); } - - + + /** * Write to a new level instance. - * + * * @param world level's world * @return the level * @throws WorldGenError on error in generation @@ -207,22 +211,22 @@ public class LevelBuilder { throw new WorldGenError("Level already built."); } built = true; - + writeToMap(); - + final Coord size = map.getNeededSize(); final Level lvl = new Level(size.x, size.y); lvl.setWorld(world); // important for creating entities - + map.writeToLevel(lvl); - + return lvl; } - - + + /** * Add an item to be added to the level when tiles are built. - * + * * @param item item to add * @param important try harder and throw error on fail * @throws WorldGenError on fail @@ -231,12 +235,12 @@ public class LevelBuilder { { items.add(new ItemEntry(item, important)); } - - + + /** * Add an entity to be added to the level when tiles are built.
* It's EID will be assigned during writing to level. - * + * * @param entity entity to add * @param important try harder and throw error on fail * @throws WorldGenError on fail @@ -245,5 +249,5 @@ public class LevelBuilder { { entities.add(new EntityEntry(entity, important)); } - + } diff --git a/src/mightypork/rogue/world/gen/MapTheme.java b/src/mightypork/rogue/world/gen/MapTheme.java index 301e93f..fa9db96 100644 --- a/src/mightypork/rogue/world/gen/MapTheme.java +++ b/src/mightypork/rogue/world/gen/MapTheme.java @@ -6,31 +6,31 @@ import mightypork.rogue.world.tile.TileModel; /** * Map theme to use for building - * + * * @author Ondřej Hruška (MightyPork) */ public interface MapTheme { - + TileModel wall(); - - + + TileModel floor(); - - + + TileModel door(); - - + + TileModel passage(); - - + + TileModel secretDoor(); - - + + TileModel entrance(); - - + + TileModel exit(); - - + + TileModel chest(); } diff --git a/src/mightypork/rogue/world/gen/RoomBuilder.java b/src/mightypork/rogue/world/gen/RoomBuilder.java index 5fec41b..0e46f12 100644 --- a/src/mightypork/rogue/world/gen/RoomBuilder.java +++ b/src/mightypork/rogue/world/gen/RoomBuilder.java @@ -8,10 +8,10 @@ import mightypork.utils.math.algo.Coord; /** * Room model - * + * * @author Ondřej Hruška (MightyPork) */ public interface RoomBuilder { - + RoomEntry buildRoom(ScratchMap map, MapTheme theme, Random rand, Coord center) throws WorldGenError; } diff --git a/src/mightypork/rogue/world/gen/RoomEntry.java b/src/mightypork/rogue/world/gen/RoomEntry.java index a93af9c..043a96b 100644 --- a/src/mightypork/rogue/world/gen/RoomEntry.java +++ b/src/mightypork/rogue/world/gen/RoomEntry.java @@ -6,47 +6,48 @@ import mightypork.utils.math.algo.Coord; /** * Room description entry for {@link ScratchMap} - * + * * @author Ondřej Hruška (MightyPork) */ public class RoomEntry { - + final Coord min; final Coord max; - - - public RoomEntry(Coord min, Coord max) { + + + public RoomEntry(Coord min, Coord max) + { super(); this.min = min; this.max = max; } - - + + public boolean intersectsWith(Coord amin, Coord amax) { int tw = max.x - min.x; int th = max.y - min.y; int rw = amax.x - amin.x; int rh = amax.y - amin.y; - + if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) { return false; } - + final int tx = min.x; final int ty = min.y; final int rx = amin.x; final int ry = amin.y; - + rw += rx; rh += ry; tw += tx; th += ty; - + return ((rw <= rx || rw >= tx) && (rh <= ry || rh >= ty) && (tw <= tx || tw >= rx) && (th <= ty || th >= ry)); } - - + + @Override public String toString() { diff --git a/src/mightypork/rogue/world/gen/Rooms.java b/src/mightypork/rogue/world/gen/Rooms.java index 86a399a..f87824e 100644 --- a/src/mightypork/rogue/world/gen/Rooms.java +++ b/src/mightypork/rogue/world/gen/Rooms.java @@ -1,26 +1,33 @@ package mightypork.rogue.world.gen; -import mightypork.rogue.world.gen.rooms.*; +import mightypork.rogue.world.gen.rooms.BasicRoom; +import mightypork.rogue.world.gen.rooms.BossRoom; +import mightypork.rogue.world.gen.rooms.DeadEndRoom; +import mightypork.rogue.world.gen.rooms.EntranceRoom; +import mightypork.rogue.world.gen.rooms.ExitRoom; +import mightypork.rogue.world.gen.rooms.ItemShrineRoom; +import mightypork.rogue.world.gen.rooms.StorageRoom; +import mightypork.rogue.world.gen.rooms.TreasureChestRoom; import mightypork.rogue.world.item.Item; public class Rooms { - + public static final RoomBuilder BASIC = new BasicRoom(); public static final RoomBuilder STORAGE = new StorageRoom(); public static final RoomBuilder DEAD_END = new DeadEndRoom(); public static final RoomBuilder ENTRANCE = new EntranceRoom(); public static final RoomBuilder EXIT = new ExitRoom(); public static final RoomBuilder BOSS = new BossRoom(); - - + + public static RoomBuilder treasure(Item item) { return new TreasureChestRoom(item); } - - + + public static RoomBuilder shrine(Item item) { return new ItemShrineRoom(item); diff --git a/src/mightypork/rogue/world/gen/ScratchMap.java b/src/mightypork/rogue/world/gen/ScratchMap.java index afcc70c..93f81a3 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -25,25 +25,25 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; /** * Temporary tile map used for level generation. - * + * * @author Ondřej Hruška (MightyPork) */ public class ScratchMap { - + private Tile[][] map; private final int width; private final int height; - + private final List rooms = new ArrayList<>(); - + /** Coords to connect with corridors */ private final List nodes = new ArrayList<>(); - + private final List occupied = new ArrayList<>(); private final List entities = new ArrayList<>(); - + private final PathFinder pathf = new PathFinder() { - + @Override public boolean isAccessible(Coord pos) { @@ -52,108 +52,109 @@ public class ScratchMap { if (t.isStairs()) return false; return t.isPotentiallyWalkable() || (t.genData.protection != TileProtectLevel.STRONG); } - - + + @Override public int getCost(Coord last, Coord pos) { final Tile t = getTile(pos); - + switch (t.getType()) { case NULL: return 60; - + case DOOR: case PASSAGE: return 10; - + case STAIRS: case FLOOR: return 20; - + case WALL: if (t.genData.protection != TileProtectLevel.NONE) return 2000; - + return 100; - + default: throw new WorldGenError("Unknown tile type: " + t.getType()); } } - - + + @Override public int getMinCost() { return 10; } - - + + @Override public Heuristic getHeuristic() { return PathFinder.CORNER_HEURISTIC; } - - + + @Override public List getWalkSides() { return Moves.CARDINAL_SIDES; } - + }; - + { // 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 final Coord enterPoint = new Coord(); private final Coord exitPoint = new Coord(); - + private static final boolean FIX_GLITCHES = true; - - - public ScratchMap(int max_size, MapTheme theme, Random rand) { + + + public ScratchMap(int max_size, MapTheme theme, Random rand) + { map = new Tile[max_size][max_size]; - + genMin = Coord.make((max_size / 2) - 1, (max_size / 2) - 1); genMax = genMin.add(1, 1); - + width = max_size; height = max_size; this.rand = rand; this.theme = theme; - + fill(Coord.make(0, 0), Coord.make(width - 1, height - 1), Tiles.NULL); } - - + + public void addRoom(RoomBuilder rb, boolean critical) throws WorldGenError { try { if (rooms.size() > 0) minimizeBounds(); - + final Coord roomPos = Coord.make(0, 0); - + int failed = 0; int failed_total = 0; - + while (true) { - + final int sizeX = genMax.x - genMin.x; final int sizeY = genMax.y - genMin.y; - + roomPos.x = genMin.x + rand.nextInt(sizeX + 1); roomPos.y = genMin.y + rand.nextInt(sizeY + 1); - + switch (rand.nextInt(4)) { case 0: roomPos.x += (failed_total / 35); @@ -167,47 +168,47 @@ public class ScratchMap { case 3: roomPos.y -= (failed_total / 35); } - + final RoomEntry rd = rb.buildRoom(this, theme, rand, roomPos); if (rd != null) { - + rooms.add(rd); - + genMin.x = Math.min(genMin.x, rd.min.x); genMin.y = Math.min(genMin.y, rd.min.y); - + genMax.x = Math.max(genMax.x, rd.max.x); genMax.y = Math.max(genMax.y, rd.max.y); clampBounds(); - + nodes.add(roomPos); - + return; - + } else { failed++; failed_total++; - + if (failed_total > 1000) { throw new WorldGenError("Failed to add a room."); } - + if (failed > 300) { Log.w("Faild to build room."); if (critical) { - + // expand gen bounds genMin.x -= 5; genMin.y -= 5; genMax.x += 5; genMax.y += 5; - + clampBounds(); - + failed = 0; Log.f3("Trying again."); continue; - + } else { throw new WorldGenError("Failed to add a room."); } @@ -224,8 +225,8 @@ public class ScratchMap { } } } - - + + /** * Clamp bounds to available area */ @@ -236,8 +237,8 @@ public class ScratchMap { genMax.x = Calc.clamp(genMax.x, 0, width - 1); genMax.y = Calc.clamp(genMax.y, 0, height - 1); } - - + + /** * Minimize gen bounds based on defined room bounds */ @@ -245,124 +246,124 @@ public class ScratchMap { { final Coord low = Coord.make(width, height); final Coord high = Coord.make(0, 0); - + for (final RoomEntry rd : rooms) { low.x = Math.min(low.x, rd.min.x); low.y = Math.min(low.y, rd.min.y); - + high.x = Math.max(high.x, rd.max.x); high.y = Math.max(high.y, rd.max.y); } - + genMin.setTo(low); genMax.setTo(high); } - - + + public boolean isIn(Coord pos) { return pos.x >= 0 && pos.x < width && pos.y >= 0 && pos.y < height; } - - + + public Tile getTile(Coord pos) { if (!isIn(pos)) { throw new WorldGenError("Tile not in map: " + pos); } - + return map[pos.y][pos.x]; } - - + + public boolean set(Coord pos, TileModel tm) { return set(pos, tm.createTile()); } - - + + public boolean set(Coord pos, Tile tile) { if (!isIn(pos)) { throw new WorldGenError("Tile not in map: " + pos); } - + map[pos.y][pos.x] = tile; return true; } - - + + public boolean isClear(Coord min, Coord max) { if (!isIn(min) || !isIn(max)) return false; for (final RoomEntry r : rooms) { if (r.intersectsWith(min, max)) return false; } - + return true; } - - + + public void protect(Coord pos, TileProtectLevel prot) { protect(pos, pos, prot); } - - + + public void protect(Coord min, Coord max, TileProtectLevel prot) { if (!isIn(min) || !isIn(max)) throw new WorldGenError("Tile(s) not in map: " + min + " , " + max); - + final Coord c = Coord.make(0, 0); for (c.x = min.x; c.x <= max.x; c.x++) for (c.y = min.y; c.y <= max.y; c.y++) getTile(c).genData.protection = prot; } - - + + public void fill(Coord min, Coord max, TileModel tm) { if (!isIn(min) || !isIn(max)) throw new WorldGenError("Tile(s) not in map: " + min + " , " + max); - + final Coord c = Coord.make(0, 0); for (c.x = min.x; c.x <= max.x; c.x++) for (c.y = min.y; c.y <= max.y; c.y++) set(c, tm.createTile()); } - - + + public void border(Coord min, Coord max, TileModel tm) { if (!isIn(min) || !isIn(max)) throw new WorldGenError("Tile(s) not in map: " + min + " , " + max); - + final Coord c = Coord.make(0, 0); - + // top for (c.x = min.x, c.y = min.y; c.x <= max.x; c.x++) set(c, tm.createTile()); - + //bottom for (c.x = min.x, c.y = max.y; c.x <= max.x; c.x++) set(c, tm.createTile()); - + //left for (c.x = min.x, c.y = min.y + 1; c.y < max.y; c.y++) set(c, tm.createTile()); - + //right for (c.x = max.x, c.y = min.y + 1; c.y < max.y; c.y++) set(c, tm.createTile()); - + } - - + + public void buildCorridors() { // Log.f3("Building corridors."); - + Coord start = nodes.get(0); final Set starts = new HashSet<>(); - + for (int i = 0; i < 2 + rooms.size() / 5; i++) { if (!starts.contains(start)) { for (int j = 0; j < nodes.size(); j++) { @@ -373,24 +374,24 @@ public class ScratchMap { start = Calc.pick(rand, nodes); } } - - + + private void buildCorridor(Coord node1, Coord node2) { // Log.f3("Building corridor " + node1 + " -> " + node2); final List steps = pathf.findPath(node1, node2); - + if (steps == null) { Log.w("Could not build corridor " + node1 + "->" + node2); return; } - + for (final Coord c : steps) { buildCorridorPiece(c); } } - - + + private void buildCorridorPiece(Coord pos) { final Coord c = Coord.make(0, 0); @@ -398,17 +399,17 @@ public class ScratchMap { for (i = -1, c.x = pos.x - 1; c.x <= pos.x + 1; c.x++, i++) { for (j = -1, c.y = pos.y - 1; c.y <= pos.y + 1; c.y++, j++) { if (!isIn(c)) continue; - + genMin.x = Math.min(genMin.x, c.x); genMin.y = Math.min(genMin.y, c.y); - + genMax.x = Math.max(genMax.x, c.x); genMax.y = Math.max(genMax.y, c.y); clampBounds(); - + final Tile current = getTile(c); if (!current.isNull() && (current.isPotentiallyWalkable() || current.isStairs())) continue; // floor already, let it be - + if (i == 0 && j == 0) { set(c, theme.floor()); } else { @@ -418,8 +419,8 @@ public class ScratchMap { } } } - - + + /** * @return dimensions of the area taken by non-null tiles */ @@ -427,141 +428,141 @@ public class ScratchMap { { return Coord.make(genMax.x - genMin.x + 1, genMax.y - genMin.y + 1); } - - + + public byte findWalls(Coord pos) { byte walls = 0; for (int i = 0; i < 8; i++) { final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc)) continue; - + if (getTile(cc).isWall()) { walls |= Moves.getBit(i); } } return walls; } - - + + public byte findFloors(Coord pos) { byte floors = 0; for (int i = 0; i <= 7; i++) { final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc)) continue; - + if (getTile(cc).isFloor()) { floors |= Moves.getBit(i); } } return floors; } - - + + public byte findDoors(Coord pos) { byte doors = 0; for (int i = 0; i <= 7; i++) { final Coord cc = pos.add(Moves.getSide(i)); if (!isIn(cc)) continue; - + if (getTile(cc).isDoor()) { doors |= Moves.getBit(i); } } return doors; } - - + + public byte findNils(Coord pos) { byte nils = 0; for (int i = 0; i <= 7; i++) { final Coord cc = pos.add(Moves.getSide(i)); - + if (!isIn(cc) || getTile(cc).isNull()) { nils |= Moves.getBit(i); } } return nils; } - - + + /** * Fix generator glitches and reduce size to the actual used size */ public void fixGlitches() { final Tile[][] out = new Tile[height][width]; - + // bounds will be adjusted by the actual tiles in the map genMin.x = width; genMin.y = height; genMax.x = 0; genMax.y = 0; - + final Coord c = Coord.make(0, 0); for (c.x = 0; c.x < width; c.x++) { for (c.y = 0; c.y < height; c.y++) { - + final Tile t = getTile(c); final boolean isNull = t.isNull(); - + final boolean isDoor = !isNull && t.isDoor(); final boolean isFloor = !isNull && t.isFloor(); final boolean isWall = !isNull && t.isWall(); - + // bitmasks final byte walls = findWalls(c); final byte nils = findNils(c); final byte floors = findFloors(c); - + boolean toWall = false; boolean toFloor = false; boolean toNull = false; - + do { if (isWall && floors == 0) { toNull = true; break; } - + if (isFloor && (nils & Moves.BITS_CARDINAL) != 0) { toWall = true; // floor with adjacent cardinal null break; } - + if (isNull && (floors & Moves.BITS_DIAGONAL) != 0) { toWall = true; // null with adjacent diagonal floor break; } - + if (isDoor) { - + if (Calc.countBits((byte) (floors & Moves.BITS_CARDINAL)) < 2) { toWall = true; break; } - + if (Calc.countBits((byte) (walls & Moves.BITS_CARDINAL)) > 2) { toWall = true; break; } - + if (Calc.countBits((byte) (floors & Moves.BITS_CARDINAL)) > 2) { toFloor = true; break; } - + if ((floors & Moves.BITS_NW_CORNER) == Moves.BITS_NW_CORNER) toWall = true; if ((floors & Moves.BITS_NE_CORNER) == Moves.BITS_NE_CORNER) toWall = true; if ((floors & Moves.BITS_SW_CORNER) == Moves.BITS_SW_CORNER) toWall = true; if ((floors & Moves.BITS_SE_CORNER) == Moves.BITS_SE_CORNER) toWall = true; - + } } while (false); - + if (toNull) { out[c.y][c.x] = Tiles.NULL.createTile(); } else if (toWall) { @@ -571,24 +572,24 @@ public class ScratchMap { } else { out[c.y][c.x] = map[c.y][c.x]; } - + if (!out[c.y][c.x].isNull()) { genMin.x = Math.min(genMin.x, c.x); genMin.y = Math.min(genMin.y, c.y); - + genMax.x = Math.max(genMax.x, c.x); genMax.y = Math.max(genMax.y, c.y); } } } - + map = out; } - - + + /** * Write tiles and entities into a level - * + * * @param level the level */ public void writeToLevel(Level level) @@ -596,23 +597,23 @@ public class ScratchMap { if (level.getWorld() == null) { throw new WorldGenError("Level has no world assigned."); // need for entities } - + // make sure no walkable are at edges. final Coord c = Coord.make(0, 0); final Coord c1 = Coord.make(0, 0); - + for (c.x = genMin.x, c1.x = 0; c.x <= genMax.x; c.x++, c1.x++) { for (c.y = genMin.y, c1.y = 0; c.y <= genMax.y; c.y++, c1.y++) { level.setTile(c1, getTile(c)); } } - + final Coord entrance = new Coord(enterPoint.x - genMin.x, enterPoint.y - genMin.y); level.setEnterPoint(entrance); - + final Coord exit = new Coord(exitPoint.x - genMin.x, exitPoint.y - genMin.y); level.setExitPoint(exit); - + for (final Entity e : entities) { final Coord pos = e.getCoord().add(-genMin.x, -genMin.y); if (!level.addEntityNear(e, pos)) { @@ -628,101 +629,101 @@ public class ScratchMap { } } } - - + + public void setEntrance(Coord pos) { enterPoint.setTo(pos); } - - + + public void setExit(Coord pos) { exitPoint.setTo(pos); } - - + + public boolean addItem(Item item, Coord pos) { return addItem(item, pos, true); } - - + + public boolean addItem(Item item, Coord pos, boolean canStack) { if (!isIn(pos)) return false; - + final Tile t = getTile(pos); if (!canStack && t.hasItem()) return false; if (t.dropItem(item)) return true; - + return false; } - - + + public boolean addItemInArea(Item item, Coord min, Coord max, int tries) { final Coord pos = Coord.zero(); - + for (int i = 0; i < tries / 2; i++) { pos.x = Calc.randInt(rand, min.x, max.x); pos.y = Calc.randInt(rand, min.y, max.y); if (addItem(item, pos, false)) return true; } - + for (int i = 0; i < tries - (tries / 2); i++) { pos.x = Calc.randInt(rand, min.x, max.x); pos.y = Calc.randInt(rand, min.y, max.y); if (addItem(item, pos, true)) return true; } - + return false; } - - + + public boolean addItemInMap(Item item, int tries) { return addItemInArea(item, genMin, genMax, tries); } - - + + public boolean addEntityInArea(Entity entity, Coord min, Coord max, int tries) { final Coord pos = Coord.zero(); - + for (int i = 0; i < tries; i++) { pos.x = Calc.randInt(rand, min.x, max.x); pos.y = Calc.randInt(rand, min.y, max.y); if (!isIn(pos)) continue; - + if (addEntity(entity, pos)) return true; } - + return false; } - - + + public boolean addEntityInMap(Entity entity, int tries) { return addEntityInArea(entity, genMin, genMax, tries); } - - + + public boolean addEntity(Entity entity, Coord pos) { if (!isIn(pos)) return false; - + if (pos.dist(enterPoint) < 4) return false; // protected distance. - + final Tile t = getTile(pos); if (!t.isWalkable()) return false; - + if (occupied.contains(pos)) return false; - + occupied.add(pos.copy()); entity.setCoord(pos); entities.add(entity); - + return true; } } diff --git a/src/mightypork/rogue/world/gen/WorldCreator.java b/src/mightypork/rogue/world/gen/WorldCreator.java index bb5e763..425ebe4 100644 --- a/src/mightypork/rogue/world/gen/WorldCreator.java +++ b/src/mightypork/rogue/world/gen/WorldCreator.java @@ -19,103 +19,103 @@ import mightypork.utils.math.Range; public class WorldCreator { - + public static Random rand = new Random(); - - + + public static World createWorld(long seed) { synchronized (rand) { - + Log.f2("Generating a new world..."); - + rand.setSeed(seed); final MapTheme theme = new ThemeBrick(); - + final World w = new World(); w.setSeed(seed); - + final LevelBuilder levelBuilders[] = new LevelBuilder[7]; - + // build the level rooms for (int floor = 1; floor <= 7; floor++) { - + Log.f3("Placing rooms for level: " + floor); - + final LevelBuilder lb = prepareFloor(rand.nextLong(), floor, theme, floor == 7); - + levelBuilders[floor - 1] = lb; } - + Log.f3("Placing items..."); final List weaponsBasic = new ArrayList<>(); weaponsBasic.add(Items.ROCK); weaponsBasic.add(Items.BONE); weaponsBasic.add(Items.TWIG); - + final List weaponsMedium = new ArrayList<>(); weaponsMedium.add(Items.CLUB); weaponsMedium.add(Items.KNIFE); - + final List weaponsGood = new ArrayList<>(); weaponsGood.add(Items.AXE); weaponsGood.add(Items.SWORD); - + for (int i = 0; i < Calc.randInt(rand, 12, 20); i++) { final Item item = Calc.pick(rand, weaponsBasic).createItemDamaged(40); final LevelBuilder lb = levelBuilders[-1 + Calc.randInt(1, 7)]; lb.addItem(item, false); } - + for (int i = 0; i < Calc.randInt(rand, 2, 4); i++) { final Item item = Calc.pick(rand, weaponsMedium).createItemDamaged(50); final LevelBuilder lb = levelBuilders[-1 + Calc.randInt(3, 5)]; lb.addRoom(Rooms.treasure(item), BuildOrder.MIDDLE, true); } - + for (int i = 0; i < Calc.randInt(rand, 2, 4); i++) { final Item item = Calc.pick(rand, weaponsGood).createItemDamaged(60); final LevelBuilder lb = levelBuilders[-1 + Calc.randInt(4, 7)]; - + lb.addRoom(Rooms.treasure(item), BuildOrder.LAST, true); } - + // place random foods final List randomFood = new ArrayList<>(); randomFood.add(Items.CHEESE); randomFood.add(Items.MEAT); - + for (int level = 1; level <= 7; level++) { final LevelBuilder lb = levelBuilders[level - 1]; final Range amount = Range.make(level / 2D, level * 2); - + for (int i = 0; i < amount.randInt(rand); i++) { lb.addItem(Calc.pick(rand, randomFood).createItem(), false); } } - - // place monsters - + + // place monsters + Log.f3("Placing monsters..."); for (int level = 1; level <= 7; level++) { - + final LevelBuilder lb = levelBuilders[level - 1]; - + final Range amount = Range.make(3 + (level) * 2, 3 + level * 3); - + for (int i = 0; i < amount.randInt(rand); i++) { Entity e; - + if (level >= 2 && Calc.randInt(rand, 0, (int) (3.5 - (level / 2D))) == 0) { e = Entities.RAT_BROWN.createEntity(); } else { e = Entities.RAT_GRAY.createEntity(); } - + lb.addEntity(e, false); } } - + // compile levels Log.f3("Building levels..."); int i = 1; @@ -124,34 +124,34 @@ public class WorldCreator { w.addLevel(lb.build(w)); i++; } - + w.createPlayer(); - + Log.f2("World generation finished."); - + return w; } } - - + + public static LevelBuilder prepareFloor(long seed, int floor, MapTheme theme, boolean lastLevel) throws WorldGenError { final LevelBuilder lb = new LevelBuilder(128, theme, seed); - + lb.addRoom(Rooms.ENTRANCE, BuildOrder.FIRST, true); - + lb.addRoom(Rooms.BASIC, Range.make(floor / 2, 2 + floor), BuildOrder.MIDDLE, false); lb.addRoom(Rooms.DEAD_END, Range.make(1, floor), BuildOrder.MIDDLE, false); lb.addRoom(Rooms.STORAGE, Range.make(1, Math.ceil(floor / 3D)), BuildOrder.MIDDLE, false); - + if (lastLevel) lb.addRoom(Rooms.BOSS, BuildOrder.LAST, true); if (!lastLevel) lb.addRoom(Rooms.EXIT, BuildOrder.LAST, true); - + if (floor % 2 == 0) { final RoomBuilder heartRoom = Rooms.shrine(Items.HEART_PIECE.createItem()); lb.addRoom(heartRoom, BuildOrder.LAST, true); } - + return lb; } } diff --git a/src/mightypork/rogue/world/gen/WorldGenError.java b/src/mightypork/rogue/world/gen/WorldGenError.java index 7e18291..1af28bb 100644 --- a/src/mightypork/rogue/world/gen/WorldGenError.java +++ b/src/mightypork/rogue/world/gen/WorldGenError.java @@ -3,28 +3,32 @@ package mightypork.rogue.world.gen; /** * Error in world generation - * + * * @author Ondřej Hruška (MightyPork) */ public class WorldGenError extends RuntimeException { - - public WorldGenError() { + + public WorldGenError() + { super(); } - - - public WorldGenError(String message, Throwable cause) { + + + public WorldGenError(String message, Throwable cause) + { super(message, cause); } - - - public WorldGenError(String message) { + + + public WorldGenError(String message) + { super(message); } - - - public WorldGenError(Throwable cause) { + + + public WorldGenError(Throwable cause) + { super(cause); } - + } diff --git a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java index cfc7761..db156a0 100644 --- a/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/AbstractRectRoom.java @@ -15,7 +15,7 @@ import mightypork.utils.math.algo.Moves; public abstract class AbstractRectRoom implements RoomBuilder { - + @Override public RoomEntry buildRoom(ScratchMap map, MapTheme theme, Random rand, Coord center) { @@ -23,46 +23,46 @@ public abstract class AbstractRectRoom implements RoomBuilder { final Coord innerSize = getInnerSize(rand); final int width = 2 + innerSize.x - 1; final int height = 2 + innerSize.y - 1; - + final int wLow = (int) Math.round(width / 2D); final int wHigh = width - wLow; final int hLow = (int) Math.round(height / 2D); final int hHigh = height - hLow; - + final Coord min = new Coord(center.x - wLow, center.y - hLow); final Coord max = new Coord(center.x + wHigh, center.y + hHigh); - + if (!map.isClear(min.add(-1, -1), max)) return null; - + map.fill(min, max, getFloor(theme)); map.border(min, max, getWall(theme)); map.protect(min, max, getWallProtectionLevel()); - + placeDoors(map, theme, rand, min, max); - + buildExtras(map, theme, rand, min, max); - + return new RoomEntry(min.add(-1, -1), max); } - - + + 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 final Coord door = min.copy(); switch (rand.nextInt(4)) { @@ -83,29 +83,29 @@ public abstract class AbstractRectRoom implements RoomBuilder { door.y += 1 + rand.nextInt(height - 1); break; } - + if ((map.findDoors(door) & Moves.BITS_CARDINAL) == 0) { map.set(door, getDoorType(theme, rand)); i++; // increment pointer } } } - - + + @Stub protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { } - - + + protected abstract Coord getInnerSize(Random rand); - - + + protected abstract TileProtectLevel getWallProtectionLevel(); - - + + protected abstract TileModel getDoorType(MapTheme theme, Random rand); - - + + protected abstract int getDoorCount(Random rand); } diff --git a/src/mightypork/rogue/world/gen/rooms/BasicRoom.java b/src/mightypork/rogue/world/gen/rooms/BasicRoom.java index d02b696..45da24e 100644 --- a/src/mightypork/rogue/world/gen/rooms/BasicRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/BasicRoom.java @@ -10,28 +10,28 @@ import mightypork.utils.math.algo.Coord; public class BasicRoom extends AbstractRectRoom { - + @Override protected TileModel getDoorType(MapTheme theme, Random rand) { return rand.nextInt(4) == 0 ? theme.passage() : theme.door(); } - - + + @Override protected int getDoorCount(Random rand) { return 1 + rand.nextInt(5); } - - + + @Override protected TileProtectLevel getWallProtectionLevel() { return TileProtectLevel.WEAK; } - - + + @Override protected Coord getInnerSize(Random rand) { diff --git a/src/mightypork/rogue/world/gen/rooms/BossRoom.java b/src/mightypork/rogue/world/gen/rooms/BossRoom.java index 5fcbd7e..b4aad99 100644 --- a/src/mightypork/rogue/world/gen/rooms/BossRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/BossRoom.java @@ -12,43 +12,43 @@ import mightypork.utils.math.algo.Coord; public class BossRoom extends SecretRoom { - + @Override protected int getDoorCount(Random rand) { return 1; } - - + + @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { final Coord bossPos = min.add(3, 3); - + final Entity boss = Entities.RAT_BOSS.createEntity(); if (!map.addEntity(boss, bossPos)) { throw new WorldGenError("Could not place boss."); } - + Entity rat; - + // 4 guardian rats - + rat = Entities.RAT_BROWN.createEntity(); map.addEntity(rat, min.add(1, 1)); - + rat = Entities.RAT_BROWN.createEntity(); map.addEntity(rat, Coord.make(max.x - 1, min.y + 1)); - + rat = Entities.RAT_BROWN.createEntity(); map.addEntity(rat, max.add(-1, -1)); - + rat = Entities.RAT_BROWN.createEntity(); map.addEntity(rat, Coord.make(min.x + 1, max.y - 1)); - + } - - + + @Override protected Coord getInnerSize(Random rand) { diff --git a/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java b/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java index e1644a5..ca07edd 100644 --- a/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/DeadEndRoom.java @@ -10,28 +10,28 @@ import mightypork.utils.math.algo.Coord; public class DeadEndRoom extends AbstractRectRoom { - + @Override protected Coord getInnerSize(Random rand) { return Coord.make(1, 1); } - - + + @Override protected TileProtectLevel getWallProtectionLevel() { return TileProtectLevel.STRONG; } - - + + @Override protected TileModel getDoorType(MapTheme theme, Random rand) { return theme.floor(); } - - + + @Override protected int getDoorCount(Random rand) { diff --git a/src/mightypork/rogue/world/gen/rooms/EntranceRoom.java b/src/mightypork/rogue/world/gen/rooms/EntranceRoom.java index 854cf0f..64d8e12 100644 --- a/src/mightypork/rogue/world/gen/rooms/EntranceRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/EntranceRoom.java @@ -12,21 +12,21 @@ import mightypork.utils.math.algo.Coord; public class EntranceRoom extends AbstractRectRoom { - + @Override protected Coord getInnerSize(Random rand) { return Coord.make(3 + rand.nextInt(3), 3 + rand.nextInt(3)); } - - + + @Override protected TileProtectLevel getWallProtectionLevel() { return TileProtectLevel.WEAK; } - - + + @Override protected TileModel getDoorType(MapTheme theme, Random rand) { @@ -40,8 +40,8 @@ public class EntranceRoom extends AbstractRectRoom { return theme.door(); } } - - + + @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { @@ -50,12 +50,12 @@ public class EntranceRoom extends AbstractRectRoom { map.protect(c, c, TileProtectLevel.STRONG); map.setEntrance(c.add(1, 0)); } - - + + @Override protected int getDoorCount(Random rand) { return Calc.randInt(rand, 1, 4); } - + } diff --git a/src/mightypork/rogue/world/gen/rooms/ExitRoom.java b/src/mightypork/rogue/world/gen/rooms/ExitRoom.java index 8b7b967..a210b36 100644 --- a/src/mightypork/rogue/world/gen/rooms/ExitRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/ExitRoom.java @@ -11,28 +11,28 @@ import mightypork.utils.math.algo.Coord; public class ExitRoom extends AbstractRectRoom { - + @Override protected Coord getInnerSize(Random rand) { return Coord.make(3 + rand.nextInt(2), 3 + rand.nextInt(2)); } - - + + @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) { @@ -41,12 +41,12 @@ public class ExitRoom extends AbstractRectRoom { map.protect(c, c, TileProtectLevel.STRONG); map.setExit(c.add(-1, 0)); } - - + + @Override protected int getDoorCount(Random rand) { return 0; } - + } diff --git a/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java b/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java index dcb5681..0d45d05 100644 --- a/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java @@ -12,33 +12,34 @@ import mightypork.utils.math.algo.Coord; public class ItemShrineRoom extends SecretRoom { - + private final Item item; - - - public ItemShrineRoom(Item item) { + + + public ItemShrineRoom(Item item) + { this.item = item; } - - + + @Override protected int getDoorCount(Random rand) { return Calc.randInt(rand, 1, 4); } - - + + @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { final Coord center = min.add(2, 2); - + if (!map.addItem(item, center)) { throw new WorldGenError("Could not place item in chest."); } } - - + + @Override protected Coord getInnerSize(Random rand) { diff --git a/src/mightypork/rogue/world/gen/rooms/SecretRoom.java b/src/mightypork/rogue/world/gen/rooms/SecretRoom.java index 90eba68..93239b3 100644 --- a/src/mightypork/rogue/world/gen/rooms/SecretRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/SecretRoom.java @@ -11,28 +11,28 @@ import mightypork.utils.math.algo.Coord; public abstract class SecretRoom extends AbstractRectRoom { - + @Override protected TileModel getDoorType(MapTheme theme, Random rand) { return rand.nextInt(5) == 0 ? theme.passage() : theme.secretDoor(); } - - + + @Override protected int getDoorCount(Random rand) { return Calc.randInt(rand, 1, 3); } - - + + @Override protected TileProtectLevel getWallProtectionLevel() { return TileProtectLevel.STRONG; } - - + + @Override protected Coord getInnerSize(Random rand) { diff --git a/src/mightypork/rogue/world/gen/rooms/StorageRoom.java b/src/mightypork/rogue/world/gen/rooms/StorageRoom.java index 94356e2..da76bfe 100644 --- a/src/mightypork/rogue/world/gen/rooms/StorageRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/StorageRoom.java @@ -11,44 +11,44 @@ import mightypork.utils.math.algo.Coord; public class StorageRoom extends SecretRoom { - + @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { int maxStuff = Calc.randInt(rand, 3, 5); - + // at least one meat or cheese. final boolean oneMeat = rand.nextBoolean(); - + for (int i = 0; i < Calc.randInt(rand, oneMeat ? 1 : 0, 3); i++) { map.addItemInArea(Items.MEAT.createItem(), min, max, 50); if (--maxStuff == 0) return; } - + for (int i = 0; i < Calc.randInt(rand, oneMeat ? 0 : 1, 2); i++) { map.addItemInArea(Items.CHEESE.createItem(), min, max, 50); if (--maxStuff == 0) return; } - + for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) { map.addItemInArea(Items.ROCK.createItemDamaged(30), min, max, 50); if (--maxStuff == 0) return; } - + for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) { map.addItemInArea(Items.SANDWICH.createItem(), min, max, 50); if (--maxStuff == 0) return; } - + for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { map.addItemInArea(Items.TWIG.createItemDamaged(40), min, max, 50); if (--maxStuff == 0) return; } - + for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) { map.addItemInArea(Items.BONE.createItemDamaged(40), min, max, 50); if (--maxStuff == 0) return; } - + } } diff --git a/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java b/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java index 3eec048..ca345be 100644 --- a/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java @@ -11,21 +11,22 @@ import mightypork.utils.math.algo.Coord; public class TreasureChestRoom extends ItemShrineRoom { - - public TreasureChestRoom(Item item) { + + public TreasureChestRoom(Item item) + { super(item); } - - + + @Override protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { // set tile final Coord center = min.add(2, 2); - + map.set(center, theme.chest()); map.protect(center, TileProtectLevel.STRONG); - + // drop item super.buildExtras(map, theme, rand, min, max); } diff --git a/src/mightypork/rogue/world/gen/themes/ThemeBrick.java b/src/mightypork/rogue/world/gen/themes/ThemeBrick.java index b9535ca..4aca630 100644 --- a/src/mightypork/rogue/world/gen/themes/ThemeBrick.java +++ b/src/mightypork/rogue/world/gen/themes/ThemeBrick.java @@ -8,56 +8,56 @@ import mightypork.rogue.world.tile.Tiles; // basic dungeon theme public class ThemeBrick implements MapTheme { - + @Override public TileModel wall() { return Tiles.BRICK_WALL; } - - + + @Override public TileModel floor() { return Tiles.BRICK_FLOOR; } - - + + @Override public TileModel door() { return Tiles.BRICK_DOOR; } - - + + @Override public TileModel passage() { return Tiles.BRICK_PASSAGE; } - - + + @Override public TileModel secretDoor() { return Tiles.BRICK_HIDDEN_DOOR; } - - + + @Override public TileModel entrance() { return Tiles.BRICK_ENTRANCE; } - - + + @Override public TileModel exit() { return Tiles.BRICK_EXIT; } - - + + @Override public TileModel chest() { diff --git a/src/mightypork/rogue/world/gui/MapView.java b/src/mightypork/rogue/world/gui/MapView.java index 08e791e..ac51318 100644 --- a/src/mightypork/rogue/world/gui/MapView.java +++ b/src/mightypork/rogue/world/gui/MapView.java @@ -29,27 +29,28 @@ import mightypork.utils.math.timing.TimedTask; /** * Level display component - * + * * @author Ondřej Hruška (MightyPork) */ -public class MapView extends InputComponent implements DelegatingClient, MouseButtonHandler, Updateable, WorldAscendRequestListener, WorldDescendRequestListener { - +public class MapView extends InputComponent implements DelegatingClient, MouseButtonHandler, Updateable, WorldAscendRequestListener, + WorldDescendRequestListener { + private static final double transition_time = 0.8; - + protected final WorldRenderer worldRenderer; public final PlayerControl plc; - + private final Set plugins = new LinkedHashSet<>(); private final NumAnimated zoom = new NumAnimated(0, Easing.SINE_BOTH); private boolean zoom_in = true; - + private final NumAnimated descFadeAnim = new NumAnimated(0); private final Color blackColor = RGB.BLACK.withAlpha(descFadeAnim); - + private int descDir = 0; - + private final TimedTask timerDesc1 = new TimedTask() { - + @Override public void run() { @@ -62,55 +63,56 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu } } }; - + private final TimedTask timerDesc2 = new TimedTask() { - + @Override public void run() { WorldProvider.get().getWorld().resume(); } }; - + private final Num tileSize; - - + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Collection getChildClients() { return plugins; } - - + + @Override public boolean doesDelegate() { return true; } - - - public MapView() { + + + public MapView() + { this.tileSize = height().min(width()).div(9).max(32).mul(Num.make(1).sub(zoom.mul(0.5))); this.worldRenderer = new WorldRenderer(this, tileSize); plc = WorldProvider.get().getPlayerControl(); - + zoom.setDefaultDuration(0.5); } - - + + @Override protected void renderComponent() { worldRenderer.render(); - + App.gfx().quad(this, blackColor); } - - + + /** * Get tile coord at a screen position - * + * * @param pos position on screen (px) * @return position on map (tiles) */ @@ -118,13 +120,13 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu { return worldRenderer.getClickedTile(pos); } - - + + @Override public void receive(MouseButtonEvent event) { if (!event.isOver(this)) return; - + if (event.isButtonEvent()) { for (final MapInteractionPlugin p : plugins) { if (p.onClick(event.getPos(), event.getButton(), event.isDown())) { @@ -133,7 +135,7 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu } } } - + if (event.isWheelEvent()) { final int delta = event.getWheelDelta(); if (!zoom.isFinished()) return; @@ -146,8 +148,8 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu } } } - - + + public void toggleMag() { if (zoom_in) { @@ -158,19 +160,19 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu zoom_in = true; } } - - + + /** * Add interaction plugin - * + * * @param plugin */ public void addPlugin(MapInteractionPlugin plugin) { plugins.add(plugin); } - - + + @Override public void update(double delta) { @@ -179,40 +181,40 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu timerDesc1.update(delta); timerDesc2.update(delta); } - - + + @Override public void onAscendRequest() { if (descFadeAnim.isInProgress()) return; - + final World w = WorldProvider.get().getWorld(); - + if (w.getPlayer().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; - + final World w = WorldProvider.get().getWorld(); - + if (w.getPlayer().canDescend()) { descDir = 1; startDescAnim(); diff --git a/src/mightypork/rogue/world/gui/Minimap.java b/src/mightypork/rogue/world/gui/Minimap.java index 8ee884c..d7205d8 100644 --- a/src/mightypork/rogue/world/gui/Minimap.java +++ b/src/mightypork/rogue/world/gui/Minimap.java @@ -18,76 +18,74 @@ import mightypork.utils.math.constraints.rect.Rect; import mightypork.utils.math.constraints.rect.var.RectVar; import mightypork.utils.math.constraints.vect.Vect; -import org.lwjgl.opengl.GL11; - public class Minimap extends InputComponent implements MouseButtonHandler { - + private final RectVar bounds = Rect.makeVar(); private int unit = 0; private final Num translucency = Num.make(0.8); private final Color playerColor = RGB.RED; - - + + @Override protected void renderComponent() { Color.pushAlpha(translucency); - + final Level lvl = WorldProvider.get().getCurrentLevel(); unit = (int) Math.min(Math.max(2, Math.ceil((height().value() / 2) / (lvl.getHeight() + 2))), 10); - + final Vect plCoord = WorldProvider.get().getPlayer().getVisualPos(); - + final int lw = lvl.getWidth(); final int lh = lvl.getHeight(); - + final Vect tl = topRight().sub(unit * lw, 0); - + bounds.setTo(tl, unit * lw, unit * lh); - + final Coord point = new Coord(tl.xi(), tl.yi()); - + // FIXME do not use LWJGL directly - + GL11.glDisable(GL11.GL_TEXTURE_2D); - + GL11.glBegin(GL11.GL_QUADS); - + for (final Coord pos = Coord.zero(); pos.y < lh; pos.y++, point.y += unit) { for (pos.x = 0, point.x = tl.xi(); pos.x < lw; pos.x++, point.x += unit) { - + final Tile t = lvl.getTile(pos); if (t.isNull() || (!t.isExplored() && Const.RENDER_UFOG)) continue; - + final Color clr = t.getMapColor(); - + App.gfx().setColor(clr); - + GL11.glVertex2i(point.x, point.y); GL11.glVertex2i(point.x + unit, point.y); GL11.glVertex2i(point.x + unit, point.y + unit); GL11.glVertex2i(point.x, point.y + unit); } } - + // player App.gfx().setColor(playerColor); - + final double plx = tl.xi() + plCoord.x() * unit; final double ply = tl.yi() + plCoord.y() * unit; - + GL11.glVertex2d(plx, ply); GL11.glVertex2d(plx + unit, ply); GL11.glVertex2d(plx + unit, ply + unit); GL11.glVertex2d(plx, ply + unit); - + GL11.glEnd(); - + Color.popAlpha(); } - - + + @Override public void receive(MouseButtonEvent event) { @@ -95,14 +93,14 @@ public class Minimap extends InputComponent implements MouseButtonHandler { if (event.isUp()) { final Vect relative = event.getPos().sub(bounds.origin()); final Coord actual = Coord.make(relative.xi() / unit, relative.yi() / unit); - + final PlayerFacade player = WorldProvider.get().getPlayer(); - + if (player.getLevel().getTile(actual).isExplored()) { player.navigateTo(actual); } } - + event.consume(); } } diff --git a/src/mightypork/rogue/world/gui/WorldConsoleRenderer.java b/src/mightypork/rogue/world/gui/WorldConsoleRenderer.java index af16e1a..528d4d2 100644 --- a/src/mightypork/rogue/world/gui/WorldConsoleRenderer.java +++ b/src/mightypork/rogue/world/gui/WorldConsoleRenderer.java @@ -21,69 +21,70 @@ import mightypork.utils.math.constraints.rect.Rect; public class WorldConsoleRenderer extends BaseComponent { - + private final Num rowHeight; private final FontRenderer fr; private final Rect itemViewRect; - - - public WorldConsoleRenderer(Num rowHeight) { + + + public WorldConsoleRenderer(Num rowHeight) + { this.rowHeight = rowHeight; this.fr = new FontRenderer(Res.getFont("tiny")); - + final Num itmsize = height().perc(25).min(256).max(16); - + this.itemViewRect = bottomRight().sub(itmsize.perc(25), itmsize.perc(25)).startRect().grow(itmsize, Num.ZERO, itmsize, Num.ZERO); } - - + + @Override protected void renderComponent() { final double rh = rowHeight.value(); - + final Rect lowRow = bottomEdge().growUp(rowHeight); - + final WorldConsole console = WorldProvider.get().getWorld().getConsole(); final Collection entries = console.getEntries(); - + int cnt = 0; - + final NumVar alph = Num.makeVar(); - + Color.pushAlpha(alph); - + try { - + for (final WorldConsole.Entry entry : entries) { - + alph.setTo(entry.getAlpha()); - + final Rect rrr = lowRow.moveY(-rh * cnt); - + fr.draw(entry.getMessage(), rrr.move(rh / 8D, rh / 8D), AlignX.LEFT, RGB.BLACK_60); fr.draw(entry.getMessage(), rrr, AlignX.LEFT, RGB.WHITE); - + cnt++; } - + } catch (final ConcurrentModificationException e) { Log.e(e); // this should not happen } - + if (console.lastPickupItem != null) { - + double alpha = 1; if (console.timeSinceLastPickup > 2) { alpha = 1 - Easing.CIRC_OUT.get(Calc.clamp((console.timeSinceLastPickup - 2) / 1, 0, 1)); } - + alph.setTo(alpha); console.lastPickupItem.render(itemViewRect); } - + Color.popAlpha(); - + } - + } diff --git a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java index 6af4aa7..878a4e8 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java @@ -22,9 +22,9 @@ import mightypork.utils.math.constraints.vect.Vect; public class MIPKeyboard extends MapInteractionPlugin implements DelegatingClient, PlayerStepEndListener, Updateable { - + // FIXME cannot be static. - + //@formatter:off private static final KeyStroke[] keys = { Config.getKeyStroke("game.walk.left"), @@ -32,41 +32,42 @@ public class MIPKeyboard extends MapInteractionPlugin implements DelegatingClien Config.getKeyStroke("game.walk.up"), Config.getKeyStroke("game.walk.down") }; - + private static final Move[] sides = { Moves.W, Moves.E, Moves.N, Moves.S }; //@formatter:on - + private final KeyBindingPool kbp = new KeyBindingPool(); private final List clients = new ArrayList<>(); - + { clients.add(kbp); } - - + + @Override public boolean doesDelegate() { return true; } - - + + @Override public Collection getChildClients() { return clients; } - - - public MIPKeyboard(MapView mapView) { + + + public MIPKeyboard(MapView mapView) + { super(mapView); - + // bind keys for (int i = 0; i < 4; i++) { - + final int j = i; kbp.bindKey(keys[i], Trigger.RISING, new Runnable() { - + @Override public void run() { @@ -75,41 +76,41 @@ public class MIPKeyboard extends MapInteractionPlugin implements DelegatingClien }); } } - - + + @Override public void onStepFinished(EntityPlayer player) { walkByKey(); } - - + + @Override public boolean onClick(Vect mouse, int button, boolean down) { return false; } - - + + private void clickSide(Move side) { if (isImmobile() || getPlayer().isMoving()) return; - + mapView.plc.clickTile(side); } - - + + private boolean walkByKey() { if (isImmobile()) return false; - + if (mapView.plc.getPlayer().getMoveProgress() < 0.8) return false; - + if (LwjglInputModule.getActiveKeyMod() != Keys.MOD_NONE) return false; - + for (int i = 0; i < 4; i++) { if (keys[i].isDown()) { - + final Move side = sides[i]; if (mapView.plc.canGo(side)) { mapView.plc.go(side); @@ -121,8 +122,8 @@ public class MIPKeyboard extends MapInteractionPlugin implements DelegatingClien } return false; } - - + + @Override public void update(double delta) { diff --git a/src/mightypork/rogue/world/gui/interaction/MIPMouse.java b/src/mightypork/rogue/world/gui/interaction/MIPMouse.java index b48fb3c..029c022 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPMouse.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPMouse.java @@ -1,7 +1,6 @@ package mightypork.rogue.world.gui.interaction; -import mightypork.gamecore.backends.lwjgl.LwjglInputModule; import mightypork.gamecore.core.App; import mightypork.rogue.world.entity.impl.EntityPlayer; import mightypork.rogue.world.events.PlayerStepEndListener; @@ -16,115 +15,116 @@ import mightypork.utils.math.constraints.vect.Vect; public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListener, Updateable { - + private static final int LEFT = 0; // left private static final int RIGHT = 1; // left - - - public MIPMouse(MapView mapView) { + + + public MIPMouse(MapView mapView) + { super(mapView); } - - + + @Override public void update(double delta) { if (isImmobile()) return; - + final Vect pos = App.input().getMousePos(); if (!pos.isInside(mapView)) return; - + if (App.input().isMouseButtonDown(LEFT)) { if (mouseWalk(pos)) return; if (mapView.plc.getPlayer().isMoving() && troToNav(pos)) return; } } - - + + @Override public boolean onClick(Vect mouse, int button, boolean down) { if (isImmobile()) { return false; } - + final Vect pos = mapView.toWorldPos(mouse); - + if (button == LEFT && !down) { // try to click tile - + if (mapView.plc.clickTile(pos)) return true; } - + final Tile t = mapView.plc.getLevel().getTile(Coord.fromVect(pos)); if (button == RIGHT && !down && t.isWalkable()) { if (troToNav(mouse)) return true; return mouseWalk(mouse); } - + return false; } - - + + private boolean troToNav(Vect mouse) { if (isImmobile()) return false; - + final Coord plpos = mapView.plc.getPlayer().getCoord(); - + final Coord clicked = Coord.fromVect(mapView.toWorldPos(mouse)); if (clicked.equals(plpos)) return false; - + final Tile t = mapView.plc.getLevel().getTile(clicked); if (!t.isWalkable() || !t.isExplored()) return false; - + mapView.plc.navigateTo(clicked); return true; } - - + + private boolean mouseWalk(Vect pos) { if (isImmobile()) return false; - + final Coord plpos = mapView.plc.getPlayer().getCoord(); final Coord clicked = Coord.fromVect(mapView.toWorldPos(pos)); if (clicked.equals(plpos)) return false; - + final Polar p = Polar.fromCoord(clicked.x - plpos.x, clicked.y - plpos.y); - + final int dir = Deg.roundTo90(p.getAngleDeg()) / 90; - + switch (dir) { case 0: return mapView.plc.tryGo(Moves.E); - + case 1: return mapView.plc.tryGo(Moves.S); - + case 2: return mapView.plc.tryGo(Moves.W); - + case 3: return mapView.plc.tryGo(Moves.N); } - + return false; } - - + + @Override public void onStepFinished(EntityPlayer player) { if (isImmobile()) return; - + final Vect pos = App.input().getMousePos(); if (!pos.isInside(mapView)) return; - + if (App.input().isMouseButtonDown(LEFT)) { if (mouseWalk(pos)) return; if (mapView.plc.getPlayer().isMoving() && troToNav(pos)) return; } } - + } diff --git a/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java b/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java index 8fde371..c0ca149 100644 --- a/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java +++ b/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java @@ -9,33 +9,34 @@ import mightypork.utils.math.constraints.vect.Vect; public abstract class MapInteractionPlugin { - + protected final MapView mapView; - - - public MapInteractionPlugin(MapView mapView) { + + + public MapInteractionPlugin(MapView mapView) + { super(); this.mapView = mapView; } - - + + protected PlayerFacade getPlayer() { return mapView.plc.getPlayer(); } - - + + protected boolean isImmobile() { return getPlayer().isDead() || getWorld().isPaused(); } - - + + protected World getWorld() { return WorldProvider.get().getWorld(); } - - + + public abstract boolean onClick(Vect mouse, int button, boolean down); } diff --git a/src/mightypork/rogue/world/item/Item.java b/src/mightypork/rogue/world/item/Item.java index 2a71f54..43c740e 100644 --- a/src/mightypork/rogue/world/item/Item.java +++ b/src/mightypork/rogue/world/item/Item.java @@ -11,31 +11,32 @@ import mightypork.utils.math.constraints.rect.Rect; public abstract class Item implements IonBundled { - + private final ItemModel model; private ItemRenderer renderer; private int amount = 1; private int uses = 1; - - - public Item(ItemModel model) { + + + public Item(ItemModel model) + { this.model = model; } - - + + public final void render(Rect rect) { if (renderer == null) { renderer = makeRenderer(); } - + renderer.render(rect); } - - + + protected abstract ItemRenderer makeRenderer(); - - + + @Override @Stub public void save(IonDataBundle out) @@ -43,8 +44,8 @@ public abstract class Item implements IonBundled { out.put("c", amount); out.put("u", uses); } - - + + @Override @Stub public void load(IonDataBundle in) @@ -52,33 +53,33 @@ public abstract class Item implements IonBundled { amount = in.get("c", amount); uses = in.get("u", uses); } - - + + public final ItemModel getModel() { return model; } - - + + @Stub protected int getMaxStackSize() { return isStackable() ? 65535 : 1; } - - + + public boolean canStackWith(Item other) { return (getModel().id == other.getModel().id); } - - + + protected abstract boolean isStackable(); - - + + /** * Add another item to this item - * + * * @param added added item * @return if items are compatible and the added item was completely moved * to this item, returns true and the added item should be @@ -88,18 +89,18 @@ public abstract class Item implements IonBundled { { if (!canStackWith(added)) return false; if (added.isEmpty()) return true; - + final int room = getMaxStackSize() - this.amount; final int avail = added.amount; - + final int moved = Math.min(room, avail); this.amount += moved; added.amount -= moved; - + return added.isEmpty(); } - - + + /** * @return item amount in the stack */ @@ -107,86 +108,86 @@ public abstract class Item implements IonBundled { { return Math.max(0, amount); } - - + + /** * Consume one item. - * + * * @return true if the item is fully consumed and should be removed. */ public void consume() { if (isEmpty()) throw new RuntimeException("Item is empty, cannot consume."); - + amount--; } - - + + public boolean isEmpty() { return getAmount() == 0; } - - + + public Item split(int removed) { if (isEmpty()) throw new RuntimeException("Item is empty, cannot split."); - + final int realRemoved = Math.min(removed, amount); - + final Item newItm = model.createItem(); newItm.uses = uses; newItm.amount = realRemoved; this.amount -= realRemoved; - + return newItm; } - - + + public abstract int getAttackPoints(); - - + + public abstract int getFoodPoints(); - - + + public abstract ItemType getType(); - - + + @Override public String toString() { return Support.str(getClass()) + " x " + getAmount(); } - - + + public int getRemainingUses() { return uses; } - - + + public abstract int getMaxUses(); - - + + public void setRemainingUses(int uses) { this.uses = Calc.clamp(uses, 0, getMaxUses()); } - - + + public void use() { if (uses > 0) uses--; if (uses == 0) consume(); } - - + + public abstract boolean isDamageable(); - - + + public abstract String getVisualName(); - - + + @Stub public boolean pickUp(PlayerFacade pl) { diff --git a/src/mightypork/rogue/world/item/ItemModel.java b/src/mightypork/rogue/world/item/ItemModel.java index a12032d..c2abf6b 100644 --- a/src/mightypork/rogue/world/item/ItemModel.java +++ b/src/mightypork/rogue/world/item/ItemModel.java @@ -9,23 +9,24 @@ import mightypork.utils.math.Calc; /** * Item model (builder) - * + * * @author Ondřej Hruška (MightyPork) */ public final class ItemModel { - + /** Model ID */ public final int id; public final Class itemClass; - - - public ItemModel(int id, Class item) { + + + public ItemModel(int id, Class item) + { Items.register(id, this); this.id = id; this.itemClass = item; } - - + + /** * @return new item instance of this type */ @@ -33,32 +34,32 @@ public final class ItemModel { { try { final Item itm = itemClass.getConstructor(ItemModel.class).newInstance(this); - + itm.setRemainingUses(itm.getMaxUses()); - + return itm; - + } catch (final Exception e) { throw new RuntimeException("Could not instantiate an item.", e); } } - - + + public Item loadItem(IonDataBundle in) throws IOException { final Item t = createItem(); t.load(in); return t; } - - + + public void saveItem(IonDataBundle out, Item item) throws IOException { if (itemClass != item.getClass()) throw new RuntimeException("Item class mismatch."); item.save(out); } - - + + public Item createItemDamaged(int minimalHealthPercent) { final Item item = createItem(); diff --git a/src/mightypork/rogue/world/item/ItemRenderer.java b/src/mightypork/rogue/world/item/ItemRenderer.java index 18bca5d..eb54c19 100644 --- a/src/mightypork/rogue/world/item/ItemRenderer.java +++ b/src/mightypork/rogue/world/item/ItemRenderer.java @@ -5,15 +5,16 @@ import mightypork.utils.math.constraints.rect.Rect; public abstract class ItemRenderer { - + protected final Item item; - - - public ItemRenderer(Item item) { + + + public ItemRenderer(Item item) + { this.item = item; } - - + + public abstract void render(Rect r); - + } diff --git a/src/mightypork/rogue/world/item/Items.java b/src/mightypork/rogue/world/item/Items.java index a6f675e..343d9dc 100644 --- a/src/mightypork/rogue/world/item/Items.java +++ b/src/mightypork/rogue/world/item/Items.java @@ -8,7 +8,13 @@ import mightypork.rogue.world.item.impl.active.ItemHeartPiece; import mightypork.rogue.world.item.impl.food.ItemCheese; import mightypork.rogue.world.item.impl.food.ItemMeat; import mightypork.rogue.world.item.impl.food.ItemSandwich; -import mightypork.rogue.world.item.impl.weapons.*; +import mightypork.rogue.world.item.impl.weapons.ItemAxe; +import mightypork.rogue.world.item.impl.weapons.ItemBone; +import mightypork.rogue.world.item.impl.weapons.ItemClub; +import mightypork.rogue.world.item.impl.weapons.ItemKnife; +import mightypork.rogue.world.item.impl.weapons.ItemRock; +import mightypork.rogue.world.item.impl.weapons.ItemSword; +import mightypork.rogue.world.item.impl.weapons.ItemTwig; import mightypork.utils.ion.IonDataBundle; import mightypork.utils.ion.IonInput; import mightypork.utils.ion.IonOutput; @@ -16,13 +22,13 @@ import mightypork.utils.ion.IonOutput; /** * Item registry - * + * * @author Ondřej Hruška (MightyPork) */ public final class Items { - + private static final ItemModel[] items = new ItemModel[256]; - + public static final ItemModel MEAT = new ItemModel(1, ItemMeat.class); public static final ItemModel CHEESE = new ItemModel(2, ItemCheese.class); public static final ItemModel BONE = new ItemModel(3, ItemBone.class); @@ -34,54 +40,54 @@ public final class Items { public static final ItemModel HEART_PIECE = new ItemModel(9, ItemHeartPiece.class); public static final ItemModel TWIG = new ItemModel(10, ItemTwig.class); public static final ItemModel KNIFE = new ItemModel(11, ItemKnife.class); - - + + public static void register(int id, ItemModel model) { if (id < 0 || id >= items.length) { throw new IllegalArgumentException("Item ID " + id + " is out of range."); } - + if (items[id] != null) { throw new IllegalArgumentException("Item ID " + id + " already in use."); } - + items[id] = model; } - - + + public static ItemModel get(int id) { final ItemModel m = items[id]; - + if (m == null) { throw new IllegalArgumentException("No item with ID " + id + "."); } - + return m; } - - + + public static Item loadItem(IonInput in) throws IOException { final int id = in.readIntByte(); final ItemModel model = get(id); return model.loadItem(in.readBundle()); } - - + + public static void saveItem(IonOutput out, Item item) throws IOException { final ItemModel model = item.getModel(); - + out.writeIntByte(model.id); - + final IonDataBundle ib = new IonDataBundle(); model.saveItem(ib, item); out.writeBundle(ib); } - - + + public static void loadItems(IonInput in, Collection items) throws IOException { items.clear(); @@ -89,16 +95,16 @@ public final class Items { items.add(loadItem(in)); } } - - + + public static void saveItems(IonOutput out, Collection items) throws IOException { for (final Item entity : items) { out.startEntry(); saveItem(out, entity); } - + out.endSequence(); } - + } diff --git a/src/mightypork/rogue/world/item/impl/ItemBaseFood.java b/src/mightypork/rogue/world/item/impl/ItemBaseFood.java index 029e618..ee8f63f 100644 --- a/src/mightypork/rogue/world/item/impl/ItemBaseFood.java +++ b/src/mightypork/rogue/world/item/impl/ItemBaseFood.java @@ -7,40 +7,41 @@ import mightypork.rogue.world.item.ItemType; public abstract class ItemBaseFood extends Item { - - public ItemBaseFood(ItemModel model) { + + public ItemBaseFood(ItemModel model) + { super(model); } - - + + @Override public boolean isStackable() { return true; } - - + + @Override public final int getAttackPoints() { return 0; } - - + + @Override public final ItemType getType() { return ItemType.FOOD; } - - + + @Override public boolean isDamageable() { return false; } - - + + @Override public int getMaxUses() { diff --git a/src/mightypork/rogue/world/item/impl/ItemBaseWeapon.java b/src/mightypork/rogue/world/item/impl/ItemBaseWeapon.java index a2ccdbd..2f7592d 100644 --- a/src/mightypork/rogue/world/item/impl/ItemBaseWeapon.java +++ b/src/mightypork/rogue/world/item/impl/ItemBaseWeapon.java @@ -7,37 +7,38 @@ import mightypork.rogue.world.item.ItemType; public abstract class ItemBaseWeapon extends Item { - - public ItemBaseWeapon(ItemModel model) { + + public ItemBaseWeapon(ItemModel model) + { super(model); } - - + + @Override public boolean isStackable() { return false; } - - + + @Override public final int getFoodPoints() { return 0; } - - + + @Override public final ItemType getType() { return ItemType.WEAPON; } - - + + @Override public boolean isDamageable() { return true; } - + } diff --git a/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java b/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java index a440114..343b181 100644 --- a/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java +++ b/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java @@ -11,77 +11,78 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemHeartPiece extends Item { - - public ItemHeartPiece(ItemModel model) { + + public ItemHeartPiece(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.heart")); } - - + + @Override protected boolean isStackable() { return false; } - - + + @Override public int getAttackPoints() { return 0; } - - + + @Override public int getFoodPoints() { return 0; } - - + + @Override public ItemType getType() { return ItemType.ACTIVE; } - - + + @Override public int getMaxUses() { return 1; } - - + + @Override public boolean isDamageable() { return false; } - - + + @Override public String getVisualName() { return "Heart Piece"; } - - + + @Override public boolean pickUp(PlayerFacade pl) { pl.setHealthMax(pl.getHealthMax() + 2); // two points / heart pl.setHealth(pl.getHealthMax()); - + pl.getWorld().getConsole().msgHeartPiece(); - + return true; } - + } diff --git a/src/mightypork/rogue/world/item/impl/food/ItemCheese.java b/src/mightypork/rogue/world/item/impl/food/ItemCheese.java index b26f007..d71116c 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemCheese.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemCheese.java @@ -9,26 +9,27 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemCheese extends ItemBaseFood { - - public ItemCheese(ItemModel model) { + + public ItemCheese(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.cheese")); } - - + + @Override public int getFoodPoints() { return 2; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/food/ItemMeat.java b/src/mightypork/rogue/world/item/impl/food/ItemMeat.java index e8f58f2..09e265f 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemMeat.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemMeat.java @@ -9,26 +9,27 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemMeat extends ItemBaseFood { - - public ItemMeat(ItemModel model) { + + public ItemMeat(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.meat")); } - - + + @Override public int getFoodPoints() { return 4; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java b/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java index f655ab6..e1b2dae 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java @@ -9,26 +9,27 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemSandwich extends ItemBaseFood { - - public ItemSandwich(ItemModel model) { + + public ItemSandwich(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.sandwich")); } - - + + @Override public int getFoodPoints() { return 8; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java b/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java index 2fbdb4d..b57c826 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemAxe extends ItemBaseWeapon { - - public ItemAxe(ItemModel model) { + + public ItemAxe(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.axe")); } - - + + @Override public int getAttackPoints() { return 4; } - - + + @Override public int getMaxUses() { return 70; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java b/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java index 51aee39..ff95eeb 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemBone extends ItemBaseWeapon { - - public ItemBone(ItemModel model) { + + public ItemBone(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.bone")); } - - + + @Override public int getAttackPoints() { return 1; } - - + + @Override public int getMaxUses() { return 15; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java b/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java index caff2f2..44dcd7e 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemClub extends ItemBaseWeapon { - - public ItemClub(ItemModel model) { + + public ItemClub(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.club")); } - - + + @Override public int getAttackPoints() { return 3; } - - + + @Override public int getMaxUses() { return 40; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java b/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java index 2fe3691..a45a4fc 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemKnife extends ItemBaseWeapon { - - public ItemKnife(ItemModel model) { + + public ItemKnife(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.knife")); } - - + + @Override public int getAttackPoints() { return 4; } - - + + @Override public int getMaxUses() { return 70; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java b/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java index 4328e89..c3ad0c5 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemRock extends ItemBaseWeapon { - - public ItemRock(ItemModel model) { + + public ItemRock(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.stone")); } - - + + @Override public int getAttackPoints() { return 2; } - - + + @Override public int getMaxUses() { return 35; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java b/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java index bb7d9b9..817edfb 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemSword extends ItemBaseWeapon { - - public ItemSword(ItemModel model) { + + public ItemSword(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.sword")); } - - + + @Override public int getAttackPoints() { return 5; } - - + + @Override public int getMaxUses() { return 210; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java b/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java index 24c86bd..85256d7 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java @@ -9,33 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemTwig extends ItemBaseWeapon { - - public ItemTwig(ItemModel model) { + + public ItemTwig(ItemModel model) + { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.getTxQuad("item.twig")); } - - + + @Override public int getAttackPoints() { return 1; } - - + + @Override public int getMaxUses() { return 10; } - - + + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/item/render/QuadItemRenderer.java b/src/mightypork/rogue/world/item/render/QuadItemRenderer.java index 8996943..6b0b25d 100644 --- a/src/mightypork/rogue/world/item/render/QuadItemRenderer.java +++ b/src/mightypork/rogue/world/item/render/QuadItemRenderer.java @@ -9,20 +9,21 @@ import mightypork.utils.math.constraints.rect.Rect; public class QuadItemRenderer extends ItemRenderer { - + private final TxQuad txq; - - - public QuadItemRenderer(Item item, TxQuad txq) { + + + public QuadItemRenderer(Item item, TxQuad txq) + { super(item); this.txq = txq; } - - + + @Override public void render(Rect r) { App.gfx().quad(r, txq); } - + } diff --git a/src/mightypork/rogue/world/level/Level.java b/src/mightypork/rogue/world/level/Level.java index 0e052a3..b8d01a9 100644 --- a/src/mightypork/rogue/world/level/Level.java +++ b/src/mightypork/rogue/world/level/Level.java @@ -2,7 +2,16 @@ package mightypork.rogue.world.level; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; import mightypork.rogue.world.World; import mightypork.rogue.world.entity.Entities; @@ -13,7 +22,6 @@ import mightypork.rogue.world.item.Item; import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.TileModel; import mightypork.rogue.world.tile.Tiles; -import mightypork.utils.eventbus.EventBus; import mightypork.utils.eventbus.clients.DelegatingClient; import mightypork.utils.eventbus.clients.ToggleableClient; import mightypork.utils.interfaces.Updateable; @@ -33,93 +41,95 @@ import mightypork.utils.math.noise.NoiseGen; /** * One level of the dungeon - * + * * @author Ondřej Hruška (MightyPork) */ public class Level implements Updateable, DelegatingClient, ToggleableClient, IonBinary { - + private final FloodFill exploreFiller = new FloodFill() { - + @Override public List getSpreadSides() { return Moves.ALL_SIDES; } - - + + @Override public double getMaxDistance() { return 5.4; } - - + + @Override public boolean canSpreadFrom(Coord pos) { final Tile t = getTile(pos); return t.isWalkable() && !t.isDoor(); } - - + + @Override public boolean canEnter(Coord pos) { final Tile t = getTile(pos); return !t.isNull(); } - - + + @Override public boolean forceSpreadStart() { return true; } }; - + public static final int ION_MARK = 53; private static final Comparator ENTITY_RENDER_CMP = new EntityRenderComparator(); - + private Coord size = Coord.zero(); private World world; - + private Coord enterPoint = Coord.zero(); private Coord exitPoint = Coord.zero(); - + /** Array of tiles [y][x] */ private Tile[][] tiles; - + private final Map entityMap = new HashMap<>(); private final List entityList = new LinkedList<>(); - + private int playerCount = 0; - + /** Level seed (used for generation and tile variation) */ public long seed; - + private transient NoiseGen noiseGen; private double timeSinceLastEntitySort; - - - public Level() { + + + public Level() + { } - - - public Level(int width, int height) { + + + public Level(int width, int height) + { size.setTo(width, height); buildArray(); } - - + + private void buildArray() { this.tiles = new Tile[size.y][size.x]; } - - + + /** * Fill whole map with tile type - * + * * @param model tile model */ public void fill(TileModel model) @@ -130,25 +140,25 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io } } } - - + + /** * 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 - + return tiles[pos.y][pos.x]; } - - + + /** * Set tile at pos - * + * * @param pos tile pos * @param tile the tile instance to set */ @@ -158,14 +168,14 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io Log.w("Invalid tile coord to set: " + pos + ", map size: " + size); return; // out of range } - + tiles[pos.y][pos.x] = tile; - + // assign level (tile logic may need it) tile.setLevel(this); } - - + + /** * @return map width in tiles */ @@ -173,8 +183,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return size.x; } - - + + /** * @return map height in tiles */ @@ -182,19 +192,19 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return size.y; } - - + + /** * Set level seed (used for visuals; the seed used for generation) - * + * * @param seed seed */ public void setSeed(long seed) { this.seed = seed; } - - + + /** * @return map seed */ @@ -202,8 +212,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return seed; } - - + + @Override public void load(IonInput in) throws IOException { @@ -213,21 +223,21 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io size = ib.get("size"); enterPoint = ib.get("enter_point", enterPoint); exitPoint = ib.get("exit_point", exitPoint); - + // -- binary data -- - + // load tiles buildArray(); - + for (final Coord c = Coord.zero(); c.x < size.x; c.x++) { for (c.y = 0; c.y < size.y; c.y++) { setTile(c, Tiles.loadTile(in)); } } - + // load entities Entities.loadEntities(in, entityList); - + // prepare entities for (final Entity ent : entityList) { ent.setLevel(this); @@ -238,8 +248,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io } } } - - + + @Override public void save(IonOutput out) throws IOException { @@ -250,50 +260,50 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io ib.put("enter_point", enterPoint); ib.put("exit_point", exitPoint); out.writeBundle(ib); - + // -- binary data -- - + // tiles for (final Coord c = Coord.zero(); c.x < size.x; c.x++) { for (c.y = 0; c.y < size.y; c.y++) { Tiles.saveTile(out, getTile(c)); } } - + Entities.saveEntities(out, entityList); } - - + + @Override public void update(double delta) { timeSinceLastEntitySort += delta; - + if (timeSinceLastEntitySort > 0.2) { Collections.sort(entityList, ENTITY_RENDER_CMP); timeSinceLastEntitySort = 0; } - + // just update them all for (final Coord c = Coord.zero(); c.x < size.x; c.x++) { for (c.y = 0; c.y < size.y; c.y++) { getTile(c).updateTile(delta); } } - + final List toRemove = new ArrayList<>(); - + for (final Entity e : entityList) { if (e.isDead() && e.canRemoveCorpse()) toRemove.add(e); } - + for (final Entity e : toRemove) { removeEntity(e); e.onCorpseRemoved(); } } - - + + /** * @return level-specific noise generator */ @@ -302,14 +312,14 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io if (noiseGen == null) { noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed); } - + return noiseGen; } - - + + /** * Get entity by ID - * + * * @param eid entity ID * @return the entity, or null */ @@ -317,11 +327,11 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return entityMap.get(eid); } - - + + /** * Try to add entity at given pos, then near the pos. - * + * * @param entity the entity * @param pos pos * @return true if added @@ -329,27 +339,27 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io public boolean addEntityNear(Entity entity, Coord pos) { if (addEntity(entity, pos)) return true; - + // closer for (int i = 0; i < 20; i++) { final Coord c = pos.add(Calc.randInt(-1, 1), Calc.randInt(-1, 1)); if (addEntity(entity, c)) return true; } - + // further for (int i = 0; i < 20; i++) { final Coord c = pos.add(Calc.randInt(-2, 2), Calc.randInt(-2, 2)); if (addEntity(entity, c)) return true; } - + return false; - + } - - + + /** * Try to add entity at given pos - * + * * @param entity the entity * @param pos pos * @return true if added (false if void, wall etc) @@ -358,42 +368,42 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { final Tile t = getTile(pos); if (!t.isWalkable() || t.isOccupied()) return false; - + // set level to init EID entity.setLevel(this); - + if (entityMap.containsKey(entity.getEntityId())) { Log.w("Entity already in level."); return false; } - + entityMap.put(entity.getEntityId(), entity); entityList.add(entity); if (entity instanceof EntityPlayer) playerCount++; - + // join to level & world occupyTile(entity.getCoord()); - + entity.setCoord(pos); - + return true; } - - + + /** * Remove an entity from the level, if present - * + * * @param entity entity */ public void removeEntity(Entity entity) { removeEntity(entity.getEntityId()); } - - + + /** * Remove an entity from the level, if present - * + * * @param eid entity id */ public void removeEntity(int eid) @@ -402,53 +412,53 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io if (removed == null) throw new NullPointerException("No such entity in level: " + eid); if (removed instanceof EntityPlayer) playerCount--; entityList.remove(removed); - + // upon kill, entities free tile themselves. if (!removed.isDead()) { freeTile(removed.getCoord()); } } - - + + /** * 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); - + return t.isWalkable() && !t.isOccupied(); } - - + + /** * Mark tile as occupied (entity entered) - * + * * @param pos tile pos */ public void occupyTile(Coord pos) { getTile(pos).setOccupied(true); } - - + + /** * Mark tile as free (entity left) - * + * * @param pos tile pos */ public void freeTile(Coord pos) { getTile(pos).setOccupied(false); } - - + + /** * Check entity on tile - * + * * @param pos tile coord * @return true if some entity is standing there */ @@ -456,94 +466,94 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return getTile(pos).isOccupied(); } - - + + /** * 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); } - - + + /** * Get location where the player appears upon descending to this level - * + * * @return pos */ public Coord getEnterPoint() { return enterPoint; } - - + + /** * 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; } - - + + /** * Assign a world - * + * * @param world new world */ public void setWorld(World world) { this.world = world; } - - + + /** * Mark tile and surrounding area as explored - * + * * @param center center the explored tile */ public void explore(Coord center) { final Collection filled = new HashSet<>(); - + exploreFiller.fill(center, filled); - + for (final Coord c : filled) { getTile(c).setExplored(); } } - - + + /** * Get entity of type closest to coord - * + * * @param pos the attack origin * @param type wanted entity type * @param radius search radius; -1 for unlimited. @@ -553,27 +563,27 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { Entity closest = null; double minDist = Double.MAX_VALUE; - + for (final Entity e : entityList) { if (e.isDead()) continue; - + if (e.getType() == type) { final double dist = e.pos.getVisualPos().dist(pos).value(); - + if (dist <= radius && dist < minDist) { minDist = dist; closest = e; } } } - + return closest; } - - + + /** * Free a tile. If entity is present, remove it. - * + * * @param pos the tile pos */ public void forceFreeTile(Coord pos) @@ -586,24 +596,24 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io break; } } - + for (final Entity e : toButcher) { removeEntity(e); freeTile(pos); } } - + if (!getTile(pos).isWalkable()) { // this should never happen. setTile(pos, Tiles.BRICK_FLOOR.createTile()); } - + } - - + + /** * Check if entity is in the level - * + * * @param entity entity * @return is present */ @@ -611,11 +621,11 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return entityList.contains(entity); } - - + + /** * Check if entity is in the level - * + * * @param eid entity ID * @return true if present */ @@ -623,71 +633,71 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return entityMap.containsKey(eid); } - - + + /** * Get entity collection (for rendering) - * + * * @return entities */ public Collection getEntities() { return entityList; } - - + + @Override public boolean isListening() { return playerCount > 0; // listen only when player is in this level } - - + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public Collection getChildClients() { return entityList; } - - + + @Override public boolean doesDelegate() { return isListening(); } - - + + public boolean dropNear(Coord coord, Item itm) { if (getTile(coord).dropItem(itm)) return true; - + for (int i = 0; i < 6; i++) { final Coord c = coord.add(Calc.randInt(-1, 1), Calc.randInt(-1, 1)); if (getTile(c).dropItem(itm)) return true; } - + return false; } - + private static class EntityRenderComparator implements Comparator { - + @Override public int compare(Entity o1, Entity o2) { if (o1.isDead() && !o2.isDead()) { return -1; } - + if (!o1.isDead() && o2.isDead()) { return 1; } - + int c = Double.compare(o1.pos.getVisualPos().y(), o1.pos.getVisualPos().y()); if (c == 0) c = Double.compare(o1.pos.getVisualPos().x(), o1.pos.getVisualPos().x()); - + return c; } - + } } diff --git a/src/mightypork/rogue/world/level/render/EntityRenderContext.java b/src/mightypork/rogue/world/level/render/EntityRenderContext.java index 25f955b..3173e09 100644 --- a/src/mightypork/rogue/world/level/render/EntityRenderContext.java +++ b/src/mightypork/rogue/world/level/render/EntityRenderContext.java @@ -6,9 +6,10 @@ import mightypork.utils.math.constraints.rect.Rect; public class EntityRenderContext extends MapRenderContext { - - public EntityRenderContext(Level map, Rect drawArea) { + + public EntityRenderContext(Level map, Rect drawArea) + { super(map, drawArea); } - + } diff --git a/src/mightypork/rogue/world/level/render/MapRenderContext.java b/src/mightypork/rogue/world/level/render/MapRenderContext.java index 98ff03e..eda9f34 100644 --- a/src/mightypork/rogue/world/level/render/MapRenderContext.java +++ b/src/mightypork/rogue/world/level/render/MapRenderContext.java @@ -9,32 +9,33 @@ import mightypork.utils.math.constraints.rect.builders.TiledRect; public abstract class MapRenderContext { - + protected final Level map; protected final TiledRect tiler; private final Rect mapRect; - - - public MapRenderContext(Level map, Rect drawArea) { + + + public MapRenderContext(Level map, Rect drawArea) + { this.map = map; - + this.tiler = drawArea.tiles(map.getWidth(), map.getHeight()); this.mapRect = drawArea; } - - + + public Rect getRectForTile(Coord pos) { return tiler.tile(pos.x, pos.y); } - - + + public Rect getMapRect() { return mapRect; } - - + + public Tile getTile(Coord pos) { return map.getTile(pos); diff --git a/src/mightypork/rogue/world/level/render/TileRenderContext.java b/src/mightypork/rogue/world/level/render/TileRenderContext.java index cfab2ba..d3d7701 100644 --- a/src/mightypork/rogue/world/level/render/TileRenderContext.java +++ b/src/mightypork/rogue/world/level/render/TileRenderContext.java @@ -12,24 +12,25 @@ import mightypork.utils.math.noise.NoiseGen; /** * Context for tile rendering. - * + * * @author Ondřej Hruška (MightyPork) */ public final class TileRenderContext extends MapRenderContext implements RectBound { - + public final Coord pos = Coord.zero(); private final NoiseGen noise; - - - public TileRenderContext(Level map, Rect drawArea) { + + + public TileRenderContext(Level map, Rect drawArea) + { super(map, drawArea); - - //this.tiler.setOverlap(0.002); // avoid gaps (rounding error?) - + + //this.tiler.setOverlap(0.002); // avoid gaps (rounding error?) + this.noise = map.getNoiseGen(); } - - + + /** * @return the rendered tile. */ @@ -37,11 +38,11 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { return map.getTile(pos); } - - + + /** * Get a neighbor tile - * + * * @param offset offsets * @return the tile at that position */ @@ -49,8 +50,8 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { return map.getTile(pos.add(offset)); } - - + + /** * @return per-coord noise value 0..1 */ @@ -58,26 +59,26 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { return noise.valueAt(pos.x, pos.y); } - - + + public void renderTile() { map.getTile(pos).renderTile(this); } - - + + public void renderUFog() { map.getTile(pos).renderUFog(this); } - - + + public void renderItems() { map.getTile(pos).renderExtra(this); } - - + + /** * Rect of the current tile to draw */ diff --git a/src/mightypork/rogue/world/tile/DroppedItemRenderer.java b/src/mightypork/rogue/world/tile/DroppedItemRenderer.java index d8a3bda..a94b6b1 100644 --- a/src/mightypork/rogue/world/tile/DroppedItemRenderer.java +++ b/src/mightypork/rogue/world/tile/DroppedItemRenderer.java @@ -15,30 +15,30 @@ import mightypork.utils.math.constraints.rect.proxy.RectProxy; public class DroppedItemRenderer { - + private final Animator itemAnim = new AnimatorBounce(2, Easing.SINE_BOTH); - + // prepared constraints, to avoid re-building each frame private final RectProxy tileRectAdapter = new RectProxy(); private final NumProxy offsAdapter = new NumProxy(); private final Rect itemRect = tileRectAdapter.shrink(tileRectAdapter.height().perc(12)).moveY(offsAdapter.neg().mul(tileRectAdapter.height().mul(0.2))); - - + + public void render(Collection items, TileRenderContext context) { tileRectAdapter.setRect(context); int cnt = 0; for (final Item i : items) { - + offsAdapter.setNum(Num.make((itemAnim.getValue() + (cnt % 3) * 0.1))); - + i.render(itemRect); - + cnt++; } } - - + + public void update(double delta) { itemAnim.update(delta); diff --git a/src/mightypork/rogue/world/tile/Tile.java b/src/mightypork/rogue/world/tile/Tile.java index f671a5a..4192bf4 100644 --- a/src/mightypork/rogue/world/tile/Tile.java +++ b/src/mightypork/rogue/world/tile/Tile.java @@ -10,7 +10,6 @@ import mightypork.rogue.world.level.Level; import mightypork.rogue.world.level.render.TileRenderContext; import mightypork.utils.Support; import mightypork.utils.annotations.Stub; -import mightypork.utils.eventbus.EventBus; import mightypork.utils.ion.IonBinary; import mightypork.utils.ion.IonInput; import mightypork.utils.ion.IonOutput; @@ -20,62 +19,63 @@ import mightypork.utils.math.color.Color; /** * Tile data bundle. Client only renders. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Tile implements IonBinary { - + // tmp extras public final TileGenData genData = new TileGenData(); - + public final TileModel model; - + // temporary flag for map. protected boolean occupied; protected boolean explored; - + protected Level level; - + private TileRenderer renderer; - - - public Tile(TileModel model) { + + + public Tile(TileModel model) + { this.model = model; } - - + + /** * Render the tile, using the main texture sheet. - * + * * @param context rendering ctx */ @Stub public void renderTile(TileRenderContext context) { if (!isExplored() && Const.RENDER_UFOG) return; - + initRenderer(); - + renderer.renderTile(context); - + if (doesReceiveShadow()) renderer.renderShadows(context); } - - + + @Stub public void renderUFog(TileRenderContext context) { initRenderer(); - + renderer.renderUnexploredFog(context); } - - + + private void initRenderer() { if (renderer == null) { renderer = makeRenderer(); - + if (renderer == /*still*/null) { Log.w("No renderer for tile " + Support.str(this)); renderer = TileRenderer.NONE; @@ -83,15 +83,15 @@ public abstract class Tile implements IonBinary { } } } - - + + protected abstract TileRenderer makeRenderer(); - - + + /** * Render extra stuff (ie. dropped items).
* Called after the whole map is rendered using renderTile. - * + * * @param context */ @Stub @@ -100,88 +100,88 @@ public abstract class Tile implements IonBinary { initRenderer(); renderer.renderExtra(context); } - - + + @Override public void save(IonOutput out) throws IOException { out.writeBoolean(explored); } - - + + @Override public void load(IonInput in) throws IOException { explored = in.readBoolean(); } - - + + public final boolean isOccupied() { return occupied; } - - + + public final void setOccupied(boolean occupied) { this.occupied = occupied; } - - + + public final boolean isExplored() { return explored; } - - + + public void setExplored() { explored = true; } - - + + public final boolean isNull() { return getType() == TileType.NULL; } - - + + public final boolean isWall() { return getType() == TileType.WALL; } - - + + public final boolean isFloor() { return getType() == TileType.FLOOR; } - - + + public final boolean isDoor() { return getType() == TileType.DOOR || getType() == TileType.PASSAGE; } - - + + public final boolean isStairs() { return getType() == TileType.STAIRS; } - - + + @Stub public void updateTile(double delta) { initRenderer(); renderer.update(delta); } - - + + /** * Check if this tile is right now walkable.
* If type is not potentially walkable, this method must return false. - * + * * @return true if currently walkable */ @Stub @@ -189,65 +189,65 @@ public abstract class Tile implements IonBinary { { return isPotentiallyWalkable(); } - - + + public final boolean isPotentiallyWalkable() { return getType().isPotentiallyWalkable(); } - - + + public abstract TileType getType(); - - + + public abstract boolean doesCastShadow(); - - + + @Stub public boolean doesReceiveShadow() { return !doesCastShadow(); } - - + + public Color getMapColor() { return getType().getMapColor(); } - - + + public final TileModel getModel() { return model; } - - + + /** * Drop item onto this tile - * + * * @param item * @return true if dropped */ public abstract boolean dropItem(Item item); - - + + /** * Remove an item from this tile - * + * * @return the picked item, or null if none */ public abstract Item pickItem(); - - + + /** * @return true if the tile has dropped items */ public abstract boolean hasItem(); - - + + /** * Handle player click - * + * * @return true if the tile is interactive and did something. */ @Stub @@ -255,23 +255,23 @@ public abstract class Tile implements IonBinary { { return false; } - - + + public void setLevel(Level level) { this.level = level; } - - + + public Level getLevel() { return level; } - - + + protected World getWorld() { return level.getWorld(); } - + } diff --git a/src/mightypork/rogue/world/tile/TileColors.java b/src/mightypork/rogue/world/tile/TileColors.java index 973ac19..0af4fc0 100644 --- a/src/mightypork/rogue/world/tile/TileColors.java +++ b/src/mightypork/rogue/world/tile/TileColors.java @@ -6,17 +6,17 @@ import mightypork.utils.math.color.pal.RGB; public class TileColors { - + public static final Color NULL = RGB.NONE; public static final Color FLOOR = RGB.GRAY_DARK; public static final Color WALL = RGB.GRAY_LIGHT; public static final Color DOOR = RGB.BROWN; public static final Color COLLAPSED_WALL = RGB.GRAY; - + public static final Color ENTRANCE = RGB.CYAN; public static final Color EXIT = Color.fromHex(0x00EA8C); - + public static final Color SECRET_DOOR_REVEALED = RGB.PINK; public static final Color SECRET_DOOR_HIDDEN = WALL; - + } diff --git a/src/mightypork/rogue/world/tile/TileGenData.java b/src/mightypork/rogue/world/tile/TileGenData.java index 4c60c5b..47bdb4f 100644 --- a/src/mightypork/rogue/world/tile/TileGenData.java +++ b/src/mightypork/rogue/world/tile/TileGenData.java @@ -6,11 +6,11 @@ import mightypork.rogue.world.gen.TileProtectLevel; /** * Data storage for world generator - * + * * @author Ondřej Hruška (MightyPork) */ public class TileGenData { - + public TileProtectLevel protection = TileProtectLevel.NONE; - + } diff --git a/src/mightypork/rogue/world/tile/TileModel.java b/src/mightypork/rogue/world/tile/TileModel.java index 5cc214a..4fdfab6 100644 --- a/src/mightypork/rogue/world/tile/TileModel.java +++ b/src/mightypork/rogue/world/tile/TileModel.java @@ -9,23 +9,24 @@ import mightypork.utils.ion.IonOutput; /** * Tile model (builder) - * + * * @author Ondřej Hruška (MightyPork) */ public final class TileModel { - + /** Model ID */ public final int id; public final Class tileClass; - - - public TileModel(int id, Class tile) { + + + public TileModel(int id, Class tile) + { Tiles.register(id, this); this.id = id; this.tileClass = tile; } - - + + /** * @return new tile of this type */ @@ -37,20 +38,20 @@ public final class TileModel { throw new RuntimeException("Could not instantiate a tile.", e); } } - - + + public Tile loadTile(IonInput in) throws IOException { final Tile t = createTile(); t.load(in); return t; } - - + + public void saveTile(IonOutput out, Tile tile) throws IOException { if (tileClass != tile.getClass()) throw new RuntimeException("Tile class mismatch."); - + tile.save(out); } } diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java index 8dd1932..6f5ed85 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -15,35 +15,36 @@ import mightypork.utils.math.constraints.rect.Rect; /** * Renderer for a tile; each tile has own renderer. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class TileRenderer implements Updateable { - + public static final TileRenderer NONE = new NullTileRenderer(); - + private static TxQuad SH_N, SH_S, SH_E, SH_W, SH_NW, SH_NE, SH_SW, SH_SE; private static TxQuad UFOG_N, UFOG_S, UFOG_E, UFOG_W, UFOG_NW, UFOG_NE, UFOG_SW, UFOG_SE, UFOG_FULL; - + private static boolean inited; - + // data - + public byte shadows; public boolean shadowsComputed; - + protected final Tile tile; - - + + protected Tile getTile() { return tile; } - - - public TileRenderer(Tile tile) { + + + public TileRenderer(Tile tile) + { this.tile = tile; - + if (!inited) { SH_N = Res.getTxQuad("tile.shadow.n"); SH_S = Res.getTxQuad("tile.shadow.s"); @@ -53,7 +54,7 @@ public abstract class TileRenderer implements Updateable { 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"); @@ -66,90 +67,90 @@ public abstract class TileRenderer implements Updateable { inited = true; } } - - + + public abstract void renderTile(TileRenderContext context); - - + + public void renderShadows(TileRenderContext context) { if (!shadowsComputed) { // no shadows computed yet - + shadows = 0; // reset the mask - + for (int i = 0; i < 8; i++) { final Tile t2 = context.getAdjacentTile(Moves.getSide(i)); if (!t2.isNull() && t2.doesCastShadow()) { shadows |= Moves.getBit(i); } } - + shadowsComputed = true; } - + if (shadows == 0) return; final Rect rect = context.getRect(); - + final GraphicsModule gfx = App.gfx(); - + if ((shadows & Moves.BITS_NW_CORNER) == Moves.BIT_NW) gfx.quad(rect, SH_NW); if ((shadows & Moves.BIT_N) != 0) gfx.quad(rect, SH_N); if ((shadows & Moves.BITS_NE_CORNER) == Moves.BIT_NE) gfx.quad(rect, SH_NE); - + if ((shadows & Moves.BIT_W) != 0) gfx.quad(rect, SH_W); if ((shadows & Moves.BIT_E) != 0) gfx.quad(rect, SH_E); - + if ((shadows & Moves.BITS_SW_CORNER) == Moves.BIT_SW) gfx.quad(rect, SH_SW); if ((shadows & Moves.BIT_S) != 0) gfx.quad(rect, SH_S); if ((shadows & Moves.BITS_SE_CORNER) == Moves.BIT_SE) gfx.quad(rect, SH_SE); } - - + + @Stub public void renderExtra(TileRenderContext context) { } - - + + public void renderUnexploredFog(TileRenderContext context) { // TODO cache values, update neighbouring tiles upon "explored" flag changed. - + final GraphicsModule gfx = App.gfx(); - + final Rect rect = context.getRect(); - + if (!context.getTile().isExplored()) { gfx.quad(rect, UFOG_FULL); return; } - + byte ufog = 0; - + for (int i = 0; i < 8; i++) { final Tile t2 = context.getAdjacentTile(Moves.getSide(i)); if (t2.isNull() || !t2.isExplored()) { ufog |= Moves.getBit(i); } } - + if (ufog == 0) return; - + if ((ufog & Moves.BITS_NW_CORNER) == Moves.BIT_NW) gfx.quad(rect, UFOG_NW); if ((ufog & Moves.BIT_N) != 0) gfx.quad(rect, UFOG_N); if ((ufog & Moves.BITS_NE_CORNER) == Moves.BIT_NE) gfx.quad(rect, UFOG_NE); - + if ((ufog & Moves.BIT_W) != 0) gfx.quad(rect, UFOG_W); if ((ufog & Moves.BIT_E) != 0) gfx.quad(rect, UFOG_E); - + if ((ufog & Moves.BITS_SW_CORNER) == Moves.BIT_SW) gfx.quad(rect, UFOG_SW); if ((ufog & Moves.BIT_S) != 0) gfx.quad(rect, UFOG_S); if ((ufog & Moves.BITS_SE_CORNER) == Moves.BIT_SE) gfx.quad(rect, UFOG_SE); - + } - - + + @Override public void update(double delta) { diff --git a/src/mightypork/rogue/world/tile/TileType.java b/src/mightypork/rogue/world/tile/TileType.java index 86fcba0..38a515c 100644 --- a/src/mightypork/rogue/world/tile/TileType.java +++ b/src/mightypork/rogue/world/tile/TileType.java @@ -6,7 +6,7 @@ import mightypork.utils.math.color.Color; /** * Kinds of tiles - * + * * @author Ondřej Hruška (MightyPork) */ public enum TileType @@ -23,23 +23,24 @@ public enum TileType PASSAGE(TileColors.COLLAPSED_WALL, true), /** Stairs */ STAIRS(TileColors.WALL, false); - + private final Color mapColor; private final boolean potentiallyWalkable; - - - private TileType(Color defaultMapColor, boolean potentiallyWalkable) { + + + private TileType(Color defaultMapColor, boolean potentiallyWalkable) + { this.mapColor = defaultMapColor; this.potentiallyWalkable = potentiallyWalkable; } - - + + public Color getMapColor() { return mapColor; } - - + + public boolean isPotentiallyWalkable() { return potentiallyWalkable; diff --git a/src/mightypork/rogue/world/tile/Tiles.java b/src/mightypork/rogue/world/tile/Tiles.java index 0d81029..8b70fb6 100644 --- a/src/mightypork/rogue/world/tile/Tiles.java +++ b/src/mightypork/rogue/world/tile/Tiles.java @@ -4,22 +4,29 @@ package mightypork.rogue.world.tile; import java.io.IOException; import mightypork.rogue.world.tile.impl.NullTile; -import mightypork.rogue.world.tile.impl.brick.*; +import mightypork.rogue.world.tile.impl.brick.TileBrickChest; +import mightypork.rogue.world.tile.impl.brick.TileBrickDoor; +import mightypork.rogue.world.tile.impl.brick.TileBrickEntrance; +import mightypork.rogue.world.tile.impl.brick.TileBrickExit; +import mightypork.rogue.world.tile.impl.brick.TileBrickFloor; +import mightypork.rogue.world.tile.impl.brick.TileBrickPassage; +import mightypork.rogue.world.tile.impl.brick.TileBrickSecretDoor; +import mightypork.rogue.world.tile.impl.brick.TileBrickWall; import mightypork.utils.ion.IonInput; import mightypork.utils.ion.IonOutput; /** * Tile registry - * + * * @author Ondřej Hruška (MightyPork) */ public final class Tiles { - + private static final TileModel[] tiles = new TileModel[256]; - + public static final TileModel NULL = new TileModel(0, NullTile.class); - + public static final TileModel BRICK_FLOOR = new TileModel(10, TileBrickFloor.class); public static final TileModel BRICK_WALL = new TileModel(11, TileBrickWall.class); public static final TileModel BRICK_DOOR = new TileModel(12, TileBrickDoor.class); @@ -28,52 +35,52 @@ public final class Tiles { public static final TileModel BRICK_ENTRANCE = new TileModel(15, TileBrickEntrance.class); public static final TileModel BRICK_EXIT = new TileModel(16, TileBrickExit.class); public static final TileModel BRICK_CHEST = new TileModel(17, TileBrickChest.class); - - + + public static void register(int id, TileModel model) { if (id < 0 || id >= tiles.length) { throw new IllegalArgumentException("Tile ID " + id + " is out of range."); } - + if (tiles[id] != null) { throw new IllegalArgumentException("Tile ID " + id + " already in use."); } - + tiles[id] = model; } - - + + public static TileModel get(int id) { final TileModel m = tiles[id]; - + if (m == null) { throw new IllegalArgumentException("No tile with ID " + id + "."); } - + return m; } - - + + public static Tile loadTile(IonInput in) throws IOException { final int id = in.readIntByte(); - + final TileModel model = get(id); return model.loadTile(in); } - - + + public static void saveTile(IonOutput out, Tile tile) throws IOException { final TileModel model = tile.getModel(); - + out.writeIntByte(model.id); model.saveTile(out, tile); } - - + + public static Tile create(int tileId) { return get(tileId).createTile(); diff --git a/src/mightypork/rogue/world/tile/impl/NullTile.java b/src/mightypork/rogue/world/tile/impl/NullTile.java index 7519eb7..99f5bab 100644 --- a/src/mightypork/rogue/world/tile/impl/NullTile.java +++ b/src/mightypork/rogue/world/tile/impl/NullTile.java @@ -10,79 +10,80 @@ import mightypork.rogue.world.tile.TileType; public class NullTile extends Tile { - - public NullTile(TileModel model) { + + public NullTile(TileModel model) + { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return TileRenderer.NONE; } - - + + @Override public void updateTile(double delta) { } - - + + @Override public void renderTile(TileRenderContext context) { } - - + + @Override public void renderExtra(TileRenderContext context) { } - - + + @Override public boolean isWalkable() { return false; } - - + + @Override public TileType getType() { return TileType.NULL; } - - + + @Override public boolean doesCastShadow() { return false; } - - + + @Override public boolean doesReceiveShadow() { return false; } - - + + @Override public boolean dropItem(Item item) { return false; } - - + + @Override public Item pickItem() { return null; } - - + + @Override public boolean hasItem() { diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseChest.java b/src/mightypork/rogue/world/tile/impl/TileBaseChest.java index cc6607c..8228816 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseChest.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseChest.java @@ -10,66 +10,67 @@ import mightypork.utils.ion.IonOutput; public abstract class TileBaseChest extends TileWithItems { - + public static final double POST_OPEN_DURA = 0.3; public boolean opened = false; public boolean removed = false; public double timeSinceOpen = 10000; - + private int clicks = 1; - - - public TileBaseChest(TileModel model) { + + + public TileBaseChest(TileModel model) + { super(model); } - - + + @Override public TileType getType() { return TileType.FLOOR; } - - + + @Override public boolean isWalkable() { return removed; } - - + + @Override protected boolean shouldRenderItems() { return removed; } - - + + @Override public boolean onClick() { if (opened & removed) return false; - + if (clicks > 0) { clicks--; - + if (clicks == 0) { opened = true; timeSinceOpen = 0; getWorld().getConsole().msgOpenChest(); } - + } else { if (opened && !removed && timeSinceOpen > POST_OPEN_DURA) { removed = true; clicks--; } } - + return true; } - - + + @Override public void save(IonOutput out) throws IOException { @@ -78,8 +79,8 @@ public abstract class TileBaseChest extends TileWithItems { out.writeBoolean(opened); out.writeBoolean(removed); } - - + + @Override public void load(IonInput in) throws IOException { @@ -88,8 +89,8 @@ public abstract class TileBaseChest extends TileWithItems { opened = in.readBoolean(); removed = in.readBoolean(); } - - + + @Override public void updateTile(double delta) { diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseDoor.java b/src/mightypork/rogue/world/tile/impl/TileBaseDoor.java index 0d4cf84..ac3c463 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseDoor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseDoor.java @@ -13,55 +13,56 @@ import mightypork.utils.ion.IonOutput; public abstract class TileBaseDoor extends TileSolid { - + private final DoorTileRenderer renderer; protected boolean locked = false; - - - public TileBaseDoor(TileModel model, TxSheet locked, TxSheet closed, TxSheet open) { + + + public TileBaseDoor(TileModel model, TxSheet locked, TxSheet closed, TxSheet open) + { super(model); - + this.renderer = new DoorTileRenderer(this, locked, closed, open); } - - + + @Override protected TileRenderer makeRenderer() { return renderer; } - - + + @Override public boolean isWalkable() { return !locked; } - - + + @Override public TileType getType() { return TileType.DOOR; } - - + + @Override public void load(IonInput in) throws IOException { super.load(in); locked = in.readBoolean(); } - - + + @Override public void save(IonOutput out) throws IOException { super.save(out); out.writeBoolean(locked); } - - + + /** * @return true if the door appears open */ @@ -69,8 +70,8 @@ public abstract class TileBaseDoor extends TileSolid { { return isOccupied(); } - - + + /** * @return true if the door is locked */ diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java b/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java index 27fc311..205b95a 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java @@ -10,31 +10,32 @@ import mightypork.utils.math.color.Color; public abstract class TileBaseEntrance extends TileBaseStairs { - - public TileBaseEntrance(TileModel model) { + + public TileBaseEntrance(TileModel model) + { super(model); } - - + + @Override public boolean onClick() { final Coord plpos = getWorld().getPlayer().getCoord(); if (!plpos.equals(getLevel().getEnterPoint())) return false; - + App.bus().send(new WorldAscendRequest()); - + return true; } - - + + @Override public boolean doesCastShadow() { return false; } - - + + @Override public Color getMapColor() { diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseExit.java b/src/mightypork/rogue/world/tile/impl/TileBaseExit.java index 71705e9..95f8890 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseExit.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseExit.java @@ -10,31 +10,32 @@ import mightypork.utils.math.color.Color; public abstract class TileBaseExit extends TileBaseStairs { - - public TileBaseExit(TileModel model) { + + public TileBaseExit(TileModel model) + { super(model); } - - + + @Override public boolean onClick() { final Coord plpos = getWorld().getPlayer().getCoord(); if (!plpos.equals(getLevel().getExitPoint())) return false; - + App.bus().send(new WorldDescendRequest()); - + return true; } - - + + @Override public boolean doesCastShadow() { return false; } - - + + @Override public Color getMapColor() { diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseFloor.java b/src/mightypork/rogue/world/tile/impl/TileBaseFloor.java index 0ca4083..ebeea41 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseFloor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseFloor.java @@ -9,23 +9,24 @@ import mightypork.rogue.world.tile.render.BasicTileRenderer; public abstract class TileBaseFloor extends TileWithItems { - + private final BasicTileRenderer renderer; - - - public TileBaseFloor(TileModel model, TxSheet sheet) { + + + public TileBaseFloor(TileModel model, TxSheet sheet) + { super(model); this.renderer = new BasicTileRenderer(this, sheet); } - - + + @Override protected TileRenderer makeRenderer() { return renderer; } - - + + @Override public TileType getType() { diff --git a/src/mightypork/rogue/world/tile/impl/TileBasePassage.java b/src/mightypork/rogue/world/tile/impl/TileBasePassage.java index 6f33542..10cb630 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBasePassage.java +++ b/src/mightypork/rogue/world/tile/impl/TileBasePassage.java @@ -10,39 +10,40 @@ import mightypork.rogue.world.tile.render.BasicTileRenderer; /** * Collapsed wall that's walk-through - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class TileBasePassage extends TileSolid { - + private final BasicTileRenderer renderer; - - - public TileBasePassage(TileModel model, TxSheet sheet) { + + + public TileBasePassage(TileModel model, TxSheet sheet) + { super(model); - + this.renderer = new BasicTileRenderer(this, sheet); } - - + + @Override protected TileRenderer makeRenderer() { return renderer; } - - + + @Override public TileType getType() { return TileType.PASSAGE; } - - + + @Override public boolean isWalkable() { return true; } - + } diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java b/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java index 560d8d9..5afa501 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java @@ -12,47 +12,48 @@ import mightypork.utils.math.color.Color; public abstract class TileBaseSecretDoor extends TileBaseDoor { - + private int clicks = 2; - - - public TileBaseSecretDoor(TileModel model, TxSheet secret, TxSheet closed, TxSheet open) { + + + public TileBaseSecretDoor(TileModel model, TxSheet secret, TxSheet closed, TxSheet open) + { super(model, secret, closed, open); } - - + + @Override public boolean onClick() { if (!locked) return false; - + if (clicks > 0) clicks--; - + if (clicks == 0) { locked = false; getWorld().getConsole().msgDiscoverSecretDoor(); } - + return true; } - - + + @Override public Color getMapColor() { if (locked) return TileColors.SECRET_DOOR_HIDDEN; return TileColors.SECRET_DOOR_REVEALED; } - - + + @Override public void save(IonOutput out) throws IOException { super.save(out); out.writeIntByte(clicks); } - - + + @Override public void load(IonInput in) throws IOException { diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseStairs.java b/src/mightypork/rogue/world/tile/impl/TileBaseStairs.java index 19949de..4bb0bff 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseStairs.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseStairs.java @@ -6,16 +6,17 @@ import mightypork.rogue.world.tile.TileType; public abstract class TileBaseStairs extends TileSolid { - - public TileBaseStairs(TileModel model) { + + public TileBaseStairs(TileModel model) + { super(model); } - - + + @Override public TileType getType() { return TileType.STAIRS; } - + } diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseWall.java b/src/mightypork/rogue/world/tile/impl/TileBaseWall.java index 5975352..e68bbb3 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseWall.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseWall.java @@ -8,23 +8,24 @@ import mightypork.rogue.world.tile.render.BasicTileRenderer; public abstract class TileBaseWall extends TileSolid { - + private final BasicTileRenderer renderer; - - - public TileBaseWall(TileModel model, TxSheet sheet) { + + + public TileBaseWall(TileModel model, TxSheet sheet) + { super(model); this.renderer = new BasicTileRenderer(this, sheet); } - - + + @Override public BasicTileRenderer makeRenderer() { return renderer; } - - + + @Override public TileType getType() { diff --git a/src/mightypork/rogue/world/tile/impl/TileSolid.java b/src/mightypork/rogue/world/tile/impl/TileSolid.java index 0ef40ce..2b034b4 100644 --- a/src/mightypork/rogue/world/tile/impl/TileSolid.java +++ b/src/mightypork/rogue/world/tile/impl/TileSolid.java @@ -7,40 +7,41 @@ import mightypork.rogue.world.tile.TileModel; public abstract class TileSolid extends Tile { - - public TileSolid(TileModel model) { + + public TileSolid(TileModel model) + { super(model); } - - + + @Override public boolean isWalkable() { return false; } - - + + @Override public boolean doesCastShadow() { return true; } - - + + @Override public boolean hasItem() { return false; } - - + + @Override public boolean dropItem(Item item) { return false; } - - + + @Override public Item pickItem() { diff --git a/src/mightypork/rogue/world/tile/impl/TileWithItems.java b/src/mightypork/rogue/world/tile/impl/TileWithItems.java index f7e9336..1847bee 100644 --- a/src/mightypork/rogue/world/tile/impl/TileWithItems.java +++ b/src/mightypork/rogue/world/tile/impl/TileWithItems.java @@ -16,95 +16,96 @@ import mightypork.utils.ion.IonOutput; public abstract class TileWithItems extends Tile { - + private final DroppedItemRenderer itemRenderer = new DroppedItemRenderer(); - + protected final Stack items = new Stack<>(); - - - public TileWithItems(TileModel model) { + + + public TileWithItems(TileModel model) + { super(model); } - - + + @Override public void renderExtra(TileRenderContext context) { super.renderExtra(context); - + if ((isExplored() || !Const.RENDER_UFOG) && hasItem() && shouldRenderItems()) { itemRenderer.render(items, context); } } - - + + protected boolean shouldRenderItems() { return true; } - - + + @Override public void updateTile(double delta) { super.updateTile(delta); itemRenderer.update(delta); } - - + + @Override public void save(IonOutput out) throws IOException { super.save(out); - + Items.saveItems(out, items); } - - + + @Override public void load(IonInput in) throws IOException { super.load(in); - + Items.loadItems(in, items); } - - + + @Override public boolean doesCastShadow() { return false; } - - + + @Override public boolean isWalkable() { return true; } - - + + @Override public boolean dropItem(Item item) { items.push(item); return true; } - - + + @Override public Item pickItem() { return hasItem() ? items.pop() : null; } - - + + @Override public boolean hasItem() { return !items.isEmpty(); } - + // @Override // public boolean onClick() // { diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java index 794c80c..4286ef7 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java @@ -9,16 +9,17 @@ import mightypork.rogue.world.tile.render.ChestRenderer; public class TileBrickChest extends TileBaseChest { - - public TileBrickChest(TileModel model) { + + public TileBrickChest(TileModel model) + { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return new ChestRenderer(this, Res.getTxQuad("tile.brick.floor"), Res.getTxQuad("tile.extra.chest.closed"), Res.getTxQuad("tile.extra.chest.open")); } - + } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java index cd60cad..1592e16 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java @@ -7,16 +7,17 @@ import mightypork.rogue.world.tile.impl.TileBaseDoor; public class TileBrickDoor extends TileBaseDoor { - - public TileBrickDoor(TileModel model) { + + public TileBrickDoor(TileModel model) + { //@formatter:off super( - model, - Res.getTxSheet("tile.brick.door.closed"), // LOCKED - Res.getTxSheet("tile.brick.door.closed"), - Res.getTxSheet("tile.brick.door.open") - ); + model, + Res.getTxSheet("tile.brick.door.closed"), // LOCKED + Res.getTxSheet("tile.brick.door.closed"), + Res.getTxSheet("tile.brick.door.open") + ); //@formatter:on } - + } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java index 97c6ca1..279e8ba 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java @@ -9,16 +9,17 @@ import mightypork.rogue.world.tile.render.OneFrameTileRenderer; public class TileBrickEntrance extends TileBaseEntrance { - - public TileBrickEntrance(TileModel model) { + + public TileBrickEntrance(TileModel model) + { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return new OneFrameTileRenderer(this, Res.getTxQuad("tile.brick.stairs.up")); } - + } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java index 337e0f0..4c3a72a 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java @@ -9,16 +9,17 @@ import mightypork.rogue.world.tile.render.OneFrameTileRenderer; public class TileBrickExit extends TileBaseExit { - - public TileBrickExit(TileModel model) { + + public TileBrickExit(TileModel model) + { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return new OneFrameTileRenderer(this, Res.getTxQuad("tile.brick.stairs.down")); } - + } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java index b50c1c6..0cb6d6d 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java @@ -7,9 +7,10 @@ import mightypork.rogue.world.tile.impl.TileBaseFloor; public class TileBrickFloor extends TileBaseFloor { - - public TileBrickFloor(TileModel model) { + + public TileBrickFloor(TileModel model) + { super(model, Res.getTxSheet("tile.brick.floor")); } - + } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java index 9265712..1287898 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java @@ -7,9 +7,10 @@ import mightypork.rogue.world.tile.impl.TileBasePassage; public class TileBrickPassage extends TileBasePassage { - - public TileBrickPassage(TileModel model) { + + public TileBrickPassage(TileModel model) + { super(model, Res.getTxSheet("tile.brick.passage")); } - + } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java index b87db09..dc591aa 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java @@ -7,17 +7,18 @@ import mightypork.rogue.world.tile.impl.TileBaseSecretDoor; public class TileBrickSecretDoor extends TileBaseSecretDoor { - - public TileBrickSecretDoor(TileModel model) { + + public TileBrickSecretDoor(TileModel model) + { //@formatter:off super( - model, - Res.getTxSheet("tile.brick.door.secret"), - Res.getTxSheet("tile.brick.door.closed"), - Res.getTxSheet("tile.brick.door.open") - ); + model, + Res.getTxSheet("tile.brick.door.secret"), + Res.getTxSheet("tile.brick.door.closed"), + Res.getTxSheet("tile.brick.door.open") + ); //@formatter:on - + locked = true; // hide it } } diff --git a/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java b/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java index 90d1c70..de33a55 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java @@ -7,9 +7,10 @@ import mightypork.rogue.world.tile.impl.TileBaseWall; public class TileBrickWall extends TileBaseWall { - - public TileBrickWall(TileModel model) { + + public TileBrickWall(TileModel model) + { super(model, Res.getTxSheet("tile.brick.wall")); } - + } diff --git a/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java b/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java index c64afa3..f6999fe 100644 --- a/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java @@ -10,16 +10,17 @@ import mightypork.utils.math.constraints.rect.Rect; public class BasicTileRenderer extends TileRenderer { - + private final TxSheet sheet; - - - public BasicTileRenderer(Tile tile, TxSheet sheet) { + + + public BasicTileRenderer(Tile tile, TxSheet sheet) + { super(tile); this.sheet = sheet; } - - + + @Override public void renderTile(TileRenderContext context) { diff --git a/src/mightypork/rogue/world/tile/render/ChestRenderer.java b/src/mightypork/rogue/world/tile/render/ChestRenderer.java index 2ef6b91..bdc9cbf 100644 --- a/src/mightypork/rogue/world/tile/render/ChestRenderer.java +++ b/src/mightypork/rogue/world/tile/render/ChestRenderer.java @@ -9,32 +9,33 @@ import mightypork.rogue.world.tile.impl.TileBaseChest; public class ChestRenderer extends TileRenderer { - + private final TxQuad txqFloor; private final TxQuad txqChest; - + private final TileBaseChest chestTile; private final TxQuad txqChestOpen; - - - public ChestRenderer(TileBaseChest tile, TxQuad txq, TxQuad chest, TxQuad chestOpen) { + + + public ChestRenderer(TileBaseChest tile, TxQuad txq, TxQuad chest, TxQuad chestOpen) + { super(tile); - + this.chestTile = tile; - + this.txqFloor = txq; this.txqChest = chest; this.txqChestOpen = chestOpen; } - - + + @Override public void renderTile(TileRenderContext context) { App.gfx().quad(context.getRect(), txqFloor); } - - + + @Override public void renderExtra(TileRenderContext context) { diff --git a/src/mightypork/rogue/world/tile/render/DoorTileRenderer.java b/src/mightypork/rogue/world/tile/render/DoorTileRenderer.java index a99bcd6..d352b37 100644 --- a/src/mightypork/rogue/world/tile/render/DoorTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/DoorTileRenderer.java @@ -11,43 +11,44 @@ import mightypork.utils.math.timing.TimedTask; public class DoorTileRenderer extends TileRenderer { - + private final TxSheet locked; private final TxSheet closed; private final TxSheet open; - + private boolean visuallyOpen = false; - + private final TimedTask closeTask = new TimedTask() { - + @Override public void run() { visuallyOpen = ((TileBaseDoor) tile).isOpen(); } }; - - - public DoorTileRenderer(TileBaseDoor doorTile, TxSheet locked, TxSheet closed, TxSheet open) { + + + public DoorTileRenderer(TileBaseDoor doorTile, TxSheet locked, TxSheet closed, TxSheet open) + { super(doorTile); - + this.locked = locked; this.closed = closed; this.open = open; } - - + + @Override public void renderTile(TileRenderContext context) { final Rect rect = context.getRect(); - + if (!visuallyOpen && ((TileBaseDoor) tile).isOpen()) visuallyOpen = true; - + if (visuallyOpen && !((TileBaseDoor) tile).isOpen()) { if (!closeTask.isRunning()) closeTask.start(0.4); } - + if (visuallyOpen) { App.gfx().quad(rect, open.getRandomQuad(context.getTileNoise())); } else { @@ -55,12 +56,12 @@ public class DoorTileRenderer extends TileRenderer { App.gfx().quad(rect, sheet.getRandomQuad(context.getTileNoise())); } } - - + + @Override public void update(double delta) { closeTask.update(delta); } - + } diff --git a/src/mightypork/rogue/world/tile/render/NullTileRenderer.java b/src/mightypork/rogue/world/tile/render/NullTileRenderer.java index 5564cb8..7ac02fc 100644 --- a/src/mightypork/rogue/world/tile/render/NullTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/NullTileRenderer.java @@ -7,37 +7,38 @@ import mightypork.rogue.world.tile.TileRenderer; /** * Do-nothing tile renderer - * + * * @author Ondřej Hruška (MightyPork) */ public class NullTileRenderer extends TileRenderer { - - public NullTileRenderer() { + + public NullTileRenderer() + { super(null); } - - + + @Override public void renderTile(TileRenderContext context) { } - - + + @Override public void renderShadows(TileRenderContext context) { } - - + + @Override public void renderUnexploredFog(TileRenderContext context) { } - - + + @Override public void update(double delta) { } - + } diff --git a/src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java b/src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java index db07558..414685d 100644 --- a/src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java @@ -10,20 +10,21 @@ import mightypork.rogue.world.tile.TileRenderer; /** * Tile that spans across two tiles visually (two-high) - * + * * @author Ondřej Hruška (MightyPork) */ public class OneFrameTileRenderer extends TileRenderer { - + private final TxQuad txq; - - - public OneFrameTileRenderer(Tile tile, TxQuad txq) { + + + public OneFrameTileRenderer(Tile tile, TxQuad txq) + { super(tile); this.txq = txq; } - - + + @Override public void renderTile(TileRenderContext context) { diff --git a/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java b/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java index 5583e6c..fafcf78 100644 --- a/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java @@ -11,20 +11,21 @@ import mightypork.utils.math.constraints.rect.Rect; /** * Tile that spans across two tiles visually (two-high) - * + * * @author Ondřej Hruška (MightyPork) */ public class TwoHighTileRenderer extends TileRenderer { - + private final TxQuad txq; - - - public TwoHighTileRenderer(Tile tile, TxQuad txq) { + + + public TwoHighTileRenderer(Tile tile, TxQuad txq) + { super(tile); this.txq = txq; } - - + + @Override public void renderTile(TileRenderContext context) {