From 1c5f578d88c327d394713ebee6939b9d9bb0afa4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 29 Mar 2019 18:48:03 -0400 Subject: [PATCH 1/5] Initial implementation --- .../anuke/mindustry/entities/type/Unit.java | 60 ++++++++++++++----- core/src/io/anuke/mindustry/world/Tile.java | 2 + 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index e9d1fd26d4..7735622074 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -7,7 +7,6 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; @@ -15,7 +14,6 @@ import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.effect.ScorchDecal; import io.anuke.mindustry.entities.impl.DestructibleEntity; import io.anuke.mindustry.entities.traits.*; @@ -49,9 +47,10 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ public static final float maxAbsVelocity = 127f / velocityPercision; public static final int noSpawner = Pos.get(-1, 1); - private static final Rectangle queryRect = new Rectangle(); private static final Vector2 moveVector = new Vector2(); + private int lastWeightTile = Pos.invalid, lastWeightDelta; + public float rotation; protected final Interpolator interpolator = new Interpolator(); @@ -140,6 +139,15 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } } + @Override + public void removed(){ + Tile tile = world.tile(lastWeightTile); + + if(tile != null){ + tile.weight -= Math.max(lastWeightDelta, tile.weight); + } + } + @Override public boolean isValid(){ return !isDead() && isAdded(); @@ -190,8 +198,8 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } protected void clampPosition(){ - x = Mathf.clamp(x, tilesize, world.width() * tilesize - tilesize); - y = Mathf.clamp(y, tilesize, world.height() * tilesize - tilesize); + x = Mathf.clamp(x, 0, world.width() * tilesize - tilesize); + y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize); } public void kill(){ @@ -219,17 +227,41 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ return status.hasEffect(effect); } - //TODO optimize public void avoidOthers(float scaling){ - hitbox(queryRect); - queryRect.setSize(queryRect.getWidth() * scaling); + if(isFlying()) return; - Units.getNearby(queryRect, t -> { - if(t == this || t.isFlying() != isFlying()) return; - float dst = dst(t); - moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / queryRect.getWidth()))); - applyImpulse(moveVector.x, moveVector.y); - }); + if(lastWeightTile != Pos.invalid){ + Tile tile = world.tile(lastWeightTile); + + if(tile != null){ + tile.weight -= Math.min(lastWeightDelta, tile.weight); + } + } + + final int rad = 1; + + moveVector.setZero(); + for(int cx = -rad; cx <= rad; cx++){ + for(int cy = -rad; cy <= rad; cy++){ + Tile tile = world.tileWorld(x + cx*tilesize, y + cy*tilesize); + if(tile == null) continue; + float scl = (Math.abs(cx) + Math.abs(cy) > 1 ? 1f / Mathf.sqrt2 : Math.abs(cx) + Math.abs(cy) == 1 ? 0.8f : 1f) * 0.2f; + + moveVector.add(-cx * scaling * tile.weight * scl, -cy*scaling * tile.weight * scl); + } + } + + applyImpulse(moveVector.x, moveVector.y); + + Tile tile = world.tileWorld(x, y); + + if(tile != null){ + lastWeightDelta = Math.min((int)(mass()), 127 - tile.weight); + lastWeightTile = tile.pos(); + tile.weight += lastWeightDelta; + }else{ + lastWeightTile = Pos.invalid; + } } public TileEntity getClosestCore(){ diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 940ee96671..3dcc1862e3 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -31,6 +31,8 @@ public class Tile implements Position, TargetTrait{ public byte link = 0; /** Tile traversal cost. */ public byte cost = 1; + /** Weight of [ground] units on this tile.*/ + public byte weight = 0; /** Tile entity, usually null. */ public TileEntity entity; public short x, y; From eb3d5b62f572cb72b0cde8bed67618804da50699 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 29 Mar 2019 22:48:04 -0400 Subject: [PATCH 2/5] Tweaks --- core/src/io/anuke/mindustry/entities/type/Unit.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index 7735622074..cfbe040678 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -238,20 +238,22 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } } - final int rad = 1; + final int rad = 2; moveVector.setZero(); for(int cx = -rad; cx <= rad; cx++){ for(int cy = -rad; cy <= rad; cy++){ Tile tile = world.tileWorld(x + cx*tilesize, y + cy*tilesize); if(tile == null) continue; - float scl = (Math.abs(cx) + Math.abs(cy) > 1 ? 1f / Mathf.sqrt2 : Math.abs(cx) + Math.abs(cy) == 1 ? 0.8f : 1f) * 0.2f; + float scl = (rad - Mathf.dst(tile.worldx(), tile.worldy(), x, y)/(8f * 1.2f * Mathf.sqrt2)) * 0.08f; - moveVector.add(-cx * scaling * tile.weight * scl, -cy*scaling * tile.weight * scl); + moveVector.add(Mathf.sign(x - tile.worldx()) * scaling * tile.weight * scl, Mathf.sign(y - tile.worldy()) * scaling * tile.weight * scl); } } - applyImpulse(moveVector.x, moveVector.y); + //moveVector.limit(0.2f); + + move(moveVector.x, moveVector.y); Tile tile = world.tileWorld(x, y); From 83bde8a7816ddbe32f62e1794afdfb4aa35c6d23 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 30 Mar 2019 12:33:01 -0400 Subject: [PATCH 3/5] Improved avoidance --- core/src/io/anuke/mindustry/ai/Pathfinder.java | 2 +- core/src/io/anuke/mindustry/entities/type/GroundUnit.java | 4 ++-- core/src/io/anuke/mindustry/entities/type/Unit.java | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index bd162140e5..9121162cfb 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -65,7 +65,7 @@ public class Pathfinder{ Tile other = world.tile(dx, dy); if(other == null) continue; - if(values[dx][dy] < value && (target == null || values[dx][dy] < tl) && + if(values[dx][dy] < value && (target == null || values[dx][dy]< tl) && !other.solid() && !(point.x != 0 && point.y != 0 && (world.solid(tile.x + point.x, tile.y) || world.solid(tile.x, tile.y + point.y)))){ //diagonal corner trap target = other; diff --git a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java index f7dc634a44..79318f4b4f 100644 --- a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -215,7 +215,7 @@ public abstract class GroundUnit extends BaseUnit{ velocity.add(vec.trns(angleTo(targetTile), type.speed*Time.delta())); if(Units.invalidateTarget(target, this)){ - rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); + rotation = Mathf.slerpDelta(rotation, baseRotation, type.rotatespeed); } } @@ -240,6 +240,6 @@ public abstract class GroundUnit extends BaseUnit{ float angle = angleTo(targetTile); velocity.add(vec.trns(angleTo(targetTile), type.speed*Time.delta())); - rotation = Mathf.slerpDelta(rotation, angle, type.rotatespeed); + rotation = Mathf.slerpDelta(rotation, baseRotation, type.rotatespeed); } } diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index cfbe040678..e9b48b1b00 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -245,15 +245,15 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ for(int cy = -rad; cy <= rad; cy++){ Tile tile = world.tileWorld(x + cx*tilesize, y + cy*tilesize); if(tile == null) continue; - float scl = (rad - Mathf.dst(tile.worldx(), tile.worldy(), x, y)/(8f * 1.2f * Mathf.sqrt2)) * 0.08f; + float scl = (rad - Mathf.dst(tile.worldx(), tile.worldy(), x, y)/(8f * 1.2f * Mathf.sqrt2)) * 0.1f; moveVector.add(Mathf.sign(x - tile.worldx()) * scaling * tile.weight * scl, Mathf.sign(y - tile.worldy()) * scaling * tile.weight * scl); } } - //moveVector.limit(0.2f); + moveVector.limit(0.2f); - move(moveVector.x, moveVector.y); + applyImpulse(moveVector.x, moveVector.y); Tile tile = world.tileWorld(x, y); From e9eb981782195f55a0f08b109698b1ec556e7689 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 30 Mar 2019 12:54:29 -0400 Subject: [PATCH 4/5] More optimization / Flying avoidance --- .../anuke/mindustry/entities/EntityDraw.java | 12 ++++----- .../anuke/mindustry/entities/type/Unit.java | 26 ++++++++++++++----- core/src/io/anuke/mindustry/world/Tile.java | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/core/src/io/anuke/mindustry/entities/EntityDraw.java b/core/src/io/anuke/mindustry/entities/EntityDraw.java index e0a95627c2..60c67959ff 100644 --- a/core/src/io/anuke/mindustry/entities/EntityDraw.java +++ b/core/src/io/anuke/mindustry/entities/EntityDraw.java @@ -6,6 +6,7 @@ import io.anuke.arc.function.Predicate; import io.anuke.arc.graphics.Camera; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.mindustry.entities.traits.Entity; public class EntityDraw{ private static final Rectangle viewport = new Rectangle(); @@ -42,15 +43,12 @@ public class EntityDraw{ viewport.set(cam.position.x - cam.width / 2, cam.position.y - cam.height / 2, cam.width, cam.height); } - group.forEach(e -> { - if(!(e instanceof DrawTrait)) return; - T t = (T) e; - - if(!toDraw.test(t) || !e.isAdded()) return; + for(Entity e : group.all()){ + if(!(e instanceof DrawTrait) || !toDraw.test((T)e) || !e.isAdded()) continue; if(!clip || rect.setSize(((DrawTrait) e).drawSize()).setCenter(e.getX(), e.getY()).overlaps(viewport)){ - cons.accept(t); + cons.accept((T)e); } - }); + } } } diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index e9b48b1b00..e919b077f2 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -50,6 +50,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ private static final Vector2 moveVector = new Vector2(); private int lastWeightTile = Pos.invalid, lastWeightDelta; + private boolean wasFlying = false; public float rotation; @@ -228,13 +229,19 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } public void avoidOthers(float scaling){ - if(isFlying()) return; + boolean flying = isFlying(); if(lastWeightTile != Pos.invalid){ Tile tile = world.tile(lastWeightTile); if(tile != null){ - tile.weight -= Math.min(lastWeightDelta, tile.weight); + int dec = Math.min(lastWeightDelta, wasFlying ? tile.airWeight : tile.weight); + if(!wasFlying){ + tile.weight -= dec; + }else{ + tile.airWeight -= dec; + } + } } @@ -245,25 +252,32 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ for(int cy = -rad; cy <= rad; cy++){ Tile tile = world.tileWorld(x + cx*tilesize, y + cy*tilesize); if(tile == null) continue; + int weight = flying ? tile.airWeight : tile.weight; float scl = (rad - Mathf.dst(tile.worldx(), tile.worldy(), x, y)/(8f * 1.2f * Mathf.sqrt2)) * 0.1f; - moveVector.add(Mathf.sign(x - tile.worldx()) * scaling * tile.weight * scl, Mathf.sign(y - tile.worldy()) * scaling * tile.weight * scl); + moveVector.add(Mathf.sign(x - tile.worldx()) * scaling * weight * scl, Mathf.sign(y - tile.worldy()) * scaling * weight * scl); } } - moveVector.limit(0.2f); + moveVector.limit(flying ? 0.1f : 0.2f); applyImpulse(moveVector.x, moveVector.y); Tile tile = world.tileWorld(x, y); if(tile != null){ - lastWeightDelta = Math.min((int)(mass()), 127 - tile.weight); + int tw = flying ? tile.airWeight : tile.weight; + lastWeightDelta = Math.min((int)(mass()), 127 - tw); lastWeightTile = tile.pos(); - tile.weight += lastWeightDelta; + if(!flying){ + tile.weight += lastWeightDelta; + }else{ + tile.airWeight += lastWeightDelta; + } }else{ lastWeightTile = Pos.invalid; } + wasFlying = flying; } public TileEntity getClosestCore(){ diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 3dcc1862e3..46fce1527e 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -32,7 +32,7 @@ public class Tile implements Position, TargetTrait{ /** Tile traversal cost. */ public byte cost = 1; /** Weight of [ground] units on this tile.*/ - public byte weight = 0; + public byte weight, airWeight = 0; /** Tile entity, usually null. */ public TileEntity entity; public short x, y; From c31f88a318e17d5b392b1dfe926656328627cc7e Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 30 Mar 2019 13:01:55 -0400 Subject: [PATCH 5/5] Fixes --- core/src/io/anuke/mindustry/entities/type/Unit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index e919b077f2..00245c3048 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -261,7 +261,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ moveVector.limit(flying ? 0.1f : 0.2f); - applyImpulse(moveVector.x, moveVector.y); + velocity.add(moveVector.x / mass() * Time.delta(), moveVector.y / mass() * Time.delta()); Tile tile = world.tileWorld(x, y);