diff --git a/core/assets/shaders/fog.fragment b/core/assets/shaders/fog.fragment new file mode 100644 index 0000000000..3f83ec4519 --- /dev/null +++ b/core/assets/shaders/fog.fragment @@ -0,0 +1,16 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +uniform sampler2D u_texture; + +varying vec4 v_color; +varying vec2 v_texCoord; + +void main() { + vec4 color = texture2D(u_texture, v_texCoord.xy); + color.a = 1.0 - color.r; + color.rgb = vec3(0.0); + gl_FragColor = color * v_color; +} diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index a0eac7d56a..e0bbc0d207 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureWrap; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.utils.*; +import com.badlogic.gdx.utils.ObjectIntMap; +import com.badlogic.gdx.utils.Pools; +import com.badlogic.gdx.utils.TimeUtils; import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Player; @@ -29,7 +31,6 @@ import io.anuke.ucore.entities.impl.BaseEntity; import io.anuke.ucore.entities.impl.EffectEntity; import io.anuke.ucore.entities.trait.DrawTrait; import io.anuke.ucore.entities.trait.SolidTrait; -import io.anuke.ucore.function.Callable; import io.anuke.ucore.function.Consumer; import io.anuke.ucore.function.Predicate; import io.anuke.ucore.graphics.Draw; @@ -50,15 +51,16 @@ public class Renderer extends RendererModule{ private int targetscale = baseCameraScale; private Texture background = new Texture("sprites/background.png"); - private FloatArray shieldHits = new FloatArray(); - private Array shieldDraws = new Array<>(); + private Rectangle rect = new Rectangle(), rect2 = new Rectangle(); private Vector2 avgPosition = new Translator(); private Vector2 tmpVector1 = new Translator(); private Vector2 tmpVector2 = new Translator(); + private BlockRenderer blocks = new BlockRenderer(); private MinimapRenderer minimap = new MinimapRenderer(); private OverlayRenderer overlays = new OverlayRenderer(); + private FogRenderer fog = new FogRenderer(); public Renderer() { pixelate = true; @@ -243,8 +245,10 @@ public class Renderer extends RendererModule{ if(showPaths && debug) drawDebug(); drawAndInterpolate(playerGroup, p -> !p.isLocal && !p.isDead(), Player::drawName); - + batch.end(); + + fog.draw(); } private void drawAllTeams(boolean flying){ @@ -328,6 +332,7 @@ public class Renderer extends RendererModule{ @Override public void dispose() { background.dispose(); + fog.dispose(); } public Vector2 averagePosition(){ @@ -408,14 +413,6 @@ public class Renderer extends RendererModule{ return blocks; } - public void addShieldHit(float x, float y){ - shieldHits.addAll(x, y, 0f); - } - - public void addShield(Callable call){ - shieldDraws.add(call); - } - public void setCameraScale(int amount){ targetscale = amount; clampScale(); diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index 0814d1d286..09025299d2 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -34,11 +34,12 @@ public class EventType { void handle(); } - /**Called from the logic thread. Do not call graphics here!*/ + /**Called from the logic thread. Do not access graphics here!*/ public interface TileChangeEvent extends Event{ void handle(Tile tile); } + //TODO unimplemented; remove? public interface TileRemoveEvent extends Event{ void handle(Tile tile, Team oldTeam); } diff --git a/core/src/io/anuke/mindustry/graphics/FogRenderer.java b/core/src/io/anuke/mindustry/graphics/FogRenderer.java new file mode 100644 index 0000000000..5d8df4ed4e --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/FogRenderer.java @@ -0,0 +1,81 @@ +package io.anuke.mindustry.graphics; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap.Format; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.FrameBuffer; +import com.badlogic.gdx.utils.Disposable; +import io.anuke.mindustry.entities.Player; +import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent; +import io.anuke.ucore.core.Core; +import io.anuke.ucore.core.Events; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Fill; + +import static io.anuke.mindustry.Vars.*; + +/**Used for rendering fog of war. A framebuffer is used for this.*/ +public class FogRenderer implements Disposable{ + private TextureRegion region = new TextureRegion(); + private FrameBuffer buffer; + + public FogRenderer(){ + Events.on(WorldLoadGraphicsEvent.class, () -> { + dispose(); + buffer = new FrameBuffer(Format.RGBA8888, world.width(), world.height(), false); + + //clear buffer to black + buffer.begin(); + Graphics.clear(Color.BLACK); + buffer.end(); + }); + } + + public void draw(){ + if(buffer == null) return; + + float vw = Core.camera.viewportWidth * Core.camera.zoom; + float vh = Core.camera.viewportHeight * Core.camera.zoom; + + float px = Core.camera.position.x -= vw/2f; + float py = Core.camera.position.y -= vh/2f; + + float u = px / tilesize / world.width(); + float v = py / tilesize / world.height(); + + float u2 = (px + vw)/ tilesize / world.width(); + float v2 = (py + vh)/ tilesize / world.height(); + + Core.batch.getProjectionMatrix().setToOrtho2D(0, 0, world.width() * tilesize, world.height() * tilesize); + + Draw.color(Color.WHITE); + + buffer.begin(); + Graphics.begin(); + for(Player player : playerGroup.all()){ + Fill.circle(player.x, player.y, 60f); + } + Graphics.end(); + buffer.end(); + + region.setTexture(buffer.getColorBufferTexture()); + //region.setRegion(0, 0, 1, 1); + region.setRegion(u, v2, u2, v); + + Core.batch.setProjectionMatrix(Core.camera.combined); + Graphics.shader(Shaders.fog); + Graphics.begin(); + + // Core.batch.draw(buffer.getColorBufferTexture(), px + 50, py, 200, 200 * world.height()/(float)world.width()); + Core.batch.draw(region, px, py, vw, vh); + + Graphics.end(); + Graphics.shader(); + } + + @Override + public void dispose() { + if(buffer != null) buffer.dispose(); + } +} diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index ca56b6be10..21c02966f5 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -24,6 +24,7 @@ public class Shaders{ public static UnitBuild build; public static MixShader mix; public static Shader fullMix; + public static FogShader fog; public static void init(){ outline = new Outline(); @@ -36,9 +37,16 @@ public class Shaders{ space = new Space(); build = new UnitBuild(); mix = new MixShader(); + fog = new FogShader(); fullMix = new Shader("fullmix", "default"); } + public static class FogShader extends Shader{ + public FogShader(){ + super("fog", "default"); + } + } + public static class MixShader extends Shader{ public Color color = new Color(Color.WHITE); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ShieldBlock.java b/core/src/io/anuke/mindustry/world/blocks/defense/ShieldBlock.java index 56055d7862..80984d505f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ShieldBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ShieldBlock.java @@ -9,9 +9,6 @@ import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.impl.BulletEntity; import io.anuke.ucore.util.Mathf; -import static io.anuke.mindustry.Vars.headless; -import static io.anuke.mindustry.Vars.renderer; - //TODO remove public class ShieldBlock extends PowerBlock{ public float shieldRadius = 40f; @@ -73,7 +70,7 @@ public class ShieldBlock extends PowerBlock{ bullet.remove(); //Effects.effect(bullet.damage > 5 ? BulletFx.shieldhit : BulletFx.laserhit, bullet); - if(!headless) renderer.addShieldHit(bullet.x, bullet.y); + //if(!headless) renderer.addShieldHit(bullet.x, bullet.y); entity.power.amount -= bullet.getDamage() * powerPerDamage; } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ShieldedWallBlock.java b/core/src/io/anuke/mindustry/world/blocks/defense/ShieldedWallBlock.java index 2ab6b4c928..261836887b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ShieldedWallBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ShieldedWallBlock.java @@ -7,7 +7,6 @@ import io.anuke.mindustry.world.blocks.PowerBlock; import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; -import static io.anuke.mindustry.Vars.renderer; import static io.anuke.mindustry.Vars.tilesize; //TODO remove @@ -54,7 +53,7 @@ public class ShieldedWallBlock extends PowerBlock{ ShieldedWallEntity entity = tile.entity(); if(entity.power.amount > powerPerDamage){ - renderer.addShield(() -> Draw.rect("blank", tile.worldx(), tile.worldy(), tilesize, tilesize)); + //renderer.addShield(() -> Draw.rect("blank", tile.worldx(), tile.worldy(), tilesize, tilesize)); } Draw.color(hitColor); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java index 6c73a5b12f..5ba1443e35 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/CooledTurret.java @@ -14,6 +14,7 @@ import static io.anuke.mindustry.Vars.tilesize; public class CooledTurret extends Turret { /**How much reload is lowered by for each unit of liquid of heat capacity 1.*/ protected float coolantMultiplier = 1f; + /**Max coolant used per tick.*/ protected float maxUsed = 1f; protected Effect coolEffect = BlockFx.fuelburn; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java index 667cc61f28..56fa978f6c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java @@ -52,8 +52,8 @@ public abstract class Turret extends Block{ protected float recoil = 1f; protected float restitution = 0.02f; protected float cooldown = 0.02f; - protected float rotatespeed = 0.2f; - protected float shootCone = 5f; + protected float rotatespeed = 5f; //in degrees per tick + protected float shootCone = 8f; protected float shootShake = 0f; protected Translator tr = new Translator(); protected Translator tr2 = new Translator(); @@ -168,7 +168,7 @@ public abstract class Turret extends Block{ entity.rotation = 0; } - entity.rotation = Angles.moveToward(entity.rotation, targetRot, 5f * Timers.delta()); + entity.rotation = Angles.moveToward(entity.rotation, targetRot, rotatespeed * Timers.delta()); if(Angles.angleDist(entity.rotation, targetRot) < shootCone){ updateShooting(tile);