Advertisement

How to initialize a reference variable in a Quadtree?

Started by July 28, 2015 09:33 AM
4 comments, last by SteveHatcher 9 years, 5 months ago

Hello,

Before we begin, this is purley a learning exercise, and my game does not require this at all.

I am using an entity component system ECS framework, entityX, in my game. My spaceships can shoot bullets at enemy spaceships, and I want to use a quadtree to reduce collision checks.

In entityX, anytime you want to obtain an entity with a certain component, you use


ComponentHandle<Body> body; 
for (Entity entity : m_entityManager.entities_with_components(body)) 
{ body->position .... }

the EntityManager m_entityManager is responsible for finding and returing the correct entity ID's.

I am using a Quadtree which works with SFML, and trying to adapt it to work with entities. I have created a QuadTreeCollisionSystem, which has a private member of a Quadtree m_quadtree; I fill the quadtree with my entities using


ex::ComponentHandle<Renderable> renderable;
for (ex::Entity entity : entities.entities_with_components(renderable))
{
    m_quadtree.insertObject(entity);
}

And this works, but I have run into a problem at the stage where the entity positions are checked to see which quad they intersect with. In the original system, the function reads:


bool Quadtree::intersects(Boundable* object)
{
    return mAABB.intersects(object->getBoundingRect());
}

where mAABB is a sf::FloatRect;

In the ECS approach, I do not have direct access to all of the objects like this. I must use


for (ex::Entity ent : m_entityManager.entities_with_components(renderable))

This is where I am stuck. My quadtree has no member "m_entityManager". I would like to initilize an "ex::EntityManager &m_entityManager" once with the consutrctor, but the quadtree creates a lot of instances of itself, and it does not feel right adding that in to everywhere I see a "new Quadtree.. e.g.


m_children.push_back(new Quadtree(sf::FloatRect(x, y, width, height), this));

A few questions:

1. Am I going the right way about interfaction a quadtree with ECS entities?

2. How do I go about priming a reference variable once when I create the Quadtree in QuadTreeCollisionSystem, but not every other time a Quadtree is called (within its own member functions)? Is this something to do with static member variables? If so, how should this be done? I have tried a few things but to no avail.

Thanks for all your help.

If you really don't want to keep a member reference variable to the entity manager, you could pass it as a function parameter to the functions that actually need it.

Another way is to make the entity manager a global variable.

Personally I think the member reference variable approach is fine, it's pretty simple. Passing the manager as a function parameter is more flexible, but you probably don't need it unless you are considering the possibility of using the same tree node on different entity managers . On the other side, you have the global entity manager approach. That's a fine approach if you will only ever use one manager.

Advertisement

If you really don't want to keep a member reference variable to the entity manager, you could pass it as a function parameter to the functions that actually need it.

Another way is to make the entity manager a global variable.

Personally I think the member reference variable approach is fine, it's pretty simple. Passing the manager as a function parameter is more flexible, but you probably don't need it unless you are considering the possibility of using the same tree node on different entity managers . On the other side, you have the global entity manager approach. That's a fine approach if you will only ever use one manager.

Hi ultramailman, thanks for your reply.

A few questions

1. What purpose would multiple entity managers serve? I thought the idea of ECS was to sort entities by component type (enemy, gun), (player, gun).

2. My understanding is I only need one entityManager which is initilized at the very start of my program. Thats why I dont want to pass in an entity manager to every other function inside the quadtree that needs to operate on the entities. I would like to just initialize it once in the quadtree as a private memver. I also don't want to make a global one (although I am sure this would solve this particular problem, id like to know the more correct way).

3. Is a static member varible the answer in this case? I guess what I am asking is "How to initalize a reference member object in a class the first time it is created, but not every other time it is created from within its own member functions" (since a quadtree creates itself)...

Thanks

First, about your questions:
1. I don't really see where ultramailman suggested multiple entity managers.

2. If you know you need only one, you could as well make it global. My experience however says you don't know until the project is actually done, so my advice would be to avoid that path. Either you pass it along with every call that needs it or your quadtree needs to store the shared state and pass it down to every sub-quadtree it creates as well.

3. A static data member is a global with a slightly different name.

I feel you have modeled that in a slightly weird way. In my mind there should only be one Quadtree per actual quadtree. A Quadtree has a root Node. A Node has up to four child Node instances. Either the Node instances should know which Quadtree they belong to (allowing them access to any shared state), or perhaps better the Node instances are pure data and the visitor function always knows in which quadtree it is, again allowing access to shared state.

Hey SteveHatcher,

I have no idea what multiple managers can achieve, and I wasn't suggesting you to have multiple managers. I was just remarking that *if* for some reason you need multiple managers, passing the manager as a parameter would be the way to go as passing parameter provides the most flexibility out of all the other options. This goes for other similar situations as well.

Like BitMaster said, a static variable in a class is just like a global variable outside a class. It may be what you need if you are very sure you will only need one manager.

I don't have much to say about your quadtree, since I don't know much about using quadtrees and ECS together. I remember L.Spiro has an article on efficient quad trees though. Here it is: http://lspiroengine.com/?p=530

Hey SteveHatcher,

I have no idea what multiple managers can achieve, and I wasn't suggesting you to have multiple managers. I was just remarking that *if* for some reason you need multiple managers, passing the manager as a parameter would be the way to go as passing parameter provides the most flexibility out of all the other options. This goes for other similar situations as well.

Like BitMaster said, a static variable in a class is just like a global variable outside a class. It may be what you need if you are very sure you will only need one manager.

I don't have much to say about your quadtree, since I don't know much about using quadtrees and ECS together. I remember L.Spiro has an article on efficient quad trees though. Here it is: http://lspiroengine.com/?p=530

Hi ultramailman,

Thanks, I did not mean to be too picky about that, It was more just out of curiosity as to what multiple manager might be used for...

I do agree I think I have approached this problem the wrong way since I am facing this issue. I am going to have a look at a few more quadtree designs such as LSpiros, looks quite beastly.

Thanks

This topic is closed to new replies.

Advertisement