Warum C Code in vielen Spieleprogrammier bücher bzw. Tutorial



  • Der Wrapper schrieb:

    Das die SDL essentiell für das Funktionieren einer Grafikanwendung wäre, steht auch nirgends in meinem Posting.

    Okay, es steht etwas anders. Aber SDL ist aus dem gleichen Grund auch keine wichtige Bibliothek für die Spieleprogrammierung.

    "Wichtig" bedeutet für mich "sollte man kennen" bzw. "man hat einen grossen Vorteil davon, wenn man es kennt". Und das ist meiner Meinung nach bei SDL nicht gegeben, zumindest nicht mehr als bei anderen ähnlichen Bibliotheken.

    Der Wrapper schrieb:

    Dann schau dir mal an, wie bei C++ Bibliotheken Bindings zu anderen Sprachen gemacht werden, also schau es dir low Level an, dann stößt du genau auf das, was ich geschrieben habe.

    Du meinst, dass das Ganze durch ein Binding langsamer wird? Und ausgerechnet bei SDL bringst du das Geschwindigkeits-Argument?



  • Also ich hab in meinem ganzen Leben noch nie ein Problem gesehen das in reinem C besser lösbar ist als in C++...

    Ach, ich finde fscanf teilweise echt deutlich besser als mit std::ifstream zu arbeiten.



  • Auch wenn ich das nicht nachvollziehen kann, fscanf() gibts auch in C++...



  • Wie macht man eigentlich das hier in C++ ?

    printf( Text, "%-10.4s %-10.2f %-10.i" )
    

    Also quasi "formatierte linksbündige Ausgabe".



  • boost::format.



  • Das reine C++ bietet da also quasi nichts vergleichbares an?
    Würde dann ja eigentlich ( von Boost mal abgesehen ) die Verwendung von Ansi-C-Code rechtfertigen.



  • Ich seh es so:

    Beim Spieleprogrammieren wirst sehr oft ueber Bibliotheken(DirectX,OpenGL,SDL ... ) getrieben. Bibliotheken haben sehr oft ein C-Interface (Binaerkompatiblitaet fuer andere compiler, bindings fuer andere sprachen werden einfacher).
    Also hasst Du sowieso scho eine C-like Aufrufsyntax am Hals.

    Um das in gutes c++ zu überfuehren, muesstest halt viel wrappen. Wrappen bedeutet oft "kopie" -> performance ade.

    Hinzu kommt, das grad c++ einen viel alltaegliches abnimmt, das aber oft performancetechnisch sehr naiv umsetzt. Man kann auch in C++ sehr porformant programmieren, klar, aber man muss sich an den einfachsten C++ Dingen da gedanken drueber machen.
    In C sind die Dinge offensichtlicher. Man sieht kopien ! man denkt in kopien, weil jede kopie expliziet getaetigt wird. Man macht sich expliziet ueber Ressourcen im Vorfeld Gedanken. In C++ geht vieles im Hintergrund ...

    Fazit:
    Um performant in C++ Spiele Programmieren zu koennen, muss man sich bissi von dem C++ Hallo World Schema trennen, mehrere Dinge hinterfragen, in c++ untypische Richtungen denken. Und die Technik, die geschwindigkeitsnachteile wieder rausholen kann, ohne den Geschriebenen Code wie einen C-Dialekt aussehen zu lassen -> generische Programmierung -> aka Templates ist halt auch eines der Komplexesten und kompliziertesten Themen in C++.

    Ciao ...



  • RHBaum schrieb:

    Also hasst Du sowieso scho eine C-like Aufrufsyntax am Hals.

    Deswegen musst du dein Programm aber noch lange nicht in C schreiben.

    RHBaum schrieb:

    Um das in gutes c++ zu überfuehren, muesstest halt viel wrappen. Wrappen bedeutet oft "kopie" -> performance ade.

    Gerade in C++ stimmt das so eben nicht unbedingt. Und die API zu Wrappen ist für ein gutes Design nicht wirklich eine notwendige Vorrausetzung. Manche C-style APIs (z.B. OpenGL) lassen sich rein prinzipiell nur sehr schlecht objektorientiert Wrappen, was aber auch gar kein Problem ist.

    RHBaum schrieb:

    Hinzu kommt, das grad c++ einen viel alltaegliches abnimmt, das aber oft performancetechnisch sehr naiv umsetzt.

    An was denkst du da so z.B.? Mir fällt grad kein Sprachmittel ein das ein vernünftiger C++ Compiler "performancetechnisch naiv" umsetzt...

    RHBaum schrieb:

    Fazit: [...]

    Du sagst also um mit C++ gut programmieren zu können muss man C++ beherrschen. Ja, dem kann ich nur zustimmen, aber das trifft auf jede beliebige andere Sprache auch zu...



  • It0101 schrieb:

    Das reine C++ bietet da also quasi nichts vergleichbares an?

    Ähm, klar doch, printf() ist natürlich auch Teil von C++...
    Allerdings würde man in C++ besser Streams verwenden und dafür gibts z.B. das. Die Streams bieten so sogar die Möglichkeit zwischen dem Vorzeichen und der Zahl aufzufüllen, was mit printf() afaik nicht geht. Und sie sind dabei natürlich typsicher...



  • dot schrieb:

    dafür gibts z.B. das.

    Aber das ist relativ umständlich zu verwenden. Für jede auszugebende Variable eine Zeile und deutlich mehr geschreibsel...

    Also da bevorzuge ich immernoch printf... 😃



  • Deswegen musst du dein Programm aber noch lange nicht in C schreiben.

    Aber die Grenzen bzw. Codeanteile verschwimmen eh mehr in Richtung C ...

    Gerade in C++ stimmt das so eben nicht unbedingt. Und die API zu Wrappen ist für ein gutes Design nicht wirklich eine notwendige Vorrausetzung. Manche C-style APIs (z.B. OpenGL) lassen sich rein prinzipiell nur sehr schlecht objektorientiert Wrappen, was aber auch gar kein Problem ist.

    Das faengt schon viel tiefer an.
    die klassische Version von C einen String zu liefern ist:

    int getString(char * Buffer,size_t BufferSize);

    Das ist Typisch C ...
    Nun Wrappe das mal auf C++ ... Das einzige was mir zu einfallen wuerde ist ...

    std::vector<char> myBuffer(128,0); 
    int ir = getString(&myBuffer[0],myBuffer.size());
    

    Super C++ 🙂 dein String steht in nem Vector, ne wandlung in nen std::string ist die unnötige Kopie.

    eine Alternaive:

    char myBuffer[128];
    int ir = getString(myBuffer,128);
    

    Das das C++ ist, wirst wohl nich behaupten oder ?

    andere Alternative:
    Ne Klasse in C++ schreiben, die den String ersetzt und dann auch gleich mit Arrays aufm Stack umgehen kann.
    Resultiert in üblen (Programmier)Overhaed ... oder verwendung von Bibliotheken, deren Anwendung alles andere als Trivial ist 🙂 Und den Rahmen jedes Buches sprengen wuerde, wenn die da reinnimmst (boost z.b.)

    An was denkst du da so z.B.?

    Ganz konkret denk ich an das Beispiel. ct vor paar jahren. Vergleich von den Programmierumgebungen hinsichtlich performance. Das Abstruse Ergebniss: C++ ist langsammer als Java und C# mit .Net ...
    Jeder der sich bissi tiefer in c++ auskennt, hat sofort gesehen, warum das Ergebnis kam. Das am C++ Beispielcode Performancetechnisch Verbrechen begangen wurden! Aber am Ende war es Code im dem Stil, wie es einige naive Tuts und andere Literatur vorschlagen und welcher auch von C++ Befuerwortern propagiert wird. Einfacher super wartbarer C++ code.
    Ubrigens, Kommentar des ct Autors im Forum wo die Vorwürfe Ihm entgegengebracht wurden: Er habe c++ so verwendet wie man es "üblicher weisse" verwenden würde. Spezielle Kniffe und Tricks wie templates 🙂 würden das ergebnis verzerren.
    Das sagt doch scho mehr wie 1000 Worte oder ?

    Das ne std::mapstd::string,std::string nie mit einem speziellen Dictonary in Java mithalten kann ... begreift man doch wirklich erst mit spaeterer Ausbaustufe. Oder warum QMap<QString,QString> um so vieles schneller ist ? Zu welchen Preis ?
    <ironie>
    Ja die Qt iss halt performanter als C++ 🙂
    </ironie>
    Der compiler kann nix fuer, in sofern hab ich mich vielleicht falsch ausgedrueckt, nur c++ suggeriert eine einfache unkomplizierte naive Programmierweisse, welche Performance kostet. Und sogar ct Autoren fallen darauf rein ....

    Ciao ...



  • Das das C++ ist, wirst wohl nich behaupten oder ?

    Doch natürlich. Gewrappt könnte das dann so aussehen, wenn du unbedingt std::string verwenden willst:

    std::string Wrapper::someFunctionName()
    {
        char myBuffer[128];
        getString(myBuffer,128); // Den Rückgabewert müsste man natürlich irgendwie prüfen
        return myBuffer;
    }
    

    Natürlich wird hier auch kopiert, aber die Kopie ist nur unnötig, wenn du die zusätzliche Abstraktionsschicht durch std::string nicht brauchst. Wenn dem tatsächlich so ist, dann kannst du natürlich auch gleich einen char* zurückgeben und hast durch den Wrapper nichts gewonnen.



  • RHBaum schrieb:

    Deswegen musst du dein Programm aber noch lange nicht in C schreiben.

    Aber die Grenzen bzw. Codeanteile verschwimmen eh mehr in Richtung C ...

    Ähm nein? Mit APIs wie z.B. OpenGL arbeitet man praktisch nur in der untersten Schicht und dort kann man das einfach auch direkt so benutzen wies eben is, da brauch man keinen Wrapper. Die restlichen 90% vom Code haben mit OpenGL sowieso nichts zu tun.

    RHBaum schrieb:

    Das faengt schon viel tiefer an.
    die klassische Version von C einen String zu liefern ist:

    Und wo war das Kopieren da schonmal ein tatsächliches Performanceproblem in einem richtigen Program das du geschrieben hast? Und wenns wirklich so ist gibts ja immer noch Möglichkeiten was zu machen wie du ja auch schon selbst gesagt hast...

    RHBaum schrieb:

    An was denkst du da so z.B.?

    Ganz konkret denk ich an das Beispiel. ct vor paar jahren.
    [...]
    Das sagt doch scho mehr wie 1000 Worte oder ?

    Ja, das sagt dass Leute die keine Ahnung von C++ haben damit langsame Programme schreiben können. Toll, wieder was was auf jede andre Sprache auch zutrifft...
    Abgesehen davon hat jeder der C++ mit Java oder .NET vergleicht sowieso ganz grundlegend wo was nicht verstanden...

    RHBaum schrieb:

    Der compiler kann nix fuer, in sofern hab ich mich vielleicht falsch ausgedrueckt, nur c++ suggeriert eine einfache unkomplizierte naive Programmierweisse, welche Performance kostet. Und sogar ct Autoren fallen darauf rein ....

    Ich bin kein regelmäßiger ct Leser also klär mich auf: Warum genau ist ein ct Autor automatisch ein guter C++ Programmierer?



  • _| schrieb:

    Das das C++ ist, wirst wohl nich behaupten oder ?

    Doch natürlich. Gewrappt könnte das dann so aussehen, wenn du unbedingt std::string verwenden willst:

    std::string Wrapper::someFunctionName()
    {
        char myBuffer[128];
        getString(myBuffer,128); // Den Rückgabewert müsste man natürlich irgendwie prüfen
        return myBuffer;
    }
    

    Natürlich wird hier auch kopiert, aber die Kopie ist nur unnötig, wenn du die zusätzliche Abstraktionsschicht durch std::string nicht brauchst. Wenn dem tatsächlich so ist, dann kannst du natürlich auch gleich einen char* zurückgeben und hast durch den Wrapper nichts gewonnen.

    Die Kopie wird gemacht, weil derjenige, der die Funktion someFunctionName() definiert hat, es so wollte. Works as designed. Die Macht liegt bei dem API-Designer.

    Und wenn es darum geht, keine Kopie erzeugen zu wollen, habe ich zwei Möglichkeiten:

    tr1::shared_ptr<string> Wrapper::someFunctionName();
    
    void Wrapper::someFunctioName(string &str);
    

    Ein wenig Nachdenken darf man verlangen, oder?



  • RHBaum schrieb:

    Ubrigens, Kommentar des ct Autors im Forum wo die Vorwürfe Ihm entgegengebracht wurden: Er habe c++ so verwendet wie man es "üblicher weisse" verwenden würde. Spezielle Kniffe und Tricks wie templates 🙂 würden das ergebnis verzerren.
    Das sagt doch scho mehr wie 1000 Worte oder ?

    Ja, ich wäre bei Leuten, die Templates als spezielle Tricks anschauen, ebenfalls vorsichtig 🙂

    Ansonsten hat dot eigentlich schon alles dazu gesagt.

    HeinzErhard schrieb:

    Und wenn es darum geht, keine Kopie erzeugen zu wollen, habe ich zwei Möglichkeiten: [...]
    Ein wenig Nachdenken darf man verlangen, oder?

    Lustig ist, ich habe sogar noch eine dritte:

    std::string Wrapper::someFunctionName();
    

    Bereits momentan häufig durch (N)RVO, in C++0x sowieso automatisch mit Move-Semantik.



  • Der Wrapper schrieb:

    Burkhi schrieb:

    Engine siehe hier: https://secure.wikimedia.org/wikipedia/de/wiki/Gameengine

    Man beachte den Unterschied:
    Grafikengine != Gameengine

    Eine Grafikengine ist nur eine Teilmenge aus einer Gameengine.

    OGRE oder Irrlich sind z.B. keine Gameengines, sondern nur eine Grafikengines.
    Dafür ist Crystal Space eine Gameengine.

    Directx stellt die Funktionen zur Verfügung, um die Darstellungen, die die Engine generiert, auf dem Bildschirm anzuzeigen, mal so ganz grob gesagt.

    Das ist falsch.

    Diesen Teil macht nur Direct3d, eine Teilmenge von DirectX
    DirectX kümmert sich auch um die Soundausgabe und Eingabegeräte etc.

    Meine Aussage ist somit nicht ganz falsch, nur unvollständig 😉



  • @HeinzErhard & Nexus
    Eure Versionen sind schon toll, haben aber gegenüber der C-Variante noch einen Nachteil. Ihr nagelt den Anwender auf dynamische Allokation fest. Auch wenns über spezielle allokatoren lenken koennt, koennte das in der Welt der absoluten performance ein Problem sein.

    die 100% Variante waere, wenn man std::string und einer Stack-ArrayKlasse, vielleicht boost::array mittels Adapter ein geeignetes Interface ueberstülpt, und das Interface als parameter nutzt. Aber das ist schon wirklich hoeheres c++.

    Und wo war das Kopieren da schonmal ein tatsächliches Performanceproblem in einem richtigen Program das du geschrieben hast?

    Und ja, ich selber hab auch ab und an Anwendungsfaelle in der Art.
    Beispielsweisse parsen von Datenbanken, im XML Format. die XML dateien sind oft +100MByte gross. Uebelst viele Referenzierungen drin. Geparst wird mit mehrstufigen eventparser ... Sax (xerces) und dann eigene Stufen drüber.
    Bei einem Plugin z.b. war die letzte Stufe eine Komfortsufe auf eine Qt Schnittstelle. ParseZeiten von 5 min bei einigen files.
    Aendern des internen Datentyps der qt Stufe von QString auf QByteArray und vermeiden der implizieten konvertierung auf utf16, druckte die Parsezeiten auf 30sek.
    Das sind Dinge die der Anwender definitiv merkt 🙂
    Und richtig kritisch iss das ned, sondern nur nervig 🙂 wer 100MB + parsen will, braucht eigentlich geduld.
    Denk mal im Bereich der GrafikProgrammierung, Spieleentwicklung, werden Strings ned so das Problem sein, aber dafuer texturpuffer etc. und da wird man sowas noch krasser merken ....

    Aber die Eingangsfrage war

    Wieso gibt es eigentlich C Funktionscode in den meisten C++ Spieleprgorammier Bücher?

    Die Buecher sollen verkauft werden ... schreib mal als Ausgangsvorraussetzung in dein DirectX - "Ich programmiere den super Shooter in 2 Tagen" Buch, das die Leute "Modern C++ Design" gelesen und verstanden haben sollten, rein.
    Was glaubst wer das Buch kauft und was fuer rezensionen da kriegst. Ich waer echt gespannt drauf und ja, wuerd es mir vielleicht sogar kaufen 🙂

    Ciao ...



  • Du hast Recht, aber std::string ist auch nicht der Weisheit letzter Schluss. Zum Beispiel ist das Interface der Klasse ziemlich zerbloatet, viele Funktionen wären besser frei. Und für spezielle Anforderungen gibt es oft geeignetere Alternativen (und seien das z.B. nur Iteratoren-Paare), doch für den Allgemeingebrauch ist std::string kein schlechter Kompromiss.



  • In der Welt der absoluten Performance verwendet man wohl sowieso keine Strings, aber Gut. Niemand hindert dich in C++ mit Character Buffern am Stack zu arbeiten, im Gegenteil, C++ bietet dir alle Mittel um auch sowas wunderbar und ohne Overhead zu kapseln. Wenn die Performance es wirklich verlangt (was sehr selten der Fall sein wird) dann macht man das eben. Und auch wenn du einfach direkt mit rohen char-Pointern um dich wirfst wird das ganze Programm nicht automatisch C...

    RHBaum schrieb:

    Und wo war das Kopieren da schonmal ein tatsächliches Performanceproblem in einem richtigen Program das du geschrieben hast?

    Und ja, ich selber hab auch ab und an Anwendungsfaelle in der Art.
    Beispielsweisse parsen von Datenbanken, im XML Format. die XML dateien sind oft +100MByte gross. Uebelst viele Referenzierungen drin. Geparst wird mit mehrstufigen eventparser ... Sax (xerces) und dann eigene Stufen drüber.
    Bei einem Plugin z.b. war die letzte Stufe eine Komfortsufe auf eine Qt Schnittstelle. ParseZeiten von 5 min bei einigen files.
    Aendern des internen Datentyps der qt Stufe von QString auf QByteArray und vermeiden der implizieten konvertierung auf utf16, druckte die Parsezeiten auf 30sek.
    Das sind Dinge die der Anwender definitiv merkt 🙂
    Und richtig kritisch iss das ned, sondern nur nervig 🙂 wer 100MB + parsen will, braucht eigentlich geduld.

    Ok, mal abgesehen davon dass man über den Sinn von 100MB großen XML Dateien vermutlich streiten kann (wer editiert 100MB große Textfiles!?) hast du also ein extremes Beispiel gefunden wo der naive Ansatz ein Problem ist und gleichzeitig gezeigt dass es einen besseren Ansatz gibt mit dem es dann doch wieder kein Problem ist...

    RHBaum schrieb:

    Denk mal im Bereich der GrafikProgrammierung, Spieleentwicklung, werden Strings ned so das Problem sein, aber dafuer texturpuffer etc. und da wird man sowas noch krasser merken ....

    Ich hatte da noch nie Probleme mit der Performance von C++. Und selbst wenn: Mit C hätt ich natürlich genau die gleichen Probleme...



  • Die Buecher sollen verkauft werden ... schreib mal als Ausgangsvorraussetzung in dein DirectX - "Ich programmiere den super Shooter in 2 Tagen" Buch, das die Leute "Modern C++ Design" gelesen und verstanden haben sollten, rein.
    Was glaubst wer das Buch kauft und was fuer rezensionen da kriegst. Ich waer echt gespannt drauf und ja, wuerd es mir vielleicht sogar kaufen 🙂

    Naja ich bin ja kein Autor, ich überlasse das schreiben lieber andere. Außerdem bin ich noch am lernen und das würde den anderen auch nicht weiterhelfen wenn ich jetzt anfange ein Buch über die 3D Spieleprogrammierung zu schreiben das noch dazu für erweiterung im code offen und für veränderungen geschlossen ist. Mir geht es ums design pattern. Denn man will ja mal eine anderen Hintergrund oder so und da ist C wirklich nicht die Ideale sprache. Für den Anfang möchte ich mal Pong und Space Invaders programmieren und danach wenn ich besser programmieren kann ein 2D Adventure aller Monkey Island schreiben da wird, glaub ich schon mehr mit design pattern gearbeitet. Korrigiert mich wenn ich falsch liege.

    Gruß Blacky


Anmelden zum Antworten