context aware walls
parent
18f4a33038
commit
3d0754f060
BIN
res/textures.png
BIN
res/textures.png
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 28 KiB |
|
|
@ -0,0 +1,104 @@
|
|||
package xyz.valnet.engine.graphics;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import xyz.valnet.engine.math.Vector4i;
|
||||
|
||||
public class Tile16 {
|
||||
public enum Direction {
|
||||
NORTH,
|
||||
EAST,
|
||||
SOUTH,
|
||||
WEST
|
||||
}
|
||||
|
||||
private Sprite solo;
|
||||
|
||||
private Sprite n; // north
|
||||
private Sprite e; // east
|
||||
private Sprite s; // south
|
||||
private Sprite w; // west
|
||||
|
||||
private Sprite h; // horizontal
|
||||
private Sprite v; // vertical
|
||||
|
||||
private Sprite cne; // corner north east
|
||||
private Sprite cnw; // corner north west
|
||||
private Sprite cse; // corner south east
|
||||
private Sprite csw; // corner south west
|
||||
|
||||
private Sprite tn; // T north east west
|
||||
private Sprite te; // T north south east
|
||||
private Sprite ts; // T south east west
|
||||
private Sprite tw; // T north south west
|
||||
|
||||
private Sprite all; // all sides
|
||||
|
||||
private Vector4i area; // the original area in the texture
|
||||
|
||||
private Map<EnumSet<Direction>, Sprite> cache = new HashMap<EnumSet<Direction>, Sprite>();
|
||||
|
||||
public Tile16(Texture base, Vector4i area) {
|
||||
this.area = area;
|
||||
solo = new Sprite(base, getPixelCoords(0, 0));
|
||||
|
||||
n = new Sprite(base, getPixelCoords(0, 3));
|
||||
e = new Sprite(base, getPixelCoords(3, 0));
|
||||
s = new Sprite(base, getPixelCoords(0, 1));
|
||||
w = new Sprite(base, getPixelCoords(1, 0));
|
||||
|
||||
h = new Sprite(base, getPixelCoords(0, 2));
|
||||
v = new Sprite(base, getPixelCoords(2, 0));
|
||||
|
||||
cne = new Sprite(base, getPixelCoords(3, 3));
|
||||
cnw = new Sprite(base, getPixelCoords(1, 3));
|
||||
cse = new Sprite(base, getPixelCoords(3, 1));
|
||||
csw = new Sprite(base, getPixelCoords(1, 1));
|
||||
|
||||
tn = new Sprite(base, getPixelCoords(2, 3));
|
||||
te = new Sprite(base, getPixelCoords(3, 2));
|
||||
ts = new Sprite(base, getPixelCoords(2, 1));
|
||||
tw = new Sprite(base, getPixelCoords(1, 2));
|
||||
|
||||
all = new Sprite(base, getPixelCoords(2, 2));
|
||||
|
||||
cache.put(EnumSet.noneOf(Direction.class), solo);
|
||||
|
||||
cache.put(EnumSet.of(Direction.NORTH), n);
|
||||
cache.put(EnumSet.of(Direction.EAST), e);
|
||||
cache.put(EnumSet.of(Direction.SOUTH), s);
|
||||
cache.put(EnumSet.of(Direction.WEST), w);
|
||||
|
||||
cache.put(EnumSet.of(Direction.NORTH, Direction.SOUTH), h);
|
||||
cache.put(EnumSet.of(Direction.EAST, Direction.WEST), v);
|
||||
|
||||
cache.put(EnumSet.of(Direction.NORTH, Direction.EAST), cne);
|
||||
cache.put(EnumSet.of(Direction.NORTH, Direction.WEST), cnw);
|
||||
cache.put(EnumSet.of(Direction.SOUTH, Direction.EAST), cse);
|
||||
cache.put(EnumSet.of(Direction.SOUTH, Direction.WEST), csw);
|
||||
|
||||
cache.put(EnumSet.of(Direction.NORTH, Direction.EAST, Direction.WEST), tn);
|
||||
cache.put(EnumSet.of(Direction.NORTH, Direction.SOUTH, Direction.EAST), te);
|
||||
cache.put(EnumSet.of(Direction.SOUTH, Direction.EAST, Direction.WEST), ts);
|
||||
cache.put(EnumSet.of(Direction.NORTH, Direction.SOUTH, Direction.WEST), tw);
|
||||
|
||||
cache.put(EnumSet.allOf(Direction.class), all);
|
||||
}
|
||||
|
||||
private Vector4i getPixelCoords(int x, int y) {
|
||||
int tileWidth = area.z / 4;
|
||||
int tileHeight = area.w / 4;
|
||||
return new Vector4i(
|
||||
area.x + x * tileWidth,
|
||||
area.y + y * tileHeight,
|
||||
tileWidth,
|
||||
tileHeight
|
||||
);
|
||||
}
|
||||
|
||||
public Sprite getTextureFor(EnumSet<Direction> directions) {
|
||||
return cache.get(directions);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,5 +15,4 @@ public class CutTreesDesignation extends Designation<Tree> {
|
|||
protected void designate(Tree thing) {
|
||||
thing.runAction(Tree.ACTION_CHOP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ public class Terrain extends GameObject implements IPathable, IWorldBoundsAdapte
|
|||
}
|
||||
|
||||
public Tile getTile(int x, int y) {
|
||||
if(x < 0 || y < 0) return null;
|
||||
if(x >= WORLD_SIZE || y >= WORLD_SIZE) return null;
|
||||
return tiles[x][y];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject;
|
|||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||
import xyz.valnet.hadean.interfaces.IPingable;
|
||||
import xyz.valnet.hadean.interfaces.ITileThing;
|
||||
import xyz.valnet.hadean.interfaces.IWorkable;
|
||||
import xyz.valnet.hadean.util.Assets;
|
||||
|
|
@ -91,12 +92,36 @@ public class Tile extends WorldObject implements IWorkable {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void pingThings() {
|
||||
for(ITileThing thing : stuff) {
|
||||
if(thing instanceof IPingable) {
|
||||
((IPingable)thing).ping();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pingNeighbors() {
|
||||
Vector2i pos = getCoords();
|
||||
Tile north = terrain.getTile(pos.x, pos.y - 1);
|
||||
Tile east = terrain.getTile(pos.x - 1, pos.y);
|
||||
Tile south = terrain.getTile(pos.x, pos.y + 1);
|
||||
Tile west = terrain.getTile(pos.x + 1, pos.y);
|
||||
if(north != null) north.pingThings();
|
||||
if(east != null) east.pingThings();
|
||||
if(south != null) south.pingThings();
|
||||
if(west != null) west.pingThings();
|
||||
}
|
||||
|
||||
public void placeThing(ITileThing thing) {
|
||||
stuff.add(thing);
|
||||
if(thing instanceof GameObject) {
|
||||
add((GameObject)thing);
|
||||
}
|
||||
thing.onPlaced(this);
|
||||
|
||||
pingThings();
|
||||
pingNeighbors();
|
||||
|
||||
if(thing instanceof FarmPlot) {
|
||||
get(JobBoard.class).postSimpleWorkJob("Till Soil", this);
|
||||
}
|
||||
|
|
@ -107,6 +132,10 @@ public class Tile extends WorldObject implements IWorkable {
|
|||
if(toRemove.contains(thing)) return null;
|
||||
|
||||
toRemove.add(thing);
|
||||
|
||||
pingThings();
|
||||
pingNeighbors();
|
||||
|
||||
return thing;
|
||||
}
|
||||
|
||||
|
|
@ -197,4 +226,13 @@ public class Tile extends WorldObject implements IWorkable {
|
|||
}
|
||||
return str.stripTrailing();
|
||||
}
|
||||
|
||||
public <T> boolean has(Class<T> clazz) {
|
||||
for(ITileThing thing : stuff) {
|
||||
if(clazz.isInstance(thing)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ import xyz.valnet.hadean.gameobjects.BottomBar;
|
|||
import xyz.valnet.hadean.gameobjects.Camera;
|
||||
import xyz.valnet.hadean.gameobjects.inputlayer.BuildLayer;
|
||||
import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.Bed;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.FarmPlot;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.Stockpile;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Bed;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Wall;
|
||||
import xyz.valnet.hadean.input.Button;
|
||||
import xyz.valnet.hadean.input.IButtonListener;
|
||||
import xyz.valnet.hadean.input.SimpleButton;
|
||||
|
|
@ -60,6 +61,8 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap
|
|||
|
||||
BuildTab.registerBuildable(Bed.class);
|
||||
|
||||
BuildTab.registerBuildable(Wall.class);
|
||||
|
||||
BuildTab.registerBuildable(FarmPlot.class);
|
||||
BuildTab.registerBuildable(Stockpile.class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ public abstract class WorldObject extends GameObject {
|
|||
private void updateTileLinks(Set<Tile> tiles) {
|
||||
if(tiles == null || tiles.size() == 0) return;
|
||||
if(!(this instanceof ITileThing)) return;
|
||||
boolean inScene = inScene();
|
||||
|
||||
Set<Tile> removeTiles = new HashSet<Tile>();
|
||||
Set<Tile> addTiles = new HashSet<Tile>();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package xyz.valnet.hadean.gameobjects.worldobjects;
|
||||
package xyz.valnet.hadean.gameobjects.worldobjects.constructions;
|
||||
|
||||
import xyz.valnet.engine.math.Vector2i;
|
||||
import xyz.valnet.engine.math.Vector4f;
|
||||
import xyz.valnet.hadean.gameobjects.Job;
|
||||
import xyz.valnet.hadean.gameobjects.JobBoard;
|
||||
import xyz.valnet.hadean.gameobjects.Tile;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.Buildable;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Log;
|
||||
import xyz.valnet.hadean.interfaces.BuildableMetadata;
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
package xyz.valnet.hadean.gameobjects.worldobjects.constructions;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import xyz.valnet.engine.graphics.Tile16.Direction;
|
||||
import xyz.valnet.engine.math.Vector2i;
|
||||
import xyz.valnet.engine.math.Vector4f;
|
||||
import xyz.valnet.hadean.gameobjects.Job;
|
||||
import xyz.valnet.hadean.gameobjects.JobBoard;
|
||||
import xyz.valnet.hadean.gameobjects.Tile;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.Buildable;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder;
|
||||
import xyz.valnet.hadean.gameobjects.worldobjects.items.Item;
|
||||
import xyz.valnet.hadean.interfaces.BuildableMetadata;
|
||||
import xyz.valnet.hadean.interfaces.IItemReceiver;
|
||||
import xyz.valnet.hadean.interfaces.IPingable;
|
||||
import xyz.valnet.hadean.interfaces.ISelectable;
|
||||
import xyz.valnet.hadean.interfaces.IWorkable;
|
||||
import xyz.valnet.hadean.util.Action;
|
||||
import xyz.valnet.hadean.util.Assets;
|
||||
import xyz.valnet.hadean.util.Layers;
|
||||
import xyz.valnet.hadean.util.detail.BooleanDetail;
|
||||
import xyz.valnet.hadean.util.detail.Detail;
|
||||
import xyz.valnet.hadean.util.detail.ObjectDetail;
|
||||
import xyz.valnet.hadean.util.detail.PercentDetail;
|
||||
|
||||
@BuildableMetadata(category = "Structure", name = "Wall", type = BuildableMetadata.Type.SINGLE)
|
||||
public class Wall extends Buildable implements IItemReceiver, IWorkable, ISelectable, IPingable {
|
||||
|
||||
private int boulders = 0;
|
||||
private float work = 0;
|
||||
private final float maxWork = 500;
|
||||
|
||||
private Job job = null;
|
||||
|
||||
@Override
|
||||
protected void create() {
|
||||
super.create();
|
||||
job = add(new Job("Build Wall"));
|
||||
job.addStep(job.new PickupItemByPredicate(Boulder.BOULDER_PREDICATE));
|
||||
job.addStep(job.new DropoffPredicateAtItemReceiver(this, Boulder.BOULDER_PREDICATE));
|
||||
job.addStep(job.new Work(this));
|
||||
get(JobBoard.class).postJob(job);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() {
|
||||
super.start();
|
||||
ping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
super.render();
|
||||
Vector2i pos = getWorldPosition().xy();
|
||||
|
||||
if(isBuilt()) {
|
||||
float b = 0.7f;
|
||||
Assets.flat.pushColor(new Vector4f(b, b, b, 1f));
|
||||
camera.draw(Layers.GROUND, Assets.wall.getTextureFor(wallSides), pos.x, pos.y);
|
||||
Assets.flat.popColor();
|
||||
} else {
|
||||
float p = work / maxWork;
|
||||
float b = 4;
|
||||
|
||||
Assets.flat.pushColor(new Vector4f(b, b, b, 0.5f));
|
||||
camera.draw(Layers.GROUND, Assets.wall.getTextureFor(wallSides), pos.x, pos.y);
|
||||
Assets.flat.popColor();
|
||||
|
||||
if(boulders > 0) {
|
||||
camera.drawProgressBar(p, getWorldBox());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Wall";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean receive(Item item) {
|
||||
if(item == null) return false;
|
||||
if(!item.matches(Boulder.BOULDER_PREDICATE)) return false;
|
||||
remove(item);
|
||||
boulders ++;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isBuilt() {
|
||||
return work >= maxWork;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doWork(float dTime) {
|
||||
work += dTime;
|
||||
return isBuilt();
|
||||
}
|
||||
|
||||
private Vector2i[] getBorders() {
|
||||
Vector2i pos = getWorldPosition().xy();
|
||||
return new Vector2i[] {
|
||||
new Vector2i(pos.x, pos.y - 1),
|
||||
|
||||
new Vector2i(pos.x - 1, pos.y),
|
||||
new Vector2i(pos.x + 1, pos.y),
|
||||
|
||||
new Vector2i(pos.x - 1, pos.y + 1),
|
||||
new Vector2i(pos.x + 1, pos.y + 1),
|
||||
|
||||
new Vector2i(pos.x, pos.y + 2),
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2i[] getWorkablePositions() {
|
||||
return getBorders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJobName() {
|
||||
return "Build Wall";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2i[] getItemDropoffLocations() {
|
||||
return getBorders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action[] getActions() {
|
||||
return new Action[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runAction(Action action) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Detail[] getDetails() {
|
||||
return new Detail[] {
|
||||
new BooleanDetail("Built", isBuilt()),
|
||||
new PercentDetail("Work", work / maxWork, 1),
|
||||
new ObjectDetail<Integer>("Logs", boulders),
|
||||
new BooleanDetail("North", wallSides.contains(Direction.NORTH)),
|
||||
new BooleanDetail("East", wallSides.contains(Direction.EAST)),
|
||||
new BooleanDetail("South", wallSides.contains(Direction.SOUTH)),
|
||||
new BooleanDetail("West", wallSides.contains(Direction.WEST)),
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWalkable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRemove() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
|
||||
}
|
||||
|
||||
private EnumSet<Direction> wallSides = EnumSet.noneOf(Direction.class);
|
||||
|
||||
@Override
|
||||
public void ping() {
|
||||
Vector2i pos = getWorldBox().asInt().xy();
|
||||
wallSides = EnumSet.noneOf(Direction.class);
|
||||
|
||||
Tile north = terrain.getTile(pos.x, pos.y - 1);
|
||||
if(north != null && north.has(Wall.class)) wallSides.add(Direction.NORTH);
|
||||
|
||||
Tile east = terrain.getTile(pos.x - 1, pos.y);
|
||||
if(east != null && east.has(Wall.class)) wallSides.add(Direction.EAST);
|
||||
|
||||
Tile south = terrain.getTile(pos.x, pos.y + 1);
|
||||
if(south != null && south.has(Wall.class)) wallSides.add(Direction.SOUTH);
|
||||
|
||||
Tile west = terrain.getTile(pos.x + 1, pos.y);
|
||||
if(west != null && west.has(Wall.class)) wallSides.add(Direction.WEST);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
package xyz.valnet.hadean.gameobjects.worldobjects.items;
|
||||
|
||||
import xyz.valnet.engine.math.Vector2i;
|
||||
import xyz.valnet.hadean.interfaces.IItemPredicate;
|
||||
import xyz.valnet.hadean.util.Assets;
|
||||
import xyz.valnet.hadean.util.Layers;
|
||||
import xyz.valnet.hadean.util.detail.Detail;
|
||||
|
||||
public class Boulder extends Item {
|
||||
|
||||
public static IItemPredicate BOULDER_PREDICATE = (item) -> (item instanceof Boulder);
|
||||
|
||||
public Boulder(int x, int y) {
|
||||
setPosition(x, y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ public @interface BuildableMetadata {
|
|||
|
||||
public enum Type {
|
||||
AREA,
|
||||
LINE,
|
||||
SINGLE
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package xyz.valnet.hadean.interfaces;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public interface IPingable extends Serializable {
|
||||
public void ping();
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import java.util.Map;
|
|||
import xyz.valnet.engine.graphics.Font;
|
||||
import xyz.valnet.engine.graphics.Sprite;
|
||||
import xyz.valnet.engine.graphics.Texture;
|
||||
import xyz.valnet.engine.graphics.Tile16;
|
||||
import xyz.valnet.engine.graphics.Tile9;
|
||||
import xyz.valnet.engine.math.Vector4i;
|
||||
import xyz.valnet.engine.shaders.SimpleShader;
|
||||
|
|
@ -24,6 +25,7 @@ public class Assets {
|
|||
public static final Tile9 uiFrameDark;
|
||||
public static final Tile9 fillColor;
|
||||
|
||||
public static final Tile16 wall;
|
||||
|
||||
public static final Sprite[] defaultTerrain;
|
||||
public static final Sprite[] growingRice;
|
||||
|
|
@ -304,6 +306,8 @@ public class Assets {
|
|||
new Sprite(atlas, 7, 103, 1, 1)
|
||||
);
|
||||
|
||||
wall = new Tile16(atlas, new Vector4i(0, 17 * 8, 32, 32));
|
||||
|
||||
System.out.println("END ASSETS");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue