Removed useless "multiplayer" crap and converted to singleplayer
This commit is contained in:
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
@@ -5,9 +5,11 @@ import static org.lwjgl.opengl.GL11.*;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mightypork.gamecore.audio.players.EffectPlayer;
|
||||||
import mightypork.gamecore.render.textures.FilterMode;
|
import mightypork.gamecore.render.textures.FilterMode;
|
||||||
import mightypork.gamecore.render.textures.GLTexture;
|
import mightypork.gamecore.render.textures.GLTexture;
|
||||||
import mightypork.gamecore.render.textures.TxQuad;
|
import mightypork.gamecore.render.textures.TxQuad;
|
||||||
|
import mightypork.rogue.Res;
|
||||||
import mightypork.util.constraints.rect.Rect;
|
import mightypork.util.constraints.rect.Rect;
|
||||||
import mightypork.util.constraints.rect.caching.RectDigest;
|
import mightypork.util.constraints.rect.caching.RectDigest;
|
||||||
import mightypork.util.constraints.vect.Vect;
|
import mightypork.util.constraints.vect.Vect;
|
||||||
@@ -230,6 +232,8 @@ public class Render {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int pushed = 0;
|
private static int pushed = 0;
|
||||||
|
/** Can be used to avoid texture binding and glBegin/glEnd in textured quads */
|
||||||
|
public static boolean batchTexturedQuadMode;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -432,14 +436,14 @@ public class Render {
|
|||||||
*/
|
*/
|
||||||
public static void quadTextured(Rect quad, Rect uvs, GLTexture texture, Color tint)
|
public static void quadTextured(Rect quad, Rect uvs, GLTexture texture, Color tint)
|
||||||
{
|
{
|
||||||
glEnable(GL_TEXTURE_2D);
|
if (!batchTexturedQuadMode) {
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
texture.bind();
|
texture.bind();
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
}
|
||||||
|
|
||||||
setColor(tint);
|
setColor(tint);
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
|
|
||||||
final RectDigest q = quad.digest();
|
final RectDigest q = quad.digest();
|
||||||
final RectDigest u = uvs.digest();
|
final RectDigest u = uvs.digest();
|
||||||
|
|
||||||
@@ -458,7 +462,8 @@ public class Render {
|
|||||||
|
|
||||||
glTexCoord2d(u.left * w, u.top * h);
|
glTexCoord2d(u.left * w, u.top * h);
|
||||||
glVertex2d(q.left, q.top);
|
glVertex2d(q.left, q.top);
|
||||||
glEnd();
|
|
||||||
|
if (!batchTexturedQuadMode) glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -544,4 +549,18 @@ public class Render {
|
|||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void enterBatchTexturedQuadMode(GLTexture texture)
|
||||||
|
{
|
||||||
|
texture.bind();
|
||||||
|
GL11.glBegin(GL11.GL_QUADS);
|
||||||
|
batchTexturedQuadMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void leaveBatchTexturedQuadMode()
|
||||||
|
{
|
||||||
|
GL11.glEnd();
|
||||||
|
batchTexturedQuadMode = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import mightypork.gamecore.render.fonts.GLFont;
|
import mightypork.gamecore.render.fonts.GLFont;
|
||||||
|
import mightypork.gamecore.render.textures.DeferredTexture;
|
||||||
import mightypork.gamecore.render.textures.FilterMode;
|
import mightypork.gamecore.render.textures.FilterMode;
|
||||||
import mightypork.util.constraints.vect.Vect;
|
import mightypork.util.constraints.vect.Vect;
|
||||||
import mightypork.util.constraints.vect.VectConst;
|
import mightypork.util.constraints.vect.VectConst;
|
||||||
@@ -374,6 +375,8 @@ public class CachedFont implements GLFont {
|
|||||||
{
|
{
|
||||||
GLUtils.checkGLContext();
|
GLUtils.checkGLContext();
|
||||||
|
|
||||||
|
DeferredTexture.lastBind = null; // needs rebind.
|
||||||
|
|
||||||
// PUSH
|
// PUSH
|
||||||
glPushAttrib(GL_ENABLE_BIT);
|
glPushAttrib(GL_ENABLE_BIT);
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import org.lwjgl.opengl.GL11;
|
|||||||
@MustLoadInMainThread
|
@MustLoadInMainThread
|
||||||
public class DeferredTexture extends DeferredResource implements GLTexture {
|
public class DeferredTexture extends DeferredResource implements GLTexture {
|
||||||
|
|
||||||
|
public static DeferredTexture lastBind = null;
|
||||||
|
|
||||||
private org.newdawn.slick.opengl.Texture backingTexture;
|
private org.newdawn.slick.opengl.Texture backingTexture;
|
||||||
private FilterMode filter = FilterMode.NEAREST;
|
private FilterMode filter = FilterMode.NEAREST;
|
||||||
private WrapMode wrap = WrapMode.CLAMP;
|
private WrapMode wrap = WrapMode.CLAMP;
|
||||||
@@ -70,15 +72,19 @@ public class DeferredTexture extends DeferredResource implements GLTexture {
|
|||||||
|
|
||||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||||
|
|
||||||
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
if (lastBind != this) {
|
||||||
|
lastBind = this;
|
||||||
|
|
||||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrap.num);
|
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrap.num);
|
|
||||||
|
|
||||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter.num);
|
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrap.num);
|
||||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter.num);
|
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrap.num);
|
||||||
|
|
||||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTextureID());
|
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter.num);
|
||||||
|
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter.num);
|
||||||
|
|
||||||
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTextureID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import mightypork.rogue.screens.main_menu.ScreenMainMenu;
|
|||||||
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
||||||
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
||||||
import mightypork.rogue.screens.test_render.ScreenTestRender;
|
import mightypork.rogue.screens.test_render.ScreenTestRender;
|
||||||
import mightypork.rogue.world.PlayerEntity;
|
import mightypork.rogue.world.entity.Entity;
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.map.Level;
|
import mightypork.rogue.world.level.Level;
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.util.control.eventbus.EventBus;
|
import mightypork.util.control.eventbus.EventBus;
|
||||||
import mightypork.util.control.eventbus.events.Event;
|
import mightypork.util.control.eventbus.events.Event;
|
||||||
@@ -110,7 +110,7 @@ public final class App extends BaseApp {
|
|||||||
Ion.registerBinary(Tile.ION_MARK, Tile.class);
|
Ion.registerBinary(Tile.ION_MARK, Tile.class);
|
||||||
Ion.registerBinary(Item.ION_MARK, Item.class);
|
Ion.registerBinary(Item.ION_MARK, Item.class);
|
||||||
Ion.registerBinary(Level.ION_MARK, Level.class);
|
Ion.registerBinary(Level.ION_MARK, Level.class);
|
||||||
Ion.registerBinary(Level.ION_MARK, PlayerEntity.class);
|
Ion.registerBinary(Entity.ION_MARK, Entity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public final class Res {
|
|||||||
textures.addQuad("xp_off", gui.makeQuad(.5, 1.5, .5, .5));
|
textures.addQuad("xp_off", gui.makeQuad(.5, 1.5, .5, .5));
|
||||||
textures.addQuad("panel", gui.makeQuad(0, 3.75, 4, .25));
|
textures.addQuad("panel", gui.makeQuad(0, 3.75, 4, .25));
|
||||||
|
|
||||||
texture = textures.loadTexture("tiles", "/res/img/map_tiles.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
texture = textures.loadTexture("tiles", "/res/img/tiles.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||||
final QuadGrid tiles = texture.grid(32, 32);
|
final QuadGrid tiles = texture.grid(32, 32);
|
||||||
|
|
||||||
textures.addSheet("tile.wall.mossy_bricks", tiles.makeSheet(4, 0, 7, 1));
|
textures.addSheet("tile.wall.mossy_bricks", tiles.makeSheet(4, 0, 7, 1));
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ import java.util.Random;
|
|||||||
|
|
||||||
import mightypork.gamecore.gui.screens.Screen;
|
import mightypork.gamecore.gui.screens.Screen;
|
||||||
import mightypork.gamecore.gui.screens.ScreenLayer;
|
import mightypork.gamecore.gui.screens.ScreenLayer;
|
||||||
import mightypork.gamecore.input.InputSystem;
|
|
||||||
import mightypork.gamecore.input.KeyStroke;
|
|
||||||
import mightypork.gamecore.input.Keys;
|
|
||||||
import mightypork.rogue.Paths;
|
import mightypork.rogue.Paths;
|
||||||
import mightypork.rogue.world.MapGenerator;
|
import mightypork.rogue.world.MapGenerator;
|
||||||
import mightypork.rogue.world.World;
|
import mightypork.rogue.world.World;
|
||||||
@@ -28,7 +25,7 @@ public class WorldLayer extends ScreenLayer {
|
|||||||
final World w = MapGenerator.createWorld(rand.nextLong());
|
final World w = MapGenerator.createWorld(rand.nextLong());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Ion.toFile(new File(Paths.WORKDIR,"test-world.ion"), w);
|
Ion.toFile(new File(Paths.WORKDIR, "test-world.ion"), w);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
@@ -49,63 +46,63 @@ public class WorldLayer extends ScreenLayer {
|
|||||||
wr.setRect(root);
|
wr.setRect(root);
|
||||||
root.add(wr);
|
root.add(wr);
|
||||||
|
|
||||||
bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
// bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void run()
|
// public void run()
|
||||||
{
|
// {
|
||||||
w.getPlayer().walk(-1, 0);
|
// w.getPlayer().walk(-1, 0);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
// bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void run()
|
// public void run()
|
||||||
{
|
// {
|
||||||
w.getPlayer().walk(1, 0);
|
// w.getPlayer().walk(1, 0);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
// bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void run()
|
// public void run()
|
||||||
{
|
// {
|
||||||
w.getPlayer().walk(0, -1);
|
// w.getPlayer().walk(0, -1);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
// bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void run()
|
// public void run()
|
||||||
{
|
// {
|
||||||
w.getPlayer().walk(0, 1);
|
// w.getPlayer().walk(0, 1);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
bindKey(new KeyStroke(true, Keys.SPACE), new Runnable() {
|
// bindKey(new KeyStroke(true, Keys.SPACE), new Runnable() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void run()
|
// public void run()
|
||||||
{
|
// {
|
||||||
w.getPlayer().walk(5, 5);
|
// w.getPlayer().walk(5, 5);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
w.getPlayer().setMoveListener(new Runnable() {
|
// w.getPlayer().setMoveListener(new Runnable() {
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void run()
|
// public void run()
|
||||||
{
|
// {
|
||||||
if (InputSystem.isKeyDown(Keys.LEFT)) {
|
// if (InputSystem.isKeyDown(Keys.LEFT)) {
|
||||||
w.getPlayer().walk(-1, 0);
|
// w.getPlayer().walk(-1, 0);
|
||||||
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
// } else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
||||||
w.getPlayer().walk(1, 0);
|
// w.getPlayer().walk(1, 0);
|
||||||
} else if (InputSystem.isKeyDown(Keys.UP)) {
|
// } else if (InputSystem.isKeyDown(Keys.UP)) {
|
||||||
w.getPlayer().walk(0, -1);
|
// w.getPlayer().walk(0, -1);
|
||||||
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
// } else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
||||||
w.getPlayer().walk(0, 1);
|
// w.getPlayer().walk(0, 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
|
|||||||
{
|
{
|
||||||
if (!event.isDown()) return;
|
if (!event.isDown()) return;
|
||||||
|
|
||||||
cat_position.setTo(event.getPos());
|
cat_position.animate(event.getPos());
|
||||||
|
|
||||||
final double newSize = root.height().perc(10 + rand.nextInt(40)).value();
|
final double newSize = root.height().perc(10 + rand.nextInt(40)).value();
|
||||||
|
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.map.Level;
|
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
|
||||||
import mightypork.util.constraints.rect.Rect;
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ClientWorld implements Updateable, WorldAccess {
|
|
||||||
|
|
||||||
private Level level = null;
|
|
||||||
|
|
||||||
private final PlayerEntity player = null;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(double delta)
|
|
||||||
{
|
|
||||||
player.update(delta);
|
|
||||||
|
|
||||||
level.updateVisual(player, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draw on screen
|
|
||||||
*
|
|
||||||
* @param viewport rendering area on screen
|
|
||||||
* @param xTiles Desired nr of tiles horizontally
|
|
||||||
* @param yTiles Desired nr of tiles vertically
|
|
||||||
* @param minSize minimum tile size
|
|
||||||
*/
|
|
||||||
public void render(final RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
|
||||||
{
|
|
||||||
final Rect r = viewport.getRect();
|
|
||||||
final double vpH = r.height().value();
|
|
||||||
final double vpW = r.width().value();
|
|
||||||
|
|
||||||
// adjust tile size to fit desired amount of tiles
|
|
||||||
|
|
||||||
final double allowedSizeW = vpW / xTiles;
|
|
||||||
final double allowedSizeH = vpH / yTiles;
|
|
||||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
|
||||||
|
|
||||||
tileSize -= tileSize % 16;
|
|
||||||
|
|
||||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
|
||||||
|
|
||||||
final double playerX = player.getPosition().getVisualX();
|
|
||||||
final double playerY = player.getPosition().getVisualY();
|
|
||||||
|
|
||||||
// total map area
|
|
||||||
//@formatter:off
|
|
||||||
final RectConst mapRect = vpCenter.startRect().grow(
|
|
||||||
playerX*tileSize,
|
|
||||||
(level.getWidth() - playerX) * tileSize,
|
|
||||||
playerY*tileSize,
|
|
||||||
(level.getHeight() - playerY) * tileSize
|
|
||||||
).freeze();
|
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
// tiles to render
|
|
||||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
|
||||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
|
||||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize));
|
|
||||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize));
|
|
||||||
|
|
||||||
final TileRenderContext trc = new TileRenderContext(level, mapRect); //-tileSize*0.5
|
|
||||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
|
||||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
|
||||||
trc.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PlayerEntity getPlayer()
|
|
||||||
{
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isServer()
|
|
||||||
{
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
import mightypork.rogue.world.map.Level;
|
|
||||||
import mightypork.util.control.timing.Updateable;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction of client-server connection from the client's view
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public abstract class ClientWorldAccess implements Updateable {
|
|
||||||
|
|
||||||
public abstract Level getLevel();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.map.Level;
|
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
|
||||||
import mightypork.util.constraints.rect.Rect;
|
|
||||||
import mightypork.util.constraints.rect.RectConst;
|
|
||||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
|
||||||
import mightypork.util.constraints.vect.VectConst;
|
|
||||||
|
|
||||||
|
|
||||||
public class LevelRenderer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Draw on screen
|
|
||||||
*
|
|
||||||
* @param viewport rendering area on screen
|
|
||||||
* @param xTiles Desired nr of tiles horizontally
|
|
||||||
* @param yTiles Desired nr of tiles vertically
|
|
||||||
* @param minSize minimum tile size
|
|
||||||
*/
|
|
||||||
public static void render(Level level, PlayerEntity player, RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
|
||||||
{
|
|
||||||
final Rect r = viewport.getRect();
|
|
||||||
final double vpH = r.height().value();
|
|
||||||
final double vpW = r.width().value();
|
|
||||||
|
|
||||||
// adjust tile size to fit desired amount of tiles
|
|
||||||
|
|
||||||
final double allowedSizeW = vpW / xTiles;
|
|
||||||
final double allowedSizeH = vpH / yTiles;
|
|
||||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
|
||||||
|
|
||||||
tileSize -= tileSize % 16;
|
|
||||||
|
|
||||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
|
||||||
|
|
||||||
final double playerX = player.getPosition().getVisualX();
|
|
||||||
final double playerY = player.getPosition().getVisualY();
|
|
||||||
|
|
||||||
// total map area
|
|
||||||
//@formatter:off
|
|
||||||
final RectConst mapRect = vpCenter.startRect().grow(
|
|
||||||
playerX*tileSize,
|
|
||||||
(level.getWidth() - playerX) * tileSize,
|
|
||||||
playerY*tileSize,
|
|
||||||
(level.getHeight() - playerY) * tileSize
|
|
||||||
).freeze();
|
|
||||||
//@formatter:on
|
|
||||||
|
|
||||||
// tiles to render
|
|
||||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
|
||||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
|
||||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize));
|
|
||||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize));
|
|
||||||
|
|
||||||
final TileRenderContext trc = new TileRenderContext(level, mapRect); //-tileSize*0.5
|
|
||||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
|
||||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
|
||||||
trc.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,9 +3,9 @@ package mightypork.rogue.world;
|
|||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import mightypork.rogue.world.map.Level;
|
import mightypork.rogue.world.level.Level;
|
||||||
import mightypork.rogue.world.tile.TileModel;
|
|
||||||
import mightypork.rogue.world.tile.Tiles;
|
import mightypork.rogue.world.tile.Tiles;
|
||||||
|
import mightypork.rogue.world.tile.models.TileModel;
|
||||||
|
|
||||||
|
|
||||||
public class MapGenerator {
|
public class MapGenerator {
|
||||||
@@ -13,19 +13,19 @@ public class MapGenerator {
|
|||||||
public static final Random rand = new Random();
|
public static final Random rand = new Random();
|
||||||
|
|
||||||
|
|
||||||
public static ServerWorld createWorld(long seed)
|
public static World createWorld(long seed)
|
||||||
{
|
{
|
||||||
synchronized (rand) {
|
synchronized (rand) {
|
||||||
rand.setSeed(seed);
|
rand.setSeed(seed);
|
||||||
|
|
||||||
final ServerWorld w = new ServerWorld();
|
final World w = new World();
|
||||||
w.setSeed(seed);
|
w.setSeed(seed);
|
||||||
|
|
||||||
w.addLevel(createLevel(rand.nextLong(), Tiles.CRYSTAL_FLOOR, Tiles.CRYSTAL_WALL));
|
w.addLevel(createLevel(rand.nextLong(), Tiles.CRYSTAL_FLOOR, Tiles.CRYSTAL_WALL));
|
||||||
w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
||||||
|
|
||||||
// TODO place on start position
|
// TODO place on start position
|
||||||
w.addPlayer("local", new PlayerEntity(10, 10, 0));
|
w.createPlayer(10, 10, 0);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ public class PathStep implements IonBinary {
|
|||||||
public int y;
|
public int y;
|
||||||
|
|
||||||
|
|
||||||
public PathStep(int x, int y) {
|
public PathStep(int x, int y)
|
||||||
|
{
|
||||||
this.x = x < 1 ? -1 : x > 0 ? 1 : 0;
|
this.x = x < 1 ? -1 : x > 0 ? 1 : 0;
|
||||||
this.y = y < 1 ? -1 : y > 0 ? 1 : 0;
|
this.y = y < 1 ? -1 : y > 0 ? 1 : 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import mightypork.rogue.world.map.MapObserver;
|
|
||||||
import mightypork.util.ion.IonBundle;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Player info
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public class PlayerEntity extends WorldEntity implements MapObserver {
|
|
||||||
|
|
||||||
public static final double PLAYER_STEP_TIME = 0.3;
|
|
||||||
|
|
||||||
public boolean connected = false;
|
|
||||||
|
|
||||||
|
|
||||||
public PlayerEntity() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PlayerEntity(ServerWorld world, int x, int y, int floor) {
|
|
||||||
super(world, new WorldPos(x, y, floor));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(IonBundle bundle) throws IOException
|
|
||||||
{
|
|
||||||
super.load(bundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(IonBundle bundle) throws IOException
|
|
||||||
{
|
|
||||||
super.save(bundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getViewRange()
|
|
||||||
{
|
|
||||||
return 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected double getStepTime()
|
|
||||||
{
|
|
||||||
return PLAYER_STEP_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isConnected()
|
|
||||||
{
|
|
||||||
return connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setConnected(boolean connected)
|
|
||||||
{
|
|
||||||
this.connected = connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WorldPos getViewPosition()
|
|
||||||
{
|
|
||||||
return getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPhysical()
|
|
||||||
{
|
|
||||||
return isConnected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package mightypork.rogue.world;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import mightypork.util.ion.IonBundle;
|
||||||
|
import mightypork.util.ion.IonBundled;
|
||||||
|
|
||||||
|
|
||||||
|
public class PlayerInfo implements IonBundled {
|
||||||
|
|
||||||
|
private int eid = -1; // marks not initialized
|
||||||
|
private int level;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonBundle bundle) throws IOException
|
||||||
|
{
|
||||||
|
eid = bundle.get("attached_eid", 0);
|
||||||
|
level = bundle.get("current_level", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonBundle bundle) throws IOException
|
||||||
|
{
|
||||||
|
bundle.put("attached_eid", eid);
|
||||||
|
bundle.put("current_level", level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setEID(int eid)
|
||||||
|
{
|
||||||
|
if (isInitialized()) throw new RuntimeException("Cannot change player EID.");
|
||||||
|
this.eid = eid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLevel(int level)
|
||||||
|
{
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getEID()
|
||||||
|
{
|
||||||
|
return eid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getLevel()
|
||||||
|
{
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isInitialized()
|
||||||
|
{
|
||||||
|
return eid != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import mightypork.rogue.world.map.Level;
|
|
||||||
import mightypork.util.control.timing.Updateable;
|
|
||||||
import mightypork.util.ion.IonBundle;
|
|
||||||
import mightypork.util.ion.IonBundled;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* World on a server. To a server, all players and levels are equal.
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public class ServerWorld implements IonBundled, Updateable, WorldAccess {
|
|
||||||
|
|
||||||
private final ArrayList<Level> levels = new ArrayList<>();
|
|
||||||
|
|
||||||
private final Map<String, PlayerEntity> players = new HashMap<>();
|
|
||||||
|
|
||||||
/** This seed can be used to re-create identical world. */
|
|
||||||
private long seed;
|
|
||||||
|
|
||||||
/** Next spawned entity ID */
|
|
||||||
private long eid;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(IonBundle in) throws IOException
|
|
||||||
{
|
|
||||||
seed = in.get("seed", 0L);
|
|
||||||
eid = in.get("eid", 0L);
|
|
||||||
in.loadSequence("levels", levels);
|
|
||||||
in.loadMap("players", players);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(IonBundle out) throws IOException
|
|
||||||
{
|
|
||||||
out.put("seed", seed);
|
|
||||||
out.put("eid", eid);
|
|
||||||
out.putSequence("levels", levels);
|
|
||||||
out.putMap("players", players);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addLevel(Level level)
|
|
||||||
{
|
|
||||||
levels.add(level);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addPlayer(String name, PlayerEntity player)
|
|
||||||
{
|
|
||||||
players.put(name, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removePlayer(String name)
|
|
||||||
{
|
|
||||||
players.remove(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(double delta)
|
|
||||||
{
|
|
||||||
Set<Integer> occupiedLevels = new HashSet<>();
|
|
||||||
|
|
||||||
// food meters and such
|
|
||||||
for (final PlayerEntity pl : players.values()) {
|
|
||||||
if(pl.isConnected()) {
|
|
||||||
pl.updateLogic(this, delta);
|
|
||||||
occupiedLevels.add(pl.getPosition().floor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i : occupiedLevels) {
|
|
||||||
levels.get(i).updateLogic(this, delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setSeed(long seed)
|
|
||||||
{
|
|
||||||
this.seed = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public long getSeed()
|
|
||||||
{
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public long generateEntityId()
|
|
||||||
{
|
|
||||||
return eid++;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isServer()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package mightypork.rogue.world;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import mightypork.rogue.world.entity.Entities;
|
||||||
|
import mightypork.rogue.world.entity.Entity;
|
||||||
|
import mightypork.rogue.world.level.Level;
|
||||||
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
|
import mightypork.util.control.timing.Updateable;
|
||||||
|
import mightypork.util.ion.IonBundle;
|
||||||
|
import mightypork.util.ion.IonBundled;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* World on a server. To a server, all players and levels are equal.
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class World implements IonBundled, Updateable {
|
||||||
|
|
||||||
|
private final ArrayList<Level> levels = new ArrayList<>();
|
||||||
|
|
||||||
|
private final PlayerInfo player = new PlayerInfo();
|
||||||
|
|
||||||
|
private long seed; // world seed
|
||||||
|
private int eid; // next entity ID
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonBundle in) throws IOException
|
||||||
|
{
|
||||||
|
seed = in.get("seed", 0L);
|
||||||
|
eid = in.get("next_eid", 0);
|
||||||
|
in.loadSequence("levels", levels);
|
||||||
|
in.loadBundled("player", player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonBundle out) throws IOException
|
||||||
|
{
|
||||||
|
out.put("seed", seed);
|
||||||
|
out.put("next_eid", eid);
|
||||||
|
out.putSequence("levels", levels);
|
||||||
|
out.putBundled("player", player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addLevel(Level level)
|
||||||
|
{
|
||||||
|
levels.add(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(double delta)
|
||||||
|
{
|
||||||
|
getCurrentLevel().update(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSeed(long seed)
|
||||||
|
{
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getSeed()
|
||||||
|
{
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return new entity ID
|
||||||
|
*/
|
||||||
|
public int getNewEID()
|
||||||
|
{
|
||||||
|
return eid++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void createPlayer(int x, int y, int level)
|
||||||
|
{
|
||||||
|
if (player.isInitialized()) {
|
||||||
|
throw new RuntimeException("Player already created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// make entity
|
||||||
|
int playerEid = getNewEID();
|
||||||
|
|
||||||
|
final Entity entity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y));
|
||||||
|
|
||||||
|
player.setLevel(level);
|
||||||
|
player.setEID(playerEid);
|
||||||
|
|
||||||
|
levels.get(level).addEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw on screen
|
||||||
|
*
|
||||||
|
* @param viewport rendering area on screen
|
||||||
|
* @param xTiles Desired nr of tiles horizontally
|
||||||
|
* @param yTiles Desired nr of tiles vertically
|
||||||
|
* @param minSize minimum tile size
|
||||||
|
*/
|
||||||
|
public void render(RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
||||||
|
{
|
||||||
|
getCurrentLevel().render(player, viewport, yTiles, xTiles, minSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Level getCurrentLevel()
|
||||||
|
{
|
||||||
|
return levels.get(player.getLevel());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
public interface WorldAccess {
|
|
||||||
|
|
||||||
public boolean isServer();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
package mightypork.rogue.world;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
|
|
||||||
import mightypork.util.ion.IonBundle;
|
|
||||||
import mightypork.util.ion.IonBundled;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class WorldEntity implements IonBundled {
|
|
||||||
|
|
||||||
private final WorldPos position = new WorldPos();
|
|
||||||
private Runnable moveEndListener, pathEndListener;
|
|
||||||
|
|
||||||
private long serial_id = 0L;
|
|
||||||
|
|
||||||
private final Queue<PathStep> path = new LinkedList<>();
|
|
||||||
|
|
||||||
|
|
||||||
public WorldEntity(ServerWorld world, WorldPos pos) {
|
|
||||||
this.serial_id = world.generateEntityId();
|
|
||||||
this.position.setTo(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public WorldEntity() {
|
|
||||||
// for ion
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(IonBundle bundle) throws IOException
|
|
||||||
{
|
|
||||||
bundle.putBundled("pos", position);
|
|
||||||
bundle.putSequence("steps", path);
|
|
||||||
bundle.put("eid", serial_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(IonBundle bundle) throws IOException
|
|
||||||
{
|
|
||||||
bundle.loadBundled("pos", position);
|
|
||||||
bundle.loadSequence("path", path);
|
|
||||||
serial_id = bundle.get("eid", 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setMoveEndListener(Runnable moveEndListener)
|
|
||||||
{
|
|
||||||
this.moveEndListener = moveEndListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setPathEndListener(Runnable pathEndListener)
|
|
||||||
{
|
|
||||||
this.pathEndListener = pathEndListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public WorldPos getPosition()
|
|
||||||
{
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setPosition(WorldPos pos)
|
|
||||||
{
|
|
||||||
position.setTo(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setPosition(int x, int y, int floor)
|
|
||||||
{
|
|
||||||
position.setTo(x, y, floor);
|
|
||||||
cancelPath(); // discard remaining steps
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param world the world
|
|
||||||
* @param delta delta time
|
|
||||||
*/
|
|
||||||
public void updateLogic(WorldAccess world, double delta)
|
|
||||||
{
|
|
||||||
if(!isPhysical()) return;
|
|
||||||
|
|
||||||
if (!position.isFinished()) {
|
|
||||||
position.update(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position.isFinished()) {
|
|
||||||
|
|
||||||
if (moveEndListener != null) moveEndListener.run();
|
|
||||||
|
|
||||||
if (!path.isEmpty()) {
|
|
||||||
// get next step to walk
|
|
||||||
PathStep step = path.poll();
|
|
||||||
position.walk(step.x, step.y, getStepTime());
|
|
||||||
} else {
|
|
||||||
// notify AI or whatever
|
|
||||||
if (pathEndListener != null) pathEndListener.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param world the world
|
|
||||||
* @param delta delta time
|
|
||||||
*/
|
|
||||||
public void updateVisual(WorldAccess world, double delta)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isPathFinished()
|
|
||||||
{
|
|
||||||
return position.isFinished() && path.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void addStep(PathStep step)
|
|
||||||
{
|
|
||||||
path.add(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void cancelPath()
|
|
||||||
{
|
|
||||||
path.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract double getStepTime();
|
|
||||||
|
|
||||||
public boolean isPhysical() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,19 +18,20 @@ import mightypork.util.math.Easing;
|
|||||||
*/
|
*/
|
||||||
public class WorldPos implements IonBundled, Updateable {
|
public class WorldPos implements IonBundled, Updateable {
|
||||||
|
|
||||||
public int x, y, floor;
|
public int x, y;
|
||||||
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
|
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
|
||||||
|
|
||||||
|
|
||||||
public WorldPos(int x, int y, int floor) {
|
public WorldPos(int x, int y)
|
||||||
|
{
|
||||||
super();
|
super();
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.floor = floor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public WorldPos() {
|
public WorldPos()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,7 +46,6 @@ public class WorldPos implements IonBundled, Updateable {
|
|||||||
{
|
{
|
||||||
x = in.get("x", 0);
|
x = in.get("x", 0);
|
||||||
y = in.get("y", 0);
|
y = in.get("y", 0);
|
||||||
floor = in.get("z", 0);
|
|
||||||
walkOffset.reset();
|
walkOffset.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,6 @@ public class WorldPos implements IonBundled, Updateable {
|
|||||||
{
|
{
|
||||||
out.put("x", x);
|
out.put("x", x);
|
||||||
out.put("y", y);
|
out.put("y", y);
|
||||||
out.put("z", floor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -71,12 +70,6 @@ public class WorldPos implements IonBundled, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public double getFloor()
|
|
||||||
{
|
|
||||||
return floor;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public double getVisualX()
|
public double getVisualX()
|
||||||
{
|
{
|
||||||
return x + walkOffset.x();
|
return x + walkOffset.x();
|
||||||
@@ -97,18 +90,9 @@ public class WorldPos implements IonBundled, Updateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTo(int x, int y, int floor)
|
|
||||||
{
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.floor = floor;
|
|
||||||
walkOffset.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setTo(WorldPos other)
|
public void setTo(WorldPos other)
|
||||||
{
|
{
|
||||||
setTo(other.x, other.y, other.floor);
|
setTo(other.x, other.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +101,6 @@ public class WorldPos implements IonBundled, Updateable {
|
|||||||
{
|
{
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + floor;
|
|
||||||
result = prime * result + x;
|
result = prime * result + x;
|
||||||
result = prime * result + y;
|
result = prime * result + y;
|
||||||
return result;
|
return result;
|
||||||
@@ -131,7 +114,6 @@ public class WorldPos implements IonBundled, Updateable {
|
|||||||
if (obj == null) return false;
|
if (obj == null) return false;
|
||||||
if (!(obj instanceof WorldPos)) return false;
|
if (!(obj instanceof WorldPos)) return false;
|
||||||
final WorldPos other = (WorldPos) obj;
|
final WorldPos other = (WorldPos) obj;
|
||||||
if (floor != other.floor) return false;
|
|
||||||
if (x != other.x) return false;
|
if (x != other.x) return false;
|
||||||
if (y != other.y) return false;
|
if (y != other.y) return false;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package mightypork.rogue.world.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.world.entity.models.EntityModel;
|
||||||
|
import mightypork.rogue.world.entity.models.PlayerModel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tile registry
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public final class Entities {
|
||||||
|
|
||||||
|
private static final EntityModel[] entities = new EntityModel[256];
|
||||||
|
|
||||||
|
public static final EntityModel PLAYER = new PlayerModel(0);
|
||||||
|
|
||||||
|
|
||||||
|
public static void register(int id, EntityModel model)
|
||||||
|
{
|
||||||
|
if (id < 0 || id >= entities.length) {
|
||||||
|
throw new IllegalArgumentException("Entity model ID " + id + " is out of range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entities[id] != null) {
|
||||||
|
throw new IllegalArgumentException("Entity model ID " + id + " already in use.");
|
||||||
|
}
|
||||||
|
|
||||||
|
entities[id] = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static EntityModel get(int id)
|
||||||
|
{
|
||||||
|
final EntityModel e = entities[id];
|
||||||
|
|
||||||
|
if (e == null) {
|
||||||
|
throw new IllegalArgumentException("No entity model with ID " + id + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
package mightypork.rogue.world.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
import mightypork.rogue.world.PathStep;
|
||||||
|
import mightypork.rogue.world.World;
|
||||||
|
import mightypork.rogue.world.WorldPos;
|
||||||
|
import mightypork.rogue.world.entity.models.EntityModel;
|
||||||
|
import mightypork.rogue.world.level.Level;
|
||||||
|
import mightypork.util.ion.IonBinary;
|
||||||
|
import mightypork.util.ion.IonBundle;
|
||||||
|
import mightypork.util.ion.IonBundled;
|
||||||
|
import mightypork.util.ion.IonInput;
|
||||||
|
import mightypork.util.ion.IonOutput;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* World entity (mob or player)
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public final class Entity implements IonBinary, IonBundled {
|
||||||
|
|
||||||
|
// binary & bundled - binary stores via a bundle
|
||||||
|
|
||||||
|
public static final int ION_MARK = 52;
|
||||||
|
|
||||||
|
private final WorldPos position = new WorldPos();
|
||||||
|
|
||||||
|
/** Entity ID */
|
||||||
|
private int eid = 0;
|
||||||
|
|
||||||
|
/** Model ID */
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private final Queue<PathStep> path = new LinkedList<>();
|
||||||
|
private EntityModel model;
|
||||||
|
private final IonBundle metadata = new IonBundle();
|
||||||
|
|
||||||
|
|
||||||
|
public Entity(int eid, WorldPos pos, EntityModel entityModel)
|
||||||
|
{
|
||||||
|
this.eid = eid;
|
||||||
|
this.position.setTo(pos);
|
||||||
|
|
||||||
|
setModel(entityModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setModel(EntityModel entityModel)
|
||||||
|
{
|
||||||
|
this.id = entityModel.id;
|
||||||
|
this.model = entityModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Entity()
|
||||||
|
{
|
||||||
|
// for ion
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getIonMark()
|
||||||
|
{
|
||||||
|
return ION_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonOutput out) throws IOException
|
||||||
|
{
|
||||||
|
final IonBundle ib = new IonBundle();
|
||||||
|
save(ib);
|
||||||
|
out.writeBundle(ib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonInput in) throws IOException
|
||||||
|
{
|
||||||
|
load(in.readBundle());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonBundle bundle) throws IOException
|
||||||
|
{
|
||||||
|
bundle.put("id", id);
|
||||||
|
bundle.putBundled("pos", position);
|
||||||
|
bundle.putSequence("steps", path);
|
||||||
|
bundle.put("eid", eid);
|
||||||
|
bundle.put("metadata", metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonBundle bundle) throws IOException
|
||||||
|
{
|
||||||
|
id = bundle.get("id", 0);
|
||||||
|
|
||||||
|
if (model == null || id != model.id) {
|
||||||
|
setModel(Entities.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle.loadBundled("pos", position);
|
||||||
|
bundle.loadSequence("path", path);
|
||||||
|
eid = bundle.get("eid", eid);
|
||||||
|
|
||||||
|
metadata.clear();
|
||||||
|
bundle.loadBundle("metadata", metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getEID()
|
||||||
|
{
|
||||||
|
return eid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public WorldPos getPosition()
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setPosition(WorldPos pos)
|
||||||
|
{
|
||||||
|
position.setTo(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setPosition(int x, int y)
|
||||||
|
{
|
||||||
|
position.setTo(x, y);
|
||||||
|
cancelPath(); // discard remaining steps
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param world the world
|
||||||
|
* @param delta delta time
|
||||||
|
*/
|
||||||
|
public void update(World world, Level level, double delta)
|
||||||
|
{
|
||||||
|
if (!position.isFinished()) {
|
||||||
|
position.update(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position.isFinished()) {
|
||||||
|
|
||||||
|
model.onStepFinished(this, world, level);
|
||||||
|
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
// get next step to walk
|
||||||
|
final PathStep step = path.poll();
|
||||||
|
position.walk(step.x, step.y, getStepTime());
|
||||||
|
} else {
|
||||||
|
// notify AI or whatever
|
||||||
|
model.onPathFinished(this, world, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isPathFinished()
|
||||||
|
{
|
||||||
|
return position.isFinished() && path.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addStep(PathStep step)
|
||||||
|
{
|
||||||
|
path.add(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void cancelPath()
|
||||||
|
{
|
||||||
|
path.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected double getStepTime()
|
||||||
|
{
|
||||||
|
return model.getStepTime(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package mightypork.rogue.world.entity.models;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.world.World;
|
||||||
|
import mightypork.rogue.world.WorldPos;
|
||||||
|
import mightypork.rogue.world.entity.Entities;
|
||||||
|
import mightypork.rogue.world.entity.Entity;
|
||||||
|
import mightypork.rogue.world.entity.renderers.EntityRenderer;
|
||||||
|
import mightypork.rogue.world.level.Level;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity model
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public abstract class EntityModel {
|
||||||
|
|
||||||
|
/** Model ID */
|
||||||
|
public final int id;
|
||||||
|
public EntityRenderer renderer = EntityRenderer.NONE;
|
||||||
|
|
||||||
|
|
||||||
|
public EntityModel(int id)
|
||||||
|
{
|
||||||
|
Entities.register(id, this);
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public EntityModel setRenderer(EntityRenderer renderer)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return new tile of this type; if 100% invariant, can return cached one.
|
||||||
|
*/
|
||||||
|
public Entity createEntity(int eid, WorldPos pos)
|
||||||
|
{
|
||||||
|
return new Entity(eid, pos, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update entity
|
||||||
|
*/
|
||||||
|
public abstract void update(Entity entity, Level level, double delta);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this entity type has metadata worth saving
|
||||||
|
*/
|
||||||
|
public abstract boolean hasMetadata();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param entity the value is valid for
|
||||||
|
* @return step time (seconds)
|
||||||
|
*/
|
||||||
|
public abstract double getStepTime(Entity entity);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void onStepFinished(Entity entity, World world, Level level);
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void onPathFinished(Entity entity, World world, Level level);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package mightypork.rogue.world.entity.models;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.world.World;
|
||||||
|
import mightypork.rogue.world.WorldPos;
|
||||||
|
import mightypork.rogue.world.entity.Entity;
|
||||||
|
import mightypork.rogue.world.level.Level;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player info
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class PlayerModel extends EntityModel {
|
||||||
|
|
||||||
|
private static final double STEP_TIME = 0.3;
|
||||||
|
|
||||||
|
|
||||||
|
public PlayerModel(int id)
|
||||||
|
{
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity createEntity(int eid, WorldPos pos)
|
||||||
|
{
|
||||||
|
final Entity e = super.createEntity(eid, pos);
|
||||||
|
|
||||||
|
// set metadata
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Entity entity, Level level, double delta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasMetadata()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getStepTime(Entity entity)
|
||||||
|
{
|
||||||
|
return STEP_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStepFinished(Entity entity, World world, Level level)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPathFinished(Entity entity, World world, Level level)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package mightypork.rogue.world.entity.renderers;
|
||||||
|
|
||||||
|
|
||||||
|
public class EntityRenderer {
|
||||||
|
|
||||||
|
public static final EntityRenderer NONE = new NullEntityRenderer();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package mightypork.rogue.world.entity.renderers;
|
||||||
|
|
||||||
|
|
||||||
|
public class NullEntityRenderer extends EntityRenderer {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ public class Item implements IonBinary {
|
|||||||
|
|
||||||
public static final short ION_MARK = 51;
|
public static final short ION_MARK = 51;
|
||||||
|
|
||||||
private transient ItemModel model;
|
private ItemModel model;
|
||||||
|
|
||||||
public int id;
|
public int id;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public final class Items {
|
|||||||
private static final ItemModel[] items = new ItemModel[256];
|
private static final ItemModel[] items = new ItemModel[256];
|
||||||
|
|
||||||
|
|
||||||
static void register(int id, ItemModel model)
|
public static void register(int id, ItemModel model)
|
||||||
{
|
{
|
||||||
if (id < 0 || id >= items.length) if (items[id] != null) throw new IllegalArgumentException("Item ID " + id + " already in use.");
|
if (id < 0 || id >= items.length) if (items[id] != null) throw new IllegalArgumentException("Item ID " + id + " already in use.");
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,330 @@
|
|||||||
|
package mightypork.rogue.world.level;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import mightypork.gamecore.render.Render;
|
||||||
|
import mightypork.rogue.Res;
|
||||||
|
import mightypork.rogue.world.PlayerInfo;
|
||||||
|
import mightypork.rogue.world.WorldPos;
|
||||||
|
import mightypork.rogue.world.entity.Entity;
|
||||||
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
|
import mightypork.rogue.world.tile.Tile;
|
||||||
|
import mightypork.rogue.world.tile.Tiles;
|
||||||
|
import mightypork.rogue.world.tile.models.TileModel;
|
||||||
|
import mightypork.util.constraints.rect.Rect;
|
||||||
|
import mightypork.util.constraints.rect.RectConst;
|
||||||
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
|
import mightypork.util.constraints.vect.VectConst;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One level of the dungeon
|
||||||
|
*
|
||||||
|
* @author MightyPork
|
||||||
|
*/
|
||||||
|
public class Level implements MapAccess, IonBinary {
|
||||||
|
|
||||||
|
public static final int ION_MARK = 53;
|
||||||
|
|
||||||
|
private static final boolean USE_BATCH_RENDERING = true;
|
||||||
|
|
||||||
|
private int width, height;
|
||||||
|
|
||||||
|
/** Array of tiles [y][x] */
|
||||||
|
private Tile[][] tiles;
|
||||||
|
|
||||||
|
private final Map<Integer, Entity> entity_map = new HashMap<>();
|
||||||
|
private final Set<Entity> entity_set = new HashSet<>();
|
||||||
|
|
||||||
|
/** Level seed (used for generation and tile variation) */
|
||||||
|
public long seed;
|
||||||
|
|
||||||
|
private transient NoiseGen noiseGen;
|
||||||
|
|
||||||
|
|
||||||
|
public Level()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Level(int width, int height)
|
||||||
|
{
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
buildArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void buildArray()
|
||||||
|
{
|
||||||
|
this.tiles = new Tile[height][width];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void fill(short id)
|
||||||
|
{
|
||||||
|
fill(Tiles.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void fill(TileModel model)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
tiles[y][x] = model.createTile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Tile getTile(int x, int y)
|
||||||
|
{
|
||||||
|
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
||||||
|
|
||||||
|
return tiles[y][x];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final void setTile(TileModel model, int x, int y)
|
||||||
|
{
|
||||||
|
setTile(model.createTile(), x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final void setTile(int tileId, int x, int y)
|
||||||
|
{
|
||||||
|
setTile(new Tile(tileId), x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final void setTile(Tile tile, int x, int y)
|
||||||
|
{
|
||||||
|
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
||||||
|
|
||||||
|
tiles[y][x] = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getWidth()
|
||||||
|
{
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getHeight()
|
||||||
|
{
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSeed(long seed)
|
||||||
|
{
|
||||||
|
this.seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSeed()
|
||||||
|
{
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(IonInput in) throws IOException
|
||||||
|
{
|
||||||
|
// metadata
|
||||||
|
final IonBundle ib = in.readBundle();
|
||||||
|
seed = ib.get("seed", 0L);
|
||||||
|
width = ib.get("w", 0);
|
||||||
|
height = ib.get("h", 0);
|
||||||
|
|
||||||
|
ib.loadSequence("entities", entity_set);
|
||||||
|
for (final Entity ent : entity_set) {
|
||||||
|
entity_map.put(ent.getEID(), ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init array of size
|
||||||
|
buildArray();
|
||||||
|
|
||||||
|
// load tiles
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
// no mark
|
||||||
|
tiles[y][x] = new Tile();
|
||||||
|
tiles[y][x].load(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(IonOutput out) throws IOException
|
||||||
|
{
|
||||||
|
// metadata
|
||||||
|
final IonBundle ib = new IonBundle();
|
||||||
|
ib.put("seed", seed);
|
||||||
|
ib.put("w", width);
|
||||||
|
ib.put("h", height);
|
||||||
|
ib.putSequence("entities", entity_set);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getIonMark()
|
||||||
|
{
|
||||||
|
return ION_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void update(double delta)
|
||||||
|
{
|
||||||
|
// just update them all
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
getTile(x, y).update(this, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NoiseGen getNoiseGen()
|
||||||
|
{
|
||||||
|
if (noiseGen == null) {
|
||||||
|
noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return noiseGen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw on screen
|
||||||
|
*
|
||||||
|
* @param playerInfo layer
|
||||||
|
* @param viewport rendering area on screen
|
||||||
|
* @param xTiles Desired nr of tiles horizontally
|
||||||
|
* @param yTiles Desired nr of tiles vertically
|
||||||
|
* @param minSize minimum tile size
|
||||||
|
*/
|
||||||
|
public void render(PlayerInfo playerInfo, RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
||||||
|
{
|
||||||
|
final WorldPos pos;
|
||||||
|
|
||||||
|
try {
|
||||||
|
pos = getEntity(playerInfo.getEID()).getPosition();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new RuntimeException("Player entity not found in level.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Rect r = viewport.getRect();
|
||||||
|
final double vpH = r.height().value();
|
||||||
|
final double vpW = r.width().value();
|
||||||
|
|
||||||
|
// adjust tile size to fit desired amount of tiles
|
||||||
|
|
||||||
|
final double allowedSizeW = vpW / xTiles;
|
||||||
|
final double allowedSizeH = vpH / yTiles;
|
||||||
|
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||||
|
|
||||||
|
tileSize -= tileSize % 16;
|
||||||
|
|
||||||
|
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||||
|
|
||||||
|
final double playerX = pos.getVisualX();
|
||||||
|
final double playerY = pos.getVisualY();
|
||||||
|
|
||||||
|
// total map area
|
||||||
|
//@formatter:off
|
||||||
|
final RectConst mapRect = vpCenter.startRect().grow(
|
||||||
|
playerX*tileSize,
|
||||||
|
(getWidth() - playerX) * tileSize,
|
||||||
|
playerY*tileSize,
|
||||||
|
(getHeight() - playerY) * tileSize
|
||||||
|
).freeze();
|
||||||
|
//@formatter:on
|
||||||
|
|
||||||
|
// tiles to render
|
||||||
|
final int x1 = (int) Math.floor(playerX - (vpW / tileSize / 2));
|
||||||
|
|
||||||
|
final int y1 = (int) Math.floor(playerY - (vpH / tileSize / 2));
|
||||||
|
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize / 2));
|
||||||
|
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize / 2));
|
||||||
|
|
||||||
|
final TileRenderContext trc = new TileRenderContext(this, mapRect); //-tileSize*0.5
|
||||||
|
|
||||||
|
// batch rendering of the tiles
|
||||||
|
if (USE_BATCH_RENDERING) {
|
||||||
|
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles"));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||||
|
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||||
|
trc.renderTile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (USE_BATCH_RENDERING) {
|
||||||
|
Render.leaveBatchTexturedQuadMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// render extras
|
||||||
|
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||||
|
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||||
|
trc.renderItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Entity getEntity(int eid)
|
||||||
|
{
|
||||||
|
return entity_map.get(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addEntity(Entity entity)
|
||||||
|
{
|
||||||
|
entity_map.put(entity.getEID(), entity);
|
||||||
|
entity_set.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void removeEntity(Entity entity)
|
||||||
|
{
|
||||||
|
entity_map.remove(entity.getEID());
|
||||||
|
entity_set.remove(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void removeEntity(int eid)
|
||||||
|
{
|
||||||
|
final Entity removed = entity_map.remove(eid);
|
||||||
|
entity_set.remove(removed);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package mightypork.rogue.world.map;
|
package mightypork.rogue.world.level;
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package mightypork.rogue.world.map;
|
package mightypork.rogue.world.level.render;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.world.level.MapAccess;
|
||||||
import mightypork.util.constraints.rect.Rect;
|
import mightypork.util.constraints.rect.Rect;
|
||||||
|
|
||||||
|
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package mightypork.rogue.world.map;
|
package mightypork.rogue.world.level.render;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.world.level.MapAccess;
|
||||||
import mightypork.util.constraints.rect.Rect;
|
import mightypork.util.constraints.rect.Rect;
|
||||||
import mightypork.util.constraints.rect.builders.TiledRect;
|
import mightypork.util.constraints.rect.builders.TiledRect;
|
||||||
|
|
||||||
+8
-3
@@ -1,6 +1,7 @@
|
|||||||
package mightypork.rogue.world.map;
|
package mightypork.rogue.world.level.render;
|
||||||
|
|
||||||
|
|
||||||
|
import mightypork.rogue.world.level.MapAccess;
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.util.constraints.rect.Rect;
|
import mightypork.util.constraints.rect.Rect;
|
||||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||||
@@ -60,11 +61,15 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void render()
|
public void renderTile()
|
||||||
{
|
{
|
||||||
map.getTile(x, y).render(this);
|
map.getTile(x, y).renderTile(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void renderItems()
|
||||||
|
{
|
||||||
|
map.getTile(x, y).renderItems(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rect of the current tile to draw
|
* Rect of the current tile to draw
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
package mightypork.rogue.world.map;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import mightypork.rogue.world.PlayerEntity;
|
|
||||||
import mightypork.rogue.world.WorldAccess;
|
|
||||||
import mightypork.rogue.world.WorldEntity;
|
|
||||||
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.ion.IonBinary;
|
|
||||||
import mightypork.util.ion.IonBundle;
|
|
||||||
import mightypork.util.ion.IonInput;
|
|
||||||
import mightypork.util.ion.IonOutput;
|
|
||||||
import mightypork.util.math.noise.NoiseGen;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* One level of the dungeon
|
|
||||||
*
|
|
||||||
* @author MightyPork
|
|
||||||
*/
|
|
||||||
public class Level implements MapAccess, IonBinary {
|
|
||||||
|
|
||||||
public static final int ION_MARK = 53;
|
|
||||||
|
|
||||||
private int width, height;
|
|
||||||
|
|
||||||
/** Array of tiles [y][x] */
|
|
||||||
private Tile[][] tiles;
|
|
||||||
|
|
||||||
private final List<WorldEntity> entities = new ArrayList<>();
|
|
||||||
|
|
||||||
/** Level seed (used for generation and tile variation) */
|
|
||||||
public long seed;
|
|
||||||
|
|
||||||
private transient NoiseGen noiseGen;
|
|
||||||
|
|
||||||
|
|
||||||
public Level()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Level(int width, int height)
|
|
||||||
{
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
buildArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void buildArray()
|
|
||||||
{
|
|
||||||
this.tiles = new Tile[height][width];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void fill(short id)
|
|
||||||
{
|
|
||||||
fill(Tiles.get(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void fill(TileModel model)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
tiles[y][x] = model.createTile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final Tile getTile(int x, int y)
|
|
||||||
{
|
|
||||||
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
|
||||||
|
|
||||||
return tiles[y][x];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public final void setTile(TileModel model, int x, int y)
|
|
||||||
{
|
|
||||||
setTile(model.createTile(), x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public final void setTile(int tileId, int x, int y)
|
|
||||||
{
|
|
||||||
setTile(new Tile(tileId), x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public final void setTile(Tile tile, int x, int y)
|
|
||||||
{
|
|
||||||
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
|
||||||
|
|
||||||
tiles[y][x] = tile;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int getWidth()
|
|
||||||
{
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final int getHeight()
|
|
||||||
{
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setSeed(long seed)
|
|
||||||
{
|
|
||||||
this.seed = seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getSeed()
|
|
||||||
{
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(IonInput in) throws IOException
|
|
||||||
{
|
|
||||||
// metadata
|
|
||||||
final IonBundle ib = in.readBundle();
|
|
||||||
seed = ib.get("seed", 0L);
|
|
||||||
width = ib.get("w", 0);
|
|
||||||
height = ib.get("h", 0);
|
|
||||||
|
|
||||||
ib.loadSequence("entities", entities);
|
|
||||||
|
|
||||||
// init array of size
|
|
||||||
buildArray();
|
|
||||||
|
|
||||||
// load tiles
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
// no mark
|
|
||||||
tiles[y][x] = new Tile();
|
|
||||||
tiles[y][x].load(in);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(IonOutput out) throws IOException
|
|
||||||
{
|
|
||||||
// metadata
|
|
||||||
final IonBundle ib = new IonBundle();
|
|
||||||
ib.put("seed", seed);
|
|
||||||
ib.put("w", width);
|
|
||||||
ib.put("h", height);
|
|
||||||
ib.putSequence("entities", entities);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short getIonMark()
|
|
||||||
{
|
|
||||||
return ION_MARK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void updateLogic(WorldAccess world, double delta)
|
|
||||||
{
|
|
||||||
if (!world.isServer()) {
|
|
||||||
throw new RuntimeException("Not allowed for client.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// just update them all
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
getTile(x, y).updateLogic(world, this, delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update visuals for player (particle effects etc)
|
|
||||||
*
|
|
||||||
* @param world
|
|
||||||
* @param player
|
|
||||||
* @param delta
|
|
||||||
*/
|
|
||||||
public void updateVisual(WorldAccess world, PlayerEntity player, double delta)
|
|
||||||
{
|
|
||||||
if (world.isServer()) {
|
|
||||||
throw new RuntimeException("Not allowed for server.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int viewRange = player.getViewRange();
|
|
||||||
final WorldPos eyepos = player.getViewPosition();
|
|
||||||
|
|
||||||
int x1 = eyepos.x - viewRange;
|
|
||||||
int y1 = eyepos.y - viewRange;
|
|
||||||
|
|
||||||
int x2 = x1 + viewRange * 2;
|
|
||||||
int y2 = y1 + viewRange * 2;
|
|
||||||
|
|
||||||
x1 = Math.min(Math.max(0, x1), width);
|
|
||||||
y1 = Math.min(Math.max(0, y1), height);
|
|
||||||
x2 = Math.min(x2, width);
|
|
||||||
y2 = Math.max(y2, height);
|
|
||||||
|
|
||||||
for (int y = y1; y <= y2; y++) {
|
|
||||||
for (int x = x1; x <= x2; x++) {
|
|
||||||
getTile(x, y).updateVisual(world, this, delta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NoiseGen getNoiseGen()
|
|
||||||
{
|
|
||||||
if (noiseGen == null) {
|
|
||||||
noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return noiseGen;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package mightypork.rogue.world.map;
|
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.WorldPos;
|
|
||||||
|
|
||||||
|
|
||||||
public interface MapObserver {
|
|
||||||
|
|
||||||
int getViewRange();
|
|
||||||
|
|
||||||
|
|
||||||
WorldPos getViewPosition();
|
|
||||||
}
|
|
||||||
@@ -2,12 +2,11 @@ package mightypork.rogue.world.tile;
|
|||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
import mightypork.util.constraints.rect.Rect;
|
import mightypork.util.constraints.rect.Rect;
|
||||||
import mightypork.util.constraints.rect.proxy.RectBoundAdapter;
|
import mightypork.util.constraints.rect.proxy.RectBoundAdapter;
|
||||||
import mightypork.util.control.timing.Animator;
|
import mightypork.util.control.timing.Animator;
|
||||||
import mightypork.util.control.timing.AnimatorBounce;
|
import mightypork.util.control.timing.AnimatorBounce;
|
||||||
import mightypork.util.control.timing.Updateable;
|
|
||||||
import mightypork.util.math.Easing;
|
import mightypork.util.math.Easing;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ package mightypork.rogue.world.tile;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import mightypork.rogue.world.WorldAccess;
|
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.map.Level;
|
import mightypork.rogue.world.level.Level;
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
import mightypork.util.control.timing.Animator;
|
import mightypork.rogue.world.tile.models.TileModel;
|
||||||
|
import mightypork.rogue.world.tile.renderers.TileRenderer;
|
||||||
import mightypork.util.ion.IonBinary;
|
import mightypork.util.ion.IonBinary;
|
||||||
import mightypork.util.ion.IonBundle;
|
import mightypork.util.ion.IonBundle;
|
||||||
import mightypork.util.ion.IonInput;
|
import mightypork.util.ion.IonInput;
|
||||||
@@ -27,16 +27,13 @@ public final class Tile implements IonBinary {
|
|||||||
private TileModel model;
|
private TileModel model;
|
||||||
private TileRenderer renderer;
|
private TileRenderer renderer;
|
||||||
|
|
||||||
public int id;
|
private int id;
|
||||||
|
|
||||||
private final Stack<Item> items = new Stack<>();
|
private final Stack<Item> items = new Stack<>();
|
||||||
|
|
||||||
/** persistent field for model, reflected by renderer */
|
/** persistent field for model, reflected by renderer */
|
||||||
public final IonBundle metadata = new IonBundle();
|
public final IonBundle metadata = new IonBundle();
|
||||||
|
|
||||||
/** non-persistent data field for model */
|
|
||||||
public Object tmpdata;
|
|
||||||
|
|
||||||
|
|
||||||
public Tile(int id)
|
public Tile(int id)
|
||||||
{
|
{
|
||||||
@@ -63,7 +60,10 @@ public final class Tile implements IonBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void render(TileRenderContext context)
|
/**
|
||||||
|
* Render the tile alone (must not use other than the main map texture)
|
||||||
|
*/
|
||||||
|
public void renderTile(TileRenderContext context)
|
||||||
{
|
{
|
||||||
renderer.render(context);
|
renderer.render(context);
|
||||||
|
|
||||||
@@ -73,6 +73,19 @@ public final class Tile implements IonBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render items
|
||||||
|
* @param context
|
||||||
|
*/
|
||||||
|
public void renderItems(TileRenderContext context)
|
||||||
|
{
|
||||||
|
if (hasItems()) {
|
||||||
|
renderer.renderItemOnTile(items.peek(), context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(IonOutput out) throws IOException
|
public void save(IonOutput out) throws IOException
|
||||||
{
|
{
|
||||||
@@ -82,7 +95,7 @@ public final class Tile implements IonBinary {
|
|||||||
out.writeSequence(items);
|
out.writeSequence(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.hasPersistentMetadata()) {
|
if (model.hasMetadata()) {
|
||||||
out.writeBundle(metadata);
|
out.writeBundle(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +115,7 @@ public final class Tile implements IonBinary {
|
|||||||
in.readSequence(items);
|
in.readSequence(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.hasPersistentMetadata()) {
|
if (model.hasMetadata()) {
|
||||||
in.readBundle(metadata);
|
in.readBundle(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,18 +124,12 @@ public final class Tile implements IonBinary {
|
|||||||
/**
|
/**
|
||||||
* Update tile logic state (on server)
|
* Update tile logic state (on server)
|
||||||
*
|
*
|
||||||
* @param world the world
|
* @param level the level
|
||||||
* @param delta delta time
|
* @param delta delta time
|
||||||
*/
|
*/
|
||||||
public void updateLogic(WorldAccess world, Level level, double delta)
|
public void update(Level level, double delta)
|
||||||
{
|
{
|
||||||
model.updateLogic(this, world, level, delta);
|
model.update(this, level, delta);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void updateVisual(WorldAccess world, Level level, double delta)
|
|
||||||
{
|
|
||||||
model.updateVisual(this, world, level, delta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package mightypork.rogue.world.tile;
|
|||||||
import mightypork.rogue.world.tile.models.Floor;
|
import mightypork.rogue.world.tile.models.Floor;
|
||||||
import mightypork.rogue.world.tile.models.NullFloor;
|
import mightypork.rogue.world.tile.models.NullFloor;
|
||||||
import mightypork.rogue.world.tile.models.NullWall;
|
import mightypork.rogue.world.tile.models.NullWall;
|
||||||
|
import mightypork.rogue.world.tile.models.TileModel;
|
||||||
import mightypork.rogue.world.tile.models.Wall;
|
import mightypork.rogue.world.tile.models.Wall;
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ public final class Tiles {
|
|||||||
public static final TileModel CRYSTAL_WALL = new Wall(11).setTexture("tile.wall.crystal");
|
public static final TileModel CRYSTAL_WALL = new Wall(11).setTexture("tile.wall.crystal");
|
||||||
|
|
||||||
|
|
||||||
static void register(int id, TileModel model)
|
public static void register(int id, TileModel model)
|
||||||
{
|
{
|
||||||
if (id < 0 || id >= tiles.length) {
|
if (id < 0 || id >= tiles.length) {
|
||||||
throw new IllegalArgumentException("Tile ID " + id + " is out of range.");
|
throw new IllegalArgumentException("Tile ID " + id + " is out of range.");
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public abstract class AbstractNullTile extends SimpleTile {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPersistentMetadata()
|
public boolean hasMetadata()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package mightypork.rogue.world.tile.models;
|
package mightypork.rogue.world.tile.models;
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.WorldAccess;
|
import mightypork.rogue.world.level.Level;
|
||||||
import mightypork.rogue.world.map.Level;
|
|
||||||
import mightypork.rogue.world.tile.Tile;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
import mightypork.rogue.world.tile.TileModel;
|
|
||||||
import mightypork.util.annotations.DefaultImpl;
|
import mightypork.util.annotations.DefaultImpl;
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ public abstract class SimpleTile extends TileModel {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPersistentMetadata()
|
public boolean hasMetadata()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -41,13 +39,7 @@ public abstract class SimpleTile extends TileModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@DefaultImpl
|
@DefaultImpl
|
||||||
public void updateLogic(Tile tile, WorldAccess world, Level level, double delta)
|
public void update(Tile tile, Level level, double delta)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@DefaultImpl
|
|
||||||
public void updateVisual(Tile tile, WorldAccess world, Level level, double delta)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-12
@@ -1,9 +1,11 @@
|
|||||||
package mightypork.rogue.world.tile;
|
package mightypork.rogue.world.tile.models;
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.WorldAccess;
|
import mightypork.rogue.world.level.Level;
|
||||||
import mightypork.rogue.world.map.Level;
|
import mightypork.rogue.world.tile.Tile;
|
||||||
|
import mightypork.rogue.world.tile.Tiles;
|
||||||
import mightypork.rogue.world.tile.renderers.BasicTileRenderer;
|
import mightypork.rogue.world.tile.renderers.BasicTileRenderer;
|
||||||
|
import mightypork.rogue.world.tile.renderers.TileRenderer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,21 +70,15 @@ public abstract class TileModel {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update tile in world, called by server
|
* Update tile in world
|
||||||
*/
|
*/
|
||||||
public abstract void updateLogic(Tile tile, WorldAccess world, Level level, double delta);
|
public abstract void update(Tile tile, Level level, double delta);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update tile visuals (particles / update for renderer)
|
|
||||||
*/
|
|
||||||
public abstract void updateVisual(Tile tile, WorldAccess world, Level level, double delta);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this item type has metadata worth saving
|
* @return true if this item type has metadata worth saving
|
||||||
*/
|
*/
|
||||||
public abstract boolean hasPersistentMetadata();
|
public abstract boolean hasMetadata();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4,13 +4,12 @@ package mightypork.rogue.world.tile.renderers;
|
|||||||
import mightypork.gamecore.render.Render;
|
import mightypork.gamecore.render.Render;
|
||||||
import mightypork.gamecore.render.textures.TxSheet;
|
import mightypork.gamecore.render.textures.TxSheet;
|
||||||
import mightypork.rogue.Res;
|
import mightypork.rogue.Res;
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
import mightypork.rogue.world.tile.TileRenderer;
|
|
||||||
|
|
||||||
|
|
||||||
public class BasicTileRenderer extends TileRenderer {
|
public class BasicTileRenderer extends TileRenderer {
|
||||||
|
|
||||||
private TxSheet sheet;
|
private final TxSheet sheet;
|
||||||
|
|
||||||
|
|
||||||
public BasicTileRenderer(String sheetKey)
|
public BasicTileRenderer(String sheetKey)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package mightypork.rogue.world.tile.renderers;
|
package mightypork.rogue.world.tile.renderers;
|
||||||
|
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
|
||||||
import mightypork.rogue.world.tile.TileRenderer;
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
|
|
||||||
|
|
||||||
public class NullTileRenderer extends TileRenderer {
|
public class NullTileRenderer extends TileRenderer {
|
||||||
|
|||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
package mightypork.rogue.world.tile;
|
package mightypork.rogue.world.tile.renderers;
|
||||||
|
|
||||||
|
|
||||||
import mightypork.rogue.world.item.Item;
|
import mightypork.rogue.world.item.Item;
|
||||||
import mightypork.rogue.world.map.TileRenderContext;
|
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||||
import mightypork.rogue.world.tile.renderers.NullTileRenderer;
|
import mightypork.rogue.world.tile.DroppedItemRenderer;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +42,29 @@ public class IonBundle implements IonBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void loadBundle(String key, IonBundle bundle)
|
||||||
|
{
|
||||||
|
if (!containsKey(key)) return;
|
||||||
|
|
||||||
|
final IonBundle ib = get(key, null);
|
||||||
|
|
||||||
|
bundle.clear();
|
||||||
|
bundle.putAll(ib);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean containsKey(Object key)
|
||||||
|
{
|
||||||
|
return backingMap.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean containsValue(Object value)
|
||||||
|
{
|
||||||
|
return backingMap.containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public <K, V> Map<K, V> getMap(String key)
|
public <K, V> Map<K, V> getMap(String key)
|
||||||
{
|
{
|
||||||
final Map<K, V> m = new HashMap<>();
|
final Map<K, V> m = new HashMap<>();
|
||||||
@@ -50,12 +73,12 @@ public class IonBundle implements IonBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public <K, V> void loadMap(String key, Map<K, V> map)
|
public <K, V> void loadMap(String key, Map<K, V> filled)
|
||||||
{
|
{
|
||||||
final IonMapWrapper imw = get(key, null);
|
final IonMapWrapper imw = get(key, null);
|
||||||
if (imw == null) return;
|
if (imw == null) return;
|
||||||
map.clear();
|
filled.clear();
|
||||||
imw.fill(map);
|
imw.fill(filled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -67,12 +90,12 @@ public class IonBundle implements IonBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public <E> void loadSequence(String key, Collection<E> sequence)
|
public <E> void loadSequence(String key, Collection<E> filled)
|
||||||
{
|
{
|
||||||
final IonSequenceWrapper isw = get(key, null);
|
final IonSequenceWrapper isw = get(key, null);
|
||||||
if (isw == null) return;
|
if (isw == null) return;
|
||||||
sequence.clear();
|
filled.clear();
|
||||||
isw.fill(sequence);
|
isw.fill(filled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -262,6 +285,12 @@ public class IonBundle implements IonBinary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void putAll(IonBundle otherBundle)
|
||||||
|
{
|
||||||
|
backingMap.putAll(otherBundle.backingMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ public class IonInput {
|
|||||||
*/
|
*/
|
||||||
public IonBundle readBundle() throws IOException
|
public IonBundle readBundle() throws IOException
|
||||||
{
|
{
|
||||||
IonBundle ib = new IonBundle();
|
final IonBundle ib = new IonBundle();
|
||||||
ib.load(this);
|
ib.load(this);
|
||||||
return ib;
|
return ib;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ public class IonOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj instanceof IonBundled) {
|
if (obj instanceof IonBundled) {
|
||||||
throw new IOException("Bundled objects cannot be written to ION stream directly.");
|
throw new IOException("Bundled objects cannot be written to ION stream directly at " + obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj instanceof Boolean) {
|
if (obj instanceof Boolean) {
|
||||||
|
|||||||
Reference in New Issue
Block a user