Entirely rewritten ION, world saving, added map movement etc
This commit is contained in:
@@ -22,15 +22,12 @@ import mightypork.rogue.screens.main_menu.ScreenMainMenu;
|
||||
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
||||
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
||||
import mightypork.rogue.screens.test_render.ScreenTestRender;
|
||||
import mightypork.rogue.world.PlayerInfo;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.control.eventbus.EventBus;
|
||||
import mightypork.util.control.eventbus.events.Event;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.ion.Ion;
|
||||
import mightypork.util.logging.Log;
|
||||
import mightypork.util.logging.writers.LogWriter;
|
||||
|
||||
@@ -109,12 +106,9 @@ public final class App extends BaseApp {
|
||||
@Override
|
||||
protected void preInit()
|
||||
{
|
||||
Ion.registerIonizable(Item.ION_MARK, Item.class);
|
||||
Ion.registerIonizable(Level.ION_MARK, Level.class);
|
||||
Ion.registerIonizable(PlayerInfo.ION_MARK, PlayerInfo.class);
|
||||
Ion.registerIonizable(Tile.ION_MARK, Tile.class);
|
||||
Ion.registerIonizable(World.ION_MARK, World.class);
|
||||
Ion.registerIonizable(WorldPos.ION_MARK, WorldPos.class);
|
||||
Ion.registerBinary(Item.ION_MARK, Item.class);
|
||||
Ion.registerBinary(Level.ION_MARK, Level.class);
|
||||
Ion.registerBinary(Tile.ION_MARK, Tile.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@ import java.util.Random;
|
||||
|
||||
import mightypork.gamecore.gui.screens.Screen;
|
||||
import mightypork.gamecore.gui.screens.ScreenLayer;
|
||||
import mightypork.gamecore.input.InputSystem;
|
||||
import mightypork.gamecore.input.KeyStroke;
|
||||
import mightypork.gamecore.input.Keys;
|
||||
import mightypork.rogue.world.MapGenerator;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.ion.Ion;
|
||||
|
||||
|
||||
public class WorldLayer extends ScreenLayer {
|
||||
@@ -17,17 +20,82 @@ public class WorldLayer extends ScreenLayer {
|
||||
{
|
||||
super(screen);
|
||||
|
||||
// FIXME just temporary test here
|
||||
|
||||
final Random rand = new Random();
|
||||
final World w = MapGenerator.createWorld(rand.nextLong());
|
||||
|
||||
try {
|
||||
Ion.toFile("amap.ion", w);
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
// final World w;
|
||||
//
|
||||
// try {
|
||||
// w = Ion.fromFile("amap.ion", World.class);
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// System.exit(1);
|
||||
// return;
|
||||
// }
|
||||
|
||||
final WorldRenderer wr = new WorldRenderer(w);
|
||||
wr.setRect(root);
|
||||
root.add(wr);
|
||||
|
||||
bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(-1, 0);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(1, 0);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(0, -1);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(0, 1);
|
||||
}
|
||||
});
|
||||
|
||||
w.getPlayer().setTargetListener(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (InputSystem.isKeyDown(Keys.LEFT)) {
|
||||
w.getPlayer().walk(-1, 0);
|
||||
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
||||
w.getPlayer().walk(1, 0);
|
||||
} else if (InputSystem.isKeyDown(Keys.UP)) {
|
||||
w.getPlayer().walk(0, -1);
|
||||
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
||||
w.getPlayer().walk(0, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import mightypork.gamecore.gui.components.painters.TextPainter;
|
||||
import mightypork.gamecore.render.fonts.GLFont;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.util.constraints.num.Num;
|
||||
import mightypork.util.constraints.num.mutable.NumVar;
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
import mightypork.util.constraints.vect.mutable.VectVar;
|
||||
import mightypork.util.math.color.Color;
|
||||
@@ -21,23 +20,14 @@ class MenuButton extends ClickableComponent {
|
||||
private final Vect offsetActive = Vect.make(this.height().perc(-5), Num.ZERO);
|
||||
private final Color color;
|
||||
|
||||
private final double ALPHA_OFF = 0.6;
|
||||
private final double ALPHA_ON = 1;
|
||||
|
||||
private final double SH_ALPHA_OFF = 0.1;
|
||||
private final double SH_ALPHA_ON = 0.5;
|
||||
|
||||
private final NumVar alphaMul = Num.makeVar(ALPHA_OFF);
|
||||
private final NumVar alphaMulSh = Num.makeVar(SH_ALPHA_OFF);
|
||||
|
||||
|
||||
public MenuButton(String text, Color color)
|
||||
{
|
||||
this.color = color.withAlpha(alphaMul);
|
||||
this.color = color;
|
||||
|
||||
this.painter = new TextPainter(font, AlignX.CENTER, this.color, text);
|
||||
this.painter.setRect(this.shrink(this.height().perc(8)).move(offset));
|
||||
this.painter.setShadow(Color.BLACK.withAlpha(alphaMulSh), height().div(24).toVectXY());
|
||||
this.painter.setShadow(Color.BLACK.withAlpha(0.3), height().div(24).toVectXY());
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +36,8 @@ class MenuButton extends ClickableComponent {
|
||||
{
|
||||
if (isMouseOver()) {
|
||||
offset.setTo(offsetActive);
|
||||
alphaMul.setTo(ALPHA_ON);
|
||||
alphaMulSh.setTo(SH_ALPHA_ON);
|
||||
} else {
|
||||
offset.setTo(Vect.ZERO);
|
||||
alphaMul.setTo(ALPHA_OFF);
|
||||
alphaMulSh.setTo(SH_ALPHA_OFF);
|
||||
}
|
||||
|
||||
painter.render();
|
||||
|
||||
@@ -4,6 +4,7 @@ package mightypork.rogue.world;
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
|
||||
|
||||
@@ -20,33 +21,30 @@ public class MapGenerator {
|
||||
final World w = new World();
|
||||
w.setSeed(seed);
|
||||
|
||||
final int levels = 4 + rand.nextInt(6);
|
||||
|
||||
for (int i = 0; i < levels; i++) {
|
||||
w.addLevel(createLevel(rand.nextLong()));
|
||||
}
|
||||
w.addLevel(createLevel(rand.nextLong(), Tiles.CRYSTAL_FLOOR, Tiles.CRYSTAL_WALL));
|
||||
w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
||||
|
||||
// TODO place on start position
|
||||
w.setPlayer(new PlayerInfo(10, 10, 0));
|
||||
w.getPlayer().teleport(new WorldPos(10, 10, 0));
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Level createLevel(long seed)
|
||||
private static Level createLevel(long seed, TileModel floor, TileModel wall)
|
||||
{
|
||||
// TODO
|
||||
|
||||
final Level lm = new Level(20, 20);
|
||||
lm.setSeed(seed);
|
||||
|
||||
lm.fill(Tiles.CRYSTAL_FLOOR);
|
||||
lm.fill(floor);
|
||||
|
||||
final Random rand = new Random();
|
||||
rand.setSeed(seed);
|
||||
|
||||
for (int i = 0; i < 150; i++) {
|
||||
lm.setTile(Tiles.CRYSTAL_WALL, rand.nextInt(20), rand.nextInt(20));
|
||||
lm.setTile(wall, rand.nextInt(20), rand.nextInt(20));
|
||||
}
|
||||
|
||||
return lm;
|
||||
|
||||
@@ -6,13 +6,7 @@ package mightypork.rogue.world;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface MapObserver {
|
||||
|
||||
/**
|
||||
* @return observer's position
|
||||
*/
|
||||
public WorldPos getPosition();
|
||||
|
||||
public interface MapObserver extends WorldEntity {
|
||||
|
||||
/**
|
||||
* @return observed range (in tiles)
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
import mightypork.util.constraints.vect.mutable.VectAnimated;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
import mightypork.util.math.Easing;
|
||||
|
||||
|
||||
/**
|
||||
* Player info
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class Player implements IonBundled, MapObserver, Updateable {
|
||||
|
||||
private final WorldPos position = new WorldPos();
|
||||
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
|
||||
private final WorldPos target = new WorldPos();
|
||||
private Runnable targetListener;
|
||||
|
||||
|
||||
public Player()
|
||||
{
|
||||
walkOffset.setDefaultDuration(0.25);
|
||||
}
|
||||
|
||||
|
||||
public Player(int x, int y, int floor)
|
||||
{
|
||||
this.position.setTo(x, y, floor);
|
||||
this.target.setTo(position);
|
||||
}
|
||||
|
||||
|
||||
public Player(WorldPos pos)
|
||||
{
|
||||
this(pos.x, pos.y, pos.floor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle in) throws IOException
|
||||
{
|
||||
in.loadBundled("pos", position);
|
||||
in.loadBundled("target", target);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle out) throws IOException
|
||||
{
|
||||
out.putBundled("pos", position);
|
||||
out.putBundled("target", target);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WorldPos getLogicalPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Vect getVisualOffset()
|
||||
{
|
||||
return walkOffset;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getViewRange()
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
|
||||
public void teleport(WorldPos pos)
|
||||
{
|
||||
position.setTo(pos);
|
||||
target.setTo(pos);
|
||||
walkOffset.reset();
|
||||
}
|
||||
|
||||
|
||||
public void walk(int offsetX, int offsetY)
|
||||
{
|
||||
this.target.setTo(position.x + offsetX, position.y + offsetY, this.position.floor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
if (!walkOffset.isFinished()) {
|
||||
walkOffset.update(delta);
|
||||
if (walkOffset.isFinished()) {
|
||||
position.add(walkOffset.xi(), walkOffset.yi(), position.floor);
|
||||
walkOffset.reset();
|
||||
targetListener.run();
|
||||
}
|
||||
}
|
||||
|
||||
if (walkOffset.isFinished() && !target.equals(position)) {
|
||||
|
||||
int x = (target.x - position.x);
|
||||
if (x > 0) x = 1;
|
||||
if (x < 0) x = -1;
|
||||
int y = (target.y - position.y);
|
||||
if (y > 0) y = 1;
|
||||
if (y < 0) y = -1;
|
||||
|
||||
walkOffset.animate(x, y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setTargetListener(Runnable r)
|
||||
{
|
||||
this.targetListener = r;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonConstructor;
|
||||
import mightypork.util.files.ion.Ionizable;
|
||||
|
||||
|
||||
/**
|
||||
* Player info
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class PlayerInfo implements Ionizable, MapObserver {
|
||||
|
||||
public static final short ION_MARK = 708;
|
||||
|
||||
public WorldPos position = new WorldPos();
|
||||
|
||||
|
||||
@IonConstructor
|
||||
public PlayerInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public PlayerInfo(int x, int y, int floor)
|
||||
{
|
||||
this.position.setTo(x, y, floor);
|
||||
}
|
||||
|
||||
|
||||
public PlayerInfo(WorldPos pos)
|
||||
{
|
||||
this.position = pos;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(InputStream in) throws IOException
|
||||
{
|
||||
final IonBundle ib = (IonBundle) Ion.readObject(in);
|
||||
|
||||
position = ib.get("pos", position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(OutputStream out) throws IOException
|
||||
{
|
||||
final IonBundle ib = new IonBundle();
|
||||
|
||||
ib.put("pos", position);
|
||||
|
||||
Ion.writeObject(out, ib);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WorldPos getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getViewRange()
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,7 @@ package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -14,19 +13,15 @@ import mightypork.util.constraints.rect.RectConst;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.Ionizable;
|
||||
import mightypork.util.files.ion.templates.StreamableArrayList;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
|
||||
|
||||
public class World implements Ionizable, Updateable {
|
||||
public class World implements IonBundled, Updateable {
|
||||
|
||||
public static final short ION_MARK = 706;
|
||||
private final ArrayList<Level> levels = new ArrayList<>();
|
||||
|
||||
private StreamableArrayList<Level> levels = new StreamableArrayList<>();
|
||||
|
||||
private PlayerInfo player = new PlayerInfo();
|
||||
private final Player player = new Player();
|
||||
|
||||
private transient final Set<MapObserver> observers = new HashSet<>();
|
||||
|
||||
@@ -35,36 +30,20 @@ public class World implements Ionizable, Updateable {
|
||||
|
||||
|
||||
@Override
|
||||
public void load(InputStream in) throws IOException
|
||||
public void load(IonBundle in) throws IOException
|
||||
{
|
||||
// world data
|
||||
final IonBundle ib = (IonBundle) Ion.readObject(in);
|
||||
player = ib.get("player", player);
|
||||
seed = ib.get("seed", seed);
|
||||
|
||||
Ion.readSequence(in, levels);
|
||||
in.loadBundled("player", player);
|
||||
seed = in.get("seed", 0L);
|
||||
in.loadSequence("levels", levels);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(OutputStream out) throws IOException
|
||||
public void save(IonBundle out) throws IOException
|
||||
{
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.put("player", player);
|
||||
ib.put("seed", seed);
|
||||
Ion.writeObject(out, ib);
|
||||
|
||||
Ion.writeSequence(out, levels);
|
||||
}
|
||||
|
||||
|
||||
public void setPlayer(PlayerInfo player)
|
||||
{
|
||||
removeObserver(this.player);
|
||||
|
||||
this.player = player;
|
||||
|
||||
addObserver(player);
|
||||
out.putBundled("player", player);
|
||||
out.put("seed", seed);
|
||||
out.putSequence("levels", levels);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,19 +65,14 @@ public class World implements Ionizable, Updateable {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
player.update(delta);
|
||||
|
||||
for (int level = 0; level < levels.size(); level++) {
|
||||
for (final MapObserver observer : observers) {
|
||||
if (observer.getPosition().floor == level) {
|
||||
if (observer.getLogicalPosition().floor == level) {
|
||||
levels.get(level).update(observer, delta);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +82,7 @@ public class World implements Ionizable, Updateable {
|
||||
|
||||
public Level getLevelForObserver(MapObserver observer)
|
||||
{
|
||||
return levels.get(observer.getPosition().floor);
|
||||
return levels.get(observer.getLogicalPosition().floor);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,19 +112,22 @@ public class World implements Ionizable, Updateable {
|
||||
|
||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||
|
||||
final int playerX = player.getPosition().x;
|
||||
final int playerY = player.getPosition().y;
|
||||
final double playerX = player.getLogicalPosition().x + player.getVisualOffset().x();
|
||||
final double playerY = player.getLogicalPosition().y + player.getVisualOffset().y();
|
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow(
|
||||
playerX*tileSize,
|
||||
playerY*tileSize,//
|
||||
(floor.getWidth() - playerX) * tileSize,
|
||||
playerY*tileSize,
|
||||
(floor.getHeight() - playerY) * tileSize
|
||||
).freeze();
|
||||
//@formatter:on
|
||||
|
||||
System.out.println(playerX + "," + playerY + " : " + mapRect);
|
||||
System.out.println(floor.getWidth() + "," + floor.getHeight());
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
||||
@@ -177,4 +154,10 @@ public class World implements Ionizable, Updateable {
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
public Player getPlayer()
|
||||
{
|
||||
return player;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
|
||||
|
||||
public interface WorldEntity {
|
||||
|
||||
WorldPos getLogicalPosition();
|
||||
|
||||
|
||||
Vect getVisualOffset();
|
||||
}
|
||||
@@ -2,12 +2,9 @@ package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.files.ion.IonConstructor;
|
||||
import mightypork.util.files.ion.Ionizable;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
|
||||
|
||||
/**
|
||||
@@ -15,57 +12,88 @@ import mightypork.util.files.ion.Ionizable;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class WorldPos implements Ionizable {
|
||||
|
||||
public static final short ION_MARK = 707;
|
||||
public class WorldPos implements IonBundled {
|
||||
|
||||
public int x, y, floor;
|
||||
|
||||
|
||||
public WorldPos(int x, int y, int z)
|
||||
public WorldPos(int x, int y, int floor)
|
||||
{
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.floor = z;
|
||||
this.floor = floor;
|
||||
}
|
||||
|
||||
|
||||
@IonConstructor
|
||||
public WorldPos()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(InputStream in) throws IOException
|
||||
public void load(IonBundle in) throws IOException
|
||||
{
|
||||
x = Ion.readInt(in);
|
||||
y = Ion.readInt(in);
|
||||
floor = Ion.readInt(in);
|
||||
x = in.get("x", 0);
|
||||
y = in.get("y", 0);
|
||||
floor = in.get("z", 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(OutputStream out) throws IOException
|
||||
public void save(IonBundle out) throws IOException
|
||||
{
|
||||
Ion.writeInt(out, x);
|
||||
Ion.writeInt(out, y);
|
||||
Ion.writeInt(out, floor);
|
||||
out.put("x", x);
|
||||
out.put("y", y);
|
||||
out.put("z", floor);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
public void setTo(int x, int y, int z)
|
||||
public void setTo(int x, int y, int floor)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.floor = z;
|
||||
this.floor = floor;
|
||||
}
|
||||
|
||||
|
||||
public void setTo(WorldPos other)
|
||||
{
|
||||
this.x = other.x;
|
||||
this.y = other.y;
|
||||
this.floor = other.floor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + floor;
|
||||
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 WorldPos)) return false;
|
||||
final WorldPos other = (WorldPos) obj;
|
||||
if (floor != other.floor) return false;
|
||||
if (x != other.x) return false;
|
||||
if (y != other.y) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void add(int x, int y, int floor)
|
||||
{
|
||||
setTo(this.x + x, this.y + y, this.floor + floor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,18 +2,16 @@ package mightypork.rogue.world.item;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.files.ion.IonConstructor;
|
||||
import mightypork.util.files.ion.Ionizable;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonInput;
|
||||
import mightypork.util.ion.IonOutput;
|
||||
|
||||
|
||||
public class Item implements Ionizable {
|
||||
public class Item implements IonBinary {
|
||||
|
||||
public static final short ION_MARK = 701;
|
||||
public static final short ION_MARK = 51;
|
||||
|
||||
private transient ItemModel model;
|
||||
|
||||
@@ -26,7 +24,6 @@ public class Item implements Ionizable {
|
||||
}
|
||||
|
||||
|
||||
@IonConstructor
|
||||
public Item()
|
||||
{
|
||||
}
|
||||
@@ -46,16 +43,16 @@ public class Item implements Ionizable {
|
||||
|
||||
|
||||
@Override
|
||||
public void save(OutputStream out) throws IOException
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
Ion.writeShort(out, (short) id);
|
||||
out.writeIntByte(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(InputStream in) throws IOException
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
id = Ion.readShort(in);
|
||||
id = in.readIntByte();
|
||||
|
||||
// if id changed, get new model
|
||||
if (model == null || id != model.id) model = Items.get(id);
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package mightypork.rogue.world.item;
|
||||
|
||||
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
import mightypork.util.constraints.num.proxy.NumBoundAdapter;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.rect.proxy.RectBoundAdapter;
|
||||
|
||||
|
||||
public abstract class ItemModel {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package mightypork.rogue.world.map;
|
||||
|
||||
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
|
||||
|
||||
public class EntityRenderContext extends MapRenderContext {
|
||||
|
||||
public EntityRenderContext(MapAccess map, Rect drawArea)
|
||||
{
|
||||
super(map, drawArea);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,17 +2,16 @@ package mightypork.rogue.world.map;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import mightypork.rogue.world.MapObserver;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.files.ion.IonConstructor;
|
||||
import mightypork.util.files.ion.Ionizable;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonInput;
|
||||
import mightypork.util.ion.IonOutput;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
|
||||
@@ -21,9 +20,9 @@ import mightypork.util.math.noise.NoiseGen;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class Level implements MapAccess, Ionizable {
|
||||
public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public static final int ION_MARK = 702;
|
||||
public static final int ION_MARK = 52;
|
||||
|
||||
private int width, height;
|
||||
|
||||
@@ -33,10 +32,9 @@ public class Level implements MapAccess, Ionizable {
|
||||
/** Level seed (used for generation and tile variation) */
|
||||
public long seed;
|
||||
|
||||
private NoiseGen noiseGen;
|
||||
private transient NoiseGen noiseGen;
|
||||
|
||||
|
||||
@IonConstructor
|
||||
public Level()
|
||||
{
|
||||
}
|
||||
@@ -53,8 +51,6 @@ public class Level implements MapAccess, Ionizable {
|
||||
private void buildArray()
|
||||
{
|
||||
this.tiles = new Tile[height][width];
|
||||
|
||||
fill(Tiles.NULL_EMPTY);
|
||||
}
|
||||
|
||||
|
||||
@@ -131,32 +127,43 @@ public class Level implements MapAccess, Ionizable {
|
||||
|
||||
|
||||
@Override
|
||||
public void load(InputStream in) throws IOException
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
seed = Ion.readLong(in);
|
||||
width = Ion.readInt(in);
|
||||
height = Ion.readInt(in);
|
||||
// metadata
|
||||
final IonBundle ib = in.readBundle();
|
||||
seed = ib.get("seed", 0L);
|
||||
width = ib.get("w", 0);
|
||||
height = ib.get("h", 0);
|
||||
|
||||
// init array of size
|
||||
buildArray();
|
||||
|
||||
// load tiles
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
tiles[y][x] = new Tile();
|
||||
tiles[y][x].load(in);
|
||||
// no mark
|
||||
final Tile t = new Tile();
|
||||
t.load(in);
|
||||
tiles[y][x] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(OutputStream out) throws IOException
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
Ion.writeLong(out, seed);
|
||||
Ion.writeInt(out, width);
|
||||
Ion.writeInt(out, height);
|
||||
// metadata
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.put("seed", seed);
|
||||
ib.put("w", width);
|
||||
ib.put("h", height);
|
||||
out.writeBundle(ib);
|
||||
|
||||
// tiles (writing this way to save space)
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// no mark to save space
|
||||
tiles[y][x].save(out);
|
||||
}
|
||||
}
|
||||
@@ -173,7 +180,7 @@ public class Level implements MapAccess, Ionizable {
|
||||
public void update(MapObserver observer, double delta)
|
||||
{
|
||||
final int viewRange = observer.getViewRange();
|
||||
final WorldPos position = observer.getPosition();
|
||||
final WorldPos position = observer.getLogicalPosition();
|
||||
|
||||
int x1 = position.x - viewRange;
|
||||
int y1 = position.y - viewRange;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package mightypork.rogue.world.map;
|
||||
|
||||
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.builders.TiledRect;
|
||||
|
||||
|
||||
public abstract class MapRenderContext {
|
||||
|
||||
protected final MapAccess map;
|
||||
protected final TiledRect tiler;
|
||||
private final Rect mapRect;
|
||||
|
||||
|
||||
public MapRenderContext(MapAccess map, Rect drawArea)
|
||||
{
|
||||
this.map = map;
|
||||
this.tiler = drawArea.tiles(map.getWidth(), map.getHeight());
|
||||
this.mapRect = drawArea;
|
||||
}
|
||||
|
||||
|
||||
public Rect getRectForTile(int x, int y)
|
||||
{
|
||||
return tiler.tile(x, y);
|
||||
}
|
||||
|
||||
|
||||
public Rect getMapRect()
|
||||
{
|
||||
return mapRect;
|
||||
}
|
||||
}
|
||||
@@ -3,32 +3,27 @@ package mightypork.rogue.world.map;
|
||||
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.builders.TiledRect;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
|
||||
/**
|
||||
* Context for tile rendering. Provides tile rect, surrounding tiles, rendered
|
||||
* tile and random noise values for position-static tile variation.
|
||||
* Context for tile rendering.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class TileRenderContext implements RectBound {
|
||||
public final class TileRenderContext extends MapRenderContext implements RectBound {
|
||||
|
||||
private final MapAccess map;
|
||||
private final TiledRect tiler;
|
||||
public int x;
|
||||
public int y;
|
||||
private final NoiseGen noise;
|
||||
|
||||
public int x, y;
|
||||
|
||||
|
||||
public TileRenderContext(MapAccess map, Rect drawArea)
|
||||
{
|
||||
this.map = map;
|
||||
this.tiler = drawArea.tiles(map.getWidth(), map.getHeight());
|
||||
super(map, drawArea);
|
||||
|
||||
this.tiler.setOverlap(0.001); // avoid gaps (rounding error?)
|
||||
this.tiler.setOverlap(0.01); // avoid gaps (rounding error?)
|
||||
|
||||
this.noise = map.getNoiseGen();
|
||||
}
|
||||
@@ -56,16 +51,6 @@ public final class TileRenderContext implements RectBound {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rect of the current tile to draw
|
||||
*/
|
||||
@Override
|
||||
public Rect getRect()
|
||||
{
|
||||
return tiler.tile(x, y);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return per-coord noise value 0..1
|
||||
*/
|
||||
@@ -79,4 +64,14 @@ public final class TileRenderContext implements RectBound {
|
||||
{
|
||||
map.getTile(x, y).render(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rect of the current tile to draw
|
||||
*/
|
||||
@Override
|
||||
public Rect getRect()
|
||||
{
|
||||
return getRectForTile(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,21 @@ package mightypork.rogue.world.tile;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Stack;
|
||||
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.util.control.timing.Animator;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.files.ion.Ion;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.files.ion.IonConstructor;
|
||||
import mightypork.util.files.ion.Ionizable;
|
||||
import mightypork.util.files.ion.Streamable;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonInput;
|
||||
import mightypork.util.ion.IonOutput;
|
||||
|
||||
|
||||
public final class Tile implements Ionizable, Updateable {
|
||||
public final class Tile implements IonBinary, Updateable {
|
||||
|
||||
public static final short ION_MARK = 700;
|
||||
public static final short ION_MARK = 50;
|
||||
|
||||
private transient TileModel model;
|
||||
|
||||
@@ -50,7 +47,6 @@ public final class Tile implements Ionizable, Updateable {
|
||||
}
|
||||
|
||||
|
||||
@IonConstructor
|
||||
public Tile()
|
||||
{
|
||||
}
|
||||
@@ -60,45 +56,45 @@ public final class Tile implements Ionizable, Updateable {
|
||||
{
|
||||
model.render(context);
|
||||
|
||||
if (!items.isEmpty()) {
|
||||
if (hasItems()) {
|
||||
getItemRenderer().render(items.peek(), context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(OutputStream out) throws IOException
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
if (model.isNullTile()) throw new RuntimeException("Cannot save null tile.");
|
||||
out.writeIntByte(id);
|
||||
|
||||
Ion.writeShort(out, (short) id); // tile ID
|
||||
Ion.writeSequence(out, items); // if empty, writes single END mark
|
||||
if (model.hasDroppedItems()) {
|
||||
out.writeSequence(items);
|
||||
}
|
||||
|
||||
// models with metadata can save their stuff
|
||||
if (model.hasMetadata()) {
|
||||
IonBundle ib = new IonBundle();
|
||||
final IonBundle ib = new IonBundle();
|
||||
model.saveMetadata(this, ib);
|
||||
Ion.writeObject(out, ib);
|
||||
out.writeBundle(ib);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(InputStream in) throws IOException
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
id = Ion.readShort(in);
|
||||
id = in.readIntByte();
|
||||
|
||||
// check if model is changed (can happen)
|
||||
// check model
|
||||
if (model == null || id != model.id) {
|
||||
model = Tiles.get(id);
|
||||
}
|
||||
|
||||
Ion.readSequence(in, items); // if END is found, nothing is read.
|
||||
if (model.hasDroppedItems()) {
|
||||
in.readSequence(items);
|
||||
}
|
||||
|
||||
// load model's stuff
|
||||
if (model.hasMetadata()) {
|
||||
IonBundle ib = (IonBundle) Ion.readObject(in);
|
||||
model.loadMetadata(this, ib);
|
||||
model.loadMetadata(this, in.readBundle());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +103,7 @@ public final class Tile implements Ionizable, Updateable {
|
||||
public void update(double delta)
|
||||
{
|
||||
model.update(this, delta);
|
||||
if (!items.isEmpty()) {
|
||||
if (hasItems()) {
|
||||
getItemRenderer().update(delta);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +127,7 @@ public final class Tile implements Ionizable, Updateable {
|
||||
|
||||
public boolean hasItems()
|
||||
{
|
||||
return !items.isEmpty();
|
||||
return model.hasDroppedItems() && !items.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package mightypork.rogue.world.tile;
|
||||
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
|
||||
|
||||
/**
|
||||
@@ -104,4 +104,13 @@ public abstract class TileModel {
|
||||
* @return has data
|
||||
*/
|
||||
public abstract boolean hasMetadata();
|
||||
|
||||
|
||||
/**
|
||||
* Check if the tile can hold dropped items. Walls and such can return false
|
||||
* to save disk space (no need to write empty list).
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public abstract boolean hasDroppedItems();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ package mightypork.rogue.world.tile.models;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
|
||||
|
||||
/**
|
||||
@@ -59,20 +59,30 @@ public abstract class AbstractNullTile extends TileModel {
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasMetadata()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void loadMetadata(Tile tile, IonBundle ib)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void saveMetadata(Tile tile, IonBundle ib)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasDroppedItems()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,4 +20,11 @@ public class Floor extends SimpleTile {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasDroppedItems()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
import mightypork.util.files.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,4 +20,11 @@ public class Wall extends SimpleTile {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasDroppedItems()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user