New 16px textures, player sprite, entity system.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 835 B |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
@@ -5,11 +5,9 @@ import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.gamecore.audio.players.EffectPlayer;
|
||||
import mightypork.gamecore.render.textures.FilterMode;
|
||||
import mightypork.gamecore.render.textures.GLTexture;
|
||||
import mightypork.gamecore.render.textures.TxQuad;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.caching.RectDigest;
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
@@ -426,72 +424,6 @@ public class Render {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render textured rect
|
||||
*
|
||||
* @param quad rectangle (px)
|
||||
* @param uvs texture coords rectangle (0-1)
|
||||
* @param texture texture instance
|
||||
* @param tint color tint
|
||||
*/
|
||||
public static void quadTextured(Rect quad, Rect uvs, GLTexture texture, Color tint)
|
||||
{
|
||||
if (!batchTexturedQuadMode) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
texture.bind();
|
||||
glBegin(GL_QUADS);
|
||||
}
|
||||
|
||||
setColor(tint);
|
||||
|
||||
final RectDigest q = quad.digest();
|
||||
final RectDigest u = uvs.digest();
|
||||
|
||||
final double w = texture.getWidth01();
|
||||
final double h = texture.getHeight01();
|
||||
|
||||
// quad with texture
|
||||
glTexCoord2d(u.x * w, u.bottom * h);
|
||||
glVertex2d(q.left, q.bottom);
|
||||
|
||||
glTexCoord2d(u.right * w, u.bottom * h);
|
||||
glVertex2d(q.right, q.bottom);
|
||||
|
||||
glTexCoord2d(u.right * w, u.top * h);
|
||||
glVertex2d(q.right, q.top);
|
||||
|
||||
glTexCoord2d(u.left * w, u.top * h);
|
||||
glVertex2d(q.left, q.top);
|
||||
|
||||
if (!batchTexturedQuadMode) glEnd();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render textured rect
|
||||
*
|
||||
* @param quad rectangle (px)
|
||||
* @param uvs texture coords rectangle (px)
|
||||
* @param texture texture instance
|
||||
*/
|
||||
public static void quadTextured(Rect quad, Rect uvs, GLTexture texture)
|
||||
{
|
||||
quadTextured(quad, uvs, texture, Color.WHITE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render textured rect
|
||||
*
|
||||
* @param quad rectangle (px)
|
||||
* @param texture texture instance
|
||||
*/
|
||||
public static void quadTextured(Rect quad, GLTexture texture)
|
||||
{
|
||||
quadTextured(quad, Rect.ONE, texture, Color.WHITE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render textured rect
|
||||
*
|
||||
@@ -513,7 +445,49 @@ public class Render {
|
||||
*/
|
||||
public static void quadTextured(Rect quad, TxQuad txquad, Color tint)
|
||||
{
|
||||
quadTextured(quad, txquad.uvs, txquad.tx, tint);
|
||||
if (!batchTexturedQuadMode) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
txquad.tx.bind();
|
||||
glBegin(GL_QUADS);
|
||||
}
|
||||
|
||||
setColor(tint);
|
||||
|
||||
final RectDigest q = quad.digest();
|
||||
final RectDigest u = txquad.uvs.digest();
|
||||
|
||||
double tL = u.left, tR = u.right, tT = u.top, tB = u.bottom;
|
||||
|
||||
// handle flip
|
||||
if (txquad.isFlippedY()) {
|
||||
final double swap = tT;
|
||||
tT = tB;
|
||||
tB = swap;
|
||||
}
|
||||
|
||||
if (txquad.isFlippedX()) {
|
||||
final double swap = tL;
|
||||
tL = tR;
|
||||
tR = swap;
|
||||
}
|
||||
|
||||
final double w = txquad.tx.getWidth01();
|
||||
final double h = txquad.tx.getHeight01();
|
||||
|
||||
// quad with texture
|
||||
glTexCoord2d(tL * w, tB * h);
|
||||
glVertex2d(q.left, q.bottom);
|
||||
|
||||
glTexCoord2d(tR * w, tB * h);
|
||||
glVertex2d(q.right, q.bottom);
|
||||
|
||||
glTexCoord2d(tR * w, tT * h);
|
||||
glVertex2d(q.right, q.top);
|
||||
|
||||
glTexCoord2d(tL * w, tT * h);
|
||||
glVertex2d(q.left, q.top);
|
||||
|
||||
if (!batchTexturedQuadMode) glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ public class Screenshot {
|
||||
*/
|
||||
public void save(File file) throws IOException
|
||||
{
|
||||
file.getParentFile().mkdirs();
|
||||
ImageIO.write(getImage(), "PNG", file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ public class TxQuad {
|
||||
/** Coords in texture (0-1) */
|
||||
public final RectConst uvs;
|
||||
|
||||
private boolean flipX;
|
||||
private boolean flipY;
|
||||
|
||||
|
||||
/**
|
||||
* TxQuad from origin and size in pixels
|
||||
@@ -88,6 +91,8 @@ public class TxQuad {
|
||||
{
|
||||
this.tx = txQuad.tx;
|
||||
this.uvs = txQuad.uvs;
|
||||
this.flipX = txQuad.flipX;
|
||||
this.flipY = txQuad.flipY;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,4 +118,38 @@ public class TxQuad {
|
||||
{
|
||||
return new TxSheet(this, width, height);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return copy flipped X
|
||||
*/
|
||||
public TxQuad flipX()
|
||||
{
|
||||
final TxQuad copy = new TxQuad(this);
|
||||
copy.flipX ^= true;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return copy flipped Y
|
||||
*/
|
||||
public TxQuad flipY()
|
||||
{
|
||||
final TxQuad copy = new TxQuad(this);
|
||||
copy.flipY ^= true;
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
public boolean isFlippedY()
|
||||
{
|
||||
return flipY;
|
||||
}
|
||||
|
||||
|
||||
public boolean isFlippedX()
|
||||
{
|
||||
return flipX;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package mightypork.gamecore.render.textures;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.util.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
* Basic sprite sheet
|
||||
@@ -39,6 +41,18 @@ public class TxSheet {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a quad based on ratio 0-1 (0: first, 1: last)
|
||||
*
|
||||
* @param ratio ratio
|
||||
* @return quad
|
||||
*/
|
||||
public TxQuad getQuad(double ratio)
|
||||
{
|
||||
return getQuad((int) Math.round((count - 1) * ratio));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get quad of index
|
||||
*
|
||||
@@ -47,8 +61,9 @@ public class TxSheet {
|
||||
*/
|
||||
public TxQuad getQuad(int index)
|
||||
{
|
||||
if (index < 0 || index > count) {
|
||||
throw new IndexOutOfBoundsException("Index out of bounds: " + index + ", allowed: 0.." + count);
|
||||
if (index < 0 || index >= count) {
|
||||
Log.w("Index out of bounds: " + index + ", allowed: 0.." + count);
|
||||
index = index % count;
|
||||
}
|
||||
|
||||
// lazy - init only when needed
|
||||
|
||||
@@ -61,10 +61,13 @@ public final class Res {
|
||||
private static void loadTextures()
|
||||
{
|
||||
GLTexture texture;
|
||||
QuadGrid tiles;
|
||||
|
||||
// tests
|
||||
texture = textures.loadTexture("test.kitten", "/res/img/kitten.png", FilterMode.LINEAR, WrapMode.CLAMP);
|
||||
texture = textures.loadTexture("test.kitten2", "/res/img/kitten_npot.png", FilterMode.LINEAR, WrapMode.CLAMP);
|
||||
|
||||
// gui
|
||||
texture = textures.loadTexture("gui1", "/res/img/gui1.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
final QuadGrid gui = texture.grid(4, 4);
|
||||
textures.addQuad("item_frame", gui.makeQuad(0, 0));
|
||||
@@ -76,19 +79,41 @@ public final class Res {
|
||||
textures.addQuad("xp_off", gui.makeQuad(.5, 1.5, .5, .5));
|
||||
textures.addQuad("panel", gui.makeQuad(0, 3.75, 4, .25));
|
||||
|
||||
texture = textures.loadTexture("tiles", "/res/img/tiles.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
final QuadGrid tiles = texture.grid(32, 32);
|
||||
// huge sheet
|
||||
// texture = textures.loadTexture("tiles", "/res/img/tiles.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
// tiles = texture.grid(32, 32);
|
||||
// textures.addSheet("tile.wall.mossy_bricks", tiles.makeSheet(4, 0, 7, 1));
|
||||
// textures.addSheet("tile.wall.small_bricks", tiles.makeSheet(0, 0, 4, 1));
|
||||
// textures.addSheet("tile.floor.mossy_bricks", tiles.makeSheet(16, 5, 7, 1));
|
||||
// textures.addSheet("tile.floor.rect_bricks", tiles.makeSheet(23, 5, 4, 1));
|
||||
// textures.addSheet("tile.wall.sandstone", tiles.makeSheet(0, 3, 10, 1));
|
||||
// textures.addSheet("tile.floor.sandstone", tiles.makeSheet(0, 6, 10, 1));
|
||||
// textures.addSheet("tile.wall.brown_cobble", tiles.makeSheet(0, 8, 8, 1));
|
||||
// textures.addSheet("tile.floor.brown_cobble", tiles.makeSheet(0, 11, 9, 1));
|
||||
// textures.addSheet("tile.floor.crystal", tiles.makeSheet(4, 5, 6, 1));
|
||||
// textures.addSheet("tile.wall.crystal", tiles.makeSheet(12, 2, 14, 1));
|
||||
|
||||
textures.addSheet("tile.wall.mossy_bricks", tiles.makeSheet(4, 0, 7, 1));
|
||||
textures.addSheet("tile.wall.small_bricks", tiles.makeSheet(0, 0, 4, 1));
|
||||
textures.addSheet("tile.floor.mossy_bricks", tiles.makeSheet(16, 5, 7, 1));
|
||||
textures.addSheet("tile.floor.rect_bricks", tiles.makeSheet(23, 5, 4, 1));
|
||||
textures.addSheet("tile.wall.sandstone", tiles.makeSheet(0, 3, 10, 1));
|
||||
textures.addSheet("tile.floor.sandstone", tiles.makeSheet(0, 6, 10, 1));
|
||||
textures.addSheet("tile.wall.brown_cobble", tiles.makeSheet(0, 8, 8, 1));
|
||||
textures.addSheet("tile.floor.brown_cobble", tiles.makeSheet(0, 11, 9, 1));
|
||||
textures.addSheet("tile.floor.crystal", tiles.makeSheet(4, 5, 6, 1));
|
||||
textures.addSheet("tile.wall.crystal", tiles.makeSheet(12, 2, 14, 1));
|
||||
// sprites
|
||||
texture = textures.loadTexture("mob", "/res/img/dudes.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
tiles = texture.grid(8, 8);
|
||||
textures.addSheet("player", tiles.makeSheet(0, 0, 4, 1));
|
||||
|
||||
// small sheet
|
||||
texture = textures.loadTexture("tiles16", "/res/img/tiles16.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
tiles = texture.grid(8, 8);
|
||||
|
||||
textures.addSheet("tile16.floor.dark", tiles.makeSheet(0, 1, 5, 1));
|
||||
textures.addSheet("tile16.wall.brick", tiles.makeSheet(0, 0, 5, 1));
|
||||
|
||||
textures.addQuad("tile16.shadow.n", tiles.makeQuad(0, 7));
|
||||
textures.addQuad("tile16.shadow.s", tiles.makeQuad(0, 7).flipY());
|
||||
textures.addQuad("tile16.shadow.w", tiles.makeQuad(2, 7));
|
||||
textures.addQuad("tile16.shadow.e", tiles.makeQuad(2, 7).flipX());
|
||||
|
||||
textures.addQuad("tile16.shadow.nw", tiles.makeQuad(1, 7));
|
||||
textures.addQuad("tile16.shadow.ne", tiles.makeQuad(1, 7).flipX());
|
||||
textures.addQuad("tile16.shadow.sw", tiles.makeQuad(1, 7).flipY());
|
||||
textures.addQuad("tile16.shadow.se", tiles.makeQuad(1, 7).flipY().flipX());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,9 +7,16 @@ 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.Paths;
|
||||
import mightypork.rogue.world.MapGenerator;
|
||||
import mightypork.rogue.world.PlayerControl;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.util.ion.Ion;
|
||||
|
||||
|
||||
@@ -46,63 +53,81 @@ public class WorldLayer extends ScreenLayer {
|
||||
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);
|
||||
// }
|
||||
// });
|
||||
// bindKey(new KeyStroke(true, Keys.SPACE), new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// w.getPlayer().walk(5, 5);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// w.getPlayer().setMoveListener(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);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
final PlayerControl c = w.getPlayerControl();
|
||||
|
||||
bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
c.walkWest();
|
||||
}
|
||||
});
|
||||
|
||||
bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
c.walkEast();
|
||||
}
|
||||
});
|
||||
|
||||
bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
c.walkNorth();
|
||||
}
|
||||
});
|
||||
|
||||
bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
c.walkSouth();
|
||||
}
|
||||
});
|
||||
|
||||
c.addMoveListener(new EntityMoveListener() {
|
||||
|
||||
private void tryGo(Entity entity)
|
||||
{
|
||||
if (InputSystem.isKeyDown(Keys.LEFT)) {
|
||||
c.walkWest();
|
||||
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
||||
c.walkEast();
|
||||
} else if (InputSystem.isKeyDown(Keys.UP)) {
|
||||
c.walkNorth();
|
||||
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
||||
c.walkSouth();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
entity.cancelPath(); // halt
|
||||
tryGo(entity);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
entity.cancelPath(); // halt
|
||||
tryGo(entity);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathAborted(Entity entity, World world, Level level)
|
||||
{
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public class WorldRenderer extends InputComponent implements Updateable {
|
||||
@Override
|
||||
protected void renderComponent()
|
||||
{
|
||||
world.render(this, 8, 6, 64);
|
||||
world.render(this, 8, 6, 110);
|
||||
|
||||
Render.quadGradH(leftShadow, RGB.BLACK, RGB.NONE);
|
||||
Render.quadGradH(rightShadow, RGB.NONE, RGB.BLACK);
|
||||
|
||||
@@ -21,8 +21,8 @@ public class MapGenerator {
|
||||
final World w = new World();
|
||||
w.setSeed(seed);
|
||||
|
||||
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.FLOOR_DARK, Tiles.WALL_BRICK));
|
||||
//w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
||||
|
||||
// TODO place on start position
|
||||
w.createPlayer(10, 10, 0);
|
||||
|
||||
@@ -10,6 +10,37 @@ import mightypork.util.ion.IonOutput;
|
||||
|
||||
public class PathStep implements IonBinary {
|
||||
|
||||
public static final PathStep NORTH = new PathStep(0, -1);
|
||||
public static final PathStep SOUTH = new PathStep(0, 1);
|
||||
public static final PathStep EAST = new PathStep(1, 0);
|
||||
public static final PathStep WEST = new PathStep(-1, 0);
|
||||
public static final PathStep NORTH_EAST = new PathStep(1, -1);
|
||||
public static final PathStep NORTH_WEST = new PathStep(-1, -1);
|
||||
public static final PathStep SOUTH_EAST = new PathStep(1, 1);
|
||||
public static final PathStep SOUTH_WEST = new PathStep(-1, 1);
|
||||
public static final PathStep NONE = new PathStep(0, 0);
|
||||
|
||||
|
||||
public static PathStep make(int x, int y)
|
||||
{
|
||||
x = x < 0 ? -1 : x > 0 ? 1 : 0;
|
||||
y = y < 0 ? -1 : y > 0 ? 1 : 0;
|
||||
|
||||
if (x == 0 && y == -1) return NORTH;
|
||||
if (x == 0 && y == 1) return SOUTH;
|
||||
if (x == -1 && y == 0) return WEST;
|
||||
if (x == 1 && y == 0) return EAST;
|
||||
|
||||
if (x == -1 && y == -1) return NORTH_WEST;
|
||||
if (x == 1 && y == -1) return NORTH_EAST;
|
||||
if (x == -1 && y == 1) return SOUTH_WEST;
|
||||
if (x == 1 && y == 1) return SOUTH_EAST;
|
||||
|
||||
if (x == 0 && y == 0) return NONE;
|
||||
|
||||
return new PathStep(x, y);
|
||||
}
|
||||
|
||||
public static final int ION_MARK = 0;
|
||||
|
||||
public int x;
|
||||
@@ -18,10 +49,8 @@ public class PathStep implements IonBinary {
|
||||
|
||||
public PathStep(int x, int y)
|
||||
{
|
||||
this.x = x < 1 ? -1 : x > 0 ? 1 : 0;
|
||||
this.y = y < 1 ? -1 : y > 0 ? 1 : 0;
|
||||
|
||||
y = (int) Math.signum(x);
|
||||
this.x = x < 0 ? -1 : x > 0 ? 1 : 0;
|
||||
this.y = y < 0 ? -1 : y > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.models.EntityMoveListener;
|
||||
|
||||
|
||||
public class PlayerControl {
|
||||
|
||||
private final World world;
|
||||
|
||||
|
||||
public PlayerControl(World w)
|
||||
{
|
||||
this.world = w;
|
||||
}
|
||||
|
||||
|
||||
public void walkNorth()
|
||||
{
|
||||
world.playerEntity.addStep(PathStep.NORTH);
|
||||
}
|
||||
|
||||
|
||||
public void walkSouth()
|
||||
{
|
||||
world.playerEntity.addStep(PathStep.SOUTH);
|
||||
}
|
||||
|
||||
|
||||
public void walkEast()
|
||||
{
|
||||
world.playerEntity.addStep(PathStep.EAST);
|
||||
}
|
||||
|
||||
|
||||
public void walkWest()
|
||||
{
|
||||
world.playerEntity.addStep(PathStep.WEST);
|
||||
}
|
||||
|
||||
|
||||
public void addMoveListener(EntityMoveListener eml)
|
||||
{
|
||||
world.playerEntity.addMoveListener(eml);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,10 @@ public class World implements IonBundled, Updateable {
|
||||
|
||||
private final ArrayList<Level> levels = new ArrayList<>();
|
||||
|
||||
private final PlayerInfo player = new PlayerInfo();
|
||||
final PlayerInfo player = new PlayerInfo();
|
||||
Entity playerEntity;
|
||||
|
||||
private final PlayerControl control = new PlayerControl(this);
|
||||
|
||||
private long seed; // world seed
|
||||
private int eid; // next entity ID
|
||||
@@ -57,7 +60,7 @@ public class World implements IonBundled, Updateable {
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
getCurrentLevel().update(delta);
|
||||
getCurrentLevel().update(this, delta);
|
||||
}
|
||||
|
||||
|
||||
@@ -89,14 +92,14 @@ public class World implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
// make entity
|
||||
int playerEid = getNewEID();
|
||||
final int playerEid = getNewEID();
|
||||
|
||||
final Entity entity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y));
|
||||
playerEntity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y));
|
||||
|
||||
player.setLevel(level);
|
||||
player.setEID(playerEid);
|
||||
|
||||
levels.get(level).addEntity(entity);
|
||||
levels.get(level).addEntity(playerEntity);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,9 +111,9 @@ public class World implements IonBundled, Updateable {
|
||||
* @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)
|
||||
public void render(RectBound viewport, final int xTiles, final int yTiles, final int minSize)
|
||||
{
|
||||
getCurrentLevel().render(player, viewport, yTiles, xTiles, minSize);
|
||||
getCurrentLevel().render(playerEntity.getPosition(), viewport, xTiles, yTiles, minSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -118,4 +121,10 @@ public class World implements IonBundled, Updateable {
|
||||
{
|
||||
return levels.get(player.getLevel());
|
||||
}
|
||||
|
||||
|
||||
public PlayerControl getPlayerControl()
|
||||
{
|
||||
return control;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,18 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public double getVisualXOffset()
|
||||
{
|
||||
return walkOffset.x();
|
||||
}
|
||||
|
||||
|
||||
public double getVisualYOffset()
|
||||
{
|
||||
return walkOffset.y();
|
||||
}
|
||||
|
||||
|
||||
public void setTo(int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
|
||||
@@ -2,14 +2,18 @@ package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
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.entity.models.EntityMoveListener;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
@@ -22,23 +26,32 @@ import mightypork.util.ion.IonOutput;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class Entity implements IonBinary, IonBundled {
|
||||
public final class Entity implements IonBinary, IonBundled, EntityMoveListener {
|
||||
|
||||
// binary & bundled - binary stores via a bundle
|
||||
|
||||
public static final int ION_MARK = 52;
|
||||
|
||||
private final WorldPos position = new WorldPos();
|
||||
private final WorldPos position = new WorldPos(); // saved
|
||||
|
||||
/** Entity ID */
|
||||
private int eid = 0;
|
||||
private int eid = 0; // saved
|
||||
|
||||
/** Model ID */
|
||||
private int id;
|
||||
private int id; // saved
|
||||
|
||||
private final Queue<PathStep> path = new LinkedList<>();
|
||||
private final Queue<PathStep> path = new LinkedList<>(); // saved
|
||||
private EntityModel model;
|
||||
private final IonBundle metadata = new IonBundle();
|
||||
public final IonBundle metadata = new IonBundle(); // saved
|
||||
public final IonBundle tmpdata = new IonBundle(); // NOT saved
|
||||
|
||||
// used for rendering "facing" sprite
|
||||
public int lastXMove = 1;
|
||||
public int lastYMove = 1;
|
||||
|
||||
private final List<EntityMoveListener> moveListeners = new ArrayList<>();
|
||||
|
||||
private boolean walking = false;
|
||||
|
||||
|
||||
public Entity(int eid, WorldPos pos, EntityModel entityModel)
|
||||
@@ -52,6 +65,10 @@ public final class Entity implements IonBinary, IonBundled {
|
||||
|
||||
private void setModel(EntityModel entityModel)
|
||||
{
|
||||
// replace listener
|
||||
if (model != null) moveListeners.remove(model);
|
||||
moveListeners.add(entityModel);
|
||||
|
||||
this.id = entityModel.id;
|
||||
this.model = entityModel;
|
||||
}
|
||||
@@ -93,8 +110,11 @@ public final class Entity implements IonBinary, IonBundled {
|
||||
bundle.putBundled("pos", position);
|
||||
bundle.putSequence("steps", path);
|
||||
bundle.put("eid", eid);
|
||||
|
||||
if (model.hasMetadata()) {
|
||||
bundle.put("metadata", metadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@@ -110,11 +130,16 @@ public final class Entity implements IonBinary, IonBundled {
|
||||
bundle.loadSequence("path", path);
|
||||
eid = bundle.get("eid", eid);
|
||||
|
||||
if (model.hasMetadata()) {
|
||||
metadata.clear();
|
||||
bundle.loadBundle("metadata", metadata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return unique entity id
|
||||
*/
|
||||
public int getEID()
|
||||
{
|
||||
return eid;
|
||||
@@ -150,19 +175,49 @@ public final class Entity implements IonBinary, IonBundled {
|
||||
position.update(delta);
|
||||
}
|
||||
|
||||
if (position.isFinished()) {
|
||||
if (walking && position.isFinished()) {
|
||||
walking = false;
|
||||
|
||||
model.onStepFinished(this, world, level);
|
||||
onStepFinished(this, world, level);
|
||||
|
||||
if (path.isEmpty()) {
|
||||
onPathFinished(this, world, level);
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking && !path.isEmpty()) {
|
||||
|
||||
walking = true;
|
||||
|
||||
if (!path.isEmpty()) {
|
||||
// get next step to walk
|
||||
final PathStep step = path.poll();
|
||||
position.walk(step.x, step.y, getStepTime());
|
||||
|
||||
final int projX = position.x + step.x, projY = position.y + step.y;
|
||||
|
||||
if (!level.canWalkInto(projX, projY)) {
|
||||
cancelPath();
|
||||
onPathAborted(this, world, level);
|
||||
walking = false;
|
||||
} else {
|
||||
// notify AI or whatever
|
||||
model.onPathFinished(this, world, level);
|
||||
|
||||
// tmp for renderer
|
||||
if (step.x != 0) lastXMove = step.x;
|
||||
if (step.y != 0) lastYMove = step.y;
|
||||
|
||||
position.walk(step.x, step.y, getStepTime());
|
||||
level.occupyTile(projX, projY);
|
||||
level.freeTile(position.x, position.y);
|
||||
}
|
||||
}
|
||||
|
||||
if (!walking) {
|
||||
model.update(this, level, delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void render(EntityRenderContext context)
|
||||
{
|
||||
model.renderer.render(this, context);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,4 +244,36 @@ public final class Entity implements IonBinary, IonBundled {
|
||||
return model.getStepTime(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onStepFinished(entity, world, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onStepFinished(entity, world, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathAborted(Entity entity, World world, Level level)
|
||||
{
|
||||
for (final EntityMoveListener l : moveListeners) {
|
||||
l.onPathAborted(entity, world, level);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addMoveListener(EntityMoveListener listener)
|
||||
{
|
||||
moveListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import mightypork.rogue.world.level.Level;
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class EntityModel {
|
||||
public abstract class EntityModel implements EntityMoveListener {
|
||||
|
||||
/** Model ID */
|
||||
public final int id;
|
||||
@@ -45,7 +45,7 @@ public abstract class EntityModel {
|
||||
|
||||
|
||||
/**
|
||||
* Update entity
|
||||
* Entity is idle, waiting for action.
|
||||
*/
|
||||
public abstract void update(Entity entity, Level level, double delta);
|
||||
|
||||
@@ -57,15 +57,20 @@ public abstract class EntityModel {
|
||||
|
||||
|
||||
/**
|
||||
* @param entity the value is valid for
|
||||
* @return step time (seconds)
|
||||
* Get one path step duration (in seconds)
|
||||
*/
|
||||
public abstract double getStepTime(Entity entity);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onStepFinished(Entity entity, World world, Level level);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathFinished(Entity entity, World world, Level level);
|
||||
|
||||
|
||||
@Override
|
||||
public abstract void onPathAborted(Entity entity, World world, Level level);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
public interface EntityMoveListener {
|
||||
|
||||
/**
|
||||
* One step of a path finished
|
||||
*/
|
||||
void onStepFinished(Entity entity, World world, Level level);
|
||||
|
||||
|
||||
/**
|
||||
* Scheduled path finished
|
||||
*/
|
||||
void onPathFinished(Entity entity, World world, Level level);
|
||||
|
||||
|
||||
/**
|
||||
* Path was aborted (bumped into a wall or entity)
|
||||
*/
|
||||
void onPathAborted(Entity entity, World world, Level level);
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ 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.entity.renderers.PlayerRenderer;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
@@ -20,6 +21,7 @@ public class PlayerModel extends EntityModel {
|
||||
public PlayerModel(int id)
|
||||
{
|
||||
super(id);
|
||||
setRenderer(new PlayerRenderer("player"));
|
||||
}
|
||||
|
||||
|
||||
@@ -64,4 +66,10 @@ public class PlayerModel extends EntityModel {
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathAborted(Entity entity, World world, Level level)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
public class EntityRenderer {
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
|
||||
|
||||
public abstract class EntityRenderer {
|
||||
|
||||
public static final EntityRenderer NONE = new NullEntityRenderer();
|
||||
|
||||
|
||||
public abstract void render(Entity entity, EntityRenderContext context);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
|
||||
|
||||
public class NullEntityRenderer extends EntityRenderer {
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, EntityRenderContext context)
|
||||
{
|
||||
// hell no
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.gamecore.render.textures.TxQuad;
|
||||
import mightypork.gamecore.render.textures.TxSheet;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.math.Calc;
|
||||
|
||||
|
||||
public class PlayerRenderer extends EntityRenderer {
|
||||
|
||||
TxSheet sheet;
|
||||
|
||||
|
||||
public PlayerRenderer(String sheetKey)
|
||||
{
|
||||
this.sheet = Res.getTxSheet(sheetKey); // expects 1x4
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(Entity entity, EntityRenderContext context)
|
||||
{
|
||||
TxQuad q = sheet.getQuad(Calc.frag(entity.getPosition().getProgress()));
|
||||
|
||||
if (entity.lastXMove == -1) q = q.flipX();
|
||||
|
||||
final WorldPos pos = entity.getPosition();
|
||||
|
||||
final Rect tileRect = context.getRectForTile(pos.x, pos.y);
|
||||
final double w = tileRect.width().value();
|
||||
|
||||
Rect spriteRect = tileRect.move(pos.getVisualXOffset() * w, pos.getVisualYOffset() * w + w * 0.1);
|
||||
spriteRect = spriteRect.shrink(w * 0.1);
|
||||
|
||||
Render.quadTextured(spriteRect, q);
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,12 @@ 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.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.EntityRenderContext;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
@@ -170,6 +169,11 @@ public class Level implements MapAccess, IonBinary {
|
||||
tiles[y][x].load(in);
|
||||
}
|
||||
}
|
||||
|
||||
// mark tiles as occupied
|
||||
for (final Entity e : entity_set) {
|
||||
occupyTile(e.getPosition().x, e.getPosition().y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +205,7 @@ public class Level implements MapAccess, IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public void update(double delta)
|
||||
public void update(World w, double delta)
|
||||
{
|
||||
// just update them all
|
||||
for (int y = 0; y < height; y++) {
|
||||
@@ -209,6 +213,10 @@ public class Level implements MapAccess, IonBinary {
|
||||
getTile(x, y).update(this, delta);
|
||||
}
|
||||
}
|
||||
|
||||
for (final Entity e : entity_set) {
|
||||
e.update(w, this, delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -232,16 +240,8 @@ public class Level implements MapAccess, IonBinary {
|
||||
* @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)
|
||||
public void render(WorldPos pos, RectBound viewport, final int xTiles, final int yTiles, 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();
|
||||
@@ -250,9 +250,9 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
final double allowedSizeW = vpW / xTiles;
|
||||
final double allowedSizeH = vpH / yTiles;
|
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||
final int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||
|
||||
tileSize -= tileSize % 16;
|
||||
//tileSize -= tileSize % 8;
|
||||
|
||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||
|
||||
@@ -280,7 +280,7 @@ public class Level implements MapAccess, IonBinary {
|
||||
|
||||
// batch rendering of the tiles
|
||||
if (USE_BATCH_RENDERING) {
|
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles"));
|
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles16"));
|
||||
}
|
||||
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
@@ -299,6 +299,12 @@ public class Level implements MapAccess, IonBinary {
|
||||
trc.renderItems();
|
||||
}
|
||||
}
|
||||
|
||||
// render entities
|
||||
final EntityRenderContext erc = new EntityRenderContext(this, mapRect);
|
||||
for (final Entity e : entity_set) {
|
||||
e.render(erc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,4 +333,30 @@ public class Level implements MapAccess, IonBinary {
|
||||
final Entity removed = entity_map.remove(eid);
|
||||
entity_set.remove(removed);
|
||||
}
|
||||
|
||||
|
||||
public boolean canWalkInto(int x, int y)
|
||||
{
|
||||
final Tile t = getTile(x, y);
|
||||
|
||||
return t.isWalkable() && !t.isOccupied();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark tile as occupied by an entity
|
||||
*/
|
||||
public void occupyTile(int x, int y)
|
||||
{
|
||||
getTile(x, y).setOccupied(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark tile as free (no longet occupied)
|
||||
*/
|
||||
public void freeTile(int x, int y)
|
||||
{
|
||||
getTile(x, y).setOccupied(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +66,13 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
||||
map.getTile(x, y).renderTile(this);
|
||||
}
|
||||
|
||||
|
||||
public void renderItems()
|
||||
{
|
||||
map.getTile(x, y).renderItems(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rect of the current tile to draw
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,13 @@ public final class Tile implements IonBinary {
|
||||
/** persistent field for model, reflected by renderer */
|
||||
public final IonBundle metadata = new IonBundle();
|
||||
|
||||
// temporary flag for map.
|
||||
private boolean occupied;
|
||||
|
||||
// for renderer of AO shadows
|
||||
public byte shadows;
|
||||
public boolean shadowsComputed;
|
||||
|
||||
|
||||
public Tile(int id)
|
||||
{
|
||||
@@ -75,6 +82,7 @@ public final class Tile implements IonBinary {
|
||||
|
||||
/**
|
||||
* Render items
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public void renderItems(TileRenderContext context)
|
||||
@@ -85,7 +93,6 @@ public final class Tile implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
@@ -156,4 +163,16 @@ public final class Tile implements IonBinary {
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
public boolean isOccupied()
|
||||
{
|
||||
return occupied;
|
||||
}
|
||||
|
||||
|
||||
public void setOccupied(boolean occupied)
|
||||
{
|
||||
this.occupied = occupied;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,21 +20,24 @@ public final class Tiles {
|
||||
public static final TileModel NULL_SOLID = new NullWall(0);
|
||||
public static final TileModel NULL_EMPTY = new NullFloor(1);
|
||||
|
||||
public static final TileModel BRICK_FLOOR_VINES = new Floor(2).setTexture("tile.floor.mossy_bricks");
|
||||
public static final TileModel BRICK_WALL_VINES = new Wall(3).setTexture("tile.wall.mossy_bricks");
|
||||
public static final TileModel FLOOR_DARK = new Floor(2).setTexture("tile16.floor.dark");
|
||||
public static final TileModel WALL_BRICK = new Wall(3).setTexture("tile16.wall.brick");
|
||||
|
||||
public static final TileModel BRICK_FLOOR_RECT = new Floor(4).setTexture("tile.floor.rect_bricks");
|
||||
public static final TileModel BRICK_WALL_SMALL = new Wall(5).setTexture("tile.wall.small_bricks");
|
||||
|
||||
public static final TileModel SANDSTONE_FLOOR = new Floor(6).setTexture("tile.floor.sandstone");
|
||||
public static final TileModel SANDSTONE_WALL = new Wall(7).setTexture("tile.wall.sandstone");
|
||||
|
||||
public static final TileModel BRCOBBLE_FLOOR = new Floor(8).setTexture("tile.floor.brown_cobble");
|
||||
public static final TileModel BRCOBBLE_WALL = new Wall(9).setTexture("tile.wall.brown_cobble");
|
||||
|
||||
public static final TileModel CRYSTAL_FLOOR = new Floor(10).setTexture("tile.floor.crystal");
|
||||
public static final TileModel CRYSTAL_WALL = new Wall(11).setTexture("tile.wall.crystal");
|
||||
|
||||
// public static final TileModel BRICK_FLOOR_VINES = new Floor(2).setTexture("tile.floor.mossy_bricks");
|
||||
// public static final TileModel BRICK_WALL_VINES = new Wall(3).setTexture("tile.wall.mossy_bricks");
|
||||
//
|
||||
// public static final TileModel BRICK_FLOOR_RECT = new Floor(4).setTexture("tile.floor.rect_bricks");
|
||||
// public static final TileModel BRICK_WALL_SMALL = new Wall(5).setTexture("tile.wall.small_bricks");
|
||||
//
|
||||
// public static final TileModel SANDSTONE_FLOOR = new Floor(6).setTexture("tile.floor.sandstone");
|
||||
// public static final TileModel SANDSTONE_WALL = new Wall(7).setTexture("tile.wall.sandstone");
|
||||
//
|
||||
// public static final TileModel BRCOBBLE_FLOOR = new Floor(8).setTexture("tile.floor.brown_cobble");
|
||||
// public static final TileModel BRCOBBLE_WALL = new Wall(9).setTexture("tile.wall.brown_cobble");
|
||||
//
|
||||
// public static final TileModel CRYSTAL_FLOOR = new Floor(10).setTexture("tile.floor.crystal");
|
||||
// public static final TileModel CRYSTAL_WALL = new Wall(11).setTexture("tile.wall.crystal");
|
||||
|
||||
public static void register(int id, TileModel model)
|
||||
{
|
||||
|
||||
@@ -55,4 +55,10 @@ public abstract class AbstractNullTile extends SimpleTile {
|
||||
@Override
|
||||
public abstract boolean isWalkable();
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesCastShadow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,10 @@ public class Floor extends SimpleTile {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesCastShadow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,9 @@ public abstract class TileModel {
|
||||
public abstract boolean isWalkable();
|
||||
|
||||
|
||||
public abstract boolean doesCastShadow();
|
||||
|
||||
|
||||
public boolean isNullTile()
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -27,4 +27,11 @@ public class Wall extends SimpleTile {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doesCastShadow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,25 +2,85 @@ package mightypork.rogue.world.tile.renderers;
|
||||
|
||||
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.gamecore.render.textures.TxQuad;
|
||||
import mightypork.gamecore.render.textures.TxSheet;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
|
||||
|
||||
public class BasicTileRenderer extends TileRenderer {
|
||||
|
||||
private final TxSheet sheet;
|
||||
|
||||
private static boolean inited;
|
||||
private static TxQuad SH_N, SH_S, SH_E, SH_W, SH_NW, SH_NE, SH_SW, SH_SE;
|
||||
|
||||
|
||||
public BasicTileRenderer(String sheetKey)
|
||||
{
|
||||
this.sheet = Res.getTxSheet(sheetKey);
|
||||
|
||||
if (!inited) {
|
||||
SH_N = Res.getTxQuad("tile16.shadow.n");
|
||||
SH_S = Res.getTxQuad("tile16.shadow.s");
|
||||
SH_E = Res.getTxQuad("tile16.shadow.e");
|
||||
SH_W = Res.getTxQuad("tile16.shadow.w");
|
||||
SH_NW = Res.getTxQuad("tile16.shadow.nw");
|
||||
SH_NE = Res.getTxQuad("tile16.shadow.ne");
|
||||
SH_SW = Res.getTxQuad("tile16.shadow.sw");
|
||||
SH_SE = Res.getTxQuad("tile16.shadow.se");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void render(TileRenderContext context)
|
||||
{
|
||||
Render.quadTextured(context.getRect(), sheet.getRandomQuad(context.getTileNoise()));
|
||||
final Rect rect = context.getRect();
|
||||
Render.quadTextured(rect, sheet.getRandomQuad(context.getTileNoise()));
|
||||
|
||||
final Tile t = context.getTile();
|
||||
|
||||
if (t.getModel().doesCastShadow()) return; // no shadows for wall
|
||||
|
||||
Tile t2;
|
||||
|
||||
if (!t.shadowsComputed) {
|
||||
// no shadows computed yet
|
||||
|
||||
t.shadows = 0; // reset the mask
|
||||
|
||||
int move = 0;
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
if (x == 0 && y == 0) continue;
|
||||
|
||||
t2 = context.getAdjacentTile(x, y);
|
||||
|
||||
if (t2.getModel().doesCastShadow()) {
|
||||
t.shadows |= 1 << move;
|
||||
}
|
||||
|
||||
move++;
|
||||
}
|
||||
}
|
||||
|
||||
t.shadowsComputed = true;
|
||||
}
|
||||
|
||||
if (t.shadows == 0) return;
|
||||
|
||||
if ((t.shadows & (1 << 0)) != 0) Render.quadTextured(rect, SH_NW);
|
||||
if ((t.shadows & (1 << 1)) != 0) Render.quadTextured(rect, SH_N);
|
||||
if ((t.shadows & (1 << 2)) != 0) Render.quadTextured(rect, SH_NE);
|
||||
|
||||
if ((t.shadows & (1 << 3)) != 0) Render.quadTextured(rect, SH_W);
|
||||
if ((t.shadows & (1 << 4)) != 0) Render.quadTextured(rect, SH_E);
|
||||
|
||||
if ((t.shadows & (1 << 5)) != 0) Render.quadTextured(rect, SH_SW);
|
||||
if ((t.shadows & (1 << 6)) != 0) Render.quadTextured(rect, SH_S);
|
||||
if ((t.shadows & (1 << 7)) != 0) Render.quadTextured(rect, SH_SE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user