Implemented dynamic ground unit spawning

This commit is contained in:
Anuken 2018-06-20 20:23:43 -04:00
parent 1c80314cfd
commit 45da578756
7 changed files with 121 additions and 17 deletions

View File

@ -79,8 +79,12 @@ public class Pathfinder {
return paths[Team.red.ordinal()].weights[x][y];
}
public float getValueforTeam(Team team, int x, int y){
return paths == null ? 0 : paths[team.ordinal()].weights[x][y];
}
private boolean passable(Tile tile, Team team){
return (tile.getWallID() == 0 && !(tile.floor().isLiquid && (tile.floor().damageTaken > 0 || tile.floor().drownTime > 0)))
return (tile.getWallID() == 0 && tile.cliffs == 0 && !(tile.floor().isLiquid && (tile.floor().damageTaken > 0 || tile.floor().drownTime > 0)))
|| (tile.breakable() && (tile.getTeam() != team)) || !tile.solid();
}
@ -173,6 +177,8 @@ public class Pathfinder {
createFor(data.team);
}
state.spawner.checkAllQuadrants();
Log.info("Elapsed calculation time: {0}", Timers.elapsed());
}

View File

@ -1,19 +1,25 @@
package io.anuke.mindustry.ai;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Bits;
import com.badlogic.gdx.utils.IntArray;
import io.anuke.mindustry.content.AmmoTypes;
import io.anuke.mindustry.content.UnitTypes;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.entities.units.Squad;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
public class WaveSpawner {
private static final int quadsize = 15;
private static final int quadsize = 4;
private Bits quadrants;
private IntArray tmpArray = new IntArray();
private Array<FlyerSpawn> flySpawns = new Array<>();
private Array<GroundSpawn> groundSpawns = new Array<>();
@ -23,24 +29,45 @@ public class WaveSpawner {
}
public void spawnEnemies(){
int spawned = 10;
int groundGroups = Math.min(1 + state.wave / 20, 4);
int flyGroups = Math.min(1 + state.wave / 20, 4);
int spawned = Math.min(state.wave, 6);
int groundGroups = 1 + state.wave / 20;
int flyGroups = 1 + state.wave / 20;
//add extra groups if necessary
for (int i = 0; i < groundGroups - groundSpawns.size; i++) {
GroundSpawn spawn = new GroundSpawn();
findLocation(spawn);
groundSpawns.add(spawn);
}
for (int i = 0; i < flyGroups - flySpawns.size; i++) {
FlyerSpawn spawn = new FlyerSpawn();
spawn.angle = Mathf.random(360f);
findLocation(spawn);
flySpawns.add(spawn);
}
for(GroundSpawn spawn : groundSpawns){
if(state.wave % 20 == 0){
for(FlyerSpawn spawn : flySpawns) findLocation(spawn);
for(GroundSpawn spawn : groundSpawns) findLocation(spawn);
}
for(GroundSpawn spawn : groundSpawns){
checkQuadrant(spawn.x, spawn.y);
if(!getQuad(spawn.x, spawn.y)){
findLocation(spawn);
}
Squad squad = new Squad();
for(int i = 0; i < spawned; i ++){
BaseUnit unit = UnitTypes.scout.create(Team.red);
unit.inventory.addAmmo(AmmoTypes.bulletIron);
unit.setWave();
unit.setSquad(squad);
unit.set(spawn.x * quadsize * tilesize + quadsize * tilesize/2f + Mathf.range(quadsize*tilesize/3f),
spawn.y * quadsize * tilesize + quadsize * tilesize/2f + Mathf.range(quadsize*tilesize/3));
unit.add();
}
}
for(FlyerSpawn spawn : flySpawns){
@ -62,11 +89,26 @@ public class WaveSpawner {
}
}
public void calculateSpawn(){
public void checkAllQuadrants(){
for(int x = 0; x < quadWidth(); x ++){
for(int y = 0; y < quadHeight(); y ++){
checkQuadrant(x, y);
}
}
}
private void checkQuadrant(int quadx, int quady){
setQuad(quadx, quady, true);
for(int x = 0; x < world.width(); x += quadsize){
for(int y = 0; y < world.height(); y += quadsize){
//TODO quadrant operations, etc
outer:
for (int x = quadx * quadsize; x < world.width() && x < (quadx + 1)*quadsize; x++) {
for (int y = quady * quadsize; y < world.height() && y < (quady + 1)*quadsize; y++) {
Tile tile = world.tile(x, y);
if(tile.solid() || world.pathfinder().getValueforTeam(Team.red, x, y) == Float.MAX_VALUE){
setQuad(quadx, quady, false);
break outer;
}
}
}
}
@ -74,9 +116,53 @@ public class WaveSpawner {
private void reset(){
flySpawns.clear();
groundSpawns.clear();
quadrants = new Bits(quadWidth() * quadHeight());
}
private boolean getQuad(int quadx, int quady){
return quadrants.get(quadx + quady * quadWidth());
}
private void setQuad(int quadx, int quady, boolean valid){
if(valid){
quadrants.set(quadx + quady * quadWidth());
}else{
quadrants.clear(quadx + quady * quadWidth());
}
}
private void findLocation(GroundSpawn spawn){
spawn.x = -1;
spawn.y = -1;
int shellWidth = quadWidth()*2 + quadHeight() * 2 * 6;
shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth);
Mathf.traverseSpiral(quadWidth(), quadHeight(), Mathf.random(shellWidth), (x, y) -> {
if(getQuad(x, y)){
spawn.x = x;
spawn.y = y;
return true;
}
return false;
});
}
private void findLocation(FlyerSpawn spawn){
spawn.angle = Mathf.random(360f);
}
private int quadWidth(){
return Mathf.ceil(world.width() / (float)quadsize);
}
private int quadHeight(){
return Mathf.ceil(world.height() / (float)quadsize);
}
private class FlyerSpawn{
//square angle
float angle;
FlyerSpawn(){
@ -85,6 +171,8 @@ public class WaveSpawner {
}
private class GroundSpawn{
//quadrant spawn coordinates
int x, y;
GroundSpawn(){

View File

@ -24,7 +24,7 @@ public class UnitTypes implements ContentList {
scout = new UnitType("scout", team -> new Scout(scout, team)){{
maxVelocity = 1.1f;
speed = 0.1f;
speed = 0.2f;
drag = 0.4f;
range = 40f;
setAmmo(AmmoTypes.bulletIron);

View File

@ -251,7 +251,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
drownTime = Mathf.clamp(drownTime);
if(drownTime >= 1f){
damage(health + 1, false);
damage(health + 1);
}
float px = x, py = y;

View File

@ -111,6 +111,7 @@ public abstract class GroundUnit extends BaseUnit {
protected void moveToCore(){
Tile tile = world.tileWorld(x, y);
if(tile == null) return;
Tile targetTile = world.pathfinder().getTargetTile(team, tile);
if(tile == targetTile) return;
@ -150,7 +151,7 @@ public abstract class GroundUnit extends BaseUnit {
}
//TODO move toward resupply point
if(inventory.totalAmmo() + 10 >= inventory.ammoCapacity()){
if(isWave || inventory.totalAmmo() + 10 >= inventory.ammoCapacity()){
state.set(attack);
}
}

View File

@ -2,6 +2,7 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import io.anuke.mindustry.content.AmmoTypes;
import io.anuke.mindustry.content.UnitTypes;
import io.anuke.mindustry.content.bullets.TurretBullets;
import io.anuke.mindustry.entities.Player;
@ -79,6 +80,8 @@ public class DebugFragment implements Fragment {
new button("spawng", () ->{
BaseUnit unit = UnitTypes.scout.create(player.getTeam());
unit.set(player.x, player.y);
unit.inventory.addAmmo(AmmoTypes.bulletIron);
unit.setWave();
unit.add();
});
row();

View File

@ -1,5 +1,6 @@
package io.anuke.mindustry.world.mapgen;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.content.blocks.StorageBlocks;
import io.anuke.mindustry.game.Team;
@ -30,11 +31,16 @@ public class ProcGen {
double r = sim2.octaveNoise2D(1, 0.6, 1f/70, x, y);
double elevation = sim.octaveNoise2D(3, 0.5, 1f/70, x, y) * 4 - 1.2;
double edgeDist = Math.max(data.width()/2, data.height()/2) - Math.max(Math.abs(x - data.width()/2), Math.abs(y - data.height()/2));
double dst = Vector2.dst(data.width()/2, data.height()/2, x, y);
double border = 10;
double border = 14;
if(edgeDist < border){
elevation += (border - edgeDist)/4.0;
elevation += (border - edgeDist)/6.0;
}
if(dst < 20){
elevation = 0;
}
if(r > 0.9){