From 18c192d30765dcea46b08153e970caa42e140ef3 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 3 Feb 2022 12:47:52 -0500 Subject: [PATCH] More animation improvements --- .../weapons/conquer-weapon-blade-heat.png | Bin 0 -> 1404 bytes .../units/weapons/conquer-weapon-blade.png | Bin 0 -> 638 bytes .../units/weapons/conquer-weapon-fold.png | Bin 0 -> 609 bytes core/src/mindustry/content/Blocks.java | 9 +-- core/src/mindustry/content/UnitTypes.java | 52 ++++++++----- .../mindustry/entities/bullet/BulletType.java | 2 + .../mindustry/entities/part/RegionPart.java | 58 +++++++++----- .../mindustry/entities/part/WeaponPart.java | 71 +++++++++++++++++- .../mindustry/entities/units/WeaponMount.java | 2 + core/src/mindustry/type/Weapon.java | 5 +- core/src/mindustry/world/draw/DrawTurret.java | 3 +- 11 files changed, 157 insertions(+), 45 deletions(-) create mode 100644 core/assets-raw/sprites/units/weapons/conquer-weapon-blade-heat.png create mode 100644 core/assets-raw/sprites/units/weapons/conquer-weapon-blade.png create mode 100644 core/assets-raw/sprites/units/weapons/conquer-weapon-fold.png diff --git a/core/assets-raw/sprites/units/weapons/conquer-weapon-blade-heat.png b/core/assets-raw/sprites/units/weapons/conquer-weapon-blade-heat.png new file mode 100644 index 0000000000000000000000000000000000000000..d3847c82db99b26fecf850d634a7aac68aa4be5d GIT binary patch literal 1404 zcmbu9jX%=~0Ed4oZ(B%|GB52?xFSt?otF~Dn3qw@#l&?e%e!kE&6c;EObX-XrPO7W z_m`P5VVF-X^S<&HXVREBuQ`+RKiuc@eV*q(_@;TdT~>lXApig#$ z6mr4qm8z>(XbNzWxTu8>NHd3g*-x|kyJLy>z!wM3&HM-np4@X=Rk&1&O;BL%C36!% zANOI9`7*uU4;L>yT@SpQYE4nA(jcc+5u|SWRdJ`7`j1Mxxnj zB|+GZ=Ae~P16to8sb<+L08ws9)$T9@TOczg*9vLHj0Go~sWzb@BnUpq1xuIbpCX$B zZ$VP~wc}I6fGsG#<8y?cNhH%w)?1*|wk-WU4$LIFM1~%X`BQlPFG$u;P-;<$Tj=r@Sg3>5EBR-;f+lXvg zMp&p;5%g7X{X?GI$LfAmuAjKm-ojPDOL)TeHPGwBU}wZrqjwPIC6qdJ-|FcK&2n48 zj7qQvvrdm>9D?YA)*BdeZKpS4<6GY9)v>>%49fHS;TPx`bbz1~2U?=CgD@c+UPq$= zY6m{&0%cmE{-oizAF{80qLl)Ao|wzr166`+mCF}H^3K8*2*A>9mLek-8O;3Yd~RVd z<-N{Ly5@`xNhc4p6UEKB8Hp#}KWM+@{v#u-tLB?_ zy2S|9>4Rr-tz17_(jjjx)4EM4>=t4R{}2;L0y}DnX7eG`z?4ajTsgR38)Ph z>8RDE{c~(T)A{8@u<)xkBn`Bnm=#z<(cO8Xtn>ud^ufc|_6%Wq1F(I&Gi}12rkS$m*k)!@4 z`H0$_6-#Am`DV!tD_giINn|%LF?!c;qP(!INsT4q$eA`15}xTy6`6%MgPpo1n~LV| zq9LrA>rq~X5Bxh@`qYJKQoqkQ#-h^tM=T4l9_+u%#}e;o+`yqEz%SPkqGVs<*ZBv{=7a`-6b6B=L@N{`JyH{t6nj@En8z{;!Sf!;fEd~(xIt4@_ZO*hsuO4JxRb=Vz;1c>P61~}H-`%Q8~6VMEM}=y literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/units/weapons/conquer-weapon-blade.png b/core/assets-raw/sprites/units/weapons/conquer-weapon-blade.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4181e03553bf69323d418d156769c4ae421054 GIT binary patch literal 638 zcmV-^0)hRBP)Px%I7vi7RCt{2*gs0dKokb>Q9R1p1ok2>C}L|ZcD8ov4a7@&5%ZZrcHkKRaF zHD#h;^*oJ$r&D{^f6MXFY?$ocESPH(=VQ3<$Ot;=e)jzcA2?Y9f1 zUT?K?8d&v~;ci9>i{COFsDY2zD}>k(riw}0N}OtO>hk~k>azNInub0--Z#I8O(^&2 zLV+gKx{NfV5ugf<0##@f7=~&yZB*KYlJ%;prRjSPS~zUaK?;ZOIY{AAP!H^$G8Q;w zo}Mf&@|TKUIJ6>3;qWpjfm3QP2T!};?6PIaT%FxkCXF#Ak1V9`K|hQ*^d5>`!_ zC|EsDBVbc;@WQS?w+cIVQ|_)B!r9dfK@bE%5ClOG1VIo4K@bE%5ClOG1VIo4K@g;$ Ye>p)1GsZcSsQ>@~07*qoM6N<$g4UcJg8%>k literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/units/weapons/conquer-weapon-fold.png b/core/assets-raw/sprites/units/weapons/conquer-weapon-fold.png new file mode 100644 index 0000000000000000000000000000000000000000..9ef6827464883edd587b9fcb0d4f34dc3add10f0 GIT binary patch literal 609 zcmV-n0-pVeP)Px%8%ab#RA_sd|*KMB*YKwW?T|5fkDF90M`4A_Nj#1St!VI&p)l z9qAII#Q53Ij-8~HzX{>^&-Y@#I1UhrL?V$$B(ly}~B08I(e@A0rF%gF7m z>uyUHFh!rLCzB3_+NrPOc-Sj~ZEdxM`1I%o18lXvBAP2y8jWYwF6$hT>$&(#wpj>f*2tbqM##sACaX_8$5)j*5 zISJZ|Q}t}>GGK`V#GNjWmH+@h-(R@hKE3VvRa3SLae#S%IT}v@4=+7^5(k(GuWZ!& zNpF|pfc@USQ2 spawnBullets = new Seq<>(); public Color trailColor = Pal.missileYellowBack; public float trailChance = -0.0001f; diff --git a/core/src/mindustry/entities/part/RegionPart.java b/core/src/mindustry/entities/part/RegionPart.java index 29f88a965d..8a54451928 100644 --- a/core/src/mindustry/entities/part/RegionPart.java +++ b/core/src/mindustry/entities/part/RegionPart.java @@ -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); + } } } \ No newline at end of file diff --git a/core/src/mindustry/entities/part/WeaponPart.java b/core/src/mindustry/entities/part/WeaponPart.java index cbb3426f7f..98d4ab94e3 100644 --- a/core/src/mindustry/entities/part/WeaponPart.java +++ b/core/src/mindustry/entities/part/WeaponPart.java @@ -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); + } } diff --git a/core/src/mindustry/entities/units/WeaponMount.java b/core/src/mindustry/entities/units/WeaponMount.java index a0e5219bcf..8473edaf9c 100644 --- a/core/src/mindustry/entities/units/WeaponMount.java +++ b/core/src/mindustry/entities/units/WeaponMount.java @@ -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 */ diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java index fbe7c00d66..553234c3d0 100644 --- a/core/src/mindustry/type/Weapon.java +++ b/core/src/mindustry/type/Weapon.java @@ -93,7 +93,7 @@ public class Weapon implements Cloneable{ /** ticks to cool down the heat region */ public float cooldownTime = 20f; /** lerp speed for shoot warmup, only used for parts */ - public float shootWarmupSpeed = 0.1f; + public float shootWarmupSpeed = 0.1f, smoothReloadSpeed = 0.15f; /** random sound pitch range */ public float soundPitchMin = 0.8f, soundPitchMax = 1f; /** whether shooter rotation is ignored when shooting. */ @@ -193,7 +193,7 @@ public class Weapon implements Cloneable{ Draw.xscl = -Mathf.sign(flipSprite); if(parts.size > 0){ - WeaponPart.params.set(mount.warmup, 1f - Mathf.clamp(mount.reload / reload), mount.heat, wx, wy, weaponRotation + 90); + WeaponPart.params.set(mount.warmup, mount.reload / reload, mount.smoothReload, mount.heat, wx, wy, weaponRotation + 90); for(int i = 0; i < parts.size; i++){ var part = parts.items[i]; @@ -246,6 +246,7 @@ public class Weapon implements Cloneable{ mount.reload = Math.max(mount.reload - Time.delta * unit.reloadMultiplier, 0); mount.recoil = Mathf.approachDelta(mount.recoil, 0, (Math.abs(recoil) * unit.reloadMultiplier) / recoilTime); mount.warmup = Mathf.lerpDelta(mount.warmup, can && mount.shoot ? 1f : 0f, shootWarmupSpeed); + mount.smoothReload = Mathf.lerpDelta(mount.smoothReload, mount.reload / reload, smoothReloadSpeed); //rotate if applicable if(rotate && (mount.rotate || mount.shoot) && can){ diff --git a/core/src/mindustry/world/draw/DrawTurret.java b/core/src/mindustry/world/draw/DrawTurret.java index 952a4c7613..5a26148ac7 100644 --- a/core/src/mindustry/world/draw/DrawTurret.java +++ b/core/src/mindustry/world/draw/DrawTurret.java @@ -65,7 +65,8 @@ public class DrawTurret extends DrawBlock{ Draw.z(Layer.turret); } - var params = WeaponPart.params.set(build.warmup(), tb.progress(), tb.heat, tb.x + tb.recoilOffset.x, tb.y + tb.recoilOffset.y, tb.rotation); + //TODO no smooth reload + var params = WeaponPart.params.set(build.warmup(), 1f - tb.progress(), 1f - tb.progress(), tb.heat, tb.x + tb.recoilOffset.x, tb.y + tb.recoilOffset.y, tb.rotation); for(var part : parts){ part.draw(params);