Force projector implementation

This commit is contained in:
Anuken
2018-09-07 23:24:55 -04:00
parent d046591512
commit 7dd487ccc5
20 changed files with 968 additions and 797 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 631 B

+1
View File
@@ -289,6 +289,7 @@ text.blocks.liquidcapacity=Liquid Capacity
text.blocks.maxitemssecond=Max Items
text.blocks.powerrange=Power Range
text.blocks.poweruse=Power Use
text.blocks.powerdamage=Power/Damage
text.blocks.inputitemcapacity=Input Item Capacity
text.blocks.outputitemcapacity=Output Item Capacity
text.blocks.itemcapacity=Item Capacity
+6 -6
View File
@@ -30,19 +30,19 @@ void main() {
vec2 T = v_texCoord.xy;
vec2 coords = (T * u_texsize) + u_offset;
T += vec2(sin(coords.y / 3.0 + u_time / 20.0) / 240.0, sin(coords.x / 3.0 + u_time / 20.0) / 240.0) * u_scaling;
float si = 1.0 + sin(u_time / 20.0) / 8.0;
float si = sin(u_time / 20.0) / 8.0;
vec4 color = texture2D(u_texture, T) * vec4(si, si, si, 1.0);
vec4 color = texture2D(u_texture, T);
vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y);
bool any = false;
float thickness = 1.0;
float step = 1.5;
float step = 2.0;
if(texture2D(u_texture, T).a < 0.1 &&
(texture2D(u_texture, T + vec2(0, step) * v).a > 0.1 || texture2D(u_texture, T + vec2(0, -step) * v).a > 0.1 ||
@@ -50,7 +50,7 @@ void main() {
any = true;
if(any){
gl_FragColor = u_color * vec4(si, si, si, 1.0);
gl_FragColor = mix(u_color, vec4(1.0), si);
}else{
if(color.a > 0.1){
@@ -67,7 +67,7 @@ void main() {
float fin = 1.0 - hit.z;
if(abs(distance(vec2(hit.x, hit.y), coords - u_texsize/2.0) - rad) < 1.0){
color = mix(color, u_color* vec4(si, si, si, 1.0), (1.0 * fin));
color = mix(color, mix(u_color, vec4(1.0), si), (1.0 * fin));
color.a = ALPHA + 0.82 *fin;
}
}
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 97 KiB

+3 -1
View File
@@ -17,6 +17,7 @@ import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Version;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.entities.impl.EffectEntity;
@@ -129,7 +130,7 @@ public class Vars{
public static EntityGroup<EffectEntity> effectGroup;
public static EntityGroup<DrawTrait> groundEffectGroup;
public static EntityGroup<ItemDrop> itemGroup;
public static EntityGroup<ShieldEntity> shieldGroup;
public static EntityGroup<Puddle> puddleGroup;
public static EntityGroup<Fire> fireGroup;
public static EntityGroup<BaseUnit>[] unitGroups;
@@ -163,6 +164,7 @@ public class Vars{
groundEffectGroup = Entities.addGroup(DrawTrait.class, false);
puddleGroup = Entities.addGroup(Puddle.class, false).enableMapping();
itemGroup = Entities.addGroup(ItemDrop.class).enableMapping();
shieldGroup = Entities.addGroup(ShieldEntity.class);
fireGroup = Entities.addGroup(Fire.class, false).enableMapping();
unitGroups = new EntityGroup[Team.all.length];
@@ -77,13 +77,13 @@ public class DefenseBlocks extends BlockList implements ContentList{
}};
overdriveProjector = new OverdriveProjector("overdrive-projector"){{
consumes.power(0.25f);
consumes.power(0.35f);
size = 2;
consumes.item(Items.phasematter).optional(true);
}};
forceProjector = new ForceProjector("force-projector"){{
consumes.power(0.25f);
consumes.power(0.2f);
size = 3;
consumes.item(Items.phasematter).optional(true);
}};
@@ -19,7 +19,8 @@ public class BlockFx extends FxList implements ContentList{
public static Effect reactorsmoke, nuclearsmoke, nuclearcloud, redgeneratespark, generatespark, fuelburn, plasticburn,
pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, producesmoke, smeltsmoke, formsmoke, blastsmoke,
lava, dooropen, doorclose, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, mine, mineBig, mineHuge,
smelt, teleportActivate, teleport, teleportOut, ripple, bubble, commandSend, healBlock, healBlockFull, healWaveMend, overdriveWave, overdriveBlockFull;
smelt, teleportActivate, teleport, teleportOut, ripple, bubble, commandSend, healBlock, healBlockFull, healWaveMend, overdriveWave,
overdriveBlockFull, shieldBreak;
@Override
public void load(){
@@ -315,9 +316,16 @@ public class BlockFx extends FxList implements ContentList{
overdriveBlockFull = new Effect(60, e -> {
Draw.color(e.color);
Draw.alpha(e.fslope() * 0.5f);
Draw.alpha(e.fslope() * 0.4f);
Fill.square(e.x, e.y, e.rotation * tilesize);
Draw.color();
});
shieldBreak = new Effect(40, e -> {
Draw.color(Color.WHITE);
Lines.stroke(3f * e.fout());
Lines.poly(e.x, e.y, 6, e.rotation, 90);
Draw.reset();
});
}
}
@@ -136,6 +136,7 @@ public class Logic extends Module{
}
Entities.update(puddleGroup);
Entities.update(tileGroup);
Entities.update(shieldGroup);
Entities.update(bulletGroup);
Entities.update(fireGroup);
Entities.update(playerGroup);
+12 -1
View File
@@ -20,8 +20,12 @@ import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity;
import io.anuke.mindustry.world.meta.BlockFlag;
import io.anuke.ucore.core.*;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.entities.EntityDraw;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.entities.impl.EffectEntity;
@@ -269,6 +273,13 @@ public class Renderer extends RendererModule{
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
overlays.drawTop();
Shaders.shield.color.set(Palette.accent);
Graphics.beginShaders(Shaders.shield);
EntityDraw.draw(shieldGroup);
EntityDraw.drawWith(shieldGroup, shield -> true, shield -> ((ShieldEntity)shield).drawOver());
Graphics.endShaders();
if(showPaths && debug) drawDebug();
Graphics.flushSurface();
@@ -260,7 +260,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
}
timeScaleDuration -= Timers.delta();
if(timeScaleDuration <= 0f){
if(timeScaleDuration <= 0f || !tile.block().canOverdrive){
timeScale = 1f;
}
@@ -170,7 +170,7 @@ public class Shaders{
public static class Shield extends Shader{
public static final int MAX_HITS = 3 * 64;
public Color color = new Color();
public FloatArray hits;
public FloatArray hits = new FloatArray();
public Shield(){
super("shield", "default");
@@ -103,6 +103,8 @@ public class Block extends BaseBlock {
public boolean turretIcon = false;
/**Whether units target this block.*/
public boolean targetable = true;
/**Whether the overdrive core has any effect on this block.*/
public boolean canOverdrive = true;
protected Array<Tile> tempTiles = new Array<>();
protected Color tempColor = new Color();
@@ -1,29 +1,64 @@
package io.anuke.mindustry.world.blocks.defense;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import io.anuke.mindustry.content.fx.BlockFx;
import io.anuke.mindustry.content.fx.BulletFx;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.traits.SyncTrait;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.StatUnit;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.entities.EntityPhysics;
import io.anuke.ucore.entities.impl.BaseEntity;
import io.anuke.ucore.entities.trait.DrawTrait;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.util.Mathf;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.*;
import static io.anuke.mindustry.Vars.bulletGroup;
import static io.anuke.mindustry.Vars.*;
public class ForceProjector extends Block {
protected float radius = 100f;
protected float breakage = 500f;
protected float cooldownNormal = 1.5f;
protected float cooldownLiquid = 1.5f;
protected float cooldownBrokenBase = 0.3f;
protected float powerDamage = 0.1f;
protected TextureRegion topRegion;
public ForceProjector(String name) {
super(name);
update = true;
solid = true;
hasPower = true;
canOverdrive = false;
hasLiquids = true;
powerCapacity = 60f;
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.1f)).optional(true).update(false);
}
@Override
public void load(){
super.load();
topRegion = Draw.region(name + "-top");
}
@Override
public void setStats(){
super.setStats();
stats.add(BlockStat.powerDamage, powerDamage, StatUnit.powerUnits);
}
@Override
@@ -34,6 +69,83 @@ public class ForceProjector extends Block {
entity.shield = new ShieldEntity(tile);
entity.shield.add();
}
entity.radscl = Mathf.lerpDelta(entity.radscl, entity.broken ? 0f : 1f, 0.05f);
if(Mathf.chance(Timers.delta() * entity.buildup / breakage * 0.1f)){
Effects.effect(BlockFx.reactorsmoke, tile.drawx() + Mathf.range(tilesize/2f), tile.drawy() + Mathf.range(tilesize/2f));
}
if(!entity.cons.valid()){
entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.1f);
if(entity.warmup <= 0.09f){
entity.broken = true;
}
}else{
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.1f);
float powerUse = Math.min(powerDamage * entity.delta() * (1f + entity.buildup / breakage), powerCapacity);
entity.power.amount -= powerUse;
}
if(entity.buildup > 0){
float scale = !entity.broken ? cooldownNormal : cooldownBrokenBase;
if(consumes.get(ConsumeLiquidFilter.class).valid(this, entity)){
consumes.get(ConsumeLiquidFilter.class).update(this, entity);
scale *= (cooldownLiquid * (1f+(entity.liquids.current().heatCapacity-0.4f)*0.9f));
}
entity.buildup -= Timers.delta()*scale;
}
if(entity.broken && entity.buildup <= 0 && entity.warmup >= 0.9f){
entity.broken = false;
}
if(entity.buildup >= breakage && !entity.broken){
entity.broken = true;
entity.buildup = breakage;
Effects.effect(BlockFx.shieldBreak, tile.drawy(), tile.drawy(), radius);
}
if(entity.hit > 0f){
entity.hit -= 1f/5f * Timers.delta();
}
if(!entity.broken){
EntityPhysics.getNearby(bulletGroup, tile.drawx(), tile.drawy(), radius * entity.radscl*2f, bullet -> {
if(bullet instanceof Bullet && ((Bullet) bullet).getTeam() != tile.getTeam() && isInsideHexagon(bullet.getX(), bullet.getY(), radius * 2f * entity.radscl, tile.drawx(), tile.drawy())){
((Bullet) bullet).absorb();
Effects.effect(BulletFx.absorb, bullet);
float hit = ((Bullet) bullet).getDamage()*powerDamage;
entity.hit = 1f;
entity.power.amount -= Math.min(hit, entity.power.amount);
entity.buildup += ((Bullet) bullet).getDamage() * entity.warmup;
}
});
}
}
boolean isInsideHexagon(float x0, float y0, float d, float x, float y) {
float dx = Math.abs(x - x0)/d;
float dy = Math.abs(y - y0)/d;
float a = 0.25f * Mathf.sqrt3;
return (dy <= a) && (a*dx + 0.25*dy <= 0.5*a);
}
@Override
public void draw(Tile tile){
super.draw(tile);
ForceEntity entity = tile.entity();
if(entity.buildup <= 0f) return;
Draw.alpha(entity.buildup / breakage * 0.75f/* * Mathf.absin(Timers.time(), 10f - (entity.buildup/breakage)*6f, 1f)*/);
Graphics.setAdditiveBlending();
Draw.rect(topRegion, tile.drawx(), tile.drawy());
Graphics.setNormalBlending();
Draw.reset();
}
@Override
@@ -43,41 +155,68 @@ public class ForceProjector extends Block {
class ForceEntity extends TileEntity{
ShieldEntity shield;
boolean broken = true;
float buildup = 0f;
float radscl = 0f;
float hit;
float warmup;
@Override
public void write(DataOutputStream stream) throws IOException{
stream.writeBoolean(broken);
stream.writeFloat(buildup);
stream.writeFloat(radscl);
stream.writeFloat(warmup);
}
@Override
public void read(DataInputStream stream) throws IOException{
broken = stream.readBoolean();
buildup = stream.readFloat();
radscl = stream.readFloat();
warmup = stream.readFloat();
}
}
class ShieldEntity extends BaseEntity implements DrawTrait, SyncTrait{
final Tile tile;
final ForceProjector block;
public class ShieldEntity extends BaseEntity implements DrawTrait, SyncTrait{
final ForceEntity entity;
public ShieldEntity(Tile tile){
this.tile = tile;
this.block = (ForceProjector)tile.block();
this.entity = tile.entity();
set(tile.drawx(), tile.drawy());
}
@Override
public void update(){
if(entity.isDead() || !entity.isAdded()){
remove();
}
}
@Override
public float drawSize(){
return radius*2f+2f*entity.radscl;
}
@Override
public void draw(){
Draw.color(Palette.accent);
Draw.alpha(0.5f);
Fill.polyTri(x, y, 6, radius*entity.radscl);
Draw.color();
}
int range = 3;
float rad = 12f;
float space = rad*2-2f;
for (int y = -range; y <= range; y++) {
for (int x = -range; x <= range; x++) {
//if(Mathf.dst(x, y) > range) continue;
float wx = tile.drawx() + x * space + ((y + range) % 2)*space/2f;
float wy = tile.drawy() + y * (space-1);
Fill.poly(wx, wy, 6, rad);
}
}
public void drawOver(){
if(entity.hit <= 0f) return;
Draw.color(Color.WHITE);
Draw.alpha(entity.hit);
Fill.polyTri(x, y, 6, radius*entity.radscl);
Draw.color();
}
@Override
public EntityGroup targetGroup(){
return bulletGroup;
return shieldGroup;
}
@Override
@@ -52,7 +52,7 @@ public class MendProjector extends Block{
public void update(Tile tile){
MendEntity entity = tile.entity();
entity.heat = Mathf.lerpDelta(entity.heat, entity.cons.valid() ? 1f : 0f, 0.08f);
entity.charge += entity.heat * Timers.delta();
entity.charge += entity.heat * entity.delta();
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f);
@@ -27,9 +27,9 @@ public class OverdriveProjector extends Block{
protected int timerUse = timers ++;
protected TextureRegion topRegion;
protected float reload = 250f;
protected float reload = 260f;
protected float range = 80f;
protected float speedBoost = 2f;
protected float speedBoost = 1.5f;
protected float speedBoostPhase = 0.5f;
protected float useTime = 300f;
@@ -39,6 +39,7 @@ public class OverdriveProjector extends Block{
update = true;
hasPower = true;
hasItems = true;
canOverdrive = false;
itemCapacity = 10;
}
@@ -67,28 +68,26 @@ public class OverdriveProjector extends Block{
Effects.effect(BlockFx.overdriveWave, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange);
entity.charge = 0f;
Timers.run(10f, () -> {
int tileRange = (int)(realRange / tilesize);
healed.clear();
int tileRange = (int)(realRange / tilesize);
healed.clear();
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue;
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue;
Tile other = world.tile(x, y);
Tile other = world.tile(x, y);
if(other == null) continue;
other = other.target();
if(other == null) continue;
other = other.target();
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null){
other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f);
other.entity.timeScale = Math.max(other.entity.timeScale, realBoost);
Effects.effect(BlockFx.overdriveBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
healed.add(other.packedPosition());
}
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null){
other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f);
other.entity.timeScale = Math.max(other.entity.timeScale, realBoost);
Effects.effect(BlockFx.overdriveBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
healed.add(other.packedPosition());
}
}
});
}
}
}
@@ -99,7 +99,7 @@ public class Conveyor extends Block{
ConveyorEntity entity = tile.entity();
byte rotation = tile.getRotation();
int frame = entity.clogHeat <= 0.5f ? (int) ((Timers.time() / 4f) % 4) : 0;
int frame = entity.clogHeat <= 0.5f ? (int) (((Timers.time() * speed * 8f * entity.timeScale)) % 4) : 0;
Draw.rect(regions[Mathf.clamp(entity.blendbits, 0, regions.length - 1)][Mathf.clamp(frame, 0, regions[0].length - 1)], tile.drawx(), tile.drawy(),
tilesize * entity.blendsclx, tilesize * entity.blendscly, rotation*90);
}
@@ -23,6 +23,7 @@ public enum BlockStat{
powerCapacity(StatCategory.power),
powerUse(StatCategory.power),
powerDamage(StatCategory.power),
powerRange(StatCategory.power),
powerTransferSpeed(StatCategory.power),
maxPowerGeneration(StatCategory.power),