Well, here's the most elegant alternative I can offer, and it's in fact what I'm using in my games:
Supposing you have a mother-class Entity from which all your classes derive, you could have a static list of Entities called Collidable (preferrably a hash map, so that through a key you can delete the Entity from it when, say, the object dies in your game). In every class that you want to be able to interact through collision, be it a Player, Car or MonsterTree class, in its constructor you can add the instance to this list. As in, Collidables.Add(this)
.
And in the Entity-based class, you override its Update() method in the following way:
override void Update() {
// Do stuff
foreach (Entity collidable in Collidables) {
if collidable.CollidesWith(this) {
// Handle the collision
}
}
}
It still uses lists, and I'd recommend using an interface for the collision-checking method. Nevertheless, I find it to be a much more flexible way of handling collisions than straight away checking it in your Main Game Loop - by leaving it to the objects themselves to deal with it -, as it easens tinkering with the Main Loop's architeture and prevents the unnecessary checking by Collidables that don't actively trigger collisions.
edit:
To adjust this design to what you want, you could use the following technique, then:
Let BasicPack
be a basic, abstract data structure akin to void*
of C and C++, if you're familiar with it, for it will have almost the same use of void* in these languages.
From BasicPack
, you can create various kinds of different Packs, each of which will store specific data. Now, instead of Update()
, your update method will be Update (BasicPack args)
. I'm going into details a little later.
Supposing you have a CollidablePack
derived from BasicPack
, which has a List of Collidable Entities, you can easily call the Update of each of your Entities in the group you separated as:
CollidablePack collisionArg = new CollidablePack(YourListToPass);
// ...
selectedEntity.Update(collisionArg);
And now, I your update method would look like this:
void Update (MyPack args) {
// ...
// Unwrap,
CollisionPack collidablesPack = args as CollisionPack;
List<Entity> myCollidables = collidablesPack.Content;
// and use as you like!
foreach (Entity collidable in myCollidables) {
// ...
}
}
Now your instances are pretty much independent from global lists, and we just made things even more flexible.