Java 如何将对象插入到四叉树的多个节点中
我正在做一个2D游戏,看看我能做些什么。现在我要做的是物体碰撞,我选择使用四叉树。目前的问题是将一个对象插入多个子节点。因此,我遇到的问题是,当我将一个对象插入到树中时,树应该将该对象放入尽可能低的叶节点中。但由于某种原因,我还没有发现至少有一个对象在每个父节点中保留,而它本不应该保留 所以我的问题是,你们能帮我找出并提供解决上述问题的可能方法吗。如果你们认为这个问题无法解决,请提供另一种解决方法 我的代码:Java 如何将对象插入到四叉树的多个节点中,java,data-structures,2d,game-engine,quadtree,Java,Data Structures,2d,Game Engine,Quadtree,我正在做一个2D游戏,看看我能做些什么。现在我要做的是物体碰撞,我选择使用四叉树。目前的问题是将一个对象插入多个子节点。因此,我遇到的问题是,当我将一个对象插入到树中时,树应该将该对象放入尽可能低的叶节点中。但由于某种原因,我还没有发现至少有一个对象在每个父节点中保留,而它本不应该保留 所以我的问题是,你们能帮我找出并提供解决上述问题的可能方法吗。如果你们认为这个问题无法解决,请提供另一种解决方法 我的代码: package net.evergone.engine; import java.ut
package net.evergone.engine;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.lwjgl.util.vector.Vector2f;
import org.newdawn.slick.Color;
import net.evergone.EverGone;
import net.evergone.game.BasicRectangle;
public class QuadtreeNode
{
private int MAX_OBJECTS = 2;
private int MAX_LEVELS = 6;
private int level = 0;
private boolean children = false;
private static boolean temp = false;
private BasicRectangle boundBox;
private ArrayList<BasicRectangle> objects;
private QuadtreeNode[] nodes;
/**
*
* Default constructor for QuadtreeNode
*/
public QuadtreeNode(int level, BasicRectangle boundBox)
{
this.level = level;
this.boundBox = boundBox;
objects = new ArrayList<BasicRectangle>();
nodes = new QuadtreeNode[4];
}
/**
*
* Splits the parent node into 4 leef nodes
*/
public void split()
{
float parentX = boundBox.getPosition().getX();
float parentY = boundBox.getPosition().getY();
nodes[0] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX+boundBox.getWidth()/2, parentY), boundBox.getWidth()/2, boundBox.getHeight()/2));
nodes[1] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX, parentY), boundBox.getWidth()/2, boundBox.getHeight()/2));
nodes[2] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX, parentY+boundBox.getHeight()/2), boundBox.getWidth()/2, boundBox.getHeight()/2));
nodes[3] = new QuadtreeNode(level+1, new BasicRectangle(new Vector2f(parentX+boundBox.getWidth()/2, parentY+boundBox.getHeight()/2), boundBox.getWidth()/2, boundBox.getHeight()/2));
children = true;
}
public int[] getIndex(BasicRectangle r)//TODO use intersection methods
{
int[] indexs = new int[4];
int e = 0;
float verticalMidpoint = boundBox.getPosition().getX() + (boundBox.getWidth() / 2);
float horizontalMidpoint = boundBox.getPosition().getY() + (boundBox.getHeight() / 2);
//BasicRectangle can completely fit within the top quadrants
boolean topQuadrant = (r.getPosition().getY() <= horizontalMidpoint);
//BasicRectangle can completely fit within the bottom quadrants
boolean bottomQuadrant = (r.getPosition().getY()+r.getHeight() >= horizontalMidpoint);
//BasicRectangle can completely fit within the left quadrants
boolean leftquadrant = (r.getPosition().getX() <= verticalMidpoint);
//BasicRectangle can completely fit within the right quadrants
boolean rightQuadrant = (r.getPosition().getX()+r.getWidth() >= verticalMidpoint);
if(topQuadrant && rightQuadrant)
{
indexs[e] = 0;
e++;
}
if(topQuadrant && leftquadrant)
{
indexs[e] = 1;
e++;
}
if(bottomQuadrant && leftquadrant)
{
indexs[e] = 2;
e++;
}
if(bottomQuadrant && rightQuadrant)
{
indexs[e] = 3;
}
for(int i =1;i<indexs.length;i++)
if(indexs[i] == 0)
indexs[i]=-1;
return indexs;
}
public void insert(BasicRectangle r)//TODO
{
if(children)
{
int[] indexs = getIndex(r);
for(int e : indexs)
if(e != -1)
nodes[e].insert(r);
return;
}
objects.add(r);
if(objects.size()>MAX_OBJECTS && level < MAX_LEVELS)
{
if(!children)
split();
int i = 0;
while(i<objects.size())
{
int[] indexs = getIndex(objects.get(i));
for(int e : indexs)
if(e != -1)
nodes[e].insert(objects.get(i));
objects.remove(i);
i++;
}
}
objects.trimToSize();
}
/**
* Return all objects that could collide with the given object
*/
public void retrieve(List<BasicRectangle> returnObjects, BasicRectangle r)
{
if(children)
{
int[] indexs = getIndex(r);
for(int e : indexs)
if(e != -1)
nodes[e].retrieve(returnObjects, r);
return;
}
for(BasicRectangle e : objects)
if(!returnObjects.contains(e))
returnObjects.addAll(objects);
/*if(!temp)
retrieveHelper(returnObjects);
temp = true;*/
while(returnObjects.contains(r))
returnObjects.remove(r);
}
public void retrieveHelper(List<BasicRectangle> returnObjects)
{
if(children)
for(QuadtreeNode e : nodes)
e.retrieveHelper(returnObjects);
returnObjects.addAll(objects);
}
/**
*
* clears the node
*/
public void clear()
{
objects.clear();
if(children)
for(QuadtreeNode e : nodes)
if(e != null)
{
e.clear();
e = null;
}
children = false;
temp = false;
}
public BasicRectangle getBoundBox()
{
return boundBox;
}
/**
*
* Strictly debug only (draw method with be Quadtree.java)
*/
public void draw()
{
if(children)
for(QuadtreeNode e : nodes)
e.draw();
else
boundBox.drawOutLine();
}
public void debugIndex(BasicRectangle r)
{
int[] indexs = getIndex(r);
System.out.println(Arrays.toString(indexs));
System.out.println("Parent node: "+objects.size());
for(BasicRectangle e : objects)
e.setColor(Color.yellow);
for(int e : indexs)
if(e != -1)
System.out.println("node "+e+": "+nodes[e].objects.size());
}
public QuadtreeNode[] getNodes()
{
return nodes;
}
}
package net.evergone.engine;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Collection;
导入java.util.List;
导入org.lwjgl.util.vector.Vector2f;
导入org.newdawn.slick.Color;
导入net.evergen.evergen;
导入net.evergone.game.BasicRectangle;
公共级四通管
{
私有int MAX_OBJECTS=2;
私有整数最大值=6;
私有整数级=0;
私有布尔子对象=false;
私有静态布尔值temp=false;
私有BasicRectangle边界框;
私有ArrayList对象;
私有四元节点[]节点;
/**
*
*QuadtreeNode的默认构造函数
*/
公共四叉树节点(整数级,基本矩形边界框)
{
这个水平=水平;
this.boundBox=boundBox;
objects=newarraylist();
节点=新的四元节点[4];
}
/**
*
*将父节点拆分为4个leef节点
*/
公开作废拆分()
{
float parentX=boundBox.getPosition().getX();
float parentY=boundBox.getPosition().getY();
节点[0]=新的四边形节点(级别+1,新的基本矩形(新的向量2F(parentX+boundBox.getWidth()/2,parentY),boundBox.getWidth()/2,boundBox.getHeight()/2));
节点[1]=新的四边形节点(级别+1,新的基本矩形(新的向量2F(parentX,parentY),boundBox.getWidth()/2,boundBox.getHeight()/2));
节点[2]=新的四边形节点(级别+1,新的基本矩形(新的向量2F(parentX,parentY+boundBox.getHeight()/2),boundBox.getWidth()/2,boundBox.getHeight()/2));
节点[3]=新的四边形节点(级别+1,新的基本矩形(新的向量2F(parentX+boundBox.getWidth()/2,parentY+boundBox.getHeight()/2),boundBox.getWidth()/2,boundBox.getHeight()/2));
儿童=正确;
}
public int[]getIndex(basicrectangler)//TODO使用交集方法
{
int[]indexs=新的int[4];
int e=0;
float verticalMidpoint=boundBox.getPosition().getX()+(boundBox.getWidth()/2);
浮点水平中点=boundBox.getPosition().getY()+(boundBox.getHeight()/2);
//BasicRectangle可以完全适合顶部象限
布尔上象限=(r.getPosition().getY()=水平中点);
//BasicRectangle可以完全适合左象限
布尔左象限=(r.getPosition().getX()=垂直点);
if(顶部象限和右侧象限)
{
指数[e]=0;
e++;
}
if(顶部象限和左侧象限)
{
指数[e]=1;
e++;
}
if(底部象限和左侧象限)
{
指数[e]=2;
e++;
}
if(底部象限和右侧象限)
{
指数[e]=3;
}
对于(int i=1;iMAX_对象和级别<最大级别)
{
如果(!儿童)
split();
int i=0;
而(i在insert方法中,而不是删除对象(objects.remove(i);)时,将i处的对象设置为null(objects.set(i,null);)。如果需要任何其他信息,请询问。我刚刚发现问题,我必须将i处的对象设置为null,而不是删除它(在insert方法中)。例如:objects.set(i,null);