Explosion propagation

This commit is contained in:
Anuken 2019-04-03 09:39:11 -04:00
parent 1c63ee6743
commit 75946b9d14
3 changed files with 82 additions and 17 deletions

View File

@ -97,7 +97,7 @@ public class WaveSpawner{
}
Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawn.x * tilesize, spawn.y * tilesize));
//would be interesting to see player structures survive this without hacks
Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, shockwaveBase + Mathf.random(shockwaveRand), 99999999f));
Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, shockwaveBase + Mathf.random(shockwaveRand), 99999999f, true));
}
}
}

View File

@ -331,8 +331,10 @@ public class Renderer implements ApplicationListener{
int w = world.width()*tilesize, h = world.height()*tilesize;
boolean isWater = settings.getBool("animatedwater");
settings.put("animatedwater", false);
boolean hadShields = Core.settings.getBool("animatedshields");
boolean hadWater = Core.settings.getBool("animatedwater");
Core.settings.put("animatedwater", false);
Core.settings.put("animatedshields", false);
FrameBuffer buffer = new FrameBuffer(w, h);
@ -366,7 +368,8 @@ public class Renderer implements ApplicationListener{
buffer.dispose();
settings.put("animatedwater", isWater);
Core.settings.put("animatedwater", hadWater);
Core.settings.put("animatedshields", hadShields);
}
}

View File

@ -1,22 +1,27 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.annotations.Annotations.Struct;
import io.anuke.arc.collection.GridBits;
import io.anuke.arc.collection.IntQueue;
import io.anuke.arc.function.Consumer;
import io.anuke.arc.function.Predicate;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.Geometry;
import io.anuke.arc.math.geom.Point2;
import io.anuke.arc.math.geom.Rectangle;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.util.Time;
import io.anuke.mindustry.content.Bullets;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.effect.Fire;
import io.anuke.mindustry.entities.effect.Lightning;
import io.anuke.mindustry.entities.type.Unit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.gen.PropCell;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.world.Tile;
@ -27,6 +32,8 @@ public class Damage{
private static Rectangle rect = new Rectangle();
private static Rectangle hitrect = new Rectangle();
private static Vector2 tr = new Vector2();
private static GridBits bits = new GridBits(30, 30);
private static IntQueue propagation = new IntQueue();
/**Creates a dynamic explosion based on specified parameters.*/
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){
@ -152,11 +159,16 @@ public class Damage{
/**Damages everything in a radius.*/
public static void damage(float x, float y, float radius, float damage){
damage(null, x, y, radius, damage);
damage(null, x, y, radius, damage, false);
}
/**Damages all entities and blocks in a radius that are enemies of the team.*/
public static void damage(Team team, float x, float y, float radius, float damage){
damage(team, x, y, radius, damage, false);
}
/**Damages all entities and blocks in a radius that are enemies of the team.*/
public static void damage(Team team, float x, float y, float radius, float damage, boolean complete){
Consumer<Unit> cons = entity -> {
if(entity.getTeam() == team || entity.dst(x, y) > radius){
return;
@ -175,25 +187,68 @@ public class Damage{
Units.getNearby(rect, cons);
}
int trad = (int) (radius / tilesize);
Tile tile = world.tileWorld(x, y);
if(tile != null){
tileDamage(tile.x, tile.y, trad);
if(!complete){
int trad = (int)(radius / tilesize);
Tile tile = world.tileWorld(x, y);
if(tile != null){
tileDamage(team, tile.x, tile.y, trad, damage);
}
}else{
completeDamage(team, x, y, radius, damage);
}
}
private static void tileDamage(int x, int y, int radius){
/*
public static void tileDamage(Team team, int startx, int starty, int radius, float baseDamage){
bits.clear();
propagation.clear();
int bitOffset = bits.width()/2;
propagation.addFirst(PropCell.get((byte)0, (byte)0, (short)baseDamage));
//clamp radius to fit bits
radius = Math.min(radius, bits.width()/2);
while(!propagation.isEmpty()){
int prop = propagation.removeLast();
int x = PropCell.x(prop);
int y = PropCell.y(prop);
int damage = PropCell.damage(prop);
//manhattan distance used for calculating falloff, results in a diamond pattern
int dst = Math.abs(x) + Math.abs(y);
int scaledDamage = (int)(damage * (1f - (float)dst / radius));
bits.set(bitOffset + x, bitOffset + y);
Tile tile = world.tile(startx + x, starty + y);
if(scaledDamage <= 0 || tile == null) continue;
//apply damage to entity if needed
if(tile.entity != null && tile.getTeam() != team){
int health = (int)tile.entity.health;
tile.entity.damage(scaledDamage);
scaledDamage -= health;
if(scaledDamage <= 0) continue;
}
for(Point2 p : Geometry.d4){
if(!bits.get(bitOffset + x + p.x, bitOffset + y + p.y)){
propagation.addFirst(PropCell.get((byte)(x + p.x), (byte)(y + p.y), (short)scaledDamage));
}
}
}
}
private static void completeDamage(Team team, float x, float y, float radius, float damage){
int trad = (int) (radius / tilesize);
for(int dx = -trad; dx <= trad; dx++){
for(int dy = -trad; dy <= trad; dy++){
Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy);
if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Mathf.dst(dx, dy, 0, 0) <= trad){
float amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage);
tile.entity.damage(amount);
if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Mathf.dst(dx, dy) <= trad){
tile.entity.damage(damage);
}
}
}*/
}
}
private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){
@ -202,4 +257,11 @@ public class Damage{
float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff);
return damage * scaled;
}
@Struct
class PropCellStruct{
byte x;
byte y;
short damage;
}
}