diff --git a/core/assets-raw/sprites/units/cix-foot.png b/core/assets-raw/sprites/units/cix-foot.png index 1e0d2bfcb7..0919d7ae30 100644 Binary files a/core/assets-raw/sprites/units/cix-foot.png and b/core/assets-raw/sprites/units/cix-foot.png differ diff --git a/core/assets-raw/sprites/units/cix-leg-base.png b/core/assets-raw/sprites/units/cix-leg-base.png index 6401faf7ee..98f6a67bc1 100644 Binary files a/core/assets-raw/sprites/units/cix-leg-base.png and b/core/assets-raw/sprites/units/cix-leg-base.png differ diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 6ca4632feb..daa5c72210 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/sprites/sprites2.png b/core/assets/sprites/sprites2.png index c8ab971458..1adae2fcd9 100644 Binary files a/core/assets/sprites/sprites2.png and b/core/assets/sprites/sprites2.png differ diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 3f6f8a869f..7bb74a4aa4 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -235,18 +235,19 @@ public class UnitTypes implements ContentList{ cix = new UnitType("cix"){{ drag = 0.1f; - speed = 0.4f; + speed = 0.5f; hitsize = 9f; health = 140; baseElevation = 0.51f; legCount = 6; - legMoveSpace = 0.9f; + legMoveSpace = 1f; + legPairOffset = 3; legLength = 34f; rotateShooting = false; legExtension = -15; - legBaseOffset = 8f; - landShake = 2f; + legBaseOffset = 10f; + landShake = 0f; legSpeed = 0.1f; for(boolean b : Mathf.booleans){ diff --git a/core/src/mindustry/entities/Leg.java b/core/src/mindustry/entities/Leg.java index 24e032e482..1bfb23ad9b 100644 --- a/core/src/mindustry/entities/Leg.java +++ b/core/src/mindustry/entities/Leg.java @@ -4,4 +4,5 @@ import arc.math.geom.*; public class Leg{ public final Vec2 joint = new Vec2(), base = new Vec2(); + public int group; } diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index 4791739786..c957a26943 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -1,12 +1,14 @@ package mindustry.entities.comp; import arc.math.*; +import arc.math.geom.*; import arc.util.*; import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.entities.*; import mindustry.gen.*; +import mindustry.graphics.*; import mindustry.type.*; import mindustry.world.blocks.environment.*; @@ -52,14 +54,32 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc, Elevatio totalLength += Mathf.dst(deltaX(), deltaY()); - int stage = (int)(totalLength / moveSpace); - int group = stage % div; - if(lastGroup != group){ - //create ripple effects when switching leg groups - int i = 0; - for(Leg l : legs){ - if(i++ % div == lastGroup){ + //float movespace = 360f / legs.length / 4f; + float stepMult = 0.8f; + float trns = legLength/2f*stepMult * 1.3f;//Mathf.dst(deltaX(), deltaY()) * 12.5f * div/1.5f * type.legTrns; + + //trns = moveSpace * 0.7f; + //trns = 0; + + //rotation + offset vector + Vec2 posOffset = Tmp.v4.trns(rot, trns); + float approach = Mathf.dst(deltaX(), deltaY()); + + for(int i = 0; i < legs.length; i++){ + Leg l = legs[i]; + float dstRot = legAngle(rot, i); + boolean side = i < legs.length/2; + //float rot2 = Angles.moveToward(dstRot, rot + (Angles.angleDist(dstRot, rot) < 90f ? 180f : 0), movespace); + + int stage = (int)((totalLength + i*type.legPairOffset) / moveSpace); + int group = stage % div; + boolean move = i % div == group; + + if(l.group != group){ + + //create effect when transitioning to a group it can't move in + if(!move && i % div == l.group){ Floor floor = Vars.world.floorWorld(l.base.x, l.base.y); if(floor.isLiquid){ floor.walkEffect.at(l.base.x, l.base.y, 0, floor.mapColor); @@ -69,37 +89,35 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc, Elevatio //shake when legs contact ground if(type.landShake > 0){ - Effects.shake(type.landShake, type.landShake, this); + Effects.shake(type.landShake, type.landShake, l.base); } } + + + l.group = group; } - lastGroup = group; - } - - float movespace = 360f / legs.length / 4f; - float trns = vel().len() * 12.5f * div/1.5f * type.legTrns; - - //rotation + offset vector - Tmp.v4.trns(rot, trns); - - for(int i = 0; i < legs.length; i++){ - float dstRot = legAngle(rot, i); - float rot2 = Angles.moveToward(dstRot, rot + (Angles.angleDist(dstRot, rot) < 90f ? 180f : 0), movespace); - - Leg l = legs[i]; + Vec2 offset = Tmp.v5.trns(dstRot, type.legBaseOffset).add(x, y); //leg destination - Tmp.v1.trns(dstRot, legLength + type.legBaseOffset).add(x, y).add(Tmp.v4); - //join destination - Tmp.v2.trns(rot2, legLength / 2f + type.legBaseOffset).add(x, y).add(Tmp.v4); + Vec2 footDest = Tmp.v1.trns(dstRot - Mathf.sign(i % 2 == 0) * 0, legLength*stepMult).add(offset).add(posOffset); + //joint destination + //Tmp.v2.trns(rot2, legLength / 2f + type.legBaseOffset).add(x, y).add(offset); - if(i % div == group){ - l.base.lerpDelta(Tmp.v1, moveSpeed); - l.joint.lerpDelta(Tmp.v2, moveSpeed / 4f); + + if(move){ + l.base.lerpDelta(footDest, moveSpeed); + //l.joint.lerpDelta(Tmp.v2, moveSpeed / 4f); } - l.joint.lerpDelta(Tmp.v2, moveSpeed / 4f); + Vec2 result = Tmp.v2; + InverseKinematics.solve(legLength/2f, legLength/2f, Tmp.v6.set(l.base).sub(offset), side, result); + result.add(offset); + + // if() + + //l.joint.lerpDelta(Tmp.v2, moveSpeed / 4f); + l.joint.set(result); } } diff --git a/core/src/mindustry/graphics/InverseKinematics.java b/core/src/mindustry/graphics/InverseKinematics.java new file mode 100644 index 0000000000..55ffd411b1 --- /dev/null +++ b/core/src/mindustry/graphics/InverseKinematics.java @@ -0,0 +1,30 @@ +package mindustry.graphics; + +import arc.math.*; +import arc.math.geom.*; + +public class InverseKinematics{ + private static final Vec2[] mat1 = {new Vec2(), new Vec2()}, mat2 = {new Vec2(), new Vec2()}; + private static final Vec2 temp = new Vec2(), temp2 = new Vec2(), at1 = new Vec2(), at2 = new Vec2(); + + static public boolean solve(float lengthA, float lengthB, Vec2 end, boolean side, Vec2 result){ + at1.set(end).rotate(side ? 1 : -1).setLength(lengthA + lengthB).add(end.x / 2f, end.y / 2f); + return solve(lengthA, lengthB, end, at1, result); + } + + static public boolean solve(float lengthA, float lengthB, Vec2 end, Vec2 attractor, Vec2 result){ + Vec2 axis = mat2[0].set(end).nor(); + mat2[1].set(attractor).sub(temp2.set(axis).scl(attractor.dot(axis))).nor(); + mat1[0].set(mat2[0].x, mat2[1].x); + mat1[1].set(mat2[0].y, mat2[1].y); + result.set(mat2[0].dot(end), mat2[1].dot(end)); + float len = result.len(); + float dist = Math.max(0, Math.min(lengthA, (len + (lengthA * lengthA - lengthB * lengthB) / len) / 2)); + float e = Mathf.sqrt(lengthA * lengthA - dist * dist); + Vec2 src = temp.set(dist, e); + result.set(mat1[0].dot(src), mat1[1].dot(src)); + + return dist > 0 && dist < lengthA; + } + +} \ No newline at end of file diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 9c2e862247..57602a15d3 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -27,6 +27,7 @@ import static mindustry.Vars.*; public class UnitType extends UnlockableContent{ public static final float shadowTX = -12, shadowTY = -13, shadowColor = Color.toFloatBits(0, 0, 0, 0.22f); + public static final boolean debug = false; private static final Vec2 legOffset = new Vec2(); public boolean flying; @@ -45,7 +46,7 @@ public class UnitType extends UnlockableContent{ //TODO document public int legCount = 4; - public float legLength = 10f, legSpeed = 0.1f, legTrns = 1f, legBaseOffset = 0f, legMoveSpace = 1f, legExtension = 0; + public float legLength = 10f, legSpeed = 0.1f, legTrns = 1f, legBaseOffset = 0f, legMoveSpace = 1f, legExtension = 0, legPairOffset = 0; public int itemCapacity = 30; public int drillTier = -1; @@ -172,9 +173,11 @@ public class UnitType extends UnlockableContent{ Draw.z(z); drawEngine(unit); - drawBody(unit); - if(drawCell) drawCell(unit); - drawWeapons(unit); + if(!debug){ + drawBody(unit); + if(drawCell) drawCell(unit); + drawWeapons(unit); + } if(drawItems) drawItems(unit); drawLight(unit); @@ -350,35 +353,40 @@ public class UnitType extends UnlockableContent{ Draw.rect(baseRegion, unit.x(), unit.y(), rotation); } - int index = 0; - //TODO figure out layering - for(Leg leg : legs){ - float angle = unit.legAngle(rotation, index); - boolean flip = index++ >= legs.length/2f; + for(int i = 0; i < legs.length; i++){ + Leg leg = legs[i]; + float angle = unit.legAngle(rotation, i); + boolean flip = i >= legs.length/2f; int flips = Mathf.sign(flip); Vec2 position = legOffset.trns(angle, legBaseOffset).add(unit); Tmp.v1.set(leg.base).sub(leg.joint).inv().setLength(legExtension); - Draw.color(); + if(debug){ + Draw.color(Color.red); + Lines.line(position.x, position.y, leg.joint.x, leg.joint.y); - Lines.stroke(legRegion.getHeight() * Draw.scl * flips); - Lines.line(legRegion, position.x, position.y, leg.joint.x, leg.joint.y, CapStyle.none, 0); + Draw.color(Color.green); + Lines.line(leg.joint.x, leg.joint.y, leg.base.x, leg.base.y); - Lines.stroke(legBaseRegion.getHeight() * Draw.scl * flips); - Lines.line(legBaseRegion, leg.joint.x + Tmp.v1.x, leg.joint.y + Tmp.v1.y, leg.base.x, leg.base.y, CapStyle.none, 0); + Draw.reset(); + }else{ + Draw.rect(footRegion, leg.base.x, leg.base.y, position.angleTo(leg.base)); - float angle2 = position.angleTo(leg.base); + Lines.stroke(legRegion.getHeight() * Draw.scl * flips); + Lines.line(legRegion, position.x, position.y, leg.joint.x, leg.joint.y, CapStyle.none, 0); - if(jointRegion.found()){ - Draw.rect(jointRegion, leg.joint.x, leg.joint.y); - } + Lines.stroke(legBaseRegion.getHeight() * Draw.scl * flips); + Lines.line(legBaseRegion, leg.joint.x + Tmp.v1.x, leg.joint.y + Tmp.v1.y, leg.base.x, leg.base.y, CapStyle.none, 0); - Draw.rect(footRegion, leg.base.x, leg.base.y, angle2); + if(jointRegion.found()){ + Draw.rect(jointRegion, leg.joint.x, leg.joint.y); + } - if(baseJointRegion.found()){ - Draw.rect(baseJointRegion, position.x, position.y, rotation); + if(baseJointRegion.found()){ + Draw.rect(baseJointRegion, position.x, position.y, rotation); + } } }