Enable full customization of core launching/landing animations. (#9693)

* Extract all updates and draws of core launch/land animations to CoreBlock/CoreBuild

* Re-add removed methods as deprecated

* Fixed tests failing

* anuke said no

* Extract launch effect
This commit is contained in:
GlFolker
2024-04-01 21:46:44 +07:00
committed by GitHub
parent 1f5d8b1f04
commit bfd8dbd769
6 changed files with 221 additions and 138 deletions

View File

@@ -1,11 +1,15 @@
package mindustry.world.blocks.storage;
import arc.*;
import arc.audio.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.scene.actions.*;
import arc.scene.event.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
@@ -29,6 +33,9 @@ import mindustry.world.modules.*;
import static mindustry.Vars.*;
public class CoreBlock extends StorageBlock{
protected static final float cloudScaling = 1700f, cfinScl = -2f, cfinOffset = 0.3f, calphaFinOffset = 0.25f, cloudAlpha = 0.81f;
protected static final float[] cloudAlphas = {0, 0.5f, 1f, 0.1f, 0, 0f};
//hacky way to pass item modules between methods
private static ItemModule nextItems;
protected static final float[] thrusterSizes = {0f, 0f, 0f, 0f, 0.3f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0f};
@@ -42,6 +49,12 @@ public class CoreBlock extends StorageBlock{
public boolean incinerateNonBuildable = false;
public UnitType unitType = UnitTypes.alpha;
public float landDuration = 160f;
public Music landMusic = Musics.land;
public Effect launchEffect = Fx.launch;
public Interp landZoomInterp = Interp.pow3;
public float landZoomFrom = 0.02f, landZoomTo = 4f;
public float captureInvicibility = 60f * 15f;
@@ -217,11 +230,8 @@ public class CoreBlock extends StorageBlock{
}
public void drawLanding(CoreBuild build, float x, float y){
float fout = renderer.getLandTime() / coreLandDuration;
if(renderer.isLaunching()) fout = 1f - fout;
float fin = 1f - fout;
float fin = renderer.getLandTimeIn();
float fout = 1f - fin;
float scl = Scl.scl(4f) / renderer.getDisplayScale();
float shake = 0f;
@@ -312,6 +322,17 @@ public class CoreBlock extends StorageBlock{
public float iframes = -1f;
public float thrusterTime = 0f;
protected float cloudSeed;
//utility methods for less Block-to-CoreBlock casts. also allows for more customization
public float landDuration(){
return landDuration;
}
public Music landMusic(){
return landMusic;
}
@Override
public void draw(){
//draw thrusters when just landed
@@ -331,6 +352,115 @@ public class CoreBlock extends StorageBlock{
}
}
// `launchType` is null if it's landing instead of launching.
public void beginLaunch(@Nullable CoreBlock launchType){
cloudSeed = Mathf.random(1f);
if(launchType != null){
Fx.coreLaunchConstruct.at(x, y, launchType.size);
}
if(!headless){
// Add fade-in and fade-out foreground when landing or launching.
if(renderer.isLaunching()){
float margin = 30f;
Image image = new Image();
image.color.a = 0f;
image.touchable = Touchable.disabled;
image.setFillParent(true);
image.actions(Actions.delay((landDuration() - margin) / 60f), Actions.fadeIn(margin / 60f, Interp.pow2In), Actions.delay(6f / 60f), Actions.remove());
image.update(() -> {
image.toFront();
ui.loadfrag.toFront();
if(state.isMenu()){
image.remove();
}
});
Core.scene.add(image);
}else{
Image image = new Image();
image.color.a = 1f;
image.touchable = Touchable.disabled;
image.setFillParent(true);
image.actions(Actions.fadeOut(35f / 60f), Actions.remove());
image.update(() -> {
image.toFront();
ui.loadfrag.toFront();
if(state.isMenu()){
image.remove();
}
});
Core.scene.add(image);
Time.run(landDuration(), () -> {
launchEffect.at(this);
Effect.shake(5f, 5f, this);
thrusterTime = 1f;
if(state.isCampaign() && Vars.showSectorLandInfo && (state.rules.sector.preset == null || state.rules.sector.preset.showSectorLandInfo)){
ui.announce("[accent]" + state.rules.sector.name() + "\n" +
(state.rules.sector.info.resources.any() ? "[lightgray]" + Core.bundle.get("sectors.resources") + "[white] " +
state.rules.sector.info.resources.toString(" ", UnlockableContent::emoji) : ""), 5);
}
});
}
}
}
public void endLaunch(){}
public void drawLanding(CoreBlock block){
var clouds = Core.assets.get("sprites/clouds.png", Texture.class);
float fin = renderer.getLandTimeIn();
float cameraScl = renderer.getDisplayScale();
float fout = 1f - fin;
float scl = Scl.scl(4f) / cameraScl;
float pfin = Interp.pow3Out.apply(fin), pf = Interp.pow2In.apply(fout);
//draw particles
Draw.color(Pal.lightTrail);
Angles.randLenVectors(1, pfin, 100, 800f * scl * pfin, (ax, ay, ffin, ffout) -> {
Lines.stroke(scl * ffin * pf * 3f);
Lines.lineAngle(x + ax, y + ay, Mathf.angle(ax, ay), (ffin * 20 + 1f) * scl);
});
Draw.color();
block.drawLanding(this, x, y);
Draw.color();
Draw.mixcol(Color.white, Interp.pow5In.apply(fout));
//accent tint indicating that the core was just constructed
if(renderer.isLaunching()){
float f = Mathf.clamp(1f - fout * 12f);
if(f > 0.001f){
Draw.mixcol(Pal.accent, f);
}
}
//draw clouds
if(state.rules.cloudColor.a > 0.0001f){
float scaling = cloudScaling;
float sscl = Math.max(1f + Mathf.clamp(fin + cfinOffset) * cfinScl, 0f) * cameraScl;
Tmp.tr1.set(clouds);
Tmp.tr1.set(
(Core.camera.position.x - Core.camera.width/2f * sscl) / scaling,
(Core.camera.position.y - Core.camera.height/2f * sscl) / scaling,
(Core.camera.position.x + Core.camera.width/2f * sscl) / scaling,
(Core.camera.position.y + Core.camera.height/2f * sscl) / scaling);
Tmp.tr1.scroll(10f * cloudSeed, 10f * cloudSeed);
Draw.alpha(Mathf.sample(cloudAlphas, fin + calphaFinOffset) * cloudAlpha);
Draw.mixcol(state.rules.cloudColor, state.rules.cloudColor.a);
Draw.rect(Tmp.tr1, Core.camera.position.x, Core.camera.position.y, Core.camera.width, Core.camera.height);
Draw.reset();
}
}
public void drawThrusters(float frame){
float length = thrusterLength * (frame - 1f) - 1f/4f;
for(int i = 0; i < 4; i++){
@@ -409,9 +539,19 @@ public class CoreBlock extends StorageBlock{
thrusterTime -= Time.delta/90f;
}
/** @return Camera zoom while landing or launching. May optionally do other things such as setting camera position to itself. */
public float zoomLaunching(){
Core.camera.position.set(this);
return landZoomInterp.apply(Scl.scl(landZoomFrom), Scl.scl(landZoomTo), renderer.getLandTimeIn());
}
public void updateLaunching(){
updateLandParticles();
}
public void updateLandParticles(){
float time = renderer.isLaunching() ? coreLandDuration - renderer.getLandTime() : renderer.getLandTime();
float tsize = Mathf.sample(thrusterSizes, (time + 35f) / coreLandDuration);
float in = renderer.getLandTimeIn() * landDuration();
float tsize = Mathf.sample(thrusterSizes, (in + 35f) / landDuration());
renderer.setLandPTimer(renderer.getLandPTimer() + tsize * Time.delta);
if(renderer.getLandTime() >= 1f){