More animation improvements

This commit is contained in:
Anuken
2022-02-03 12:47:52 -05:00
parent 2f989d57bb
commit 18c192d307
11 changed files with 157 additions and 45 deletions

View File

@@ -5,6 +5,7 @@ import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
@@ -138,6 +139,7 @@ public class BulletType extends Content implements Cloneable{
public @Nullable BulletType fragBullet = null;
public Color hitColor = Color.white;
public Color healColor = Pal.heal;
public Seq<BulletType> spawnBullets = new Seq<>();
public Color trailColor = Pal.missileYellowBack;
public float trailChance = -0.0001f;

View File

@@ -9,32 +9,33 @@ import arc.util.*;
import mindustry.graphics.*;
public class RegionPart extends WeaponPart{
protected PartParams childParam = new PartParams();
public String suffix = "";
public TextureRegion heat;
public TextureRegion[] regions = {};
public TextureRegion[] outlines = {};
/** If true, turret reload is used as the measure of progress. Otherwise, warmup is used. */
public boolean useReload = true;
/** If true, parts are mirrored across the turret. Requires -1 and -2 regions. */
public boolean mirror = false;
/** If true, an outline is drawn under the part. */
public boolean outline = true;
/** If true, the base + outline regions are drawn. Set to false for heat-only regions. */
public boolean drawRegion = true;
/** If true, progress is inverted. */
public boolean invert = false;
/** Progress function for determining position/rotation. */
public PartProgress progress = PartProgress.warmup;
/** Progress function for heat alpha. */
public PartProgress heatProgress = PartProgress.heat;
public Blending blending = Blending.normal;
public boolean useProgressHeat = false;
public Interp interp = Interp.linear;
public float layer = -1;
public float outlineLayerOffset = -0.01f;
public float layer = -1, layerOffset = 0f;
public float outlineLayerOffset = -0.001f;
public float rotation, rotMove;
public float x, y, moveX, moveY;
public float oscMag = 0f, oscScl = 7f;
public boolean oscAbs = false;
public @Nullable Color color, colorTo;
public Color heatColor = Pal.turretHeat.cpy();
public @Nullable WeaponPart child;
public RegionPart(String region){
this.suffix = region;
@@ -49,26 +50,27 @@ public class RegionPart extends WeaponPart{
if(layer > 0) Draw.z(layer);
//TODO 'under' should not be special cased like this...
if(under && turretShading) Draw.z(z - 0.0001f);
Draw.z(Draw.z() + layerOffset);
float prevZ = Draw.z();
float progress = useReload ? 1f - params.reload : params.warmup;
float prog = progress.get(params);
if(oscMag > 0) progress += oscAbs ? Mathf.absin(oscScl, oscMag) : Mathf.sin(oscScl, oscMag);
if(invert) progress = 1f - progress;
prog = interp.apply(prog);
int len = mirror && params.sideOverride == -1 ? 2 : 1;
progress = interp.apply(progress);
int len = mirror ? 2 : 1;
for(int s = 0; s < len; s++){
//use specific side if necessary
int i = params.sideOverride == -1 ? s : params.sideOverride;
for(int i = 0; i < len; i++){
//can be null
var region = drawRegion ? regions[Math.min(i, regions.length - 1)] : null;
float sign = i == 1 ? -1 : 1;
Tmp.v1.set((x + moveX * progress) * sign, y + moveY * progress).rotate((params.rotation - 90));
Tmp.v1.set((x + moveX * prog) * sign, y + moveY * prog).rotate(params.rotation - 90);
float
rx = params.x + Tmp.v1.x,
ry = params.y + Tmp.v1.y,
rot = i * sign + rotMove * progress * sign + params.rotation - 90;
rot = rotMove * prog * sign + params.rotation - 90;
Draw.xscl = i == 0 ? 1 : -1;
@@ -80,7 +82,7 @@ public class RegionPart extends WeaponPart{
if(drawRegion && region.found()){
if(color != null && colorTo != null){
Draw.color(color, colorTo, progress);
Draw.color(color, colorTo, prog);
}else if(color != null){
Draw.color(color);
}
@@ -91,13 +93,27 @@ public class RegionPart extends WeaponPart{
}
if(heat.found()){
Drawf.additive(heat, heatColor.write(Tmp.c1).a((useProgressHeat ? params.warmup : params.heat) * heatColor.a), rx, ry, rot, turretShading ? Layer.turretHeat : z + 1f);
Drawf.additive(heat, heatColor.write(Tmp.c1).a(heatProgress.get(params) * heatColor.a), rx, ry, rot, turretShading ? Layer.turretHeat : z + 1f);
}
Draw.xscl = 1f;
}
Draw.z(z);
//draw child, if applicable - only at the end
//TODO lots of copy-paste here
if(child != null){
for(int s = 0; s < len; s++){
int i = (params.sideOverride == -1 ? s : params.sideOverride);
float sign = i == 1 ? -1 : 1;
Tmp.v1.set((x + moveX * prog) * sign, y + moveY * prog).rotate(params.rotation - 90);
childParam.set(params.warmup, params.reload, params.smoothReload, params.heat, params.x + Tmp.v1.x, params.y + Tmp.v1.y, i * sign + rotMove * prog * sign + params.rotation);
childParam.sideOverride = i;
child.draw(childParam);
}
}
}
@Override
@@ -121,6 +137,9 @@ public class RegionPart extends WeaponPart{
}
heat = Core.atlas.find(name + suffix + "-heat");
if(child != null){
child.load(name);
}
}
@Override
@@ -128,5 +147,8 @@ public class RegionPart extends WeaponPart{
if(outline && drawRegion){
out.addAll(regions);
}
if(child != null){
child.getOutlines(out);
}
}
}

View File

@@ -1,6 +1,7 @@
package mindustry.entities.part;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.struct.*;
public abstract class WeaponPart{
@@ -18,17 +19,83 @@ public abstract class WeaponPart{
/** Parameters for drawing a part in draw(). */
public static class PartParams{
//TODO document
public float warmup, reload, heat;
public float warmup, reload, smoothReload, heat;
public float x, y, rotation;
public int sideOverride = -1;
public PartParams set(float warmup, float reload, float heat, float x, float y, float rotation){
public PartParams set(float warmup, float reload, float smoothReload, float heat, float x, float y, float rotation){
this.warmup = warmup;
this.reload = reload;
this.heat = heat;
this.smoothReload = smoothReload;
this.x = x;
this.y = y;
this.rotation = rotation;
this.sideOverride = -1;
return this;
}
}
public interface PartProgress{
PartProgress
reload = p -> p.reload,
smoothReload = p -> p.smoothReload,
warmup = p -> p.warmup,
heat = p -> p.heat;
float get(PartParams p);
static PartProgress constant(float value){
return p -> value;
}
default PartProgress inv(){
return p -> 1f - get(p);
}
default PartProgress delay(float amount){
return p -> Mathf.clamp((get(p) - amount) / (1f - amount));
}
default PartProgress shorten(float amount){
return p -> Mathf.clamp(get(p) / (1f - amount));
}
default PartProgress blend(PartProgress other, float amount){
return p -> Mathf.lerp(get(p), other.get(p), amount);
}
default PartProgress mul(PartProgress other){
return p -> get(p) * other.get(p);
}
default PartProgress min(PartProgress other){
return p -> Math.min(get(p), other.get(p));
}
default PartProgress sin(float scl, float mag){
return p -> Mathf.clamp(get(p) + Mathf.sin(scl, mag));
}
default PartProgress absin(float scl, float mag){
return p -> Mathf.clamp(get(p) + Mathf.absin(scl, mag));
}
default PartProgress apply(PartProgress other, PartFunc func){
return p -> func.get(get(p), other.get(p));
}
default PartProgress add(float amount){
return p -> Mathf.clamp(get(p) + amount);
}
default PartProgress curve(Interp interp){
return p -> interp.apply(get(p));
}
}
public interface PartFunc{
float get(float a, float b);
}
}

View File

@@ -20,6 +20,8 @@ public class WeaponMount{
public float heat;
/** lerps to 1 when shooting, 0 when not */
public float warmup;
/** lerps to reload time */
public float smoothReload;
/** aiming position in world coordinates */
public float aimX, aimY;
/** whether to shoot right now */