Physics
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package mindustry.async;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.game.EventType.*;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@@ -12,15 +14,28 @@ public class AsyncLogic{
|
||||
private Array<Future<?>> futures = new Array<>();
|
||||
|
||||
private ExecutorService executor = Executors.newFixedThreadPool(processes.size, r -> {
|
||||
Thread thread = new Thread(r, "AsyncExecutor-Thread");
|
||||
Thread thread = new Thread(r, "AsyncLogic-Thread");
|
||||
thread.setDaemon(true);
|
||||
thread.setUncaughtExceptionHandler((t, e) -> {
|
||||
e.printStackTrace();
|
||||
//TODO crash!
|
||||
});
|
||||
thread.setUncaughtExceptionHandler((t, e) -> Core.app.post(() -> { throw new RuntimeException(e); }));
|
||||
return thread;
|
||||
});
|
||||
|
||||
public AsyncLogic(){
|
||||
Events.on(WorldLoadEvent.class, e -> {
|
||||
complete();
|
||||
for(AsyncProcess p : processes){
|
||||
p.init();
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(ResetEvent.class, e -> {
|
||||
complete();
|
||||
for(AsyncProcess p : processes){
|
||||
p.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void begin(){
|
||||
//sync begin
|
||||
for(AsyncProcess p : processes){
|
||||
@@ -36,6 +51,15 @@ public class AsyncLogic{
|
||||
}
|
||||
|
||||
public void end(){
|
||||
complete();
|
||||
|
||||
//sync end (flush data)
|
||||
for(AsyncProcess p : processes){
|
||||
p.end();
|
||||
}
|
||||
}
|
||||
|
||||
private void complete(){
|
||||
//wait for all threads to stop processing
|
||||
for(Future future : futures){
|
||||
try{
|
||||
@@ -45,11 +69,7 @@ public class AsyncLogic{
|
||||
}
|
||||
}
|
||||
|
||||
//clear processed futures
|
||||
futures.clear();
|
||||
|
||||
//sync end (flush data)
|
||||
for(AsyncProcess p : processes){
|
||||
p.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,13 @@ package mindustry.async;
|
||||
|
||||
public interface AsyncProcess{
|
||||
|
||||
/** Synchronous. Called at the beginning of the main loop. */
|
||||
/** Sync. Called when the world loads. */
|
||||
void init();
|
||||
|
||||
/** Sync. Called when the world resets. */
|
||||
void reset();
|
||||
|
||||
/** Sync. Called at the beginning of the main loop. */
|
||||
void begin();
|
||||
|
||||
/** Async. Called in a separate thread. */
|
||||
|
||||
@@ -1,19 +1,161 @@
|
||||
package mindustry.async;
|
||||
|
||||
import arc.*;
|
||||
import arc.box2d.*;
|
||||
import arc.box2d.BodyDef.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
|
||||
public class PhysicsProcess implements AsyncProcess{
|
||||
private Physics physics;
|
||||
private Array<PhysicRef> refs = new Array<>(false);
|
||||
private BodyDef def;
|
||||
|
||||
private EntityGroup<? extends Hitboxc> group;
|
||||
private Filter flying = new Filter(){{
|
||||
maskBits = categoryBits = 2;
|
||||
}}, ground = new Filter(){{
|
||||
maskBits = categoryBits = 1;
|
||||
}};
|
||||
|
||||
public PhysicsProcess(){
|
||||
def = new BodyDef();
|
||||
def.allowSleep = true;
|
||||
def.bullet = false;
|
||||
def.type = BodyType.DynamicBody;
|
||||
|
||||
//currently only enabled for units
|
||||
group = Groups.unit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void begin(){
|
||||
if(physics == null) return;
|
||||
|
||||
//remove stale entities
|
||||
refs.removeAll(ref -> {
|
||||
if(!ref.entity.isAdded()){
|
||||
physics.destroyBody(ref.body);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
//find entities without bodies and assign them
|
||||
for(Hitboxc entity : group){
|
||||
boolean grounded = ((Flyingc)entity).isGrounded();
|
||||
|
||||
if(entity.body() == null){
|
||||
//add bodies to entities that have none
|
||||
CircleShape shape = new CircleShape();
|
||||
shape.setRadius(entity.hitSize() * 0.46f);
|
||||
|
||||
FixtureDef fd = new FixtureDef();
|
||||
fd.shape = shape;
|
||||
fd.density = 10.0f;
|
||||
fd.restitution = 0.05f;
|
||||
fd.filter.maskBits = fd.filter.categoryBits = (grounded ? ground : flying).maskBits;
|
||||
|
||||
def.position.set(entity);
|
||||
|
||||
Body body = physics.createBody(def);
|
||||
body.createFixture(fd);
|
||||
|
||||
body.setUserData(entity);
|
||||
|
||||
PhysicRef ref = new PhysicRef(entity, body);
|
||||
refs.add(ref);
|
||||
|
||||
entity.body(ref);
|
||||
}
|
||||
|
||||
//save last position
|
||||
PhysicRef ref = entity.body();
|
||||
|
||||
if(ref.wasGround != grounded){
|
||||
//set correct filter
|
||||
ref.body.getFixtureList().first().setFilterData(grounded ? ground : flying);
|
||||
ref.wasGround = grounded;
|
||||
}
|
||||
|
||||
ref.velocity.set(entity.deltaX(), entity.deltaY());
|
||||
ref.position.set(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(){
|
||||
if(physics == null) return;
|
||||
|
||||
//get last position vectors before step
|
||||
for(PhysicRef ref : refs){
|
||||
//force set target position
|
||||
ref.body.setPosition(ref.position.x, ref.position.y);
|
||||
|
||||
//save last position for delta
|
||||
ref.lastPosition.set(ref.body.getPosition());
|
||||
|
||||
//write velocity
|
||||
ref.body.setLinearVelocity(ref.velocity);
|
||||
}
|
||||
|
||||
physics.step(Core.graphics.getDeltaTime(), 3, 3);
|
||||
|
||||
//get delta vectors
|
||||
for(PhysicRef ref : refs){
|
||||
//get delta vector
|
||||
ref.delta.set(ref.body.getPosition()).sub(ref.lastPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end(){
|
||||
if(physics == null) return;
|
||||
|
||||
//move entities
|
||||
for(PhysicRef ref : refs){
|
||||
Hitboxc entity = ref.entity;
|
||||
|
||||
if(entity instanceof Velc){
|
||||
//move using velocity component move method TODO hack
|
||||
((Velc)entity).move(ref.delta.x, ref.delta.y);
|
||||
}else{
|
||||
//move directly
|
||||
entity.trns(ref.delta.x, ref.delta.y);
|
||||
}
|
||||
|
||||
//save last position
|
||||
ref.position.set(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
if(physics != null){
|
||||
refs.clear();
|
||||
physics.dispose();
|
||||
physics = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
reset();
|
||||
|
||||
physics = new Physics(new Vec2(), true);
|
||||
}
|
||||
|
||||
public static class PhysicRef{
|
||||
Hitboxc entity;
|
||||
Body body;
|
||||
boolean wasGround = true;
|
||||
Vec2 lastPosition = new Vec2(), delta = new Vec2(), velocity = new Vec2(), position = new Vec2();
|
||||
|
||||
public PhysicRef(Hitboxc entity, Body body){
|
||||
this.entity = entity;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user