From 49b327b951569931102e2b49fa1bd3fd65420722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 11 May 2014 23:35:51 +0200 Subject: [PATCH] + rats & improvements; damaged items; --- res/img/sprites.png | Bin 1529 -> 2935 bytes res/img/sprites.xcf | Bin 10500 -> 16755 bytes .../gui/components/BaseComponent.java | 3 +- .../gui/components/InputComponent.java | 2 +- .../gui/components/LayoutComponent.java | 4 +- .../gui/components/painters/TextPainter.java | 18 ++- .../gamecore/gui/screens/Overlay.java | 12 +- .../resources/fonts/FontRenderer.java | 6 +- .../resources/fonts/impl/CachedFont.java | 14 +- src/mightypork/gamecore/util/math/Calc.java | 10 +- .../num/proxy/NumBoundAdapter.java | 4 +- .../gamecore/util/math/timing/Animator.java | 2 +- src/mightypork/rogue/Config.java | 1 - src/mightypork/rogue/Res.java | 5 +- .../rogue/screens/game/HeartBar.java | 5 +- .../rogue/screens/game/HudLayer.java | 17 +-- .../rogue/screens/game/InvLayer.java | 41 +++--- .../rogue/screens/game/InvSlot.java | 27 +++- .../rogue/screens/game/NavButton.java | 2 +- .../rogue/screens/game/ScreenGame.java | 22 +-- .../screens/game/WorldConsoleRenderer.java | 17 +-- src/mightypork/rogue/world/Inventory.java | 14 +- src/mightypork/rogue/world/PlayerControl.java | 14 +- src/mightypork/rogue/world/PlayerInfo.java | 2 +- src/mightypork/rogue/world/World.java | 15 ++- src/mightypork/rogue/world/WorldConsole.java | 16 ++- src/mightypork/rogue/world/WorldCreator.java | 14 +- .../rogue/world/entity/Entities.java | 8 +- src/mightypork/rogue/world/entity/Entity.java | 7 +- .../rogue/world/entity/EntityModel.java | 12 ++ .../world/entity/entities/BossRatAi.java | 48 +++++++ .../world/entity/entities/BrownRatAi.java | 37 +++++ .../world/entity/entities/EntityBossRat.java | 92 +++++++++++++ .../world/entity/entities/EntityBrownRat.java | 92 +++++++++++++ .../{RatEntity.java => EntityGrayRat.java} | 36 ++--- .../entities/{RatAi.java => GrayRatAi.java} | 4 +- .../world/entity/entities/PlayerEntity.java | 6 +- .../rogue/world/gen/LevelGenerator.java | 64 +++++---- .../rogue/world/gen/RoomBuilder.java | 2 +- .../rogue/world/gen/ScratchMap.java | 126 +++++++++++++----- .../rogue/world/gen/WorldGenError.java | 34 +++++ .../rogue/world/gen/rooms/BossRoom.java | 36 +++++ .../rogue/world/gen/rooms/Rooms.java | 1 + .../rogue/world/gen/rooms/SecretRoom.java | 8 +- src/mightypork/rogue/world/gui/MapView.java | 12 +- src/mightypork/rogue/world/item/Item.java | 25 ++-- .../rogue/world/item/ItemModel.java | 17 ++- .../rogue/world/item/ItemRenderer.java | 9 +- .../rogue/world/item/items/ItemBaseFood.java | 2 + .../world/item/items/ItemBaseWeapon.java | 1 + .../world/item/items/food/ItemCheese.java | 2 +- .../rogue/world/item/items/food/ItemMeat.java | 2 +- .../world/item/items/food/ItemSandwich.java | 2 +- .../world/item/items/weapons/ItemBone.java | 16 ++- .../world/item/items/weapons/ItemClub.java | 16 ++- .../world/item/items/weapons/ItemHammer.java | 16 ++- .../world/item/items/weapons/ItemStone.java | 16 ++- .../world/item/items/weapons/ItemSword.java | 18 ++- .../world/item/render/QuadItemRenderer.java | 28 +--- src/mightypork/rogue/world/level/Level.java | 40 +++++- .../rogue/world/tile/DroppedItemRenderer.java | 31 +++-- .../rogue/world/tile/TileRenderer.java | 2 +- .../rogue/world/tile/tiles/TileWithItems.java | 5 +- 63 files changed, 850 insertions(+), 310 deletions(-) create mode 100644 src/mightypork/rogue/world/entity/entities/BossRatAi.java create mode 100644 src/mightypork/rogue/world/entity/entities/BrownRatAi.java create mode 100644 src/mightypork/rogue/world/entity/entities/EntityBossRat.java create mode 100644 src/mightypork/rogue/world/entity/entities/EntityBrownRat.java rename src/mightypork/rogue/world/entity/entities/{RatEntity.java => EntityGrayRat.java} (69%) rename src/mightypork/rogue/world/entity/entities/{RatAi.java => GrayRatAi.java} (91%) create mode 100644 src/mightypork/rogue/world/gen/WorldGenError.java create mode 100644 src/mightypork/rogue/world/gen/rooms/BossRoom.java diff --git a/res/img/sprites.png b/res/img/sprites.png index ef107f82fac2453c542e6ed56a093587247e6767..cb412e166fc03e03f74f31399220ee9375b45052 100644 GIT binary patch literal 2935 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 L&NlC?0@D5qirjW( literal 1529 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%0DDa zl4p^KwtxRnv>p$&t;gQqVLft>;||6X=Fxd6lO3I(kJjQJVlB!EOftfgSknysxzJwv z@k12-y8L>VfxAFFNKshs0wd`OOUhsM=ntJea;{Tm{~cjz$EYtTzlx<=7QqXlNam{U zl-*@7>`%7&7)RD2_dNVy-7NL>5iJz1or$#}7%;lQ9O=ClBT!zGt-@C%xFuyuS%oB%a^)4AUKO{StJKhm62b|-i zlzP`e@4P_ZwF0jp!pkjsndwKFvitMb&y?KakbmQnL9PnMNi=!uD_1Y{=qrYC935ik z2NwwZK9IeN!41nL)DSCgVDtqFZZojb#^r*QmzN^q>yB2G8z+5t!yB7uDYB*R zprLSO!pk5clGI~}_vaq06t?1zMo*gY@)5F>r_S4wS&EFx2b?tt)d zeB=)u_<|5FaddP$;2m|<`|BV%Ivk`%hXVh9@qcPtpZp>?95{{5^-=uy-A^EQHD17T z2%r2Lol(&m4I0UYGkQ4aXtaXS;02V!0sf;Y9+Yb+*HDh4MDy;bAB;MqS33^{(qkWb z>_d;g#JBxhAOD;^u5I4w!+$LJ7_z&T_{?2HuWRVFZ>=*bT7AJ*(b=%J)&ekFpOXx^VmapwHz3OZj|^G=%8s^nh&_rtG-+ca6x7tUX)pxC4Y{X zhw?S^@WLr|s&w(vkIq8Em7Lt-aDKxZCffgy{~7%pJJdf%){SrtB_G@{y@da8{?d8K k{JEx|m!5$Qe^-79w^J{jrUS1$8he<6-%3XlN6e%C56<2NqW}N^ literal 10500 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 PD%{Kcw|JO%-4yX(2`dh} diff --git a/src/mightypork/gamecore/gui/components/BaseComponent.java b/src/mightypork/gamecore/gui/components/BaseComponent.java index e1f138b..f55a18d 100644 --- a/src/mightypork/gamecore/gui/components/BaseComponent.java +++ b/src/mightypork/gamecore/gui/components/BaseComponent.java @@ -27,7 +27,8 @@ public abstract class BaseComponent extends AbstractRectCache implements Compone private int disableLevel = 0; - public BaseComponent() { + public BaseComponent() + { enableCaching(false); } diff --git a/src/mightypork/gamecore/gui/components/InputComponent.java b/src/mightypork/gamecore/gui/components/InputComponent.java index d4844a1..d286a34 100644 --- a/src/mightypork/gamecore/gui/components/InputComponent.java +++ b/src/mightypork/gamecore/gui/components/InputComponent.java @@ -6,7 +6,7 @@ import mightypork.gamecore.gui.Enableable; public abstract class InputComponent extends BaseComponent implements Enableable, ToggleableClient { - + @Override public boolean isListening() { diff --git a/src/mightypork/gamecore/gui/components/LayoutComponent.java b/src/mightypork/gamecore/gui/components/LayoutComponent.java index b2b0bb5..f675cba 100644 --- a/src/mightypork/gamecore/gui/components/LayoutComponent.java +++ b/src/mightypork/gamecore/gui/components/LayoutComponent.java @@ -105,15 +105,17 @@ public abstract class LayoutComponent extends BaseComponent implements ClientHub subModule.removeChildClient(client); } + @Override public void enable(boolean yes) { super.enable(yes); - for(Component c : components) { + for (final Component c : components) { c.enable(yes); } } + // @Override // public void enable(boolean yes) // { diff --git a/src/mightypork/gamecore/gui/components/painters/TextPainter.java b/src/mightypork/gamecore/gui/components/painters/TextPainter.java index 902c98a..dea4a26 100644 --- a/src/mightypork/gamecore/gui/components/painters/TextPainter.java +++ b/src/mightypork/gamecore/gui/components/painters/TextPainter.java @@ -41,7 +41,8 @@ public class TextPainter extends BaseComponent { /** * @param font font to use */ - public TextPainter(GLFont font) { + public TextPainter(GLFont font) + { this(font, AlignX.LEFT, RGB.WHITE); } @@ -54,7 +55,8 @@ public class TextPainter extends BaseComponent { * @param color default color * @param text drawn text */ - public TextPainter(GLFont font, AlignX align, Color color, String text) { + public TextPainter(GLFont font, AlignX align, Color color, String text) + { this(font, align, color, new StringWrapper(text)); } @@ -67,7 +69,8 @@ public class TextPainter extends BaseComponent { * @param color default color * @param text text provider */ - public TextPainter(GLFont font, AlignX align, Color color, StringProvider text) { + public TextPainter(GLFont font, AlignX align, Color color, StringProvider text) + { this.font = new FontRenderer(font); this.color = color; this.align = align; @@ -80,7 +83,8 @@ public class TextPainter extends BaseComponent { * @param align text align * @param color default color */ - public TextPainter(GLFont font, AlignX align, Color color) { + public TextPainter(GLFont font, AlignX align, Color color) + { this(font, align, color, (StringProvider) null); } @@ -92,8 +96,8 @@ public class TextPainter extends BaseComponent { final String str = text.getString(); - Num shrX = height().perc(xPaddingPerc); - Num shrY = height().perc(yPaddingPerc); + final Num shrX = height().perc(xPaddingPerc); + final Num shrY = height().perc(yPaddingPerc); final Rect rect = getRect().shrink(shrX, shrY); @@ -101,7 +105,7 @@ public class TextPainter extends BaseComponent { font.draw(str, rect.round(), align, shadowColor); } - Rect r = (shadow ? rect.move(shadowOffset.neg()) : rect).round(); + final Rect r = (shadow ? rect.move(shadowOffset.neg()) : rect).round(); font.draw(str, r, align, color); if (Config.DEBUG_FONT_RENDER) Render.quadColor(r, RGB.PINK.withAlpha(0.4)); diff --git a/src/mightypork/gamecore/gui/screens/Overlay.java b/src/mightypork/gamecore/gui/screens/Overlay.java index d6e8632..18539f7 100644 --- a/src/mightypork/gamecore/gui/screens/Overlay.java +++ b/src/mightypork/gamecore/gui/screens/Overlay.java @@ -25,7 +25,8 @@ import mightypork.gamecore.util.math.constraints.vect.Vect; * * @author MightyPork */ -public abstract class Overlay extends AppSubModule implements Comparable, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener { +public abstract class Overlay extends AppSubModule implements Comparable, Updateable, Renderable, KeyBinder, Hideable, Enableable, + LayoutChangeListener { private boolean visible = true; private boolean enabled = true; @@ -87,19 +88,22 @@ public abstract class Overlay extends AppSubModule implements Comparable= 0 ? "+" : "") + atk); rtTxP.setColor(RGB.CYAN); rtTxP.render(); } + + + if (itm.isDamageable()) { + Color.pushAlpha(hAlpha); + + Render.quadColor(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); + + Render.quadColor(usesRect.shrinkRight(usesRect.width().value() * (1 - useRatio)), barColor); + + Color.popAlpha(); + } } } diff --git a/src/mightypork/rogue/screens/game/NavButton.java b/src/mightypork/rogue/screens/game/NavButton.java index 188dd98..e1c7aed 100644 --- a/src/mightypork/rogue/screens/game/NavButton.java +++ b/src/mightypork/rogue/screens/game/NavButton.java @@ -40,7 +40,7 @@ public class NavButton extends ClickableComponent { bg = base; } - if(!isEnabled()) bg = base; // override effects + if (!isEnabled()) bg = base; // override effects Render.quadTextured(this, bg); Render.quadTextured(this, fg); diff --git a/src/mightypork/rogue/screens/game/ScreenGame.java b/src/mightypork/rogue/screens/game/ScreenGame.java index d172029..51931cc 100644 --- a/src/mightypork/rogue/screens/game/ScreenGame.java +++ b/src/mightypork/rogue/screens/game/ScreenGame.java @@ -4,12 +4,14 @@ package mightypork.rogue.screens.game; import java.util.Random; import mightypork.gamecore.app.AppAccess; +import mightypork.gamecore.eventbus.events.Updateable; import mightypork.gamecore.gui.Action; import mightypork.gamecore.gui.ActionGroup; import mightypork.gamecore.gui.screens.LayeredScreen; import mightypork.gamecore.input.KeyStroke; import mightypork.gamecore.input.Keys; import mightypork.rogue.Config; +import mightypork.rogue.world.World.PlayerFacade; import mightypork.rogue.world.WorldProvider; import mightypork.rogue.world.events.WorldPauseRequest; import mightypork.rogue.world.events.WorldPauseRequest.PauseAction; @@ -31,6 +33,8 @@ public class ScreenGame extends LayeredScreen { private InvLayer invLayer; private HudLayer hudLayer; + private WorldLayer worldLayer; + private GScrState state = GScrState.WORLD; private final ActionGroup worldActions = new ActionGroup(); @@ -40,16 +44,18 @@ public class ScreenGame extends LayeredScreen { @Override public void execute() { - WorldProvider.get().getPlayer().tryToEatSomeFood(); + final PlayerFacade pl = WorldProvider.get().getPlayer(); + if (pl.isDead()) return; + pl.tryToEatSomeFood(); } }; - public Action actionInv = new Action() { + public Action actionToggleInv = new Action() { @Override public void execute() { - setState(GScrState.INV); + setState(getState() == GScrState.INV ? GScrState.WORLD : GScrState.INV); } }; @@ -80,8 +86,6 @@ public class ScreenGame extends LayeredScreen { } }; - private WorldLayer worldLayer; - /** * Set gui state (overlay) @@ -122,7 +126,8 @@ public class ScreenGame extends LayeredScreen { } - public ScreenGame(AppAccess app) { + public ScreenGame(AppAccess app) + { super(app); addLayer(invLayer = new InvLayer(this)); @@ -152,17 +157,16 @@ public class ScreenGame extends LayeredScreen { bindKey(new KeyStroke(Keys.PAUSE), actionTogglePause); bindKey(new KeyStroke(Keys.SPACE), actionTogglePause); - bindKey(new KeyStroke(Keys.I), actionInv); + bindKey(new KeyStroke(Keys.I), actionToggleInv); bindKey(new KeyStroke(Keys.E), actionEat); bindKey(new KeyStroke(Keys.M), actionToggleMinimap); bindKey(new KeyStroke(Keys.Z), actionToggleZoom); - + // add as actions - enableables. worldActions.add(worldLayer); worldActions.add(hudLayer); worldActions.add(actionEat); - worldActions.add(actionInv); worldActions.add(actionToggleMinimap); worldActions.add(actionTogglePause); worldActions.add(actionToggleZoom); diff --git a/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java b/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java index 14eada2..a3ea86e 100644 --- a/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java +++ b/src/mightypork/rogue/screens/game/WorldConsoleRenderer.java @@ -3,8 +3,6 @@ package mightypork.rogue.screens.game; import java.util.Collection; import java.util.ConcurrentModificationException; -import java.util.LinkedList; -import java.util.List; import mightypork.gamecore.gui.AlignX; import mightypork.gamecore.gui.components.BaseComponent; @@ -17,7 +15,6 @@ import mightypork.gamecore.util.math.constraints.num.mutable.NumVar; import mightypork.gamecore.util.math.constraints.rect.Rect; import mightypork.rogue.Res; import mightypork.rogue.world.WorldConsole; -import mightypork.rogue.world.WorldConsole.Entry; import mightypork.rogue.world.WorldProvider; @@ -37,25 +34,25 @@ public class WorldConsoleRenderer extends BaseComponent { @Override protected void renderComponent() { - double rh = rowHeight.value(); + final double rh = rowHeight.value(); - Rect lowRow = bottomEdge().growUp(rowHeight); + final Rect lowRow = bottomEdge().growUp(rowHeight); - Collection entries = WorldProvider.get().getWorld().getConsole().getEntries(); + final Collection entries = WorldProvider.get().getWorld().getConsole().getEntries(); int cnt = 0; - NumVar alph = Num.makeVar(); + final NumVar alph = Num.makeVar(); Color.pushAlpha(alph); try { - for (WorldConsole.Entry entry : entries) { + for (final WorldConsole.Entry entry : entries) { alph.setTo(entry.getAlpha()); - Rect rrr = lowRow.moveY(-rh * cnt); + final Rect rrr = lowRow.moveY(-rh * cnt); fr.draw(entry.getMessage(), rrr.move(rh / 12, rh / 12), AlignX.LEFT, RGB.BLACK_60); fr.draw(entry.getMessage(), rrr, AlignX.LEFT, RGB.WHITE); @@ -63,7 +60,7 @@ public class WorldConsoleRenderer extends BaseComponent { cnt++; } - } catch (ConcurrentModificationException e) { + } catch (final ConcurrentModificationException e) { Log.e(e); // this should not happen anymore } diff --git a/src/mightypork/rogue/world/Inventory.java b/src/mightypork/rogue/world/Inventory.java index ed0bd6e..9d12a41 100644 --- a/src/mightypork/rogue/world/Inventory.java +++ b/src/mightypork/rogue/world/Inventory.java @@ -16,12 +16,14 @@ public class Inventory implements IonObjBinary { private Item[] items; - public Inventory(int size) { + public Inventory(int size) + { this.items = new Item[size]; } - public Inventory() { + public Inventory() + { // ION constructor } @@ -158,7 +160,7 @@ public class Inventory implements IonObjBinary { public void clean() { for (int i = 0; i < getSize(); i++) { - Item itm = getItem(i); + final Item itm = getItem(i); if (itm == null) continue; if (itm.isEmpty()) setItem(i, null); } @@ -175,10 +177,8 @@ public class Inventory implements IonObjBinary { s += i + ": "; final Item itm = getItem(i); - if (itm == null) - s += ""; - else - s += itm; + if (itm == null) s += ""; + else s += itm; } s += "]"; return s; diff --git a/src/mightypork/rogue/world/PlayerControl.java b/src/mightypork/rogue/world/PlayerControl.java index 829327f..ace0d74 100644 --- a/src/mightypork/rogue/world/PlayerControl.java +++ b/src/mightypork/rogue/world/PlayerControl.java @@ -12,6 +12,7 @@ import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.entity.EntityType; import mightypork.rogue.world.entity.modules.EntityMoveListener; import mightypork.rogue.world.level.Level; +import mightypork.rogue.world.tile.Tile; public abstract class PlayerControl { @@ -104,7 +105,7 @@ public abstract class PlayerControl { public boolean clickTile(Vect pos) - { + { if (pos.dist(getPlayer().getVisualPos().add(0.5, 0.5)).value() < 1.5) { return doClickTile(pos); } @@ -115,15 +116,20 @@ public abstract class PlayerControl { private boolean doClickTile(Vect pos) { - // 1st try to hit entity + //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; } - //2nd try to click tile - return getLevel().getTile(Coord.fromVect(pos)).onClick(); + return false; } diff --git a/src/mightypork/rogue/world/PlayerInfo.java b/src/mightypork/rogue/world/PlayerInfo.java index 4b5c9b7..b113ecc 100644 --- a/src/mightypork/rogue/world/PlayerInfo.java +++ b/src/mightypork/rogue/world/PlayerInfo.java @@ -106,7 +106,7 @@ public class PlayerInfo implements IonObjBundled { public void selectWeapon(int selectedWeapon) { - if(selectedWeapon<0||selectedWeapon>=getInventory().getSize()) { + if (selectedWeapon < 0 || selectedWeapon >= getInventory().getSize()) { selectedWeapon = NO_WEAPON; } diff --git a/src/mightypork/rogue/world/World.java b/src/mightypork/rogue/world/World.java index f4259c2..d7fa328 100644 --- a/src/mightypork/rogue/world/World.java +++ b/src/mightypork/rogue/world/World.java @@ -229,7 +229,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea public void tryToEatSomeFood() { - List foods = new ArrayList<>(); + final List foods = new ArrayList<>(); for (int i = 0; i < getInventory().getSize(); i++) { final Item itm = getInventory().getItem(i); if (itm != null && itm.getType() == ItemType.FOOD) { @@ -247,14 +247,14 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea } }); - for (Item itm : foods) { + for (final Item itm : foods) { if (eatFood(itm)) { getInventory().clean(); return; } } - if(getHealth() wpns = new ArrayList<>(); + final List wpns = new ArrayList<>(); for (int i = 0; i < getInventory().getSize(); i++) { final Item itm = getInventory().getItem(i); if (itm != null && itm.getType() == ItemType.WEAPON) { @@ -311,7 +311,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea } }); - for (Item itm : wpns) { + for (final Item itm : wpns) { for (int i = 0; i < getInventory().getSize(); i++) { final Item itm2 = getInventory().getItem(i); if (itm2 == itm) { @@ -584,6 +584,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea console.addMessage("You don't have any food!"); } + public void msgNotHungry() { console.addMessage("You are not hungry."); diff --git a/src/mightypork/rogue/world/WorldConsole.java b/src/mightypork/rogue/world/WorldConsole.java index 6a8d1fd..72c2937 100644 --- a/src/mightypork/rogue/world/WorldConsole.java +++ b/src/mightypork/rogue/world/WorldConsole.java @@ -1,9 +1,10 @@ package mightypork.rogue.world; -import java.util.*; +import java.util.Collection; +import java.util.Deque; +import java.util.Iterator; import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.LinkedBlockingQueue; import mightypork.gamecore.eventbus.events.Updateable; import mightypork.gamecore.util.math.Easing; @@ -22,7 +23,8 @@ public class WorldConsole implements Updateable { private double elapsed = 0; - private Entry(String text) { + private Entry(String text) + { this.text = text; this.fadeout = new NumAnimated(1, Easing.LINEAR); this.fadeout.setDefaultDuration(0.5); @@ -76,8 +78,8 @@ public class WorldConsole implements Updateable { @Override public void update(double delta) { - for (Iterator iter = entries.iterator(); iter.hasNext();) { - Entry e = iter.next(); + for (final Iterator iter = entries.iterator(); iter.hasNext();) { + final Entry e = iter.next(); e.update(delta); @@ -99,7 +101,9 @@ public class WorldConsole implements Updateable { return entries; } - public void clear() { + + public void clear() + { entries.clear(); } } diff --git a/src/mightypork/rogue/world/WorldCreator.java b/src/mightypork/rogue/world/WorldCreator.java index 71247a9..8a3a9a3 100644 --- a/src/mightypork/rogue/world/WorldCreator.java +++ b/src/mightypork/rogue/world/WorldCreator.java @@ -4,7 +4,6 @@ package mightypork.rogue.world; import java.util.Random; import mightypork.rogue.world.gen.LevelGenerator; -import mightypork.rogue.world.level.Level; public class WorldCreator { @@ -20,12 +19,15 @@ public class WorldCreator { final World w = new World(); w.setSeed(seed); - final int count = 7; +// final int count = 7; +// +// for (int i = 1; i <= count; i++) { +// final Level l = LevelGenerator.build(w, rand.nextLong(), i, LevelGenerator.DUNGEON_THEME, i == count); +// w.addLevel(l); +// } - for (int i = 1; i <= count; i++) { - final Level l = LevelGenerator.build(w, rand.nextLong(), i, LevelGenerator.DUNGEON_THEME, i == count); - w.addLevel(l); - } + w.addLevel(LevelGenerator.build(w, rand.nextLong(), 6, LevelGenerator.DUNGEON_THEME, false)); + w.addLevel(LevelGenerator.build(w, rand.nextLong(), 7, LevelGenerator.DUNGEON_THEME, true)); w.createPlayer(); diff --git a/src/mightypork/rogue/world/entity/Entities.java b/src/mightypork/rogue/world/entity/Entities.java index 019de4d..ff9c624 100644 --- a/src/mightypork/rogue/world/entity/Entities.java +++ b/src/mightypork/rogue/world/entity/Entities.java @@ -6,8 +6,10 @@ import java.util.Collection; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonOutput; +import mightypork.rogue.world.entity.entities.EntityBossRat; +import mightypork.rogue.world.entity.entities.EntityBrownRat; +import mightypork.rogue.world.entity.entities.EntityGrayRat; import mightypork.rogue.world.entity.entities.PlayerEntity; -import mightypork.rogue.world.entity.entities.RatEntity; /** @@ -20,7 +22,9 @@ public final class Entities { private static final EntityModel[] entities = new EntityModel[256]; public static final EntityModel PLAYER = new EntityModel(1, PlayerEntity.class); - public static final EntityModel RAT = new EntityModel(2, RatEntity.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) diff --git a/src/mightypork/rogue/world/entity/Entity.java b/src/mightypork/rogue/world/entity/Entity.java index 209bf80..afe7c09 100644 --- a/src/mightypork/rogue/world/entity/Entity.java +++ b/src/mightypork/rogue/world/entity/Entity.java @@ -35,7 +35,7 @@ public abstract class Entity implements IonObjBundled, Updateable { protected final Random rand = new Random(); /** Entity ID */ - private int entityId; + private int entityId = -1; private final Map modules = new HashMap<>(); @@ -123,6 +123,10 @@ public abstract class Entity implements IonObjBundled, Updateable { public void setLevel(Level level) { + if (level != null && entityId < 0) { + entityId = level.getWorld().getNewEID(); + } + if (level != null) level.freeTile(getCoord()); this.level = level; @@ -266,5 +270,6 @@ public abstract class Entity implements IonObjBundled, Updateable { return despawnDelay; } + public abstract String getVisualName(); } diff --git a/src/mightypork/rogue/world/entity/EntityModel.java b/src/mightypork/rogue/world/entity/EntityModel.java index 60ffa08..01c8314 100644 --- a/src/mightypork/rogue/world/entity/EntityModel.java +++ b/src/mightypork/rogue/world/entity/EntityModel.java @@ -45,6 +45,18 @@ public final class EntityModel { } + /** + * Create entitiy without EID. EID will be assigned when the entity is added + * to a level. + * + * @return entity. + */ + public Entity createEntity() + { + return createEntity(-1); + } + + public Entity loadEntity(IonInput in) throws IOException { final IonBundle bundle = in.readBundle(); diff --git a/src/mightypork/rogue/world/entity/entities/BossRatAi.java b/src/mightypork/rogue/world/entity/entities/BossRatAi.java new file mode 100644 index 0000000..4135af2 --- /dev/null +++ b/src/mightypork/rogue/world/entity/entities/BossRatAi.java @@ -0,0 +1,48 @@ +package mightypork.rogue.world.entity.entities; + + +import mightypork.rogue.world.entity.AiTimer; +import mightypork.rogue.world.entity.Entity; + + +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.6); + } + + + @Override + protected int getAttackStrength() + { + return 5 + rand.nextInt(4); + } + + + @Override + protected int getPreyAbandonDistance() + { + return 15 + rand.nextInt(4); + } + + + @Override + public void update(double delta) + { + super.update(delta); + healTimer.update(delta); + } +} diff --git a/src/mightypork/rogue/world/entity/entities/BrownRatAi.java b/src/mightypork/rogue/world/entity/entities/BrownRatAi.java new file mode 100644 index 0000000..f64ed65 --- /dev/null +++ b/src/mightypork/rogue/world/entity/entities/BrownRatAi.java @@ -0,0 +1,37 @@ +package mightypork.rogue.world.entity.entities; + + +import mightypork.rogue.world.entity.Entity; + + +public class BrownRatAi extends GrayRatAi { + + public BrownRatAi(Entity entity) + { + super(entity); + + setAttackTime(0.8); + setScanTime(1); + } + + + @Override + protected double getScanRadius() + { + return isSleeping() ? 3 + rand.nextInt(3) : 5 + rand.nextInt(3); + } + + + @Override + protected int getAttackStrength() + { + return 3 + rand.nextInt(2); + } + + + @Override + protected int getPreyAbandonDistance() + { + return 11 + rand.nextInt(4); + } +} diff --git a/src/mightypork/rogue/world/entity/entities/EntityBossRat.java b/src/mightypork/rogue/world/entity/entities/EntityBossRat.java new file mode 100644 index 0000000..8746d2a --- /dev/null +++ b/src/mightypork/rogue/world/entity/entities/EntityBossRat.java @@ -0,0 +1,92 @@ +package mightypork.rogue.world.entity.entities; + + +import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; +import mightypork.rogue.world.entity.Entity; +import mightypork.rogue.world.entity.EntityModel; +import mightypork.rogue.world.entity.EntityPathFinder; +import mightypork.rogue.world.entity.EntityRenderer; +import mightypork.rogue.world.entity.EntityType; +import mightypork.rogue.world.entity.render.EntityRendererMobLR; +import mightypork.rogue.world.item.Items; + + +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); + + pos.setStepTime(0.4); + setDespawnDelay(1); + + health.setMaxHealth(80); + health.setHealth(80); + health.setHitCooldownTime(0.35); + } + + + @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 onCorpseRemoved() + { + // TODO drop rare stuff & fire event. + + if (rand.nextInt(8) == 0) { + getLevel().dropNear(getCoord(), Items.BONE.createItem()); + return; + } + + if (rand.nextInt(3) == 0) { + getLevel().dropNear(getCoord(), Items.MEAT.createItem()); + return; + } + + if (rand.nextInt(6) == 0) { + getLevel().dropNear(getCoord(), Items.CHEESE.createItem()); + return; + } + } + + + @Override + public String getVisualName() + { + return "Rat Boss"; + } +} diff --git a/src/mightypork/rogue/world/entity/entities/EntityBrownRat.java b/src/mightypork/rogue/world/entity/entities/EntityBrownRat.java new file mode 100644 index 0000000..3bfe752 --- /dev/null +++ b/src/mightypork/rogue/world/entity/entities/EntityBrownRat.java @@ -0,0 +1,92 @@ +package mightypork.rogue.world.entity.entities; + + +import mightypork.gamecore.util.math.Calc; +import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; +import mightypork.rogue.world.entity.Entity; +import mightypork.rogue.world.entity.EntityModel; +import mightypork.rogue.world.entity.EntityPathFinder; +import mightypork.rogue.world.entity.EntityRenderer; +import mightypork.rogue.world.entity.EntityType; +import mightypork.rogue.world.entity.render.EntityRendererMobLR; +import mightypork.rogue.world.item.Items; + + +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); + + pos.setStepTime(0.37); // faster than gray rat + setDespawnDelay(1); + + health.setMaxHealth(14); + health.setHealth(Calc.randInt(rand, 8, 14)); // tougher to kill + health.setHitCooldownTime(0.35); // a bit longer than gray rat + } + + + @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 onCorpseRemoved() + { + // drop rat stuff + + if (rand.nextInt(8) == 0) { + getLevel().dropNear(getCoord(), Items.BONE.createItemDamaged(10)); + return; + } + + if (rand.nextInt(3) == 0) { + getLevel().dropNear(getCoord(), Items.MEAT.createItem()); + return; + } + + if (rand.nextInt(6) == 0) { + getLevel().dropNear(getCoord(), Items.CHEESE.createItem()); + return; + } + } + + + @Override + public String getVisualName() + { + return "Brown Rat"; + } +} diff --git a/src/mightypork/rogue/world/entity/entities/RatEntity.java b/src/mightypork/rogue/world/entity/entities/EntityGrayRat.java similarity index 69% rename from src/mightypork/rogue/world/entity/entities/RatEntity.java rename to src/mightypork/rogue/world/entity/entities/EntityGrayRat.java index 8754400..556fc76 100644 --- a/src/mightypork/rogue/world/entity/entities/RatEntity.java +++ b/src/mightypork/rogue/world/entity/entities/EntityGrayRat.java @@ -12,17 +12,17 @@ import mightypork.rogue.world.entity.render.EntityRendererMobLR; import mightypork.rogue.world.item.Items; -public class RatEntity extends Entity { +public class EntityGrayRat extends Entity { - /** Navigation PFC */ - private PathFinder pathf; + private final PathFinder pathf = new EntityPathFinder(this); - private final RatAi ai = new RatAi(this); + private final GrayRatAi ai = new GrayRatAi(this); private EntityRenderer renderer; - public RatEntity(EntityModel model, int eid) { + public EntityGrayRat(EntityModel model, int eid) + { super(model, eid); addModule("ai", ai); @@ -32,7 +32,7 @@ public class RatEntity extends Entity { setDespawnDelay(1); health.setMaxHealth(5); - health.setHealth(Calc.randInt(rand, 3, 5)); // fill health bar to max + health.setHealth(Calc.randInt(rand, 3, 5)); health.setHitCooldownTime(0.3); } @@ -40,10 +40,6 @@ public class RatEntity extends Entity { @Override public PathFinder getPathFinder() { - if (pathf == null) { - pathf = new EntityPathFinder(this); - } - return pathf; } @@ -59,41 +55,35 @@ public class RatEntity extends Entity { protected EntityRenderer getRenderer() { if (renderer == null) { - renderer = new EntityRendererMobLR(this, "sprite.rat"); + renderer = new EntityRendererMobLR(this, "sprite.rat.gray"); } return renderer; } - @Override - public void onKilled() - { - super.onKilled(); - } - - @Override public void onCorpseRemoved() { // drop rat stuff - if(rand.nextInt(7) == 0) { - getLevel().dropNear(getCoord(), Items.BONE.createItem()); + if (rand.nextInt(6) == 0) { + getLevel().dropNear(getCoord(), Items.BONE.createItemDamaged(10)); return; } - - if(rand.nextInt(3) == 0) { + + if (rand.nextInt(7) == 0) { getLevel().dropNear(getCoord(), Items.MEAT.createItem()); return; } - if(rand.nextInt(2) == 0) { + if (rand.nextInt(3) == 0) { getLevel().dropNear(getCoord(), Items.CHEESE.createItem()); return; } } + @Override public String getVisualName() { diff --git a/src/mightypork/rogue/world/entity/entities/RatAi.java b/src/mightypork/rogue/world/entity/entities/GrayRatAi.java similarity index 91% rename from src/mightypork/rogue/world/entity/entities/RatAi.java rename to src/mightypork/rogue/world/entity/entities/GrayRatAi.java index 2ebe289..8db37a9 100644 --- a/src/mightypork/rogue/world/entity/entities/RatAi.java +++ b/src/mightypork/rogue/world/entity/entities/GrayRatAi.java @@ -4,9 +4,9 @@ package mightypork.rogue.world.entity.entities; import mightypork.rogue.world.entity.Entity; -public class RatAi extends MonsterAi { +public class GrayRatAi extends MonsterAi { - public RatAi(Entity entity) + public GrayRatAi(Entity entity) { super(entity); diff --git a/src/mightypork/rogue/world/entity/entities/PlayerEntity.java b/src/mightypork/rogue/world/entity/entities/PlayerEntity.java index 9e9183d..86e5fce 100644 --- a/src/mightypork/rogue/world/entity/entities/PlayerEntity.java +++ b/src/mightypork/rogue/world/entity/entities/PlayerEntity.java @@ -16,7 +16,8 @@ public class PlayerEntity extends Entity { class PlayerAi extends EntityModule implements EntityMoveListener { - public PlayerAi(Entity entity) { + public PlayerAi(Entity entity) + { super(entity); setDespawnDelay(2); @@ -79,7 +80,8 @@ public class PlayerEntity extends Entity { private final PlayerAi ai = new PlayerAi(this); - public PlayerEntity(EntityModel model, int eid) { + public PlayerEntity(EntityModel model, int eid) + { super(model, eid); pos.setStepTime(0.25); diff --git a/src/mightypork/rogue/world/gen/LevelGenerator.java b/src/mightypork/rogue/world/gen/LevelGenerator.java index 7f18215..c749eb0 100644 --- a/src/mightypork/rogue/world/gen/LevelGenerator.java +++ b/src/mightypork/rogue/world/gen/LevelGenerator.java @@ -20,7 +20,7 @@ public class LevelGenerator { @SuppressWarnings("fallthrough") - public static Level build(World world, long seed, int complexity, MapTheme theme, boolean lastLevel) + public static Level build(World world, long seed, int complexity, MapTheme theme, boolean lastLevel) throws WorldGenError { Log.f3("Generating level of complexity: " + complexity); @@ -31,7 +31,9 @@ public class LevelGenerator { final ScratchMap map = new ScratchMap(max_size, theme, rand); // start - map.addRoom(Rooms.ENTRANCE, true); + if (!map.addRoom(Rooms.ENTRANCE, true)) { + throw new WorldGenError("Could not place entrance room."); + } for (int i = 0; i < 1 + complexity / 2 + rand.nextInt((int) (1 + complexity * 0.2)); i++) { map.addRoom(Rooms.BASIC, false); @@ -39,51 +41,61 @@ public class LevelGenerator { if (rand.nextInt(7) > 0) map.addRoom(Rooms.DEAD_END, false); } - if (!lastLevel) map.addRoom(Rooms.EXIT, true); + if (!lastLevel) { + if (!map.addRoom(Rooms.EXIT, true)) { + throw new WorldGenError("Could not place exit room."); + } + } + + if (lastLevel) { + if (!map.addRoom(Rooms.BOSS_ROOM, true)) { + throw new WorldGenError("Could not place boss room."); + } + } + map.buildCorridors(); - switch(complexity) { + switch (complexity) { default: case 3: case 2: - if(rand.nextInt(2)==0) map.dropInMap(Items.CLUB.createItem(), 50); + if (rand.nextInt(2) == 0) map.dropInMap(Items.CLUB.createItemDamaged(60), 50); case 1: case 0: - if(rand.nextInt(2)==0) map.dropInMap(Items.ROCK.createItem(), 50); + if (rand.nextInt(2) == 0) map.dropInMap(Items.ROCK.createItemDamaged(10), 50); } - if(complexity == 6) { - map.dropInMap(Items.SWORD.createItem(), 200); + if (complexity == 6) { + map.dropInMap(Items.SWORD.createItemDamaged(40), 200); } - if(complexity == 5) { - map.dropInMap(Items.HAMMER.createItem(), 100); + if (complexity == 5) { + map.dropInMap(Items.HAMMER.createItemDamaged(40), 100); } - final Coord size = map.getNeededSize(); - final Level lvl = new Level(size.x, size.y); - - map.writeToLevel(lvl); - - // TODO tmp - // spawn rats + // entities - random rats - // TODO entities in ScratchMap itself - final Coord pos = Coord.make(0, 0); for (int i = 0; i < 3 + complexity + rand.nextInt(1 + complexity); i++) { + Entity e; - final Entity e = Entities.RAT.createEntity(world); - - for (int j = 0; j < 20; j++) { - pos.x = rand.nextInt(lvl.getWidth()); - pos.y = rand.nextInt(lvl.getHeight()); - - if (lvl.addEntity(e, pos)) break; + if (rand.nextInt((int) (complexity / 1.5) + 1) != 0) { + e = Entities.RAT_BROWN.createEntity(); + } else { + e = Entities.RAT_GRAY.createEntity(); } + + map.putEntityInMap(e, 20); } + + 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; } } diff --git a/src/mightypork/rogue/world/gen/RoomBuilder.java b/src/mightypork/rogue/world/gen/RoomBuilder.java index ac53653..39c3e4d 100644 --- a/src/mightypork/rogue/world/gen/RoomBuilder.java +++ b/src/mightypork/rogue/world/gen/RoomBuilder.java @@ -13,5 +13,5 @@ import mightypork.gamecore.util.math.algo.Coord; */ public interface RoomBuilder { - RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center); + RoomDesc buildToFit(ScratchMap map, MapTheme theme, Random rand, Coord center) throws WorldGenError; } diff --git a/src/mightypork/rogue/world/gen/ScratchMap.java b/src/mightypork/rogue/world/gen/ScratchMap.java index 1d976c5..34d5feb 100644 --- a/src/mightypork/rogue/world/gen/ScratchMap.java +++ b/src/mightypork/rogue/world/gen/ScratchMap.java @@ -14,6 +14,7 @@ import mightypork.gamecore.util.math.algo.Sides; import mightypork.gamecore.util.math.algo.Step; import mightypork.gamecore.util.math.algo.pathfinding.Heuristic; import mightypork.gamecore.util.math.algo.pathfinding.PathFinder; +import mightypork.rogue.world.entity.Entity; import mightypork.rogue.world.item.Item; import mightypork.rogue.world.level.Level; import mightypork.rogue.world.tile.Tile; @@ -37,6 +38,9 @@ public class ScratchMap { /** 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 @@ -72,7 +76,7 @@ public class ScratchMap { return 100; default: - throw new RuntimeException("Unknown tile type: " + t.getType()); + throw new WorldGenError("Unknown tile type: " + t.getType()); } } @@ -132,7 +136,7 @@ public class ScratchMap { } - public void addRoom(RoomBuilder rb, boolean critical) + public boolean addRoom(RoomBuilder rb, boolean critical) { final Coord center = Coord.make(0, 0); @@ -150,16 +154,16 @@ public class ScratchMap { switch (rand.nextInt(4)) { case 0: - center.x += 1 + (failed_total / 50); + center.x += (failed_total / 35); break; case 1: - center.x -= 1 + (failed_total / 50); + center.x -= (failed_total / 35); break; case 2: - center.y += 1 + (failed_total / 50); + center.y += (failed_total / 35); break; case 3: - center.y -= 1 + (failed_total / 50); + center.y -= (failed_total / 35); } final RoomDesc rd = rb.buildToFit(this, theme, rand, center); @@ -174,14 +178,18 @@ public class ScratchMap { clampBounds(); nodes.add(center); - Log.f3("Placed room on " + Calc.ordinal(1+failed_total) + " try."); +// Log.f3("Placed room (failed " + failed_total + " x)."); - return; + return true; } else { failed++; failed_total++; - if (failed > 400) { + if (failed_total > 1000) { + return false; + } + + if (failed > 300) { Log.w("Faild to build room."); if (critical) { @@ -192,16 +200,13 @@ public class ScratchMap { clampBounds(); failed = 0; + Log.f3("Trying again."); continue; } else { - return; + return false; } } - - if (failed_total > 1000) { - throw new RuntimeException("Generation error - could not place critical room."); - } } } @@ -226,7 +231,7 @@ public class ScratchMap { public Tile getTile(Coord pos) { if (!isIn(pos)) { - throw new IndexOutOfBoundsException("Tile not in map: " + pos); + throw new WorldGenError("Tile not in map: " + pos); } return map[pos.y][pos.x]; @@ -242,7 +247,7 @@ public class ScratchMap { public boolean set(Coord pos, Tile tile) { if (!isIn(pos)) { - throw new IndexOutOfBoundsException("Tile not in map: " + pos); + throw new WorldGenError("Tile not in map: " + pos); } map[pos.y][pos.x] = tile; @@ -263,7 +268,7 @@ public class ScratchMap { public void protect(Coord min, Coord max, TileProtectLevel prot) { - if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max); + 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++) @@ -274,7 +279,7 @@ public class ScratchMap { public void fill(Coord min, Coord max, TileModel tm) { - if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max); + 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++) @@ -285,7 +290,7 @@ public class ScratchMap { public void border(Coord min, Coord max, TileModel tm) { - if (!isIn(min) || !isIn(max)) throw new IndexOutOfBoundsException("Tile(s) not in map: " + min + " , " + max); + if (!isIn(min) || !isIn(max)) throw new WorldGenError("Tile(s) not in map: " + min + " , " + max); final Coord c = Coord.make(0, 0); @@ -540,9 +545,24 @@ public class ScratchMap { 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)) { + final Tile t = level.getTile(pos); + //@formatter:off + throw new WorldGenError( + "Could not put entity into a level map: e_pos=" + pos + + ", tile: " + Log.str(t) + + ", t.wa " + t.isWalkable() + + ", t.oc " + t.isOccupied() + + ", ent.. " + e.getVisualName()); + //@formatter:on + } + } } @@ -556,26 +576,68 @@ public class ScratchMap { { exitPoint.setTo(pos); } - - + + public boolean dropInArea(Item item, Coord min, Coord max, int tries) { - Coord pos = Coord.zero(); + final Coord pos = Coord.zero(); - for(int i=0; i0) uses--; - if(uses==0) consume(); + + public void use() + { + if (uses > 0) uses--; + if (uses == 0) consume(); } - - + + public abstract boolean isDamageable(); - - + + public abstract String getVisualName(); } diff --git a/src/mightypork/rogue/world/item/ItemModel.java b/src/mightypork/rogue/world/item/ItemModel.java index 173d69e..86774da 100644 --- a/src/mightypork/rogue/world/item/ItemModel.java +++ b/src/mightypork/rogue/world/item/ItemModel.java @@ -2,9 +2,11 @@ package mightypork.rogue.world.item; import java.io.IOException; +import java.util.Random; import mightypork.gamecore.util.ion.IonInput; import mightypork.gamecore.util.ion.IonOutput; +import mightypork.gamecore.util.math.Calc; /** @@ -18,8 +20,11 @@ public final class ItemModel { public final int id; public final Class itemClass; + public static final Random rand = new Random(); - public ItemModel(int id, Class item) { + + public ItemModel(int id, Class item) + { Items.register(id, this); this.id = id; this.itemClass = item; @@ -32,7 +37,7 @@ public final class ItemModel { public Item createItem() { try { - Item itm = itemClass.getConstructor(ItemModel.class).newInstance(this); + final Item itm = itemClass.getConstructor(ItemModel.class).newInstance(this); itm.setRemainingUses(itm.getMaxUses()); @@ -58,4 +63,12 @@ public final class ItemModel { tile.save(out); } + + + public Item createItemDamaged(int minimalHealthPercent) + { + final Item item = createItem(); + item.setRemainingUses(Calc.randInt(rand, (int) Math.ceil(item.getMaxUses() * (minimalHealthPercent / 100D)), item.getMaxUses())); + return item; + } } diff --git a/src/mightypork/rogue/world/item/ItemRenderer.java b/src/mightypork/rogue/world/item/ItemRenderer.java index d4a26e3..a3d9ba7 100644 --- a/src/mightypork/rogue/world/item/ItemRenderer.java +++ b/src/mightypork/rogue/world/item/ItemRenderer.java @@ -9,13 +9,12 @@ public abstract class ItemRenderer { protected final Item item; - - public ItemRenderer(Item item) { + public ItemRenderer(Item item) + { this.item = item; } - - - + + public abstract void render(Rect r); } diff --git a/src/mightypork/rogue/world/item/items/ItemBaseFood.java b/src/mightypork/rogue/world/item/items/ItemBaseFood.java index a539334..579e7ef 100644 --- a/src/mightypork/rogue/world/item/items/ItemBaseFood.java +++ b/src/mightypork/rogue/world/item/items/ItemBaseFood.java @@ -34,12 +34,14 @@ public abstract class ItemBaseFood extends Item { return ItemType.FOOD; } + @Override public boolean isDamageable() { return false; } + @Override public int getMaxUses() { diff --git a/src/mightypork/rogue/world/item/items/ItemBaseWeapon.java b/src/mightypork/rogue/world/item/items/ItemBaseWeapon.java index 394a25e..2602871 100644 --- a/src/mightypork/rogue/world/item/items/ItemBaseWeapon.java +++ b/src/mightypork/rogue/world/item/items/ItemBaseWeapon.java @@ -34,6 +34,7 @@ public abstract class ItemBaseWeapon extends Item { return ItemType.WEAPON; } + @Override public boolean isDamageable() { diff --git a/src/mightypork/rogue/world/item/items/food/ItemCheese.java b/src/mightypork/rogue/world/item/items/food/ItemCheese.java index d90ab8b..0b57645 100644 --- a/src/mightypork/rogue/world/item/items/food/ItemCheese.java +++ b/src/mightypork/rogue/world/item/items/food/ItemCheese.java @@ -28,7 +28,7 @@ public class ItemCheese extends ItemBaseFood { { return 2; } - + @Override public String getVisualName() diff --git a/src/mightypork/rogue/world/item/items/food/ItemMeat.java b/src/mightypork/rogue/world/item/items/food/ItemMeat.java index d5d56e4..e57344d 100644 --- a/src/mightypork/rogue/world/item/items/food/ItemMeat.java +++ b/src/mightypork/rogue/world/item/items/food/ItemMeat.java @@ -28,7 +28,7 @@ public class ItemMeat extends ItemBaseFood { { return 3; } - + @Override public String getVisualName() diff --git a/src/mightypork/rogue/world/item/items/food/ItemSandwich.java b/src/mightypork/rogue/world/item/items/food/ItemSandwich.java index 6378c06..4355a40 100644 --- a/src/mightypork/rogue/world/item/items/food/ItemSandwich.java +++ b/src/mightypork/rogue/world/item/items/food/ItemSandwich.java @@ -28,7 +28,7 @@ public class ItemSandwich extends ItemBaseFood { { return 6; } - + @Override public String getVisualName() diff --git a/src/mightypork/rogue/world/item/items/weapons/ItemBone.java b/src/mightypork/rogue/world/item/items/weapons/ItemBone.java index ca34b9a..8613ad8 100644 --- a/src/mightypork/rogue/world/item/items/weapons/ItemBone.java +++ b/src/mightypork/rogue/world/item/items/weapons/ItemBone.java @@ -1,5 +1,6 @@ package mightypork.rogue.world.item.items.weapons; + import mightypork.rogue.Res; import mightypork.rogue.world.item.ItemModel; import mightypork.rogue.world.item.ItemRenderer; @@ -8,32 +9,37 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemBone extends ItemBaseWeapon { - - public ItemBone(ItemModel model) { + + public ItemBone(ItemModel model) + { super(model); } - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txq("item.bone")); } - + + @Override public int getAttackPoints() { return 1; } + @Override public int getMaxUses() { return 15; } + @Override public String getVisualName() { return "Bone"; } -} \ No newline at end of file +} diff --git a/src/mightypork/rogue/world/item/items/weapons/ItemClub.java b/src/mightypork/rogue/world/item/items/weapons/ItemClub.java index 96e6be8..15fe48d 100644 --- a/src/mightypork/rogue/world/item/items/weapons/ItemClub.java +++ b/src/mightypork/rogue/world/item/items/weapons/ItemClub.java @@ -1,5 +1,6 @@ package mightypork.rogue.world.item.items.weapons; + import mightypork.rogue.Res; import mightypork.rogue.world.item.ItemModel; import mightypork.rogue.world.item.ItemRenderer; @@ -8,32 +9,37 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemClub extends ItemBaseWeapon { - - public ItemClub(ItemModel model) { + + public ItemClub(ItemModel model) + { super(model); } - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txq("item.club")); } - + + @Override public int getAttackPoints() { return 3; } + @Override public int getMaxUses() { return 25; } + @Override public String getVisualName() { return "Wooden Club"; } -} \ No newline at end of file +} diff --git a/src/mightypork/rogue/world/item/items/weapons/ItemHammer.java b/src/mightypork/rogue/world/item/items/weapons/ItemHammer.java index d7de95e..5ef5712 100644 --- a/src/mightypork/rogue/world/item/items/weapons/ItemHammer.java +++ b/src/mightypork/rogue/world/item/items/weapons/ItemHammer.java @@ -1,5 +1,6 @@ package mightypork.rogue.world.item.items.weapons; + import mightypork.rogue.Res; import mightypork.rogue.world.item.ItemModel; import mightypork.rogue.world.item.ItemRenderer; @@ -8,32 +9,37 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemHammer extends ItemBaseWeapon { - - public ItemHammer(ItemModel model) { + + public ItemHammer(ItemModel model) + { super(model); } - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txq("item.hammer")); } - + + @Override public int getAttackPoints() { return 4; } + @Override public int getMaxUses() { return 50; } + @Override public String getVisualName() { return "Hammer"; } -} \ No newline at end of file +} diff --git a/src/mightypork/rogue/world/item/items/weapons/ItemStone.java b/src/mightypork/rogue/world/item/items/weapons/ItemStone.java index d680dac..e50e1a4 100644 --- a/src/mightypork/rogue/world/item/items/weapons/ItemStone.java +++ b/src/mightypork/rogue/world/item/items/weapons/ItemStone.java @@ -1,5 +1,6 @@ package mightypork.rogue.world.item.items.weapons; + import mightypork.rogue.Res; import mightypork.rogue.world.item.ItemModel; import mightypork.rogue.world.item.ItemRenderer; @@ -8,32 +9,37 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemStone extends ItemBaseWeapon { - - public ItemStone(ItemModel model) { + + public ItemStone(ItemModel model) + { super(model); } - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txq("item.stone")); } - + + @Override public int getAttackPoints() { return 2; } + @Override public int getMaxUses() { return 20; } + @Override public String getVisualName() { return "Rock"; } -} \ No newline at end of file +} diff --git a/src/mightypork/rogue/world/item/items/weapons/ItemSword.java b/src/mightypork/rogue/world/item/items/weapons/ItemSword.java index efbfea5..9459194 100644 --- a/src/mightypork/rogue/world/item/items/weapons/ItemSword.java +++ b/src/mightypork/rogue/world/item/items/weapons/ItemSword.java @@ -1,5 +1,6 @@ package mightypork.rogue.world.item.items.weapons; + import mightypork.rogue.Res; import mightypork.rogue.world.item.ItemModel; import mightypork.rogue.world.item.ItemRenderer; @@ -8,32 +9,37 @@ import mightypork.rogue.world.item.render.QuadItemRenderer; public class ItemSword extends ItemBaseWeapon { - - public ItemSword(ItemModel model) { + + public ItemSword(ItemModel model) + { super(model); } - + + @Override protected ItemRenderer makeRenderer() { return new QuadItemRenderer(this, Res.txq("item.sword")); } - + + @Override public int getAttackPoints() { return 6; } + @Override public int getMaxUses() { return 100; } + @Override public String getVisualName() { - return "Wooden Club"; + return "Sword"; } -} \ No newline at end of file +} diff --git a/src/mightypork/rogue/world/item/render/QuadItemRenderer.java b/src/mightypork/rogue/world/item/render/QuadItemRenderer.java index 7940487..e9003d6 100644 --- a/src/mightypork/rogue/world/item/render/QuadItemRenderer.java +++ b/src/mightypork/rogue/world/item/render/QuadItemRenderer.java @@ -3,11 +3,7 @@ package mightypork.rogue.world.item.render; import mightypork.gamecore.render.Render; import mightypork.gamecore.resources.textures.TxQuad; -import mightypork.gamecore.util.math.color.Color; -import mightypork.gamecore.util.math.color.pal.RGB; -import mightypork.gamecore.util.math.constraints.num.Num; import mightypork.gamecore.util.math.constraints.rect.Rect; -import mightypork.gamecore.util.math.constraints.rect.mutable.RectVar; import mightypork.rogue.world.item.Item; import mightypork.rogue.world.item.ItemRenderer; @@ -16,12 +12,9 @@ public class QuadItemRenderer extends ItemRenderer { private final TxQuad txq; - private final RectVar rrect = Rect.makeVar(); - private final Rect usesRect = rrect.topLeft().startRect().grow(Num.ZERO, rrect.width().perc(40), Num.ZERO, rrect.height().perc(8)); - private final Num hAlpha = Num.make(0.7); - - public QuadItemRenderer(Item item, TxQuad txq) { + public QuadItemRenderer(Item item, TxQuad txq) + { super(item); this.txq = txq; } @@ -31,23 +24,6 @@ public class QuadItemRenderer extends ItemRenderer { public void render(Rect r) { Render.quadTextured(r, txq); - - if (item.isDamageable()) { - Color.pushAlpha(hAlpha); - - rrect.setTo(r); - - Render.quadColor(usesRect, RGB.BLACK); - - double useRatio = (item.getRemainingUses() / (double)item.getMaxUses()); - - Color barColor = (useRatio > 0.6 ? RGB.GREEN : useRatio > 0.2 ? RGB.ORANGE : RGB.RED); - - Render.quadColor(usesRect.shrinkRight(usesRect.width().value() * (1 - useRatio)), barColor); - - Color.popAlpha(); - } - } } diff --git a/src/mightypork/rogue/world/level/Level.java b/src/mightypork/rogue/world/level/Level.java index 8bfb203..0add773 100644 --- a/src/mightypork/rogue/world/level/Level.java +++ b/src/mightypork/rogue/world/level/Level.java @@ -86,11 +86,13 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl private double timeSinceLastEntitySort; - public Level() { + public Level() + { } - public Level(int width, int height) { + public Level(int width, int height) + { size.setTo(width, height); buildArray(); } @@ -126,7 +128,7 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl 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]; } @@ -308,6 +310,34 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl } + /** + * Try to add entity at given pos, then near the pos. + * + * @param entity the entity + * @param pos pos + * @return true if added + */ + 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(-1 + rand.nextInt(3), -1 + rand.nextInt(3)); + if (addEntity(entity, c)) return true; + } + + // further + for (int i = 0; i < 20; i++) { + final Coord c = pos.add(-2 + rand.nextInt(5), -2 + rand.nextInt(5)); + if (addEntity(entity, c)) return true; + } + + return false; + + } + + /** * Try to add entity at given pos * @@ -320,6 +350,9 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl 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; @@ -330,7 +363,6 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl if (entity instanceof PlayerEntity) playerCount++; // join to level & world - entity.setLevel(this); occupyTile(entity.getCoord()); entity.setCoord(pos); diff --git a/src/mightypork/rogue/world/tile/DroppedItemRenderer.java b/src/mightypork/rogue/world/tile/DroppedItemRenderer.java index 9abb8fd..0acfee6 100644 --- a/src/mightypork/rogue/world/tile/DroppedItemRenderer.java +++ b/src/mightypork/rogue/world/tile/DroppedItemRenderer.java @@ -1,7 +1,11 @@ package mightypork.rogue.world.tile; +import java.util.Collection; + import mightypork.gamecore.util.math.Easing; +import mightypork.gamecore.util.math.constraints.num.Num; +import mightypork.gamecore.util.math.constraints.num.proxy.NumBoundAdapter; import mightypork.gamecore.util.math.constraints.rect.Rect; import mightypork.gamecore.util.math.constraints.rect.proxy.RectBoundAdapter; import mightypork.gamecore.util.math.timing.Animator; @@ -12,27 +16,26 @@ import mightypork.rogue.world.level.render.TileRenderContext; public class DroppedItemRenderer { - private Animator itemAnim = new AnimatorBounce(2, Easing.SINE_BOTH); + private final Animator itemAnim = new AnimatorBounce(2, Easing.SINE_BOTH); // prepared constraints, to avoid re-building each frame private final RectBoundAdapter tileRectAdapter = new RectBoundAdapter(); - private final Rect itemRect = tileRectAdapter.shrink(tileRectAdapter.height().perc(10)).moveY(itemAnim.neg().mul(tileRectAdapter.height().mul(0.2))); + private final NumBoundAdapter offsAdapter = new NumBoundAdapter(); + private final Rect itemRect = tileRectAdapter.shrink(tileRectAdapter.height().perc(12)).moveY(offsAdapter.neg().mul(tileRectAdapter.height().mul(0.2))); - public Animator getItemAnim() - { - if (itemAnim == null) { - itemAnim = new AnimatorBounce(2, Easing.SINE_BOTH); - } - - return itemAnim; - } - - - public void render(Item item, TileRenderContext context) + public void render(Collection items, TileRenderContext context) { tileRectAdapter.setRect(context); - item.render(itemRect); + int cnt = 0; + for (final Item i : items) { + + offsAdapter.setNum(Num.make((itemAnim.value() + (cnt % 3) * 0.1))); + + i.render(itemRect); + + cnt++; + } } diff --git a/src/mightypork/rogue/world/tile/TileRenderer.java b/src/mightypork/rogue/world/tile/TileRenderer.java index cb6a14d..d1fee55 100644 --- a/src/mightypork/rogue/world/tile/TileRenderer.java +++ b/src/mightypork/rogue/world/tile/TileRenderer.java @@ -105,7 +105,7 @@ public abstract class TileRenderer implements Updateable { public void renderUnexploredFog(TileRenderContext context) { - if(!Config.RENDER_UFOG) return; + if (!Config.RENDER_UFOG) return; // TODO cache values, update neighbouring tiles upon "explored" flag changed. diff --git a/src/mightypork/rogue/world/tile/tiles/TileWithItems.java b/src/mightypork/rogue/world/tile/tiles/TileWithItems.java index caff12d..aacd6fb 100644 --- a/src/mightypork/rogue/world/tile/tiles/TileWithItems.java +++ b/src/mightypork/rogue/world/tile/tiles/TileWithItems.java @@ -22,7 +22,8 @@ public abstract class TileWithItems extends Tile { protected final Stack items = new Stack<>(); - public TileWithItems(TileModel model) { + public TileWithItems(TileModel model) + { super(model); } @@ -31,7 +32,7 @@ public abstract class TileWithItems extends Tile { public void renderExtra(TileRenderContext context) { if ((isExplored() || !Config.RENDER_UFOG) && !items.isEmpty()) { - itemRenderer.render(items.peek(), context); + itemRenderer.render(items, context); } }