+ rats & improvements; damaged items;
This commit is contained in:
@@ -27,7 +27,8 @@ public abstract class BaseComponent extends AbstractRectCache implements Compone
|
||||
private int disableLevel = 0;
|
||||
|
||||
|
||||
public BaseComponent() {
|
||||
public BaseComponent()
|
||||
{
|
||||
enableCaching(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import mightypork.gamecore.gui.Enableable;
|
||||
|
||||
|
||||
public abstract class InputComponent extends BaseComponent implements Enableable, ToggleableClient {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isListening()
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
// {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -25,7 +25,8 @@ import mightypork.gamecore.util.math.constraints.vect.Vect;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class Overlay extends AppSubModule implements Comparable<Overlay>, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener {
|
||||
public abstract class Overlay extends AppSubModule implements Comparable<Overlay>, 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<Overlay
|
||||
root.setVisible(visible);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void enable(boolean yes)
|
||||
{
|
||||
this.enabled = yes;
|
||||
this.enabled = yes;
|
||||
root.enable(yes);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get rendering layer
|
||||
*
|
||||
@@ -126,7 +130,7 @@ public abstract class Overlay extends AppSubModule implements Comparable<Overlay
|
||||
@Override
|
||||
public void render()
|
||||
{
|
||||
if(!isVisible()) return;
|
||||
if (!isVisible()) return;
|
||||
|
||||
for (final Renderable r : rendered) {
|
||||
r.render();
|
||||
@@ -137,7 +141,7 @@ public abstract class Overlay extends AppSubModule implements Comparable<Overlay
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
for (final Updateable u : updated) {
|
||||
u.update(delta);
|
||||
|
||||
@@ -24,7 +24,8 @@ public class FontRenderer {
|
||||
/**
|
||||
* @param font used font
|
||||
*/
|
||||
public FontRenderer(GLFont font) {
|
||||
public FontRenderer(GLFont font)
|
||||
{
|
||||
this(font, RGB.WHITE);
|
||||
}
|
||||
|
||||
@@ -33,7 +34,8 @@ public class FontRenderer {
|
||||
* @param font used font
|
||||
* @param color drawing color
|
||||
*/
|
||||
public FontRenderer(GLFont font, Color color) {
|
||||
public FontRenderer(GLFont font, Color color)
|
||||
{
|
||||
this.font = font;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ public class CachedFont implements GLFont {
|
||||
* @param filter used Gl filter
|
||||
* @param chars chars to load
|
||||
*/
|
||||
public CachedFont(java.awt.Font font, boolean antialias, FilterMode filter, String chars) {
|
||||
public CachedFont(java.awt.Font font, boolean antialias, FilterMode filter, String chars)
|
||||
{
|
||||
this(font, antialias, filter, (" " + chars).toCharArray());
|
||||
}
|
||||
|
||||
@@ -103,7 +104,8 @@ public class CachedFont implements GLFont {
|
||||
* @param filter used Gl filter
|
||||
* @param chars chars to load
|
||||
*/
|
||||
public CachedFont(java.awt.Font font, boolean antialias, FilterMode filter, char[] chars) {
|
||||
public CachedFont(java.awt.Font font, boolean antialias, FilterMode filter, char[] chars)
|
||||
{
|
||||
GLUtils.checkGLContext();
|
||||
|
||||
this.font = font;
|
||||
@@ -163,7 +165,8 @@ public class CachedFont implements GLFont {
|
||||
public int height;
|
||||
|
||||
|
||||
public LoadedGlyph(char c, BufferedImage image) {
|
||||
public LoadedGlyph(char c, BufferedImage image)
|
||||
{
|
||||
this.image = image;
|
||||
this.c = c;
|
||||
this.width = image.getWidth();
|
||||
@@ -299,7 +302,8 @@ public class CachedFont implements GLFont {
|
||||
|
||||
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
|
||||
} else {
|
||||
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
|
||||
byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder())
|
||||
.put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
|
||||
}
|
||||
|
||||
byteBuffer.flip();
|
||||
@@ -413,7 +417,7 @@ public class CachedFont implements GLFont {
|
||||
final float tymin = chtx.texPosY;
|
||||
final float draw_width = minx + chtx.width - minx;
|
||||
final float draw_height = chtx.height;
|
||||
final float drawy0 = (float) (0f - draw_height*discardTop);
|
||||
final float drawy0 = (float) (0f - draw_height * discardTop);
|
||||
|
||||
final float txmin01 = txmin / textureWidth;
|
||||
final float tymin01 = tymin / textureHeight;
|
||||
|
||||
@@ -671,11 +671,11 @@ public class Calc {
|
||||
public static int randInt(Random rand, int low, int high)
|
||||
{
|
||||
int range = high - low + 1;
|
||||
if(range < 1) range = 1;
|
||||
if (range < 1) range = 1;
|
||||
return low + rand.nextInt(range);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get ordinal version of numbers (1 = 1st, 5 = 5th etc.)
|
||||
*
|
||||
@@ -691,8 +691,8 @@ public class Calc {
|
||||
}
|
||||
return number + "th";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Format number with thousands separated by a dot.
|
||||
*
|
||||
|
||||
@@ -21,9 +21,9 @@ public class NumBoundAdapter extends NumAdapter implements PluggableNumBound {
|
||||
|
||||
|
||||
@Override
|
||||
public void setNum(NumBound rect)
|
||||
public void setNum(NumBound num)
|
||||
{
|
||||
this.backing = rect;
|
||||
this.backing = num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ public abstract class Animator extends Num implements Updateable, Pauseable {
|
||||
{
|
||||
final double target = numAnim.getEnd();
|
||||
numAnim.setTo(Calc.clamp(value, lowValue, highValue));
|
||||
numAnim.animate(target, numAnim.getDefaultDuration());
|
||||
numAnim.animate((target < value ? highValue : lowValue), target, numAnim.getDefaultDuration());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ public final class Config {
|
||||
// property keys
|
||||
private static final String PK_LAST_RUN_VERSION = "status.last_run_version";
|
||||
private static final String PK_START_IN_FS = "cfg.start_in_fullscreen";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,7 +108,10 @@ public final class Res {
|
||||
texture = textures.loadTexture("/res/img/sprites.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
grid = texture.grid(8, 8);
|
||||
textures.add("sprite.player", grid.makeSheet(0, 0, 4, 1));
|
||||
textures.add("sprite.rat", grid.makeSheet(0, 1, 4, 1));
|
||||
textures.add("sprite.rat.gray", grid.makeSheet(0, 1, 4, 1));
|
||||
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
|
||||
|
||||
@@ -30,7 +30,8 @@ public class HeartBar extends BaseComponent {
|
||||
* @param img_off
|
||||
* @param align
|
||||
*/
|
||||
public HeartBar(Num total, Num active, TxQuad img_on, TxQuad img_half, TxQuad img_off, AlignX align) {
|
||||
public HeartBar(Num total, Num active, TxQuad img_on, TxQuad img_half, TxQuad img_off, AlignX align)
|
||||
{
|
||||
super();
|
||||
this.total = total;
|
||||
this.active = active;
|
||||
@@ -60,7 +61,7 @@ public class HeartBar extends BaseComponent {
|
||||
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
{
|
||||
for (int i = 0; i < total.value(); i++) {
|
||||
index.setTo(i);
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ public class HudLayer extends ScreenLayer {
|
||||
private final ScreenGame gameScreen;
|
||||
|
||||
|
||||
public HudLayer(ScreenGame screen) {
|
||||
public HudLayer(ScreenGame screen)
|
||||
{
|
||||
super(screen);
|
||||
this.gameScreen = screen;
|
||||
|
||||
@@ -55,13 +56,13 @@ public class HudLayer extends ScreenLayer {
|
||||
|
||||
private void buildConsole()
|
||||
{
|
||||
Num rh = root.height();
|
||||
Num rw = root.width();
|
||||
Rect consoleRect = root.shrink(rw.perc(2), Num.ZERO, rh.perc(6), rh.perc(16));
|
||||
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));
|
||||
|
||||
Num perRow = consoleRect.height().div(20).max(12).min(32);
|
||||
final Num perRow = consoleRect.height().div(20).max(12).min(32);
|
||||
|
||||
WorldConsoleRenderer wcr = new WorldConsoleRenderer(perRow);
|
||||
final WorldConsoleRenderer wcr = new WorldConsoleRenderer(perRow);
|
||||
wcr.setRect(consoleRect);
|
||||
root.add(wcr);
|
||||
}
|
||||
@@ -103,7 +104,7 @@ public class HudLayer extends ScreenLayer {
|
||||
}
|
||||
});
|
||||
|
||||
levelText.setRect(hearts_box.moveY(hearts_box.height().mul(1/7D)));
|
||||
levelText.setRect(hearts_box.moveY(hearts_box.height().mul(1 / 7D)));
|
||||
root.add(levelText);
|
||||
}
|
||||
|
||||
@@ -117,7 +118,7 @@ public class HudLayer extends ScreenLayer {
|
||||
NavButton btn;
|
||||
|
||||
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.inventory")));
|
||||
btn.setAction(gameScreen.actionInv);
|
||||
btn.setAction(gameScreen.actionToggleInv);
|
||||
|
||||
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.eat")));
|
||||
btn.setAction(gameScreen.actionEat);
|
||||
|
||||
@@ -87,12 +87,15 @@ public class InvLayer extends ScreenLayer {
|
||||
}
|
||||
|
||||
|
||||
public InvLayer(final ScreenGame screen) {
|
||||
public InvLayer(final ScreenGame screen)
|
||||
{
|
||||
super(screen);
|
||||
|
||||
final Rect fg = root.shrink(root.height().perc(15));
|
||||
|
||||
final QuadPainter qp = new QuadPainter(RGB.BLACK_30, RGB.BLACK_30, RGB.BLACK_80, RGB.BLACK_80);
|
||||
// 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);
|
||||
|
||||
@@ -137,19 +140,7 @@ public class InvLayer extends ScreenLayer {
|
||||
gl.put(txp2, pos, 0, 1, 1);
|
||||
txp2.setPaddingHPerc(0, 25);
|
||||
|
||||
final Runnable leaveInv = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
|
||||
screen.setState(GScrState.WORLD);
|
||||
}
|
||||
};
|
||||
|
||||
bindKey(new KeyStroke(Keys.ESCAPE), leaveInv);
|
||||
//bindKey(new KeyStroke(Keys.I), leaveInv);
|
||||
bindKey(new KeyStroke(Keys.ESCAPE), screen.actionToggleInv);
|
||||
// TODO needs some rewrite of keys system
|
||||
|
||||
bindKey(new KeyStroke(Keys.E), new Runnable() {
|
||||
@@ -157,7 +148,7 @@ public class InvLayer extends ScreenLayer {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
if (WorldProvider.get().getPlayer().isDead()) return;
|
||||
|
||||
@@ -198,7 +189,7 @@ public class InvLayer extends ScreenLayer {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
final int selected = getSelectedSlot();
|
||||
if (selected != -1) {
|
||||
@@ -229,9 +220,9 @@ public class InvLayer extends ScreenLayer {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
int sel = getSelectedSlot();
|
||||
final int sel = getSelectedSlot();
|
||||
if (sel == -1) {
|
||||
selectSlot(0);
|
||||
return;
|
||||
@@ -246,9 +237,9 @@ public class InvLayer extends ScreenLayer {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
int sel = getSelectedSlot();
|
||||
final int sel = getSelectedSlot();
|
||||
if (sel == -1) {
|
||||
selectSlot(0);
|
||||
return;
|
||||
@@ -263,9 +254,9 @@ public class InvLayer extends ScreenLayer {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
int sel = getSelectedSlot();
|
||||
final int sel = getSelectedSlot();
|
||||
if (sel == -1) {
|
||||
selectSlot(0);
|
||||
return;
|
||||
@@ -280,9 +271,9 @@ public class InvLayer extends ScreenLayer {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if(!isEnabled()) return;
|
||||
if (!isEnabled()) return;
|
||||
|
||||
int sel = getSelectedSlot();
|
||||
final int sel = getSelectedSlot();
|
||||
if (sel == -1) {
|
||||
selectSlot(0);
|
||||
return;
|
||||
|
||||
@@ -8,8 +8,10 @@ import mightypork.gamecore.gui.components.painters.TextPainter;
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.gamecore.resources.textures.TxQuad;
|
||||
import mightypork.gamecore.util.math.Calc;
|
||||
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.caching.RectCache;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.World.PlayerFacade;
|
||||
@@ -41,8 +43,12 @@ public class InvSlot extends ClickableComponent {
|
||||
private final RectCache rbTxRect;
|
||||
private final RectCache rtTxRect;
|
||||
|
||||
private final Rect usesRect;
|
||||
private final Num hAlpha = Num.make(0.7);
|
||||
|
||||
public InvSlot(int index, InvSlot[] allSlots) {
|
||||
|
||||
public InvSlot(int index, InvSlot[] allSlots)
|
||||
{
|
||||
super();
|
||||
this.txBase = Res.txq("inv.slot.base");
|
||||
this.txSelected = Res.txq("inv.slot.selected");
|
||||
@@ -53,6 +59,8 @@ public class InvSlot extends ClickableComponent {
|
||||
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)))
|
||||
@@ -134,11 +142,26 @@ public class InvSlot extends ClickableComponent {
|
||||
rtTxP.render();
|
||||
} else if (itm.getType() == ItemType.WEAPON) {
|
||||
|
||||
int atk = itm.getAttackPoints();
|
||||
final int atk = itm.getAttackPoints();
|
||||
rtTxP.setText((atk >= 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<WorldConsole.Entry> entries = WorldProvider.get().getWorld().getConsole().getEntries();
|
||||
final Collection<WorldConsole.Entry> 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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 += "<null>";
|
||||
else
|
||||
s += itm;
|
||||
if (itm == null) s += "<null>";
|
||||
else s += itm;
|
||||
}
|
||||
s += "]";
|
||||
return s;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
|
||||
|
||||
public void tryToEatSomeFood()
|
||||
{
|
||||
List<Item> foods = new ArrayList<>();
|
||||
final List<Item> 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()<getHealthMax()) {
|
||||
if (getHealth() < getHealthMax()) {
|
||||
msgNoMoreFood();
|
||||
} else {
|
||||
msgNotHungry();
|
||||
@@ -264,7 +264,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
|
||||
|
||||
public void attack(Entity prey)
|
||||
{
|
||||
int attackPoints = getAttackStrength();
|
||||
final int attackPoints = getAttackStrength();
|
||||
|
||||
prey.receiveAttack(getPlayer().getEntity(), attackPoints);
|
||||
|
||||
@@ -272,7 +272,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
|
||||
msgKill(prey);
|
||||
}
|
||||
|
||||
Item wpn = getSelectedWeapon();
|
||||
final Item wpn = getSelectedWeapon();
|
||||
|
||||
if (wpn != null) {
|
||||
wpn.use();
|
||||
@@ -293,7 +293,7 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
|
||||
{
|
||||
if (getSelectedWeapon() != null) return;
|
||||
|
||||
List<Item> wpns = new ArrayList<>();
|
||||
final List<Item> 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.");
|
||||
|
||||
@@ -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<Entry> iter = entries.iterator(); iter.hasNext();) {
|
||||
Entry e = iter.next();
|
||||
for (final Iterator<Entry> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<String, EntityModule> 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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
+13
-23
@@ -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()
|
||||
{
|
||||
+2
-2
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
// entities - random rats
|
||||
|
||||
|
||||
for (int i = 0; i < 3 + complexity + rand.nextInt(1 + complexity); i++) {
|
||||
Entity e;
|
||||
|
||||
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);
|
||||
|
||||
// TODO tmp
|
||||
// spawn 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++) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return lvl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<Coord> nodes = new ArrayList<>();
|
||||
|
||||
private final List<Coord> occupied = new ArrayList<>();
|
||||
private final List<Entity> 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; i<tries; i++) {
|
||||
pos.x = min.x+rand.nextInt(max.x-min.x);
|
||||
pos.y = min.y+rand.nextInt(max.y-min.y);
|
||||
for (int i = 0; i < tries; i++) {
|
||||
pos.x = min.x + rand.nextInt(max.x - min.x);
|
||||
pos.y = min.y + rand.nextInt(max.y - min.y);
|
||||
if (!isIn(pos)) continue;
|
||||
|
||||
Tile t = getTile(pos);
|
||||
if(t.dropItem(item)) return true;
|
||||
final Tile t = getTile(pos);
|
||||
if (t.dropItem(item)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void dropInMap(Item item, int tries)
|
||||
|
||||
|
||||
public boolean dropInMap(Item item, int tries)
|
||||
{
|
||||
dropInArea(item, genMin, genMax, tries);
|
||||
return dropInArea(item, genMin, genMax, tries);
|
||||
}
|
||||
|
||||
|
||||
public boolean putEntityInArea(Entity entity, Coord min, Coord max, int tries)
|
||||
{
|
||||
final Coord pos = Coord.zero();
|
||||
|
||||
for (int i = 0; i < tries; i++) {
|
||||
pos.x = min.x + rand.nextInt(max.x - min.x);
|
||||
pos.y = min.y + rand.nextInt(max.y - min.y);
|
||||
if (!isIn(pos)) continue;
|
||||
|
||||
if (putEntity(entity, pos)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean putEntityInMap(Entity entity, int tries)
|
||||
{
|
||||
return putEntityInArea(entity, genMin, genMax, tries);
|
||||
}
|
||||
|
||||
|
||||
public boolean putEntity(Entity entity, Coord pos)
|
||||
{
|
||||
if (!isIn(pos)) return false;
|
||||
|
||||
if (pos.dist(enterPoint) < 5) 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package mightypork.rogue.world.gen;
|
||||
|
||||
|
||||
/**
|
||||
* Error in world generation
|
||||
*
|
||||
* @author 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package mightypork.rogue.world.gen.rooms;
|
||||
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.gamecore.util.math.algo.Coord;
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.gen.MapTheme;
|
||||
import mightypork.rogue.world.gen.ScratchMap;
|
||||
import mightypork.rogue.world.gen.WorldGenError;
|
||||
|
||||
|
||||
public class BossRoom extends SecretRoom {
|
||||
|
||||
@Override
|
||||
protected int getDoorCount(Random rand)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max)
|
||||
{
|
||||
final Entity boss = Entities.RAT_BOSS.createEntity();
|
||||
if (!map.putEntityInArea(boss, min, max, 100)) {
|
||||
|
||||
// just place it anywhere then
|
||||
if (!map.putEntityInMap(boss, 100)) {
|
||||
throw new WorldGenError("Could not place boss.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,5 @@ public class Rooms {
|
||||
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_ROOM = new BossRoom();
|
||||
}
|
||||
|
||||
@@ -43,18 +43,18 @@ public class SecretRoom extends AbstractRectRoom {
|
||||
}
|
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) {
|
||||
map.dropInArea(Items.BONE.createItem(), min, max, 50);
|
||||
map.dropInArea(Items.BONE.createItemDamaged(20), min, max, 50);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) {
|
||||
map.dropInArea(Items.ROCK.createItem(), min, max, 50);
|
||||
map.dropInArea(Items.ROCK.createItemDamaged(30), min, max, 50);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 3); i++) {
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) {
|
||||
map.dropInArea(Items.MEAT.createItem(), min, max, 50);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 3); i++) {
|
||||
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) {
|
||||
map.dropInArea(Items.CHEESE.createItem(), min, max, 50);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,14 +128,14 @@ public class MapView extends InputComponent implements DelegatingClient, MouseBu
|
||||
{
|
||||
if (!event.isOver(this)) return;
|
||||
|
||||
if(event.isButtonEvent()) {
|
||||
for (final MapInteractionPlugin p : plugins) {
|
||||
if (p.onClick(event.getPos(), event.getButton(), event.isDown())) {
|
||||
event.consume();
|
||||
break;
|
||||
if (event.isButtonEvent()) {
|
||||
for (final MapInteractionPlugin p : plugins) {
|
||||
if (p.onClick(event.getPos(), event.getButton(), event.isDown())) {
|
||||
event.consume();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.isWheelEvent()) {
|
||||
final int delta = event.getWheelDelta();
|
||||
|
||||
@@ -161,24 +161,31 @@ public abstract class Item implements IonObjBlob {
|
||||
return Log.str(getClass()) + " x " + getAmount();
|
||||
}
|
||||
|
||||
public int getRemainingUses() {
|
||||
|
||||
public int getRemainingUses()
|
||||
{
|
||||
return uses;
|
||||
}
|
||||
|
||||
|
||||
public abstract int getMaxUses();
|
||||
|
||||
public void setRemainingUses(int uses) {
|
||||
|
||||
public void setRemainingUses(int uses)
|
||||
{
|
||||
this.uses = Calc.clamp(uses, 0, getMaxUses());
|
||||
}
|
||||
|
||||
public void use() {
|
||||
if(uses>0) uses--;
|
||||
if(uses==0) consume();
|
||||
|
||||
public void use()
|
||||
{
|
||||
if (uses > 0) uses--;
|
||||
if (uses == 0) consume();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public abstract boolean isDamageable();
|
||||
|
||||
|
||||
|
||||
|
||||
public abstract String getVisualName();
|
||||
}
|
||||
|
||||
@@ -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<? extends Item> itemClass;
|
||||
|
||||
public static final Random rand = new Random();
|
||||
|
||||
public ItemModel(int id, Class<? extends Item> item) {
|
||||
|
||||
public ItemModel(int id, Class<? extends Item> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -34,12 +34,14 @@ public abstract class ItemBaseFood extends Item {
|
||||
return ItemType.FOOD;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDamageable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxUses()
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ public abstract class ItemBaseWeapon extends Item {
|
||||
return ItemType.WEAPON;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDamageable()
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ItemCheese extends ItemBaseFood {
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getVisualName()
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ItemMeat extends ItemBaseFood {
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getVisualName()
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ItemSandwich extends ItemBaseFood {
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getVisualName()
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Item> 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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ public abstract class TileWithItems extends Tile {
|
||||
protected final Stack<Item> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user