1

So I want to spawn in a random enemy from a List of enemies, but I can't find a clean way to create a new Enemy instance from the Enemy instance in the list. This is mainly because I have enemies of different object types (subclasses of type Enemy) entirely, so I can't simply copy all the attributes over. For example:

List<Enemy> EnemyDB = new List<Enemy>();
EnemyDB.Add(new Enemy(150,1.8f,"grunt"));
EnemyDB.Add(new EnemyOther(60, 5.8f, "bug"));
Enemy template = EnemyDB.[get random enemy];
Enemy toBeSpawned = ????;

How can I get a new instance of the list's enemy? Is there a better way entirely to do this?

Gregorio246
  • 589
  • 2
  • 7
  • 15

3 Answers3

3

Try creating a "Clone" method on each Enemy subtype and call that method on the one you choose randomly from the List. You could also go "flyweight"; create a shallower copy that simply references the Enemy's more expensive members, like graphical elements (sprites, textures, skeleton), instead of making multiple in-memory copies.

KeithS
  • 70,210
  • 21
  • 112
  • 164
1

Change your definition of enemy to implement the ICloneable interface, or use the Object.MemberwiseClone method.

See also Creating a copy of an object in C# and How do you do a deep copy of an object in .NET (C# specifically)?

Community
  • 1
  • 1
ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • ICloneable is not a great interface conceptually (there's no information inherent in the interface to tell you how deep a copy the implementation makes), but functionally speaking it's pretty much what the OP wants. I didn't specifically recommend ICloneable in my answer, but the OP needs some sort of deep copy method, whether it's an ICloneable implementation or something hand-rolled. – KeithS Nov 14 '12 at 18:13
0

You need to, at least conceptually, make a distinction between classes of enemies (grunts, bugs, ...) and enemy instances. The class defines the initial health/hitpoints of an enemy, while an instance represents an actually spawned enemy with individual stats and a position.

There are two options to model this.

Class/instance model

You create two classes: one for the class of enemy, and one for an instance of enemy. The EnemyClass is a factory for Enemy instances.

class EnemyClass
{
    public string Name { get; }
    public int InitialHealth { get; }

    public Enemy Spawn();
}

class Enemy
{
    public EnemyClass Class { get; }
    public int CurrentHealth { get; }
    public Vector2D Position { get; }
}

// define enemy classes
EnemyClass gruntClass = new EnemyClass(...);
EnemyClass bugClass = new EnemyClass(...);

// spawn an enemy
Enemy enemy = gruntClass.Spawn();

Prototype model

There is only one class, Enemy. For each enemy class, there's a prototype of an enemy instance of that class. This prototype does not exist in game. To spawn an enemy, you make a clone of the prototype.

class Enemy
{
    public string Name { get; }
    public int InitialHealth { get; }
    public int CurrentHealth { get; }
    public Vector2D Position { get; }

    public Enemy Clone();
}

// define enemy prototypes
Enemy gruntPrototype = new Enemy(...);
Enemy bugPrototype = new Enemy(...);

// spawn an enemy
Enemy enemy = gruntPrototype.Clone();
dtb
  • 213,145
  • 36
  • 401
  • 431
  • The problem is, I need to use multiple classes in order to change things like AI and basic behavior. It's working fine right now with a multiple-class Prototype model (and overriding Clone methods for each class) – Gregorio246 Nov 10 '12 at 22:00