From cf096bcce5d245950599f8841fb8f42fecf386af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 29 Jul 2014 14:14:24 +0200 Subject: [PATCH] Reflecting engine changes, some init task improvements --- .gitignore | 1 + src/mightypork/rogue/Const.java | 10 +- src/mightypork/rogue/Launcher.java | 38 +- src/mightypork/rogue/RogueApp.java | 81 ++-- src/mightypork/rogue/RogueStateManager.java | 18 +- .../rogue/events/LoadingOverlayRequest.java | 12 +- .../rogue/events/RogueStateRequest.java | 14 +- ...dResources.java => RogueAddResources.java} | 70 ++-- .../{InitScreens.java => RogueInitUI.java} | 18 +- ...SetupConfig.java => RogueSetupConfig.java} | 30 +- ...tupDisplay.java => RogueSetupDisplay.java} | 8 +- ...balKeys.java => RogueSetupGlobalKeys.java} | 4 +- ...tupWorkdir.java => RogueSetupWorkdir.java} | 10 +- src/mightypork/rogue/screens/FpsOverlay.java | 28 +- .../rogue/screens/LoadingOverlay.java | 46 +-- src/mightypork/rogue/screens/RogueScreen.java | 12 +- .../rogue/screens/game/HeartBar.java | 22 +- .../rogue/screens/game/IngameNav.java | 36 +- .../rogue/screens/game/InvSlot.java | 80 ++-- .../rogue/screens/game/LayerAskSave.java | 64 ++-- .../rogue/screens/game/LayerDeath.java | 40 +- .../rogue/screens/game/LayerGameUi.java | 86 ++--- .../rogue/screens/game/LayerInv.java | 146 ++++---- .../rogue/screens/game/LayerMapView.java | 26 +- .../rogue/screens/game/LayerWin.java | 36 +- .../rogue/screens/game/NavButton.java | 18 +- .../rogue/screens/game/ScreenGame.java | 156 ++++---- .../rogue/screens/menu/ScreenMainMenu.java | 52 +-- .../select_world/ScreenSelectWorld.java | 44 +-- .../rogue/screens/select_world/WorldSlot.java | 88 ++--- .../rogue/screens/story/ScreenStory.java | 111 +++--- src/mightypork/rogue/world/Inventory.java | 74 ++-- src/mightypork/rogue/world/PlayerControl.java | 80 ++-- src/mightypork/rogue/world/PlayerData.java | 64 ++-- src/mightypork/rogue/world/PlayerFacade.java | 218 +++++------ src/mightypork/rogue/world/World.java | 132 +++---- src/mightypork/rogue/world/WorldConsole.java | 136 +++---- src/mightypork/rogue/world/WorldProvider.java | 66 ++-- src/mightypork/rogue/world/WorldRenderer.java | 90 ++--- .../rogue/world/entity/AiTimer.java | 18 +- .../rogue/world/entity/Entities.java | 44 +-- src/mightypork/rogue/world/entity/Entity.java | 150 ++++---- .../rogue/world/entity/EntityModel.java | 26 +- .../rogue/world/entity/EntityModule.java | 22 +- .../rogue/world/entity/EntityPathFinder.java | 28 +- .../rogue/world/entity/EntityRenderer.java | 4 +- .../rogue/world/entity/impl/BossRatAi.java | 28 +- .../rogue/world/entity/impl/BrownRatAi.java | 20 +- .../world/entity/impl/EntityBossRat.java | 38 +- .../world/entity/impl/EntityBrownRat.java | 42 +-- .../world/entity/impl/EntityGrayRat.java | 44 +-- .../rogue/world/entity/impl/EntityPlayer.java | 76 ++-- .../rogue/world/entity/impl/GrayRatAi.java | 24 +- .../rogue/world/entity/impl/MonsterAi.java | 200 +++++----- .../entity/modules/EntityModuleHealth.java | 72 ++-- .../entity/modules/EntityModulePosition.java | 134 +++---- .../entity/modules/EntityMoveListener.java | 12 +- .../rogue/world/entity/modules/EntityPos.java | 98 ++--- .../entity/render/EntityRendererMobLR.java | 38 +- .../rogue/world/events/GameWinEvent.java | 2 +- .../rogue/world/events/GameWinHandler.java | 4 +- .../world/events/PlayerDeathHandler.java | 2 +- .../rogue/world/events/PlayerKilledEvent.java | 4 +- .../world/events/PlayerStepEndEvent.java | 12 +- .../world/events/PlayerStepEndListener.java | 2 +- .../world/events/WorldAscendRequest.java | 4 +- .../events/WorldAscendRequestListener.java | 2 +- .../world/events/WorldDescendRequest.java | 4 +- .../events/WorldDescendRequestListener.java | 2 +- .../rogue/world/events/WorldPauseRequest.java | 20 +- .../rogue/world/gen/LevelBuilder.java | 110 +++--- src/mightypork/rogue/world/gen/MapTheme.java | 30 +- .../rogue/world/gen/RoomBuilder.java | 2 +- src/mightypork/rogue/world/gen/RoomEntry.java | 22 +- src/mightypork/rogue/world/gen/Rooms.java | 10 +- .../rogue/world/gen/ScratchMap.java | 352 +++++++++--------- .../rogue/world/gen/WorldCreator.java | 78 ++-- .../rogue/world/gen/WorldGenError.java | 16 +- .../world/gen/rooms/AbstractRectRoom.java | 52 +-- .../rogue/world/gen/rooms/BasicRoom.java | 14 +- .../rogue/world/gen/rooms/BossRoom.java | 26 +- .../rogue/world/gen/rooms/DeadEndRoom.java | 14 +- .../rogue/world/gen/rooms/EntranceRoom.java | 20 +- .../rogue/world/gen/rooms/ExitRoom.java | 20 +- .../rogue/world/gen/rooms/ItemShrineRoom.java | 20 +- .../rogue/world/gen/rooms/SecretRoom.java | 14 +- .../rogue/world/gen/rooms/StorageRoom.java | 18 +- .../world/gen/rooms/TreasureChestRoom.java | 10 +- .../rogue/world/gen/themes/ThemeBrick.java | 30 +- src/mightypork/rogue/world/gui/MapView.java | 88 ++--- src/mightypork/rogue/world/gui/Minimap.java | 32 +- .../rogue/world/gui/WorldConsoleRenderer.java | 50 +-- .../world/gui/interaction/MIPKeyboard.java | 70 ++-- .../rogue/world/gui/interaction/MIPMouse.java | 70 ++-- .../gui/interaction/MapInteractionPlugin.java | 22 +- src/mightypork/rogue/world/item/Item.java | 122 +++--- .../rogue/world/item/ItemModel.java | 28 +- .../rogue/world/item/ItemRenderer.java | 12 +- src/mightypork/rogue/world/item/Items.java | 44 +-- .../rogue/world/item/impl/ItemBaseFood.java | 22 +- .../rogue/world/item/impl/ItemBaseWeapon.java | 20 +- .../item/impl/active/ItemHeartPiece.java | 44 +-- .../world/item/impl/food/ItemCheese.java | 14 +- .../rogue/world/item/impl/food/ItemMeat.java | 14 +- .../world/item/impl/food/ItemSandwich.java | 14 +- .../world/item/impl/weapons/ItemAxe.java | 18 +- .../world/item/impl/weapons/ItemBone.java | 18 +- .../world/item/impl/weapons/ItemClub.java | 18 +- .../world/item/impl/weapons/ItemKnife.java | 18 +- .../world/item/impl/weapons/ItemRock.java | 18 +- .../world/item/impl/weapons/ItemSword.java | 18 +- .../world/item/impl/weapons/ItemTwig.java | 18 +- .../world/item/render/QuadItemRenderer.java | 12 +- src/mightypork/rogue/world/level/Level.java | 284 +++++++------- .../level/render/EntityRenderContext.java | 4 +- .../world/level/render/MapRenderContext.java | 20 +- .../world/level/render/TileRenderContext.java | 38 +- .../rogue/world/tile/DroppedItemRenderer.java | 18 +- src/mightypork/rogue/world/tile/Tile.java | 154 ++++---- .../rogue/world/tile/TileColors.java | 8 +- .../rogue/world/tile/TileGenData.java | 4 +- .../rogue/world/tile/TileModel.java | 20 +- .../rogue/world/tile/TileRenderer.java | 80 ++-- src/mightypork/rogue/world/tile/TileType.java | 14 +- src/mightypork/rogue/world/tile/Tiles.java | 38 +- .../rogue/world/tile/impl/NullTile.java | 46 +-- .../rogue/world/tile/impl/TileBaseChest.java | 44 +-- .../rogue/world/tile/impl/TileBaseDoor.java | 36 +- .../world/tile/impl/TileBaseEntrance.java | 18 +- .../rogue/world/tile/impl/TileBaseExit.java | 18 +- .../rogue/world/tile/impl/TileBaseFloor.java | 14 +- .../world/tile/impl/TileBasePassage.java | 22 +- .../world/tile/impl/TileBaseSecretDoor.java | 28 +- .../rogue/world/tile/impl/TileBaseStairs.java | 8 +- .../rogue/world/tile/impl/TileBaseWall.java | 14 +- .../rogue/world/tile/impl/TileSolid.java | 22 +- .../rogue/world/tile/impl/TileWithItems.java | 56 +-- .../world/tile/impl/brick/TileBrickChest.java | 8 +- .../world/tile/impl/brick/TileBrickDoor.java | 4 +- .../tile/impl/brick/TileBrickEntrance.java | 8 +- .../world/tile/impl/brick/TileBrickExit.java | 8 +- .../world/tile/impl/brick/TileBrickFloor.java | 4 +- .../tile/impl/brick/TileBrickPassage.java | 4 +- .../tile/impl/brick/TileBrickSecretDoor.java | 4 +- .../world/tile/impl/brick/TileBrickWall.java | 4 +- .../world/tile/render/BasicTileRenderer.java | 10 +- .../world/tile/render/ChestRenderer.java | 20 +- .../world/tile/render/DoorTileRenderer.java | 30 +- .../world/tile/render/NullTileRenderer.java | 20 +- .../tile/render/OneFrameTileRenderer.java | 10 +- .../tile/render/TwoHighTileRenderer.java | 10 +- 151 files changed, 3119 insertions(+), 3136 deletions(-) rename src/mightypork/rogue/init/{AddResources.java => RogueAddResources.java} (98%) rename src/mightypork/rogue/init/{InitScreens.java => RogueInitUI.java} (89%) rename src/mightypork/rogue/init/{SetupConfig.java => RogueSetupConfig.java} (95%) rename src/mightypork/rogue/init/{SetupDisplay.java => RogueSetupDisplay.java} (89%) rename src/mightypork/rogue/init/{SetupGlobalKeys.java => RogueSetupGlobalKeys.java} (92%) rename src/mightypork/rogue/init/{SetupWorkdir.java => RogueSetupWorkdir.java} (75%) diff --git a/.gitignore b/.gitignore index 597163c..b253759 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /target/ /~local/ /.rogue-save/ +/rogue-workdir/ /build/out/*.jar /build/in/*.jar *.log diff --git a/src/mightypork/rogue/Const.java b/src/mightypork/rogue/Const.java index c5d61aa..400644e 100644 --- a/src/mightypork/rogue/Const.java +++ b/src/mightypork/rogue/Const.java @@ -7,20 +7,20 @@ package mightypork.rogue; * @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 c0087b7..1715e33 100644 --- a/src/mightypork/rogue/Launcher.java +++ b/src/mightypork/rogue/Launcher.java @@ -9,7 +9,7 @@ import mightypork.utils.files.OsUtils; public class Launcher { - + /** * Launcher * @@ -18,72 +18,72 @@ public class Launcher { public static void main(String[] args) { // System.out.println("argv = " + Arrays.toString(args)+"\n"); - + Level llSyso = Level.FINER; - + 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(workdir, llSyso); - if (logBus) App.bus().detailedLogging = true; + final App app = new RogueApp(workdir, llSyso); + if (logBus) App.bus().detailedLogging = true; + app.start(); } - - + + private static void printHelp() { //@formatter:off diff --git a/src/mightypork/rogue/RogueApp.java b/src/mightypork/rogue/RogueApp.java index 60dcfd3..8a97a64 100644 --- a/src/mightypork/rogue/RogueApp.java +++ b/src/mightypork/rogue/RogueApp.java @@ -6,15 +6,10 @@ import java.util.logging.Level; import mightypork.gamecore.backends.lwjgl.LwjglBackend; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.DeltaMainLoop; -import mightypork.gamecore.core.MainLoop; import mightypork.gamecore.core.events.MainLoopRequest; -import mightypork.gamecore.core.init.InitTaskCrashHandler; import mightypork.gamecore.core.init.InitTaskIonizables; import mightypork.gamecore.core.init.InitTaskLog; import mightypork.gamecore.core.init.InitTaskLogHeader; -import mightypork.gamecore.core.init.InitTaskMainLoop; -import mightypork.gamecore.core.init.InitTaskResourceLoaderAsync; import mightypork.gamecore.core.plugins.screenshot.InitTaskPluginScreenshot; import mightypork.gamecore.core.plugins.screenshot.ScreenshotRequestListener; import mightypork.gamecore.gui.events.ViewportChangeEvent; @@ -22,12 +17,12 @@ import mightypork.gamecore.gui.events.ViewportChangeListener; import mightypork.gamecore.resources.Res; import mightypork.rogue.RogueStateManager.RogueState; import mightypork.rogue.events.RogueStateRequest; -import mightypork.rogue.init.AddResources; -import mightypork.rogue.init.InitScreens; -import mightypork.rogue.init.SetupConfig; -import mightypork.rogue.init.SetupDisplay; -import mightypork.rogue.init.SetupGlobalKeys; -import mightypork.rogue.init.SetupWorkdir; +import mightypork.rogue.init.RogueAddResources; +import mightypork.rogue.init.RogueInitUI; +import mightypork.rogue.init.RogueSetupConfig; +import mightypork.rogue.init.RogueSetupDisplay; +import mightypork.rogue.init.RogueSetupGlobalKeys; +import mightypork.rogue.init.RogueSetupWorkdir; import mightypork.rogue.world.Inventory; import mightypork.utils.ion.Ion; import mightypork.utils.logging.Log; @@ -39,13 +34,13 @@ import mightypork.utils.logging.Log; * @author Ondřej Hruška (MightyPork) */ public final class RogueApp extends App implements ViewportChangeListener, ScreenshotRequestListener { - + public RogueApp(File workdir, final Level logStdout) { super(new LwjglBackend()); - + addInitTask(new InitTaskLog() { - + @Override public void init() { @@ -55,25 +50,24 @@ public final class RogueApp extends App implements ViewportChangeListener, Scree setLogName("runtime"); } }); - + addInitTask(new InitTaskLogHeader() { - + @Override public void before() { Log.i("## Starting Rogue v." + Const.VERSION + " ##"); } }); - - addInitTask(new InitTaskCrashHandler()); - addInitTask(new SetupWorkdir(workdir)); - - addInitTask(new SetupConfig()); - + + addInitTask(new RogueSetupWorkdir(workdir)); + + addInitTask(new RogueSetupConfig()); + addInitTask(new InitTaskPluginScreenshot("screenshots")); - + addInitTask(new InitTaskIonizables() { - + @Override public void after() { @@ -81,38 +75,27 @@ public final class RogueApp extends App implements ViewportChangeListener, Scree Ion.register(Inventory.class); } }); - - - addInitTask(new SetupDisplay()); - addInitTask(new SetupGlobalKeys()); - addInitTask(new InitTaskResourceLoaderAsync()); - addInitTask(new AddResources()); - addInitTask(new InitTaskMainLoop() { - - @Override - protected MainLoop getLoopImpl() - { - return new DeltaMainLoop(); - } - }); - - addInitTask(new InitScreens()); + + addInitTask(new RogueSetupDisplay()); + addInitTask(new RogueSetupGlobalKeys()); + addInitTask(new RogueAddResources()); + addInitTask(new RogueInitUI()); } - - + + @Override public void onScreenshotRequest() { Res.sound("gui.shutter").play(0.8); } - - + + @Override protected void postInit() { bus().send(new MainLoopRequest(new Runnable() { - + @Override public void run() { @@ -125,16 +108,16 @@ public final class RogueApp extends App implements ViewportChangeListener, Scree } }, false)); } - - + + @Override public void onViewportChanged(ViewportChangeEvent event) { // save viewport size to config file final boolean fs = gfx().isFullscreen(); - + cfg().setValue("display.fullscreen", fs); - + if (!fs) { cfg().setValue("display.width", gfx().getWidth()); cfg().setValue("display.height", gfx().getHeight()); diff --git a/src/mightypork/rogue/RogueStateManager.java b/src/mightypork/rogue/RogueStateManager.java index cd063e2..586fef0 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 b56e9fb..7949a05 100644 --- a/src/mightypork/rogue/events/LoadingOverlayRequest.java +++ b/src/mightypork/rogue/events/LoadingOverlayRequest.java @@ -13,11 +13,11 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; */ @SingleReceiverEvent public class LoadingOverlayRequest extends BusEvent { - + private final String msg; private final Runnable task; - - + + /** * @param msg task description * @param task task runnable @@ -27,12 +27,12 @@ public class LoadingOverlayRequest extends BusEvent { 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 33867a3..eb6277c 100644 --- a/src/mightypork/rogue/events/RogueStateRequest.java +++ b/src/mightypork/rogue/events/RogueStateRequest.java @@ -12,25 +12,25 @@ import mightypork.utils.eventbus.BusEvent; * @author Ondřej Hruška (MightyPork) */ public class RogueStateRequest extends BusEvent { - + final private RogueState requested; private final boolean fromDark; - - + + public RogueStateRequest(RogueState requested) { this.requested = requested; this.fromDark = false; } - - + + public RogueStateRequest(RogueState requested, boolean fromDark) { this.requested = requested; this.fromDark = fromDark; } - - + + @Override protected void handleBy(RogueStateManager handler) { diff --git a/src/mightypork/rogue/init/AddResources.java b/src/mightypork/rogue/init/RogueAddResources.java similarity index 98% rename from src/mightypork/rogue/init/AddResources.java rename to src/mightypork/rogue/init/RogueAddResources.java index b1c04d4..58df105 100644 --- a/src/mightypork/rogue/init/AddResources.java +++ b/src/mightypork/rogue/init/RogueAddResources.java @@ -15,29 +15,29 @@ import mightypork.gamecore.graphics.textures.WrapMode; import mightypork.utils.math.constraints.rect.Rect; -public class AddResources extends InitTaskResources { - +public class RogueAddResources extends InitTaskResources { + @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 = App.gfx().createFont("/res/font/PressStart2P.ttf", Glyphs.basic, 16)); - + fonts.addFont("battlenet", font = App.gfx().createFont("/res/font/battlenet.ttf", Glyphs.basic, 16)); font.setDiscardRatio(3 / 16D, 2 / 16D); - + fonts.addFont("tinyutf", font = App.gfx().createFont("/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) { @@ -45,42 +45,42 @@ public class AddResources extends InitTaskResources { 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.loadTexture("/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)); @@ -88,14 +88,14 @@ public class AddResources extends InitTaskResources { 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)); @@ -106,10 +106,10 @@ public class AddResources extends InitTaskResources { 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.loadTexture("/res/img/sprites.png", FilterMode.NEAREST, WrapMode.CLAMP); grid = texture.grid(8, 8); @@ -118,7 +118,7 @@ public class AddResources extends InitTaskResources { 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.loadTexture("/res/img/logo.png", FilterMode.NEAREST, WrapMode.CLAMP); textures.add("logo", texture.makeQuad(Rect.make(0, 0, 0.543, 0.203))); @@ -126,52 +126,52 @@ public class AddResources extends InitTaskResources { 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)); @@ -186,5 +186,5 @@ public class AddResources extends InitTaskResources { textures.add("item.knife", grid.makeQuad(1, 1)); textures.add("item.twig", grid.makeQuad(2, 1)); } - + } diff --git a/src/mightypork/rogue/init/InitScreens.java b/src/mightypork/rogue/init/RogueInitUI.java similarity index 89% rename from src/mightypork/rogue/init/InitScreens.java rename to src/mightypork/rogue/init/RogueInitUI.java index d7e2df9..25d0d9c 100644 --- a/src/mightypork/rogue/init/InitScreens.java +++ b/src/mightypork/rogue/init/RogueInitUI.java @@ -2,7 +2,7 @@ package mightypork.rogue.init; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.init.InitTaskScreens; +import mightypork.gamecore.core.init.InitTaskUI; import mightypork.gamecore.graphics.Renderable; import mightypork.gamecore.gui.screens.ScreenRegistry; import mightypork.gamecore.gui.screens.impl.CrossfadeOverlay; @@ -16,28 +16,28 @@ import mightypork.rogue.screens.story.ScreenStory; import mightypork.rogue.world.WorldProvider; -public class InitScreens extends InitTaskScreens { - +public class RogueInitUI extends InitTaskUI { + @Override - protected Renderable getMainRenderableImpl() + protected Renderable createMainRenderable() { final ScreenRegistry screens = new ScreenRegistry(); app.addChildClient(screens); - + /* game screen references world provider instance */ App.bus().subscribe(new RogueStateManager()); App.bus().subscribe(WorldProvider.get()); - - screens.addOverlay(new CrossfadeOverlay()); + screens.addOverlay(new CrossfadeOverlay()); + screens.addScreen("main_menu", new ScreenMainMenu()); screens.addScreen("select_world", new ScreenSelectWorld()); screens.addScreen("game", new ScreenGame()); screens.addScreen("story", new ScreenStory()); - + screens.addOverlay(new FpsOverlay()); screens.addOverlay(new LoadingOverlay()); - + return screens; } } diff --git a/src/mightypork/rogue/init/SetupConfig.java b/src/mightypork/rogue/init/RogueSetupConfig.java similarity index 95% rename from src/mightypork/rogue/init/SetupConfig.java rename to src/mightypork/rogue/init/RogueSetupConfig.java index 595ffdf..1a2a809 100644 --- a/src/mightypork/rogue/init/SetupConfig.java +++ b/src/mightypork/rogue/init/RogueSetupConfig.java @@ -2,37 +2,37 @@ package mightypork.rogue.init; import mightypork.gamecore.core.config.Config; -import mightypork.gamecore.core.config.InitTaskConfig; +import mightypork.gamecore.core.init.InitTaskConfig; -public class SetupConfig extends InitTaskConfig { - +public class RogueSetupConfig extends InitTaskConfig { + @Override protected Config buildConfig() { final Config cfg = new Config("config.ini", "Rogue config file"); - + cfg.addBoolean("display.fullscreen", false, "Start in fullscreen (remembers state at exit)"); cfg.addInteger("display.width", 1024, "Initial width (remembers from last time)"); cfg.addInteger("display.height", 768, "Initial height (remembers from last time)"); - - cfg.addBoolean("opt.show_story", true, "Show story on start-up."); - // keys + cfg.addBoolean("opt.show_story", true, "Show story on start-up."); + // keys + cfg.addKeyStroke("global.quit", "CTRL+Q", "Quit the game"); cfg.addKeyStroke("global.quit_force", "CTRL+SHIFT+Q", "Quit the game without asking, low-level"); - + cfg.addKeyStroke("global.screenshot", "F2", "Take screenshot (save into working directory)"); cfg.addKeyStroke("global.fullscreen", "F11", "Toggle fullscreen"); cfg.addKeyStroke("global.fps_meter", "F3", "Toggle FPS meter overlay"); - + cfg.addKeyStroke("general.close", "ESC", "Leave a dialog or screen"); cfg.addKeyStroke("general.cancel", "ESC", "\"Cancel\" option in dialogs"); cfg.addKeyStroke("general.confirm", "ENTER", "\"Confirm\" option in dialogs"); cfg.addKeyStroke("general.yes", "Y", "\"Yes\" option in dialogs"); cfg.addKeyStroke("general.no", "N", "\"No\" option in dialogs"); - + cfg.addKeyStroke("game.quit", "ESC", "Quit to menu"); cfg.addKeyStroke("game.save", "CTRL+S", "Save to file"); cfg.addKeyStroke("game.load", "CTRL+L", "Load from file"); @@ -42,22 +42,22 @@ public class SetupConfig extends InitTaskConfig { cfg.addKeyStroke("game.drop", "D", "Drop last picked item"); cfg.addKeyStroke("game.inventory", "I", "Toggle inventory view"); cfg.addKeyStroke("game.pause", "P", "Pause the game"); - + cfg.addKeyStroke("game.walk.up", "UP", "Walk north"); cfg.addKeyStroke("game.walk.down", "DOWN", "Walk south"); cfg.addKeyStroke("game.walk.left", "LEFT", "Walk west"); cfg.addKeyStroke("game.walk.right", "RIGHT", "Walk east"); - + cfg.addKeyStroke("game.cheat.xray", "CTRL+SHIFT+X", "Cheat to see unexplored tiles"); - + cfg.addKeyStroke("game.inv.use", "E", "Use (eat or equip) the selected item"); cfg.addKeyStroke("game.inv.drop", "D", "Drop the selected item"); cfg.addKeyStroke("game.inv.move.left", "LEFT", "Move inventory cursor left"); cfg.addKeyStroke("game.inv.move.right", "RIGHT", "Move inventory cursor right"); cfg.addKeyStroke("game.inv.move.up", "UP", "Move inventory cursor up"); cfg.addKeyStroke("game.inv.move.down", "DOWN", "Move inventory cursor down"); - + return cfg; } - + } diff --git a/src/mightypork/rogue/init/SetupDisplay.java b/src/mightypork/rogue/init/RogueSetupDisplay.java similarity index 89% rename from src/mightypork/rogue/init/SetupDisplay.java rename to src/mightypork/rogue/init/RogueSetupDisplay.java index 9e267a4..d212716 100644 --- a/src/mightypork/rogue/init/SetupDisplay.java +++ b/src/mightypork/rogue/init/RogueSetupDisplay.java @@ -6,20 +6,20 @@ import mightypork.gamecore.core.init.InitTaskDisplay; import mightypork.rogue.Const; -public class SetupDisplay extends InitTaskDisplay { - +public class RogueSetupDisplay extends InitTaskDisplay { + @Override public void init() { final int w = App.cfg().getValue("display.width"); final int h = App.cfg().getValue("display.height"); final boolean fs = App.cfg().getValue("display.fullscreen"); - + setSize(w, h); setResizable(true); setFullscreen(fs); setTitle(Const.TITLEBAR); setTargetFps(Const.FPS_RENDER); } - + } diff --git a/src/mightypork/rogue/init/SetupGlobalKeys.java b/src/mightypork/rogue/init/RogueSetupGlobalKeys.java similarity index 92% rename from src/mightypork/rogue/init/SetupGlobalKeys.java rename to src/mightypork/rogue/init/RogueSetupGlobalKeys.java index 383f277..4fe785b 100644 --- a/src/mightypork/rogue/init/SetupGlobalKeys.java +++ b/src/mightypork/rogue/init/RogueSetupGlobalKeys.java @@ -9,7 +9,7 @@ import mightypork.gamecore.input.Trigger; import mightypork.utils.eventbus.BusEvent; -public class SetupGlobalKeys extends InitTask { +public class RogueSetupGlobalKeys extends InitTask { @Override @@ -55,6 +55,6 @@ public class SetupGlobalKeys extends InitTask { @Override public String[] getDependencies() { - return new String[] { "config" }; + return new String[] { "config", "backend" }; } } diff --git a/src/mightypork/rogue/init/SetupWorkdir.java b/src/mightypork/rogue/init/RogueSetupWorkdir.java similarity index 75% rename from src/mightypork/rogue/init/SetupWorkdir.java rename to src/mightypork/rogue/init/RogueSetupWorkdir.java index 85a85b5..91f5788 100644 --- a/src/mightypork/rogue/init/SetupWorkdir.java +++ b/src/mightypork/rogue/init/RogueSetupWorkdir.java @@ -6,14 +6,14 @@ import java.io.File; import mightypork.gamecore.core.init.InitTaskWorkdir; -public class SetupWorkdir extends InitTaskWorkdir { - - public SetupWorkdir(File workdir) +public class RogueSetupWorkdir extends InitTaskWorkdir { + + public RogueSetupWorkdir(File workdir) { super(workdir, true); } - - + + @Override public void init() { diff --git a/src/mightypork/rogue/screens/FpsOverlay.java b/src/mightypork/rogue/screens/FpsOverlay.java index 242a9af..1a5e05e 100644 --- a/src/mightypork/rogue/screens/FpsOverlay.java +++ b/src/mightypork/rogue/screens/FpsOverlay.java @@ -22,48 +22,48 @@ import mightypork.utils.string.StringProvider; * @author Ondřej Hruška (MightyPork) */ public class FpsOverlay extends Overlay { - + TextPainter tp; - - + + 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.font("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 48ce8f0..7161330 100644 --- a/src/mightypork/rogue/screens/LoadingOverlay.java +++ b/src/mightypork/rogue/screens/LoadingOverlay.java @@ -24,32 +24,32 @@ import mightypork.utils.string.StringProvider; * @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,38 +61,38 @@ public class LoadingOverlay extends Overlay { }); } }; - - + + 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.font("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 * @@ -102,14 +102,14 @@ public class LoadingOverlay extends Overlay { 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 aa9d581..02f0584 100644 --- a/src/mightypork/rogue/screens/RogueScreen.java +++ b/src/mightypork/rogue/screens/RogueScreen.java @@ -2,20 +2,20 @@ package mightypork.rogue.screens; import mightypork.gamecore.core.App; -import mightypork.gamecore.core.events.ShutdownEvent; -import mightypork.gamecore.core.events.ShutdownListener; +import mightypork.gamecore.core.events.ShutdownRequest; +import mightypork.gamecore.core.events.ShutdownRequestListener; import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.rogue.RogueStateManager.RogueState; import mightypork.rogue.events.RogueStateRequest; import mightypork.utils.annotations.Stub; -public class RogueScreen extends LayeredScreen implements ShutdownListener { - - +public class RogueScreen extends LayeredScreen implements ShutdownRequestListener { + + @Override @Stub - public void onShutdown(ShutdownEvent event) + public void onShutdownRequested(ShutdownRequest event) { App.bus().send(new RogueStateRequest(RogueState.EXIT)); //event.consume(); FIXME we need a "shutdown request" event AND "shutdown" event. diff --git a/src/mightypork/rogue/screens/game/HeartBar.java b/src/mightypork/rogue/screens/game/HeartBar.java index 9af79a5..b6c11a6 100644 --- a/src/mightypork/rogue/screens/game/HeartBar.java +++ b/src/mightypork/rogue/screens/game/HeartBar.java @@ -11,17 +11,17 @@ 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) { super(); @@ -30,10 +30,10 @@ public class HeartBar extends BaseComponent { 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)); @@ -47,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 7288973..8bf0672 100644 --- a/src/mightypork/rogue/screens/game/IngameNav.java +++ b/src/mightypork/rogue/screens/game/IngameNav.java @@ -12,51 +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() { this(null); } - - + + 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.txQuad("nav.bg"); } - - + + public void addLeft(NavButton comp) { leftFlow.add(comp); } - - + + public void addRight(NavButton comp) { rightFlow.add(comp); } - - + + @Override public void renderComponent() { @@ -64,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 3b602a0..52a6c8e 100644 --- a/src/mightypork/rogue/screens/game/InvSlot.java +++ b/src/mightypork/rogue/screens/game/InvSlot.java @@ -11,7 +11,7 @@ import mightypork.rogue.world.PlayerFacade; import mightypork.rogue.world.WorldProvider; import mightypork.rogue.world.item.Item; import mightypork.rogue.world.item.ItemType; -import mightypork.utils.Support; +import mightypork.utils.Str; import mightypork.utils.math.AlignX; import mightypork.utils.math.color.Color; import mightypork.utils.math.color.pal.RGB; @@ -26,76 +26,76 @@ import mightypork.utils.math.constraints.rect.caching.RectCache; * @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) { super(); this.txBase = Res.txQuad("inv.slot.base"); this.txSelected = Res.txQuad("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.font("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.font("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() { @@ -104,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); @@ -129,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.setText(Str.val(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 25d3f3d..076d5f6 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.font("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); - + 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 eec8b13..0482c79 100644 --- a/src/mightypork/rogue/screens/game/LayerDeath.java +++ b/src/mightypork/rogue/screens/game/LayerDeath.java @@ -28,45 +28,45 @@ import mightypork.utils.math.constraints.num.Num; public class LayerDeath extends FadingLayer { - + 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.font("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.txQuad("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() { @@ -78,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); - + 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 910fd1c..3c2d1bd 100644 --- a/src/mightypork/rogue/screens/game/LayerGameUi.java +++ b/src/mightypork/rogue/screens/game/LayerGameUi.java @@ -16,71 +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) { 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, @@ -90,13 +90,13 @@ public class LayerGameUi extends ScreenLayer { Res.txQuad("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.font("tiny"), AlignX.RIGHT, RGB.WHITE, new StringProvider() { - + @Override public String getString() { @@ -104,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.txQuad("nav.button.fg.inventory"))); btn.setAction(gameScreen.actionToggleInv); - + nav.addRight(btn = new NavButton(Res.txQuad("nav.button.fg.eat"))); btn.setAction(gameScreen.actionEat); - + nav.addRight(btn = new NavButton(Res.txQuad("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.txQuad("nav.button.fg.menu"))); btn.setAction(gameScreen.actionMenu); - + nav.addLeft(btn = new NavButton(Res.txQuad("nav.button.fg.save"))); btn.setAction(gameScreen.actionSave); - + nav.addLeft(btn = new NavButton(Res.txQuad("nav.button.fg.load"))); btn.setAction(gameScreen.actionLoad); - + nav.addLeft(btn = new NavButton(Res.txQuad("nav.button.fg.map"))); btn.setAction(gameScreen.actionToggleMinimap); - + nav.addLeft(btn = new NavButton(Res.txQuad("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 074bd04..86a5680 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,45 +101,45 @@ public class LayerInv extends FadingLayer { gscreen.actionToggleInv.run(); } } - - + + 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.font("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); @@ -147,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.font("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() { @@ -166,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() { 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 5f02809..cf26ec7 100644 --- a/src/mightypork/rogue/screens/game/LayerMapView.java +++ b/src/mightypork/rogue/screens/game/LayerMapView.java @@ -10,41 +10,41 @@ import mightypork.utils.math.constraints.num.Num; public class LayerMapView extends ScreenLayer { - + protected final MapView map; - - + + 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 0e5a6fb..0176e65 100644 --- a/src/mightypork/rogue/screens/game/LayerWin.java +++ b/src/mightypork/rogue/screens/game/LayerWin.java @@ -24,69 +24,69 @@ import mightypork.utils.math.constraints.num.Num; public class LayerWin extends FadingLayer { - + 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.font("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.txQuad("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.sound().fadeOutAllLoops(); Res.sound("game.win").play(1); } - + } diff --git a/src/mightypork/rogue/screens/game/NavButton.java b/src/mightypork/rogue/screens/game/NavButton.java index 01d9d2b..57653c5 100644 --- a/src/mightypork/rogue/screens/game/NavButton.java +++ b/src/mightypork/rogue/screens/game/NavButton.java @@ -13,10 +13,10 @@ import mightypork.gamecore.resources.Res; * @author Ondřej Hruška (MightyPork) */ public class NavButton extends ClickableComponent { - + private final TxQuad base, hover, down, fg; - - + + public NavButton(TxQuad fg) { super(); @@ -25,13 +25,13 @@ public class NavButton extends ClickableComponent { this.down = Res.txQuad("nav.button.bg.down"); this.fg = fg; } - - + + @Override protected void renderComponent() { TxQuad bg; - + if (btnDownOver) { bg = down; } else if (isMouseOver()) { @@ -39,11 +39,11 @@ public class NavButton extends ClickableComponent { } else { bg = base; } - - if (!isEnabled()) bg = base; // override effects + 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 ed5c6a0..a0b8885 100644 --- a/src/mightypork/rogue/screens/game/ScreenGame.java +++ b/src/mightypork/rogue/screens/game/ScreenGame.java @@ -5,7 +5,7 @@ import java.io.File; import mightypork.gamecore.core.App; import mightypork.gamecore.core.config.Config; -import mightypork.gamecore.core.events.ShutdownEvent; +import mightypork.gamecore.core.events.ShutdownRequest; import mightypork.gamecore.gui.Action; import mightypork.gamecore.gui.ActionGroup; import mightypork.gamecore.input.Trigger; @@ -25,11 +25,11 @@ 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. * @@ -39,20 +39,20 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW { 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,8 +163,8 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW } }; private LayerAskSave askSaveLayer; - - + + /** * Set gui state (overlay) * @@ -173,52 +173,52 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW 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,41 +226,41 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW askSaveLayer.show(); } } - + this.state = nstate; } - - + + public GScrState getState() { return state; } - - + + 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)); - + 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 @@ -269,26 +269,26 @@ public class ScreenGame extends RogueScreen implements PlayerDeathHandler, GameW // 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() { @@ -296,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.sound().fadeOutAllLoops(); Res.loop("music.dungeon").fadeIn(); } - - + + @Override protected void onScreenLeave() { super.onScreenLeave(); WorldProvider.get().setListening(false); - + Res.loop("music.dungeon").fadeOut(); } - - + + private void hideAllPopups() { invLayer.hideImmediate(); @@ -329,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) + public void onShutdownRequested(ShutdownRequest event) { // 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 ff8104f..a71babd 100644 --- a/src/mightypork/rogue/screens/menu/ScreenMainMenu.java +++ b/src/mightypork/rogue/screens/menu/ScreenMainMenu.java @@ -29,47 +29,47 @@ import mightypork.utils.math.constraints.rect.Rect; * @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.txQuad("logo"))); rows.add(linlayout, 4); rows.skip(1); - + TextButton btn; - + final IFont btnFont = Res.font("thick"); - + // world button btn = new TextButton(btnFont, "Play", PAL16.SLIMEGREEN); btn.setAction(new Action() { - + @Override protected void execute() { @@ -78,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() { @@ -90,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() { @@ -102,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() { @@ -112,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.sound().fadeOutAllLoops(); Res.loop("music.menu").fadeIn(); } diff --git a/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java b/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java index ef780f0..96cdac7 100644 --- a/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java +++ b/src/mightypork/rogue/screens/select_world/ScreenSelectWorld.java @@ -27,57 +27,57 @@ import mightypork.utils.math.constraints.rect.Rect; * @author Ondřej Hruška (MightyPork) */ public class ScreenSelectWorld extends RogueScreen { - + public ScreenSelectWorld() { addLayer(new WorldsLayer(this)); } - + class WorldsLayer extends ScreenLayer { - + private WorldSlot slot1; private WorldSlot slot2; private WorldSlot slot3; - - + + 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.font("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() { @@ -85,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 d09c3f1..feee0e7 100644 --- a/src/mightypork/rogue/screens/select_world/WorldSlot.java +++ b/src/mightypork/rogue/screens/select_world/WorldSlot.java @@ -26,121 +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) { - + 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.font("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() { @@ -149,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 + 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); @@ -180,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 f7ba27e..df121ad 100644 --- a/src/mightypork/rogue/screens/story/ScreenStory.java +++ b/src/mightypork/rogue/screens/story/ScreenStory.java @@ -30,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; @@ -40,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.txQuad(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() { @@ -75,9 +75,9 @@ public class ScreenStory extends RogueScreen implements MouseButtonHandler { } } }; - + private final TimedTask ttText2 = new TimedTask() { - + @Override public void run() { @@ -89,108 +89,107 @@ 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) { super(screen); - - final TextPainter help = new TextPainter(Res.font("tiny"), AlignX.CENTER, RGB.WHITE.withAlpha(txProceedAlpha.mul(0.3)), - "Space / click to proceed."); + + final TextPainter help = new TextPainter(Res.font("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.txQuad("story_1")); ll.add(img); - + tp1 = new TextPainter(Res.font("tiny"), AlignX.CENTER, textColor.withAlpha(tx1alpha), ""); rl.add(tp1); tp1.setVPaddingPercent(19); - + tp2 = new TextPainter(Res.font("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() { @@ -198,33 +197,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() { - + 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() { @@ -232,29 +231,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 10026b7..1a55dc5 100644 --- a/src/mightypork/rogue/world/Inventory.java +++ b/src/mightypork/rogue/world/Inventory.java @@ -11,59 +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) { this.items = new Item[size]; } - - + + 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); } @@ -71,8 +71,8 @@ public class Inventory implements IonBinary { // close sequence out.endSequence(); } - - + + /** * Get item in a slot * @@ -82,22 +82,22 @@ public class Inventory implements IonBinary { 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 * @@ -110,8 +110,8 @@ public class Inventory implements IonBinary { items[i] = item; lastAddIndex = i; } - - + + /** * @return inventory size */ @@ -119,8 +119,8 @@ public class Inventory implements IonBinary { { return items.length; } - - + + /** * Add an item, try to merge first. * @@ -139,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); @@ -149,12 +149,12 @@ public class Inventory implements IonBinary { return true; } } - + // could not insert. return false; } - - + + /** * Clean empty items */ @@ -166,24 +166,24 @@ 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; } diff --git a/src/mightypork/rogue/world/PlayerControl.java b/src/mightypork/rogue/world/PlayerControl.java index 2018e77..901b8a3 100644 --- a/src/mightypork/rogue/world/PlayerControl.java +++ b/src/mightypork/rogue/world/PlayerControl.java @@ -15,82 +15,82 @@ 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 * @@ -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 11676bf..516ca36 100644 --- a/src/mightypork/rogue/world/PlayerData.java +++ b/src/mightypork/rogue/world/PlayerData.java @@ -12,32 +12,32 @@ import mightypork.utils.ion.IonDataBundle; * @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 0e08024..9798f37 100644 --- a/src/mightypork/rogue/world/PlayerFacade.java +++ b/src/mightypork/rogue/world/PlayerFacade.java @@ -21,11 +21,11 @@ import mightypork.utils.math.constraints.vect.Vect; * @author Ondřej Hruška (MightyPork) */ public class PlayerFacade { - + /** a world */ private final World world; - - + + /** * @return true if can go up */ @@ -33,8 +33,8 @@ public class PlayerFacade { { return world.playerData.getLevelNumber() > 0; } - - + + /** * @param world */ @@ -42,8 +42,8 @@ public class PlayerFacade { { this.world = world; } - - + + /** * @return true if can go down */ @@ -51,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. */ @@ -100,8 +100,8 @@ public class PlayerFacade { { return world.playerData.getLevelNumber(); } - - + + /** * @return current level */ @@ -109,8 +109,8 @@ public class PlayerFacade { { return world.levels.get(world.playerData.getLevelNumber()); } - - + + /** * @return entity ID */ @@ -118,8 +118,8 @@ public class PlayerFacade { { return world.playerData.getEID(); } - - + + /** * @return entity coordinate in level */ @@ -127,8 +127,8 @@ public class PlayerFacade { { return world.playerEntity.getCoord(); } - - + + /** * @return entity visual pos in level */ @@ -136,8 +136,8 @@ public class PlayerFacade { { return world.playerEntity.pos.getVisualPos(); } - - + + /** * Find path to * @@ -147,8 +147,8 @@ public class PlayerFacade { { world.playerEntity.pos.navigateTo(pos); } - - + + /** * Discard steps in buffer */ @@ -156,66 +156,66 @@ 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. * @@ -225,39 +225,39 @@ public class PlayerFacade { 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<>(); @@ -267,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); @@ -331,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); @@ -352,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 f72b161..1e23bcc 100644 --- a/src/mightypork/rogue/world/World.java +++ b/src/mightypork/rogue/world/World.java @@ -26,67 +26,67 @@ import mightypork.utils.math.algo.Coord; * @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) { @@ -94,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) { @@ -107,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 */ @@ -139,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 */ @@ -219,8 +219,8 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl { return console; } - - + + /** * Set file for saving * @@ -230,8 +230,8 @@ public class World implements DelegatingClient, IonBundled, Pauseable, Updateabl { this.saveFile = file; } - - + + /** * @return assigned file fro saving */ @@ -239,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 377e820..f877618 100644 --- a/src/mightypork/rogue/world/WorldConsole.java +++ b/src/mightypork/rogue/world/WorldConsole.java @@ -19,219 +19,219 @@ import mightypork.utils.math.animation.NumAnimated; * @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) { 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 8a146dc..e758c34 100644 --- a/src/mightypork/rogue/world/WorldProvider.java +++ b/src/mightypork/rogue/world/WorldProvider.java @@ -18,35 +18,35 @@ import mightypork.utils.logging.Log; * @author Ondřej Hruška (MightyPork) */ public class WorldProvider extends BusNode { - + public WorldProvider() { setListening(false); } - + private static WorldProvider inst = new WorldProvider(); - - + + 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 * @@ -60,35 +60,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) { @@ -97,21 +97,21 @@ 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. * @@ -121,20 +121,20 @@ public class WorldProvider extends BusNode { { saveWorld(world.getSaveFile()); } - - + + public Level getCurrentLevel() { return getWorld().getPlayer().getLevel(); } - - + + public PlayerFacade getPlayer() { return getWorld().getPlayer(); } - - + + /** * @return constant player control (world independent) */ @@ -142,5 +142,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 e3bec39..3116abe 100644 --- a/src/mightypork/rogue/world/WorldRenderer.java +++ b/src/mightypork/rogue/world/WorldRenderer.java @@ -24,89 +24,89 @@ import mightypork.utils.math.constraints.vect.VectConst; * @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) { 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) { @@ -121,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) { @@ -163,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 c4d2ae0..2e4545a 100644 --- a/src/mightypork/rogue/world/entity/AiTimer.java +++ b/src/mightypork/rogue/world/entity/AiTimer.java @@ -7,17 +7,17 @@ import mightypork.utils.math.timing.TaskRepeater; public abstract class AiTimer extends TaskRepeater implements IonBundled { - + public AiTimer(double duration) { super(duration); } - - + + @Override public abstract void run(); - - + + @Override public void load(IonDataBundle bundle) { @@ -27,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) { @@ -40,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 e105156..c123b79 100644 --- a/src/mightypork/rogue/world/entity/Entities.java +++ b/src/mightypork/rogue/world/entity/Entities.java @@ -18,41 +18,41 @@ import mightypork.utils.ion.IonOutput; * @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 d571fc9..8029896 100644 --- a/src/mightypork/rogue/world/entity/Entity.java +++ b/src/mightypork/rogue/world/entity/Entity.java @@ -27,80 +27,80 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; * @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) { 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)) { @@ -108,8 +108,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient } modules.put(key, module); } - - + + /** * @return unique entity id */ @@ -117,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) { @@ -172,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 */ @@ -187,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. */ @@ -206,8 +206,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient public void onKilled() { } - - + + /** * @return true if dead */ @@ -215,8 +215,8 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { return health.isDead(); } - - + + /** * @return whether this dead entity can be removed from level */ @@ -225,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. */ @@ -234,8 +234,8 @@ 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. @@ -249,8 +249,8 @@ 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 * @@ -260,37 +260,37 @@ public abstract class Entity implements IonBundled, Updateable, DelegatingClient { 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 91af070..1bb0a76 100644 --- a/src/mightypork/rogue/world/entity/EntityModel.java +++ b/src/mightypork/rogue/world/entity/EntityModel.java @@ -15,26 +15,26 @@ import mightypork.utils.ion.IonOutput; * @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) { 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 { @@ -43,8 +43,8 @@ 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. @@ -55,8 +55,8 @@ public final class EntityModel { { return createEntity(-1); } - - + + public Entity loadEntity(IonInput in) throws IOException { final IonDataBundle bundle = in.readBundle(); @@ -64,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 754d2cb..0be373b 100644 --- a/src/mightypork/rogue/world/entity/EntityModule.java +++ b/src/mightypork/rogue/world/entity/EntityModule.java @@ -14,36 +14,36 @@ import mightypork.utils.ion.IonDataBundle; * @author Ondřej Hruška (MightyPork) */ public abstract class EntityModule implements IonBundled, Updateable { - + protected final 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 5891089..b93f196 100644 --- a/src/mightypork/rogue/world/entity/EntityPathFinder.java +++ b/src/mightypork/rogue/world/entity/EntityPathFinder.java @@ -16,48 +16,48 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; * @author Ondřej Hruška (MightyPork) */ public class EntityPathFinder extends PathFinder { - + protected final 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 80670db..2967129 100644 --- a/src/mightypork/rogue/world/entity/EntityRenderer.java +++ b/src/mightypork/rogue/world/entity/EntityRenderer.java @@ -10,7 +10,7 @@ import mightypork.rogue.world.level.render.MapRenderContext; * @author Ondřej Hruška (MightyPork) */ public abstract class EntityRenderer { - + public abstract void render(MapRenderContext context); - + } diff --git a/src/mightypork/rogue/world/entity/impl/BossRatAi.java b/src/mightypork/rogue/world/entity/impl/BossRatAi.java index beb76fb..3ec6525 100644 --- a/src/mightypork/rogue/world/entity/impl/BossRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/BossRatAi.java @@ -7,48 +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) { 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 5b79d3b..70e7a91 100644 --- a/src/mightypork/rogue/world/entity/impl/BrownRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/BrownRatAi.java @@ -6,37 +6,37 @@ import mightypork.utils.math.Calc; public class BrownRatAi extends GrayRatAi { - + 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 f9dca09..f126764 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityBossRat.java +++ b/src/mightypork/rogue/world/entity/impl/EntityBossRat.java @@ -13,63 +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) { 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 9667fd6..5dcc581 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityBrownRat.java +++ b/src/mightypork/rogue/world/entity/impl/EntityBrownRat.java @@ -13,70 +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) { 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 caceefd..28a96ff 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityGrayRat.java +++ b/src/mightypork/rogue/world/entity/impl/EntityGrayRat.java @@ -13,75 +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) { 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 c4c0d9d..ad80df7 100644 --- a/src/mightypork/rogue/world/entity/impl/EntityPlayer.java +++ b/src/mightypork/rogue/world/entity/impl/EntityPlayer.java @@ -19,32 +19,32 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; public class EntityPlayer extends Entity { - + class PlayerAi extends EntityModule implements EntityMoveListener { - + 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 { @@ -52,102 +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) { 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 a427f85..0f8bf61 100644 --- a/src/mightypork/rogue/world/entity/impl/GrayRatAi.java +++ b/src/mightypork/rogue/world/entity/impl/GrayRatAi.java @@ -6,44 +6,44 @@ import mightypork.utils.math.Calc; public class GrayRatAi extends MonsterAi { - + 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 cab8ac4..4a53118 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,144 +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) { 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(); @@ -177,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 + 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 afab649..3cae487 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModuleHealth.java @@ -9,20 +9,20 @@ import mightypork.utils.math.Calc; public class EntityModuleHealth extends EntityModule { - + 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) { @@ -30,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) { @@ -39,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) */ @@ -126,8 +126,8 @@ public class EntityModuleHealth extends EntityModule { { return timeSinceLastDamage; } - - + + /** * Set how long after hit another hit can be received. * diff --git a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java index cb31df4..c98cc90 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java +++ b/src/mightypork/rogue/world/entity/modules/EntityModulePosition.java @@ -16,28 +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) { super(entity); } - - + + @Override public void save(IonDataBundle bundle) { @@ -46,26 +46,26 @@ 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 * @@ -74,15 +74,15 @@ public class EntityModulePosition extends EntityModule { 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 */ @@ -92,8 +92,8 @@ public class EntityModulePosition extends EntityModule { entity.getLevel().occupyTile(getCoord()); } } - - + + /** * free current tile in level */ @@ -103,8 +103,8 @@ public class EntityModulePosition extends EntityModule { entity.getLevel().freeTile(getCoord()); } } - - + + /** * @param delta delta time */ @@ -112,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); @@ -160,8 +160,8 @@ public class EntityModulePosition extends EntityModule { } } } - - + + /** * @return true if path buffer is empty */ @@ -169,8 +169,8 @@ public class EntityModulePosition extends EntityModule { { return entityPos.isFinished() && path.isEmpty(); } - - + + /** * Add a step to path buffer * @@ -179,11 +179,11 @@ public class EntityModulePosition extends EntityModule { public void addStep(Move step) { if (path.isEmpty() && !canGoTo(step)) return; - + path.add(step); } - - + + /** * Discard steps in buffer */ @@ -191,8 +191,8 @@ public class EntityModulePosition extends EntityModule { { path.clear(); } - - + + /** * Find path to * @@ -203,14 +203,14 @@ 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. * @@ -220,8 +220,8 @@ public class EntityModulePosition extends EntityModule { { moveListeners.add(listener); } - - + + /** * Add steps to path buffer * @@ -231,8 +231,8 @@ public class EntityModulePosition extends EntityModule { { this.path.addAll(path); } - - + + /** * @return coord in level */ @@ -240,8 +240,8 @@ public class EntityModulePosition extends EntityModule { { return entityPos.getCoord(); } - - + + /** * Set step time (seconds) * @@ -251,8 +251,8 @@ public class EntityModulePosition extends EntityModule { { this.stepTime = stepTime; } - - + + /** * @return step progress 0..1 */ @@ -260,8 +260,8 @@ public class EntityModulePosition extends EntityModule { { return entityPos.getProgress(); } - - + + /** * @return visual pos in level; interpolated from last to new coord */ @@ -269,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 f305e5f..c5701d4 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 db4cb08..dc30505 100644 --- a/src/mightypork/rogue/world/entity/modules/EntityPos.java +++ b/src/mightypork/rogue/world/entity/modules/EntityPos.java @@ -18,141 +18,141 @@ import mightypork.utils.math.constraints.vect.VectConst; * @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) { this.coord.setTo(pos); } - - + + public EntityPos(int x, int y) { this.coord.setTo(x, y); } - - + + 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() { @@ -161,8 +161,8 @@ class EntityPos implements IonBundled, Updateable { result = prime * result + ((coord == null) ? 0 : coord.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { @@ -175,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 1922230..60f1254 100644 --- a/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java +++ b/src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java @@ -24,53 +24,53 @@ import mightypork.utils.math.constraints.vect.Vect; * @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) { this.entity = entity; this.sheet = Res.txSheet(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 8e88cfa..4d544fc 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 e655219..c724288 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 91c9e10..dc3da48 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 95e5a32..50c00e2 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 1055de3..a6dc4d1 100644 --- a/src/mightypork/rogue/world/events/PlayerStepEndEvent.java +++ b/src/mightypork/rogue/world/events/PlayerStepEndEvent.java @@ -8,21 +8,21 @@ import mightypork.utils.eventbus.events.flags.NotLoggedEvent; @NotLoggedEvent public class PlayerStepEndEvent extends BusEvent { - + private final 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 8dd4697..de5e49c 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 a0abb18..87fb1c1 100644 --- a/src/mightypork/rogue/world/events/WorldAscendRequest.java +++ b/src/mightypork/rogue/world/events/WorldAscendRequest.java @@ -10,11 +10,11 @@ import mightypork.utils.eventbus.BusEvent; * @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 e67c969..94ed86f 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 21a0f80..0a18dc8 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 59ffc58..a71a496 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 e452da9..320a4eb 100644 --- a/src/mightypork/rogue/world/events/WorldPauseRequest.java +++ b/src/mightypork/rogue/world/events/WorldPauseRequest.java @@ -11,22 +11,22 @@ import mightypork.utils.eventbus.BusEvent; * @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) { super(); this.op = op; } - - + + @Override protected void handleBy(World handler) { @@ -34,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(); @@ -49,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 f74e6e0..2f56439 100644 --- a/src/mightypork/rogue/world/gen/LevelBuilder.java +++ b/src/mightypork/rogue/world/gen/LevelBuilder.java @@ -16,19 +16,19 @@ 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) { this.count = count; @@ -36,45 +36,45 @@ public class LevelBuilder { this.important = important; } } - + private class 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) { 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. * @@ -87,8 +87,8 @@ public class LevelBuilder { this.rand = new Random(seed); this.map = new ScratchMap(max_size, theme, rand); } - - + + /** * Add a single room to the room buffer. * @@ -100,8 +100,8 @@ public class LevelBuilder { { addRoom(room, Range.make(1, 1), order, important); } - - + + /** * Add multiple rooms of the type to the room buffer. * @@ -113,91 +113,91 @@ 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. * @@ -211,19 +211,19 @@ 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. * @@ -235,8 +235,8 @@ 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. @@ -249,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 fa9db96..7b1b337 100644 --- a/src/mightypork/rogue/world/gen/MapTheme.java +++ b/src/mightypork/rogue/world/gen/MapTheme.java @@ -10,27 +10,27 @@ import mightypork.rogue.world.tile.TileModel; * @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 0e46f12..8f65fae 100644 --- a/src/mightypork/rogue/world/gen/RoomBuilder.java +++ b/src/mightypork/rogue/world/gen/RoomBuilder.java @@ -12,6 +12,6 @@ import mightypork.utils.math.algo.Coord; * @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 043a96b..76669ca 100644 --- a/src/mightypork/rogue/world/gen/RoomEntry.java +++ b/src/mightypork/rogue/world/gen/RoomEntry.java @@ -10,44 +10,44 @@ import mightypork.utils.math.algo.Coord; * @author Ondřej Hruška (MightyPork) */ public class RoomEntry { - + final Coord min; final 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 f87824e..f363849 100644 --- a/src/mightypork/rogue/world/gen/Rooms.java +++ b/src/mightypork/rogue/world/gen/Rooms.java @@ -13,21 +13,21 @@ 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 93f81a3..ea60c7e 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -13,7 +13,7 @@ import mightypork.rogue.world.level.Level; import mightypork.rogue.world.tile.Tile; import mightypork.rogue.world.tile.TileModel; import mightypork.rogue.world.tile.Tiles; -import mightypork.utils.Support; +import mightypork.utils.Str; import mightypork.utils.logging.Log; import mightypork.utils.math.Calc; import mightypork.utils.math.algo.Coord; @@ -29,21 +29,21 @@ import mightypork.utils.math.algo.pathfinding.PathFinder; * @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,109 +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) { 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); @@ -168,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."); } @@ -225,8 +225,8 @@ public class ScratchMap { } } } - - + + /** * Clamp bounds to available area */ @@ -237,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 */ @@ -246,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++) { @@ -374,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); @@ -399,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 { @@ -419,8 +419,8 @@ public class ScratchMap { } } } - - + + /** * @return dimensions of the area taken by non-null tiles */ @@ -428,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) { @@ -572,21 +572,21 @@ 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 * @@ -597,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)) { @@ -621,7 +621,7 @@ public class ScratchMap { //@formatter:off throw new WorldGenError( "Could not put entity into a level map: e_pos=" + pos - + ", tile: " + Support.str(t) + + ", tile: " + Str.val(t) + ", t.wa " + t.isWalkable() + ", t.oc " + t.isOccupied() + ", ent.. " + e.getVisualName()); @@ -629,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. + 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 425ebe4..058ecc1 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 - + 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 1af28bb..6eec8d8 100644 --- a/src/mightypork/rogue/world/gen/WorldGenError.java +++ b/src/mightypork/rogue/world/gen/WorldGenError.java @@ -7,28 +7,28 @@ package mightypork.rogue.world.gen; * @author Ondřej Hruška (MightyPork) */ public class WorldGenError extends RuntimeException { - + public WorldGenError() { super(); } - - + + public WorldGenError(String message, Throwable cause) { super(message, cause); } - - + + public WorldGenError(String message) { super(message); } - - + + 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 db156a0..cfc7761 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 45da24e..d02b696 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 b4aad99..5fcbd7e 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 ca07edd..e1644a5 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 64d8e12..854cf0f 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 a210b36..8b7b967 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 0d45d05..9683122 100644 --- a/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/ItemShrineRoom.java @@ -12,34 +12,34 @@ import mightypork.utils.math.algo.Coord; public class ItemShrineRoom extends SecretRoom { - + private final 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 93239b3..90eba68 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 da76bfe..94356e2 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 ca345be..cf551e8 100644 --- a/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java +++ b/src/mightypork/rogue/world/gen/rooms/TreasureChestRoom.java @@ -11,22 +11,22 @@ import mightypork.utils.math.algo.Coord; public class TreasureChestRoom extends ItemShrineRoom { - + 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 4aca630..b9535ca 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 ac51318..4f4d368 100644 --- a/src/mightypork/rogue/world/gui/MapView.java +++ b/src/mightypork/rogue/world/gui/MapView.java @@ -33,24 +33,24 @@ import mightypork.utils.math.timing.TimedTask; * @author Ondřej Hruška (MightyPork) */ public class MapView extends InputComponent implements DelegatingClient, MouseButtonHandler, Updateable, WorldAscendRequestListener, - WorldDescendRequestListener { - +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() { @@ -63,53 +63,53 @@ 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() { 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 * @@ -120,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())) { @@ -135,7 +135,7 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu } } } - + if (event.isWheelEvent()) { final int delta = event.getWheelDelta(); if (!zoom.isFinished()) return; @@ -148,8 +148,8 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu } } } - - + + public void toggleMag() { if (zoom_in) { @@ -160,8 +160,8 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu zoom_in = true; } } - - + + /** * Add interaction plugin * @@ -171,8 +171,8 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu { plugins.add(plugin); } - - + + @Override public void update(double delta) { @@ -181,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 0d71372..763daef 100644 --- a/src/mightypork/rogue/world/gui/Minimap.java +++ b/src/mightypork/rogue/world/gui/Minimap.java @@ -17,32 +17,32 @@ import mightypork.utils.math.constraints.vect.Vect; 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); @@ -78,11 +78,11 @@ public class Minimap extends InputComponent implements MouseButtonHandler { GL11.glVertex2d(plx, ply + unit); GL11.glEnd();*/ - + Color.popAlpha(); } - - + + @Override public void receive(MouseButtonEvent event) { @@ -90,14 +90,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 b9ba6a9..2fb7355 100644 --- a/src/mightypork/rogue/world/gui/WorldConsoleRenderer.java +++ b/src/mightypork/rogue/world/gui/WorldConsoleRenderer.java @@ -21,70 +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) { this.rowHeight = rowHeight; this.fr = new FontRenderer(Res.font("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 3c27d26..4e25a47 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPKeyboard.java @@ -22,26 +22,26 @@ import mightypork.utils.math.constraints.vect.Vect; public class MIPKeyboard extends MapInteractionPlugin implements DelegatingClient, PlayerStepEndListener, Updateable { - + // FIXME cannot be static. - + private static final Move[] sides = { Moves.W, Moves.E, Moves.N, Moves.S }; - + private final KeyBindingPool kbp = new KeyBindingPool(); private final List clients = new ArrayList<>(); - - + + { clients.add(kbp); } - - + + private KeyStroke[] getKeys() { //@formatter:off - + final Config cfg = App.cfg(); - + return new KeyStroke[] { cfg.getKeyStroke("game.walk.left"), cfg.getKeyStroke("game.walk.right"), @@ -50,34 +50,34 @@ public class MIPKeyboard extends MapInteractionPlugin implements DelegatingClien }; //@formatter:on } - - + + @Override public boolean doesDelegate() { return true; } - - + + @Override public Collection getChildClients() { return clients; } - - + + public MIPKeyboard(MapView mapView) { super(mapView); - - final KeyStroke[] keys = getKeys(); + final KeyStroke[] keys = getKeys(); + // 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() { @@ -86,43 +86,43 @@ 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 (Keys.getActiveMods() != Keys.MOD_NONE) return false; - final KeyStroke[] keys = getKeys(); + if (Keys.getActiveMods() != Keys.MOD_NONE) return false; + final KeyStroke[] keys = getKeys(); + 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); @@ -134,8 +134,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 029c022..d04f6cb 100644 --- a/src/mightypork/rogue/world/gui/interaction/MIPMouse.java +++ b/src/mightypork/rogue/world/gui/interaction/MIPMouse.java @@ -15,116 +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) { 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 c0ca149..5d24107 100644 --- a/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java +++ b/src/mightypork/rogue/world/gui/interaction/MapInteractionPlugin.java @@ -9,34 +9,34 @@ import mightypork.utils.math.constraints.vect.Vect; public abstract class MapInteractionPlugin { - + protected final 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 43c740e..9bc6353 100644 --- a/src/mightypork/rogue/world/item/Item.java +++ b/src/mightypork/rogue/world/item/Item.java @@ -2,7 +2,7 @@ package mightypork.rogue.world.item; import mightypork.rogue.world.PlayerFacade; -import mightypork.utils.Support; +import mightypork.utils.Str; import mightypork.utils.annotations.Stub; import mightypork.utils.ion.IonBundled; import mightypork.utils.ion.IonDataBundle; @@ -11,32 +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) { 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) @@ -44,8 +44,8 @@ public abstract class Item implements IonBundled { out.put("c", amount); out.put("u", uses); } - - + + @Override @Stub public void load(IonDataBundle in) @@ -53,30 +53,30 @@ 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 * @@ -89,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 */ @@ -108,8 +108,8 @@ public abstract class Item implements IonBundled { { return Math.max(0, amount); } - - + + /** * Consume one item. * @@ -118,76 +118,76 @@ public abstract class Item implements IonBundled { 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(); + return Str.val(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 c2abf6b..471d5aa 100644 --- a/src/mightypork/rogue/world/item/ItemModel.java +++ b/src/mightypork/rogue/world/item/ItemModel.java @@ -13,20 +13,20 @@ import mightypork.utils.math.Calc; * @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) { Items.register(id, this); this.id = id; this.itemClass = item; } - - + + /** * @return new item instance of this type */ @@ -34,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 eb54c19..4c85492 100644 --- a/src/mightypork/rogue/world/item/ItemRenderer.java +++ b/src/mightypork/rogue/world/item/ItemRenderer.java @@ -5,16 +5,16 @@ import mightypork.utils.math.constraints.rect.Rect; public abstract class ItemRenderer { - + protected final 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 343d9dc..3b48684 100644 --- a/src/mightypork/rogue/world/item/Items.java +++ b/src/mightypork/rogue/world/item/Items.java @@ -26,9 +26,9 @@ import mightypork.utils.ion.IonOutput; * @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); @@ -40,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(); @@ -95,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 ee8f63f..e03b624 100644 --- a/src/mightypork/rogue/world/item/impl/ItemBaseFood.java +++ b/src/mightypork/rogue/world/item/impl/ItemBaseFood.java @@ -7,41 +7,41 @@ import mightypork.rogue.world.item.ItemType; public abstract class ItemBaseFood extends Item { - + 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 2f7592d..869fcaa 100644 --- a/src/mightypork/rogue/world/item/impl/ItemBaseWeapon.java +++ b/src/mightypork/rogue/world/item/impl/ItemBaseWeapon.java @@ -7,38 +7,38 @@ import mightypork.rogue.world.item.ItemType; public abstract class ItemBaseWeapon extends Item { - + 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 4bf24d1..d538123 100644 --- a/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java +++ b/src/mightypork/rogue/world/item/impl/active/ItemHeartPiece.java @@ -11,78 +11,78 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemHeartPiece extends Item { - + public ItemHeartPiece(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 47e1184..e375b2a 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemCheese.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemCheese.java @@ -9,27 +9,27 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemCheese extends ItemBaseFood { - + public ItemCheese(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 5e4eaca..6bfab89 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemMeat.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemMeat.java @@ -9,27 +9,27 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemMeat extends ItemBaseFood { - + public ItemMeat(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 7a4f4a3..0772c2a 100644 --- a/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java +++ b/src/mightypork/rogue/world/item/impl/food/ItemSandwich.java @@ -9,27 +9,27 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemSandwich extends ItemBaseFood { - + public ItemSandwich(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 3e93d29..6d288cc 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemAxe.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemAxe extends ItemBaseWeapon { - + public ItemAxe(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 94d1889..6fdb701 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemBone.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemBone extends ItemBaseWeapon { - + public ItemBone(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 df90037..a14d9a9 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemClub.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemClub extends ItemBaseWeapon { - + public ItemClub(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 5208764..ce53d70 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemKnife.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemKnife extends ItemBaseWeapon { - + public ItemKnife(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 7c576e6..6819c94 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemRock.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemRock extends ItemBaseWeapon { - + public ItemRock(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 ad40fe3..09a962a 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemSword.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemSword extends ItemBaseWeapon { - + public ItemSword(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 62f015e..3b214ce 100644 --- a/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java +++ b/src/mightypork/rogue/world/item/impl/weapons/ItemTwig.java @@ -9,34 +9,34 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemTwig extends ItemBaseWeapon { - + public ItemTwig(ItemModel model) { super(model); } - - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txQuad("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 6b0b25d..8c8f550 100644 --- a/src/mightypork/rogue/world/item/render/QuadItemRenderer.java +++ b/src/mightypork/rogue/world/item/render/QuadItemRenderer.java @@ -9,21 +9,21 @@ import mightypork.utils.math.constraints.rect.Rect; public class QuadItemRenderer extends ItemRenderer { - + private final 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 b8d01a9..7820010 100644 --- a/src/mightypork/rogue/world/level/Level.java +++ b/src/mightypork/rogue/world/level/Level.java @@ -45,88 +45,88 @@ import mightypork.utils.math.noise.NoiseGen; * @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(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 * @@ -140,8 +140,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io } } } - - + + /** * Ge tile at X,Y * @@ -151,11 +151,11 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io 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 * @@ -168,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 */ @@ -183,8 +183,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return size.x; } - - + + /** * @return map height in tiles */ @@ -192,8 +192,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return size.y; } - - + + /** * Set level seed (used for visuals; the seed used for generation) * @@ -203,8 +203,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { this.seed = seed; } - - + + /** * @return map seed */ @@ -212,8 +212,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return seed; } - - + + @Override public void load(IonInput in) throws IOException { @@ -223,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); @@ -248,8 +248,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io } } } - - + + @Override public void save(IonOutput out) throws IOException { @@ -260,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 */ @@ -312,11 +312,11 @@ 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 * @@ -327,8 +327,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return entityMap.get(eid); } - - + + /** * Try to add entity at given pos, then near the pos. * @@ -339,24 +339,24 @@ 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 * @@ -368,28 +368,28 @@ 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 * @@ -399,8 +399,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { removeEntity(entity.getEntityId()); } - - + + /** * Remove an entity from the level, if present * @@ -412,14 +412,14 @@ 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 * @@ -429,11 +429,11 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io public boolean isWalkable(Coord pos) { final Tile t = getTile(pos); - + return t.isWalkable() && !t.isOccupied(); } - - + + /** * Mark tile as occupied (entity entered) * @@ -443,8 +443,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { getTile(pos).setOccupied(true); } - - + + /** * Mark tile as free (entity left) * @@ -454,8 +454,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { getTile(pos).setOccupied(false); } - - + + /** * Check entity on tile * @@ -466,8 +466,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return getTile(pos).isOccupied(); } - - + + /** * Set level entry point * @@ -477,8 +477,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { this.enterPoint.setTo(pos); } - - + + /** * Get location where the player appears upon descending to this level * @@ -488,8 +488,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return enterPoint; } - - + + /** * Set level exit point * @@ -499,8 +499,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { this.exitPoint.setTo(pos); } - - + + /** * Get location where the player appears upon ascending to this level * @@ -510,8 +510,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return exitPoint; } - - + + /** * Get the level's world * @@ -521,8 +521,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return world; } - - + + /** * Assign a world * @@ -532,8 +532,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { this.world = world; } - - + + /** * Mark tile and surrounding area as explored * @@ -542,15 +542,15 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io 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 * @@ -563,24 +563,24 @@ 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. * @@ -596,21 +596,21 @@ 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 * @@ -621,8 +621,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return entityList.contains(entity); } - - + + /** * Check if entity is in the level * @@ -633,8 +633,8 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { return entityMap.containsKey(eid); } - - + + /** * Get entity collection (for rendering) * @@ -644,60 +644,60 @@ public class Level implements Updateable, DelegatingClient, ToggleableClient, Io { 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 3173e09..edb3b33 100644 --- a/src/mightypork/rogue/world/level/render/EntityRenderContext.java +++ b/src/mightypork/rogue/world/level/render/EntityRenderContext.java @@ -6,10 +6,10 @@ import mightypork.utils.math.constraints.rect.Rect; public class EntityRenderContext extends MapRenderContext { - + 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 eda9f34..82e2a0e 100644 --- a/src/mightypork/rogue/world/level/render/MapRenderContext.java +++ b/src/mightypork/rogue/world/level/render/MapRenderContext.java @@ -9,33 +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) { 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 d3d7701..0cffa16 100644 --- a/src/mightypork/rogue/world/level/render/TileRenderContext.java +++ b/src/mightypork/rogue/world/level/render/TileRenderContext.java @@ -16,21 +16,21 @@ import mightypork.utils.math.noise.NoiseGen; * @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) { super(map, drawArea); - + //this.tiler.setOverlap(0.002); // avoid gaps (rounding error?) - + this.noise = map.getNoiseGen(); } - - + + /** * @return the rendered tile. */ @@ -38,8 +38,8 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { return map.getTile(pos); } - - + + /** * Get a neighbor tile * @@ -50,8 +50,8 @@ public final class TileRenderContext extends MapRenderContext implements RectBou { return map.getTile(pos.add(offset)); } - - + + /** * @return per-coord noise value 0..1 */ @@ -59,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 a94b6b1..d8a3bda 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 4192bf4..0003993 100644 --- a/src/mightypork/rogue/world/tile/Tile.java +++ b/src/mightypork/rogue/world/tile/Tile.java @@ -8,7 +8,7 @@ import mightypork.rogue.world.World; import mightypork.rogue.world.item.Item; import mightypork.rogue.world.level.Level; import mightypork.rogue.world.level.render.TileRenderContext; -import mightypork.utils.Support; +import mightypork.utils.Str; import mightypork.utils.annotations.Stub; import mightypork.utils.ion.IonBinary; import mightypork.utils.ion.IonInput; @@ -23,27 +23,27 @@ import mightypork.utils.math.color.Color; * @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) { this.model = model; } - - + + /** * Render the tile, using the main texture sheet. * @@ -53,41 +53,41 @@ public abstract class Tile implements IonBinary { 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)); + Log.w("No renderer for tile " + Str.val(this)); renderer = TileRenderer.NONE; return; } } } - - + + protected abstract TileRenderer makeRenderer(); - - + + /** * Render extra stuff (ie. dropped items).
* Called after the whole map is rendered using renderTile. @@ -100,84 +100,84 @@ 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. @@ -189,39 +189,39 @@ 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 * @@ -229,22 +229,22 @@ public abstract class Tile implements IonBinary { * @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 * @@ -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 0af4fc0..973ac19 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 47bdb4f..fbb94fe 100644 --- a/src/mightypork/rogue/world/tile/TileGenData.java +++ b/src/mightypork/rogue/world/tile/TileGenData.java @@ -10,7 +10,7 @@ import mightypork.rogue.world.gen.TileProtectLevel; * @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 4fdfab6..ffd520f 100644 --- a/src/mightypork/rogue/world/tile/TileModel.java +++ b/src/mightypork/rogue/world/tile/TileModel.java @@ -13,20 +13,20 @@ import mightypork.utils.ion.IonOutput; * @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) { Tiles.register(id, this); this.id = id; this.tileClass = tile; } - - + + /** * @return new tile of this type */ @@ -38,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 ecf2d4c..f993354 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -19,32 +19,32 @@ import mightypork.utils.math.constraints.rect.Rect; * @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) { this.tile = tile; - + if (!inited) { SH_N = Res.txQuad("tile.shadow.n"); SH_S = Res.txQuad("tile.shadow.s"); @@ -54,7 +54,7 @@ public abstract class TileRenderer implements Updateable { SH_NE = Res.txQuad("tile.shadow.ne"); SH_SW = Res.txQuad("tile.shadow.sw"); SH_SE = Res.txQuad("tile.shadow.se"); - + UFOG_N = Res.txQuad("tile.ufog.n"); UFOG_S = Res.txQuad("tile.ufog.s"); UFOG_E = Res.txQuad("tile.ufog.e"); @@ -67,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 38a515c..73884df 100644 --- a/src/mightypork/rogue/world/tile/TileType.java +++ b/src/mightypork/rogue/world/tile/TileType.java @@ -23,24 +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) { 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 8b70fb6..fde374e 100644 --- a/src/mightypork/rogue/world/tile/Tiles.java +++ b/src/mightypork/rogue/world/tile/Tiles.java @@ -22,11 +22,11 @@ import mightypork.utils.ion.IonOutput; * @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); @@ -35,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 99f5bab..a785cb6 100644 --- a/src/mightypork/rogue/world/tile/impl/NullTile.java +++ b/src/mightypork/rogue/world/tile/impl/NullTile.java @@ -10,80 +10,80 @@ import mightypork.rogue.world.tile.TileType; public class NullTile extends Tile { - + 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 8228816..35cce7b 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseChest.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseChest.java @@ -10,67 +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) { 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 { @@ -79,8 +79,8 @@ public abstract class TileBaseChest extends TileWithItems { out.writeBoolean(opened); out.writeBoolean(removed); } - - + + @Override public void load(IonInput in) throws IOException { @@ -89,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 ac3c463..078f942 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseDoor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseDoor.java @@ -13,56 +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) { 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 */ @@ -70,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 205b95a..89cae7e 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseEntrance.java @@ -10,32 +10,32 @@ import mightypork.utils.math.color.Color; public abstract class TileBaseEntrance extends TileBaseStairs { - + 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 95f8890..42367b2 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseExit.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseExit.java @@ -10,32 +10,32 @@ import mightypork.utils.math.color.Color; public abstract class TileBaseExit extends TileBaseStairs { - + 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 ebeea41..0168ca5 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseFloor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseFloor.java @@ -9,24 +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) { 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 10cb630..46543bb 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBasePassage.java +++ b/src/mightypork/rogue/world/tile/impl/TileBasePassage.java @@ -14,36 +14,36 @@ import mightypork.rogue.world.tile.render.BasicTileRenderer; * @author Ondřej Hruška (MightyPork) */ public abstract class TileBasePassage extends TileSolid { - + private final BasicTileRenderer renderer; - - + + 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 5afa501..6380653 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseSecretDoor.java @@ -12,48 +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) { 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 4bb0bff..27ebcaf 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseStairs.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseStairs.java @@ -6,17 +6,17 @@ import mightypork.rogue.world.tile.TileType; public abstract class TileBaseStairs extends TileSolid { - + public TileBaseStairs(TileModel model) { super(model); } - - + + @Override public TileType getType() { return TileType.STAIRS; } - + } diff --git a/src/mightypork/rogue/world/tile/impl/TileBaseWall.java b/src/mightypork/rogue/world/tile/impl/TileBaseWall.java index e68bbb3..32f2251 100644 --- a/src/mightypork/rogue/world/tile/impl/TileBaseWall.java +++ b/src/mightypork/rogue/world/tile/impl/TileBaseWall.java @@ -8,24 +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) { 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 2b034b4..c7cc1f6 100644 --- a/src/mightypork/rogue/world/tile/impl/TileSolid.java +++ b/src/mightypork/rogue/world/tile/impl/TileSolid.java @@ -7,41 +7,41 @@ import mightypork.rogue.world.tile.TileModel; public abstract class TileSolid extends Tile { - + 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 1847bee..b18527a 100644 --- a/src/mightypork/rogue/world/tile/impl/TileWithItems.java +++ b/src/mightypork/rogue/world/tile/impl/TileWithItems.java @@ -16,96 +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) { 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 c3614c4..1a0967a 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickChest.java @@ -9,17 +9,17 @@ import mightypork.rogue.world.tile.render.ChestRenderer; public class TileBrickChest extends TileBaseChest { - + public TileBrickChest(TileModel model) { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return new ChestRenderer(this, Res.txQuad("tile.brick.floor"), Res.txQuad("tile.extra.chest.closed"), Res.txQuad("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 6cdc356..e95b58a 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickDoor.java @@ -7,7 +7,7 @@ import mightypork.rogue.world.tile.impl.TileBaseDoor; public class TileBrickDoor extends TileBaseDoor { - + public TileBrickDoor(TileModel model) { //@formatter:off @@ -19,5 +19,5 @@ public class TileBrickDoor extends TileBaseDoor { ); //@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 9b28775..5c179cb 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickEntrance.java @@ -9,17 +9,17 @@ import mightypork.rogue.world.tile.render.OneFrameTileRenderer; public class TileBrickEntrance extends TileBaseEntrance { - + public TileBrickEntrance(TileModel model) { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return new OneFrameTileRenderer(this, Res.txQuad("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 3809e74..2a4597e 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickExit.java @@ -9,17 +9,17 @@ import mightypork.rogue.world.tile.render.OneFrameTileRenderer; public class TileBrickExit extends TileBaseExit { - + public TileBrickExit(TileModel model) { super(model); } - - + + @Override protected TileRenderer makeRenderer() { return new OneFrameTileRenderer(this, Res.txQuad("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 4ba0eb0..5b44c40 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickFloor.java @@ -7,10 +7,10 @@ import mightypork.rogue.world.tile.impl.TileBaseFloor; public class TileBrickFloor extends TileBaseFloor { - + public TileBrickFloor(TileModel model) { super(model, Res.txSheet("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 d9c0ab9..b0ff862 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickPassage.java @@ -7,10 +7,10 @@ import mightypork.rogue.world.tile.impl.TileBasePassage; public class TileBrickPassage extends TileBasePassage { - + public TileBrickPassage(TileModel model) { super(model, Res.txSheet("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 f082b16..c77066b 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickSecretDoor.java @@ -7,7 +7,7 @@ import mightypork.rogue.world.tile.impl.TileBaseSecretDoor; public class TileBrickSecretDoor extends TileBaseSecretDoor { - + public TileBrickSecretDoor(TileModel model) { //@formatter:off @@ -18,7 +18,7 @@ public class TileBrickSecretDoor extends TileBaseSecretDoor { Res.txSheet("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 802baf8..c0d287c 100644 --- a/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java +++ b/src/mightypork/rogue/world/tile/impl/brick/TileBrickWall.java @@ -7,10 +7,10 @@ import mightypork.rogue.world.tile.impl.TileBaseWall; public class TileBrickWall extends TileBaseWall { - + public TileBrickWall(TileModel model) { super(model, Res.txSheet("tile.brick.wall")); } - + } diff --git a/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java b/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java index f6999fe..c2f1476 100644 --- a/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/BasicTileRenderer.java @@ -10,17 +10,17 @@ import mightypork.utils.math.constraints.rect.Rect; public class BasicTileRenderer extends TileRenderer { - + private final 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 bdc9cbf..c7b00ff 100644 --- a/src/mightypork/rogue/world/tile/render/ChestRenderer.java +++ b/src/mightypork/rogue/world/tile/render/ChestRenderer.java @@ -9,33 +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) { 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 d352b37..0275fe3 100644 --- a/src/mightypork/rogue/world/tile/render/DoorTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/DoorTileRenderer.java @@ -11,44 +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) { 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 { @@ -56,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 7ac02fc..f7b8fd3 100644 --- a/src/mightypork/rogue/world/tile/render/NullTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/NullTileRenderer.java @@ -11,34 +11,34 @@ import mightypork.rogue.world.tile.TileRenderer; * @author Ondřej Hruška (MightyPork) */ public class NullTileRenderer extends TileRenderer { - + 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 414685d..97bbf1b 100644 --- a/src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/OneFrameTileRenderer.java @@ -14,17 +14,17 @@ import mightypork.rogue.world.tile.TileRenderer; * @author Ondřej Hruška (MightyPork) */ public class OneFrameTileRenderer extends TileRenderer { - + private final TxQuad txq; - - + + public OneFrameTileRenderer(Tile tile, TxQuad txq) { super(tile); this.txq = txq; } - - + + @Override public void renderTile(TileRenderContext context) { diff --git a/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java b/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java index fafcf78..9de6e69 100644 --- a/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java +++ b/src/mightypork/rogue/world/tile/render/TwoHighTileRenderer.java @@ -15,17 +15,17 @@ import mightypork.utils.math.constraints.rect.Rect; * @author Ondřej Hruška (MightyPork) */ public class TwoHighTileRenderer extends TileRenderer { - + private final TxQuad txq; - - + + public TwoHighTileRenderer(Tile tile, TxQuad txq) { super(tile); this.txq = txq; } - - + + @Override public void renderTile(TileRenderContext context) {