From b2cd95899c93763b6e38d0dbc80febea4225eaad Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 23 Nov 2017 20:58:32 -0500 Subject: [PATCH] Broken attempt at per-enemy pathfinding; balancing --- .../io/anuke/mindustry/AndroidLauncher.java | 4 - .../sprites/blocks/liquidrouter.png | Bin 261 -> 279 bytes core/src/io/anuke/mindustry/ai/Pathfind.java | 80 +++++++++++------- .../anuke/mindustry/ai/SmoothGraphPath.java | 7 +- .../anuke/mindustry/entities/BulletType.java | 8 +- .../mindustry/entities/enemies/Enemy.java | 10 ++- core/src/io/anuke/mindustry/world/World.java | 6 +- .../mindustry/world/blocks/DefenseBlocks.java | 4 +- .../blocks/types/production/Generator.java | 16 ++-- .../production/LiquidPowerGenerator.java | 2 +- .../types/production/NuclearReactor.java | 10 +++ desktop/mindustry-saves/0.mins | Bin 1700 -> 2156 bytes 12 files changed, 93 insertions(+), 54 deletions(-) create mode 100644 core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 2f07c3e724..1a9b86b774 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -6,7 +6,6 @@ import java.util.Date; import com.badlogic.gdx.backends.android.AndroidApplication; import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration; -import com.badlogic.gdx.utils.Array; import android.annotation.SuppressLint; import android.os.Bundle; @@ -35,9 +34,6 @@ public class AndroidLauncher extends AndroidApplication { } }; - //TODO - Mindustry.args = Array.with("-debug"); - initialize(new Mindustry(), config); } } diff --git a/core/assets-raw/sprites/blocks/liquidrouter.png b/core/assets-raw/sprites/blocks/liquidrouter.png index f131090f7226074bdc86626666903cf4a67f9a3b..2b542a739f0d4ea973b2eef7a0736ecbe76c7541 100644 GIT binary patch delta 172 zcmV;d08{^k0+#}iBo78+OGiWi{{a60|De66laV1G2@4kj8Z)P>a}$wCIDg3Bz!LHt z-hs7H_F@M{K%zrJ)N~|81p2A+D(lX&?;bJ6x0wNuQUV}^06@+ex6Pb0n?0Ku*A`S2 zRsC5qGoB*ynsc(&qSi|99q&E0R!S*2{&0m5&QB3JhKOKh-wQkF7=tket+k`Md*aQ# a*#}p;Iku_qEI0rF002ovP6b4+LSTZaKuQ$= delta 181 zcmV;m080Ot0)+yQBqa%ONLh0L01FcU01FcV0GgZ_00007bV*G`2jK}80xCAj`-N(e zTR4CCDe2sJ4)5T#Q1)U6M)(pP4IL64Nf8nKC`Dd%y0cE_TT1C^W&q@z0dRK!N-2aL zmQvVkZD!oJp{l6r*O8fVh{$8k$y$ps24f6jjMQ2=&y&C(g1aLkKY@tg?(c>@wD(T$ joz~jN3)jV)>t`>g<~O passpathfinder; - static Array paths = new Array<>(); - static Tile[][] pathSequences; + static PassTileGraph graph = new PassTileGraph(); + static PathFinder finder = new IndexedAStarPathFinder(graph); static PathSmoother smoother = new PathSmoother(new Raycaster()); static Vector2 vector = new Vector2(); static public Vector2 find(Enemy enemy){ - if(enemy.node == -1){ - findNode(enemy); - } + findNode(enemy); + + if(enemy.node <= -1) return vector.set(enemy.x, enemy.y); //-1 is only possible here if both pathfindings failed, which should NOT happen //check graph code - Tile[] path = enemy.path; + //Tile[] path = enemy.path; + Array path = enemy.gpath.nodes; - Tile target = path[enemy.node]; + Tile target = path.get(enemy.node); float dst = Vector2.dst(enemy.x, enemy.y, target.worldx(), target.worldy()); if(dst < 2){ - if(enemy.node <= path.length-2) + if(enemy.node <= path.size-2) enemy.node ++; - target = path[enemy.node]; + target = path.get(enemy.node); } //near the core, stop - if(enemy.node == path.length - 1){ + if(enemy.node == path.size - 1){ vector.set(target.worldx(), target.worldy()); } @@ -51,13 +49,9 @@ public class Pathfind{ } - static public void reset(){ - paths.clear(); - pathSequences = null; - passpathfinder = new IndexedAStarPathFinder(passgraph); - } - static public void updatePath(){ + + /* if(paths.size == 0 || paths.size != World.spawnpoints.size){ paths.clear(); pathSequences = new Tile[World.spawnpoints.size][0]; @@ -67,13 +61,6 @@ public class Pathfind{ } } - //TODO make this work? - /* - PathFinderRequest request = new PathFinderRequest(); - request.startNode = World.spawnpoints.get(0); - request.endNode = World.core; - passpathfinder.search(request, 1000); */ - for(int i = 0; i < paths.size; i ++){ SmoothGraphPath path = paths.get(i); @@ -98,18 +85,47 @@ public class Pathfind{ Effects.effect(Fx.ind, tile.worldx(), tile.worldy()); } - } + }*/ } static void findNode(Enemy enemy){ + /* enemy.path = pathSequences[enemy.spawn]; Tile[] path = enemy.path; + */ + + + + if(enemy.node == -1 || (Timers.get(enemy, "pathfind", 120) && enemy.request.pathFound)){ + + enemy.gpath = new SmoothGraphPath(); + enemy.finder = new IndexedAStarPathFinder(graph); + enemy.gpath.clear(); + + enemy.request = new PathFinderRequest(World.tileWorld(enemy.x, enemy.y), + World.core, + heuristic, enemy.gpath); + enemy.request.statusChanged = true; + + enemy.node = -2; + } + + if(enemy.gpath != null && !enemy.request.pathFound){ + enemy.request.executionFrames ++; + if(enemy.finder.search(enemy.request, 1000000 / 5)){ + smoother.smoothPath(enemy.gpath); + enemy.node = 1; + //UCore.log("done in " + enemy.request.executionFrames + " frames with path of size " + enemy.gpath.getCount()); + } + } + + /* Tile closest = null; float ldst = 0f; int cindex = -1; - for(int i = 0; i < path.length; i ++){ - Tile tile = path[i]; + for(int i = 0; i < path.size; i ++){ + Tile tile = path.get(i); float dst = Vector2.dst(tile.worldx(), tile.worldy(), enemy.x, enemy.y); if(closest == null || dst < ldst){ @@ -118,6 +134,6 @@ public class Pathfind{ cindex = i; } } - enemy.node = cindex; + enemy.node = cindex;*/ } } diff --git a/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java b/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java index 5d3bbc56c2..2196fb97b7 100644 --- a/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java +++ b/core/src/io/anuke/mindustry/ai/SmoothGraphPath.java @@ -12,7 +12,7 @@ public class SmoothGraphPath extends DefaultGraphPath implements Smoothabl @Override public Vector2 getNodePosition(int index){ Tile tile = nodes.get(index); - return Tmp.v1.set(tile.worldx(), tile.worldy()); + return Tmp.v3.set(tile.worldx(), tile.worldy()); } @Override @@ -24,5 +24,10 @@ public class SmoothGraphPath extends DefaultGraphPath implements Smoothabl public void truncatePath(int newLength){ nodes.truncate(newLength); } + + @Override + public void add (Tile node) { + nodes.add(node); + } } diff --git a/core/src/io/anuke/mindustry/entities/BulletType.java b/core/src/io/anuke/mindustry/entities/BulletType.java index 7f7a0cb445..0db38cca5a 100644 --- a/core/src/io/anuke/mindustry/entities/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/BulletType.java @@ -47,7 +47,7 @@ public abstract class BulletType extends BaseBulletType{ Draw.reset(); } }, - sniper = new BulletType(3f, 23){ + sniper = new BulletType(3f, 25){ public void draw(Bullet b){ Draw.color(Color.LIGHT_GRAY); Draw.thick(1f); @@ -223,7 +223,7 @@ public abstract class BulletType extends BaseBulletType{ Draw.reset(); } }, - flame = new BulletType(0.6f, 4){ + flame = new BulletType(0.6f, 5){ public void draw(Bullet b){ Draw.color(Color.YELLOW, Color.SCARLET, b.time/lifetime); float size = 6f-b.time/lifetime*5f; @@ -250,7 +250,7 @@ public abstract class BulletType extends BaseBulletType{ Draw.reset(); } }, - shot = new BulletType(2.4f, 2){ + shot = new BulletType(2.4f, 4){ {lifetime = 40;} public void draw(Bullet b){ Draw.color(lightGold); @@ -258,7 +258,7 @@ public abstract class BulletType extends BaseBulletType{ Draw.reset(); } }, - multishot = new BulletType(2.5f, 2){ + multishot = new BulletType(2.5f, 3){ {lifetime=40;} public void draw(Bullet b){ Draw.color(Color.SKY); diff --git a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java index 88bb73ffc8..45a9011c18 100644 --- a/core/src/io/anuke/mindustry/entities/enemies/Enemy.java +++ b/core/src/io/anuke/mindustry/entities/enemies/Enemy.java @@ -1,5 +1,7 @@ package io.anuke.mindustry.entities.enemies; +import com.badlogic.gdx.ai.pfa.PathFinder; +import com.badlogic.gdx.ai.pfa.PathFinderRequest; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; @@ -7,6 +9,7 @@ import com.badlogic.gdx.utils.reflect.ClassReflection; import io.anuke.mindustry.Vars; import io.anuke.mindustry.ai.Pathfind; +import io.anuke.mindustry.ai.SmoothGraphPath; import io.anuke.mindustry.entities.Bullet; import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.Player; @@ -34,9 +37,11 @@ public class Enemy extends DestructibleEntity{ protected String shootsound = "enemyshoot"; protected int damage; - public Tile[] path; + public PathFinderRequest request = new PathFinderRequest<>();; + public SmoothGraphPath gpath; public int spawn; public int node = -1; + public PathFinder finder; public Vector2 direction = new Vector2(); public float xvelocity, yvelocity; @@ -122,6 +127,7 @@ public class Enemy extends DestructibleEntity{ public void findClosestNode(){ Pathfind.find(this); + /* int index = 0; int cindex = -1; @@ -147,7 +153,7 @@ public class Enemy extends DestructibleEntity{ Timers.run(Mathf.random(15f), ()->{ set(x2 * Vars.tilesize, y2 * Vars.tilesize); }); - } + }*/ } @Override diff --git a/core/src/io/anuke/mindustry/world/World.java b/core/src/io/anuke/mindustry/world/World.java index a5fa41e177..3ae112b316 100644 --- a/core/src/io/anuke/mindustry/world/World.java +++ b/core/src/io/anuke/mindustry/world/World.java @@ -68,6 +68,10 @@ public class World{ return tiles[x][y]; } + public static Tile tileWorld(float x, float y){ + return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize)); + } + public static Tile[] getNearby(int x, int y){ temptiles[0] = tile(x+1, y); temptiles[1] = tile(x, y+1); @@ -146,8 +150,6 @@ public class World{ World.seed = seed; Generator.generate(mapPixmaps[map.ordinal()]); - Pathfind.reset(); - //TODO multiblock core placeBlock(core.x, core.y, ProductionBlocks.core, 0); diff --git a/core/src/io/anuke/mindustry/world/blocks/DefenseBlocks.java b/core/src/io/anuke/mindustry/world/blocks/DefenseBlocks.java index 2803b7eb4e..5258f4322d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/DefenseBlocks.java +++ b/core/src/io/anuke/mindustry/world/blocks/DefenseBlocks.java @@ -71,7 +71,7 @@ public class DefenseBlocks{ { fullDescription = "Repairs nearby damaged blocks in range at a slow rate. " + "Uses small amounts of power."; - formalName = "heal turret"; + formalName = "repair turret"; range = 30; reload = 40f; health = 60; @@ -82,7 +82,7 @@ public class DefenseBlocks{ { fullDescription = "Repairs nearby damaged blocks in range at a decent rate. " + "Uses power."; - formalName = "heal turret II"; + formalName = "repair turret II"; range = 44; reload = 20f; health = 90; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java index 5217160616..7f38024cbf 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java @@ -14,6 +14,7 @@ import io.anuke.mindustry.world.blocks.types.PowerBlock; import io.anuke.ucore.core.Draw; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Timers; +import io.anuke.ucore.graphics.Hue; import io.anuke.ucore.util.Angles; import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; @@ -80,9 +81,13 @@ public class Generator extends PowerBlock{ public void drawOver(Tile tile){ PowerEntity entity = tile.entity(); if(entity.power > powerSpeed){ - for(int i = 0; i < laserDirections; i++){ - drawLaserTo(tile, (tile.rotation + i) - laserDirections/2); - } + Draw.alpha(1f); + }else{ + Draw.alpha(0.75f); + } + + for(int i = 0; i < laserDirections; i++){ + drawLaserTo(tile, (tile.rotation + i) - laserDirections/2); } } @@ -114,10 +119,9 @@ public class Generator extends PowerBlock{ Tile target = laserTarget(tile, rotation); if(target != null){ - Angles.translation(rotation * 90, 6f); + Angles.translation(rotation * 90, width * Vars.tilesize/2 + 2f); - Draw.color(Color.GRAY, Color.WHITE, 0.902f + Mathf.sin(Timers.time(), 1.7f, 0.08f)); - Draw.alpha(1f); + Draw.tint(Hue.mix(Color.GRAY, Color.WHITE, 0.902f + Mathf.sin(Timers.time(), 1.7f, 0.08f))); float r = 0f; diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java index e0a6727d1d..869582b83e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/LiquidPowerGenerator.java @@ -36,7 +36,7 @@ public class LiquidPowerGenerator extends Generator implements LiquidAcceptor{ public void getStats(Array list){ super.getStats(list); list.add("[liquidinfo]Liquid Capacity: " + (int)liquidCapacity); - list.add("[liquidinfo]Generation: " + Strings.toFixed(generatePower / inputLiquid, 3) + "power units/liquid unit"); + list.add("[liquidinfo]Generation: " + Strings.toFixed(generatePower / inputLiquid, 2) + " power/liquid"); list.add("[liquidinfo]Input: " + generateLiquid); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java new file mode 100644 index 0000000000..d7714d9dc9 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/NuclearReactor.java @@ -0,0 +1,10 @@ +package io.anuke.mindustry.world.blocks.types.production; + +public class NuclearReactor extends LiquidItemPowerGenerator{ + + //TODO make it explode when broken + public NuclearReactor(String name) { + super(name); + } + +} diff --git a/desktop/mindustry-saves/0.mins b/desktop/mindustry-saves/0.mins index 487788e77ddc083125d00047e6c7fd5d1aeedf96..33ced92f3581ce27eed67a7d823dd6d34338fe9a 100644 GIT binary patch literal 2156 zcmZvcOK1~O6oyZe`s$+1WG2&0UMBU?Vp@~fRI!>=P2vkhi}*lL7m5qfg$rLBQBXt> z6a-%@6$KGgR1jYk+iF|T7F?+4LUEzuW97=F=bkg?HYOS9@Xi1K=iGDeOalN@0P41V zebPS%06c|}`Qf6y^G4xF|7v{R0h8(>c5HGT-i`poj{7GdMJB38FW&Zh*uW^jvA=k` z29P~Vj{$($_=gwXlg&gHK#Iu(NL&=R!y!`ICCRljq2>#V>yHQ}n6PtWOtb}>{8L5i zjuT-nk`OI(Maa3TX_`>*x=?6_kaI&Q)FzbCn*XL~zILIQCjTwbnr;ilXA32n@LW3B zRcDnV7qw_wa>iYuu%@PaqNSOzHp7Iq)_rk9T|!-&j0dD)&i9ZAYde|n#LY)i5q>Nb z?G_3yggWH7dOim|d225~@M*Q?l;zI2xu!l<1-P!!M-?g6stt1c22SI;HMBqttvOd- zn>T(P#tB#psrKjaFUWOtzHN|y-%tW@I1}d#Pu`VNPwE>D=BxJ*d{(VFWw}%Cz9K!; z1^3m$g#C=?Jf#OM{%ioc7fH@sOfIdiT(kfGXRE?bE~ZNCYc8Q=E1w*xU=CDkmYY)v zS>NJZ&g*J{8odHFdfA*?p?am&!gLMb$GU__z0g4#AyvLztH5Ka42^*1!7l&}m+{04 z2b7G>0)q!#vI~b?N)9Seuf=#FWECqm>4DxA!*HkP6n;@JDm+zOJfTX}3hZ{`lV=m& z?BYq+iR$h?{6O%+6|EBY(mPR8|G}wWpPaLF#wFBz_5zf_XyF_*jHxtL3< zCo_ktHOtNERk4x9xg55p^9$7I6)5Y~qE^St=3K?=!mY-K$X8=6qY=ixzv1!cnHaJv z{N%7y8Y7ha??v0o$;FM&8IjyPtu@jh>c4)Pro>9AFkV;pvsOtLW0c$y9}E6Y9QD>? zpHW>sMt+uk?*yEDOgu+Zbd6}{TA?r#PUU+en#qKk-Afu$R8wS~EL^IfzKChR=@hiI)or8c#T2&c-jruMO0-1KjuENkfI_He~NK60+( literal 1700 zcmZvb*=til7{$M&E>U6{dY5#GNs~4vr8YK=g;*P<=EkZhf`X`^RooC%6v5?11V!;l zs)7oFAc|0Z_es>cy{I6*39g``;){QQXJ&G)G|fB=zd7eyX6D`zkvSrPu}^<5hD2np zH(oyC4ShZ89X?aUdbi9LNt~USf$4NmO-*W=sis+K3aANz7=h(#z92GmNr6}*gO@eg zBDrhSiavE+r`CN#lOwV?&WwD5R5S!Pa+4XEBr^t$h93D&W>_i4rP9=Lw@B&Rbi3|Q zD`cp}7LW=)CGJwo7{Xq1S?0zk=qB!wocpAtPd$Cih%TbrHbAl-&}}t@`-_#RwJc$r zZ3yRe%5;+tN$xUI+z@se)gMMcu}5_0KPL4Xf@_UP0IIH<16WU{uI)NMGoouCvt$T+ z3QuYcWUbKISyfV1Q^T5^uGzIXz(%AujcfZgdl=a|`3F_nIucyRCGax6$qRK(e>f?f6J7>C^BSwcgK+8{R=`-l+-a zSo(!j-bL5hL#@XU_T2Z4Zo$_gdl}dMT@&`4H-yTmAJlsHF|N;Os2BRFHBfjz-EO0y bO4ev_`+w05{U$9uz}&(?pZ<_ShYbA#)E|7y