mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-05 15:58:14 +07:00
cleanup
This commit is contained in:
@ -131,6 +131,10 @@ public class EntityGroup<T extends Entityc> implements Iterable<T>{
|
||||
return array.size == 0;
|
||||
}
|
||||
|
||||
public T index(int i){
|
||||
return array.get(i);
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return array.size;
|
||||
}
|
||||
|
@ -1,349 +0,0 @@
|
||||
package mindustry.entities;
|
||||
|
||||
import arc.struct.*;
|
||||
import arc.util.pooling.*;
|
||||
import arc.util.pooling.Pool.*;
|
||||
|
||||
/**
|
||||
* Quad tree for optimized queries in 2d space
|
||||
* @author Piotr-J
|
||||
*/
|
||||
public class QuadTree2 implements Poolable{
|
||||
/**
|
||||
* Max count of containers in a tree before it is split
|
||||
* <p>
|
||||
* Should be tweaked for best performance
|
||||
*/
|
||||
public static int MAX_IN_BUCKET = 16;
|
||||
/**
|
||||
* Max count of splits, tree start at depth = 0
|
||||
* <p>
|
||||
* Should be tweaked for best performance
|
||||
*/
|
||||
public static int MAX_DEPTH = 8;
|
||||
|
||||
private static Pool<QuadTree2> qtPool = Pools.get(QuadTree2.class, QuadTree2::new);
|
||||
private static Pool<Container> cPool = Pools.get(Container.class, Container::new);
|
||||
private static Array<Container> idToContainer = new Array<>();
|
||||
|
||||
public final static int OUTSIDE = -1;
|
||||
public final static int SW = 0;
|
||||
public final static int SE = 1;
|
||||
public final static int NW = 2;
|
||||
public final static int NE = 3;
|
||||
protected int depth;
|
||||
protected Array<Container> containers;
|
||||
protected Container bounds;
|
||||
protected QuadTree2[] nodes;
|
||||
protected QuadTree2 parent;
|
||||
|
||||
/**
|
||||
* Public constructor for {@link Pool} use only
|
||||
*/
|
||||
public QuadTree2(){
|
||||
this(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor for initial {@link QuadTree2}
|
||||
* <p>
|
||||
* Specify max tree bounds
|
||||
*/
|
||||
public QuadTree2(float x, float y, float width, float height){
|
||||
bounds = new Container();
|
||||
containers = new Array<>(MAX_IN_BUCKET);
|
||||
nodes = new QuadTree2[4];
|
||||
init(0, x, y, width, height, null);
|
||||
}
|
||||
|
||||
protected QuadTree2 init(int depth, float x, float y, float width, float height, QuadTree2 parent){
|
||||
this.depth = depth;
|
||||
bounds.set(x, y, width, height);
|
||||
this.parent = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
private int indexOf(float x, float y, float width, float height){
|
||||
float midX = bounds.x + bounds.width / 2;
|
||||
float midY = bounds.y + bounds.height / 2;
|
||||
boolean top = y > midY;
|
||||
boolean bottom = y < midY && y + height < midY;
|
||||
if(x < midX && x + width < midX){
|
||||
if(top){
|
||||
return NW;
|
||||
}else if(bottom){
|
||||
return SW;
|
||||
}
|
||||
}else if(x > midX){
|
||||
if(top){
|
||||
return NE;
|
||||
}else if(bottom){
|
||||
return SE;
|
||||
}
|
||||
}
|
||||
return OUTSIDE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts given entity id to tree with given bounds
|
||||
*/
|
||||
public void insert(int eid, float x, float y, float width, float height){
|
||||
insert(cPool.obtain().set(eid, x, y, width, height));
|
||||
}
|
||||
|
||||
protected void insert(Container c){
|
||||
if(nodes[0] != null){
|
||||
int index = indexOf(c.x, c.y, c.width, c.height);
|
||||
if(index != OUTSIDE){
|
||||
nodes[index].insert(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
c.parent = this;
|
||||
idToContainer.set(c.eid, c);
|
||||
containers.add(c);
|
||||
|
||||
if(containers.size > MAX_IN_BUCKET && depth < MAX_DEPTH){
|
||||
if(nodes[0] == null){
|
||||
float halfWidth = bounds.width / 2;
|
||||
float halfHeight = bounds.height / 2;
|
||||
nodes[SW] = qtPool.obtain().init(depth + 1, bounds.x, bounds.y, halfWidth, halfHeight, this);
|
||||
nodes[SE] = qtPool.obtain().init(depth + 1, bounds.x + halfWidth, bounds.y, halfWidth, halfHeight, this);
|
||||
nodes[NW] = qtPool.obtain().init(depth + 1, bounds.x, bounds.y + halfHeight, halfWidth, halfHeight, this);
|
||||
nodes[NE] = qtPool.obtain().init(depth + 1, bounds.x + halfWidth, bounds.y + halfHeight, halfWidth, halfHeight, this);
|
||||
}
|
||||
|
||||
for(int i = containers.size - 1; i >= 0; i--){
|
||||
Container next = containers.get(i);
|
||||
int index = indexOf(next.x, next.y, next.width, next.height);
|
||||
if(index != OUTSIDE){
|
||||
nodes[index].insert(next);
|
||||
containers.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entity ids of entities that are inside {@link QuadTree2}s that contain given point
|
||||
* <p>
|
||||
* Returned entities must be filtered further as these results are not exact
|
||||
*/
|
||||
public IntArray get(IntArray fill, float x, float y){
|
||||
if(bounds.contains(x, y)){
|
||||
if(nodes[0] != null){
|
||||
int index = indexOf(x, y, 0, 0);
|
||||
if(index != OUTSIDE){
|
||||
nodes[index].get(fill, x, y, 0, 0);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < containers.size; i++){
|
||||
fill.add(containers.get(i).eid);
|
||||
}
|
||||
}
|
||||
return fill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entity ids of entities that bounds contain given point
|
||||
*/
|
||||
public IntArray getExact(IntArray fill, float x, float y){
|
||||
if(bounds.contains(x, y)){
|
||||
if(nodes[0] != null){
|
||||
int index = indexOf(x, y, 0, 0);
|
||||
if(index != OUTSIDE){
|
||||
nodes[index].getExact(fill, x, y, 0, 0);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < containers.size; i++){
|
||||
Container c = containers.get(i);
|
||||
if(c.contains(x, y)){
|
||||
fill.add(c.eid);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entity ids of entities that are inside {@link QuadTree2}s that overlap given bounds
|
||||
* <p>
|
||||
* Returned entities must be filtered further as these results are not exact
|
||||
*/
|
||||
public IntArray get(IntArray fill, float x, float y, float width, float height){
|
||||
if(bounds.overlaps(x, y, width, height)){
|
||||
if(nodes[0] != null){
|
||||
int index = indexOf(x, y, width, height);
|
||||
if(index != OUTSIDE){
|
||||
nodes[index].get(fill, x, y, width, height);
|
||||
}else{
|
||||
// if test bounds don't fully fit inside a node, we need to check them all
|
||||
for(QuadTree2 node : nodes){
|
||||
node.get(fill, x, y, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < containers.size; i++){
|
||||
Container c = containers.get(i);
|
||||
fill.add(c.eid);
|
||||
}
|
||||
}
|
||||
return fill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns entity ids of entities that overlap given bounds
|
||||
*/
|
||||
public IntArray getExact(IntArray fill, float x, float y, float width, float height){
|
||||
if(bounds.overlaps(x, y, width, height)){
|
||||
if(nodes[0] != null){
|
||||
int index = indexOf(x, y, width, height);
|
||||
if(index != OUTSIDE){
|
||||
nodes[index].getExact(fill, x, y, width, height);
|
||||
}else{
|
||||
// if test bounds don't fully fit inside a node, we need to check them all
|
||||
for(QuadTree2 node : nodes){
|
||||
node.getExact(fill, x, y, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < containers.size; i++){
|
||||
Container c = containers.get(i);
|
||||
if(c.overlaps(x, y, width, height)){
|
||||
fill.add(c.eid);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fill;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update position for this id with new one
|
||||
*/
|
||||
public void update(int id, float x, float y, float width, float height){
|
||||
Container c = idToContainer.get(id);
|
||||
c.set(id, x, y, width, height);
|
||||
|
||||
QuadTree2 qTree = c.parent;
|
||||
qTree.containers.remove(c);
|
||||
while(qTree.parent != null && !qTree.bounds.contains(c)){
|
||||
qTree = qTree.parent;
|
||||
}
|
||||
qTree.insert(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this id from the tree
|
||||
*/
|
||||
public void remove(int id){
|
||||
Container c = idToContainer.get(id);
|
||||
if(c == null)
|
||||
return;
|
||||
if(c.parent != null){
|
||||
c.parent.containers.remove(c);
|
||||
}
|
||||
cPool.free(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the QuadTree by removing all nodes and stored ids
|
||||
*/
|
||||
@Override
|
||||
public void reset(){
|
||||
for(int i = containers.size - 1; i >= 0; i--){
|
||||
cPool.free(containers.remove(i));
|
||||
}
|
||||
for(int i = 0; i < nodes.length; i++){
|
||||
if(nodes[i] != null){
|
||||
qtPool.free(nodes[i]);
|
||||
nodes[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose of the QuadTree by removing all nodes and stored ids
|
||||
*/
|
||||
public void dispose(){
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link QuadTree2[]} with nodes of these tree, nodes may be null
|
||||
*/
|
||||
public QuadTree2[] getNodes(){
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Container} that represents bounds of this tree
|
||||
*/
|
||||
public Container getBounds(){
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "QuadTree{" +
|
||||
"depth=" + depth + "}";
|
||||
}
|
||||
|
||||
/** Simple container for entity ids and their bounds*/
|
||||
static class Container implements Poolable{
|
||||
private int eid;
|
||||
private float x;
|
||||
private float y;
|
||||
private float width;
|
||||
private float height;
|
||||
private QuadTree2 parent;
|
||||
|
||||
public Container(){
|
||||
}
|
||||
|
||||
public Container set(int eid, float x, float y, float width, float height){
|
||||
this.eid = eid;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Container set(float x, float y, float width, float height){
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean contains(float x, float y){
|
||||
return this.x <= x && this.x + this.width >= x && this.y <= y && this.y + this.height >= y;
|
||||
}
|
||||
|
||||
public boolean overlaps(float x, float y, float width, float height){
|
||||
return this.x < x + width && this.x + this.width > x && this.y < y + height && this.y + this.height > y;
|
||||
}
|
||||
|
||||
public boolean contains(float ox, float oy, float owidth, float oheight){
|
||||
float xmax = ox + owidth;
|
||||
float ymax = oy + oheight;
|
||||
|
||||
return ((ox > x && ox < x + width) && (xmax > x && xmax < x + width)) && ((oy > y && oy < y + height) && (ymax > y && ymax < y + height));
|
||||
}
|
||||
|
||||
public boolean contains(Container c){
|
||||
return contains(c.x, c.y, c.width, c.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
eid = -1;
|
||||
x = 0;
|
||||
y = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -159,7 +159,7 @@ public class DesktopInput extends InputHandler{
|
||||
if(unit != null){
|
||||
unit.hitbox(Tmp.r1);
|
||||
if(Tmp.r1.contains(Core.input.mouseWorld())){
|
||||
player.unit(unit);
|
||||
//player.unit(unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||
archash=68b2451bd0f8c6252ccf2c065a1c4b4896605183
|
||||
archash=292d60e7d6c2013334b0f4f30659e1d885f73cfe
|
||||
|
Reference in New Issue
Block a user