mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-03 13:30:25 +07:00
Groupified entities, improved performance
This commit is contained in:
parent
56113cd1de
commit
25952985dd
@ -79,7 +79,7 @@ project(":core") {
|
||||
apply plugin: "java"
|
||||
|
||||
dependencies {
|
||||
compile 'com.github.Anuken:ucore:9d84d75ee1'
|
||||
compile 'com.github.Anuken:ucore:7752d632e1'
|
||||
compile "com.badlogicgames.gdx:gdx:$gdxVersion"
|
||||
compile "com.badlogicgames.gdx:gdx-ai:1.8.1"
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 744 B |
@ -34,6 +34,7 @@ public class Pathfind{
|
||||
|
||||
Tile[] path = enemy.path;
|
||||
|
||||
//REPRODUCE BUG: load in test map, then load save 1
|
||||
Tile prev = path[enemy.node - 1];
|
||||
|
||||
Tile target = path[enemy.node];
|
||||
|
@ -15,8 +15,7 @@ import io.anuke.mindustry.Mindustry;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.ai.Pathfind;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.EnemySpawn;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.*;
|
||||
import io.anuke.mindustry.entities.effect.Fx;
|
||||
import io.anuke.mindustry.entities.enemies.*;
|
||||
import io.anuke.mindustry.input.AndroidInput;
|
||||
@ -29,7 +28,7 @@ import io.anuke.mindustry.world.*;
|
||||
import io.anuke.ucore.UCore;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.graphics.Atlas;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
@ -44,6 +43,10 @@ public class Control extends Module{
|
||||
final Array<Weapon> weapons = new Array<>();
|
||||
final ObjectMap<Item, Integer> items = new ObjectMap<>();
|
||||
|
||||
final EntityGroup<Enemy> enemyGroup = Entities.addGroup(Enemy.class);
|
||||
final EntityGroup<TileEntity> tileGroup = Entities.addGroup(TileEntity.class, false);
|
||||
final EntityGroup<Bullet> bulletGroup = Entities.addGroup(Bullet.class);
|
||||
|
||||
Array<EnemySpawn> spawns = new Array<>();
|
||||
int wave = 1;
|
||||
float wavetime;
|
||||
@ -252,7 +255,7 @@ public class Control extends Module{
|
||||
enemy.set(tile.worldx() + Mathf.range(range), tile.worldy() + Mathf.range(range));
|
||||
enemy.tier = spawn.tier(wave, fl);
|
||||
Effects.effect(Fx.spawn, enemy);
|
||||
enemy.add();
|
||||
enemy.add(enemyGroup);
|
||||
|
||||
enemies ++;
|
||||
}catch (Exception e){
|
||||
@ -412,11 +415,7 @@ public class Control extends Module{
|
||||
}
|
||||
|
||||
if(Inputs.keyUp(Keys.C)){
|
||||
for(Entity entity : Entities.all()){
|
||||
if(entity instanceof Enemy){
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
enemyGroup.clear();
|
||||
}
|
||||
|
||||
if(Inputs.keyUp(Keys.O)){
|
||||
@ -479,7 +478,14 @@ public class Control extends Module{
|
||||
|
||||
Profiler.begin("entityUpdate");
|
||||
|
||||
Entities.update();
|
||||
//TODO
|
||||
Entities.update(Entities.defaultGroup());
|
||||
Entities.update(bulletGroup);
|
||||
Entities.update(enemyGroup);
|
||||
Entities.update(tileGroup);
|
||||
|
||||
Entities.collideGroups(enemyGroup, bulletGroup);
|
||||
Entities.collideGroups(Entities.defaultGroup(), bulletGroup);
|
||||
|
||||
Profiler.end("entityUpdate");
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.effect.Shaders;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.input.AndroidInput;
|
||||
@ -29,7 +28,6 @@ import io.anuke.ucore.UCore;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.entities.DestructibleEntity;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.graphics.Cache;
|
||||
import io.anuke.ucore.graphics.Caches;
|
||||
import io.anuke.ucore.modules.RendererModule;
|
||||
@ -124,9 +122,9 @@ public class Renderer extends RendererModule{
|
||||
}
|
||||
|
||||
Profiler.begin("draw");
|
||||
|
||||
|
||||
drawDefault();
|
||||
|
||||
|
||||
Profiler.end("draw");
|
||||
|
||||
if(Vars.debug && Vars.debugGL && Timers.get("profile", 60)){
|
||||
@ -147,13 +145,18 @@ public class Renderer extends RendererModule{
|
||||
Graphics.surface();
|
||||
|
||||
Profiler.begin("blockDraw");
|
||||
|
||||
renderTiles();
|
||||
|
||||
Profiler.end("blockDraw");
|
||||
|
||||
Profiler.begin("entityDraw");
|
||||
Entities.draw();
|
||||
|
||||
Graphics.shader(Shaders.outline, false);
|
||||
Entities.draw(control.enemyGroup);
|
||||
Graphics.shader();
|
||||
|
||||
Entities.draw(Entities.defaultGroup());
|
||||
Entities.draw(control.bulletGroup);
|
||||
|
||||
Profiler.end("entityDraw");
|
||||
|
||||
drawShield();
|
||||
@ -177,18 +180,15 @@ public class Renderer extends RendererModule{
|
||||
void drawEnemyMarkers(){
|
||||
Draw.color(Color.RED);
|
||||
Draw.alpha(0.6f);
|
||||
for(Entity entity : Entities.all()){
|
||||
if(entity instanceof Enemy){
|
||||
Enemy enemy = (Enemy) entity;
|
||||
for(Enemy enemy : control.enemyGroup.all()){
|
||||
|
||||
if(Tmp.r1.setSize(camera.viewportWidth, camera.viewportHeight).setCenter(camera.position.x, camera.position.y).overlaps(enemy.hitbox.getRect(enemy.x, enemy.y))){
|
||||
continue;
|
||||
}
|
||||
|
||||
float angle = Angles.angle(camera.position.x, camera.position.y, enemy.x, enemy.y);
|
||||
Angles.translation(angle, Unit.dp.inPixels(20f));
|
||||
Draw.rect("enemyarrow", camera.position.x + Angles.x(), camera.position.y + Angles.y(), angle);
|
||||
if(Tmp.r1.setSize(camera.viewportWidth, camera.viewportHeight).setCenter(camera.position.x, camera.position.y).overlaps(enemy.hitbox.getRect(enemy.x, enemy.y))){
|
||||
continue;
|
||||
}
|
||||
|
||||
float angle = Angles.angle(camera.position.x, camera.position.y, enemy.x, enemy.y);
|
||||
Angles.translation(angle, Unit.dp.inPixels(20f));
|
||||
Draw.rect("enemyarrow", camera.position.x + Angles.x(), camera.position.y + Angles.y(), angle);
|
||||
}
|
||||
Draw.color();
|
||||
}
|
||||
@ -303,8 +303,7 @@ public class Renderer extends RendererModule{
|
||||
|
||||
if(!Mathf.inBounds(worldx, worldy, floorCache))
|
||||
continue;
|
||||
Draw.linerect(worldx * chunksize * tilesize, worldy * chunksize * tilesize,
|
||||
chunksize * tilesize, chunksize * tilesize);
|
||||
Draw.linerect(worldx * chunksize * tilesize, worldy * chunksize * tilesize, chunksize * tilesize, chunksize * tilesize);
|
||||
}
|
||||
}
|
||||
Draw.reset();
|
||||
@ -330,7 +329,7 @@ public class Renderer extends RendererModule{
|
||||
}
|
||||
|
||||
void renderPixelOverlay(){
|
||||
|
||||
|
||||
//draw tutorial placement point
|
||||
if(Vars.control.tutorial.showBlock()){
|
||||
int x = World.core.x + Vars.control.tutorial.getPlacePoint().x;
|
||||
@ -348,10 +347,9 @@ public class Renderer extends RendererModule{
|
||||
}
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
|
||||
//draw placement box
|
||||
if(player.recipe != null && Vars.control.hasItems(player.recipe.requirements)
|
||||
&& (!ui.hasMouse() || android) && AndroidInput.mode == PlaceMode.cursor){
|
||||
if(player.recipe != null && Vars.control.hasItems(player.recipe.requirements) && (!ui.hasMouse() || android) && AndroidInput.mode == PlaceMode.cursor){
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
|
||||
@ -424,7 +422,7 @@ public class Renderer extends RendererModule{
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//draw selected block health
|
||||
if(player.recipe == null && !ui.hasMouse()){
|
||||
Tile tile = World.tile(Input.tilex(), Input.tiley());
|
||||
@ -443,23 +441,22 @@ public class Renderer extends RendererModule{
|
||||
}
|
||||
}
|
||||
|
||||
boolean smoothcam = Settings.getBool("smoothcam");
|
||||
|
||||
//draw entity health bars
|
||||
for(Entity entity : Entities.all()){
|
||||
if(entity instanceof DestructibleEntity && !(entity instanceof TileEntity)){
|
||||
DestructibleEntity dest = ((DestructibleEntity) entity);
|
||||
|
||||
if(dest instanceof Player && Vars.snapCamera && smoothcam && Settings.getBool("pixelate")){
|
||||
drawHealth((int) dest.x, (int) dest.y - 7f, dest.health, dest.maxhealth);
|
||||
}else{
|
||||
drawHealth(dest.x, dest.y - 7f, dest.health, dest.maxhealth);
|
||||
}
|
||||
|
||||
}
|
||||
for(Enemy entity : control.enemyGroup.all()){
|
||||
drawHealth(entity);
|
||||
}
|
||||
|
||||
drawHealth(player);
|
||||
}
|
||||
|
||||
void drawHealth(DestructibleEntity dest){
|
||||
if(dest instanceof Player && Vars.snapCamera && Settings.getBool("smoothcam") && Settings.getBool("pixelate")){
|
||||
drawHealth((int) dest.x, (int) dest.y - 7f, dest.health, dest.maxhealth);
|
||||
}else{
|
||||
drawHealth(dest.x, dest.y - 7f, dest.health, dest.maxhealth);
|
||||
}
|
||||
}
|
||||
|
||||
void drawHealth(float x, float y, float health, float maxhealth){
|
||||
drawBar(Color.RED, x, y, health / maxhealth);
|
||||
}
|
||||
|
@ -4,9 +4,7 @@ import static io.anuke.mindustry.Vars.tilesize;
|
||||
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.World;
|
||||
import io.anuke.ucore.entities.BulletEntity;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
import io.anuke.ucore.entities.SolidEntity;
|
||||
import io.anuke.ucore.entities.*;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class Bullet extends BulletEntity{
|
||||
@ -75,5 +73,10 @@ public class Bullet extends BulletEntity{
|
||||
public int getDamage(){
|
||||
return damage == -1 ? type.damage : damage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bullet add(){
|
||||
return super.add(Entities.getGroup(Bullet.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import io.anuke.mindustry.world.blocks.ProductionBlocks;
|
||||
import io.anuke.mindustry.world.blocks.types.Wall;
|
||||
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.util.Mathf;
|
||||
|
||||
@ -38,7 +39,7 @@ public class TileEntity extends Entity{
|
||||
health = maxhealth;
|
||||
|
||||
if(added){
|
||||
add();
|
||||
add(Entities.getGroup(TileEntity.class));
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -34,26 +34,25 @@ public class TeslaOrb extends Entity{
|
||||
float curx = x, cury = y;
|
||||
float shake = 3f;
|
||||
|
||||
outer:
|
||||
while(true){
|
||||
int max = 7;
|
||||
|
||||
while(points.size < max){
|
||||
if(Mathf.chance(stopchance)){
|
||||
break;
|
||||
}
|
||||
Array<SolidEntity> enemies = Entities.getNearby(curx, cury, range*2f);
|
||||
|
||||
Array<SolidEntity> enemies = Entities.getNearby(Entities.getGroup(Enemy.class), curx, cury, range*2f);
|
||||
|
||||
for(SolidEntity entity : enemies){
|
||||
if(entity instanceof Enemy && entity.distanceTo(curx, cury) < range
|
||||
&& !hit.contains((Enemy)entity)){
|
||||
if(entity.distanceTo(curx, cury) < range && !hit.contains((Enemy)entity)){
|
||||
hit.add((Enemy)entity);
|
||||
points.add(new Vector2(entity.x + Mathf.range(shake), entity.y + Mathf.range(shake)));
|
||||
damageEnemy((Enemy)entity);
|
||||
curx = entity.x;
|
||||
cury = entity.y;
|
||||
continue outer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(points.size == 0){
|
||||
@ -122,6 +121,10 @@ public class TeslaOrb extends Entity{
|
||||
Timers.run(1f, ()->{
|
||||
shock();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drawSize(){
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package io.anuke.mindustry.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
@ -20,14 +19,9 @@ import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Tmp;
|
||||
|
||||
public class Enemy extends DestructibleEntity{
|
||||
public final static Color[] tierColors = {
|
||||
Color.valueOf("ffe451"),
|
||||
Color.valueOf("f48e20"),
|
||||
Color.valueOf("ff6757"),
|
||||
Color.valueOf("ff2d86")
|
||||
};
|
||||
public final static Color[] tierColors = { Color.valueOf("ffe451"), Color.valueOf("f48e20"), Color.valueOf("ff6757"), Color.valueOf("ff2d86") };
|
||||
public final static int maxtier = 4;
|
||||
|
||||
|
||||
protected float speed = 0.3f;
|
||||
protected float reload = 32;
|
||||
protected float range = 60;
|
||||
@ -38,152 +32,151 @@ public class Enemy extends DestructibleEntity{
|
||||
protected BulletType bullet = BulletType.small;
|
||||
protected String shootsound = "enemyshoot";
|
||||
protected int damage;
|
||||
|
||||
|
||||
public int spawn;
|
||||
public int node = -1;
|
||||
public Tile[] path;
|
||||
|
||||
|
||||
public Vector2 direction = new Vector2();
|
||||
public float xvelocity, yvelocity;
|
||||
public Entity target;
|
||||
public int tier = 1;
|
||||
|
||||
|
||||
public Enemy(int spawn){
|
||||
|
||||
public Enemy(int spawn) {
|
||||
this.spawn = spawn;
|
||||
|
||||
|
||||
hitbox.setSize(5f);
|
||||
hitboxTile.setSize(4f);
|
||||
|
||||
|
||||
maxhealth = 60;
|
||||
heal();
|
||||
}
|
||||
|
||||
|
||||
public float drawSize(){
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
void move(){
|
||||
boolean nearCore = distanceTo(World.core.worldx(), World.core.worldy()) <= range - 18f;
|
||||
|
||||
|
||||
Vector2 vec;
|
||||
|
||||
|
||||
if(nearCore){
|
||||
vec = Tmp.v2.setZero();
|
||||
target = World.core.entity;
|
||||
}else{
|
||||
vec = Pathfind.find(this);
|
||||
vec = Pathfind.find(this);
|
||||
vec.sub(x, y).setLength(speed);
|
||||
}
|
||||
|
||||
Array<SolidEntity> entities = Entities.getNearby(x, y, range);
|
||||
|
||||
|
||||
Vector2 shift = Tmp.v3.setZero();
|
||||
float shiftRange = hitbox.width + 3f;
|
||||
float avoidRange = 16f;
|
||||
float avoidSpeed = 0.1f;
|
||||
|
||||
for(SolidEntity other : entities){
|
||||
Entities.getNearby(Entities.getGroup(Enemy.class), x, y, range, other -> {
|
||||
float dst = other.distanceTo(this);
|
||||
if(other != this && other instanceof Enemy){
|
||||
if(dst < shiftRange){
|
||||
float scl = Mathf.clamp(1.4f - dst/shiftRange);
|
||||
shift.add((x - other.x) * scl, (y - other.y) * scl);
|
||||
}else if(dst < avoidRange){
|
||||
Tmp.v2.set((x - other.x), (y - other.y)).setLength(avoidSpeed);
|
||||
shift.add(Tmp.v2);
|
||||
}
|
||||
if(other == this)
|
||||
return;
|
||||
|
||||
if(dst < shiftRange){
|
||||
float scl = Mathf.clamp(1.4f - dst / shiftRange);
|
||||
shift.add((x - other.x) * scl, (y - other.y) * scl);
|
||||
}else if(dst < avoidRange){
|
||||
Tmp.v2.set((x - other.x), (y - other.y)).setLength(avoidSpeed);
|
||||
shift.add(Tmp.v2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
shift.limit(1f);
|
||||
vec.add(shift.scl(0.5f));
|
||||
|
||||
move(vec.x*Timers.delta(), vec.y*Timers.delta());
|
||||
|
||||
|
||||
move(vec.x * Timers.delta(), vec.y * Timers.delta());
|
||||
|
||||
if(Timers.get(this, "target", 15) && !nearCore){
|
||||
target = World.findTileTarget(x, y, null, range, false);
|
||||
|
||||
|
||||
//no tile found
|
||||
if(target == null){
|
||||
target = Entities.getClosest(entities, x, y, range, e -> e instanceof Player);
|
||||
target = Entities.getClosest(Entities.defaultGroup(), x, y, range, e -> e instanceof Player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(target != null && bullet != null){
|
||||
updateShooting();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateShooting(){
|
||||
if(Timers.get(this, "reload", reload*Vars.multiplier)){
|
||||
if(Timers.get(this, "reload", reload * Vars.multiplier)){
|
||||
shoot(bullet);
|
||||
Effects.sound(shootsound, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void shoot(BulletType bullet){
|
||||
shoot(bullet, 0);
|
||||
}
|
||||
|
||||
|
||||
void shoot(BulletType bullet, float rotation){
|
||||
vector.set(length, 0).rotate(direction.angle() + rotation);
|
||||
Bullet out = new Bullet(bullet, this, x+vector.x, y+vector.y, direction.angle() + rotation).add();
|
||||
out.damage = (int)(damage*Vars.multiplier);
|
||||
Bullet out = new Bullet(bullet, this, x + vector.x, y + vector.y, direction.angle() + rotation).add();
|
||||
out.damage = (int) (damage * Vars.multiplier);
|
||||
}
|
||||
|
||||
|
||||
public void findClosestNode(){
|
||||
Pathfind.find(this);
|
||||
|
||||
|
||||
int index = 0;
|
||||
int cindex = -1;
|
||||
float dst = Float.MAX_VALUE;
|
||||
|
||||
|
||||
//find closest node index
|
||||
for(Tile tile : path){
|
||||
if(Vector2.dst(tile.worldx(), tile.worldy(), x, y) < dst){
|
||||
dst = Vector2.dst(tile.worldx(), tile.worldy(), x, y);
|
||||
cindex = index;
|
||||
}
|
||||
|
||||
index ++;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
node = Math.max(cindex, 1);
|
||||
|
||||
|
||||
cindex = Math.max(cindex, 1);
|
||||
|
||||
//set node to that index
|
||||
node = cindex;
|
||||
|
||||
|
||||
int x2 = path[node].x, y2 = path[node].y;
|
||||
|
||||
//if the enemy can move to that node right now, set its position to it
|
||||
if(World.raycast(Mathf.scl2(x, Vars.tilesize), Mathf.scl2(y, Vars.tilesize), x2, y2) == null){
|
||||
Timers.run(Mathf.random(15f), ()->{
|
||||
|
||||
//if the enemy can't move to that node right now, set its position to it
|
||||
if(World.raycast(Mathf.scl2(x, Vars.tilesize), Mathf.scl2(y, Vars.tilesize), x2, y2) != null){
|
||||
Timers.run(Mathf.random(15f), () -> {
|
||||
set(x2 * Vars.tilesize, y2 * Vars.tilesize);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void added(){
|
||||
if(bullet != null){
|
||||
damage = (int)(bullet.damage * (1 + (tier - 1) * 1f));
|
||||
damage = (int) (bullet.damage * (1 + (tier - 1) * 1f));
|
||||
}
|
||||
|
||||
|
||||
maxhealth *= tier;
|
||||
speed += 0.04f*tier + Mathf.range(0.1f);
|
||||
speed += 0.04f * tier + Mathf.range(0.1f);
|
||||
reload /= Math.max(tier / 1.5f, 1f);
|
||||
range += tier*5;
|
||||
range += tier * 5;
|
||||
speed = Math.max(speed, 0.07f);
|
||||
|
||||
|
||||
heal();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidEntity other){
|
||||
return (other instanceof Bullet) && !(((Bullet)other).owner instanceof Enemy);
|
||||
return (other instanceof Bullet) && !(((Bullet) other).owner instanceof Enemy);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDeath(){
|
||||
Effects.effect(Fx.explosion, this);
|
||||
@ -192,44 +185,50 @@ public class Enemy extends DestructibleEntity{
|
||||
remove();
|
||||
dead = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
if(!dead){
|
||||
Vars.control.enemyDeath();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
float lastx = x, lasty = y;
|
||||
|
||||
|
||||
move();
|
||||
|
||||
|
||||
xvelocity = (x - lastx) / Timers.delta();
|
||||
yvelocity = (y - lasty) / Timers.delta();
|
||||
|
||||
|
||||
if(target == null || alwaysRotate){
|
||||
direction.add(xvelocity * Timers.delta() / 3f, yvelocity * Timers.delta() / 3f);
|
||||
direction.limit(speed*rotatespeed);
|
||||
direction.limit(speed * rotatespeed);
|
||||
}else{
|
||||
float angle = angleTo(target);
|
||||
direction.lerp(vector.set(0, 1).setAngle(angle), turretrotatespeed * Timers.delta());
|
||||
direction.lerp(vector.set(1f, 0f).rotate(angle), turretrotatespeed * Timers.delta());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
String region = ClassReflection.getSimpleName(getClass()).toLowerCase() + "-t" + Mathf.clamp(tier, 1, 3);
|
||||
|
||||
Shaders.outline.color.set(tierColors[tier - 1]);
|
||||
Shaders.outline.region = Draw.region(region);
|
||||
|
||||
Shaders.outline.apply();
|
||||
|
||||
Draw.color();
|
||||
Draw.rect(region, x, y, direction.angle() - 90);
|
||||
|
||||
Graphics.flush();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
|
||||
String region = ClassReflection.getSimpleName(getClass()).toLowerCase() + "-t" + Mathf.clamp(tier, 1, 3);
|
||||
|
||||
//TODO is this really necessary?
|
||||
Shaders.outline.color.set(tierColors[tier-1]);
|
||||
Shaders.outline.region = Draw.region(region);
|
||||
|
||||
Graphics.shader(Shaders.outline);
|
||||
Draw.color();
|
||||
Draw.rect(region, x, y, direction.angle()-90);
|
||||
Graphics.shader();
|
||||
public <T extends Entity> T add(){
|
||||
return (T) add(Entities.getGroup(Enemy.class));
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ public class HealerEnemy extends Enemy{
|
||||
move(vec.x*Timers.delta(), vec.y*Timers.delta());
|
||||
|
||||
if(Timers.get(this, "target", 15)){
|
||||
target = Entities.getClosest(x, y, range, e->e instanceof Enemy && e != this && ((Enemy)e).healthfrac() < 1f);
|
||||
target = Entities.getClosest(Entities.getGroup(Enemy.class),
|
||||
x, y, range, e -> e instanceof Enemy && e != this && ((Enemy)e).healthfrac() < 1f);
|
||||
}
|
||||
|
||||
if(target != null){
|
||||
|
@ -3,6 +3,7 @@ package io.anuke.mindustry.entities.enemies;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
|
||||
@ -14,12 +15,15 @@ public class TargetEnemy extends Enemy{
|
||||
maxhealth = 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
void move(){
|
||||
|
||||
speed = 0f;
|
||||
super.move();
|
||||
}
|
||||
|
||||
void shoot(){
|
||||
|
||||
@Override
|
||||
void shoot(BulletType bullet){
|
||||
//do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,7 +23,6 @@ import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.blocks.Blocks;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.Entity;
|
||||
|
||||
/*
|
||||
* Save format:
|
||||
@ -182,17 +181,16 @@ public class SaveIO{
|
||||
|
||||
int totalEnemies = 0;
|
||||
|
||||
for(Entity entity : Entities.all()){
|
||||
if(entity instanceof Enemy && idEnemies.containsKey((Class<? extends Enemy>) entity.getClass())){
|
||||
for(Enemy entity : Entities.get(Enemy.class)){
|
||||
if(idEnemies.containsKey(entity.getClass())){
|
||||
totalEnemies ++;
|
||||
}
|
||||
}
|
||||
|
||||
stream.writeInt(totalEnemies); //enemy amount
|
||||
|
||||
for(Entity entity : Entities.all()){
|
||||
if(entity instanceof Enemy && idEnemies.containsKey((Class<? extends Enemy>) entity.getClass())){
|
||||
Enemy enemy = (Enemy)entity;
|
||||
for(Enemy enemy : Entities.get(Enemy.class)){
|
||||
if(idEnemies.containsKey(enemy.getClass())){
|
||||
stream.writeByte(idEnemies.get(enemy.getClass())); //type
|
||||
stream.writeByte(enemy.spawn); //lane
|
||||
stream.writeFloat(enemy.x); //x
|
||||
@ -333,7 +331,7 @@ public class SaveIO{
|
||||
enemy.x = x;
|
||||
enemy.y = y;
|
||||
enemy.tier = tier;
|
||||
enemy.add();
|
||||
enemy.add(Entities.getGroup(Enemy.class));
|
||||
enemiesToUpdate.add(enemy);
|
||||
}catch (Exception e){
|
||||
throw new RuntimeException(e);
|
||||
|
@ -10,6 +10,7 @@ import io.anuke.mindustry.Mindustry;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.GameState;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.enemies.Enemy;
|
||||
import io.anuke.mindustry.resource.Item;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Draw;
|
||||
@ -109,14 +110,6 @@ public class HudFragment implements Fragment{
|
||||
visible(()->!GameState.is(State.menu));
|
||||
}}.end();
|
||||
|
||||
//settings icon
|
||||
new table(){{
|
||||
atop().aright();
|
||||
new imagebutton("icon-info", Unit.dp.inPixels(30f), ()->{
|
||||
ui.showAbout();
|
||||
}).get().pad(14);
|
||||
}}.end().visible(()->GameState.is(State.menu));
|
||||
|
||||
//respawn background table
|
||||
new table("white"){{
|
||||
respawntable = get();
|
||||
@ -140,7 +133,7 @@ public class HudFragment implements Fragment{
|
||||
new table(){{
|
||||
abottom();
|
||||
aleft();
|
||||
new label((StringSupplier)()->"[purple]entities: " + Entities.amount()).left();
|
||||
new label((StringSupplier)()->"[purple]enemies: " + Entities.getGroup(Enemy.class).amount()).left();
|
||||
row();
|
||||
new label((StringSupplier)()->"[orange]noclip: " + Vars.noclip).left();
|
||||
row();
|
||||
|
@ -62,6 +62,14 @@ public class MenuFragment implements Fragment{
|
||||
|
||||
visible(()->GameState.is(State.menu));
|
||||
}}.end();
|
||||
}
|
||||
}
|
||||
|
||||
//settings icon
|
||||
new table(){{
|
||||
atop().aright();
|
||||
new imagebutton("icon-info", Unit.dp.inPixels(30f), ()->{
|
||||
ui.showAbout();
|
||||
}).get().pad(Unit.dp.inPixels(14));
|
||||
}}.end().visible(()->GameState.is(State.menu));
|
||||
}
|
||||
}
|
||||
|
@ -139,9 +139,10 @@ public class Turret extends Block{
|
||||
if(hasAmmo(tile) || (Vars.debug && Vars.infiniteAmmo)){
|
||||
|
||||
if(Timers.get(entity, "target", targetInterval)){
|
||||
entity.target = (Enemy)Entities.getClosest(tile.worldx(), tile.worldy(), range, e->{
|
||||
return e instanceof Enemy && !((Enemy)e).isDead();
|
||||
});
|
||||
entity.target = (Enemy)Entities.getClosest(Entities.getGroup(Enemy.class),
|
||||
tile.worldx(), tile.worldy(), range, e->
|
||||
e instanceof Enemy && !((Enemy)e).isDead()
|
||||
);
|
||||
}
|
||||
|
||||
if(entity.target != null){
|
||||
|
Binary file not shown.
Binary file not shown.
@ -17,7 +17,7 @@ public class DesktopLauncher {
|
||||
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
|
||||
config.setTitle("Mindustry");
|
||||
config.setMaximized(true);
|
||||
config.useVsync(false);
|
||||
//config.useVsync(false);
|
||||
config.setWindowedMode(800, 600);
|
||||
config.setWindowIcon("sprites/icon.png");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user