mirror of
https://github.com/Anuken/Mindustry.git
synced 2024-09-21 21:38:29 +03:00
Better build beam visuals
This commit is contained in:
parent
834e4f175b
commit
9f8fce72d3
@ -1,6 +1,5 @@
|
||||
uniform sampler2D u_texture;
|
||||
|
||||
uniform vec4 u_color;
|
||||
uniform vec2 u_texsize;
|
||||
uniform vec2 u_uv;
|
||||
uniform vec2 u_uv2;
|
||||
@ -38,11 +37,11 @@ void main(){
|
||||
float dst = (abs(center.x - coords.x) + abs(center.y - coords.y))/2.0;
|
||||
|
||||
if((mod(u_time / 1.5 + value, 20.0) < 15.0 && cont(t, v))){
|
||||
gl_FragColor = u_color;
|
||||
gl_FragColor = v_color;
|
||||
}else if(dst > (1.0-u_progress) * (center.x)){
|
||||
gl_FragColor = color;
|
||||
}else if((dst + 1.0 > (1.0-u_progress) * (center.x)) && color.a > 0.1){
|
||||
gl_FragColor = u_color;
|
||||
gl_FragColor = v_color;
|
||||
}else{
|
||||
gl_FragColor = vec4(0.0);
|
||||
}
|
||||
|
25
core/assets/shaders/buildbeam.frag
Normal file
25
core/assets/shaders/buildbeam.frag
Normal file
@ -0,0 +1,25 @@
|
||||
#define HIGHP
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
uniform vec2 u_texsize;
|
||||
uniform vec2 u_invsize;
|
||||
uniform float u_time;
|
||||
uniform float u_dp;
|
||||
uniform vec2 u_offset;
|
||||
|
||||
varying vec2 v_texCoords;
|
||||
|
||||
float triwave(float y){
|
||||
return abs(2.*fract(y)-1.);
|
||||
}
|
||||
|
||||
void main(){
|
||||
vec2 T = v_texCoords.xy;
|
||||
vec2 coords = (T * u_texsize) + u_offset;
|
||||
|
||||
vec4 color = texture2D(u_texture, T);
|
||||
|
||||
color.a *= (0.37 + abs(sin(u_time / 15.0)) * .05 + 0.2 * (step(mod(coords.x / u_dp + coords.y / u_dp + u_time / 4.0, 10.0), 3.0)));
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
@ -1317,6 +1317,7 @@ public class UnitTypes implements ContentList{
|
||||
hitSize = 32f;
|
||||
payloadCapacity = (3 * 3) * tilePayload;
|
||||
buildSpeed = 2.5f;
|
||||
buildBeamOffset = 23;
|
||||
range = 140f;
|
||||
targetAir = false;
|
||||
targetFlag = BlockFlag.battery;
|
||||
@ -1388,6 +1389,7 @@ public class UnitTypes implements ContentList{
|
||||
drawShields = false;
|
||||
commandLimit = 6;
|
||||
lowAltitude = true;
|
||||
buildBeamOffset = 43;
|
||||
|
||||
ammoCapacity = 1300;
|
||||
ammoResupplyAmount = 20;
|
||||
|
@ -30,6 +30,7 @@ public class Renderer implements ApplicationListener{
|
||||
public @Nullable Bloom bloom;
|
||||
public FrameBuffer effectBuffer = new FrameBuffer();
|
||||
public float laserOpacity = 1f;
|
||||
public boolean animateShields;
|
||||
/** minZoom = zooming out, maxZoom = zooming in */
|
||||
public float minZoom = 1.5f, maxZoom = 6f;
|
||||
|
||||
@ -69,7 +70,8 @@ public class Renderer implements ApplicationListener{
|
||||
float dest = Mathf.round(targetscale, 0.5f);
|
||||
camerascale = Mathf.lerpDelta(camerascale, dest, 0.1f);
|
||||
if(Mathf.equal(camerascale, dest, 0.001f)) camerascale = dest;
|
||||
laserOpacity = Core.settings.getInt("lasersopacity") / 100f;
|
||||
laserOpacity = settings.getInt("lasersopacity") / 100f;
|
||||
animateShields = settings.getBool("animatedshields");
|
||||
|
||||
if(landTime > 0){
|
||||
landTime -= Time.delta;
|
||||
@ -204,7 +206,7 @@ public class Renderer implements ApplicationListener{
|
||||
graphics.clear(clearColor);
|
||||
Draw.reset();
|
||||
|
||||
if(Core.settings.getBool("animatedwater") || Core.settings.getBool("animatedshields")){
|
||||
if(Core.settings.getBool("animatedwater") || animateShields){
|
||||
effectBuffer.resize(graphics.getWidth(), graphics.getHeight());
|
||||
}
|
||||
|
||||
@ -248,11 +250,16 @@ public class Renderer implements ApplicationListener{
|
||||
|
||||
Draw.draw(Layer.plans, overlays::drawBottom);
|
||||
|
||||
if(settings.getBool("animatedshields") && Shaders.shield != null){
|
||||
if(animateShields && Shaders.shield != null){
|
||||
Draw.drawRange(Layer.shields, 1f, () -> effectBuffer.begin(Color.clear), () -> {
|
||||
effectBuffer.end();
|
||||
effectBuffer.blit(Shaders.shield);
|
||||
});
|
||||
|
||||
Draw.drawRange(Layer.buildBeam, 1f, () -> effectBuffer.begin(Color.clear), () -> {
|
||||
effectBuffer.end();
|
||||
effectBuffer.blit(Shaders.buildBeam);
|
||||
});
|
||||
}
|
||||
|
||||
Draw.draw(Layer.overlayUI, overlays::drawTop);
|
||||
|
@ -35,12 +35,25 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
|
||||
@SyncLocal boolean updateBuilding = true;
|
||||
|
||||
private transient BuildPlan lastActive;
|
||||
private transient int lastSize;
|
||||
private transient float buildAlpha = 0f;
|
||||
|
||||
public boolean canBuild(){
|
||||
return type.buildSpeed > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(!headless){
|
||||
//visual activity update
|
||||
if(lastActive != null && buildAlpha <= 0.01f){
|
||||
lastActive = null;
|
||||
}
|
||||
|
||||
buildAlpha = Mathf.lerpDelta(buildAlpha, activelyBuilding() ? 1f : 0f, 0.15f);
|
||||
}
|
||||
|
||||
if(!updateBuilding || !canBuild()) return;
|
||||
|
||||
float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange;
|
||||
@ -56,9 +69,12 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
}
|
||||
|
||||
Building core = core();
|
||||
BuildPlan current = buildPlan();
|
||||
|
||||
//nothing to build.
|
||||
if(buildPlan() == null) return;
|
||||
if(current == null) return;
|
||||
|
||||
Tile tile = current.tile();
|
||||
|
||||
//find the next build request
|
||||
if(plans.size > 1){
|
||||
@ -71,11 +87,11 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
}
|
||||
}
|
||||
|
||||
BuildPlan current = buildPlan();
|
||||
lastActive = current;
|
||||
buildAlpha = 1f;
|
||||
if(current.breaking) lastSize = tile.block().size;
|
||||
|
||||
if(!within(current.tile(), finalPlaceDst)) return;
|
||||
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
if(!within(tile, finalPlaceDst)) return;
|
||||
|
||||
if(!(tile.build instanceof ConstructBuild cb)){
|
||||
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){
|
||||
@ -204,7 +220,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
boolean activelyBuilding(){
|
||||
//not actively building when not near the build plan
|
||||
if(isBuilding()){
|
||||
if(!within(buildPlan(), state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange)){
|
||||
if(!state.isEditor() && !within(buildPlan(), state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -218,30 +234,31 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
}
|
||||
|
||||
public void draw(){
|
||||
if(!activelyBuilding()) return;
|
||||
boolean active = activelyBuilding();
|
||||
if(!active && lastActive == null) return;
|
||||
|
||||
Draw.z(Layer.flyingUnit);
|
||||
|
||||
BuildPlan plan = buildPlan();
|
||||
BuildPlan plan = active ? buildPlan() : lastActive;
|
||||
Tile tile = world.tile(plan.x, plan.y);
|
||||
var core = team.core();
|
||||
|
||||
if(tile == null || (!state.rules.infiniteResources && !within(tile, buildingRange) && !state.isEditor())){
|
||||
if(tile == null || !within(plan, state.rules.infiniteResources ? Float.MAX_VALUE : buildingRange)){
|
||||
return;
|
||||
}
|
||||
|
||||
//draw remote plans.
|
||||
if(core != null && !isLocal() && !(tile.block() instanceof ConstructBlock)){
|
||||
if(core != null && active && !isLocal() && !(tile.block() instanceof ConstructBlock)){
|
||||
Draw.z(Layer.plans - 1f);
|
||||
drawPlan(plan, 0.5f);
|
||||
Draw.z(Layer.flyingUnit);
|
||||
}
|
||||
|
||||
int size = plan.breaking ? tile.block().size : plan.block.size;
|
||||
int size = plan.breaking ? active ? tile.block().size : lastSize : plan.block.size;
|
||||
float tx = plan.drawx(), ty = plan.drawy();
|
||||
|
||||
Lines.stroke(1f, Pal.accent);
|
||||
float focusLen = 3.8f + Mathf.absin(Time.time, 1.1f, 0.6f);
|
||||
Lines.stroke(1f, plan.breaking ? Pal.remove : Pal.accent);
|
||||
float focusLen = type.buildBeamOffset + Mathf.absin(Time.time, 3f, 0.6f);
|
||||
float px = x + Angles.trnsx(rotation, focusLen);
|
||||
float py = y + Angles.trnsy(rotation, focusLen);
|
||||
|
||||
@ -255,16 +272,35 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
|
||||
Arrays.sort(vecs, Structs.comparingFloat(vec -> -Angles.angleDist(angleTo(vec), ang)));
|
||||
|
||||
Vec2 close = Geometry.findClosest(x, y, vecs);
|
||||
|
||||
float x1 = vecs[0].x, y1 = vecs[0].y,
|
||||
x2 = close.x, y2 = close.y,
|
||||
x3 = vecs[1].x, y3 = vecs[1].y;
|
||||
|
||||
Draw.alpha(1f);
|
||||
Draw.z(Layer.buildBeam);
|
||||
|
||||
Draw.alpha(buildAlpha);
|
||||
|
||||
if(!active && !(tile.build instanceof ConstructBuild)){
|
||||
Fill.square(plan.drawx(), plan.drawy(), size * tilesize/2f);
|
||||
}
|
||||
|
||||
if(renderer.animateShields){
|
||||
if(close != vecs[0] && close != vecs[1]){
|
||||
Fill.tri(px, py, x1, y1, x2, y2);
|
||||
Fill.tri(px, py, x3, y3, x2, y2);
|
||||
}else{
|
||||
Fill.tri(px, py, x1, y1, x3, y3);
|
||||
}
|
||||
}else{
|
||||
Lines.line(px, py, x1, y1);
|
||||
Lines.line(px, py, x3, y3);
|
||||
}
|
||||
|
||||
Fill.circle(px, py, 1.6f + Mathf.absin(Time.time, 0.8f, 1.5f));
|
||||
Fill.square(px, py, 1.8f + Mathf.absin(Time.time, 2.2f, 1.1f), rotation + 45);
|
||||
|
||||
Draw.color();
|
||||
Draw.reset();
|
||||
Draw.z(Layer.flyingUnit);
|
||||
}
|
||||
}
|
||||
|
@ -199,10 +199,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
public void addPlan(boolean checkPrevious){
|
||||
if(!block.rebuildable || (team == state.rules.defaultTeam && state.isCampaign() && !block.isVisible())) return;
|
||||
|
||||
Object overrideConfig = null;
|
||||
|
||||
if(self() instanceof ConstructBuild entity){
|
||||
//update block to reflect the fact that something was being constructed
|
||||
if(entity.cblock != null && entity.cblock.synthetic() && entity.wasConstructing){
|
||||
block = entity.cblock;
|
||||
overrideConfig = entity.lastConfig;
|
||||
}else{
|
||||
//otherwise this was a deconstruction that was interrupted, don't want to rebuild that
|
||||
return;
|
||||
@ -223,7 +226,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
}
|
||||
|
||||
data.blocks.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, block.id, config()));
|
||||
data.blocks.addFirst(new BlockPlan(tile.x, tile.y, (short)rotation, block.id, overrideConfig == null ? config() : overrideConfig));
|
||||
}
|
||||
|
||||
/** Configure with the current, local player. */
|
||||
|
@ -109,6 +109,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
|
||||
@Replace
|
||||
public float clipSize(){
|
||||
if(isBuilding()){
|
||||
return state.rules.infiniteResources ? Float.MAX_VALUE : Math.max(type.clipSize, type.region.width) + buildingRange + tilesize*4f;
|
||||
}
|
||||
return Math.max(type.region.width * 2f, type.clipSize);
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,9 @@ public class Layer{
|
||||
//overlaied UI, like block config guides
|
||||
overlayUI = 120,
|
||||
|
||||
//build beam effects
|
||||
buildBeam = 122,
|
||||
|
||||
//shield effects
|
||||
shields = 125,
|
||||
|
||||
|
@ -17,6 +17,7 @@ import static mindustry.Vars.*;
|
||||
public class Shaders{
|
||||
public static BlockBuild blockbuild;
|
||||
public static @Nullable ShieldShader shield;
|
||||
public static BuildBeamShader buildBeam;
|
||||
public static UnitBuild build;
|
||||
public static DarknessShader darkness;
|
||||
public static LightShader light;
|
||||
@ -38,6 +39,7 @@ public class Shaders{
|
||||
shield = null;
|
||||
t.printStackTrace();
|
||||
}
|
||||
buildBeam = new BuildBeamShader();
|
||||
build = new UnitBuild();
|
||||
darkness = new DarknessShader();
|
||||
light = new LightShader();
|
||||
@ -161,7 +163,6 @@ public class Shaders{
|
||||
}
|
||||
|
||||
public static class BlockBuild extends LoadShader{
|
||||
public Color color = new Color();
|
||||
public float progress;
|
||||
public TextureRegion region = new TextureRegion();
|
||||
|
||||
@ -172,7 +173,6 @@ public class Shaders{
|
||||
@Override
|
||||
public void apply(){
|
||||
setUniformf("u_progress", progress);
|
||||
setUniformf("u_color", color);
|
||||
setUniformf("u_uv", region.u, region.v);
|
||||
setUniformf("u_uv2", region.u2, region.v2);
|
||||
setUniformf("u_time", Time.time);
|
||||
@ -198,6 +198,24 @@ public class Shaders{
|
||||
}
|
||||
}
|
||||
|
||||
public static class BuildBeamShader extends LoadShader{
|
||||
|
||||
public BuildBeamShader(){
|
||||
super("buildbeam", "screenspace");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(){
|
||||
setUniformf("u_dp", Scl.scl(1f));
|
||||
setUniformf("u_time", Time.time / Scl.scl(1f));
|
||||
setUniformf("u_offset",
|
||||
Core.camera.position.x - Core.camera.width / 2,
|
||||
Core.camera.position.y - Core.camera.height / 2);
|
||||
setUniformf("u_texsize", Core.camera.width, Core.camera.height);
|
||||
setUniformf("u_invsize", 1f/Core.camera.width, 1f/Core.camera.height);
|
||||
}
|
||||
}
|
||||
|
||||
//seed: 8kmfuix03fw
|
||||
public static class SpaceShader extends SurfaceShader{
|
||||
Texture texture;
|
||||
|
@ -52,6 +52,7 @@ public class UnitType extends UnlockableContent{
|
||||
public float groundLayer = Layer.groundUnit;
|
||||
public float payloadCapacity = 8;
|
||||
public float aimDst = -1f;
|
||||
public float buildBeamOffset = 3.8f;
|
||||
public int commandLimit = 8;
|
||||
public float visualElevation = -1f;
|
||||
public boolean allowLegStep = false;
|
||||
|
@ -145,8 +145,9 @@ public class ConstructBlock extends Block{
|
||||
* If a non-recipe block is being deconstructed, this is the block that is being deconstructed.
|
||||
*/
|
||||
public Block previous;
|
||||
public Object lastConfig;
|
||||
public boolean wasConstructing;
|
||||
public @Nullable Object lastConfig;
|
||||
public boolean wasConstructing, activeDeconstruct;
|
||||
public float constructColor;
|
||||
|
||||
@Nullable
|
||||
public Unit lastBuilder;
|
||||
@ -176,7 +177,7 @@ public class ConstructBlock extends Block{
|
||||
|
||||
@Override
|
||||
public void tapped(){
|
||||
//if the target is constructible, begin constructing
|
||||
//if the target is constructable, begin constructing
|
||||
if(cblock != null){
|
||||
if(control.input.buildWasAutoPaused && !control.input.isBuilding && player.isBuilder()){
|
||||
control.input.isBuilding = true;
|
||||
@ -194,6 +195,12 @@ public class ConstructBlock extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
constructColor = Mathf.lerpDelta(constructColor, activeDeconstruct ? 1f : 0f, 0.2f);
|
||||
activeDeconstruct = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
if(!(previous == null || cblock == null || previous == cblock) && Core.atlas.isFound(previous.icon(Cicon.full))){
|
||||
@ -201,7 +208,7 @@ public class ConstructBlock extends Block{
|
||||
}
|
||||
|
||||
Draw.draw(Layer.blockBuilding, () -> {
|
||||
Shaders.blockbuild.color = Pal.accent;
|
||||
Draw.color(Pal.accent, Pal.remove, constructColor);
|
||||
|
||||
Block target = cblock == null ? previous : cblock;
|
||||
|
||||
@ -214,11 +221,14 @@ public class ConstructBlock extends Block{
|
||||
Draw.flush();
|
||||
}
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
});
|
||||
}
|
||||
|
||||
public void construct(Unit builder, @Nullable Building core, float amount, Object config){
|
||||
wasConstructing = true;
|
||||
activeDeconstruct = false;
|
||||
if(cblock == null){
|
||||
kill();
|
||||
return;
|
||||
@ -254,6 +264,7 @@ public class ConstructBlock extends Block{
|
||||
|
||||
public void deconstruct(Unit builder, @Nullable Building core, float amount){
|
||||
wasConstructing = false;
|
||||
activeDeconstruct = true;
|
||||
float deconstructMultiplier = state.rules.deconstructRefundMultiplier;
|
||||
|
||||
if(builder.isPlayer()){
|
||||
@ -333,7 +344,8 @@ public class ConstructBlock extends Block{
|
||||
}
|
||||
|
||||
public void setConstruct(Block previous, Block block){
|
||||
wasConstructing = true;
|
||||
this.constructColor = 0f;
|
||||
this.wasConstructing = true;
|
||||
this.cblock = block;
|
||||
this.previous = previous;
|
||||
this.accumulator = new float[block.requirements.length];
|
||||
@ -343,7 +355,9 @@ public class ConstructBlock extends Block{
|
||||
|
||||
public void setDeconstruct(Block previous){
|
||||
if(previous == null) return;
|
||||
wasConstructing = false;
|
||||
|
||||
this.constructColor = 1f;
|
||||
this.wasConstructing = false;
|
||||
this.previous = previous;
|
||||
this.progress = 1f;
|
||||
if(previous.buildCost >= 0.01f){
|
||||
|
@ -201,7 +201,7 @@ public class StackConveyor extends Block implements Autotiler{
|
||||
if(cooldown > 0f) return;
|
||||
|
||||
// get current item
|
||||
if(lastItem == null){
|
||||
if(lastItem == null || !items.has(lastItem)){
|
||||
lastItem = items.first();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user