mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-10 18:57:39 +07:00
Brief shockwave experiment
This commit is contained in:
parent
46489f9893
commit
5603672983
42
core/assets/shaders/shockwave.frag
Normal file
42
core/assets/shaders/shockwave.frag
Normal file
@ -0,0 +1,42 @@
|
||||
#define MAX_SHOCKWAVES 64
|
||||
#define WAVE_RADIUS 4.0
|
||||
#define DIFF_SCL 1
|
||||
#define WAVE_POW 0.8
|
||||
|
||||
varying vec2 v_texCoords;
|
||||
|
||||
uniform sampler2D u_texture;
|
||||
uniform vec2 u_resolution;
|
||||
uniform vec2 u_campos;
|
||||
uniform vec4 u_shockwaves[MAX_SHOCKWAVES];
|
||||
uniform int u_shockwave_count;
|
||||
|
||||
void main(){
|
||||
vec2 worldCoords = v_texCoords * u_resolution + u_campos;
|
||||
vec2 uv = v_texCoords;
|
||||
vec2 displacement = vec2(0.0, 0.0);
|
||||
|
||||
for(int i = 0; i < MAX_SHOCKWAVES; i ++){
|
||||
vec4 wave = u_shockwaves[i];
|
||||
float radius = wave.z;
|
||||
float strength = wave.w;
|
||||
float dst = distance(worldCoords, wave.xy);
|
||||
float realStrength = 1.0 - pow(1.0 - strength, 5.0);
|
||||
|
||||
if(abs(dst - radius) <= WAVE_RADIUS){
|
||||
float diff = dst - radius;
|
||||
float pdiff = 1.0 - pow(abs(diff * DIFF_SCL), WAVE_POW);
|
||||
float diffTime = diff * pdiff;
|
||||
vec2 relative = normalize(worldCoords - wave.xy);
|
||||
|
||||
displacement += (relative * diffTime * strength) / u_resolution;
|
||||
}
|
||||
|
||||
if(i >= u_shockwave_count - 1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 c = texture2D(u_texture, uv + displacement);
|
||||
gl_FragColor = c;
|
||||
}
|
@ -85,6 +85,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
transient float efficiency;
|
||||
/** Same as efficiency, but for optional consumers only. */
|
||||
transient float optionalEfficiency;
|
||||
/** The efficiency this block would have if consValid() / productionValid() returned true. */
|
||||
transient float potentialEfficiency;
|
||||
|
||||
transient float healSuppressionTime = -1f;
|
||||
transient float lastHealTime = -120f * 10f;
|
||||
@ -224,7 +226,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
//version 3 has efficiency numbers instead of bools
|
||||
if(version >= 3){
|
||||
efficiency = read.ub() / 255f;
|
||||
efficiency = potentialEfficiency = read.ub() / 255f;
|
||||
optionalEfficiency = read.ub() / 255f;
|
||||
}
|
||||
|
||||
@ -1640,7 +1642,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
public boolean canConsume(){
|
||||
return efficiency > 0;
|
||||
return potentialEfficiency > 0;
|
||||
}
|
||||
|
||||
/** Scaled delta. */
|
||||
@ -1671,40 +1673,43 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
public void updateConsumption(){
|
||||
//everything is valid when cheating
|
||||
if(!block.hasConsumers || cheating()){
|
||||
efficiency = optionalEfficiency = 1f;
|
||||
potentialEfficiency = efficiency = optionalEfficiency = 1f;
|
||||
return;
|
||||
}
|
||||
|
||||
//disabled -> nothing works
|
||||
if(!enabled){
|
||||
efficiency = optionalEfficiency = 0f;
|
||||
potentialEfficiency = efficiency = optionalEfficiency = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO why check for old state?
|
||||
boolean prevValid = efficiency > 0, update = shouldConsume() && productionValid();
|
||||
|
||||
if(update){
|
||||
float minEfficiency = 1f;
|
||||
float minEfficiency = 1f;
|
||||
|
||||
//assume efficiency is 1 for the calculations below
|
||||
efficiency = optionalEfficiency = 1f;
|
||||
//assume efficiency is 1 for the calculations below
|
||||
efficiency = optionalEfficiency = 1f;
|
||||
|
||||
//first pass: get the minimum efficiency of any consumer
|
||||
for(var cons : block.nonOptionalConsumers){
|
||||
minEfficiency = Math.min(minEfficiency, cons.efficiency(self()));
|
||||
}
|
||||
//first pass: get the minimum efficiency of any consumer
|
||||
for(var cons : block.nonOptionalConsumers){
|
||||
minEfficiency = Math.min(minEfficiency, cons.efficiency(self()));
|
||||
}
|
||||
|
||||
//same for optionals
|
||||
for(var cons : block.optionalConsumers){
|
||||
optionalEfficiency = Math.min(optionalEfficiency, cons.efficiency(self()));
|
||||
}
|
||||
//same for optionals
|
||||
for(var cons : block.optionalConsumers){
|
||||
optionalEfficiency = Math.min(optionalEfficiency, cons.efficiency(self()));
|
||||
}
|
||||
|
||||
//efficiency is now this minimum value
|
||||
efficiency = minEfficiency;
|
||||
optionalEfficiency = Math.min(optionalEfficiency, minEfficiency);
|
||||
}else{
|
||||
//should not consume, efficiency now zero
|
||||
//efficiency is now this minimum value
|
||||
efficiency = minEfficiency;
|
||||
optionalEfficiency = Math.min(optionalEfficiency, minEfficiency);
|
||||
|
||||
//assign "potential"
|
||||
potentialEfficiency = efficiency;
|
||||
|
||||
//no updating means zero efficiency
|
||||
if(!update){
|
||||
efficiency = optionalEfficiency = 0f;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,9 @@ import arc.graphics.g3d.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@ -28,6 +30,7 @@ public class Shaders{
|
||||
public static CloudShader clouds;
|
||||
public static PlanetGridShader planetGrid;
|
||||
public static AtmosphereShader atmosphere;
|
||||
public static ShockwaveShader shockwave;
|
||||
public static MeshShader mesh;
|
||||
public static Shader unlit;
|
||||
public static Shader screenspace;
|
||||
@ -67,6 +70,9 @@ public class Shaders{
|
||||
atmosphere = new AtmosphereShader();
|
||||
unlit = new LoadShader("planet", "unlit");
|
||||
screenspace = new LoadShader("screenspace", "screenspace");
|
||||
|
||||
//disabled for now...
|
||||
//shockwave = new ShockwaveShader();
|
||||
}
|
||||
|
||||
public static class AtmosphereShader extends LoadShader{
|
||||
@ -350,6 +356,112 @@ public class Shaders{
|
||||
}
|
||||
}
|
||||
|
||||
public static class ShockwaveShader extends LoadShader{
|
||||
static final int max = 64;
|
||||
static final int size = 5;
|
||||
static final String[] uniformNames = new String[max];
|
||||
|
||||
//x y radius life[1-0] lifetime
|
||||
protected FloatSeq data = new FloatSeq();
|
||||
protected boolean hadAny = false;
|
||||
protected FrameBuffer buffer = new FrameBuffer();
|
||||
|
||||
public float lifetime = 20f;
|
||||
|
||||
static{
|
||||
for(int i = 0; i < max; i++){
|
||||
uniformNames[i] = "u_shockwaves[" + i + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public ShockwaveShader(){
|
||||
super("shockwave", "screenspace");
|
||||
|
||||
Events.run(Trigger.update, () -> {
|
||||
if(state.isPaused()) return;
|
||||
if(state.isMenu()){
|
||||
data.size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var items = data.items;
|
||||
for(int i = 0; i < data.size; i += size){
|
||||
//decrease lifetime
|
||||
items[i + 3] -= Time.delta / items[i + 4];
|
||||
|
||||
if(items[i + 3] <= 0f){
|
||||
//swap with head.
|
||||
if(data.size > size){
|
||||
System.arraycopy(items, data.size - size, items, i, size);
|
||||
}
|
||||
|
||||
data.size -= size;
|
||||
i -= size;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Events.run(Trigger.preDraw, () -> {
|
||||
hadAny = data.size > 0;
|
||||
|
||||
if(hadAny){
|
||||
buffer.resize(Core.graphics.getWidth(), Core.graphics.getHeight());
|
||||
buffer.begin(Color.clear);
|
||||
}
|
||||
});
|
||||
|
||||
Events.run(Trigger.postDraw, () -> {
|
||||
if(hadAny){
|
||||
buffer.end();
|
||||
Draw.blend(Blending.disabled);
|
||||
buffer.blit(this);
|
||||
Draw.blend();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(){
|
||||
int count = data.size / 4;
|
||||
|
||||
setUniformi("u_shockwave_count", count);
|
||||
if(count > 0){
|
||||
setUniformf("u_resolution", Core.camera.width, Core.camera.height);
|
||||
setUniformf("u_campos", Core.camera.position.x - Core.camera.width/2f, Core.camera.position.y - Core.camera.height/2f);
|
||||
|
||||
var items = data.items;
|
||||
for(int i = 0; i < count; i++){
|
||||
int offset = i * size;
|
||||
|
||||
setUniformf(uniformNames[i],
|
||||
items[offset], items[offset + 1], //xy
|
||||
items[offset + 2] * (1f - items[offset + 3]), //radius * time
|
||||
items[offset + 3] //time
|
||||
//lifetime ignored
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void add(float x, float y, float radius){
|
||||
add(x, y, radius, 20f);
|
||||
}
|
||||
|
||||
public void add(float x, float y, float radius, float lifetime){
|
||||
//replace first entry
|
||||
if(data.size / size >= max){
|
||||
var items = data.items;
|
||||
items[0] = x;
|
||||
items[1] = y;
|
||||
items[2] = radius;
|
||||
items[3] = 1f;
|
||||
items[4] = lifetime;
|
||||
}else{
|
||||
data.addAll(x, y, radius, 1f, lifetime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoadShader extends Shader{
|
||||
public LoadShader(String frag, String vert){
|
||||
super(getShaderFi(vert + ".vert"), getShaderFi(frag + ".frag"));
|
||||
|
@ -331,13 +331,13 @@ public class Turret extends ReloadTurret{
|
||||
//turret always reloads regardless of whether it's targeting something
|
||||
updateReload();
|
||||
|
||||
if(timer(timerTarget, targetInterval)){
|
||||
findTarget();
|
||||
}
|
||||
|
||||
if(hasAmmo()){
|
||||
if(Float.isNaN(reloadCounter)) reloadCounter = 0;
|
||||
|
||||
if(timer(timerTarget, targetInterval)){
|
||||
findTarget();
|
||||
}
|
||||
|
||||
if(validateTarget()){
|
||||
boolean canShoot = true;
|
||||
|
||||
@ -402,7 +402,7 @@ public class Turret extends ReloadTurret{
|
||||
}
|
||||
|
||||
protected void turnToTarget(float targetRot){
|
||||
rotation = Angles.moveToward(rotation, targetRot, rotateSpeed * delta() * baseReloadSpeed());
|
||||
rotation = Angles.moveToward(rotation, targetRot, rotateSpeed * delta() * potentialEfficiency);
|
||||
}
|
||||
|
||||
public boolean shouldTurn(){
|
||||
|
@ -107,7 +107,7 @@ public class CoreBlock extends StorageBlock{
|
||||
public void init(){
|
||||
//assign to update clipSize internally
|
||||
lightRadius = 30f + 20f * size;
|
||||
fogRadius = Math.max(fogRadius, (int)(lightRadius / 8f * 3f) + 5);
|
||||
fogRadius = Math.max(fogRadius, (int)(lightRadius / 8f * 3f) + 13);
|
||||
emitLight = true;
|
||||
|
||||
super.init();
|
||||
|
Loading…
Reference in New Issue
Block a user