Problema di riprogettazione (ereditarietà multipla senza ereditarietà multipla)

2

Attualmente sto lavorando a un motore di gioco per lavoro e ho centrato un muro sulla mia idea. Ho più oggetti (detti prefabbricati) con proprietà molto comuni come Position , Rotation e Scale . Ce ne sono altri, ma concentriamoci su quelli per questo particolare problema.

L'idea era di creare una classe base chiamata RenderObject in cui queste proprietà vivranno; tuttavia, c'è un problema. Alcuni oggetti nel nostro motore possono essere visualizzati sia in 3D che in 2D . Voglio avere un singolare metodo Render per ogni oggetto che gestisce entrambi i casi. Ora, questo era semplice da risolvere in quanto posso solo creare due metodi virtuali:

public virtual void Render() { }
public virtual void Render(CameraMode mode) { }

Ciò semplifica il rendering degli oggetti nel modo giusto. Ad esempio, ho una collezione di 2D solo oggetti; Posso semplicemente chiamare Render per questi oggetti e il loro codice di rendering 2D viene eseguito. Se ho una collezione di oggetti che possono essere renderizzati in 2D o 3D mode, allora chiamerò invece Render(CameraMode) .

Il problema sta nelle proprietà; con DirectX 11 most 2D metodi specifici (come DrawLine ) richiedono Vector2 oggetti per le posizioni. Questo è un problema per la semplificazione se la classe base ha solo Vector3 oggetti per le posizioni. Devo quindi prendere le proprietà X e Y di Vector3 e creare un nuovo oggetto Vector2 ogni chiamata di estrazione. Invece, mi è venuta l'idea di creare una classe di base secondaria chiamata RenderObject2D che nasconde Vector3 restituendo invece Vector2 . Tuttavia, questo è ancora un problema in quanto questo non riguarda gli oggetti che possono essere visualizzati in 2D e 3D . Posso implementare l'opzione multi metodo Render e solo renderizzare in modo diverso per l'oggetto, ma poi ho 2D oggetti che hanno campi 3D inutilizzati e proprietà come Buffer oggetti che non sono usati in 2D .

Esempio di codice

Il codice corrente non è la strada che voglio seguire perché non sono un fan di nascondere le proprietà sottostanti. In genere si aggiunge a una classe base, non da togliere.

// Currently 3D is perspective and 2D is orthographic.
public enum CameraMode { Perspective, Orthographic }
public class RenderObject {
    public Vector3 Position { get; set; } = Vector3.Zero;
    public virtual void Render() { }
    public virtual void Render(CameraMode mode) { }
    ...
}
public class RenderObject2D : RenderObject {
    public new Vector2 Position {
        get { return new Vector2(base.Position.X, base.Position.Y); }
        set { base.Position = new Vector3(value, 0); }
    }
}
public class Tree : RenderObject2D {
    // Can be rendered in 2D as a sprite and 3D as a model.
    // Current structure does not support this.
}

C'è un modo più intelligente per realizzare questo in modo semplicistico o sono bloccato ad attuare i due diversi metodi e solo a gestire il trade-off?

    
posta PerpetualJ 08.11.2018 - 19:36
fonte

1 risposta

1

La modifica del tipo di una proprietà in una classe derivata sta per essere un problema di manutenzione. È molto confuso.

Inoltre non ti sei salvato dalla creazione di oggetti Vector2d. Ogni volta che recuperi RenderObject2d.Position, stai istanziando un Vector2d.

Vorrei solo fare questo:

public class RenderObject {
    public Vector3 Position3d 
    { 
        get => _position3d; 
        set
        {
            _position3d = value;  
            Position2d = new Vector2(_position3d.X, _position3d.Y);
        } 
    };
    private Vector3 _position3d;

    public Vector2 Position2d { get; private set; }

    public virtual void Render() { }
    public virtual void Render(CameraMode mode) { }
    ...
}
    
risposta data 08.11.2018 - 21:51
fonte

Leggi altre domande sui tag