I'm new to this whole thing, so please tell me if I'm doing this wrong of if there's a better spot for my question.
I'm making a game with basic systems for projectiles, npcs and items. This game will have multiple variants of each of these types. For the purposes of this example, there will be a Bullet projectile, a Rocket projectile, and a Pistol which shoots Bullets.
The only experience I have with such a system is inside Terraria's source code, where Items are all defined in a massive if-else tree, e.g.
else if (this.type == 467)
{
this.name = "Fireball";
this.width = 40;
this.height = 40;
this.aiStyle = 1;
this.hostile = true;
this.damage = 10;
}
The problem with this approach is (apart from the terrible mess it makes) that adding new items requires modifications to 4-5 different areas of code - especially if you want to add any extra effects, like giving off light, burning enemies etc.
I'm trying to do this in a much better format. I've come up with a simple system that with nested classes, e.g.
public class ProjectileData
{
public class Bullet : Projectile
{
public float speed;
public Bullet() : base()
{
this.type = ProjectileID.Bullet;
this.damage = 25;
this.origin = new Vector2(9.5f, 2.5f);
speed = 10;
}
public override void AI()
{
this.velocity += new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * speed;
}
public override void OnHit()
{
Game.CreateExplosion(this.position);
}
}
public class Rocket : Projectile
{ ... }
}
With this system, to create a bullet, instead of using something like
Projectile.CreateProjectile(int id, ...)
{
Projectile projectile = new Projectile(id);
}
...
Projectile.CreateProjectile(ProjectileID.Bullet, ...);
I have
Projectile.CreateProjectile<T>(...) where T : Projectile, new()
{
T projectile = new T(id);
}
...
Projectile.CreateProjectile<ProjectileData.Bullet>(...);
which looks and works nicely.
However, I've run into a problem: if I want to create an item that shoots a projectile, I can't reference it. For example, with the id-based system I could write something like
item.projectileType = ProjectileID.Bullet
but it isn't possible to assign a Class to a property like that.
I guess this boils down to 2 questions:
- Is this the 'correct' way to pass data to an object or is there a better structure, with or without inheritance??
- Is there a way to reference a class, and use that reference at runtime in a generic method call?
ProjectileData.Bullet
class.item.projectileType = typeof(ProjectileData.Bullet)
andCreateProjectile<item.projectileType>(..)
doesn't work).