Added support for generating box2d bodies for monster and objects and generalized player entities

Added support for generating box2d bodies for monster and objects and generalized player entities
Added support for object entities to perform a bitwise or with the map tile flags so pathfinding will avoid them
This commit is contained in:
Collin Smith 2019-11-21 01:34:56 -08:00
parent 266eca76ce
commit d6f8de3b86
4 changed files with 134 additions and 11 deletions

View File

@ -20,6 +20,7 @@ import com.riiablo.codec.util.BBox;
import com.riiablo.engine.component.AngleComponent;
import com.riiablo.engine.component.AnimationComponent;
import com.riiablo.engine.component.BBoxComponent;
import com.riiablo.engine.component.Box2DComponent;
import com.riiablo.engine.component.ClassnameComponent;
import com.riiablo.engine.component.CofComponent;
import com.riiablo.engine.component.DS1Component;
@ -231,6 +232,10 @@ public class Engine extends PooledEngine {
interactableComponent.range = base.OperateRange;
}
SizeComponent sizeComponent = createComponent(SizeComponent.class);
Box2DComponent box2DComponent = createComponent(Box2DComponent.class);
Entity entity = createEntity(base.Description);
entity.add(typeComponent);
if (draw) entity.add(cofComponent);
@ -242,6 +247,8 @@ public class Engine extends PooledEngine {
entity.add(objectComponent);
entity.add(labelComponent);
if (interactableComponent != null) entity.add(interactableComponent);
entity.add(sizeComponent);
entity.add(box2DComponent);
labelComponent.actor.setUserObject(entity);
@ -298,6 +305,10 @@ public class Engine extends PooledEngine {
PositionComponent positionComponent = createComponent(PositionComponent.class);
positionComponent.position.set(x, y);
VelocityComponent velocityComponent = createComponent(VelocityComponent.class);
velocityComponent.walkSpeed = monstats.Velocity;
velocityComponent.runSpeed = monstats.Run;
LabelComponent labelComponent = createComponent(LabelComponent.class);
labelComponent.offset.y = monstats2.pixHeight;
labelComponent.actor = createLabel(name);
@ -312,18 +323,22 @@ public class Engine extends PooledEngine {
SizeComponent sizeComponent = createComponent(SizeComponent.class);
sizeComponent.size = monstats2.SizeX; // FIXME: see above note
Box2DComponent box2DComponent = createComponent(Box2DComponent.class);
Entity entity = createEntity(monstats.Id);
entity.add(typeComponent);
entity.add(cofComponent);
entity.add(animationComponent);
entity.add(boxComponent);
entity.add(positionComponent);
entity.add(velocityComponent);
entity.add(mapComponent);
entity.add(ds1Component);
entity.add(monsterComponent);
entity.add(labelComponent);
if (interactableComponent != null) entity.add(interactableComponent);
entity.add(sizeComponent);
entity.add(box2DComponent);
labelComponent.actor.setUserObject(entity);
@ -453,6 +468,8 @@ public class Engine extends PooledEngine {
SizeComponent sizeComponent = createComponent(SizeComponent.class);
sizeComponent.size = SizeComponent.MEDIUM;
Box2DComponent box2DComponent = createComponent(Box2DComponent.class);
Entity entity = createEntity("player");
entity.add(typeComponent);
entity.add(cofComponent);
@ -466,6 +483,7 @@ public class Engine extends PooledEngine {
entity.add(playerComponent);
entity.add(zoneAwareComponent);
entity.add(sizeComponent);
entity.add(box2DComponent);
return entity;
}

View File

@ -8,7 +8,7 @@ import com.riiablo.engine.component.Box2DComponent;
import com.riiablo.engine.component.VelocityComponent;
public class Box2DBodySystem extends IteratingSystem {
private final ComponentMapper<VelocityComponent> velocitycomponent = ComponentMapper.getFor(VelocityComponent.class);
private final ComponentMapper<VelocityComponent> velocityComponent = ComponentMapper.getFor(VelocityComponent.class);
private final ComponentMapper<Box2DComponent> box2DComponent = ComponentMapper.getFor(Box2DComponent.class);
public Box2DBodySystem() {
@ -17,7 +17,7 @@ public class Box2DBodySystem extends IteratingSystem {
@Override
protected void processEntity(Entity entity, float delta) {
VelocityComponent velocityComponent = this.velocitycomponent.get(entity);
VelocityComponent velocityComponent = this.velocityComponent.get(entity);
Box2DComponent box2DComponent = this.box2DComponent.get(entity);
box2DComponent.body.setLinearVelocity(velocityComponent.velocity);
}

View File

@ -6,11 +6,13 @@ import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IntervalIteratingSystem;
import com.badlogic.ashley.utils.ImmutableArray;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2D;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Filter;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.PolygonShape;
@ -21,7 +23,10 @@ import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.ObjectMap;
import com.riiablo.camera.IsometricCamera;
import com.riiablo.engine.component.Box2DComponent;
import com.riiablo.engine.component.ObjectComponent;
import com.riiablo.engine.component.PositionComponent;
import com.riiablo.engine.component.SizeComponent;
import com.riiablo.engine.component.TypeComponent;
import com.riiablo.engine.component.VelocityComponent;
import java.util.Arrays;
@ -32,9 +37,31 @@ public class Box2DPhysicsSystem extends IntervalIteratingSystem implements Entit
private final ComponentMapper<PositionComponent> positionComponent = ComponentMapper.getFor(PositionComponent.class);
private final ComponentMapper<Box2DComponent> box2dComponent = ComponentMapper.getFor(Box2DComponent.class);
private final ComponentMapper<SizeComponent> sizeComponent = ComponentMapper.getFor(SizeComponent.class);
private final ComponentMapper<TypeComponent> typeComponent = ComponentMapper.getFor(TypeComponent.class);
private final ComponentMapper<ObjectComponent> objectComponent = ComponentMapper.getFor(ObjectComponent.class);
private final Family objectFamily = Family.all(ObjectComponent.class, SizeComponent.class, PositionComponent.class).get();
private ImmutableArray<Entity> objectEntities;
private final float timeStep;
private final BodyDef wallBodyDef = new BodyDef() {{
type = BodyDef.BodyType.StaticBody;
awake = false;
allowSleep = true;
fixedRotation = true;
}};
private final BodyDef objectBodyDef = new BodyDef() {{
type = BodyDef.BodyType.StaticBody;
fixedRotation = true;
}};
private final BodyDef monsterBodyDef = new BodyDef() {{
type = BodyDef.BodyType.DynamicBody;
fixedRotation = true;
}};
private final BodyDef playerBodyDef = monsterBodyDef;
private Map map;
public World world;
@ -55,25 +82,34 @@ public class Box2DPhysicsSystem extends IntervalIteratingSystem implements Entit
@Override
public void addedToEngine(Engine engine) {
super.addedToEngine(engine);
engine.addEntityListener(Family.all(Box2DComponent.class).get(), this);
engine.addEntityListener(Family.all(TypeComponent.class, PositionComponent.class, SizeComponent.class, Box2DComponent.class).get(), this);
objectEntities = engine.getEntitiesFor(objectFamily);
}
@Override
public void removedFromEngine(Engine engine) {
super.removedFromEngine(engine);
engine.removeEntityListener(this);
objectEntities = null;
dispose();
}
@Override
public void entityAdded(Entity entity) {
Box2DComponent box2DComponent = this.box2dComponent.get(entity);
Box2DComponent box2DComponent = com.riiablo.engine.Engine
.getOrCreateComponent(entity, getEngine(), Box2DComponent.class, box2dComponent);
if (box2DComponent.body == null) box2DComponent.body = createBody(entity);
if (box2DComponent.body == null) {
entity.remove(Box2DComponent.class);
return;
}
bodies.put(entity, box2DComponent.body);
}
@Override
public void entityRemoved(Entity entity) {
Body body = bodies.remove(entity);
if (body == null) return;
world.destroyBody(body);
}
@ -86,14 +122,57 @@ public class Box2DPhysicsSystem extends IntervalIteratingSystem implements Entit
}
}
private Body createBody(Entity entity) {
SizeComponent sizeComponent = this.sizeComponent.get(entity);
TypeComponent typeComponent = this.typeComponent.get(entity);
if (sizeComponent.size == SizeComponent.INSIGNIFICANT && typeComponent.type != TypeComponent.Type.OBJ) return null;
PositionComponent positionComponent = this.positionComponent.get(entity);
Body body;
switch (typeComponent.type) {
case OBJ: {
ObjectComponent objectComponent = entity.getComponent(ObjectComponent.class);
objectBodyDef.position.set(positionComponent.position);
body = world.createBody(objectBodyDef);
PolygonShape shape = new PolygonShape(); {
shape.setAsBox(objectComponent.base.SizeX / 2f, objectComponent.base.SizeY / 2f);
body.createFixture(shape, 1f);
} shape.dispose();
if (map != null) {
map.or(positionComponent.position, objectComponent.base.SizeX, objectComponent.base.SizeY, DT1.Tile.FLAG_BLOCK_WALK);
}
}
break;
case MON: {
monsterBodyDef.position.set(positionComponent.position);
body = world.createBody(monsterBodyDef);
CircleShape shape = new CircleShape(); {
shape.setRadius(sizeComponent.size / 2f);
Fixture fixture = body.createFixture(shape, 1f);
//fixture.setSensor(true);
} shape.dispose();
}
break;
case PLR: {
playerBodyDef.position.set(positionComponent.position);
body = world.createBody(playerBodyDef);
CircleShape shape = new CircleShape(); {
shape.setRadius(sizeComponent.size / 2f);
Fixture fixture = body.createFixture(shape, 1f);
//fixture.setSensor(true);
} shape.dispose();
}
break;
default:
body = null;
}
return body;
}
private void createBodies(Vector2 offset) {
IntMap<Filter> filters = new IntMap<>();
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.StaticBody;
def.awake = false;
def.allowSleep = true;
def.fixedRotation = true;
boolean[][] handled = new boolean[1000][1000];
for (Map.Zone zone : new Array.ArrayIterator<>(map.zones)) {
for (boolean[] a : handled) Arrays.fill(a, false);
@ -118,7 +197,7 @@ public class Box2DPhysicsSystem extends IntervalIteratingSystem implements Entit
}
int lenY = endY - ty;
def.position.set((endX + tx) / 2f, (endY + ty) / 2f).add(offset);
wallBodyDef.position.set((endX + tx) / 2f, (endY + ty) / 2f).add(offset);
PolygonShape shape = new PolygonShape();
shape.setAsBox(lenX / 2f, lenY / 2f);
@ -131,7 +210,7 @@ public class Box2DPhysicsSystem extends IntervalIteratingSystem implements Entit
filter.groupIndex = 0;
}
Body body = world.createBody(def);
Body body = world.createBody(wallBodyDef);
Fixture f = body.createFixture(shape, 0);
f.setFilterData(filter);
@ -143,6 +222,12 @@ public class Box2DPhysicsSystem extends IntervalIteratingSystem implements Entit
}
}
}
for (Entity entity : objectEntities) {
PositionComponent positionComponent = this.positionComponent.get(entity);
ObjectComponent objectComponent = this.objectComponent.get(entity);
map.or(positionComponent.position, objectComponent.base.SizeX, objectComponent.base.SizeY, DT1.Tile.FLAG_BLOCK_WALK);
}
}
private static boolean allEqual(Map map, int x, int y, int len, int flags) {

View File

@ -633,6 +633,18 @@ public class Map implements Disposable {
return zone.flags(x, y);
}
void or(Vector2 position, int width, int height, int flags) {
if (width == 0 || height == 0) return;
int x0 = round(position.x - width / 2f);
int y0 = round(position.y - height / 2f);
for (int x = 0; x < width; x++, x0++) {
for (int y = 0; y < height; y++, y0++) {
Zone zone = getZone(x0, y0);
if (zone != null) zone.or(x0, y0, flags);
}
}
}
public DT1.Tile getTile(int l, int x, int y) {
Zone zone = getZone(x, y);
if (zone == null) return null;
@ -886,6 +898,14 @@ public class Map implements Disposable {
return flags[x][y] & 0xFF;
}
int or(int x, int y, int flags) {
x -= this.x;
if (x < 0 || x > width ) return 0xFF;
y -= this.y;
if (y < 0 || y > height) return 0xFF;
return (this.flags[x][y] |= flags) & 0xFF;
}
void load(DT1s dt1s) {
Validate.validState(tiles == null, "tiles have already been loaded");
tiles = new Tile[Map.MAX_LAYERS][][];