Fixed compile errors, unitification

This commit is contained in:
Anuken
2018-03-15 21:42:23 -04:00
parent 807c4688c2
commit 52c0a8e573
35 changed files with 392 additions and 347 deletions

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.BulletEntity;
import io.anuke.ucore.entities.Entity;
@@ -39,6 +40,10 @@ public class Bullet extends BulletEntity{
public boolean collidesTiles(){
return owner instanceof BaseUnit;
}
public Team team(){
return ((Unit)owner).team;
}
@Override
public void update(){

View File

@@ -3,12 +3,11 @@ package io.anuke.mindustry.entities;
import com.badlogic.gdx.graphics.Color;
import io.anuke.mindustry.entities.effect.DamageArea;
import io.anuke.mindustry.entities.effect.EMP;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
@@ -122,7 +121,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shellexplosion, b);
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 25f, (int)(damage * 2f/3f));
DamageArea.damage(b.team(), b.x, b.y, 25f, (int)(damage * 2f/3f));
}
},
flak = new BulletType(2.9f, 8) {
@@ -202,7 +201,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shockwaveSmall, b);
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 50f, (int)(damage * 2f/3f));
DamageArea.damage(b.team(), b.x, b.y, 50f, (int)(damage * 2f/3f));
}
},
yellowshell = new BulletType(1.2f, 20){
@@ -233,7 +232,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shockwaveSmall, b);
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 25f, (int)(damage * 2f/3f));
DamageArea.damage(b.team(), b.x, b.y, 25f, (int)(damage * 2f/3f));
}
},
blast = new BulletType(1.1f, 90){
@@ -371,7 +370,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.clusterbomb, b);
DamageArea.damage(!(b.owner instanceof BaseUnit), b.x, b.y, 35f, damage);
DamageArea.damage(b.team(), b.x, b.y, 35f, damage);
}
},
vulcan = new BulletType(4.5f, 12) {
@@ -450,7 +449,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void init(Bullet b) {
DamageArea.damageLine(b.owner, Fx.beamhit, b.x, b.y, b.angle(), length, damage);
DamageArea.damageLine(b.team(), Fx.beamhit, b.x, b.y, b.angle(), length, damage);
}
public void draw(Bullet b) {

View File

@@ -57,6 +57,13 @@ public class Player extends Unit{
heal();
}
@Override
public void onRemoteShoot(BulletType type, float x, float y, float rotation, short data) {
//TODO shoot!
Weapon weapon = Upgrade.getByID((byte)data);
weapon.shoot(player, x, y, rotation);
}
@Override
public float getMass(){
return mech.mass;
@@ -105,8 +112,8 @@ public class Player extends Unit{
ui.hudfrag.fadeRespawn(true);
}
/**called when a remote player death event is recieved*/
public void doRespawn(){
@Override
public void onRemoteDeath(){
dead = true;
Effects.effect(Fx.explosion, this);
Effects.shake(4f, 5f, this);
@@ -136,7 +143,7 @@ public class Player extends Unit{
float ft = Mathf.sin(walktime, 6f, 2f);
Draw.alpha(hitTime / hitDuration);
//Draw.alpha(hitTime / hitDuration);
for(int i : Mathf.signs){
tr.trns(footRotation, ft * i);
@@ -154,7 +161,7 @@ public class Player extends Unit{
Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, rotation - 90);
}
Draw.alpha(1f);
//Draw.alpha(1f);
x = px;
y = py;

View File

@@ -14,15 +14,24 @@ import static io.anuke.mindustry.Vars.threads;
/**Base class for any entity that needs to be synced across clients.*/
public abstract class SyncEntity extends DestructibleEntity{
protected transient Interpolator interpolator = new Interpolator();
/**Interpolator, used for smoothing position.*/
protected Interpolator interpolator = new Interpolator();
/**smoothed position and rotation*/
private Vector3 spos = new Vector3();
/**the general rotation.*/
public float rotation;
/**Called when a death event is recieved remotely.*/
public abstract void onRemoteDeath();
/**Called when a shoot event is recieved remotely.*/
public abstract void onRemoteShoot(BulletType type, float x, float y, float rotation, short data);
//Read and write spawn data, which is sent when the entity is requested
public abstract void writeSpawn(ByteBuffer data);
public abstract void readSpawn(ByteBuffer data);
//Read and write sync data, usually position
public abstract void write(ByteBuffer data);
public abstract void read(ByteBuffer data, long time);
@@ -101,6 +110,7 @@ public abstract class SyncEntity extends DestructibleEntity{
}
public void update(){
//TODO prevent rubberbanding from getting too bad, clamp values?
time += 1f / spacing * Math.min(Timers.delta(), 1f);

View File

@@ -1,18 +1,24 @@
package io.anuke.mindustry.entities;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.function.Predicate;
import static io.anuke.mindustry.Vars.playerGroup;
import static io.anuke.mindustry.Vars.unitGroups;
import static io.anuke.mindustry.Vars.*;
/**Utility class for unit-based interactions.*/
/**Utility class for unit and team interactions.*/
public class Units {
private static Rectangle rect = new Rectangle();
/**Iterates over all units on all teams, including players.*/
public static void allUnits(Consumer<Unit> cons){
//check all unit groups first
for(EntityGroup<BaseUnit> group : unitGroups){
if(!group.isEmpty()){
for(BaseUnit unit : group.all()){
@@ -21,12 +27,73 @@ public class Units {
}
}
//then check all player groups
for(Player player : playerGroup.all()){
cons.accept(player);
}
}
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
public static Unit getClosestEnemies(Team team, float x, float y, float range, Predicate<Unit> predicate){
Unit[] result = {null};
float[] cdist = {0};
getNearbyEnemies(team, rect, e -> {
if (!predicate.test(e))
return;
float dist = Vector2.dst(e.x, e.y, x, y);
if (dist < range) {
if (result[0] == null || dist < cdist[0]) {
result[0] = e;
cdist[0] = dist;
}
}
});
return result[0];
}
/**Iterates over all units in a rectangle.*/
public static void getNearby(Rectangle rect, Consumer<Unit> cons){
for(Team team : Team.values()){
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
if(!group.isEmpty()){
Entities.getNearby(group, rect, entity -> cons.accept((Unit)entity));
}
}
//now check all enemy players
Entities.getNearby(playerGroup, rect, player -> cons.accept((Unit)player));
}
/**Iterates over all units that are enemies of this team.*/
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
//check if it's an ally team to the 'main team'
boolean ally = state.team == team || state.allyTeams.contains(team);
ObjectSet<Team> targets = ally ? state.enemyTeams : state.allyTeams;
for(Team other : targets){
EntityGroup<BaseUnit> group = unitGroups[other.ordinal()];
if(!group.isEmpty()){
Entities.getNearby(group, rect, entity -> cons.accept((Unit)entity));
}
}
//now check all enemy players
Entities.getNearby(playerGroup, rect, player -> {
if(targets.contains(((Player)player).team)){
cons.accept((Unit)player);
}
});
}
/**Returns whether these two teams are enemies.*/
public static boolean areEnemies(Team team, Team other){
if(team == other) return false; //fast fail to be more efficient
boolean ally = state.team == team || state.allyTeams.contains(team);
boolean ally2 = state.team == other || state.allyTeams.contains(other);
return ally == ally2;
}
}

View File

@@ -2,27 +2,27 @@ package io.anuke.mindustry.entities.effect;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.entities.DestructibleEntity;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Physics;
import io.anuke.ucore.util.Translator;
import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.tilesize;
import static io.anuke.mindustry.Vars.world;
public class DamageArea{
private static Rectangle rect = new Rectangle();
private static Translator tr = new Translator();
//only for entities, not tiles (yet!)
public static void damageLine(Entity owner, Effect effect, float x, float y, float angle, float length, int damage){
/**Damages entities in a line.
* Only enemies of the specified team are damaged.*/
public static void damageLine(Team team, Effect effect, float x, float y, float angle, float length, int damage){
tr.trns(angle, length);
rect.setPosition(x, y).setSize(tr.x, tr.y);
float x2 = tr.x + x, y2 = tr.y + y;
@@ -44,10 +44,8 @@ public class DamageArea{
rect.width += expand*2;
rect.height += expand*2;
Consumer<SolidEntity> cons = e -> {
if(e == owner) return;
DestructibleEntity enemy = (DestructibleEntity) e;
Rectangle other = enemy.hitbox.getRect(enemy.x, enemy.y);
Consumer<Unit> cons = e -> {
Rectangle other = e.hitbox.getRect(e.x, e.y);
other.y -= expand;
other.x -= expand;
other.width += expand * 2;
@@ -57,53 +55,49 @@ public class DamageArea{
if (vec != null) {
Effects.effect(effect, vec.x, vec.y);
enemy.damage(damage);
e.damage(damage);
}
};
Entities.getNearby(enemyGroup, rect, cons);
if(state.friendlyFire) Entities.getNearby(playerGroup, rect, cons);
Units.getNearbyEnemies(team, rect, cons);
}
public static void damageEntities(float x, float y, float radius, int damage){
damage(true, x, y, radius, damage);
for(Player player : playerGroup.all()){
//if(player.isAndroid) continue;
int amount = calculateDamage(x, y, player.x, player.y, radius, damage);
player.damage(amount);
}
/**Damages everything in a radius.*/
public static void damage(float x, float y, float radius, int damage){
damage(null, x, y, radius, damage);
}
public static void damage(boolean enemies, float x, float y, float radius, int damage){
Consumer<SolidEntity> cons = entity -> {
DestructibleEntity enemy = (DestructibleEntity)entity;
if(enemy.distanceTo(x, y) > radius){
/**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, int damage){
Consumer<Unit> cons = entity -> {
if(entity.distanceTo(x, y) > radius){
return;
}
int amount = calculateDamage(x, y, enemy.x, enemy.y, radius, damage);
enemy.damage(amount);
int amount = calculateDamage(x, y, entity.x, entity.y, radius, damage);
entity.damage(amount);
};
if(enemies){
Entities.getNearby(enemyGroup, x, y, radius*2, cons);
rect.setSize(radius *2).setCenter(x, y);
if(team != null) {
Units.getNearbyEnemies(team, rect, cons);
}else{
int trad = (int)(radius / tilesize);
for(int dx = -trad; dx <= trad; dx ++){
for(int dy= -trad; dy <= trad; dy ++){
Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy);
if(tile != null && tile.entity != null && Vector2.dst(dx, dy, 0, 0) <= trad){
int amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage);
tile.entity.damage(amount);
}
Units.getNearby(rect, cons);
}
int trad = (int)(radius / tilesize);
for(int dx = -trad; dx <= trad; dx ++){
for(int dy= -trad; dy <= trad; dy ++){
Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy);
if(tile != null && tile.entity != null && (team == null || Units.areEnemies(team, tile.getTeam())) && Vector2.dst(dx, dy, 0, 0) <= trad){
int amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage);
tile.entity.damage(amount);
}
}
Entities.getNearby(playerGroup, x, y, radius*2, cons);
}
}
static int calculateDamage(float x, float y, float tx, float ty, float radius, int damage){
private static int calculateDamage(float x, float y, float tx, float ty, float radius, int damage){
float dist = Vector2.dst(x, y, tx, ty);
float scaled = 1f - dist/radius;
return (int)(damage * scaled);

View File

@@ -1,40 +1,45 @@
package io.anuke.mindustry.entities.effect;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.enemyGroup;
public class TeslaOrb extends Entity{
private Array<Vector2> points = new Array<>();
private ObjectSet<BaseUnit> hit = new ObjectSet<>();
private int damage = 0;
private float range = 0;
private float lifetime = 30f;
private final static Rectangle rect = new Rectangle();
private final Array<Vector2> points = new Array<>();
private final ObjectSet<BaseUnit> hit = new ObjectSet<>();
private final int damage;
private final float range;
private final float lifetime = 30f;
private final Vector2 vector = new Vector2();
private final Team team;
private float life = 0f;
private Vector2 vector = new Vector2();
private float curx = x, cury = y;
private boolean done = false;
public TeslaOrb(float x, float y, float range, int damage){
public TeslaOrb(Team team, float x, float y, float range, int damage){
set(x, y);
this.team = team;
this.damage = damage;
this.range = range;
}
void shock(){
float stopchance = 0.1f;
float curx = x, cury = y;
float shake = 3f;
int max = 7;
@@ -43,19 +48,19 @@ public class TeslaOrb extends Entity{
if(Mathf.chance(stopchance)){
break;
}
Array<SolidEntity> enemies = Entities.getNearby(enemyGroup, curx, cury, range*2f);
for(SolidEntity entity : enemies){
if(entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){
rect.setSize(range*2f).setCenter(curx, cury);
Units.getNearbyEnemies(team, rect, entity -> {
if(!done && entity != null && entity.distanceTo(curx, cury) < range && !hit.contains((BaseUnit)entity)){
hit.add((BaseUnit)entity);
points.add(new Vector2(entity.x + Mathf.range(shake), entity.y + Mathf.range(shake)));
damageEnemy((BaseUnit)entity);
curx = entity.x;
cury = entity.y;
break;
done = true;
}
}
});
}
if(points.size == 0){
@@ -107,11 +112,6 @@ public class TeslaOrb extends Entity{
Draw.rect("circle", x, y, rad, rad);
}
//Draw.color(Color.WHITE);
//Draw.stroke(2f - life/lifetime*2f);
//Draw.line(x1, y1, x2, y2);
Draw.reset();
previous = enemy;

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.entities.units;
import io.anuke.mindustry.entities.Bullet;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Unit;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.SolidEntity;
@@ -63,9 +64,19 @@ public class BaseUnit extends Unit {
hitTime = hitDuration;
}
@Override
public void onRemoteShoot(BulletType type, float x, float y, float rotation, short data) {
new Bullet(type, this, x, y, rotation).add().damage = data;
}
@Override
public void onDeath(){
type.onDeath(this, false);
type.onDeath(this);
}
@Override
public void onRemoteDeath(){
type.onRemoteDeath(this);
}
@Override

View File

@@ -67,7 +67,11 @@ public class UnitType {
//TODO
}
public void onDeath(BaseUnit enemy, boolean force){
public void onDeath(BaseUnit enemy){
//TODO
}
public void onRemoteDeath(BaseUnit enemy){
//TODO
}