Ist es sinnvoll, eine Game-Engine in C zu schreiben? [geschlossen]

53

Obwohl C ++ der König zu sein scheint, wird C, wie mir gesagt wurde, immer noch häufig in Spielen verwendet, insbesondere auf den Konsolen. Wäre es heute jedoch unvernünftig, eine komplette Game-Engine in C zu schreiben? Was sind, wenn überhaupt, einige Vorteile, die C gegenüber C ++ hat? Warum sollte jemand möglicherweise C über C ++ verwenden wollen?

Schlürft Mad Rips
quelle
1
Konsolenspiele verwenden c ++ FYI!
Alan Wolfe
Tatsächlich denke ich, dass C einfacher wäre, Spiele bis zu einer bestimmten Größe zu schreiben, zum Beispiel Zehntausende von LOC oder so, hauptsächlich, weil man sich auf Bits und Bytes ohne komplexe Datentypen konzentrieren kann und im Vergleich zu C ++ superschnell baut. Aber nach einer bestimmten Größenordnung (z. B. Erreichen von Hunderttausenden von LOCs) würde ich nach C ++ greifen wollen, wo ich tatsächlich komplexe Datentypen, mehr Typensicherheit, möglicherweise Ausnahmen, Vorlagen und eine noch größere Anzahl von Dateien haben möchte scale (sagen wir Millionen), damit andere Dinge als C ++ mit dem C- und C ++ - Code kombiniert werden können.
C hat auch den zusätzlichen Vorteil, dass es selbst für ABI weithin portierbar ist, so dass es ziemlich einfach wird, Ihren vorhandenen C-Code zu übernehmen und ihn dann in anderen Sprachen zu verwenden, beispielsweise von einem FFI. C ++ ist etwas umständlicher in Bezug auf die Namensverfälschung, die Unfähigkeit, sicher über Modulgrenzen hinwegzugehen, die Vtable-Wiederholungen sind nicht über Compiler hinweg gleich, Standard-Bibliotheksimplementierungen unterscheiden sich zwischen Anbietern usw. Im Allgemeinen finde ich, dass die C-Bibliotheken, die ich schreibe, länger halten, ohne dass Änderungen erforderlich sind, und aus der Mode kommen, obwohl es länger dauert, damit irgendetwas Skaliertes zu schreiben.

Antworten:

49

Wäre es heute jedoch unvernünftig, eine komplette Game-Engine in C zu schreiben?

Es ist vernünftig, aber die Frage ist, was es Ihnen kauft? Sie brauchen wahrscheinlich nicht die extreme Portabilität, die C bietet, und es ist eine Schande, auf alle Funktionen zu verzichten, die C ++ bietet, es sei denn, Sie sind wirklich philosophisch dagegen eingestellt.

Was sind, wenn überhaupt, einige Vorteile, die C gegenüber C ++ hat?

Bessere Kompilierungszeit?

Warum sollte jemand möglicherweise C über C ++ verwenden wollen?

Ich denke, es ist hauptsächlich eine ästhetische Entscheidung. Viele Leute mögen C, weil es einfach und minimal ist und sich sauber anfühlt. C ++ hat viele nette Funktionen (Namespaces alleine machen es wert, benutzt zu werden), aber es ist auch groß und chaotisch.

herrlich
quelle
3
Bis Id Tech 4
Optiker
9
@Josh: Einfacher zu debuggen !? C-Programme sind bekanntermaßen schwer zu debuggen, hauptsächlich aufgrund von Zeigern und Speicherverwaltung. C ++ - Programme (bei Verwendung echter C ++ - Programmiersprachen, bei denen Zeiger und Speicherverwaltung nach Möglichkeit vermieden werden) sind um mehrere Größenordnungen einfacher zu debuggen.
BlueRaja - Danny Pflughoeft
14
C kann von bloßen Sterblichen verstanden werden. C ++ scheint viele Funktionen zu bieten, die erfahrene Programmierer auch nach einem Jahrzehnt, in dem sie es jeden Tag zum Leben erwecken, kennenlernen.
Jari Komppa
13
C ++ ist eine große Sprache, aber ihr furchterregender Ruf wird hauptsächlich von Leuten verbreitet, die gerade Horrorgeschichten gelesen und sich nicht die Zeit genommen haben, sie zu lernen. Es gibt viel zu lernen, aber dafür bekommt man viel Wert. Mit C ++ können Sie viele Dinge ausdrücken, die C einfach nicht kann.
Munificent
2
@ BlueRaja-DannyPflughoeft #define malloc(x) my_malloc(x) #define free(x) my_free(x)und Sie debuggen jetzt Speicher. Mit C ++ wissen Sie nie, was wann zugewiesen wird, weil es so viele Möglichkeiten gibt, Speicher zuzuweisen (neu, malloc, Klassenkonstruktoren usw.)
YoYoYonnY
59

Ich habe ausgiebig mit einer Pure-C-Game-Engine gearbeitet, die mehrere Produkte ausgeliefert hat, daher ist dies absolut möglich. Hier ist meine persönliche Erfahrung mit der Arbeit in beiden C vs C ++ Engines:

  1. Durch die Verwendung von Pure-C-Strukturen können Sie das Wissen über die Ausrichtung von Strukturen nutzen und diese Informationen dann zum Erstellen Ihrer Objektpersistenz- und Serialisierungsebenen verwenden. Die Engine, mit der ich gearbeitet habe, hatte einige einfache Header-Parser, die diese Metadaten über Strukturen automatisch erstellten, und bestimmte Arten von Datenoperationen wurden trivial. Das Parsen beliebiger C ++ - Header-Dateien ist im Grunde unmöglich, und sobald Sie Vererbungs- und virtuelle Funktionen hinzufügen, verlieren Sie die Fähigkeit, genau zu wissen, wo sich Dinge im Speicher befinden
  2. Die Kompilierungszeit ist erheblich kürzer, da Sie Ihre Header-Dateien sehr kompakt halten und die Vorwärtsdeklarationen von Strukturen nutzen können.
  3. Das Debuggen kann verbessert werden, da es ohne die Verwendung von Vorlagen und Vererbung sehr einfach ist, genau herauszufinden, was ein bestimmtes Objekt ist und was es tut.

All diese Vorteile ließen sich auch mit eingeschränktem C ++ - Code erzielen, der auf Vorlagen und Vererbung von serialisierten Objekten verzichtet. Es war jedoch die Entscheidung des CTO, die Einfachheit leichter durchzusetzen, wenn die verwirrenderen Elemente von C ++ nicht vorhanden wären verfügbar.

Ich persönlich halte dies für etwas extrem, da ich die Möglichkeit, Variablen in for-Schleifen zu deklarieren, und die vielen völlig legitimen Vererbungszwecke wirklich vermisst habe. Aber es hat uns letztendlich nicht viel Produktivität gekostet

Ben Zeigler
quelle
5
Es gibt wirklich nichts, was Sie daran hindert, Vererbung in C zu implementieren. Und wenn Sie C99 verwenden, können Sie Variablen in for-Schleifen deklarieren.
Jsimmons
15
Ich werde Punkt 3 ablehnen. Es ist genauso einfach, chaotischen, schwer zu debuggenden Code in C zu schreiben wie in C ++. Besseres Debuggen ist nichts, was der Sprache C innewohnt.
Dan Olson
7
Sogar sauberer Code kann in C ++ schwieriger zu verstehen sein - mit Überladungen, Vorlagen, virtuellen Funktionen und Ausnahmen ist es viel schwieriger, auf einen Blick genau zu erkennen, wie der tatsächliche Steuerungsfluss aussehen wird.
Kylotan
6
@Dan: Wenn man einfach mehr Zeug hat, ist C ++ schwerer zu debuggen. Sie können sich natürlich darauf beschränken,
Weniger Zeug ist eigentlich der Grund, warum ich C mag. Zum Beispiel kann ich in CI nur Bits und Bytes mit einem memcpyfür alles kopieren , weil das Typensystem Dinge wie ctors und dtors nicht zulässt. Ich kann Code schreiben, in dem Wissen, dass ich bei fast jeder Codezeile keine Nebeneffekte rückgängig machen muss, da ich eine Funktion nur dann implizit beenden kann, wenn ich sie explizit wieder beende. Es werden keine Ausnahmen geworfen. All dies macht das Schreiben von Datenstrukturen so viel einfacher - in C ++ vectorist es sehr zeitaufwändig, nur standardkonform zu schreiben , insbesondere, wenn Sie ...
18

Ich schreibe eine in C ++ und Lua geschriebene 2D-Game-Engine in C und Lua um. Bisher waren die Erfahrungen recht gut. Vektor- und Matrixoperationen sehen in C natürlich nicht so gut aus. Abgesehen davon fand ich die Erfahrung nach mehr als 10 Jahren als C ++ - Entwickler recht erfrischend.

C hat eine Reihe von Vorteilen gegenüber C ++:

  1. Der Compiler stellt sicher, dass zur statischen Initialisierungszeit kein Code ausgeführt wird. Das macht es völlig sicher, globale Daten wie Zeichenfolgen, die als Schlüssel verwendet werden, statisch zuzuweisen, z
  2. Transparenz. In C führt die Zuweisung oder Zuweisung oder Definition einer Variablen nicht dazu, dass eine Menge Code ausgeführt wird. C ++ generiert automatisch Kopierkonstruktoren für Sie, sodass Sie weniger Kontrolle darüber haben, was beim Ausführen von Zuweisungen ausgeführt wird.
  3. Ein Großteil des Debuggens kann einfacher sein, da Funktionsnamen nicht unleserlich gemacht werden
  4. Es ist normalerweise in Ordnung, memcpy in C zu verwenden, aber in C ++ kann es leicht zu Problemen kommen, da Kopierkonstruktoren nicht ausgeführt werden. Angesichts dessen ist memcpy viel schneller als std :: copy , was zählt.

Abgesehen davon hat der Einstieg in die C-Denkweise eine Reihe von Vorteilen. In C ++ stelle ich oft fest, dass die Dinge ein bisschen übergeneralisiert und abstrakt sind. In CI werden normalerweise Dinge wie Get-Set-Methoden herausgeschnitten und häufig Arrays mit fester Größe vorab zugewiesen, anstatt dynamische Arrays zu verwenden. Oft habe ich kürzeren und einfacher zu debuggenden Code in C. Die Datenstrukturen sind in der Regel flacher und in einem Debugger einfacher anzuzeigen.

Um fair zu sein, würde ich eine App niemals exklusiv in C erstellen. Der Grund dafür ist, dass ich sie mit einer höheren Sprache wie Lua kombiniere, die C sehr gut ergänzen kann, wenn C nicht so stark ist.

Id-Software schreibt die meisten ihrer Motoren in CI glauben, können Sie sich Return to Castle Wolfenstein , das in C geschrieben wurde, ansehen .

Ich schrieb über einige meiner Erfahrungen mit der Skalierbarkeit von C vs C ++ und den Nachteilen des STL-Vektors im Vergleich zu einfachen Arrays.

Erik Engheim
quelle
11
Zu Ihrer Information, in jedem Fall, den ich überprüft habe (das sind, glaube ich, darwin gcc und vc2008), wird std :: copy nur zu einem Aufruf von memcpy kompiliert, wenn beide Typen POD sind.
Gewinnspiel
3
Auch RE: STL-Vektor gegen einfache Arrays, warum nicht die netten Teile des Vektors verwenden und normale C-Zeiger anstelle von Iteratoren verwenden, wenn Sie sie nicht mögen? Du kannst einfach & myvector [N] machen. Es ist wie das Beste aus beiden Welten, wenn Ihr C-Code die gleiche Speicherzuweisung vornimmt. Oder schauen Sie sich BOOST_FOREACH für Schleifen an. Macht es noch einfacher als C.
Gewinnspiel
1
Danke für den Tipp zu std :: copy memcpy. Ich wusste das nicht. Als Alexandrescu dies vor einigen Jahren behandelte, war dies nicht der Fall. Informationen zu C ++ - Iteratoren. Es geht hauptsächlich um die Philosophie. Ich versuche zu programmieren, wie C ++ programmiert werden soll, um den Menschen, mit denen ich zusammenarbeite, und um die Vorteile von C ++ - Funktionen zu nutzen. Es wurde hauptsächlich darauf hingewiesen, dass einige C ++ - Verbesserungen wie STL-Container nicht immer besser sind, als dies auf die alte C-Weise zu tun.
Erik Engheim
7

Wie jemand anderes betonte, bringt C ++ den Vorteil großer Schultern mit sich, auf denen Sie stehen können (BOOST, STL usw.). Am Ende ist es eine persönliche Entscheidung, aber ich würde C ++ aufgrund der verfügbaren Ressourcen wählen. Wenn es Features in C ++ gibt, die Sie nicht verwenden möchten, verwenden Sie sie nicht.

user266
quelle
1
Beachten Sie, dass 99% der kommerziellen und firmeninternen Spiele-Engines aus verschiedenen Gründen (Leistungsgarantie, Debugbarkeit, Threadsicherheit, Kontrolle) von Boost und STL abweichen.
Kaj
42
Und 99% der Statistiken sind erfunden.
Gewinnspiel
Ich denke, es sollte eine Art Regel sein, alle Statistiken zu zitieren.
Matt Jensen
3

Ich glaube nicht, dass irgendjemand C heutzutage ausschließlich verwendet, es wird normalerweise mit einer höheren Sprache gemischt.

Das Programmieren in C hat einige Vorteile gegenüber dem Programmieren in C ++. C ++ kann viele Dinge unter der Haube tun, die für den Benutzer unsichtbar sind, was die Leistung beeinträchtigen kann, wenn Sie nicht vorsichtig sind. C ++ kann auch schrecklich sein, wenn es um die Cache-Nutzung geht, was wiederum Ihre Leistung beeinträchtigen kann.

Daher kann es einige Vorteile bringen, die leistungskritischen Teile eines Spiels in einer C-ähnlichen Art und Weise zu schreiben, anstatt in einer traditionellen C ++ Art und Weise. Ich habe in den letzten Jahren noch nie von jemandem gehört, der tatsächlich ein ganzes Spiel in C geschrieben hat.

Auf einigen Plattformen wie dem iPhone kann die Verwendung von C ++ die ausführbare Größe um einen bestimmten Teil der Kilobyte erhöhen (ich habe leider vergessen, wie viel). Dies ist ein Grund, warum einige iPhone-Entwickler ihren Code in einer Mischung aus C und Objective schreiben -C.

Sander van Rossen
quelle
3

Ich gebe Ihnen noch ein paar Gründe, warum es nicht zumutbar wäre, heute eine Game-Engine in C anstelle von C ++ zu schreiben: STL und BOOST.

Ich kann mir nicht vorstellen, wie es sich lohnen würde, eine weitere listImplementierung zu schreiben , wenn Sie sich auf Code verlassen könnten, der sofort funktioniert (und den Sie nicht schreiben müssen!).

Loris
quelle
1
Nutzt irgendein großes Studio Boost? Sogar die STL-Nutzung wird aufgrund der Portabilität immer noch diskutiert. Zumindest für Konsolenmotoren.
Schnittkalk
2
Persönlich verwende ich Boost.FunctionTypes für die C ++ / Lua-Interaktion (siehe gamedev.net/reference/programming/features/CPPLuaExport/… ) und die Boost-Zufallszahlenbibliothek für die einheitliche Zufallszahlengenerierung (für Partikelsysteme). Auch Boost.Foreach ist ordentlich. Übrigens, wen interessiert es, wenn große Studios BOOST nicht verwenden? Sie haben das Personal, um ihre eigenen STL-Bibliotheken von Grund auf neu zu schreiben.
Loris
1
Ja, aber stellen Sie auch fest, dass es ähnliche Bibliotheken auch für C gibt.
Jsimmons
2
Ich glaube, dass viele Leute Boost in Spielen einsetzen. Aber für viele von uns ist das alles andere als eine Anforderung (oder sogar wünschenswert).
Dan Olson
6
Leute, was du glaubst, ist irrelevant: Entweder du weißt oder du weißt nicht .
o0 '.
3

Es ist vernünftig, eine Game-Engine in C zu schreiben. Es ist schnell und kann auf mehrere Systeme portiert werden. Zum Beispiel könnten Sie für Android (mit der Verwendung des NDK) verwenden. Sie können es für das iPhone verwenden (Objective c ist nur eine Erweiterung von c). Sie können es auch für und unter Hauptbetriebssystemen wie Linux, Mac oder Windows verwenden. Wenn Sie sich mit c wohl fühlen, sollten Sie es versuchen!

Luke Taylor
quelle
2

Natürlich ist es vernünftig. Ich persönlich würde es nicht tun, und die meisten C-Fans, die ich kenne, schreiben einfach C-ähnlichen Code in CPP-Dateien. Aber die Sprachen sind ähnlich genug, wo es nicht wirklich wichtig ist.

Was den Grund angeht, warum sich jemand dafür entscheidet, liegt meiner Meinung nach hauptsächlich an der Anti-C ++ - Philosophie. Persönlich denke ich immer noch nicht, dass dies ein guter Grund ist, C gegenüber "C-style C ++" zu wählen. typedef struct craziness ist ein guter Grund, C aus dem Weg zu gehen, und es gibt eine Reihe weiterer Gründe.

Leider sind C und C ++ beide ziemlich schreckliche Sprachen, wenn wir uns darauf beschränken. Das ist einer der Gründe, warum die Leute in den letzten Jahren versucht haben, einen Großteil ihres Codes in Skripten zu schreiben.

Wenn Sie nach Beispielen für Personen suchen, die in C arbeiten, können Sie id ignorieren, wenn ich mich erinnere, dass sie C vor langer Zeit verlassen haben. Cryptic Studios (Star Trek Online) entwickeln die gesamte Engine jedoch in C. Soweit ich das beurteilen kann, liegt es mehr an der Philosophie als an einem greifbaren Vorteil.

Dan Olson
quelle
0

Ja und nein. Ja, ich habe es vor ein paar Jahren getan, aber ich brauchte mein Spiel, um es in 3D auf einem 64-Bit-Remoteserver unter Unix (nicht Linux) mit Spielern auf dummen Terminals auszuführen. Es war nicht trivial. C kann nett sein, wenn Sie LUA integrieren wollen, aber ich habe schließlich Lua dazu gebracht, in C ++ zu arbeiten, also würde ich sagen, dass es möglich ist, aber es nicht tun.

Jeff
quelle
0

Darf eine mögliche gute Antwort "beide verwenden" sein?

Als ich hörte, dass panda3d-Projekte optimiert werden könnten, um Engpässe entweder mit Cython zu beseitigen oder diese Teile neu zu kodieren.

Die meisten Teile, die optimiert werden müssen, sind Teile mit vielen Iterationen und Verschachtelungen oder mit vielen numerischen Berechnungen. Daher gehe ich davon aus, dass ein fairer Kompromiss darin besteht, beide Sprachen mit C zu verwenden für Teile, die viel Low-Level-Programmierung enthalten, sodass Sie die C ++ - Sprache für den Teil, der Geschwindigkeit benötigt, und C ++ für den Rest des Spiels nicht missbrauchen können.

Idealerweise erledigen Sie den schnellen Teil der Engine unter Berücksichtigung des hohen Levels und verwenden dann eine Skriptsprache oder C ++, die viel weniger Nest / Loops verwenden.

Natürlich könnten Sie niemals eine solche Engine entwickeln, die für alle Spieleentwickler geeignet wäre, es sei denn, Sie widmen Ihre Engine einer bestimmten Art von Spiel ...

Aber halte meinen Rat nicht für selbstverständlich, da ich weder ein erfahrener Spieleentwickler noch ein erfahrener Entwickler bin. Ich denke, C zwingt Sie, schnellen Code zu schreiben, während Sie guten und schnellen C ++ - Code für ein Projekt schreiben, das so groß wie ein Spiel ist ist eine andere Sache ...

jokoon
quelle
0

C hat für John Carmack gearbeitet , mit C können Sie viele Vorteile erzielen, aber bis Sie dorthin gelangen, um von ihnen zu profitieren, kann es eine Weile dauern.

Hier finden Sie eine Liste der Spiele-Engines, von denen einige in C geschrieben sind. Vielleicht können Sie anhand des Quellcodes einige Einblicke in die Funktionsweise einer C-Spiele-Engine gewinnen.


quelle
0

C-Code ist normalerweise gültiger C ++ - Code.

Die Hauptprobleme mit C ++ sind die falsche Verwendung ( Linus Torvalds hasst es aus diesem Grund , er hatte auch einige andere Probleme mit der Portabilität von Bibliotheken und so weiter. Er arbeitet auf Betriebssystemebene und muss in der Lage sein, Dinge nach dem Zufallsprinzip auszuführen Chip da draußen).

Zum Beispiel gibt es fast keinen Vorteil, ein cstyle-Array [] gegenüber einem c ++ std :: vector <> (oder einem ähnlichen Container) zu verwenden.

Die Vektoren sind typsicher und können auf Grenzen geprüft werden (Sie können entweder mit get () oder [] auf Elemente zugreifen, auch wenn Sie die Methode array checked nicht verwenden, können Sie dennoch die Größe abfragen, anstatt sie mit dem Zeiger zu verschieben).

Vektoren können jedoch langsamer sein, wenn Sie beispielsweise die Standardgröße im Konstruktor nicht deklarieren. Das Hinzufügen von Dingen zu einem Vektor kann zu Verlangsamungen führen, wenn die Größe geändert werden muss. C ++ 11 bietet auch viele Vorteile wie die einheitliche Initialisierung (Sie können jetzt Vektoren mit derselben Syntax deklarieren und initialisieren) und es gibt Verschiebungskonstruktoren, mit denen Sie das Kopieren vermeiden können. Sie können sogar Ihre eigenen benutzerdefinierten Initialisierungen erstellen (wenn Sie aus irgendeinem Grund etwas anderes als malloc verwenden möchten).

Oder natürlich, wenn Sie die Größe ändern müssen, dann sind Vektoren immer noch einfacher zu handhaben, Sie müssen nicht mit malloc herumspielen, Dinge manuell kopieren und so weiter.

C ++ gibt Ihnen objektorientierten Code. Wenn es kompiliert wird, wird es genauso effizient sein, da es wirklich nur eine Abstraktion für Menschen ist, die mit dem Code arbeiten. Obwohl Dinge wie Konstruktoren die Objekterstellung verlangsamen können. Sie benötigen jedoch entweder den Konstruktor, um die Standardwerte festzulegen, oder Sie können Objekte auf andere Weise initialisieren, ohne den Konstruktor zu verwenden (indem Sie die () weglassen).

Aber die Objektorientierung erleichtert das Programmieren von Spielen erheblich . Spiele beschäftigen sich oft mit Objekten.

David C. Bishop
quelle