leg 1
This commit is contained in:
@@ -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){
|
||||
|
||||
@@ -4,4 +4,5 @@ import arc.math.geom.*;
|
||||
|
||||
public class Leg{
|
||||
public final Vec2 joint = new Vec2(), base = new Vec2();
|
||||
public int group;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
30
core/src/mindustry/graphics/InverseKinematics.java
Normal file
30
core/src/mindustry/graphics/InverseKinematics.java
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user