Improved entity path debug rendering

Included reference to source DS1.Object in StaticEntity and Monster classes
Added reference to DS1.Path in DS1.Object owner (assumes 1 path per object)
Moved path debug rendering to Entity from MapRenderer
Added Entity.drawDebugPath(ShapeRenderer)
This commit is contained in:
Collin Smith 2019-02-15 02:09:17 -08:00
parent dda1c4b47d
commit 1d781c5b8f
5 changed files with 97 additions and 65 deletions

View File

@ -330,6 +330,8 @@ public class Entity {
shapes.line(x, y, x + MathUtils.cos(rounded) * R * 0.5f, y + MathUtils.sin(rounded) * R * 0.5f);
}
public void drawDebugPath(ShapeRenderer shapes) {}
public void draw(Batch batch) {
draw((PaletteIndexedBatch) batch);
}

View File

@ -1,6 +1,8 @@
package gdx.diablo.entity;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.MathUtils;
import org.apache.commons.lang3.StringUtils;
@ -9,15 +11,18 @@ import gdx.diablo.Diablo;
import gdx.diablo.codec.excel.MonStats;
import gdx.diablo.codec.excel.MonStats2;
import gdx.diablo.map.DS1;
import gdx.diablo.map.DT1.Tile;
public class Monster extends Entity {
private static final String TAG = "Monster";
MonStats.Entry monstats;
DS1.Object object;
MonStats.Entry monstats;
MonStats2.Entry monstats2;
public Monster(MonStats.Entry monstats) {
public Monster(DS1.Object object, MonStats.Entry monstats) {
super(monstats.Code, EntType.MONSTER);
this.object = object;
this.monstats = monstats;
this.monstats2 = Diablo.files.monstats2.get(monstats.MonStatsEx);
setWeaponClass(monstats2.BaseW);
@ -40,7 +45,47 @@ public class Monster extends Entity {
Gdx.app.debug(TAG, "Monster: " + monstats);
if (monstats == null) return null; // TODO: Which ones fall under this case? Some static entities did, none here yet in testing.
//if (!object.Draw) return null; // TODO: Not yet
return new Monster(monstats);
return new Monster(obj, monstats);
}
@Override
public void drawDebugPath(ShapeRenderer shapes) {
DS1.Path path = object.path;
if (path == null) return;
float p1x = +(position.x * Tile.SUBTILE_WIDTH50) - (position.y * Tile.SUBTILE_WIDTH50);
float p1y = -(position.x * Tile.SUBTILE_HEIGHT50) - (position.y * Tile.SUBTILE_HEIGHT50);
float p2x = 0, p2y = 0;
for (int i = 0; i < path.numPoints; i++) {
DS1.Path.Point point = path.points[i];
p2x = +(point.x * Tile.SUBTILE_WIDTH50) - (point.y * Tile.SUBTILE_WIDTH50);
p2y = -(point.x * Tile.SUBTILE_HEIGHT50) - (point.y * Tile.SUBTILE_HEIGHT50);
shapes.setColor(Color.PURPLE);
shapes.rectLine(p1x, p1y, p2x, p2y, 2);
p1x = p2x;
p1y = p2y;
}
if (path.numPoints > 1) {
DS1.Path.Point point = path.points[0];
p1x = +(point.x * Tile.SUBTILE_WIDTH50) - (point.y * Tile.SUBTILE_WIDTH50);
p1y = -(point.x * Tile.SUBTILE_HEIGHT50) - (point.y * Tile.SUBTILE_HEIGHT50);
shapes.setColor(Color.PURPLE);
shapes.rectLine(p1x, p1y, p2x, p2y, 2);
}
final float BOX_SIZE = 8;
final float HALF_BOX = BOX_SIZE / 2;
p1x = +(position.x * Tile.SUBTILE_WIDTH50) - (position.y * Tile.SUBTILE_WIDTH50);
p1y = -(position.x * Tile.SUBTILE_HEIGHT50) - (position.y * Tile.SUBTILE_HEIGHT50);
shapes.setColor(Color.WHITE);
shapes.rect(p1x - HALF_BOX, p1y - HALF_BOX, BOX_SIZE, BOX_SIZE);
for (int i = 0; i < path.numPoints; i++) {
DS1.Path.Point point = path.points[i];
p1x = +(point.x * Tile.SUBTILE_WIDTH50) - (point.y * Tile.SUBTILE_WIDTH50);
p1y = -(point.x * Tile.SUBTILE_HEIGHT50) - (point.y * Tile.SUBTILE_HEIGHT50);
shapes.setColor(Color.WHITE);
shapes.rect(p1x - HALF_BOX, p1y - HALF_BOX, BOX_SIZE, BOX_SIZE);
}
}
}

View File

@ -9,11 +9,13 @@ import gdx.diablo.map.DS1;
public class StaticEntity extends Entity {
private static final String TAG = "StaticEntity";
Objects.Entry object;
DS1.Object object;
Objects.Entry base;
public StaticEntity(Objects.Entry object) {
super(object.Token, EntType.OBJECT);
public StaticEntity(DS1.Object object, Objects.Entry base) {
super(base.Token, EntType.OBJECT);
this.object = object;
this.base = base;
init();
}
@ -21,10 +23,10 @@ public class StaticEntity extends Entity {
assert obj.type == DS1.Object.STATIC_TYPE;
int id = Diablo.files.obj.getType2(ds1.getAct(), obj.id);
Objects.Entry object = Diablo.files.objects.get(id);
if (object == null) return null; // TODO: Which ones fall under this case?
if (!object.Draw) return null; // TODO: Not yet
return new StaticEntity(object);
Objects.Entry base = Diablo.files.objects.get(id);
if (base == null) return null; // TODO: Which ones fall under this case?
if (!base.Draw) return null; // TODO: Not yet
return new StaticEntity(obj, base);
}
@Override
@ -32,17 +34,17 @@ public class StaticEntity extends Entity {
super.update();
int mode = Diablo.files.ObjMode.index(this.mode);
//System.out.println(getName() + " " + this.mode + "(" + mode + ") " + object.FrameDelta[mode]);
animation.setLooping(object.CycleAnim[mode]);
animation.setFrame(object.Start[mode]);
animation.setFrameDelta(object.FrameDelta[mode]); // FIXME: anim framedelta looks too quick
animation.setLooping(base.CycleAnim[mode]);
animation.setFrame(base.Start[mode]);
animation.setFrameDelta(base.FrameDelta[mode]); // FIXME: anim framedelta looks too quick
}
public String getName() {
return object == null ? toString() : object.Name + "(" + object.Id + ")";
return base == null ? toString() : base.Name + "(" + base.Id + ")";
}
private void init() {
switch (object.InitFn) {
switch (base.InitFn) {
case 0:
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7:
@ -70,12 +72,12 @@ public class StaticEntity extends Entity {
case 79:
break;
default:
Gdx.app.error(TAG, "Invalid InitFn for " + getName() + ": " + object.InitFn);
Gdx.app.error(TAG, "Invalid InitFn for " + getName() + ": " + base.InitFn);
}
}
private void operate() {
switch (object.OperateFn) {
switch (base.OperateFn) {
case 0:
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
@ -88,30 +90,30 @@ public class StaticEntity extends Entity {
case 70: case 71: case 72: case 73:
break;
default:
Gdx.app.error(TAG, "Invalid OperateFn for " + getName() + ": " + object.OperateFn);
Gdx.app.error(TAG, "Invalid OperateFn for " + getName() + ": " + base.OperateFn);
}
}
private void populate() {
switch (object.PopulateFn) {
switch (base.PopulateFn) {
case 0:
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
break;
default:
Gdx.app.error(TAG, "Invalid PopulateFn for " + getName() + ": " + object.PopulateFn);
Gdx.app.error(TAG, "Invalid PopulateFn for " + getName() + ": " + base.PopulateFn);
}
}
private void client() {
switch (object.ClientFn) {
switch (base.ClientFn) {
case 0:
break;
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
break;
default:
Gdx.app.error(TAG, "Invalid ClientFn for " + getName() + ": " + object.ClientFn);
Gdx.app.error(TAG, "Invalid ClientFn for " + getName() + ": " + base.ClientFn);
}
}
}

View File

@ -473,11 +473,12 @@ public class DS1 {
public static final int DYNAMIC_TYPE = 1;
public static final int STATIC_TYPE = 2;
public int type;
public int id;
public int x;
public int y;
public int flags;
public int type;
public int id;
public int x;
public int y;
public int flags;
public Path path;
Object read(int version, InputStream in) throws IOException {
type = EndianUtils.readSwappedInteger(in);
@ -485,6 +486,7 @@ public class DS1 {
x = EndianUtils.readSwappedInteger(in);
y = EndianUtils.readSwappedInteger(in);
flags = version < 6 ? 0 : EndianUtils.readSwappedInteger(in);
path = null;
return this;
}
@ -498,13 +500,14 @@ public class DS1 {
@Override
public String toString() {
return new ToStringBuilder(this)
ToStringBuilder builder = new ToStringBuilder(this)
.append("type", getType())
.append("id", id)
.append("x", x)
.append("y", y)
.append("ds1Flags", String.format("%08x", flags))
.build();
.append("ds1Flags", String.format("%08x", flags));
if (path != null) builder.append("path", path);
return builder.build();
}
}
@ -540,14 +543,14 @@ public class DS1 {
}
}
static class Path {
public static class Path {
public static final Path[] EMPTY_PATH_ARRAY = new Path[0];
int numPoints;
Point points[];
public int numPoints;
public Point points[];
int x;
int y;
public int x;
public int y;
Path read(int version, Object[] objects, InputStream in) throws IOException {
numPoints = EndianUtils.readSwappedInteger(in);
@ -575,6 +578,7 @@ public class DS1 {
}
for (int p = 0; p < numPoints; p++) points[p] = new Point().read(version, in);
object.path = this;
return this;
}
@ -588,10 +592,10 @@ public class DS1 {
.build();
}
static class Point {
int x;
int y;
int action;
public static class Point {
public int x;
public int y;
public int action;
Point read(int version, InputStream in) throws IOException {
x = EndianUtils.readSwappedInteger(in);

View File

@ -745,32 +745,11 @@ public class MapRenderer {
for (x = 0; x < size; x++) {
Map.Zone zone = map.getZone(stx, sty);
if (zone != null) {
Map.Preset preset = zone.getGrid(tx, ty);
if (preset != null) {
for (int i = 0; i < preset.ds1.numPaths; i++) {
DS1.Path path = preset.ds1.paths[i];
if ((stx <= path.x && path.x < stx + Tile.SUBTILE_SIZE)
&& (sty <= path.y && path.y < sty + Tile.SUBTILE_SIZE)) {
DS1.Path.Point prevPoint = null;
for (int j = 0; j < path.numPoints; j++) {
DS1.Path.Point point = path.points[j];
if (prevPoint != null) {
float p1x = +(prevPoint.x * Tile.SUBTILE_WIDTH50) - (prevPoint.y * Tile.SUBTILE_WIDTH50);
float p1y = -(prevPoint.x * Tile.SUBTILE_HEIGHT50) - (prevPoint.y * Tile.SUBTILE_HEIGHT50);
float p2x = +(point.x * Tile.SUBTILE_WIDTH50) - (point.y * Tile.SUBTILE_WIDTH50);
float p2y = -(point.x * Tile.SUBTILE_HEIGHT50) - (point.y * Tile.SUBTILE_HEIGHT50);
shapes.setColor(Color.PURPLE);
shapes.rectLine(p1x, p1y, p2x, p2y, 2);
shapes.setColor(Color.WHITE);
shapes.rect(p1x - 4, p1y - 4, 8, 8);
if (j == path.numPoints - 1) {
shapes.rect(p2x - 4, p2y - 4, 8, 8);
}
}
prevPoint = point;
}
}
for (Entity entity : zone.entities) {
Vector3 position = entity.position();
if ((stx <= position.x && position.x < stx + Tile.SUBTILE_SIZE)
&& (sty <= position.y && position.y < sty + Tile.SUBTILE_SIZE)) {
entity.drawDebugPath(shapes);
}
}
}