Übersichtlichkeit erhalten



  • Tobias, auf jeden Fall ist die Idee mit den A_ ... F_ furchtbar.

    Du mußt Dir mal überlegen, ob Deine Vererbungshierarchie wirklich richtig ist. Manchmal wird zu oft geerbt, weil Vererbung ja OOP ist. Aber das muß nicht so sein. Denk Dir noch mal die Klassen durch, ob ein RotAccSprite wirklich ein spezialisiertes AccSprite ist - oder ob sich RotAccSprite und AccSprite vielleicht durch ein Memberobjekt unterscheiden!

    Möglicherweise fährst Du besser, wenn Du komplexe Klassen als zusammengesetzte Dinge betrachtest (Stichwort: Komposition), z.B. kann eine Sprite-Klasse mit einer Bewegungsklasse (die dann Rot, Acc, Move sein kann) kombiniert werden und dadurch neue Fähigkeiten erlangen. Dann muß nicht jede neue Möglichkeit durch Vererbung gewonnen werden.

    Ist die alte Frage: "ist ein" oder "hat ein"?

    Nur mal als Anregung: ich könnte mir denken, daß ein Grafikobjekt eine Art "Bewegungsslot" hat, wo man Objekte reinsteckt, die die Bewegung realisieren. Diese Bewegungsobjekte können dann aus einer anderen Hierarchie stammen und die Berechnungen der neuen Koordinaten enthalten. So eine Art Visitor-Pattern. Stecke ich ein Objekt Rot und ein Objekt Move rein, so habe ich Drehung und Bewegung gleichzeitig.

    Kann man aus Entfernung natürlich nur schwer sagen, da man Deine Absicht nicht genau kennt, ebenso wenig Dein Designziel.



  • Original erstellt von Gregor:
    Sieht IMHO garnicht so aus. Die Methodennamen lassen vermuten, dass es sich größtenteils um sehr einfache Methoden handelt. Entsprechend sollte die Klasse trotz der vielen Methoden recht klein sein.

    nicht die methoden stoeren mich, sondern die member -> braucht eine klasse mit

    die effektiv 4 sachen kann:
    checkScreenBorders
    deactivateThrust
    activateThrust
    move

    wirklich
    10 member variablen?

    zuviele getter und setter - das stoert irgendwie... man kann ja fast jede variable setten 😞



  • ja, wir haben hier für jeweils X und Y:

    inc, dec, set, get.

    Eigentlich würden set und get genügen. Damit kannst Du den Rest bequem implementieren. Vielleicht noch ein SetDirection wo man x und(!) y Richtung angeben kann für den Speed. das macht dann schonmal 5 Methode statt 8. Das Klasseninterface ist damit zwar nichtmehr minimal, aber dafür kleiner und noch relativ komfortabel.



  • warum kriegt set/get double und inc/dec int?
    ich wuerde mit vektoren statt einzelnen koordinaten rechnen.
    kann man uebersichtlicher mit rechnen. und man kanns einfacher auf 3d erweitern.



  • Immer wenn du eine C API verwendest, was du hier anscheinend tust, solltest du dir wrapper um die einzelnen funktionen schreiben - es muessen nicht immer klassen sein, du kannst auch ne funktion um ne funktion wrappen:
    der sinn ist der: du wirfst eine exception wenn die funktion fehlschlaegt.

    Meinst du sowas:

    void TD_SetAlpha(surface, SDL_SRCALPHA, alpa)
    {
        if(SDL_SetAlpha(surface, SDL_SRCALPHA, alpha) == ERROR)
        {
            printf("Couldn't set alpha: %s.\n", SDL_GetError());
            exit(EXIT_FAILURE);
        }
    }?
    

    achja: ruf kein exit() auf -> das ruft dir naemlich keine dtors auf.

    dtors = Destruktoren?

    @ Tobias : Nenn doch mal konkret Zahlen, wie groß die Klassen und Methoden so sind.

    sprites.h: 172 Zeilen
    sprites.cpp: 908 Zeilen

    Tobias, auf jeden Fall ist die Idee mit den A_ ... F_ furchtbar.

    Ja, stimmt.

    [...] Ist die alte Frage: "ist ein" oder "hat ein"?

    Darüber habe ich mir bei der Aufstellung der Klassenhierarchie auch schon meine Gedanken gemacht. Allerdings denke ich nun, dass ich zumindest die Bitmap/Anzeigefunktionalität nicht erben lassen brauche.

    Nur mal als Anregung: ich könnte mir denken, daß ein Grafikobjekt eine Art "Bewegungsslot" hat, wo man Objekte reinsteckt, die die Bewegung realisieren. Diese Bewegungsobjekte können dann aus einer anderen Hierarchie stammen und die Berechnungen der neuen Koordinaten enthalten. So eine Art Visitor-Pattern. Stecke ich ein Objekt Rot und ein Objekt Move rein, so habe ich Drehung und Bewegung gleichzeitig.

    Oh man, da kommen wieder diese komischen "Factories", "Singletons" und "Visitors" 😃 Tut mir Leid, aber dies Erklärung habe ich nicht recht verstanden. Ich hoffe das änder sich, sobald ich dein Buch lese.

    @ Shade

    Die 10 Variablen halte ich schon alle für erforderlich, doch die Setter/Getter und Increaser/Decreaser können eigentlich alle weg!
    Die habe ich in meinem neuen Code nur noch aus Kompatibilitätsgründen drin, werden aber bald entfernt.

    ich wuerde mit vektoren statt einzelnen koordinaten rechnen.
    kann man uebersichtlicher mit rechnen. und man kanns einfacher auf 3d erweitern.

    Dann hat man aber immer sowas wie motion.x bzw. motion.y.
    Außerdem finde ich es recht unhandlich, wenn Kräfteüberlagerungen (Gravitation, Kollision, Schub etc.) überlagern.



  • sprites.h: 172 Zeilen
    sprites.cpp: 908 Zeilen

    Das ist IMHO viel zu groß. Aber das hast du ja eh schon aufgeteilt, wenn ich das richtig mitgekriegt habe. Ist sicherlich Geschmackssache, aber ich würde darauf achten, keine Datei und keine Klasse zu kriegen, die größer als 250 Zeilen ist. Ich kann in größeren Dateien und Klassen nur schwer den Überblick behalten. Bei mir sind die Klassen und Dateien sogar noch viel kleiner: im Schnitt weniger als 50 Zeilen.



  • Original erstellt von jetzt_heiße_ich_Smax:
    Meinst du sowas:

    void TD_SetAlpha(surface, SDL_SRCALPHA, alpa)
    {
        if(SDL_SetAlpha(surface, SDL_SRCALPHA, alpha) == ERROR)
        {
            printf("Couldn't set alpha: %s.\n", SDL_GetError());
            exit(EXIT_FAILURE);
        }
    }
    

    ?

    nein, ich meine

    namespace TD {
    void SetAlpha(surface, SDL_SRCALPHA, alpa)
    {
        if(SDL_SetAlpha(surface, SDL_SRCALPHA, alpha) == ERROR)
        {
            throw SDLExceptopm(SDL_GetError());
           //bzw. was spezifischeres wie AlphaBlending(SDL_GetError())
        }
    }
    }
    

    dtors = Destruktoren?

    jep. ich keurze immer ab, sorry
    dtor == Destruktor
    ctor == Konstruktor
    copyctor == Kopierkonstruktor
    stdctor == Standard Konstruktor

    sprites.h: 172 Zeilen
    sprites.cpp: 908 Zeilen

    172 Zeilen fuer die interface definition sind viel
    und 908 zeichen fuer die implementation sind viel zu viel.

    bedenke: eine methode sollte nie laenger als 15 zeilen seien.

    Oh man, da kommen wieder diese komischen "Factories", "Singletons" und "Visitors" Tut mir Leid, aber dies Erklärung habe ich nicht recht verstanden. Ich hoffe das änder sich, sobald ich dein Buch lese.

    Jo, factory, Singleton und Visitor wird in seinem buch erklaert.
    kannst dir aber auch sachen im netz suchen. singleton und factory sind einfach zu verstehen.

    Die 10 Variablen halte ich schon alle für erforderlich, doch die Setter/Getter und Increaser/Decreaser können eigentlich alle weg!
    Die habe ich in meinem neuen Code nur noch aus Kompatibilitätsgründen drin, werden aber bald entfernt.

    wie gesagt: ich kenne mich mit grafikprogrammierung nicht aus...
    ich kann dir nicht sagen was warum wo nicht hingehoert, ich kann nur sagen, dass da zuviel ist.

    schau dir an, was deine klasse koennen muss (notfalls mach n simples UML Diagramm).
    muss die klasse setter anbieten? reicht es vielleicht wenn der sprite einmal positioniert wird, und dann nur noch ge'move't?
    reicht es vielleicht ein setVector anzubieten um bewegungsvectoren direkt zu setzen?
    etc.

    das interface einer klasse sollte moeglichst klein gehalten werden, alles was unnoetig ist kommt raus. manchmal muss man viel anbieten, aber oft kann man das wegdesignen...



  • Shade, Du darfst hier aber etwas nicht vergessen: bei einem Framework macht es durchaus Sinn, daß es sehr große Interfaces geben kann, um dem Aufrufer allerlei Schnickschnack in wenigen Schritten anzubieten. Der Aufrufer soll einige Sachen zentral finden. Hierdurch gibt es evtl. Teil-Redundanzen bei den Methoden, aber für den Anwender ist das von Vorteil.

    Auch die 15 Zeilen Regel kann ich so nicht unterstützen - bei der Programmierung von API-nahen Funktionen ist es durch Setzen und Abfragen von Optionen leicht möglich, daß man solche Grenzen sprengt. Es macht z.B. wenig Sinn einen Dialoghandler, der die Buttons nach einer Aktion umsetzt oder disabled/enabled, mit Gewalt auf so ein Limit zu beschneiden, nur damit die Regel erfüllt ist. Hier ist es oftmals übersichtlicher, wenn man die Anprogrammierung der API zusammen läßt. Ähnliches gilt auch für Schnittstellen oder z.B. für solche Grafik-Initialisierungen. Wenn typische Beispiele für eine Grafik-Lib in C geschrieben sind und dort bestimmte Schritte 30 Zeilen lang sind, so kann es hilfreicher sein dies weitgehend 1:1 zu übertragen, um die Analogie zu erhalten.



  • Original erstellt von jetzt_heiße_ich_Smax:
    Dann hat man aber immer sowas wie motion.x bzw. motion.y.
    Außerdem finde ich es recht unhandlich, wenn Kräfteüberlagerungen (Gravitation, Kollision, Schub etc.) überlagern.

    Hm. Trotzdem wäre eine Vektorklasse hilfreich, weil diese Kräfteüberlagerungen doch alle linear sind! D.h. Du kannst das problemlos in x und y zerlegen.

    Angenommen Du schreibst eine 2D-Vektorklasse (von mir aus auch 3D), so kannst Du die ganzen Operatoren dazu implementieren und das ganze wird dann zu position = richtung * zeit + startposition, ohne daß jemand sieht daß dahinter ein (x,y) oder gar (x,y,z) stecken. Halbiert Deinen ganzen Rechencode um den Faktor 2 in der Zeilenzahl und lagerst das aus. Das macht schon Sinn. Auch Drehungen kannst Du dann mit einer Maxtrixklasse realisieren, wo Vektor = Vektor * Matrix. Die eigentliche Arbeit verschwindet dann anderswo und Du benutzt nur noch die Mathematik innerhalb Deiner Wrapperklassen. Ebenso halbiert sich die Anzahl an Membervariablen, weil das x/y getrennt einfach wegwandert in ein vector m_Position statt int m_PosX int m_PosY.



  • Original erstellt von Marc++us:
    Vektor = Vektor * Matrix

    Iiihhh Zeilenvektoren 😃



  • hehe. normalerweise multipliziert man transformationen ja auch von links.


Anmelden zum Antworten