All merged into gamecore and reorganized

This commit is contained in:
ondra
2014-04-30 20:37:09 +02:00
parent d2276bee9c
commit a8ed021156
308 changed files with 2250 additions and 1450 deletions
+69 -62
View File
@@ -4,18 +4,22 @@ package mightypork.rogue;
import java.io.File;
import java.util.Locale;
import mightypork.gamecore.control.BaseApp;
import mightypork.gamecore.control.GameLoop;
import mightypork.gamecore.app.BaseApp;
import mightypork.gamecore.app.MainLoop;
import mightypork.gamecore.eventbus.BusEvent;
import mightypork.gamecore.eventbus.EventBus;
import mightypork.gamecore.gui.screens.CrossfadeRequest;
import mightypork.gamecore.gui.screens.ScreenRegistry;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.loading.AsyncResourceLoader;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.logging.writers.LogWriter;
import mightypork.gamecore.render.DisplaySystem;
import mightypork.gamecore.resources.loading.AsyncResourceLoader;
import mightypork.gamecore.util.ion.Ion;
import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.rogue.screens.CrossfadeOverlay;
import mightypork.rogue.screens.CrossfadeRequest;
import mightypork.rogue.screens.FpsOverlay;
import mightypork.rogue.screens.gamescreen.ScreenGame;
import mightypork.rogue.screens.main_menu.ScreenMainMenu;
@@ -25,11 +29,6 @@ import mightypork.rogue.screens.test_render.ScreenTestRender;
import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.Level;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.EventBus;
import mightypork.util.files.ion.Ion;
import mightypork.util.logging.Log;
import mightypork.util.logging.writers.LogWriter;
/**
@@ -45,11 +44,25 @@ public final class App extends BaseApp {
* @param args
*/
public static void main(String[] args)
{
(new App()).start();
}
@Override
protected File getLockFile()
{
return Paths.LOCK;
}
@Override
protected void preInit()
{
Config.init();
Config.save();
(new App()).start();
WorldProvider.init(this);
}
@@ -62,6 +75,23 @@ public final class App extends BaseApp {
}
@Override
protected void registerIonizables()
{
super.registerIonizables();
Ion.registerType(Item.ION_MARK, Item.class);
Ion.registerType(Level.ION_MARK, Level.class);
}
@Override
protected void initBus(EventBus bus)
{
bus.detailedLogging = true;
}
@Override
protected void initDisplay(DisplaySystem display)
{
@@ -70,32 +100,6 @@ public final class App extends BaseApp {
}
@Override
protected void initScreens(ScreenRegistry screens)
{
// world provider instance is referenced by screens
WorldProvider.init(this);
screens.addScreen(new ScreenTestBouncy(this));
screens.addScreen(new ScreenTestCat(this));
screens.addScreen(new ScreenTestRender(this));
screens.addScreen(new ScreenMainMenu(this));
screens.addScreen(new ScreenGame(this));
screens.addOverlay(new FpsOverlay(this));
screens.addOverlay(new CrossfadeOverlay(this));
screens.showScreen("game_screen");//main_menu
}
@Override
protected GameLoop createLoop()
{
return new MainLoop(this);
}
@Override
protected void initResources()
{
@@ -107,32 +111,17 @@ public final class App extends BaseApp {
@Override
protected void preInit()
protected void initScreens(ScreenRegistry screens)
{
Ion.registerBinary(Item.ION_MARK, Item.class);
Ion.registerBinary(Level.ION_MARK, Level.class);
}
@Override
protected void postInit()
{
// TODO tmp
WorldProvider.get().createWorld(42);
}
@Override
protected File getLockFile()
{
return Paths.LOCK;
}
@Override
protected void initBus(EventBus bus)
{
bus.detailedLogging = true;
super.initScreens(screens);
screens.addScreen(new ScreenTestBouncy(this));
screens.addScreen(new ScreenTestCat(this));
screens.addScreen(new ScreenTestRender(this));
screens.addScreen(new ScreenMainMenu(this));
screens.addScreen(new ScreenGame(this));
screens.addOverlay(new FpsOverlay(this));
}
@@ -144,6 +133,8 @@ public final class App extends BaseApp {
bindEventToKey(new ActionRequest(RequestType.SCREENSHOT), Keys.F2);
bindEventToKey(new CrossfadeRequest(null), Keys.L_CONTROL, Keys.Q);
bindEventToKey(new CrossfadeRequest("main_menu"), Keys.L_CONTROL, Keys.M);
// TODO tmp
getInput().bindKey(new KeyStroke(Keys.N), new Runnable() {
@Override
@@ -167,4 +158,20 @@ public final class App extends BaseApp {
});
}
@Override
protected MainLoop createMainLoop()
{
return new GameLoop(this);
}
@Override
protected void postInit()
{
// TODO tmp
WorldProvider.get().createWorld(42);
getEventBus().send(new CrossfadeRequest("game_screen"));
}
}
+2 -2
View File
@@ -1,8 +1,8 @@
package mightypork.rogue;
import mightypork.util.files.config.PropertyManager;
import mightypork.util.logging.Log;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.files.config.PropertyManager;
/**
+2 -2
View File
@@ -18,6 +18,6 @@ public final class Const {
public static final int FPS_RENDER = 100; // max
// INITIAL WINDOW SIZE
public static final int WINDOW_W = 640;
public static final int WINDOW_H = 480;
public static final int WINDOW_W = 800;
public static final int WINDOW_H = 600;
}
@@ -7,19 +7,19 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import mightypork.gamecore.control.BaseApp;
import mightypork.gamecore.control.GameLoop;
import mightypork.gamecore.app.BaseApp;
import mightypork.gamecore.app.MainLoop;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.render.Screenshot;
import mightypork.gamecore.util.Utils;
import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.rogue.util.Utils;
import mightypork.util.control.Action;
import mightypork.util.logging.Log;
public final class MainLoop extends GameLoop implements ActionRequest.Listener {
public final class GameLoop extends MainLoop implements ActionRequest.Listener {
public MainLoop(BaseApp app)
public GameLoop(BaseApp app)
{
super(app);
}
+9 -9
View File
@@ -1,15 +1,15 @@
package mightypork.rogue;
import mightypork.gamecore.audio.SoundBank;
import mightypork.gamecore.audio.players.EffectPlayer;
import mightypork.gamecore.audio.players.LoopPlayer;
import mightypork.gamecore.control.BaseApp;
import mightypork.gamecore.render.fonts.FontBank;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.gamecore.render.fonts.Glyphs;
import mightypork.gamecore.render.fonts.impl.DeferredFont;
import mightypork.gamecore.render.textures.*;
import mightypork.gamecore.app.BaseApp;
import mightypork.gamecore.resources.audio.SoundBank;
import mightypork.gamecore.resources.audio.players.EffectPlayer;
import mightypork.gamecore.resources.audio.players.LoopPlayer;
import mightypork.gamecore.resources.fonts.FontBank;
import mightypork.gamecore.resources.fonts.GLFont;
import mightypork.gamecore.resources.fonts.Glyphs;
import mightypork.gamecore.resources.fonts.impl.DeferredFont;
import mightypork.gamecore.resources.textures.*;
/**
@@ -1,8 +1,8 @@
package mightypork.rogue.events;
import mightypork.util.control.eventbus.BusEvent;
import mightypork.util.control.eventbus.event_flags.SingleReceiverEvent;
import mightypork.gamecore.eventbus.BusEvent;
import mightypork.gamecore.eventbus.event_flags.SingleReceiverEvent;
/**
@@ -1,83 +0,0 @@
package mightypork.rogue.screens;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.control.events.requests.ScreenRequestEvent;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.screens.Overlay;
import mightypork.rogue.events.ActionRequest;
import mightypork.rogue.events.ActionRequest.RequestType;
import mightypork.util.math.Easing;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.num.mutable.NumAnimated;
import mightypork.util.timing.TimedTask;
public class CrossfadeOverlay extends Overlay implements CrossfadeRequest.Listener {
private static final double T_IN = 0.5;
private static final double T_OUT = 0.7;
NumAnimated level = new NumAnimated(0);
Color color = Color.dark(level);
String requestedScreenName;
TimedTask tt = new TimedTask() {
@Override
public void run()
{
if (requestedScreenName == null) {
getEventBus().send(new ActionRequest(RequestType.SHUTDOWN));
} else {
getEventBus().send(new ScreenRequestEvent(requestedScreenName));
}
}
};
TimedTask tt2 = new TimedTask() {
@Override
public void run()
{
level.setEasing(Easing.SINE_OUT);
level.fadeOut(T_OUT);
}
};
public CrossfadeOverlay(AppAccess app)
{
super(app);
final QuadPainter qp = new QuadPainter(color);
qp.setRect(root);
root.add(qp);
updated.add(level);
updated.add(tt);
updated.add(tt2);
}
@Override
public int getZIndex()
{
return Integer.MAX_VALUE - 1; // let FPS go on top
}
@Override
public void goToScreen(String screen)
{
tt.start(T_IN);
tt2.start(T_IN);
level.setEasing(Easing.SINE_IN);
level.fadeIn(T_IN);
requestedScreenName = screen;
}
}
@@ -1,36 +0,0 @@
package mightypork.rogue.screens;
import mightypork.util.control.eventbus.BusEvent;
/**
* @author MightyPork
*/
public class CrossfadeRequest extends BusEvent<CrossfadeRequest.Listener> {
private final String screen;
/**
* @param screen screen key to show. Null = exit the app.
*/
public CrossfadeRequest(String screen)
{
super();
this.screen = screen;
}
public interface Listener {
void goToScreen(String screen);
}
@Override
public void handleBy(Listener handler)
{
handler.goToScreen(screen);
}
}
+8 -8
View File
@@ -1,20 +1,20 @@
package mightypork.rogue.screens;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.Overlay;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.gamecore.resources.fonts.GLFont;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.strings.StringProvider;
import mightypork.rogue.Res;
import mightypork.util.control.Action;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.rect.proxy.RectBound;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.string.StringProvider;
public class FpsOverlay extends Overlay {
@@ -4,10 +4,10 @@ package mightypork.rogue.screens.gamescreen;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.VisualComponent;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxQuad;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.num.mutable.NumVar;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.gamecore.resources.textures.TxQuad;
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 {
@@ -8,10 +8,10 @@ import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.Res;
import mightypork.rogue.world.gui.Minimap;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.rect.Rect;
public class HudLayer extends ScreenLayer {
@@ -1,19 +1,19 @@
package mightypork.rogue.screens.gamescreen;
import mightypork.gamecore.control.events.input.MouseMotionEvent;
import mightypork.gamecore.control.events.input.MouseMotionListener;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.gui.components.ClickableComponent;
import mightypork.gamecore.input.events.MouseMotionEvent;
import mightypork.gamecore.input.events.MouseMotionListener;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxQuad;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.caching.RectCache;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.Res;
import mightypork.util.math.Easing;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.num.mutable.NumAnimated;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.caching.RectCache;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.timing.Updateable;
public class NavItemSlot extends ClickableComponent implements MouseMotionListener, Updateable {
@@ -1,7 +1,7 @@
package mightypork.rogue.screens.gamescreen;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.rogue.world.WorldProvider;
@@ -3,10 +3,10 @@ package mightypork.rogue.screens.gamescreen;
import mightypork.gamecore.gui.screens.Screen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.rogue.world.gui.MapView;
import mightypork.rogue.world.gui.interaction.MIPClickPathfWalk;
import mightypork.rogue.world.gui.interaction.MIPKeyWalk;
import mightypork.util.math.constraints.num.Num;
public class WorldLayer extends ScreenLayer {
@@ -4,12 +4,12 @@ package mightypork.rogue.screens.main_menu;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.ClickableComponent;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.render.fonts.GLFont;
import mightypork.gamecore.resources.fonts.GLFont;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.math.constraints.vect.mutable.VectVar;
import mightypork.rogue.Res;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.math.constraints.vect.mutable.VectVar;
class MenuButton extends ClickableComponent {
@@ -1,19 +1,19 @@
package mightypork.rogue.screens.main_menu;
import mightypork.gamecore.gui.Action;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.layout.GridLayout;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.components.painters.TextPainter;
import mightypork.gamecore.gui.screens.BaseScreen;
import mightypork.gamecore.gui.screens.CrossfadeRequest;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.util.math.color.pal.COMMODORE;
import mightypork.gamecore.util.math.color.pal.PAL16;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.Res;
import mightypork.rogue.screens.CrossfadeRequest;
import mightypork.util.control.Action;
import mightypork.util.math.color.COMMODORE;
import mightypork.util.math.color.PAL16;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.rect.Rect;
class MenuLayer extends ScreenLayer {
@@ -1,7 +1,7 @@
package mightypork.rogue.screens.main_menu;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen;
@@ -3,15 +3,15 @@ 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.render.Render;
import mightypork.util.math.Easing;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.num.mutable.NumAnimated;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.caching.RectCache;
import mightypork.util.timing.Updateable;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.caching.RectCache;
public class BouncyBox extends VisualComponent implements Updateable {
@@ -11,10 +11,10 @@ import mightypork.gamecore.gui.screens.BaseScreen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.Res;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.vect.Vect;
public class LayerBouncyBoxes extends ScreenLayer {
@@ -1,7 +1,7 @@
package mightypork.rogue.screens.test_bouncyboxes;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen;
@@ -4,7 +4,7 @@ package mightypork.rogue.screens.test_cat_sound;
import mightypork.gamecore.gui.components.painters.QuadPainter;
import mightypork.gamecore.gui.screens.BaseScreen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.util.math.color.Color;
import mightypork.gamecore.util.math.color.Color;
public class LayerColor extends ScreenLayer {
@@ -3,8 +3,6 @@ package mightypork.rogue.screens.test_cat_sound;
import java.util.Random;
import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.input.MouseButtonListener;
import mightypork.gamecore.gui.AlignX;
import mightypork.gamecore.gui.components.painters.ImagePainter;
import mightypork.gamecore.gui.components.painters.QuadPainter;
@@ -13,13 +11,15 @@ import mightypork.gamecore.gui.screens.BaseScreen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseButtonListener;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.math.constraints.vect.mutable.VectAnimated;
import mightypork.rogue.Res;
import mightypork.util.math.Easing;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.num.mutable.NumAnimated;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.math.constraints.vect.mutable.VectAnimated;
public class LayerFlyingCat extends ScreenLayer implements MouseButtonListener {
@@ -1,7 +1,7 @@
package mightypork.rogue.screens.test_cat_sound;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen;
import mightypork.gamecore.input.KeyStroke;
import mightypork.gamecore.input.Keys;
@@ -4,8 +4,8 @@ package mightypork.rogue.screens.test_render;
import mightypork.gamecore.gui.screens.BaseScreen;
import mightypork.gamecore.gui.screens.ScreenLayer;
import mightypork.gamecore.render.Render;
import mightypork.util.math.color.Color;
import mightypork.util.math.constraints.rect.proxy.RectBound;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
public class LayerTestGradient extends ScreenLayer {
@@ -1,7 +1,7 @@
package mightypork.rogue.screens.test_render;
import mightypork.gamecore.control.AppAccess;
import mightypork.gamecore.app.AppAccess;
import mightypork.gamecore.gui.screens.LayeredScreen;
-17
View File
@@ -1,17 +0,0 @@
package mightypork.rogue.util;
/**
* Utils class
*
* @author MightyPork
*/
public final class Utils {
public static Thread runAsThread(Runnable r)
{
final Thread t = new Thread(r);
t.start();
return t;
}
}
-150
View File
@@ -1,150 +0,0 @@
package mightypork.rogue.world;
import java.io.IOException;
import mightypork.util.annotations.FactoryMethod;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonBundled;
import mightypork.util.math.Calc;
/**
* Coordinate
*
* @author MightyPork
*/
public class Coord implements IonBundled {
public int x;
public int y;
@FactoryMethod
public static Coord make(int x, int y)
{
return new Coord(x, y);
}
@FactoryMethod
public static Coord make(Coord other)
{
return new Coord(other);
}
@FactoryMethod
public static Coord zero()
{
return make(0, 0);
}
public Coord(int x, int y)
{
super();
this.x = x;
this.y = y;
}
public Coord(Coord other)
{
this.x = other.x;
this.y = other.y;
}
public Coord add(int addX, int addY)
{
return new Coord(x + addX, y + addY);
}
public Coord add(Coord other)
{
return add(other.x, other.y);
}
public Coord copy()
{
return make(this);
}
public void setTo(int x, int y)
{
this.x = x;
this.y = y;
}
public void setTo(Coord pos)
{
setTo(pos.x, pos.y);
}
/**
* Check if coord is in a range (inclusive)
*/
public boolean isInRange(int x0, int y0, int x1, int y1)
{
return !(x < x0 || x > x1 || y < y0 || y > y1);
}
@Override
public void load(IonBundle bundle) throws IOException
{
x = bundle.get("x", 0);
y = bundle.get("y", 0);
}
@Override
public void save(IonBundle bundle) throws IOException
{
bundle.put("x", x);
bundle.put("y", y);
}
@Override
public String toString()
{
return "Coord(" + x + "," + y + ")";
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof Coord)) return false;
final Coord other = (Coord) obj;
if (x != other.x) return false;
if (y != other.y) return false;
return true;
}
public double dist(Coord coord)
{
return Calc.dist(x, y, coord.x, coord.y);
}
}
@@ -4,8 +4,9 @@ package mightypork.rogue.world;
import java.util.HashSet;
import java.util.Set;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.PathStep;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.level.Level;
@@ -48,28 +49,28 @@ public abstract class PlayerControl {
public void goNorth()
{
getPlayerEntity().pos.cancelPath();
getPlayerEntity().pos.addStep(PathStep.NORTH);
getPlayerEntity().pos.addStep(Step.NORTH);
}
public void goSouth()
{
getPlayerEntity().pos.cancelPath();
getPlayerEntity().pos.addStep(PathStep.SOUTH);
getPlayerEntity().pos.addStep(Step.SOUTH);
}
public void goEast()
{
getPlayerEntity().pos.cancelPath();
getPlayerEntity().pos.addStep(PathStep.EAST);
getPlayerEntity().pos.addStep(Step.EAST);
}
public void goWest()
{
getPlayerEntity().pos.cancelPath();
getPlayerEntity().pos.addStep(PathStep.WEST);
getPlayerEntity().pos.addStep(Step.WEST);
}
+3 -3
View File
@@ -3,11 +3,11 @@ package mightypork.rogue.world;
import java.io.IOException;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonBundled;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
public class PlayerInfo implements IonBundled {
public class PlayerInfo implements IonObjBundled {
private int eid = -1; // marks not initialized
private int level;
-60
View File
@@ -1,60 +0,0 @@
package mightypork.rogue.world;
public class Sides {
public static final byte NW = (byte) 0b10000000;
public static final byte N = 0b01000000;
public static final byte NE = 0b00100000;
public static final byte E = 0b00010000;
public static final byte SE = 0b00001000;
public static final byte S = 0b00000100;
public static final byte SW = 0b00000010;
public static final byte W = 0b00000001;
public static final byte CARDINAL = N | S | E | W;
public static final byte DIAGONAL = NE | NW | SE | SW;
public static final byte NW_CORNER = W | NW | N;
public static final byte NE_CORNER = E | NE | N;
public static final byte SW_CORNER = W | SW | S;
public static final byte SE_CORNER = E | SE | S;
//@formatter:off
public final static Coord[] allSides = {
Coord.make(-1, -1),
Coord.make(0, -1),
Coord.make(1, -1),
Coord.make(1, 0),
Coord.make(1, 1),
Coord.make(0, 1),
Coord.make(-1, 1),
Coord.make(-1, 0)
};
public final static Coord[] cardinalSides = {
Coord.make(0, -1),
Coord.make(1, 0),
Coord.make(0, 1),
Coord.make(-1, 0)
};
//@formatter:on
/**
* Get element from all sides
*
* @param i side index
* @return the side coord
*/
public static Coord get(int i)
{
return allSides[i]; // FIXME Coord is mutable
}
public static byte bit(int i)
{
return (byte) (1 << (7 - i));
}
}
+4 -4
View File
@@ -4,12 +4,12 @@ package mightypork.rogue.world;
import java.io.IOException;
import java.util.ArrayList;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonBundled;
import mightypork.util.timing.Updateable;
/**
@@ -17,7 +17,7 @@ import mightypork.util.timing.Updateable;
*
* @author MightyPork
*/
public class World implements IonBundled, Updateable {
public class World implements IonObjBundled, Updateable {
private final ArrayList<Level> levels = new ArrayList<>();
@@ -4,11 +4,11 @@ package mightypork.rogue.world;
import java.io.File;
import java.io.IOException;
import mightypork.gamecore.eventbus.BusAccess;
import mightypork.gamecore.eventbus.clients.RootBusNode;
import mightypork.gamecore.util.ion.Ion;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level;
import mightypork.util.control.eventbus.BusAccess;
import mightypork.util.control.eventbus.clients.RootBusNode;
import mightypork.util.files.ion.Ion;
public class WorldProvider extends RootBusNode {
@@ -2,17 +2,18 @@ package mightypork.rogue.world;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.util.math.algo.Coord;
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.RectConst;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectProxy;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.math.constraints.vect.VectConst;
import mightypork.rogue.Res;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.util.math.color.RGB;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.RectConst;
import mightypork.util.math.constraints.rect.proxy.RectProxy;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.math.constraints.vect.VectConst;
/**
@@ -0,0 +1,44 @@
package mightypork.rogue.world.entity;
import java.io.IOException;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.gamecore.util.math.timing.TaskRepeater;
public abstract class AiTimer extends TaskRepeater implements IonObjBundled {
public AiTimer(double duration) {
super(duration);
}
@Override
public abstract void run();
@Override
public void load(IonBundle bundle) throws IOException
{
boolean wasPaused = bundle.get("paused", isPaused());
if(wasPaused) {
pause();
} else {
resume();
}
setProgress(bundle.get("progress", getProgress()));
setDuration(bundle.get("duration", getDuration()));
}
@Override
public void save(IonBundle bundle) throws IOException
{
bundle.put("paused", isPaused());
bundle.put("progress", getProgress());
bundle.put("duration", getDuration());
}
}
@@ -4,13 +4,13 @@ package mightypork.rogue.world.entity;
import java.io.IOException;
import java.util.Collection;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.world.entity.entities.PlayerEntity;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
/**
* Tile registry
* Entity registry
*
* @author MightyPork
*/
+114 -32
View File
@@ -6,18 +6,19 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.error.IllegalValueException;
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.PathFindingContext;
import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.modules.EntityModuleHealth;
import mightypork.rogue.world.entity.modules.EntityModulePosition;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.entity.renderers.EntityRenderer;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.MapRenderContext;
import mightypork.rogue.world.pathfinding.PathFindingContext;
import mightypork.util.annotations.DefaultImpl;
import mightypork.util.error.IllegalValueException;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonBundled;
import mightypork.util.timing.Updateable;
/**
@@ -25,7 +26,7 @@ import mightypork.util.timing.Updateable;
*
* @author MightyPork
*/
public abstract class Entity implements IonBundled, Updateable, EntityMoveListener {
public abstract class Entity implements IonObjBundled, Updateable {
private Level level;
private final EntityModel model;
@@ -40,45 +41,76 @@ public abstract class Entity implements IonBundled, Updateable, EntityMoveListen
public final EntityModuleHealth health = new EntityModuleHealth(this);
public Entity(EntityModel model, int eid)
{
public Entity(EntityModel model, int eid) {
this.entityId = eid;
this.model = model;
// register modules
modules.put("pos", pos);
pos.addMoveListener(this);
modules.put("health", health);
addModule("pos", pos);
addModule("health", health);
}
@Override
public void save(IonBundle bundle) throws IOException
public final void save(IonBundle bundle) throws IOException
{
bundle.put("eid", entityId);
IonBundle modulesBundle = new IonBundle();
for (final Entry<String, EntityModule> entry : modules.entrySet()) {
bundle.putBundled(entry.getKey(), entry.getValue());
modulesBundle.putBundled(entry.getKey(), entry.getValue());
}
bundle.put("modules", modulesBundle);
IonBundle extra = new IonBundle();
saveExtra(extra);
bundle.put("extra", extra);
}
@DefaultImpl
protected void saveExtra(IonBundle bundle)
{
}
@Override
public void load(IonBundle bundle) throws IOException
public final void load(IonBundle bundle) throws IOException
{
entityId = bundle.get("eid", -1);
if (entityId < 0) throw new IllegalValueException("Bad entity id: " + entityId);
IonBundle modulesBundle = bundle.get("modules", new IonBundle());
for (final Entry<String, EntityModule> entry : modules.entrySet()) {
bundle.loadBundled(entry.getKey(), entry.getValue());
modulesBundle.loadBundled(entry.getKey(), entry.getValue());
}
IonBundle extra = bundle.get("extra", new IonBundle());
loadExtra(extra);
}
@DefaultImpl
protected void loadExtra(IonBundle bundle)
{
}
protected final void addModule(String key, EntityModule module)
{
if (modules.containsKey(key)) {
throw new RuntimeException("Entity module " + key + " already defined.");
}
modules.put(key, module);
}
/**
* @return unique entity id
*/
public int getEntityId()
public final int getEntityId()
{
return entityId;
}
@@ -90,19 +122,19 @@ public abstract class Entity implements IonBundled, Updateable, EntityMoveListen
}
public Level getLevel()
public final Level getLevel()
{
return level;
}
public World getWorld()
public final World getWorld()
{
return getLevel().getWorld();
return level.getWorld();
}
public EntityModel getModel()
public final EntityModel getModel()
{
return model;
}
@@ -111,7 +143,14 @@ public abstract class Entity implements IonBundled, Updateable, EntityMoveListen
public abstract PathFindingContext getPathfindingContext();
public abstract void render(MapRenderContext context);
@DefaultImpl
public final void render(MapRenderContext context)
{
getRenderer().render(context);
}
protected abstract EntityRenderer getRenderer();
@Override
@@ -123,26 +162,69 @@ public abstract class Entity implements IonBundled, Updateable, EntityMoveListen
}
/**
* @return entity type (used for AI targeting)
*/
public abstract EntityType getType();
/**
* @return entity coord in level
*/
public Coord getCoord()
{
return pos.getCoord();
}
/**
* Called right after the entity's health reaches zero.
*/
@DefaultImpl
public void onKilled()
{
}
@Override
public void onStepFinished(Entity entity)
/**
* @return true if dead
*/
public final boolean isDead()
{
return health.isDead();
}
/**
* @return whether this dead entity can be removed from level
*/
@DefaultImpl
public boolean canRemoveCorpse()
{
return isDead();
}
/**
* Called when the dead entity was removed from the level.
*/
@DefaultImpl
public void onCorpseRemoved()
{
}
@Override
public void onPathFinished(Entity entity)
/**
* Receive damage from an attacker.<br>
* The entity can decide whether to dodge, reduce damage etc.
*
* @param attacker the entity attacking. Can be null for environmental
* damage.
* @param attackStrength attack strength in health points to take
*/
public void receiveAttack(Entity attacker, int attackStrength)
{
health.receiveDamage(attackStrength);
}
@Override
public void onPathInterrupted(Entity entity)
{
}
}
@@ -3,9 +3,9 @@ package mightypork.rogue.world.entity;
import java.io.IOException;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
/**
@@ -1,11 +1,50 @@
package mightypork.rogue.world.entity;
import mightypork.util.files.ion.IonBundled;
import mightypork.util.timing.Updateable;
import java.io.IOException;
import java.util.Random;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
public interface EntityModule extends IonBundled, Updateable {
/**
* Abstract entity module
*
* @author MightyPork
*/
public abstract class EntityModule implements IonObjBundled, Updateable {
protected final Entity entity;
protected final Random rand = new Random();
public EntityModule(Entity entity) {
this.entity = entity;
}
public abstract boolean isModuleSaved();
@Override
@DefaultImpl
public void load(IonBundle bundle) throws IOException
{
}
@Override
@DefaultImpl
public void save(IonBundle bundle) throws IOException
{
}
@Override
@DefaultImpl
public void update(double delta)
{
}
}
@@ -1,11 +1,12 @@
package mightypork.rogue.world.entity;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.Sides;
import mightypork.rogue.world.pathfinding.Heuristic;
import mightypork.rogue.world.pathfinding.PathFinder;
import mightypork.rogue.world.pathfinding.PathFindingContext;
import mightypork.gamecore.util.math.algo.Coord;
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.gamecore.util.math.algo.pathfinding.PathFindingContext;
public abstract class EntityPathfindingContext implements PathFindingContext {
@@ -42,7 +43,7 @@ public abstract class EntityPathfindingContext implements PathFindingContext {
@Override
public Coord[] getWalkSides()
public Step[] getWalkSides()
{
return Sides.cardinalSides;
}
@@ -0,0 +1,12 @@
package mightypork.rogue.world.entity;
/**
* Type of an entity
*
* @author MightyPork
*/
public enum EntityType
{
PLAYER, MONSTER, PASSIVE;
}
@@ -1,88 +0,0 @@
package mightypork.rogue.world.entity;
import java.io.IOException;
import mightypork.rogue.world.Coord;
import mightypork.util.files.ion.IonBinary;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
/**
* Path step.<br>
* Must be binary in order to be saveable in lists.
*
* @author MightyPork
*/
public class PathStep implements IonBinary {
public static final PathStep NORTH = new PathStep(0, -1);
public static final PathStep SOUTH = new PathStep(0, 1);
public static final PathStep EAST = new PathStep(1, 0);
public static final PathStep WEST = new PathStep(-1, 0);
public static final PathStep NONE = new PathStep(0, 0);
public static PathStep make(int x, int y)
{
x = x < 0 ? -1 : x > 0 ? 1 : 0;
y = y < 0 ? -1 : y > 0 ? 1 : 0;
if (y == -1) return NORTH;
if (y == 1) return SOUTH;
if (x == -1) return WEST;
if (x == 1) return EAST;
return NONE;
}
public static final int ION_MARK = 0;
public int x;
public int y;
public PathStep(int x, int y)
{
this.x = x < 0 ? -1 : x > 0 ? 1 : 0;
this.y = y < 0 ? -1 : y > 0 ? 1 : 0;
}
@Override
public void load(IonInput in) throws IOException
{
x = in.readByte();
y = in.readByte();
}
@Override
public void save(IonOutput out) throws IOException
{
out.writeByte(x);
out.writeByte(y);
}
public Coord toCoord()
{
return Coord.make(x, y);
}
@Override
public short getIonMark()
{
return ION_MARK;
}
@Override
public String toString()
{
return "(" + x + ";" + y + ")";
}
}
@@ -1,7 +1,7 @@
package mightypork.rogue.world.entity;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
public class SimpleEntityPathFindingContext extends EntityPathfindingContext {
@@ -0,0 +1,226 @@
package mightypork.rogue.world.entity.entities;
import java.io.IOException;
import java.util.List;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.algo.pathfinding.PathFinder;
import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext;
import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContextProxy;
import mightypork.rogue.world.entity.AiTimer;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityModule;
import mightypork.rogue.world.entity.EntityType;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.tile.Tile;
public class MonsterAi extends EntityModule implements EntityMoveListener {
private boolean sleeping = true;
private boolean chasing = false;
private AiTimer timerFindPrey = new AiTimer(3) {
@Override
public void run()
{
System.out.println("Mob looks around.");
lookForTarget();
}
};
private AiTimer timerSleepStart = new AiTimer(10) {
@Override
public void run()
{
System.out.println("Mob going to sleep");
sleeping = true;
}
};
private PathFindingContext pathfcNoDoor;
private int targetId = -1;
public MonsterAi(final Entity entity) {
super(entity);
pathfcNoDoor = new PathFindingContextProxy(entity.getPathfindingContext()) {
@Override
public boolean isAccessible(Coord pos)
{
Tile t = entity.getLevel().getTile(pos);
if (t.isDoor()) return false;
return super.isAccessible(pos);
}
};
}
private void lookForTarget()
{
if (rand.nextInt(3) == 0) return; // not hungry right now
Entity prey = entity.getLevel().getClosestEntity(entity, EntityType.PLAYER, getScanRadius());
if (prey != null) {
// check if reachable without leaving room
List<Coord> noDoorPath = PathFinder.findPath(pathfcNoDoor, entity.getCoord(), prey.getCoord());
if (noDoorPath == null) {
return; // cant reach, give up
}
startChasing(prey);
}
}
private void startChasing(Entity prey)
{
// TODO if too close, attack directly
targetId = prey.getEntityId();
chasing = true;
sleeping = false;
// not good to take a nap while chasing
timerSleepStart.pause();
// follow this one prey
timerFindPrey.pause();
onStepFinished(); // go towards prey
}
private void stopChasing()
{
chasing = false;
targetId = -1;
timerSleepStart.restart();
timerFindPrey.restart();
}
private List<Step> getPathToPrey(Entity prey)
{
return PathFinder.findPathRelative(entity.getPathfindingContext(), entity.getCoord(), prey.getCoord());
}
protected double getScanRadius()
{
return sleeping ? 1 + rand.nextInt(3) : 4 + rand.nextInt(4); // For override
}
protected int getPreyAbandonDistance()
{
return 5 + rand.nextInt(4); // For override
}
@DefaultImpl
@Override
public void onStepFinished()
{
if (chasing) {
Entity prey = entity.getLevel().getEntity(targetId);
if (prey == null || prey.isDead()) {
stopChasing();
return;
}
stepTowardsPrey(prey);
// TODO if close enough, attack.
}
}
private void stepTowardsPrey(Entity prey)
{
// if close enough
Coord preyPos = prey.getCoord();
if(preyPos.dist(entity.getCoord()) <= 1.5) {
attackPrey(prey);
return;
}
List<Step> preyPath = getPathToPrey(prey);
if (preyPath.size() > getPreyAbandonDistance()) {
stopChasing();
return;
}
entity.pos.addStep(preyPath.get(0));
}
private void attackPrey(Entity prey)
{
prey.receiveAttack(entity, getAttackStrength());
}
protected int getAttackStrength() {
return 1; // For override
}
@Override
public void onPathFinished()
{
}
@Override
public void onPathInterrupted()
{
}
@Override
public void save(IonBundle bundle) throws IOException
{
bundle.putBundled("tscan", timerFindPrey);
bundle.putBundled("tsleep", timerSleepStart);
}
@Override
public void load(IonBundle bundle) throws IOException
{
bundle.loadBundled("tscan", timerFindPrey);
bundle.loadBundled("tsleep", timerSleepStart);
}
@Override
public boolean isModuleSaved()
{
return true;
}
@Override
public void update(double delta)
{
timerFindPrey.update(delta);
timerSleepStart.update(delta);
}
}
@@ -1,48 +1,87 @@
package mightypork.rogue.world.entity.entities;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityModel;
import mightypork.rogue.world.entity.EntityPathfindingContext;
import mightypork.rogue.world.entity.SimpleEntityPathFindingContext;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext;
import mightypork.rogue.world.entity.*;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.entity.renderers.EntityRenderer;
import mightypork.rogue.world.entity.renderers.EntityRendererMobLR;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.MapRenderContext;
import mightypork.rogue.world.pathfinding.PathFindingContext;
public class PlayerEntity extends Entity {
private final EntityPathfindingContext pathfc = new SimpleEntityPathFindingContext(this) {
class PlayerAi extends EntityModule implements EntityMoveListener {
public PlayerAi(Entity entity) {
super(entity);
}
@Override
public int getCost(Coord from, Coord to)
public void onStepFinished()
{
if (!getLevel().getTile(pos.getCoord()).isExplored()) { return 1000; }
return super.getCost(from, to);
};
};
entity.getLevel().explore(entity.pos.getCoord());
}
@Override
public void onPathFinished()
{
}
@Override
public void onPathInterrupted()
{
}
@Override
public boolean isModuleSaved()
{
return false;
}
}
private final EntityRenderer renderer = new EntityRendererMobLR(this, "sprite.player");
private EntityPathfindingContext pathfc;
private EntityRenderer renderer;
private final PlayerAi ai = new PlayerAi(this);
public PlayerEntity(EntityModel model, int eid)
{
public PlayerEntity(EntityModel model, int eid) {
super(model, eid);
// init default values
pos.setStepTime(0.25);
addModule("ai", ai);
pos.addMoveListener(ai);
}
@Override
public PathFindingContext getPathfindingContext()
{
if (pathfc == null) {
pathfc = new SimpleEntityPathFindingContext(this) {
@Override
public int getCost(Coord from, Coord to)
{
if (!getLevel().getTile(pos.getCoord()).isExplored()) {
return 1000;
}
return super.getCost(from, to);
};
};
}
return pathfc;
}
@@ -51,20 +90,24 @@ public class PlayerEntity extends Entity {
public void setLevel(Level level)
{
super.setLevel(level);
onStepFinished(this);
ai.onStepFinished(); // explore start area
}
@Override
public void render(MapRenderContext context)
protected EntityRenderer getRenderer()
{
renderer.render(context);
if (renderer == null) {
renderer = new EntityRendererMobLR(this, "sprite.player");
}
return renderer;
}
@Override
public void onStepFinished(Entity entity)
public EntityType getType()
{
getLevel().explore(pos.getCoord());
return EntityType.PLAYER;
}
}
@@ -0,0 +1,38 @@
package mightypork.rogue.world.entity.entities;
import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext;
import mightypork.rogue.world.entity.*;
public abstract class SimpleMonster extends Entity {
/** Navigation PFC */
private EntityPathfindingContext pathfc;
private EntityModule ai = new MonsterAi(this);
public SimpleMonster(EntityModel model, int eid) {
super(model, eid);
addModule("ai", ai);
}
@Override
public PathFindingContext getPathfindingContext()
{
if (pathfc == null) {
pathfc = new SimpleEntityPathFindingContext(this);
}
return pathfc;
}
@Override
public EntityType getType()
{
return EntityType.MONSTER;
}
}
@@ -3,22 +3,19 @@ package mightypork.rogue.world.entity.modules;
import java.io.IOException;
import mightypork.gamecore.util.error.IllegalValueException;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.math.Calc;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityModule;
import mightypork.util.error.IllegalValueException;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.math.Calc;
public class EntityModuleHealth implements EntityModule {
public class EntityModuleHealth extends EntityModule {
public EntityModuleHealth(Entity entity)
{
this.entity = entity;
public EntityModuleHealth(Entity entity) {
super(entity);
}
private final Entity entity;
protected int health = 1;
protected int maxHealth = 1;
protected boolean dead = false;
@@ -43,8 +40,9 @@ public class EntityModuleHealth implements EntityModule {
@Override
public void update(double delta)
public boolean isModuleSaved()
{
return true;
}
@@ -90,4 +88,10 @@ public class EntityModuleHealth implements EntityModule {
this.dead = dead;
}
public void receiveDamage(int attackStrength)
{
setHealth(health - attackStrength);
}
}
@@ -8,25 +8,23 @@ import java.util.List;
import java.util.Queue;
import java.util.Set;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.algo.pathfinding.PathFinder;
import mightypork.gamecore.util.math.algo.pathfinding.PathFindingContext;
import mightypork.gamecore.util.math.constraints.vect.VectConst;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.EntityModule;
import mightypork.rogue.world.entity.PathStep;
import mightypork.rogue.world.pathfinding.PathFinder;
import mightypork.rogue.world.pathfinding.PathFindingContext;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.math.constraints.vect.VectConst;
public class EntityModulePosition implements EntityModule {
private final Entity entity;
public class EntityModulePosition extends EntityModule {
/** Last pos, will be freed upon finishing move */
private final Coord lastPos = new Coord(0, 0);
private boolean walking = false;
private final Queue<PathStep> path = new LinkedList<>();
private final Queue<Step> path = new LinkedList<>();
private final EntityPos entityPos = new EntityPos();
private double stepTime = 0.5;
@@ -39,7 +37,7 @@ public class EntityModulePosition implements EntityModule {
public EntityModulePosition(Entity entity)
{
this.entity = entity;
super(entity);
}
@@ -60,6 +58,12 @@ public class EntityModulePosition implements EntityModule {
stepTime = bundle.get("step_time", stepTime);
}
@Override
public boolean isModuleSaved()
{
return true;
}
public void setPosition(Coord coord)
@@ -85,12 +89,12 @@ public class EntityModulePosition implements EntityModule {
entity.getLevel().freeTile(lastPos);
for (final EntityMoveListener l : moveListeners) {
l.onStepFinished(entity);
l.onStepFinished();
}
if (path.isEmpty()) {
for (final EntityMoveListener l : moveListeners) {
l.onPathFinished(entity);
l.onPathFinished();
}
}
}
@@ -99,7 +103,7 @@ public class EntityModulePosition implements EntityModule {
walking = true;
final PathStep step = path.poll();
final Step step = path.poll();
final Coord planned = entityPos.getCoord().add(step.toCoord());
@@ -107,15 +111,15 @@ public class EntityModulePosition implements EntityModule {
cancelPath();
for (final EntityMoveListener l : moveListeners) {
l.onPathInterrupted(entity);
l.onPathInterrupted();
}
walking = false;
} else {
// tmp for renderer
if (step.x != 0) this.lastXDir = step.x;
if (step.y != 0) this.lastYDir = step.y;
if (step.x() != 0) this.lastXDir = step.x();
if (step.y() != 0) this.lastYDir = step.y();
lastPos.setTo(entityPos.getCoord());
entityPos.walk(step, stepTime);
@@ -131,7 +135,7 @@ public class EntityModulePosition implements EntityModule {
}
public void addStep(PathStep step)
public void addStep(Step step)
{
path.add(step);
}
@@ -147,7 +151,7 @@ public class EntityModulePosition implements EntityModule {
{
if (target.equals(getCoord())) return true;
final PathFindingContext pfc = entity.getPathfindingContext();
final List<PathStep> newPath = PathFinder.findPathRelative(pfc, entityPos.getCoord(), target);
final List<Step> newPath = PathFinder.findPathRelative(pfc, entityPos.getCoord(), target);
if (newPath == null) return false;
cancelPath();
@@ -165,7 +169,7 @@ public class EntityModulePosition implements EntityModule {
}
public void addSteps(List<PathStep> path)
public void addSteps(List<Step> path)
{
this.path.addAll(path);
}
@@ -1,7 +1,6 @@
package mightypork.rogue.world.entity.modules;
import mightypork.rogue.world.entity.Entity;
public interface EntityMoveListener {
@@ -9,18 +8,18 @@ public interface EntityMoveListener {
/**
* One step of a path finished
*/
void onStepFinished(Entity entity);
void onStepFinished();
/**
* Scheduled path finished
*/
void onPathFinished(Entity entity);
void onPathFinished();
/**
* Path was interrupted (bumped into a wall or entity)
*/
void onPathInterrupted(Entity entity);
void onPathInterrupted();
}
@@ -3,15 +3,15 @@ package mightypork.rogue.world.entity.modules;
import java.io.IOException;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.entity.PathStep;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonBundled;
import mightypork.util.math.Easing;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.math.constraints.vect.VectConst;
import mightypork.util.math.constraints.vect.mutable.VectAnimated;
import mightypork.util.timing.Updateable;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonObjBundled;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.gamecore.util.math.constraints.vect.VectConst;
import mightypork.gamecore.util.math.constraints.vect.mutable.VectAnimated;
/**
@@ -19,7 +19,7 @@ import mightypork.util.timing.Updateable;
*
* @author MightyPork
*/
class EntityPos implements IonBundled, Updateable {
class EntityPos implements IonObjBundled, Updateable {
private final Coord coord = new Coord(0, 0);
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
@@ -128,10 +128,10 @@ class EntityPos implements IonBundled, Updateable {
}
public void walk(PathStep step, double secs)
public void walk(Step step, double secs)
{
setTo(coord.x + step.x, coord.y + step.y);
walkOffset.setTo(-step.x, -step.y);
setTo(coord.x + step.x(), coord.y + step.y());
walkOffset.setTo(-step.x(), -step.y());
walkOffset.animate(0, 0, 0, secs);
}
@@ -2,14 +2,14 @@ package mightypork.rogue.world.entity.renderers;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxQuad;
import mightypork.gamecore.render.textures.TxSheet;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.resources.textures.TxSheet;
import mightypork.gamecore.util.math.Calc;
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.level.render.MapRenderContext;
import mightypork.util.math.Calc;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.vect.Vect;
/**
@@ -3,7 +3,7 @@ package mightypork.rogue.world.gen;
import java.util.Random;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.gen.rooms.DeadEndRoom;
import mightypork.rogue.world.gen.rooms.SimpleRectRoom;
import mightypork.rogue.world.gen.themes.ThemeDungeon;
@@ -3,7 +3,7 @@ package mightypork.rogue.world.gen;
import java.util.Random;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
/**
+1 -1
View File
@@ -1,7 +1,7 @@
package mightypork.rogue.world.gen;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
/**
+17 -9
View File
@@ -7,19 +7,25 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.Sides;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.math.Calc;
import mightypork.gamecore.util.math.algo.Coord;
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.gamecore.util.math.algo.pathfinding.PathFindingContext;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.pathfinding.Heuristic;
import mightypork.rogue.world.pathfinding.PathFinder;
import mightypork.rogue.world.pathfinding.PathFindingContext;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.Tiles;
import mightypork.util.logging.Log;
import mightypork.util.math.Calc;
/**
* Temporary tile map used for level generation.
*
* @author MightyPork
*/
public class ScratchMap {
private Tile[][] map;
@@ -27,7 +33,9 @@ public class ScratchMap {
private final int height;
private final List<RoomDesc> rooms = new ArrayList<>();
private final List<Coord> nodes = new ArrayList<>(); // points to connect with corridors
/** Coords to connect with corridors */
private final List<Coord> nodes = new ArrayList<>();
private final PathFindingContext pfc = new PathFindingContext() {
@@ -79,7 +87,7 @@ public class ScratchMap {
@Override
public Coord[] getWalkSides()
public Step[] getWalkSides()
{
return Sides.cardinalSides;
}
@@ -3,7 +3,7 @@ package mightypork.rogue.world.gen.rooms;
import java.util.Random;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.rogue.world.gen.RoomBuilder;
import mightypork.rogue.world.gen.RoomDesc;
import mightypork.rogue.world.gen.ScratchMap;
@@ -3,8 +3,8 @@ package mightypork.rogue.world.gen.rooms;
import java.util.Random;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.Sides;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Sides;
import mightypork.rogue.world.gen.RoomBuilder;
import mightypork.rogue.world.gen.RoomDesc;
import mightypork.rogue.world.gen.ScratchMap;
+13 -14
View File
@@ -4,24 +4,23 @@ package mightypork.rogue.world.gui;
import java.util.HashSet;
import java.util.Set;
import mightypork.gamecore.control.events.input.KeyEvent;
import mightypork.gamecore.control.events.input.KeyListener;
import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.input.MouseButtonListener;
import mightypork.gamecore.eventbus.events.Updateable;
import mightypork.gamecore.gui.components.InputComponent;
import mightypork.gamecore.input.Keys;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.input.events.KeyEvent;
import mightypork.gamecore.input.events.KeyListener;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseButtonListener;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.constraints.num.Num;
import mightypork.gamecore.util.math.constraints.num.mutable.NumAnimated;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.WorldRenderer;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.entity.modules.EntityMoveListener;
import mightypork.rogue.world.gui.interaction.MapInteractionPlugin;
import mightypork.util.math.Easing;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.num.mutable.NumAnimated;
import mightypork.util.math.constraints.vect.Vect;
import mightypork.util.timing.Updateable;
/**
@@ -69,7 +68,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
@Override
public void onStepFinished(Entity entity)
public void onStepFinished()
{
for (final MapInteractionPlugin p : plugins) {
p.onStepEnd(this, pc);
@@ -78,7 +77,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
@Override
public void onPathFinished(Entity entity)
public void onPathFinished()
{
for (final MapInteractionPlugin p : plugins) {
p.onStepEnd(this, pc);
@@ -87,7 +86,7 @@ public class MapView extends InputComponent implements KeyListener, MouseButtonL
@Override
public void onPathInterrupted(Entity entity)
public void onPathInterrupted()
{
for (final MapInteractionPlugin p : plugins) {
p.onStepEnd(this, pc);
+9 -9
View File
@@ -1,21 +1,21 @@
package mightypork.rogue.world.gui;
import mightypork.gamecore.control.events.input.MouseButtonEvent;
import mightypork.gamecore.control.events.input.MouseButtonListener;
import mightypork.gamecore.gui.components.InputComponent;
import mightypork.gamecore.input.events.MouseButtonEvent;
import mightypork.gamecore.input.events.MouseButtonListener;
import mightypork.gamecore.render.Render;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
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.RectMutable;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.WorldProvider;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.tile.Tile;
import mightypork.util.math.color.Color;
import mightypork.util.math.color.RGB;
import mightypork.util.math.constraints.num.Num;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.mutable.RectMutable;
import mightypork.util.math.constraints.vect.Vect;
import org.lwjgl.opengl.GL11;
@@ -2,10 +2,10 @@ package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.input.InputSystem;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.gui.MapView;
import mightypork.util.math.constraints.vect.Vect;
public class MIPClickPathfWalk implements MapInteractionPlugin {
@@ -3,9 +3,9 @@ package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.input.InputSystem;
import mightypork.gamecore.input.Keys;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.gui.MapView;
import mightypork.util.math.constraints.vect.Vect;
public class MIPKeyWalk implements MapInteractionPlugin {
@@ -2,12 +2,12 @@ package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.input.InputSystem;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.Calc.Deg;
import mightypork.gamecore.util.math.Polar;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.gui.MapView;
import mightypork.util.math.Calc.Deg;
import mightypork.util.math.Polar;
import mightypork.util.math.constraints.vect.Vect;
public class MIPMouseWalk implements MapInteractionPlugin {
@@ -1,9 +1,9 @@
package mightypork.rogue.world.gui.interaction;
import mightypork.gamecore.util.math.constraints.vect.Vect;
import mightypork.rogue.world.PlayerControl;
import mightypork.rogue.world.gui.MapView;
import mightypork.util.math.constraints.vect.Vect;
public interface MapInteractionPlugin {
+5 -5
View File
@@ -3,13 +3,13 @@ package mightypork.rogue.world.item;
import java.io.IOException;
import mightypork.util.files.ion.IonBinary;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
import mightypork.util.math.constraints.rect.proxy.RectBound;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonObjBinary;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
public class Item implements IonBinary {
public class Item implements IonObjBinary {
public static final short ION_MARK = 51;
@@ -1,8 +1,8 @@
package mightypork.rogue.world.item;
import mightypork.util.annotations.DefaultImpl;
import mightypork.util.math.constraints.rect.proxy.RectBound;
import mightypork.gamecore.util.annot.DefaultImpl;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
public abstract class ItemModel {
+57 -24
View File
@@ -2,29 +2,27 @@ package mightypork.rogue.world.level;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.Sides;
import mightypork.gamecore.logging.Log;
import mightypork.gamecore.util.ion.IonBundle;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonObjBinary;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.algo.floodfill.FillContext;
import mightypork.gamecore.util.math.algo.floodfill.FloodFill;
import mightypork.gamecore.util.math.noise.NoiseGen;
import mightypork.rogue.world.World;
import mightypork.rogue.world.entity.Entities;
import mightypork.rogue.world.entity.Entity;
import mightypork.rogue.world.pathfinding.FillContext;
import mightypork.rogue.world.pathfinding.FloodFill;
import mightypork.rogue.world.entity.EntityType;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.TileType;
import mightypork.rogue.world.tile.Tiles;
import mightypork.util.files.ion.IonBinary;
import mightypork.util.files.ion.IonBundle;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
import mightypork.util.logging.Log;
import mightypork.util.math.noise.NoiseGen;
/**
@@ -32,7 +30,7 @@ import mightypork.util.math.noise.NoiseGen;
*
* @author MightyPork
*/
public class Level implements MapAccess, IonBinary {
public class Level implements MapAccess, IonObjBinary {
public static final int ION_MARK = 53;
@@ -53,13 +51,11 @@ public class Level implements MapAccess, IonBinary {
private transient NoiseGen noiseGen;
public Level()
{
public Level() {
}
public Level(int width, int height)
{
public Level(int width, int height) {
size.setTo(width, height);
buildArray();
}
@@ -91,7 +87,7 @@ public class Level implements MapAccess, IonBinary {
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];
}
@@ -155,7 +151,6 @@ public class Level implements MapAccess, IonBinary {
ib.loadBundled("size", size);
ib.loadBundled("enter_point", enterPoint);
// -- binary data --
// load tiles
@@ -167,7 +162,6 @@ public class Level implements MapAccess, IonBinary {
}
}
// load entities
Entities.loadEntities(in, entitySet);
@@ -296,6 +290,16 @@ public class Level implements MapAccess, IonBinary {
getTile(pos).setOccupied(false);
}
public void cleanCorpses() {
for(Iterator<Entity> i = entitySet.iterator(); i.hasNext();) {
Entity e = i.next();
if(e.isDead() && e.canRemoveCorpse()) {
e.onCorpseRemoved();
removeEntity(e);
}
}
}
public Collection<Entity> getEntities()
{
@@ -341,7 +345,7 @@ public class Level implements MapAccess, IonBinary {
private final FillContext exploreFc = new FillContext() {
@Override
public Coord[] getSpreadSides()
public Step[] getSpreadSides()
{
return Sides.allSides;
}
@@ -376,4 +380,33 @@ public class Level implements MapAccess, IonBinary {
return true;
}
};
public Entity getClosestEntity(Entity self, EntityType type, double radius)
{
Entity closest = null;
double minDist = Double.MAX_VALUE;
for (Entity e : entitySet) {
if (e == self) continue;
if (e.isDead()) continue;
if (e.getType() == type) {
double dist = e.getCoord().dist(self.getCoord());
if (dist <= radius && dist < minDist) {
minDist = dist;
closest = e;
}
}
}
return closest;
}
public boolean isEntityPresent(Entity entity)
{
return entitySet.contains(entity);
}
}
@@ -1,9 +1,9 @@
package mightypork.rogue.world.level;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.noise.NoiseGen;
import mightypork.rogue.world.tile.Tile;
import mightypork.util.math.noise.NoiseGen;
/**
@@ -1,8 +1,8 @@
package mightypork.rogue.world.level.render;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.world.level.MapAccess;
import mightypork.util.math.constraints.rect.Rect;
public class EntityRenderContext extends MapRenderContext {
@@ -1,10 +1,10 @@
package mightypork.rogue.world.level.render;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.builders.TiledRect;
import mightypork.rogue.world.level.MapAccess;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.builders.TiledRect;
public abstract class MapRenderContext {
@@ -1,12 +1,13 @@
package mightypork.rogue.world.level.render;
import mightypork.rogue.world.Coord;
import mightypork.gamecore.util.math.algo.Coord;
import mightypork.gamecore.util.math.algo.Step;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBound;
import mightypork.gamecore.util.math.noise.NoiseGen;
import mightypork.rogue.world.level.MapAccess;
import mightypork.rogue.world.tile.Tile;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.proxy.RectBound;
import mightypork.util.math.noise.NoiseGen;
/**
@@ -45,7 +46,7 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
* @param offset offsets
* @return the tile at that position
*/
public Tile getAdjacentTile(Coord offset)
public Tile getAdjacentTile(Step offset)
{
return map.getTile(pos.add(offset));
}
@@ -1,14 +0,0 @@
package mightypork.rogue.world.pathfinding;
import mightypork.rogue.world.Coord;
public class DiagonalHeuristic extends Heuristic {
@Override
public double getCost(Coord pos, Coord target)
{
return Math.sqrt(Math.pow(pos.x - target.x, 2) + Math.pow(pos.y - target.y, 2));
}
}
@@ -1,30 +0,0 @@
package mightypork.rogue.world.pathfinding;
import mightypork.rogue.world.Coord;
public interface FillContext {
boolean canEnter(Coord pos);
boolean canSpreadFrom(Coord pos);
Coord[] getSpreadSides();
/**
* Get the max distance filled form start point. Use -1 for unlimited range.
*
* @return max distance
*/
double getMaxDistance();
/**
* @return true if start should be spread no matter what
*/
boolean forceSpreadStart();
}
@@ -1,62 +0,0 @@
package mightypork.rogue.world.pathfinding;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Queue;
import mightypork.rogue.world.Coord;
public class FloodFill {
/**
* Fill an area
*
* @param start start point
* @param context filling context
* @param foundNodes collection to put filled coords in
* @return true if fill was successful; false if max range was reached.
*/
public static final boolean fill(Coord start, FillContext context, Collection<Coord> foundNodes)
{
final Queue<Coord> activeNodes = new LinkedList<>();
final double maxDist = context.getMaxDistance();
activeNodes.add(start);
final Coord[] sides = context.getSpreadSides();
boolean forceSpreadNext = context.forceSpreadStart();
boolean limitReached = false;
while (!activeNodes.isEmpty()) {
final Coord current = activeNodes.poll();
foundNodes.add(current);
if (!context.canSpreadFrom(current) && !forceSpreadNext) continue;
forceSpreadNext = false;
for (final Coord spr : sides) {
final Coord next = current.add(spr);
if (activeNodes.contains(next) || foundNodes.contains(next)) continue;
if (next.dist(start) > maxDist) {
limitReached = true;
continue;
}
if (context.canEnter(next)) {
activeNodes.add(next);
} else {
foundNodes.add(next);
}
}
}
return !limitReached;
}
}
@@ -1,17 +0,0 @@
package mightypork.rogue.world.pathfinding;
import mightypork.rogue.world.Coord;
public abstract class Heuristic {
/**
* Get tile cost (estimate of how many tiles remain to the target)
*
* @param pos current pos
* @param target target pos
* @return estimated number of tiles
*/
public abstract double getCost(Coord pos, Coord target);
}
@@ -1,14 +0,0 @@
package mightypork.rogue.world.pathfinding;
import mightypork.rogue.world.Coord;
public class ManhattanHeuristic extends Heuristic {
@Override
public double getCost(Coord pos, Coord target)
{
return Math.abs(target.x - pos.x) + Math.abs(target.y - pos.y);
}
}
@@ -1,190 +0,0 @@
package mightypork.rogue.world.pathfinding;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import mightypork.rogue.world.Coord;
import mightypork.rogue.world.entity.PathStep;
/**
* A* pathfinder
*
* @author MightyPork
*/
public class PathFinder {
private static final FComparator F_COMPARATOR = new FComparator();
public static final Heuristic CORNER_HEURISTIC = new ManhattanHeuristic();
public static final Heuristic DIAGONAL_HEURISTIC = new DiagonalHeuristic();
public static List<PathStep> findPathRelative(PathFindingContext context, Coord start, Coord end)
{
final List<Coord> path = findPath(context, start, end);
if (path == null) return null;
final List<PathStep> out = new ArrayList<>();
final Coord current = start.copy();
for (final Coord c : path) {
if (c.equals(current)) continue;
out.add(PathStep.make(c.x - current.x, c.y - current.y));
current.x = c.x;
current.y = c.y;
}
return out;
}
public static List<Coord> findPath(PathFindingContext context, Coord start, Coord end)
{
final LinkedList<Node> open = new LinkedList<>();
final LinkedList<Node> closed = new LinkedList<>();
final Heuristic heuristic = context.getHeuristic();
// add first node
{
final Node n = new Node(start);
n.h_cost = (int) (heuristic.getCost(start, end) * context.getMinCost());
n.g_cost = 0;
open.add(n);
}
final Coord[] walkDirs = context.getWalkSides();
Node current = null;
while (true) {
current = open.poll();
if (current == null) {
break;
}
closed.add(current);
if (current.pos.equals(end)) {
break;
}
for (final Coord go : walkDirs) {
final Coord c = current.pos.add(go);
if (!context.isAccessible(c)) continue;
final Node a = new Node(c);
a.g_cost = current.g_cost + context.getCost(c, a.pos);
a.h_cost = (int) (heuristic.getCost(a.pos, end) * context.getMinCost());
a.parent = current;
if (context.isAccessible(a.pos)) {
if (!closed.contains(a)) {
if (open.contains(a)) {
boolean needSort = false;
// find where it is
for (final Node n : open) {
if (n.pos.equals(a.pos)) { // found it
if (n.g_cost > a.g_cost) {
n.parent = current;
n.g_cost = a.g_cost;
needSort = true;
}
break;
}
}
if (needSort) Collections.sort(open, F_COMPARATOR);
} else {
open.add(a);
}
}
}
}
}
if (current == null) { return null; // no path found
}
final LinkedList<Coord> path = new LinkedList<>();
// extract path elements
while (current != null) {
path.addFirst(current.pos);
current = current.parent;
}
return path;
}
private static class Node {
Coord pos;
int g_cost; // to get there
int h_cost; // to target
Node parent;
public Node(Coord pos)
{
this.pos = pos;
}
int fCost()
{
return g_cost + h_cost;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((pos == null) ? 0 : pos.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (!(obj instanceof Node)) return false;
final Node other = (Node) obj;
if (pos == null) {
if (other.pos != null) return false;
} else if (!pos.equals(other.pos)) return false;
return true;
}
@Override
public String toString()
{
return "N " + pos + ", G =" + g_cost + ", H = " + h_cost;
}
}
private static class FComparator implements Comparator<Node> {
@Override
public int compare(Node n1, Node n2)
{
return n1.fCost() - n2.fCost();
}
}
}
@@ -1,39 +0,0 @@
package mightypork.rogue.world.pathfinding;
import mightypork.rogue.world.Coord;
public interface PathFindingContext {
/**
* @param pos tile pos
* @return true if the tile is walkable
*/
boolean isAccessible(Coord pos);
/**
* Cost of walking onto a tile. It's useful to use ie. 10 for basic step.
*
* @param from last tile
* @param to current tile
* @return cost
*/
int getCost(Coord from, Coord to);
/**
* @return lowest cost. Used to multiply heuristics.
*/
int getMinCost();
/**
* @return used heuristic
*/
Heuristic getHeuristic();
Coord[] getWalkSides();
}
@@ -1,13 +1,13 @@
package mightypork.rogue.world.tile;
import mightypork.gamecore.util.math.Easing;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.gamecore.util.math.constraints.rect.proxy.RectBoundAdapter;
import mightypork.gamecore.util.math.timing.Animator;
import mightypork.gamecore.util.math.timing.AnimatorBounce;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.util.math.Easing;
import mightypork.util.math.constraints.rect.Rect;
import mightypork.util.math.constraints.rect.proxy.RectBoundAdapter;
import mightypork.util.timing.Animator;
import mightypork.util.timing.AnimatorBounce;
public class DroppedItemRenderer {
+6 -6
View File
@@ -3,14 +3,14 @@ package mightypork.rogue.world.tile;
import java.io.IOException;
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.color.Color;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.util.annotations.DefaultImpl;
import mightypork.util.files.ion.IonBinaryHeadless;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
import mightypork.util.math.color.Color;
/**
@@ -18,7 +18,7 @@ import mightypork.util.math.color.Color;
*
* @author MightyPork
*/
public abstract class Tile implements IonBinaryHeadless {
public abstract class Tile implements IonObjBlob {
// tmp extras
public final TileRenderData renderData = new TileRenderData();
@@ -3,8 +3,8 @@ package mightypork.rogue.world.tile;
import java.io.IOException;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
/**
@@ -2,11 +2,11 @@ package mightypork.rogue.world.tile;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxQuad;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.algo.Sides;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.Res;
import mightypork.rogue.world.Sides;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.util.math.constraints.rect.Rect;
/**
@@ -1,9 +1,9 @@
package mightypork.rogue.world.tile;
import mightypork.util.math.color.Color;
import mightypork.util.math.color.PAL16;
import mightypork.util.math.color.RGB;
import mightypork.gamecore.util.math.color.Color;
import mightypork.gamecore.util.math.color.pal.PAL16;
import mightypork.gamecore.util.math.color.pal.RGB;
/**
+2 -2
View File
@@ -3,6 +3,8 @@ package mightypork.rogue.world.tile;
import java.io.IOException;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.world.tile.renderers.BasicTileRenderer;
import mightypork.rogue.world.tile.renderers.DoorTileRenderer;
import mightypork.rogue.world.tile.renderers.NullTileRenderer;
@@ -10,8 +12,6 @@ import mightypork.rogue.world.tile.tiles.DoorTile;
import mightypork.rogue.world.tile.tiles.FloorTile;
import mightypork.rogue.world.tile.tiles.NullTile;
import mightypork.rogue.world.tile.tiles.WallTile;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
/**
@@ -2,11 +2,11 @@ package mightypork.rogue.world.tile.renderers;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxSheet;
import mightypork.gamecore.resources.textures.TxSheet;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.Res;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.rogue.world.tile.TileRenderer;
import mightypork.util.math.constraints.rect.Rect;
public class BasicTileRenderer extends TileRenderer {
@@ -2,12 +2,12 @@ package mightypork.rogue.world.tile.renderers;
import mightypork.gamecore.render.Render;
import mightypork.gamecore.render.textures.TxQuad;
import mightypork.gamecore.resources.textures.TxQuad;
import mightypork.gamecore.util.math.constraints.rect.Rect;
import mightypork.rogue.Res;
import mightypork.rogue.world.level.render.TileRenderContext;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileRenderer;
import mightypork.util.math.constraints.rect.Rect;
public class DoorTileRenderer extends TileRenderer {
@@ -4,6 +4,8 @@ package mightypork.rogue.world.tile.tiles;
import java.io.IOException;
import java.util.Stack;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.world.item.Item;
import mightypork.rogue.world.level.Level;
import mightypork.rogue.world.level.render.TileRenderContext;
@@ -11,8 +13,6 @@ import mightypork.rogue.world.tile.DroppedItemRenderer;
import mightypork.rogue.world.tile.Tile;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.TileRenderer;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
public abstract class GroundTile extends Tile {
@@ -3,10 +3,10 @@ package mightypork.rogue.world.tile.tiles;
import java.io.IOException;
import mightypork.gamecore.util.ion.IonInput;
import mightypork.gamecore.util.ion.IonOutput;
import mightypork.rogue.world.tile.TileModel;
import mightypork.rogue.world.tile.TileRenderer;
import mightypork.util.files.ion.IonInput;
import mightypork.util.files.ion.IonOutput;
public class LockedDoorTile extends DoorTile {