More items, bugfixes

v5stable
ondra 11 years ago
parent c67ab0cd4a
commit c13a624520
  1. BIN
      res/font/TinyUnicode.ttf
  2. BIN
      res/font/TinyUnicode2.ttf
  3. BIN
      res/font/battlenet.ttf
  4. BIN
      res/img/items.png
  5. BIN
      res/img/items.xcf
  6. 2
      src/mightypork/gamecore/eventbus/clients/BusNode.java
  7. 28
      src/mightypork/gamecore/gui/components/BaseComponent.java
  8. 24
      src/mightypork/gamecore/gui/components/Component.java
  9. 19
      src/mightypork/gamecore/gui/components/InputComponent.java
  10. 31
      src/mightypork/gamecore/gui/components/LayoutComponent.java
  11. 4
      src/mightypork/gamecore/gui/components/painters/ImagePainter.java
  12. 4
      src/mightypork/gamecore/gui/components/painters/QuadPainter.java
  13. 40
      src/mightypork/gamecore/gui/components/painters/TextPainter.java
  14. 5
      src/mightypork/gamecore/gui/screens/LayeredScreen.java
  15. 22
      src/mightypork/gamecore/gui/screens/Overlay.java
  16. 13
      src/mightypork/gamecore/resources/fonts/FontRenderer.java
  17. 26
      src/mightypork/gamecore/resources/fonts/impl/CachedFont.java
  18. 1
      src/mightypork/gamecore/resources/fonts/impl/DeferredFont.java
  19. 47
      src/mightypork/gamecore/util/math/Calc.java
  20. 2
      src/mightypork/gamecore/util/math/constraints/rect/Rect.java
  21. 39
      src/mightypork/gamecore/util/strings/StringUtils.java
  22. 6
      src/mightypork/rogue/Config.java
  23. 18
      src/mightypork/rogue/Res.java
  24. 15
      src/mightypork/rogue/screens/game/HeartBar.java
  25. 54
      src/mightypork/rogue/screens/game/HudLayer.java
  26. 52
      src/mightypork/rogue/screens/game/InvLayer.java
  27. 67
      src/mightypork/rogue/screens/game/InvSlot.java
  28. 2
      src/mightypork/rogue/screens/game/NavButton.java
  29. 29
      src/mightypork/rogue/screens/game/ScreenGame.java
  30. 62
      src/mightypork/rogue/screens/game/WorldConsoleRenderer.java
  31. 4
      src/mightypork/rogue/screens/test_bouncyboxes/BouncyBox.java
  32. 25
      src/mightypork/rogue/world/Inventory.java
  33. 27
      src/mightypork/rogue/world/PlayerControl.java
  34. 6
      src/mightypork/rogue/world/PlayerInfo.java
  35. 229
      src/mightypork/rogue/world/World.java
  36. 103
      src/mightypork/rogue/world/WorldConsole.java
  37. 2
      src/mightypork/rogue/world/WorldCreator.java
  38. 7
      src/mightypork/rogue/world/entity/Entity.java
  39. 2
      src/mightypork/rogue/world/entity/EntityRenderer.java
  40. 3
      src/mightypork/rogue/world/entity/entities/MonsterAi.java
  41. 25
      src/mightypork/rogue/world/entity/entities/PlayerEntity.java
  42. 34
      src/mightypork/rogue/world/entity/entities/RatEntity.java
  43. 1
      src/mightypork/rogue/world/entity/render/EntityRendererMobLR.java
  44. 40
      src/mightypork/rogue/world/gen/LevelGenerator.java
  45. 48
      src/mightypork/rogue/world/gen/ScratchMap.java
  46. 29
      src/mightypork/rogue/world/gen/rooms/SecretRoom.java
  47. 2
      src/mightypork/rogue/world/gui/MapView.java
  48. 19
      src/mightypork/rogue/world/gui/interaction/MIPMouse.java
  49. 34
      src/mightypork/rogue/world/item/Item.java
  50. 12
      src/mightypork/rogue/world/item/ItemModel.java
  51. 10
      src/mightypork/rogue/world/item/ItemRenderer.java
  52. 16
      src/mightypork/rogue/world/item/Items.java
  53. 11
      src/mightypork/rogue/world/item/items/ItemBaseFood.java
  54. 6
      src/mightypork/rogue/world/item/items/ItemBaseWeapon.java
  55. 38
      src/mightypork/rogue/world/item/items/food/ItemCheese.java
  56. 13
      src/mightypork/rogue/world/item/items/food/ItemMeat.java
  57. 38
      src/mightypork/rogue/world/item/items/food/ItemSandwich.java
  58. 39
      src/mightypork/rogue/world/item/items/weapons/ItemBone.java
  59. 39
      src/mightypork/rogue/world/item/items/weapons/ItemClub.java
  60. 39
      src/mightypork/rogue/world/item/items/weapons/ItemHammer.java
  61. 39
      src/mightypork/rogue/world/item/items/weapons/ItemStone.java
  62. 39
      src/mightypork/rogue/world/item/items/weapons/ItemSword.java
  63. 37
      src/mightypork/rogue/world/item/render/QuadItemRenderer.java
  64. 11
      src/mightypork/rogue/world/level/Level.java
  65. 3
      src/mightypork/rogue/world/tile/Tile.java
  66. 3
      src/mightypork/rogue/world/tile/TileRenderer.java
  67. 5
      src/mightypork/rogue/world/tile/tiles/TileBaseSecretDoor.java
  68. 34
      src/mightypork/rogue/world/tile/tiles/TileWithItems.java

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 B

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

@ -48,7 +48,7 @@ public abstract class BusNode implements BusAccess, ClientHub {
@Override
public boolean isListening()
public final boolean isListening()
{
return listening;
}

@ -1,6 +1,7 @@
package mightypork.gamecore.gui.components;
import mightypork.gamecore.gui.Enableable;
import mightypork.gamecore.gui.events.LayoutChangeEvent;
import mightypork.gamecore.gui.events.LayoutChangeListener;
import mightypork.gamecore.input.InputSystem;
@ -18,14 +19,15 @@ import mightypork.gamecore.util.math.constraints.rect.proxy.RectBoundAdapter;
*
* @author MightyPork
*/
public abstract class VisualComponent extends AbstractRectCache implements Component, LayoutChangeListener {
public abstract class BaseComponent extends AbstractRectCache implements Component, LayoutChangeListener, Enableable {
private Rect source;
private boolean visible = true;
private int disableLevel = 0;
public VisualComponent()
{
public BaseComponent() {
enableCaching(false);
}
@ -61,7 +63,7 @@ public abstract class VisualComponent extends AbstractRectCache implements Compo
@Override
public final void render()
{
if (!visible) return;
if (!isVisible()) return;
renderComponent();
}
@ -101,4 +103,22 @@ public abstract class VisualComponent extends AbstractRectCache implements Compo
public void updateLayout()
{
}
@Override
public void enable(boolean yes)
{
if (yes) {
if (disableLevel > 0) disableLevel--;
} else {
disableLevel++;
}
}
@Override
public boolean isEnabled()
{
return disableLevel == 0;
}
}

@ -1,9 +1,8 @@
package mightypork.gamecore.gui.components;
import mightypork.gamecore.gui.Enableable;
import mightypork.gamecore.gui.Hideable;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
/**
@ -11,26 +10,7 @@ import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
*
* @author MightyPork
*/
public interface Component extends Hideable, PluggableRenderable {
/**
* Set visible. When not visible, the component should not render.
*/
@Override
void setVisible(boolean yes);
@Override
boolean isVisible();
@Override
Rect getRect();
@Override
void setRect(RectBound rect);
public interface Component extends Enableable, Hideable, PluggableRenderable {
/**
* Render the component, if it is visible.

@ -5,24 +5,7 @@ import mightypork.gamecore.eventbus.clients.ToggleableClient;
import mightypork.gamecore.gui.Enableable;
public abstract class InputComponent extends VisualComponent implements Enableable, ToggleableClient {
private boolean enabled = true;
@Override
public void enable(boolean yes)
{
this.enabled = yes;
}
@Override
public boolean isEnabled()
{
return enabled && isVisible();
}
public abstract class InputComponent extends BaseComponent implements Enableable, ToggleableClient {
@Override
public boolean isListening()

@ -8,14 +8,13 @@ import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.app.AppSubModule;
import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.eventbus.clients.ClientHub;
import mightypork.gamecore.gui.Enableable;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.render.DisplaySystem;
import mightypork.gamecore.resources.audio.SoundSystem;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
public abstract class LayoutComponent extends VisualComponent implements Enableable, ClientHub, AppAccess {
public abstract class LayoutComponent extends BaseComponent implements ClientHub, AppAccess {
private boolean enabled;
@ -106,21 +105,29 @@ public abstract class LayoutComponent extends VisualComponent implements Enablea
subModule.removeChildClient(client);
}
@Override
public void enable(boolean yes)
{
subModule.setDelegating(yes);
subModule.setListening(yes);
enabled = yes;
super.enable(yes);
for(Component c : components) {
c.enable(yes);
}
}
@Override
public boolean isEnabled()
{
return enabled;
}
// @Override
// public void enable(boolean yes)
// {
// subModule.setDelegating(yes);
// subModule.setListening(yes);
// enabled = yes;
// }
//
//
// @Override
// public boolean isEnabled()
// {
// return enabled;
// }
/**

@ -1,7 +1,7 @@
package mightypork.gamecore.gui.components.painters;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.constraints.num.Num;
@ -13,7 +13,7 @@ import mightypork.gamecore.util.math.constraints.rect.Rect;
*
* @author MightyPork
*/
public class ImagePainter extends VisualComponent {
public class ImagePainter extends BaseComponent {
private final TxQuad txQuad;
private boolean aspratio = false;

@ -1,7 +1,7 @@
package mightypork.gamecore.gui.components.painters;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.util.annot.FactoryMethod;
import mightypork.gamecore.util.math.color.Color;
@ -12,7 +12,7 @@ import mightypork.gamecore.util.math.color.Color;
*
* @author MightyPork
*/
public class QuadPainter extends VisualComponent {
public class QuadPainter extends BaseComponent {
@FactoryMethod
public static QuadPainter gradH(Color colorLeft, Color colorRight)

@ -2,15 +2,18 @@ package mightypork.gamecore.gui.components.painters;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.fonts.FontRenderer;
import mightypork.gamecore.resources.fonts.GLFont;
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.vect.Vect;
import mightypork.gamecore.util.strings.StringProvider;
import mightypork.gamecore.util.strings.StringWrapper;
import mightypork.rogue.Config;
/**
@ -20,7 +23,7 @@ import mightypork.gamecore.util.strings.StringWrapper;
*
* @author MightyPork
*/
public class TextPainter extends VisualComponent {
public class TextPainter extends BaseComponent {
private final FontRenderer font;
private Color color;
@ -28,6 +31,9 @@ public class TextPainter extends VisualComponent {
private StringProvider text;
private boolean shadow;
private double yPaddingPerc = 0;
private double xPaddingPerc = 0;
private Color shadowColor = RGB.BLACK;
private Vect shadowOffset = Vect.make(2, 2);
@ -35,8 +41,7 @@ public class TextPainter extends VisualComponent {
/**
* @param font font to use
*/
public TextPainter(GLFont font)
{
public TextPainter(GLFont font) {
this(font, AlignX.LEFT, RGB.WHITE);
}
@ -49,8 +54,7 @@ public class TextPainter extends VisualComponent {
* @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));
}
@ -63,8 +67,7 @@ public class TextPainter extends VisualComponent {
* @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;
@ -77,8 +80,7 @@ public class TextPainter extends VisualComponent {
* @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);
}
@ -89,13 +91,20 @@ public class TextPainter extends VisualComponent {
if (text == null) return;
final String str = text.getString();
final Rect rect = getRect();
Num shrX = height().perc(xPaddingPerc);
Num shrY = height().perc(yPaddingPerc);
final Rect rect = getRect().shrink(shrX, shrY);
if (shadow) {
font.draw(str, rect.round(), align, shadowColor);
}
font.draw(str, rect.move(shadowOffset.neg()).round(), align, color);
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));
}
@ -147,4 +156,11 @@ public class TextPainter extends VisualComponent {
{
this.text = text;
}
public void setPaddingHPerc(double percX, double percY)
{
xPaddingPerc = percX;
yPaddingPerc = percY;
}
}

@ -16,6 +16,11 @@ import mightypork.gamecore.eventbus.clients.DelegatingClient;
*/
public abstract class LayeredScreen extends Screen {
/**
* Wrapper for delegating client, to use custom client ordering.
*
* @author MightyPork
*/
private class LayersClient implements DelegatingClient {
@SuppressWarnings({ "unchecked", "rawtypes" })

@ -7,6 +7,7 @@ import java.util.LinkedHashSet;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.app.AppSubModule;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.gui.Enableable;
import mightypork.gamecore.gui.Hideable;
import mightypork.gamecore.gui.components.layout.ConstraintLayout;
import mightypork.gamecore.gui.events.LayoutChangeListener;
@ -24,9 +25,11 @@ import mightypork.gamecore.util.math.constraints.vect.Vect;
*
* @author MightyPork
*/
public abstract class Overlay extends AppSubModule implements Comparable<Overlay>, Updateable, Renderable, KeyBinder, Hideable, LayoutChangeListener {
public abstract class Overlay extends AppSubModule implements Comparable<Overlay>, Updateable, Renderable, KeyBinder, Hideable, Enableable, LayoutChangeListener {
private boolean visible = true;
private boolean enabled = true;
private final KeyBindingPool keybindings = new KeyBindingPool();
/** Root layout, rendered and attached to the event bus. */
@ -81,8 +84,21 @@ public abstract class Overlay extends AppSubModule implements Comparable<Overlay
public void setVisible(boolean visible)
{
this.visible = visible;
root.setVisible(visible);
}
@Override
public void enable(boolean yes)
{
this.enabled = yes;
root.enable(yes);
}
@Override
public boolean isEnabled()
{
return enabled;
}
/**
* Get rendering layer
@ -110,6 +126,8 @@ public abstract class Overlay extends AppSubModule implements Comparable<Overlay
@Override
public void render()
{
if(!isVisible()) return;
for (final Renderable r : rendered) {
r.render();
}
@ -119,6 +137,8 @@ public abstract class Overlay extends AppSubModule implements Comparable<Overlay
@Override
public void update(double delta)
{
if(!isEnabled()) return;
for (final Updateable u : updated) {
u.update(delta);
}

@ -24,8 +24,7 @@ public class FontRenderer {
/**
* @param font used font
*/
public FontRenderer(GLFont font)
{
public FontRenderer(GLFont font) {
this(font, RGB.WHITE);
}
@ -34,8 +33,7 @@ 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;
}
@ -69,10 +67,7 @@ public class FontRenderer {
private double getScale(double height)
{
final double fontHeight = font.getLineHeight();
final double usefulHeight = fontHeight - fontHeight * font.getTopDiscardRatio() - fontHeight * font.getBottomDiscardRatio();
return height / usefulHeight;
return height / font.getLineHeight();
}
@ -112,7 +107,7 @@ public class FontRenderer {
final double sc = getScale(height);
Render.translate(pos.x(), pos.y() - font.getTopDiscardRatio() * sc);
Render.translate(pos.x(), pos.y());
Render.scaleXY(sc);
font.draw(text, color);

@ -90,8 +90,7 @@ 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());
}
@ -104,8 +103,7 @@ 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;
@ -165,8 +163,7 @@ 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();
@ -302,8 +299,7 @@ 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();
@ -363,7 +359,7 @@ public class CachedFont implements GLFont {
@Override
public int getLineHeight()
{
return fontHeight;
return (int) Math.round(fontHeight * ((1 - discardTop) - discardBottom));
}
@ -416,7 +412,8 @@ public class CachedFont implements GLFont {
final float txmin = chtx.texPosX;
final float tymin = chtx.texPosY;
final float draw_width = minx + chtx.width - minx;
final float draw_height = (float) (chtx.height) - (float) 0;
final float draw_height = chtx.height;
final float drawy0 = (float) (0f - draw_height*discardTop);
final float txmin01 = txmin / textureWidth;
final float tymin01 = tymin / textureHeight;
@ -424,18 +421,17 @@ public class CachedFont implements GLFont {
final float theight01 = ((chtx.texPosY + chtx.height - tymin) / textureHeight);
glTexCoord2f(txmin01, tymin01);
glVertex2f(minx, 0);
glVertex2f(minx, drawy0);
glTexCoord2f(txmin01, tymin01 + theight01);
glVertex2f(minx, 0 + draw_height);
glVertex2f(minx, drawy0 + draw_height);
glTexCoord2f(txmin01 + twidth01, tymin01 + theight01);
glVertex2f(minx + draw_width, 0 + draw_height);
glVertex2f(minx + draw_width, drawy0 + draw_height);
glTexCoord2f(txmin01 + twidth01, tymin01);
glVertex2f(minx + draw_width, 0);
glVertex2f(minx + draw_width, drawy0);
minx += chtx.width;
}
}

@ -119,6 +119,7 @@ public class DeferredFont extends DeferredResource implements GLFont {
final Font awtFont = getAwtFont(path, (float) size, style.numval);
font = new CachedFont(awtFont, antialias, filter, chars);
font.setDiscardRatio(discardTop, discardBottom);
}

@ -666,4 +666,51 @@ public class Calc {
{
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
public static int randInt(Random rand, int low, int high)
{
int range = high - low + 1;
if(range < 1) range = 1;
return low + rand.nextInt(range);
}
/**
* Get ordinal version of numbers (1 = 1st, 5 = 5th etc.)
*
* @param number number
* @return ordinal, string
*/
public static String ordinal(int number)
{
if (number % 100 < 4 || number % 100 > 13) {
if (number % 10 == 1) return number + "st";
if (number % 10 == 2) return number + "nd";
if (number % 10 == 3) return number + "rd";
}
return number + "th";
}
/**
* Format number with thousands separated by a dot.
*
* @param number number
* @return string 12.004.225
*/
public static String formatInt(long number)
{
final String num = number + "";
String out = "";
final String dot = ".";
int cnt = 1;
for (int i = num.length() - 1; i >= 0; i--) {
out = num.charAt(i) + out;
if (cnt % 3 == 0 && i > 0) out = dot + out;
cnt++;
}
return out;
}
}

@ -474,7 +474,7 @@ public abstract class Rect implements RectBound, Digestable<RectDigest> {
public Rect shrinkRight(final double shrink)
{
return growLeft(-shrink);
return growRight(-shrink);
}

@ -100,45 +100,6 @@ public class StringUtils {
}
/**
* Get ordinal version of numbers (1 = 1st, 5 = 5th etc.)
*
* @param number number
* @return ordinal, string
*/
public static String numberToOrdinal(int number)
{
if (number % 100 < 4 || number % 100 > 13) {
if (number % 10 == 1) return number + "st";
if (number % 10 == 2) return number + "nd";
if (number % 10 == 3) return number + "rd";
}
return number + "th";
}
/**
* Format number with thousands separated by a dot.
*
* @param number number
* @return string 12.004.225
*/
public static String formatInt(long number)
{
final String num = number + "";
String out = "";
final String dot = ".";
int cnt = 1;
for (int i = num.length() - 1; i >= 0; i--) {
out = num.charAt(i) + out;
if (cnt % 3 == 0 && i > 0) out = dot + out;
cnt++;
}
return out;
}
public static boolean isValidFilenameChar(char ch)
{
return isValidFilenameString(Character.toString(ch));

@ -26,6 +26,7 @@ public final class Config {
private static final String PK_START_IN_FS = "cfg.start_in_fullscreen";
/**
* Prepare config manager and load user settings
*/
@ -76,4 +77,9 @@ public final class Config {
public static boolean LOG_TO_STDOUT = true;
public static boolean SINGLE_INSTANCE = true;
/** Render dark in unknown area & skip invisible stuff */
public static boolean RENDER_UFOG = true;
/** Render a font bounding box in text painters. */
public static boolean DEBUG_FONT_RENDER = false;
}

@ -53,13 +53,18 @@ public final class Res {
//fonts.loadFont("polygon_pixel", new DeferredFont("/res/font/PolygonPixel5x7Standard.ttf", Glyphs.basic, 16));
fonts.loadFont("press_start", font = new DeferredFont("/res/font/PressStart2P.ttf", Glyphs.basic, 16));
fonts.loadFont("polygon_pixel", font = new DeferredFont("/res/font/Simpleton.ttf", Glyphs.basic, 16));
font.setDiscardRatio(5 / 16D, 2 / 16D);
fonts.loadFont("battlenet", font = new DeferredFont("/res/font/battlenet.ttf", Glyphs.basic, 16));
font.setDiscardRatio(3 / 16D, 2 / 16D);
fonts.loadFont("tinyutf", font = new DeferredFont("/res/font/TinyUnicode2.ttf", Glyphs.basic, 16));
font.setDiscardRatio(6 / 16D, 2 / 16D);
// aliases based on concrete usage
fonts.addAlias("thick", "press_start");
fonts.addAlias("thin", "polygon_pixel");
fonts.addAlias("thin", "battlenet");
fonts.addAlias("tiny", "tinyutf");
}
@ -152,6 +157,13 @@ public final class Res {
texture = textures.loadTexture("items", "/res/img/items.png", FilterMode.NEAREST, WrapMode.CLAMP);
grid = texture.grid(8, 8);
textures.add("item.meat", grid.makeQuad(0, 0));
textures.add("item.club", grid.makeQuad(1, 0));
textures.add("item.sword", grid.makeQuad(2, 0));
textures.add("item.hammer", grid.makeQuad(3, 0));
textures.add("item.stone", grid.makeQuad(4, 0));
textures.add("item.bone", grid.makeQuad(5, 0));
textures.add("item.cheese", grid.makeQuad(6, 0));
textures.add("item.sandwich", grid.makeQuad(7, 0));
}

@ -2,15 +2,16 @@ package mightypork.rogue.screens.game;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.color.pal.RGB;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.num.mutable.NumVar;
import mightypork.gamecore.util.math.constraints.rect.Rect;
public class HeartBar extends VisualComponent {
public class HeartBar extends BaseComponent {
private final TxQuad img_on;
private final TxQuad img_off;
@ -18,8 +19,8 @@ public class HeartBar extends VisualComponent {
private final Num total;
private final Num active;
NumVar index = new NumVar(0);
Rect heart;
private final NumVar index = new NumVar(0);
private final Rect heart;
/**
@ -30,8 +31,7 @@ public class HeartBar extends VisualComponent {
* @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;
@ -52,6 +52,8 @@ public class HeartBar extends VisualComponent {
case CENTER:
heart = leftEdge().moveX(w.half().add(h.mul(total.half().neg()))).growRight(h).moveX(index.mul(h));
break;
default:
heart = null; // impossible
}
}
@ -64,7 +66,6 @@ public class HeartBar extends VisualComponent {
index.setTo(i);
final double rem = active.value() - i;
Render.quadTextured(heart, (rem > 0.6 ? img_on : rem > 0.25 ? img_half : img_off));
}
}

@ -39,8 +39,7 @@ public class HudLayer extends ScreenLayer {
private final ScreenGame gameScreen;
public HudLayer(ScreenGame screen)
{
public HudLayer(ScreenGame screen) {
super(screen);
this.gameScreen = screen;
@ -49,6 +48,22 @@ public class HudLayer extends ScreenLayer {
buildDisplays();
buildMinimap();
buildConsole();
}
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));
Num perRow = consoleRect.height().div(20).max(12).min(32);
WorldConsoleRenderer wcr = new WorldConsoleRenderer(perRow);
wcr.setRect(consoleRect);
root.add(wcr);
}
@ -64,8 +79,6 @@ public class HudLayer extends ScreenLayer {
{
final Num h = root.height();
final Num displays_height = h.perc(6);
//@formatter:off
final HeartBar hearts = new HeartBar(
playerHealthTotal,
@ -76,13 +89,11 @@ public class HudLayer extends ScreenLayer {
AlignX.LEFT);
//@formatter:on
final Rect hearts_box = root.shrink(h.perc(3)).topLeft().startRect().growDown(displays_height);
final Rect hearts_box = root.shrink(h.perc(3)).topEdge().growDown(h.perc(6));
hearts.setRect(hearts_box);
root.add(hearts);
final TextPainter lvl = new TextPainter(Res.getFont("thick"), AlignX.RIGHT, RGB.WHITE, new StringProvider() {
final TextPainter levelText = new TextPainter(Res.getFont("tiny"), AlignX.RIGHT, RGB.WHITE, new StringProvider() {
@Override
public String getString()
@ -92,15 +103,8 @@ public class HudLayer extends ScreenLayer {
}
});
final Rect rr = root.shrink(h.perc(3)).topEdge().growDown(displays_height);
lvl.setRect(rr.shrink(Num.ZERO, rr.height().perc(20)));
root.add(lvl);
/*final HeartBar experience = new HeartBar(6, 2, Res.getTxQuad("xp_on"), Res.getTxQuad("xp_off"), AlignX.RIGHT);
final Rect xp_box = shrunk.topRight().startRect().growDown(displays_height);
experience.setRect(xp_box);
root.add(experience);*/
levelText.setRect(hearts_box.moveY(hearts_box.height().mul(1/7D)));
root.add(levelText);
}
@ -112,24 +116,24 @@ public class HudLayer extends ScreenLayer {
NavButton btn;
// ltr
nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.inventory")));
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.inventory")));
btn.setAction(gameScreen.actionInv);
nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.eat")));
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.eat")));
btn.setAction(gameScreen.actionEat);
nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.pause")));
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.pause")));
btn.setAction(gameScreen.actionTogglePause);
// TODO actions
nav.addRight(new NavButton(Res.txq("nav.button.fg.options")));
nav.addRight(new NavButton(Res.txq("nav.button.fg.help")));
nav.addLeft(new NavButton(Res.txq("nav.button.fg.options")));
nav.addLeft(new NavButton(Res.txq("nav.button.fg.help")));
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.map")));
nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.map")));
btn.setAction(gameScreen.actionToggleMinimap);
nav.addRight(btn = new NavButton(Res.txq("nav.button.fg.magnify")));
nav.addLeft(btn = new NavButton(Res.txq("nav.button.fg.magnify")));
btn.setAction(gameScreen.actionToggleZoom);
}

@ -30,7 +30,7 @@ public class InvLayer extends ScreenLayer {
@Override
public String getString()
{
String s = "Esc - close";
String s = "ESC-close";
final int selected = getSelectedSlot();
if (selected != -1) {
@ -39,16 +39,18 @@ public class InvLayer extends ScreenLayer {
final Item itm = pl.getInventory().getItem(selected);
if (itm != null && !itm.isEmpty()) {
s = "D - drop, " + s;
s = "D-drop," + s;
if (itm.getType() == ItemType.FOOD) {
s = "E - eat, " + s;
s = "E-eat," + s;
}
if (itm.getType() == ItemType.WEAPON) {
s = "E - equip, " + s;
s = "E-equip," + s;
}
}
}else {
s = "Click-select,"+s;
}
return s;
@ -76,18 +78,19 @@ public class InvLayer extends ScreenLayer {
final Rect fg = root.shrink(root.height().perc(15));
final QuadPainter qp = new QuadPainter(Color.rgba(0, 0, 0, 0.5));
final QuadPainter qp = new QuadPainter(RGB.BLACK_30, RGB.BLACK_30, RGB.BLACK_80, RGB.BLACK_80);
qp.setRect(root);
root.add(qp);
int pos = 0;
final GridLayout gl = new GridLayout(root, fg, 21, 1);
final GridLayout gl = new GridLayout(root, fg, 10, 1);
root.add(gl);
final TextPainter txp = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.YELLOW, "Inventory");
gl.put(txp, pos, 0, 2, 1);
pos += 3;
gl.put(txp, pos, 0, 1, 1);
txp.setPaddingHPerc(0, 5);
pos += 1;
final HorizontalFixedFlowLayout row1 = new HorizontalFixedFlowLayout(root, null, AlignX.LEFT);
row1.setElementWidth(row1.height());
@ -95,8 +98,8 @@ public class InvLayer extends ScreenLayer {
row1.setRect(cl1.axisV().grow(cl1.height().mul(2), Num.ZERO));
cl1.add(row1);
gl.put(cl1, pos, 0, 8, 1);
pos += 8;
gl.put(cl1, pos, 0, 4, 1);
pos += 4;
row1.add(slots[0] = new InvSlot(0, slots));
row1.add(slots[1] = new InvSlot(1, slots));
@ -109,25 +112,24 @@ public class InvLayer extends ScreenLayer {
final ConstraintLayout cl2 = new ConstraintLayout(root);
row2.setRect(cl2.axisV().grow(cl2.height().mul(2), Num.ZERO));
cl2.add(row2);
gl.put(cl2, pos, 0, 8, 1);
pos += 8;
gl.put(cl2, pos, 0, 4, 1);
pos += 4;
row2.add(slots[4] = new InvSlot(4, slots));
row2.add(slots[5] = new InvSlot(5, slots));
row2.add(slots[6] = new InvSlot(6, slots));
row2.add(slots[7] = new InvSlot(7, slots));
final TextPainter txp2 = new TextPainter(Res.getFont("thin"), AlignX.CENTER, RGB.WHITE, contextStrProv);
gl.put(txp2, pos + 1, 0, 1, 1);
setVisible(false);
final TextPainter txp2 = new TextPainter(Res.getFont("thick"), AlignX.CENTER, RGB.WHITE, contextStrProv);
gl.put(txp2, pos, 0, 1, 1);
txp2.setPaddingHPerc(0, 25);
bindKey(new KeyStroke(Keys.ESCAPE), new Runnable() {
@Override
public void run()
{
if (!isVisible()) return;
if(WorldProvider.get().getPlayer().isDead()) return;
screen.setState(GScrState.WORLD);
}
@ -138,7 +140,7 @@ public class InvLayer extends ScreenLayer {
@Override
public void run()
{
if (!isVisible()) return;
if(WorldProvider.get().getPlayer().isDead()) return;
final int selected = getSelectedSlot();
if (selected != -1) {
@ -148,14 +150,13 @@ public class InvLayer extends ScreenLayer {
if (itm.getType() == ItemType.FOOD) {
if (pl.eatFood(itm)) {
if (itm.consume()) {
pl.getInventory().setItem(selected, null);
}
pl.getInventory().clean();
}
}
if (itm.getType() == ItemType.WEAPON) {
pl.selectWeapon(selected);
WorldProvider.get().getWorld().msgEquipWeapon(itm);
}
}
}
@ -194,4 +195,13 @@ public class InvLayer extends ScreenLayer {
return 200;
}
@Override
public void onLayoutChanged()
{
// TODO Auto-generated method stub
super.onLayoutChanged();
System.out.println("LayoutChange @ invlayer");
}
}

@ -7,12 +7,17 @@ import mightypork.gamecore.gui.components.ClickableComponent;
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.caching.RectCache;
import mightypork.rogue.Res;
import mightypork.rogue.world.World.PlayerFacade;
import mightypork.rogue.world.PlayerInfo;
import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.item.ItemType;
/**
@ -28,16 +33,18 @@ public class InvSlot extends ClickableComponent {
protected int index;
private final RectCache itemRect;
private final RectCache uiRect;
private final InvSlot[] slots;
private final TextPainter txt;
private final TextPainter rbTxP;
private final TextPainter rtTxP;
private final RectCache txtRect;
private final RectCache rbTxRect;
private final RectCache rtTxRect;
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");
@ -45,17 +52,27 @@ public class InvSlot extends ClickableComponent {
this.index = index;
this.slots = allSlots;
this.itemRect = getRect().shrink(height().perc(16)).cached();
this.uiRect = getRect().shrink(height().perc(16)).cached();
this.itemRect = uiRect.shrink(Num.ZERO, height().perc(14), height().perc(14), Num.ZERO).cached();
//@formatter:off
this.rbTxRect = uiRect.bottomEdge()
.moveY(uiRect.height().perc(1*(30/7D)))
.growUp(uiRect.height().perc(30)).cached();
//@formatter:on
rbTxP = new TextPainter(Res.getFont("tiny"), AlignX.RIGHT, RGB.WHITE);
rbTxP.setRect(rbTxRect);
rbTxP.setShadow(RGB.BLACK_70, rbTxP.getRect().height().div(7).toVectXY());
//@formatter:off
this.txtRect = itemRect.bottomEdge()
.move(itemRect.height().perc(5).neg(), itemRect.height().perc(10).neg())
.growUp(itemRect.height().perc(35)).cached();
this.rtTxRect = uiRect.topEdge()
.growDown(uiRect.height().perc(30)).cached();
//@formatter:on
txt = new TextPainter(Res.getFont("thin"), AlignX.RIGHT, RGB.WHITE);
txt.setRect(txtRect);
txt.setShadow(RGB.BLACK_60, txt.getRect().height().div(8).toVectXY());
rtTxP = new TextPainter(Res.getFont("tiny"), AlignX.RIGHT, RGB.GREEN);
rtTxP.setRect(rtTxRect);
rtTxP.setShadow(RGB.BLACK_70, rtTxP.getRect().height().div(7).toVectXY());
setAction(new Action() {
@ -76,8 +93,10 @@ public class InvSlot extends ClickableComponent {
@Override
public void updateLayout()
{
uiRect.poll();
itemRect.poll();
txtRect.poll();
rbTxRect.poll();
rtTxRect.poll();
}
@ -100,18 +119,28 @@ public class InvSlot extends ClickableComponent {
if (itm != null && !itm.isEmpty()) {
itm.render(itemRect);
if (itm.getAmount() > 1) {
txt.setText("" + itm.getAmount());
txt.setColor(RGB.WHITE);
txt.render();
rbTxP.setText("" + itm.getAmount());
rbTxP.setColor(RGB.WHITE);
rbTxP.render();
}
if (pl.getSelectedWeapon() == index) {
txt.setText("*");
txt.setColor(RGB.YELLOW);
txt.render();
if (pl.getSelectedWeaponIndex() == index) {
rbTxP.setText("*");
rbTxP.setColor(RGB.YELLOW);
rbTxP.render();
}
if (itm.getType() == ItemType.FOOD) {
rtTxP.setText(Calc.toString(itm.getFoodPoints() / 2D));
rbTxP.setColor(RGB.GREEN);
rtTxP.render();
} else if (itm.getType() == ItemType.WEAPON) {
int atk = itm.getAttackPoints();
rtTxP.setText((atk >= 0 ? "+" : "") + atk);
rtTxP.setColor(RGB.CYAN);
rtTxP.render();
}
}
}

@ -40,6 +40,8 @@ public class NavButton extends ClickableComponent {
bg = base;
}
if(!isEnabled()) bg = base; // override effects
Render.quadTextured(this, bg);
Render.quadTextured(this, fg);
}

@ -9,6 +9,7 @@ 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.WorldProvider;
import mightypork.rogue.world.events.WorldPauseRequest;
import mightypork.rogue.world.events.WorldPauseRequest.PauseAction;
@ -26,7 +27,6 @@ public class ScreenGame extends LayeredScreen {
WORLD, INV;
}
private final Random rand = new Random();
private InvLayer invLayer;
private HudLayer hudLayer;
@ -102,12 +102,14 @@ public class ScreenGame extends LayeredScreen {
getEventBus().send(new WorldPauseRequest(PauseAction.RESUME));
invLayer.setVisible(false); // hide all extra layers
invLayer.enable(false);
worldActions.enable(true);
}
if (nstate == GScrState.INV) {
invLayer.setVisible(true);
invLayer.enable(true);
}
this.state = nstate;
@ -120,13 +122,20 @@ public class ScreenGame extends LayeredScreen {
}
public ScreenGame(AppAccess app)
{
public ScreenGame(AppAccess app) {
super(app);
addLayer(invLayer = new InvLayer(this));
invLayer.enable(false);
invLayer.setVisible(false);
addLayer(hudLayer = new HudLayer(this));
hudLayer.enable(true);
hudLayer.setVisible(true);
addLayer(worldLayer = new WorldLayer(this));
worldLayer.enable(true);
worldLayer.setVisible(true);
// TODO temporary here ↓
bindKey(new KeyStroke(Keys.L_CONTROL, Keys.N), new Runnable() {
@ -147,6 +156,10 @@ public class ScreenGame extends LayeredScreen {
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);
@ -154,6 +167,16 @@ public class ScreenGame extends LayeredScreen {
worldActions.add(actionToggleZoom);
worldActions.enable(true);
// TMP TODO remove
bindKey(new KeyStroke(Keys.X), new Runnable() {
@Override
public void run()
{
Config.RENDER_UFOG ^= true;
}
});
}

@ -0,0 +1,62 @@
package mightypork.rogue.screens.game;
import java.util.Collection;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.resources.fonts.FontRenderer;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.color.pal.RGB;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.num.mutable.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;
public class WorldConsoleRenderer extends BaseComponent {
private final Num rowHeight;
private final FontRenderer fr;
public WorldConsoleRenderer(Num rowHeight) {
this.rowHeight = rowHeight;
this.fr = new FontRenderer(Res.getFont("tiny"));
}
@Override
protected void renderComponent()
{
double rh = rowHeight.value();
Rect lowRow = bottomEdge().growUp(rowHeight);
Collection<Entry> entries = WorldProvider.get().getWorld().getConsole().getEntries();
int cnt = 0;
NumVar alph = Num.makeVar();
Color.pushAlpha(alph);
for (WorldConsole.Entry entry : entries) {
alph.setTo(entry.getAlpha());
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);
cnt++;
}
Color.popAlpha();
}
}

@ -4,7 +4,7 @@ package mightypork.rogue.screens.test_bouncyboxes;
import java.util.Random;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.gui.components.BaseComponent;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.color.pal.RGB;
@ -14,7 +14,7 @@ import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.caching.RectCache;
public class BouncyBox extends VisualComponent implements Updateable {
public class BouncyBox extends BaseComponent implements Updateable {
private final Random rand = new Random();

@ -16,14 +16,12 @@ 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
}
@ -154,6 +152,19 @@ public class Inventory implements IonObjBinary {
}
/**
* Clean empty items
*/
public void clean()
{
for (int i = 0; i < getSize(); i++) {
Item itm = getItem(i);
if (itm == null) continue;
if (itm.isEmpty()) setItem(i, null);
}
}
@Override
public String toString()
{
@ -164,8 +175,10 @@ 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;

@ -99,28 +99,31 @@ public abstract class PlayerControl {
*/
public boolean clickTile(Step side)
{
return clickTile(getPlayer().getCoord().add(side).toVect().add(0.5, 0.5));
return doClickTile(getPlayer().getCoord().add(side).toVect());
}
public boolean clickTile(Vect pos)
{
//if (pos.dist(getPlayer().getVisualPos()).value() > 8) return false; // too far
if (pos.dist(getPlayer().getVisualPos().add(0.5, 0.5)).value() < 1.5) {
return doClickTile(pos);
}
// 1st try to hit entity
final Entity prey = getLevel().getClosestEntity(pos, EntityType.MONSTER, 1);
if (prey != null) {
prey.receiveAttack(getPlayer().getEntity(), getPlayer().getAttackStrength());
return true;
}
return false;
}
//2nd try to click tile
return getLevel().getTile(Coord.fromVect(pos)).onClick();
private boolean doClickTile(Vect pos)
{
// 1st try to hit entity
final Entity prey = getLevel().getClosestEntity(pos, EntityType.MONSTER, 1);
if (prey != null) {
getPlayer().attack(prey);
return true;
}
return false;
//2nd try to click tile
return getLevel().getTile(Coord.fromVect(pos)).onClick();
}

@ -19,7 +19,7 @@ public class PlayerInfo implements IonObjBundled {
private static final int INV_SIZE = 8;
/** Constant indicating that no weapon is selected. */
private static final int NO_WEAPON = -1;
public static final int NO_WEAPON = -1;
/** Attack str with bare hands */
public static final int BARE_ATTACK = 1;
@ -106,6 +106,10 @@ public class PlayerInfo implements IonObjBundled {
public void selectWeapon(int selectedWeapon)
{
if(selectedWeapon<0||selectedWeapon>=getInventory().getSize()) {
selectedWeapon = NO_WEAPON;
}
this.selectedWeapon = selectedWeapon;
}

@ -2,15 +2,15 @@ package mightypork.rogue.world;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.*;
import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.eventbus.clients.DelegatingClient;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.gamecore.util.math.Calc;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.constraints.vect.Vect;
@ -27,7 +27,7 @@ import mightypork.rogue.world.level.Level;
*
* @author MightyPork
*/
public class World implements DelegatingClient, BusAccess, IonObjBundled, Pauseable {
public class World implements DelegatingClient, BusAccess, IonObjBundled, Pauseable, Updateable {
/**
* Convenient access to player-related methods and data
@ -36,7 +36,6 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
*/
public class PlayerFacade {
public boolean canAscend()
{
return playerInfo.getLevelNumber() > 0;
@ -52,8 +51,11 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
playerInfo.setLevelNumber(lvl_num + 1);
getLevel().forceFreeTile(getLevel().getEnterPoint());
getLevel().addEntity(playerEntity, getLevel().getEnterPoint());
getLevel().explore(getCoord());
msgEnterFloor(getLevelNumber());
}
@ -72,8 +74,11 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
playerInfo.setLevelNumber(lvl_num - 1);
getLevel().forceFreeTile(getLevel().getExitPoint());
getLevel().addEntity(playerEntity, getLevel().getExitPoint());
getLevel().explore(getCoord());
msgEnterFloor(getLevelNumber());
}
@ -176,10 +181,16 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
if (weapon == null) return PlayerInfo.BARE_ATTACK;
return Math.min(weapon.getAttackPoints(), playerInfo.BARE_ATTACK);
return PlayerInfo.BARE_ATTACK + weapon.getAttackPoints();
}
/**
* Eat food.
*
* @param itm food item
* @return if something was eaten
*/
public boolean eatFood(Item itm)
{
if (itm == null || itm.isEmpty() || itm.getType() != ItemType.FOOD) return false;
@ -187,11 +198,13 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
if (getHealth() < getHealthMax()) {
playerEntity.health.addHealth(itm.getFoodPoints());
itm.consume();
msgEat(itm);
return true;
}
return false;
}
@ -202,7 +215,13 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
}
public int getSelectedWeapon()
public Item getSelectedWeapon()
{
return playerInfo.getSelectedWeapon();
}
public int getSelectedWeaponIndex()
{
return playerInfo.getSelectedWeaponIndex();
}
@ -210,17 +229,122 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
public void tryToEatSomeFood()
{
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) {
foods.add(itm);
}
}
// sort from smallest to biggest foods
Collections.sort(foods, new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2)
{
return (o1.getFoodPoints() - o2.getFoodPoints());
}
});
for (Item itm : foods) {
if (eatFood(itm)) {
getInventory().clean();
return;
}
}
msgNoMoreFood();
}
public void attack(Entity prey)
{
int attackPoints = getAttackStrength();
prey.receiveAttack(getPlayer().getEntity(), attackPoints);
if (prey.isDead()) {
msgKill(prey);
}
Item wpn = getSelectedWeapon();
if (wpn != null) {
wpn.use();
if (wpn.isEmpty()) {
msgWeaponBreak(wpn);
getInventory().clean();
selectWeapon(-1);
pickBestWeaponIfNoneSelected();
}
}
}
private void pickBestWeaponIfNoneSelected()
{
if (getSelectedWeapon() != null) return;
List<Item> wpns = new ArrayList<>();
for (int i = 0; i < getInventory().getSize(); i++) {
final Item itm = getInventory().getItem(i);
if (itm == null || itm.isEmpty()) continue;
if (itm != null && itm.getType() == ItemType.WEAPON) {
wpns.add(itm);
}
}
final Item slice = itm.split(1);
if (!eatFood(slice)) itm.addItem(slice);
if (itm.isEmpty()) getInventory().setItem(i, null);
return;
// sort from smallest to biggest foods
Collections.sort(wpns, new Comparator<Item>() {
@Override
public int compare(Item o1, Item o2)
{
return (o2.getAttackPoints() - o1.getAttackPoints());
}
});
for (Item itm : wpns) {
for (int i = 0; i < getInventory().getSize(); i++) {
final Item itm2 = getInventory().getItem(i);
if (itm2 == itm) {
selectWeapon(i);
break;
}
}
break; // just one cycle
}
msgEquipWeapon(getSelectedWeapon());
}
public boolean addItem(Item item)
{
if (!getInventory().addItem(item)) {
msgCannotPick();
return false;
}
msgPick(item);
if (item.getType() == ItemType.WEAPON) {
if (getSelectedWeapon() != null) {
if (item.getAttackPoints() > getSelectedWeapon().getAttackPoints()) {
selectWeapon(-1); // unselect to grab the best one
}
}
pickBestWeaponIfNoneSelected();
}
return true;
}
}
// not saved stuffs
@ -229,10 +353,10 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
private BusAccess bus;
private int pauseDepth = 0;
private final ArrayList<Level> levels = new ArrayList<>();
private final PlayerInfo playerInfo = new PlayerInfo();
private final WorldConsole console = new WorldConsole();
/** World seed */
private long seed;
@ -342,6 +466,8 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
playerInfo.setLevelNumber(0);
playerInfo.setEID(playerEid);
msgEnterFloor(0);
}
@ -390,4 +516,79 @@ public class World implements DelegatingClient, BusAccess, IonObjBundled, Pausea
return player;
}
@Override
public void update(double delta)
{
if (isPaused()) return;
// update console timing
console.update(delta);
}
public WorldConsole getConsole()
{
return console;
}
public void msgPick(Item item)
{
console.addMessage("You've picked a " + item.getVisualName() + ".");
}
public void msgWeaponBreak(Item item)
{
console.addMessage("Your " + item.getVisualName() + " has broken!");
}
public void msgEquipWeapon(Item item)
{
console.addMessage("You're now wielding " + (item == null ? "NOTHING" : "a " + item.getVisualName()) + ".");
}
public void msgEat(Item item)
{
console.addMessage("You've eaten a " + item.getVisualName() + ".");
}
public void msgKill(Entity prey)
{
console.addMessage("You've killed a " + prey.getVisualName() + ".");
}
public void msgDie(Entity attacker)
{
console.addMessage("You've been defeated by a " + attacker.getVisualName() + "!");
}
public void msgDiscoverSecretDoor()
{
console.addMessage("You've discovered a secret door.");
}
public void msgNoMoreFood()
{
console.addMessage("You have no more food!");
}
public void msgCannotPick()
{
console.addMessage("Inventory is full.");
}
public void msgEnterFloor(int floor)
{
console.addMessage("~ " + Calc.ordinal(floor + 1) + " floor ~");
}
}

@ -0,0 +1,103 @@
package mightypork.rogue.world;
import java.util.*;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
public class WorldConsole implements Updateable {
private static final double DURATION = 5;
public class Entry implements Updateable {
private final String text;
private final NumAnimated fadeout;
private boolean fading = false;
private double elapsed = 0;
private Entry(String text) {
this.text = text;
this.fadeout = new NumAnimated(1, Easing.LINEAR);
this.fadeout.setDefaultDuration(0.5);
}
@Override
public void update(double delta)
{
elapsed += delta;
if (fading) {
fadeout.update(delta);
return;
}
if (elapsed > DURATION) {
fading = true;
fadeout.fadeOut();
}
}
private boolean canRemove()
{
return fading && fadeout.isFinished();
}
public double getAlpha()
{
return !fading ? 1 : fadeout.value();
}
public String getMessage()
{
return text;
}
public double getAge()
{
return elapsed;
}
}
private final Deque<Entry> entries = new LinkedList<>();
@Override
public void update(double delta)
{
for (Iterator<Entry> iter = entries.iterator(); iter.hasNext();) {
Entry e = iter.next();
e.update(delta);
if (e.canRemove()) {
iter.remove();
}
}
}
public void addMessage(String message)
{
entries.addFirst(new Entry(message));
}
public Collection<Entry> getEntries()
{
return entries;
}
public void clear() {
entries.clear();
}
}

@ -20,7 +20,7 @@ public class WorldCreator {
final World w = new World();
w.setSeed(seed);
final int count = 6;
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);

@ -14,10 +14,10 @@ import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.pathfinding.PathFinder;
import mightypork.rogue.Config;
import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.modules.EntityModuleHealth;
import mightypork.rogue.world.entity.modules.EntityModulePosition;
import mightypork.rogue.world.entity.render.EntityRenderer;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.MapRenderContext;
@ -43,6 +43,7 @@ public abstract class Entity implements IonObjBundled, Updateable {
public final EntityModulePosition pos = new EntityModulePosition(this);
public final EntityModuleHealth health = new EntityModuleHealth(this);
private double despawnDelay = 1;
protected Entity lastAttacker;
public Entity(EntityModel model, int eid)
@ -154,7 +155,7 @@ public abstract class Entity implements IonObjBundled, Updateable {
@DefaultImpl
public final void render(MapRenderContext context)
{
if (context.getTile(getCoord()).isExplored()) {
if (context.getTile(getCoord()).isExplored() || !Config.RENDER_UFOG) {
getRenderer().render(context);
}
}
@ -244,6 +245,7 @@ public abstract class Entity implements IonObjBundled, Updateable {
*/
public void receiveAttack(Entity attacker, int attackStrength)
{
this.lastAttacker = attacker;
health.receiveDamage(attackStrength);
}
@ -264,4 +266,5 @@ public abstract class Entity implements IonObjBundled, Updateable {
return despawnDelay;
}
public abstract String getVisualName();
}

@ -1,4 +1,4 @@
package mightypork.rogue.world.entity.render;
package mightypork.rogue.world.entity;
import mightypork.rogue.world.level.render.MapRenderContext;

@ -94,9 +94,7 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
{
if (entity.isDead()) return;
//System.out.println("monster ai step finished.");
if (chasing) {
//System.out.println("chasing..");
final Entity prey = getPreyEntity();
if (!isPreyValid(prey)) {
stopChasing();
@ -283,7 +281,6 @@ public class MonsterAi extends EntityModule implements EntityMoveListener {
return;
}
//System.out.println("step to prey");
entity.pos.cancelPath();
entity.pos.addSteps(preyPath);
}

@ -3,13 +3,8 @@ package mightypork.rogue.world.entity.entities;
import mightypork.gamecore.util.math.algo.Coord;
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.EntityModule;
import mightypork.rogue.world.entity.EntityPathFinder;
import mightypork.rogue.world.entity.EntityType;
import mightypork.rogue.world.entity.*;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.entity.render.EntityRenderer;
import mightypork.rogue.world.entity.render.EntityRendererMobLR;
import mightypork.rogue.world.events.PlayerKilledEvent;
import mightypork.rogue.world.events.PlayerStepEndEvent;
@ -21,8 +16,7 @@ public class PlayerEntity extends Entity {
class PlayerAi extends EntityModule implements EntityMoveListener {
public PlayerAi(Entity entity)
{
public PlayerAi(Entity entity) {
super(entity);
setDespawnDelay(2);
@ -43,7 +37,7 @@ public class PlayerEntity extends Entity {
final Tile t = getLevel().getTile(getCoord());
if (t.hasItem()) {
final Item item = t.pickItem();
if (getWorld().getPlayer().getInventory().addItem(item)) {
if (getWorld().getPlayer().addItem(item)) {
// player picked item
} else {
t.dropItem(item); // put back.
@ -85,8 +79,7 @@ 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);
@ -141,5 +134,15 @@ public class PlayerEntity extends Entity {
{
// send kill event to listeners, after the entity has despawned (disappeared)
getWorld().getEventBus().sendDelayed(new PlayerKilledEvent(), getDespawnDelay());
getWorld().msgDie(lastAttacker);
}
@Override
public String getVisualName()
{
return "Player";
}
}

@ -1,14 +1,14 @@
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.EntityRenderer;
import mightypork.rogue.world.entity.render.EntityRendererMobLR;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.item.Items;
@ -22,8 +22,7 @@ public class RatEntity extends Entity {
private EntityRenderer renderer;
public RatEntity(EntityModel model, int eid)
{
public RatEntity(EntityModel model, int eid) {
super(model, eid);
addModule("ai", ai);
@ -32,8 +31,8 @@ public class RatEntity extends Entity {
pos.setStepTime(0.5);
setDespawnDelay(1);
health.setMaxHealth(3 + rand.nextInt(3));
health.fill(); // fill health bar to max
health.setMaxHealth(5);
health.setHealth(Calc.randInt(rand, 3, 5)); // fill health bar to max
health.setHitCooldownTime(0.3);
}
@ -77,10 +76,27 @@ public class RatEntity extends Entity {
@Override
public void onCorpseRemoved()
{
// drop rat meat
final Item meat = Items.MEAT.createItem();
// drop rat stuff
if(rand.nextInt(7) == 0) {
getLevel().dropNear(getCoord(), Items.BONE.createItem());
return;
}
if(rand.nextInt(3) == 0) {
getLevel().dropNear(getCoord(), Items.MEAT.createItem());
return;
}
getLevel().dropNear(getCoord(), meat);
if(rand.nextInt(2) == 0) {
getLevel().dropNear(getCoord(), Items.CHEESE.createItem());
return;
}
}
@Override
public String getVisualName()
{
return "Gray Rat";
}
}

@ -13,6 +13,7 @@ import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.Res;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityRenderer;
import mightypork.rogue.world.level.render.MapRenderContext;

@ -10,6 +10,7 @@ import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.gen.rooms.Rooms;
import mightypork.rogue.world.gen.themes.ThemeBrick;
import mightypork.rogue.world.item.Items;
import mightypork.rogue.world.level.Level;
@ -18,6 +19,7 @@ public class LevelGenerator {
public static final MapTheme DUNGEON_THEME = new ThemeBrick();
@SuppressWarnings("fallthrough")
public static Level build(World world, long seed, int complexity, MapTheme theme, boolean lastLevel)
{
Log.f3("Generating level of complexity: " + complexity);
@ -31,16 +33,34 @@ public class LevelGenerator {
// start
map.addRoom(Rooms.ENTRANCE, true);
for (int i = 0; i < 1 + complexity / 2 + rand.nextInt((int) (1 + complexity * 0.3)); i++) {
for (int i = 0; i < 1 + complexity / 2 + rand.nextInt((int) (1 + complexity * 0.2)); i++) {
map.addRoom(Rooms.BASIC, false);
if (rand.nextInt(7) > 0) map.addRoom(Rooms.SECRET, false);
if (rand.nextInt(6) > 0) map.addRoom(Rooms.DEAD_END, false);
if (rand.nextInt(7) > 0) map.addRoom(Rooms.DEAD_END, false);
}
if (!lastLevel) map.addRoom(Rooms.EXIT, true);
map.buildCorridors();
switch(complexity) {
default:
case 3:
case 2:
if(rand.nextInt(2)==0) map.dropInMap(Items.CLUB.createItem(), 50);
case 1:
case 0:
if(rand.nextInt(2)==0) map.dropInMap(Items.ROCK.createItem(), 50);
}
if(complexity == 6) {
map.dropInMap(Items.SWORD.createItem(), 200);
}
if(complexity == 5) {
map.dropInMap(Items.HAMMER.createItem(), 100);
}
final Coord size = map.getNeededSize();
final Level lvl = new Level(size.x, size.y);
@ -49,6 +69,8 @@ public class LevelGenerator {
// 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++) {
@ -62,20 +84,6 @@ public class LevelGenerator {
}
}
// for (int i = 0; i < 4 + complexity + rand.nextInt(1 + complexity); i++) {
//
// final Item meat = Items.MEAT.createItem();
//
// for (int j = 0; j < 20; j++) {
// pos.x = rand.nextInt(lvl.getWidth());
// pos.y = rand.nextInt(lvl.getHeight());
//
// final Tile t = lvl.getTile(pos);
// if (t.dropItem(meat)) break;
// }
// }
return lvl;
}
}

@ -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.item.Item;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
@ -42,7 +43,7 @@ public class ScratchMap {
public boolean isAccessible(Coord pos)
{
if (!isIn(pos)) return false;
final Tile t = get(pos);
final Tile t = getTile(pos);
if (t.isStairs()) return false;
return t.isPotentiallyWalkable() || (t.genData.protection != TileProtectLevel.STRONG);
}
@ -51,7 +52,7 @@ public class ScratchMap {
@Override
public int getCost(Coord last, Coord pos)
{
final Tile t = get(pos);
final Tile t = getTile(pos);
switch (t.getType()) {
case NULL:
@ -173,7 +174,7 @@ public class ScratchMap {
clampBounds();
nodes.add(center);
// Log.f3("placed room: " + rd.min + " -> " + rd.max);
Log.f3("Placed room on " + Calc.ordinal(1+failed_total) + " try.");
return;
} else {
@ -222,7 +223,7 @@ public class ScratchMap {
}
public Tile get(Coord pos)
public Tile getTile(Coord pos)
{
if (!isIn(pos)) {
throw new IndexOutOfBoundsException("Tile not in map: " + pos);
@ -267,7 +268,7 @@ public class ScratchMap {
final Coord c = Coord.make(0, 0);
for (c.x = min.x; c.x <= max.x; c.x++)
for (c.y = min.y; c.y <= max.y; c.y++)
get(c).genData.protection = prot;
getTile(c).genData.protection = prot;
}
@ -357,7 +358,7 @@ public class ScratchMap {
genMax.y = Math.max(genMax.y, c.y);
clampBounds();
final Tile current = get(c);
final Tile current = getTile(c);
if (!current.isNull() && (current.isPotentiallyWalkable() || current.isStairs())) continue; // floor already, let it be
if (i == 0 && j == 0) {
@ -394,7 +395,7 @@ public class ScratchMap {
final Coord cc = pos.add(Sides.get(i));
if (!isIn(cc)) continue;
if (get(cc).isWall()) {
if (getTile(cc).isWall()) {
walls |= Sides.bit(i);
}
}
@ -409,7 +410,7 @@ public class ScratchMap {
final Coord cc = pos.add(Sides.get(i));
if (!isIn(cc)) continue;
if (get(cc).isFloor()) {
if (getTile(cc).isFloor()) {
floors |= Sides.bit(i);
}
}
@ -424,7 +425,7 @@ public class ScratchMap {
final Coord cc = pos.add(Sides.get(i));
if (!isIn(cc)) continue;
if (get(cc).isDoor()) {
if (getTile(cc).isDoor()) {
doors |= Sides.bit(i);
}
}
@ -438,7 +439,7 @@ public class ScratchMap {
for (int i = 0; i <= 7; i++) {
final Coord cc = pos.add(Sides.get(i));
if (!isIn(cc) || get(cc).isNull()) {
if (!isIn(cc) || getTile(cc).isNull()) {
nils |= Sides.bit(i);
}
}
@ -459,7 +460,7 @@ public class ScratchMap {
for (c.x = 0; c.x < width; c.x++) {
for (c.y = 0; c.y < height; c.y++) {
final Tile t = get(c);
final Tile t = getTile(c);
final boolean isNull = t.isNull();
final boolean isDoor = !isNull && t.isDoor();
@ -533,13 +534,12 @@ public class ScratchMap {
for (c.x = genMin.x, c1.x = 0; c.x <= genMax.x; c.x++, c1.x++) {
for (c.y = genMin.y, c1.y = 0; c.y <= genMax.y; c.y++, c1.y++) {
level.setTile(c1, get(c));
level.setTile(c1, getTile(c));
}
}
final Coord entrance = new Coord(enterPoint.x - genMin.x, enterPoint.y - genMin.y);
level.setEnterPoint(entrance);
// System.out.println("Entrance = " + entrance + ", original: " + enterPoint + ", minG=" + genMin + ", maxG=" + genMax);
final Coord exit = new Coord(exitPoint.x - genMin.x, exitPoint.y - genMin.y);
level.setExitPoint(exit);
@ -556,4 +556,26 @@ public class ScratchMap {
{
exitPoint.setTo(pos);
}
public boolean dropInArea(Item item, Coord min, Coord max, int tries)
{
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);
Tile t = getTile(pos);
if(t.dropItem(item)) return true;
}
return false;
}
public void dropInMap(Item item, int tries)
{
dropInArea(item, genMin, genMax, tries);
}
}

@ -3,15 +3,17 @@ package mightypork.rogue.world.gen.rooms;
import java.util.Random;
import mightypork.gamecore.util.math.Calc;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.gen.MapTheme;
import mightypork.rogue.world.gen.ScratchMap;
import mightypork.rogue.world.gen.TileProtectLevel;
import mightypork.rogue.world.item.Items;
import mightypork.rogue.world.tile.TileModel;
public class SecretRoom extends AbstractRectRoom {
@Override
protected TileModel getDoorType(MapTheme theme, Random rand)
{
@ -33,6 +35,31 @@ public class SecretRoom extends AbstractRectRoom {
}
@Override
protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max)
{
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) {
map.dropInArea(Items.SANDWICH.createItem(), min, max, 50);
}
for (int i = 0; i < Calc.randInt(rand, 0, 2); i++) {
map.dropInArea(Items.BONE.createItem(), min, max, 50);
}
for (int i = 0; i < Calc.randInt(rand, 0, 1); i++) {
map.dropInArea(Items.ROCK.createItem(), min, max, 50);
}
for (int i = 0; i < Calc.randInt(rand, 0, 3); i++) {
map.dropInArea(Items.MEAT.createItem(), min, max, 50);
}
for (int i = 0; i < Calc.randInt(rand, 0, 3); i++) {
map.dropInArea(Items.CHEESE.createItem(), min, max, 50);
}
}
@Override
protected Coord getInnerSize(Random rand)
{

@ -128,12 +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.isWheelEvent()) {
final int delta = event.getWheelDelta();

@ -16,7 +16,8 @@ import mightypork.rogue.world.tile.Tile;
public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListener, Updateable {
private static final int BTN = 0; // left
private static final int LEFT = 0; // left
private static final int RIGHT = 1; // left
public MIPMouse(MapView mapView)
@ -33,7 +34,7 @@ public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListe
final Vect pos = InputSystem.getMousePos();
if (!pos.isInside(mapView)) return;
if (InputSystem.isMouseButtonDown(BTN)) {
if (InputSystem.isMouseButtonDown(LEFT)) {
if (mouseWalk(pos)) return;
if (mapView.plc.getPlayer().isMoving() && troToNav(pos)) return;
}
@ -43,22 +44,20 @@ public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListe
@Override
public boolean onClick(Vect mouse, int button, boolean down)
{
if (isImmobile()) return false;
if (isImmobile()) {
return false;
}
final Vect pos = mapView.toWorldPos(mouse);
if (button == BTN && !down) {
if (button == LEFT && !down) {
// try to click tile
System.out.println("---");
System.out.println("Standing at: " + getPlayer().getCoord() + ", visual " + getPlayer().getVisualPos());
System.out.println("Click tile: " + pos + ", floored: " + pos.floor());
if (mapView.plc.clickTile(pos)) return true;
}
final Tile t = mapView.plc.getLevel().getTile(Coord.fromVect(pos));
if (button == 1 && !down && t.isWalkable()) {
if (button == RIGHT && !down && t.isWalkable()) {
if (troToNav(mouse)) return true;
return mouseWalk(mouse);
}
@ -122,7 +121,7 @@ public class MIPMouse extends MapInteractionPlugin implements PlayerStepEndListe
final Vect pos = InputSystem.getMousePos();
if (!pos.isInside(mapView)) return;
if (InputSystem.isMouseButtonDown(BTN)) {
if (InputSystem.isMouseButtonDown(LEFT)) {
if (mouseWalk(pos)) return;
if (mapView.plc.getPlayer().isMoving() && troToNav(pos)) return;
}

@ -2,12 +2,14 @@ package mightypork.rogue.world.item;
import java.io.IOException;
import java.util.Random;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonObjBlob;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.gamecore.util.math.Calc;
import mightypork.gamecore.util.math.constraints.rect.Rect;
@ -16,6 +18,9 @@ public abstract class Item implements IonObjBlob {
private final ItemModel model;
private ItemRenderer renderer;
private int amount = 1;
private int uses = 1;
protected static final Random rand = new Random();
public Item(ItemModel model)
@ -68,11 +73,11 @@ public abstract class Item implements IonObjBlob {
public boolean canStackWith(Item other)
{
return (getModel().id == other.getModel().id) && isStackable();
return (getModel().id == other.getModel().id);
}
public abstract boolean isStackable();
protected abstract boolean isStackable();
/**
@ -113,13 +118,11 @@ public abstract class Item implements IonObjBlob {
*
* @return true if the item is fully consumed and should be removed.
*/
public boolean consume()
public void consume()
{
if (isEmpty()) throw new RuntimeException("Item is empty, cannot consume.");
amount--;
return isEmpty();
}
@ -157,4 +160,25 @@ public abstract class Item implements IonObjBlob {
{
return Log.str(getClass()) + " x " + getAmount();
}
public int getRemainingUses() {
return uses;
}
public abstract int getMaxUses();
public void setRemainingUses(int uses) {
this.uses = Calc.clamp(uses, 0, getMaxUses());
}
public void use() {
if(uses>0) uses--;
if(uses==0) consume();
}
public abstract boolean isDamageable();
public abstract String getVisualName();
}

@ -19,8 +19,7 @@ public final class ItemModel {
public final Class<? extends Item> itemClass;
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;
@ -30,10 +29,15 @@ public final class ItemModel {
/**
* @return new item instance of this type
*/
public <T extends Item> T createItem()
public Item createItem()
{
try {
return (T) itemClass.getConstructor(ItemModel.class).newInstance(this);
Item itm = itemClass.getConstructor(ItemModel.class).newInstance(this);
itm.setRemainingUses(itm.getMaxUses());
return itm;
} catch (final Exception e) {
throw new RuntimeException("Could not instantiate an item.", e);
}

@ -6,6 +6,16 @@ import mightypork.gamecore.util.math.constraints.rect.Rect;
public abstract class ItemRenderer {
protected final Item item;
public ItemRenderer(Item item) {
this.item = item;
}
public abstract void render(Rect r);
}

@ -6,7 +6,14 @@ import java.util.Collection;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.world.item.items.ItemMeat;
import mightypork.rogue.world.item.items.food.ItemCheese;
import mightypork.rogue.world.item.items.food.ItemMeat;
import mightypork.rogue.world.item.items.food.ItemSandwich;
import mightypork.rogue.world.item.items.weapons.ItemBone;
import mightypork.rogue.world.item.items.weapons.ItemClub;
import mightypork.rogue.world.item.items.weapons.ItemHammer;
import mightypork.rogue.world.item.items.weapons.ItemStone;
import mightypork.rogue.world.item.items.weapons.ItemSword;
/**
@ -19,6 +26,13 @@ public final class Items {
private static final ItemModel[] items = new ItemModel[256];
public static final ItemModel MEAT = new ItemModel(1, ItemMeat.class);
public static final ItemModel CHEESE = new ItemModel(2, ItemCheese.class);
public static final ItemModel BONE = new ItemModel(3, ItemBone.class);
public static final ItemModel SANDWICH = new ItemModel(4, ItemSandwich.class);
public static final ItemModel CLUB = new ItemModel(5, ItemClub.class);
public static final ItemModel HAMMER = new ItemModel(6, ItemHammer.class);
public static final ItemModel SWORD = new ItemModel(7, ItemSword.class);
public static final ItemModel ROCK = new ItemModel(8, ItemStone.class);
public static void register(int id, ItemModel model)

@ -34,4 +34,15 @@ public abstract class ItemBaseFood extends Item {
return ItemType.FOOD;
}
@Override
public boolean isDamageable()
{
return false;
}
@Override
public int getMaxUses()
{
return 1;
}
}

@ -34,4 +34,10 @@ public abstract class ItemBaseWeapon extends Item {
return ItemType.WEAPON;
}
@Override
public boolean isDamageable()
{
return true;
}
}

@ -0,0 +1,38 @@
package mightypork.rogue.world.item.items.food;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseFood;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemCheese extends ItemBaseFood {
public ItemCheese(ItemModel model)
{
super(model);
}
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(this, Res.txq("item.cheese"));
}
@Override
public int getFoodPoints()
{
return 2;
}
@Override
public String getVisualName()
{
return "Cheese";
}
}

@ -1,9 +1,10 @@
package mightypork.rogue.world.item.items;
package mightypork.rogue.world.item.items.food;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseFood;
import mightypork.rogue.world.item.render.QuadItemRenderer;
@ -18,14 +19,20 @@ public class ItemMeat extends ItemBaseFood {
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(Res.txq("item.meat"));
return new QuadItemRenderer(this, Res.txq("item.meat"));
}
@Override
public int getFoodPoints()
{
return 2;
return 3;
}
@Override
public String getVisualName()
{
return "Chunk Of Meat";
}
}

@ -0,0 +1,38 @@
package mightypork.rogue.world.item.items.food;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseFood;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemSandwich extends ItemBaseFood {
public ItemSandwich(ItemModel model)
{
super(model);
}
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(this, Res.txq("item.sandwich"));
}
@Override
public int getFoodPoints()
{
return 6;
}
@Override
public String getVisualName()
{
return "Sandwich";
}
}

@ -0,0 +1,39 @@
package mightypork.rogue.world.item.items.weapons;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseWeapon;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemBone extends ItemBaseWeapon {
public ItemBone(ItemModel model) {
super(model);
}
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(this, Res.txq("item.bone"));
}
@Override
public int getAttackPoints()
{
return 1;
}
@Override
public int getMaxUses()
{
return 15;
}
@Override
public String getVisualName()
{
return "Bone";
}
}

@ -0,0 +1,39 @@
package mightypork.rogue.world.item.items.weapons;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseWeapon;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemClub extends ItemBaseWeapon {
public ItemClub(ItemModel model) {
super(model);
}
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(this, Res.txq("item.club"));
}
@Override
public int getAttackPoints()
{
return 3;
}
@Override
public int getMaxUses()
{
return 25;
}
@Override
public String getVisualName()
{
return "Wooden Club";
}
}

@ -0,0 +1,39 @@
package mightypork.rogue.world.item.items.weapons;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseWeapon;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemHammer extends ItemBaseWeapon {
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";
}
}

@ -0,0 +1,39 @@
package mightypork.rogue.world.item.items.weapons;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseWeapon;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemStone extends ItemBaseWeapon {
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";
}
}

@ -0,0 +1,39 @@
package mightypork.rogue.world.item.items.weapons;
import mightypork.rogue.Res;
import mightypork.rogue.world.item.ItemModel;
import mightypork.rogue.world.item.ItemRenderer;
import mightypork.rogue.world.item.items.ItemBaseWeapon;
import mightypork.rogue.world.item.render.QuadItemRenderer;
public class ItemSword extends ItemBaseWeapon {
public ItemSword(ItemModel model) {
super(model);
}
@Override
protected ItemRenderer makeRenderer()
{
return new QuadItemRenderer(this, Res.txq("item.sword"));
}
@Override
public int getAttackPoints()
{
return 6;
}
@Override
public int getMaxUses()
{
return 100;
}
@Override
public String getVisualName()
{
return "Wooden Club";
}
}

@ -3,8 +3,12 @@ package mightypork.rogue.world.item.render;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.resources.textures.TxSheet;
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;
@ -12,16 +16,14 @@ public class QuadItemRenderer extends ItemRenderer {
private final TxQuad txq;
public QuadItemRenderer(TxQuad txq)
{
this.txq = 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(TxSheet txs)
{
this.txq = txs.getQuad(0);
public QuadItemRenderer(Item item, TxQuad txq) {
super(item);
this.txq = txq;
}
@ -29,6 +31,23 @@ 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,13 +86,11 @@ 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();
}
@ -589,6 +587,11 @@ public class Level implements BusAccess, Updateable, DelegatingClient, Toggleabl
}
}
if (!getTile(pos).isWalkable()) {
// this should never happen.
setTile(pos, Tiles.BRICK_FLOOR.createTile());
}
}

@ -12,6 +12,7 @@ import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonObjBlob;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.gamecore.util.math.color.Color;
import mightypork.rogue.Config;
import mightypork.rogue.world.World;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.Level;
@ -56,7 +57,7 @@ public abstract class Tile implements BusAccess, IonObjBlob {
@DefaultImpl
public void renderTile(TileRenderContext context)
{
if (!isExplored()) return;
if (!isExplored() && Config.RENDER_UFOG) return;
initRenderer();

@ -6,6 +6,7 @@ import mightypork.gamecore.render.Render;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.Config;
import mightypork.rogue.Res;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.rogue.world.tile.render.NullTileRenderer;
@ -104,6 +105,8 @@ public abstract class TileRenderer implements Updateable {
public void renderUnexploredFog(TileRenderContext context)
{
if(!Config.RENDER_UFOG) return;
// TODO cache values, update neighbouring tiles upon "explored" flag changed.
byte ufog = 0;

@ -30,7 +30,10 @@ public abstract class TileBaseSecretDoor extends TileBaseDoor {
if (clicks > 0) clicks--;
if (clicks == 0) locked = false;
if (clicks == 0) {
locked = false;
getWorld().msgDiscoverSecretDoor();
}
return true;
}

@ -6,6 +6,7 @@ import java.util.Stack;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.Config;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.item.Items;
import mightypork.rogue.world.level.render.TileRenderContext;
@ -21,8 +22,7 @@ public abstract class TileWithItems extends Tile {
protected final Stack<Item> items = new Stack<>();
public TileWithItems(TileModel model)
{
public TileWithItems(TileModel model) {
super(model);
}
@ -30,7 +30,7 @@ public abstract class TileWithItems extends Tile {
@Override
public void renderExtra(TileRenderContext context)
{
if (isExplored() && !items.isEmpty()) {
if ((isExplored() || !Config.RENDER_UFOG) && !items.isEmpty()) {
itemRenderer.render(items.peek(), context);
}
}
@ -98,18 +98,18 @@ public abstract class TileWithItems extends Tile {
}
@Override
public boolean onClick()
{
if (hasItem()) {
final Item item = pickItem();
if (getWorld().getPlayer().getInventory().addItem(item)) {
// player picked item
} else {
dropItem(item); // put back.
}
return true;
}
return false;
}
// @Override
// public boolean onClick()
// {
// if (hasItem()) {
// final Item item = pickItem();
// if (getWorld().getPlayer().addItem(item)) {
// // player picked item
// } else {
// dropItem(item); // put back.
// }
// return true;
// }
// return false;
// }
}

Loading…
Cancel
Save