From 53b55a9f0e795d04ac1c5a4c990b0e18506164fb Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 12 Dec 2021 20:05:37 -0500 Subject: [PATCH] Tank animations & FX --- .../annotations/entity/EntityProcess.java | 10 ++--- .../sprites/units/vanquish-treads.png | Bin 555 -> 555 bytes core/assets-raw/sprites/units/vanquish.png | Bin 4452 -> 4432 bytes core/src/mindustry/content/Fx.java | 12 +++++- core/src/mindustry/content/UnitTypes.java | 4 ++ core/src/mindustry/entities/Effect.java | 16 ++++++++ .../mindustry/entities/EntityCollisions.java | 2 +- .../src/mindustry/entities/comp/MechComp.java | 9 +---- .../src/mindustry/entities/comp/TankComp.java | 26 +++++++++++- core/src/mindustry/type/UnitType.java | 37 +++++++++++++++++- tools/src/mindustry/tools/Generators.java | 22 +++++++++++ 11 files changed, 119 insertions(+), 19 deletions(-) diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index 3f8d56c249..a9ada9f45c 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -800,12 +800,12 @@ public class EntityProcess extends BaseProcessor{ } } - write(def.builder, imports.asArray()); + write(def.builder, imports.toSeq()); } //write base classes last for(TypeSpec.Builder b : baseClasses){ - write(b, imports.asArray()); + write(b, imports.toSeq()); } //TODO nulls were an awful idea @@ -878,7 +878,7 @@ public class EntityProcess extends BaseProcessor{ nullsBuilder.addField(FieldSpec.builder(type, Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build()); - write(nullBuilder, imports.asArray()); + write(nullBuilder, imports.toSeq()); } write(nullsBuilder); @@ -934,7 +934,7 @@ public class EntityProcess extends BaseProcessor{ out.addAll(getDependencies(comp)); } - defComponents.put(type, out.asArray()); + defComponents.put(type, out.toSeq()); } return defComponents.get(type); @@ -961,7 +961,7 @@ public class EntityProcess extends BaseProcessor{ //remove it again just in case out.remove(component); - componentDependencies.put(component, result.asArray()); + componentDependencies.put(component, result.toSeq()); } return componentDependencies.get(component); diff --git a/core/assets-raw/sprites/units/vanquish-treads.png b/core/assets-raw/sprites/units/vanquish-treads.png index dea46d155ed91bb3a1ddf56286930edca0a11f63..a8cbe1e0cd4a5726fef8e21aa358c0b2c637887d 100644 GIT binary patch delta 95 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 iUcGwt>eZ_kPyYvcNTHX4AZHH%0000 { color(Tmp.c1.set(e.color).mul(1.1f)); + //TODO doesn't respect rotation / size randLenVectors(e.id, 6, 17f * e.finpow(), (x, y) -> { Fill.circle(e.x + x, e.y + y, e.fout() * 4f + 0.3f); }); }).layer(Layer.debris), + unitDust = new Effect(30, e -> { + color(Tmp.c1.set(e.color).mul(1.3f)); + randLenVectors(e.id, 3, 8f * e.finpow(), e.rotation, 30f, (x, y) -> { + Fill.circle(e.x + x, e.y + y, e.fout() * 3f + 0.3f); + }); + }).layer(Layer.debris), + unitLandSmall = new Effect(30, e -> { color(Tmp.c1.set(e.color).mul(1.1f)); randLenVectors(e.id, (int)(6 * e.rotation), 12f * e.finpow() * e.rotation, (x, y) -> { diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index ebdd90c805..9c961396bc 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2429,6 +2429,10 @@ public class UnitTypes{ vanquish = new TankUnitType("vanquish"){{ hitSize = 28f; + speed = 0.6f; + health = 10000; + armor = 20f; + treadRect = new Rect(22f, 16f, 28f, 130f); }}; //endregion diff --git a/core/src/mindustry/entities/Effect.java b/core/src/mindustry/entities/Effect.java index aa32ed60db..6b164a3f98 100644 --- a/core/src/mindustry/entities/Effect.java +++ b/core/src/mindustry/entities/Effect.java @@ -166,6 +166,22 @@ public class Effect{ shake(intensity, duration, loc.getX(), loc.getY()); } + public static void floorDust(float x, float y, float size){ + Tile tile = world.tileWorld(x, y); + if(tile != null){ + Color color = tile.floor().mapColor; + Fx.unitLand.at(x, y, size, color); + } + } + + public static void floorDustAngle(Effect effect, float x, float y, float angle){ + Tile tile = world.tileWorld(x, y); + if(tile != null){ + Color color = tile.floor().mapColor; + effect.at(x, y, angle, color); + } + } + public static void create(Effect effect, float x, float y, float rotation, Color color, Object data){ if(headless || effect == Fx.none || !Core.settings.getBool("effects")) return; diff --git a/core/src/mindustry/entities/EntityCollisions.java b/core/src/mindustry/entities/EntityCollisions.java index 1a94f29fd6..f29a2c67f3 100644 --- a/core/src/mindustry/entities/EntityCollisions.java +++ b/core/src/mindustry/entities/EntityCollisions.java @@ -119,7 +119,7 @@ public class EntityCollisions{ @SuppressWarnings("unchecked") public void updatePhysics(EntityGroup group){ - QuadTree tree = group.tree(); + var tree = group.tree(); tree.clear(); group.each(s -> { diff --git a/core/src/mindustry/entities/comp/MechComp.java b/core/src/mindustry/entities/comp/MechComp.java index 18ffc784a7..ff4970e108 100644 --- a/core/src/mindustry/entities/comp/MechComp.java +++ b/core/src/mindustry/entities/comp/MechComp.java @@ -1,15 +1,12 @@ package mindustry.entities.comp; -import arc.graphics.*; import arc.math.*; import arc.math.geom.*; import arc.util.*; import mindustry.annotations.Annotations.*; -import mindustry.content.*; import mindustry.entities.*; import mindustry.gen.*; import mindustry.type.*; -import mindustry.world.*; import mindustry.world.blocks.environment.*; import static mindustry.Vars.*; @@ -52,11 +49,7 @@ abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, Elevati } if(type.mechStepParticles){ - Tile tile = world.tileWorld(cx, cy); - if(tile != null){ - Color color = tile.floor().mapColor; - Fx.unitLand.at(cx, cy, hitSize/8f, color); - } + Effect.floorDust(cx, cy, hitSize/8f); } } diff --git a/core/src/mindustry/entities/comp/TankComp.java b/core/src/mindustry/entities/comp/TankComp.java index f721b13bb3..320ddcf555 100644 --- a/core/src/mindustry/entities/comp/TankComp.java +++ b/core/src/mindustry/entities/comp/TankComp.java @@ -1,8 +1,10 @@ package mindustry.entities.comp; +import arc.math.*; import arc.math.geom.*; import arc.util.*; import mindustry.annotations.Annotations.*; +import mindustry.entities.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.blocks.environment.*; @@ -11,14 +13,36 @@ import static mindustry.Vars.*; @Component abstract class TankComp implements Posc, Flyingc, Hitboxc, Unitc, ElevationMovec{ - @Import float x, y, hitSize; + @Import float x, y, hitSize, rotation; @Import UnitType type; + transient private float treadEffectTime; + transient float treadTime; transient boolean walked; @Override public void update(){ + //dust + if(walked && !headless){ + treadEffectTime += Time.delta; + if(treadEffectTime >= 6f){ + var treadRegion = type.treadRegion; + var treadRect = type.treadRect; + + float xOffset = (treadRegion.width/2f - (treadRect.x + treadRect.width/2f)) / 4f; + float yOffset = (treadRegion.height/2f - (treadRect.y + treadRect.height/2f)) / 4f; + + for(int i : Mathf.signs){ + Tmp.v1.set(xOffset * i, yOffset - treadRect.height / 2f / 4f).rotate(rotation - 90); + + Effect.floorDustAngle(type.treadEffect, Tmp.v1.x + x, Tmp.v1.y + y, rotation + 180f); + } + + treadEffectTime = 0f; + } + } + //trigger animation only when walking manually if(walked || net.client()){ float len = deltaLen(); diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index b0dc05cc95..6e2a00ad57 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -34,6 +34,7 @@ import mindustry.world.blocks.units.*; import mindustry.world.consumers.*; import mindustry.world.meta.*; +import static arc.graphics.g2d.Draw.*; import static mindustry.Vars.*; //TODO document @@ -92,6 +93,7 @@ public class UnitType extends UnlockableContent{ public Effect fallEffect = Fx.fallSmoke; public Effect fallThrusterEffect = Fx.fallSmoke; public Effect deathExplosionEffect = Fx.dynamicExplosion; + public @Nullable Effect treadEffect; /** Additional sprites that are drawn with the unit. */ public Seq decals = new Seq<>(); public Seq abilities = new Seq<>(); @@ -117,6 +119,9 @@ public class UnitType extends UnlockableContent{ public boolean mechStepParticles = false; public Color mechLegColor = Pal.darkMetal; + public Rect treadRect = new Rect(); + public int treadFrames = 18; + public int itemCapacity = -1; public int ammoCapacity = -1; public AmmoType ammoType = new ItemAmmoType(Items.copper); @@ -166,8 +171,7 @@ public class UnitType extends UnlockableContent{ public Seq weapons = new Seq<>(); public TextureRegion baseRegion, legRegion, region, shadowRegion, cellRegion, softShadowRegion, jointRegion, footRegion, legBaseRegion, baseJointRegion, outlineRegion, treadRegion; - public TextureRegion[] wreckRegions; - public TextureRegion[] segmentRegions, segmentOutlineRegions; + public TextureRegion[] wreckRegions, segmentRegions, segmentOutlineRegions, treadRegions; protected float buildTime = -1f; protected @Nullable ItemStack[] totalRequirements, cachedRequirements, firstRequirements; @@ -437,6 +441,17 @@ public class UnitType extends UnlockableContent{ mechStepParticles = hitSize > 15f; } + if(treadEffect == null){ + treadEffect = new Effect(45, e -> { + color(Tmp.c1.set(e.color).mul(1.5f)); + Fx.rand.setSeed(e.id); + for(int i = 0; i < 3; i++){ + Fx.v.trns(e.rotation + Fx.rand.range(40f), Fx.rand.random(6f * e.finpow())); + Fill.circle(e.x + Fx.v.x + Fx.rand.range(3f), e.y + Fx.v.y + Fx.rand.range(3f), e.fout() * hitSize / 28f * 3f * Fx.rand.random(0.8f, 1.1f) + 0.3f); + } + }).layer(Layer.debris); + } + canHeal = weapons.contains(w -> w.bullet.healPercent > 0f); //add mirrored weapon variants @@ -498,6 +513,12 @@ public class UnitType extends UnlockableContent{ baseJointRegion = Core.atlas.find(name + "-joint-base"); footRegion = Core.atlas.find(name + "-foot"); treadRegion = Core.atlas.find(name + "-treads"); + if(treadRegion.found()){ + treadRegions = new TextureRegion[treadFrames]; + for(int i = 0; i < treadFrames; i++){ + treadRegions[i] = Core.atlas.find(name + "-treads" + i); + } + } legBaseRegion = Core.atlas.find(name + "-leg-base", name + "-leg"); baseRegion = Core.atlas.find(name + "-base"); cellRegion = Core.atlas.find(name + "-cell", Core.atlas.find("power-cell")); @@ -963,6 +984,18 @@ public class UnitType extends UnlockableContent{ public void drawTank(T unit){ Draw.rect(treadRegion, unit.x, unit.y, unit.rotation - 90); + + if(treadRegion.found()){ + int frame = (int)(unit.treadTime()) % treadFrames; + var region = treadRegions[frame]; + float xOffset = treadRegion.width/2f - (treadRect.x + treadRect.width/2f); + float yOffset = treadRegion.height/2f - (treadRect.y + treadRect.height/2f); + + for(int i : Mathf.signs){ + Tmp.v1.set(xOffset * i, yOffset).rotate(unit.rotation - 90); + Draw.rect(region, unit.x + Tmp.v1.x / 4f, unit.y + Tmp.v1.y / 4f, treadRect.width / 4f, region.height / 4f, unit.rotation - 90); + } + } } public void drawLegs(T unit){ diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index 4ffc842f12..6eededbe91 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -509,6 +509,28 @@ public class Generators{ } } + //generate tank animation + if(sample instanceof Tankc){ + Pixmap pix = get(type.treadRegion); + //slice is always 1 pixel wide + Pixmap slice = pix.crop((int)type.treadRect.x, (int)type.treadRect.y, 1, (int)type.treadRect.height); + int frames = type.treadFrames; + for(int i = 0; i < frames; i++){ + int pullOffset = 4; + Pixmap frame = new Pixmap(slice.width, slice.height); + for(int y = 0; y < slice.height; y++){ + int idx = y + i; + if(idx >= slice.height){ + idx -= slice.height; + idx += pullOffset; + } + + frame.setRaw(0, y, slice.getRaw(0, idx)); + } + save(frame, type.name + "-treads" + i); + } + } + outliner.get(type.jointRegion); outliner.get(type.footRegion); outliner.get(type.legBaseRegion);