Come passare i dati agli oggetti OOP?

3

Sono nuovo di questa cosa, quindi per favore dimmi se sto sbagliando se c'è un posto migliore per la mia domanda.

Sto facendo un gioco con i sistemi di base per proiettili, npc e oggetti. Questo gioco avrà più varianti di ciascuno di questi tipi. Ai fini di questo esempio, ci sarà un proiettile proiettile, un proiettile missilistico e una pistola che sparerà ai proiettili.

L'unica esperienza che ho con un tale sistema è all'interno del codice sorgente di Terraria, in cui gli oggetti sono tutti definiti in un albero di grandi dimensioni if-else, ad es.

else if (this.type == 467)
{
    this.name = "Fireball";
    this.width = 40;
    this.height = 40;
    this.aiStyle = 1;
    this.hostile = true;
    this.damage = 10;
}

Il problema con questo approccio è (a parte il pasticcio terribile che fa) che aggiungere nuovi elementi richiede modifiche a 4-5 diverse aree di codice, specialmente se si desidera aggiungere effetti aggiuntivi, come emettere luce, nemici ardenti ecc.

Sto provando a farlo in un formato molto migliore. Sono arrivato con un semplice sistema che con classi nidificate, ad es.

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
    { ... }
}

Con questo sistema, per creare un proiettile, invece di usare qualcosa come

Projectile.CreateProjectile(int id, ...)
{
    Projectile projectile = new Projectile(id);
}
...
Projectile.CreateProjectile(ProjectileID.Bullet, ...);

Ho

Projectile.CreateProjectile<T>(...) where T : Projectile, new()
{
    T projectile = new T(id);
}
...
Projectile.CreateProjectile<ProjectileData.Bullet>(...);

che sembra e funziona bene.

Tuttavia, ho incontrato un problema: se voglio creare un oggetto che spara un proiettile, non posso farvi riferimento. Ad esempio, con il sistema basato su ID, potrei scrivere qualcosa come

item.projectileType = ProjectileID.Bullet

ma non è possibile assegnare una Classe a una proprietà del genere.

Immagino che questo si riduce a 2 domande:

  • È questo il modo "corretto" per passare i dati a un oggetto o esiste una struttura migliore, con o senza ereditarietà?
  • Esiste un modo per fare riferimento a una classe e utilizzare tale riferimento in fase di esecuzione in una chiamata di metodo generica?
posta FiveThree 25.04.2016 - 09:19
fonte

1 risposta

2

Utilizza il modello di fabbrica . Una fabbrica è un oggetto che crea oggetti.

Quindi, quando hai un'arma che spara proiettili, passa a ProjectileFactory e lascia la creazione del proiettile a quella classe.

Puoi quindi avere classi diverse che estendono ProjectileFactory, come BulletProjectileFactory , ExplosiveProjectileFactory , GravityAffectedProjectileFactory , HomingProjectileFactory ecc. che creano punti elenco con diverse meccaniche di gioco.

Ad esempio, quando vuoi creare una pistola che spara proiettili che volano con una velocità di 8,0 pixel per tick, fai 12 danni e usa lo sprite "bullet.png" per scrivere qualcosa del tipo:

 Weapon pistol = new Weapon( new BulletProjectileFactory( 8.0f, 12, "bullet.png") );

Il metodo fire() della tua classe di armi farebbe quindi qualcosa di simile a

 projectileFactory.createProjectile();
    
risposta data 25.04.2016 - 11:20
fonte