2
\$\begingroup\$

I have the following problem:

I have a a class called Stage, that keeps an list of entities, which it iterates over every update loop, and updates them. One of these entities might be a weapon (PEW PEW!) that when updating spawns new entities (projectiles, KA-ZOOM, KER BANG!). How do I add these new entities to the list in of entities in Stage? Currently, I have Stage as an singleton with global access, so that the entities which in turn spawns entities just calls the instance of Stage's addEntity method, but that feels silly.

Stage -> Entity (weapon) -> Stage again?

I have a similar problem when creating enemies:

Stage -> Entity (enemy wave) -> Stage again

I've been thinking about passing the List into all entities that can create other entities, but then I'd have to change the update method for the base Entity class so that it takes this list, a list which most entities have no need of. Also, when adding an entity to Stage, Stage must be made aware of a number of graphics components for that entity, in order for Stage to be able to tell the renderer (which has an OpenGL context) to load the appropriate resources for those graphic components.

Any ideas what I should do? Am I doing it the wrong way now?

Also, while we're at it, why is Singletons so frowned upon?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ can you show us some code ? \$\endgroup\$
    – concept3d
    Commented Feb 27, 2014 at 11:44
  • \$\begingroup\$ Does stage do any game logic itself or is it just asking each entity to update itself? \$\endgroup\$ Commented Feb 27, 2014 at 12:54
  • \$\begingroup\$ Stage updates entities, and is also responsible for collision detection between entities that can collide. \$\endgroup\$
    – Herp
    Commented Feb 28, 2014 at 9:26

2 Answers 2

1
\$\begingroup\$

Add event handling.

There's a ton of different ways you can implement event handling, but the main idea is that different components of your game interact via events, eliminating most cross/circular dependencies. Just as an example, you might have an eventHandler class (can be singleton, if you so wish), which receives and forwards events. All classes would have access to the eventHandler, and would communicate through it.

As for the singleton pattern (or anti-pattern), it's been answered before.

\$\endgroup\$
0
\$\begingroup\$

It looks like your entities should be able to trigger the creation any other type entity.

Option 1: (the case you explained)

public class WolfSpawner extends Entity
{
    public void Update()
    {
        Wolf wolf = new Wolf();
        Stage.Instance.AddEntity(wolf);
    }
}

Option 2: (in this case the Spawner is not aware about the Stage)

public class Spawner extends Entity
{
    protected Vector<ISpawnListener> spawnListeners;

    public void AddSpawnListener(ISpawnListener spawnListener)
    {
        if (spawnListeners == null)
            spawnListeners = new Vector();

        spawnListeners.Add(spawnListener);
    }

    public void RemoveSpawnListener(ISpawnListener spawnListener)
    {
        // ...
    }

    public void Spawn(Entity entity)
    {
        if (spawnListeners != null && !spawnListeners.isEmpty())
        {
            foreach(var spawnListener in spawnListeners)
            {
                spawnListener.Spawned(entity)
            }
        }
    }
}

public class WolfSpawner extends Spawner
{
    public void Update()
    {
        Wolf wolf = new Wolf();
        Spawn(wolf);
    }

}

// Listener interface
public interface ISpawnListener {
    void Spawned(Entity entity);
}

public class Stage implements ISpawnListener
{
    private Vector<Entity> entities;

    public void Spawned(Entity entity)
    {
        AddEntity(entity)
    }

    public void AddEntity(Entity entity)
    {
        entities.Add(entity);

        if(entity instanceof Spawner)
        {
            var spawner = (Spawner)entity;
            spawner.AddSpawnListener(this);
        }
    }

    public void RemoveEntity(Entity entity)
    {
        entities.Remove(entity);

        if(entity instanceof Spawner)
        {
            var spawner = (Spawner)entity;
            spawner.RemoveSpawnListener(this);
        }
    }
}

There are a other options available to tackle this problem.

Singleton is not a bad pattern, the implementation of it is or how you get that single instance is. There are scenarios when you only need a single instance of an object in your application.

\$\endgroup\$
2
  • \$\begingroup\$ I would upvote where it not for the fact that I just created a lol email address some months ago to answer a dudes question, and then stuck to it like an idiot. Maybe I'll create the email account later so I can upvote \$\endgroup\$
    – Herp
    Commented Feb 28, 2014 at 9:36
  • \$\begingroup\$ @Herp get to it! :) \$\endgroup\$ Commented Feb 28, 2014 at 14:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .