diff --git a/core/assets-raw/sprites/blocks/environment/grass.png b/core/assets-raw/sprites/blocks/environment/grass.png index 815f3c734c..76a1491b9b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/grass.png and b/core/assets-raw/sprites/blocks/environment/grass.png differ diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index b5c0950a14..94c44f44c3 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/version.properties b/core/assets/version.properties index 626da3b4d7..eade061535 100644 --- a/core/assets/version.properties +++ b/core/assets/version.properties @@ -1,7 +1,7 @@ #Autogenerated file. Do not modify. -#Tue Apr 17 23:51:39 EDT 2018 +#Wed Apr 18 15:22:14 EDT 2018 version=release -androidBuildCode=977 +androidBuildCode=988 name=Mindustry code=3.5 build=custom build diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 9b0c81348d..4b7d19d057 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -120,7 +120,8 @@ public class Logic extends Module { runWave(); } - Entities.update(Entities.defaultGroup()); + if(!Entities.defaultGroup().isEmpty()) throw new RuntimeException("Do not add anything to the default group!"); + Entities.update(bulletGroup); for(EntityGroup group : unitGroups){ Entities.update(group); diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 0c568586a5..861cd10425 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -49,7 +49,7 @@ import static io.anuke.ucore.core.Core.camera; public class Renderer extends RendererModule{ private final static float shieldHitDuration = 18f; - public Surface shadowSurface, shieldSurface, indicatorSurface, waterSurface; + public Surface shadowSurface, shieldSurface, waterSurface; private int targetscale = baseCameraScale; private Texture background = new Texture("sprites/background.png"); @@ -120,7 +120,6 @@ public class Renderer extends RendererModule{ shadowSurface = Graphics.createSurface(scale); shieldSurface = Graphics.createSurface(scale); - indicatorSurface = Graphics.createSurface(scale); pixelSurface = Graphics.createSurface(scale); waterSurface = Graphics.createSurface(scale); } @@ -220,7 +219,6 @@ public class Renderer extends RendererModule{ blocks.drawBlocks(Layer.overlay); drawAllTeams(false); - Entities.draw(Entities.defaultGroup()); blocks.skipLayer(Layer.turret); blocks.drawBlocks(Layer.laser); @@ -250,7 +248,8 @@ public class Renderer extends RendererModule{ private void drawAllTeams(boolean flying){ for(Team team : Team.values()){ EntityGroup group = unitGroups[team.ordinal()]; - if(group.all().size() < 0) continue; + if(group.count(p -> p.isFlying() == flying) + + playerGroup.count(p -> p.isFlying() == flying && p.team == team) == 0) continue; Shaders.outline.color.set(team.color); diff --git a/core/src/io/anuke/mindustry/entities/Unit.java b/core/src/io/anuke/mindustry/entities/Unit.java index 4a83f9fb8c..3508e6449e 100644 --- a/core/src/io/anuke/mindustry/entities/Unit.java +++ b/core/src/io/anuke/mindustry/entities/Unit.java @@ -86,8 +86,8 @@ public abstract class Unit extends SyncEntity implements SerializableEntity { status.update(this); if(isFlying()) { - x += velocity.x / getMass(); - y += velocity.y / getMass(); + x += velocity.x / getMass() * Timers.delta(); + y += velocity.y / getMass() * Timers.delta(); }else{ boolean onLiquid = floor.liquid; @@ -123,7 +123,7 @@ public abstract class Unit extends SyncEntity implements SerializableEntity { damage(health + 1, false); } - move(velocity.x / getMass() * floor.speedMultiplier, velocity.y / getMass() * floor.speedMultiplier); + move(velocity.x / getMass() * floor.speedMultiplier * Timers.delta(), velocity.y / getMass() * floor.speedMultiplier * Timers.delta()); } velocity.scl(Mathf.clamp(1f-drag* floor.dragMultiplier* Timers.delta())); diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index dec370b830..c6168d6af5 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -82,7 +82,7 @@ public class Puddle extends Entity implements SerializableEntity, Poolable{ private static void reactPuddle(Puddle p, Liquid liquid, float amount){ if((p.liquid.flammability > 0.3f && liquid.temperature > 0.7f) || - liquid.flammability > 0.3f && p.liquid.temperature > 0.7f){ //flammable liquid + hot liquid + (liquid.flammability > 0.3f && p.liquid.temperature > 0.7f)){ //flammable liquid + hot liquid Fire.create(p.tile); if(Mathf.chance(0.006 * amount)){ new Fireball(p.x, p.y, p.liquid.flameColor, Mathf.random(360f)).add(); diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index a80ed2333e..0b7593a5ac 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -1,13 +1,18 @@ package io.anuke.mindustry.graphics; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.*; +import com.badlogic.gdx.graphics.VertexAttributes.Usage; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShaderProgram; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.NumberUtils; import com.badlogic.gdx.utils.async.AsyncExecutor; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Core; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.util.Mathf; @@ -15,13 +20,16 @@ import static io.anuke.mindustry.Vars.tilesize; import static io.anuke.mindustry.Vars.world; public class FloorRenderer { - private final static int vsize = 5; + private final static int vsize = 6; private final static int chunksize = 32; private AsyncExecutor executor = new AsyncExecutor(4); + private ShaderProgram program = createDefaultShader(); private Chunk[][] cache; + private float z = 0f; public void drawFloor(){ + int chunksx = world.width() / chunksize, chunksy = world.height() / chunksize; if(cache == null || cache.length != chunksx || cache[0].length != chunksy){ @@ -33,8 +41,8 @@ public class FloorRenderer { int crangex = (int)(camera.viewportWidth * camera.zoom / (chunksize * tilesize))+1; int crangey = (int)(camera.viewportHeight * camera.zoom / (chunksize * tilesize))+1; - for(int x = -crangex; x <= crangex; x++){ - for(int y = -crangey; y <= crangey; y++){ + for(int x = -crangex; x <= crangex; x++) { + for (int y = -crangey; y <= crangey; y++) { int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; @@ -42,6 +50,28 @@ public class FloorRenderer { continue; fillChunk(worldx * chunksize * tilesize, worldy * chunksize * tilesize); + } + } + + Graphics.end(); + + Graphics.clear(Color.CLEAR); + Gdx.gl.glEnable(GL20.GL_BLEND); + + program.begin(); + + Core.atlas.getTextures().first().bind(); + + program.setUniformMatrix("u_projTrans", Core.camera.combined); + program.setUniformi("u_texture", 0); + + for(int x = -crangex; x <= crangex; x++){ + for(int y = -crangey; y <= crangey; y++){ + int worldx = Mathf.scl(camera.position.x, chunksize * tilesize) + x; + int worldy = Mathf.scl(camera.position.y, chunksize * tilesize) + y; + + if(!Mathf.inBounds(worldx, worldy, cache)) + continue; if(cache[worldx][worldy] == null){ cache[worldx][worldy] = new Chunk(); @@ -55,9 +85,15 @@ public class FloorRenderer { continue; } - Core.batch.draw(Core.atlas.getTextures().first(), chunk.vertices, 0, chunk.length); + chunk.mesh.render(program, GL20.GL_TRIANGLES, 0, chunk.length); + + //Core.batch.draw(Core.atlas.getTextures().first(), chunk.vertices, 0, chunk.length); } } + + program.end(); + + Graphics.begin(); } private void fillChunk(float x, float y){ @@ -80,34 +116,69 @@ public class FloorRenderer { Tile tile = world.tile(tilex, tiley); if(tile == null) continue; - Block floor = tile.floor(); - if(!Draw.hasRegion(floor.name())) continue; + Block block = tile.floor(); + if(!Draw.hasRegion(block.name()) || Draw.region(block.name()).getRegionWidth() == 8){ + TextureRegion base = Draw.region(block.variants > 0 ? (block.name() + MathUtils.random(1, block.variants)) : block.name()); + idx = draw(vertices, idx, base, tile.worldx(), tile.worldy(), color); - TextureRegion base = Draw.region(floor.name()); + for(int dx = -1; dx <= 1; dx ++){ + for(int dy = -1; dy <= 1; dy ++){ - set(base, region, 1 + Mathf.random(1), 1 + Mathf.random(1)); + if(dx == 0 && dy == 0) continue; - idx = draw(vertices, idx, region, tile.worldx(), tile.worldy(), color); + Tile other = world.tile(tile.x+dx, tile.y+dy); - for(int dx = -1; dx <= 1; dx ++) { - for (int dy = -1; dy <= 1; dy++) { + if(other == null) continue; - if (dx == 0 && dy == 0) continue; + Block floor = other.floor(); - Tile other = world.tile(tile.x + dx, tile.y + dy); + if(floor.id <= block.id) continue; - if (other == null) continue; + TextureRegion result = Draw.hasRegion(floor.name() + "edge") ? Draw.region(floor.name() + "edge") : + Draw.region(floor.edge + "edge"); - Block of = other.floor(); + int sx = -dx*8+2, sy = -dy*8+2; + int x = Mathf.clamp(sx, 0, 12); + int y = Mathf.clamp(sy, 0, 12); + int w = Mathf.clamp(sx+8, 0, 12) - x, h = Mathf.clamp(sy+8, 0, 12) - y; - if(of.id < floor.id){ - float ox = (dx == 0 ? Mathf.range(0.5f) : 0); - float oy = (dy == 0 ? Mathf.range(0.5f) : 0); - set(base, region, (int)(1.5f + 2f*dx + ox), (int)(2f - 2f*dy + oy)); + float rx = Mathf.clamp(dx*8, 0, 8-w); + float ry = Mathf.clamp(dy*8, 0, 8-h); - idx = draw(vertices, idx, region, - tile.worldx() + dx * tilesize, - tile.worldy() + dy * tilesize, color); + region.setTexture(result.getTexture()); + region.setRegion(result.getRegionX()+x, result.getRegionY()+y+h, w, -h); + + idx = drawc(vertices, idx, region, tile.worldx()-4 + rx, tile.worldy()-4 + ry, w, h, color); + } + } + }else { + + TextureRegion base = Draw.region(block.name()); + + set(base, region, 1 + Mathf.random(1), 1 + Mathf.random(1)); + + idx = draw(vertices, idx, region, tile.worldx(), tile.worldy(), color); + + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + + if (dx == 0 && dy == 0) continue; + + Tile other = world.tile(tile.x + dx, tile.y + dy); + + if (other == null) continue; + + Block floor = other.floor(); + + if (floor.id < block.id) { + float ox = (dx == 0 ? Mathf.range(0.5f) : 0); + float oy = (dy == 0 ? Mathf.range(0.5f) : 0); + set(base, region, (int) (1.5f + 2f * dx + ox), (int) (2f - 2f * dy + oy)); + + idx = draw(vertices, idx, region, + tile.worldx() + dx * tilesize, + tile.worldy() + dy * tilesize, color); + } } } } @@ -115,7 +186,14 @@ public class FloorRenderer { } chunk.length = idx; - chunk.rendered = true; + Timers.run(0f, () -> { + chunk.mesh = new Mesh(true, vertices.length, 0, + new VertexAttribute(Usage.Position, 3, "a_position"), + new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0")); + chunk.mesh.setVertices(chunk.vertices, 0, chunk.length); + + chunk.rendered = true; + }); return chunk; } @@ -126,9 +204,10 @@ public class FloorRenderer { } private int draw(float[] vertices, int idx, TextureRegion region, float x, float y, float color){ - x -= tilesize/2f; - y -= tilesize/2f; - float width = tilesize, height = tilesize; + return drawc(vertices, idx, region, x - tilesize/2f, y - tilesize/2f, tilesize, tilesize, color); + } + + private int drawc(float[] vertices, int idx, TextureRegion region, float x, float y, float width, float height, float color){ final float fx2 = x + width; final float fy2 = y + height; @@ -139,28 +218,40 @@ public class FloorRenderer { vertices[idx ++] = x; vertices[idx ++] = y; - vertices[idx ++] = color; + vertices[idx ++] = z; vertices[idx ++] = u; vertices[idx ++] = v; vertices[idx ++] = x; vertices[idx ++] = fy2; - vertices[idx ++] = color; + vertices[idx ++] = z; vertices[idx ++] = u; vertices[idx ++] = v2; vertices[idx ++] = fx2; vertices[idx ++] = fy2; - vertices[idx ++] = color; + vertices[idx ++] = z; vertices[idx ++] = u2; vertices[idx ++] = v2; + vertices[idx ++] = x; + vertices[idx ++] = y; + vertices[idx ++] = z; + vertices[idx ++] = u; + vertices[idx ++] = v; + vertices[idx ++] = fx2; vertices[idx ++] = y; - vertices[idx ++] = color; + vertices[idx ++] = z; vertices[idx ++] = u2; vertices[idx ++] = v; + vertices[idx ++] = fx2; + vertices[idx ++] = fy2; + vertices[idx ++] = z; + vertices[idx ++] = u2; + vertices[idx ++] = v2; + return idx; } @@ -168,9 +259,39 @@ public class FloorRenderer { float[] vertices; boolean rendered; int length; + Mesh mesh; } public void clearTiles(){ cache = null; } + + static ShaderProgram createDefaultShader () { + String vertexShader = "attribute vec4 " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" // + + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" // + + "uniform mat4 u_projTrans;\n" // + + "varying vec2 v_texCoords;\n" // + + "\n" // + + "void main()\n" // + + "{\n" // + + " v_texCoords = " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n" // + + " gl_Position = u_projTrans * " + ShaderProgram.POSITION_ATTRIBUTE + ";\n" // + + "}\n"; + String fragmentShader = "#ifdef GL_ES\n" // + + "#define LOWP lowp\n" // + + "precision mediump float;\n" // + + "#else\n" // + + "#define LOWP \n" // + + "#endif\n" // + + "varying vec2 v_texCoords;\n" // + + "uniform sampler2D u_texture;\n" // + + "void main()\n"// + + "{\n" // + + " gl_FragColor = texture2D(u_texture, v_texCoords);\n" // + + "}"; + + ShaderProgram shader = new ShaderProgram(vertexShader, fragmentShader); + if (!shader.isCompiled()) throw new IllegalArgumentException("Error compiling shader: " + shader.getLog()); + return shader; + } } diff --git a/core/src/io/anuke/mindustry/world/BaseBlock.java b/core/src/io/anuke/mindustry/world/BaseBlock.java index 409829d298..9eb12c4178 100644 --- a/core/src/io/anuke/mindustry/world/BaseBlock.java +++ b/core/src/io/anuke/mindustry/world/BaseBlock.java @@ -1,10 +1,13 @@ package io.anuke.mindustry.world; import com.badlogic.gdx.math.GridPoint2; +import io.anuke.mindustry.content.fx.EnvironmentFx; import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Liquid; +import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Translator; @@ -117,21 +120,29 @@ public abstract class BaseBlock { if(next.block().hasLiquids && tile.entity.liquids.amount > 0f){ float ofract = next.entity.liquids.amount / next.block().liquidCapacity; float fract = tile.entity.liquids.amount / liquidCapacity; - - if(ofract > fract) return 0; - float flow = Math.min(Mathf.clamp((fract - ofract)*(1f)) * (liquidCapacity), tile.entity.liquids.amount); - flow = Math.min(flow, next.block().liquidCapacity - next.entity.liquids.amount - 0.001f); - if(flow <= 0f) return 0; - - float amount = flow; - - if(next.block().acceptLiquid(next, tile, tile.entity.liquids.liquid, amount)){ - next.block().handleLiquid(next, tile, tile.entity.liquids.liquid, amount); - tile.entity.liquids.amount -= amount; + if(flow > 0f && ofract <= fract && next.block().acceptLiquid(next, tile, tile.entity.liquids.liquid, flow)){ + next.block().handleLiquid(next, tile, tile.entity.liquids.liquid, flow); + tile.entity.liquids.amount -= flow; return flow; + }else if(ofract > 0.1f && fract > 0.1f){ + Liquid liquid = tile.entity.liquids.liquid, other = next.entity.liquids.liquid; + if((other.flammability > 0.3f && liquid.temperature > 0.7f) || + (liquid.flammability > 0.3f && other.temperature > 0.7f)){ + tile.entity.damage(1 * Timers.delta()); + next.entity.damage(1 * Timers.delta()); + if(Mathf.chance(0.1 * Timers.delta())){ + Effects.effect(EnvironmentFx.fire, (tile.worldx() + next.worldx())/2f, (tile.worldy() + next.worldy())/2f); + } + }else if((liquid.temperature > 0.7f && other.temperature < 0.55f) || + (other.temperature > 0.7f && liquid.temperature < 0.55f)){ + tile.entity.liquids.amount -= Math.min(tile.entity.liquids.amount, 0.7f * Timers.delta()); + if(Mathf.chance(0.2f * Timers.delta())){ + Effects.effect(EnvironmentFx.steam, (tile.worldx() + next.worldx())/2f, (tile.worldy() + next.worldy())/2f); + } + } } }else if(leak && !next.block().solid && !next.block().hasLiquids){ float leakAmount = Math.min(tile.entity.liquids.amount, tile.entity.liquids.amount/1.5f);