¿Es razonable escribir un motor de juego en C? [cerrado]

53

Aunque C ++ parece ser el rey, por lo que me han dicho, C todavía se usa ampliamente en los juegos, especialmente en las consolas. Sin embargo, ¿sería irrazonable escribir un motor de juego completo en C hoy? ¿Cuáles son, si las hay, algunas ventajas que tiene C sobre C ++? ¿Por qué alguien querría usar C sobre C ++?

Slurps Mad Rips
fuente
1
Los juegos de consola usan c ++ FYI!
Alan Wolfe
De hecho, creo que C sería más fácil escribir juegos en una cierta escala, digamos decenas de miles de LOC, más o menos, principalmente porque te permite concentrarte en bits y bytes sin tipos de datos complejos y construye súper rápido en comparación con C ++. Pero después de una cierta escala (por ejemplo, llegar a cientos de miles de LOC), comenzaría a querer llegar a C ++ donde realmente comenzaría a querer tipos de datos complejos, más seguridad de tipos, posiblemente excepciones, plantillas, y aún más grande en escala (digamos millones), para que otras cosas que no sean C ++ se combinen con el código C y C ++.
C también tiene la ventaja adicional de ser ampliamente portátil incluso para ABI, por lo que se vuelve bastante fácil tomar su código C existente y luego comenzar a usarlo en otros idiomas desde, por ejemplo, un FFI. C ++ es un poco más incómodo con el cambio de nombre, la incapacidad para cruzar con seguridad los límites del módulo, las repeticiones de vtable no son las mismas en los compiladores, las implementaciones de biblioteca estándar que difieren entre los proveedores, etc. En general, encuentro que las bibliotecas C que escribo duran más sin necesidad de cambios y pasa de moda, aunque lleva más tiempo escribir algo de escala con él.

Respuestas:

49

Sin embargo, ¿sería irrazonable escribir un motor de juego completo en C hoy?

Es razonable, pero la pregunta es ¿qué te compra? Es probable que no necesite la extrema portabilidad que ofrece C, y es una pena renunciar a todas las características que ofrece C ++ a menos que esté realmente filosóficamente en su contra.

¿Cuáles son, si las hay, algunas ventajas que tiene C sobre C ++?

¿Mejor tiempo de compilación?

¿Por qué alguien querría usar C sobre C ++?

Creo que es principalmente una elección estética. A muchas personas les gusta C porque es simple y mínimo y se siente limpio. C ++ tiene muchas características agradables (solo los espacios de nombres hacen que valga la pena usarlo), pero también es grande y desordenado.

munificente
fuente
3
Hasta Id Tech 4
óptico
99
@ Josh: ¿Más fácil de depurar? Los programas C son notoriamente difíciles de depurar, en gran parte debido a los punteros y la administración de memoria. Los programas de C ++ (cuando se usan expresiones idiomáticas de programación de C ++ verdaderas, que tienden a evitar punteros y administración de memoria siempre que sea posible) son varios órdenes de magnitud más fáciles de depurar.
BlueRaja - Danny Pflughoeft
14
C puede ser entendido por simples mortales. C ++ parece tener muchas características y casos extremos que los programadores experimentados conocen incluso después de una década de usarlo todos los días para vivir.
Jari Komppa
13
C ++ es un gran lenguaje, pero su temible reputación se extiende principalmente por personas que acaban de leer historias de terror y no se han tomado el tiempo para aprenderlo. Hay mucho que aprender, pero obtienes mucho valor a cambio de eso. C ++ te permite expresar muchas cosas que C simplemente no puede.
munificent
2
@ BlueRaja-DannyPflughoeft #define malloc(x) my_malloc(x) #define free(x) my_free(x)y ahora está depurando la memoria. Con C ++ nunca se sabe qué se asignará cuando, porque hay muchas maneras de asignar memoria (nuevos, malloc, constructores de clases, etc.)
YoYoYonnY
59

He trabajado mucho con un motor de juego puro-C que ha enviado varios productos, por lo que es absolutamente posible. Aquí está mi experiencia personal trabajando en motores C vs C ++:

  1. El uso de estructuras Pure-C le permite aprovechar el conocimiento sobre la alineación de estructuras, y luego puede usar esta información para construir sus capas de serialización y persistencia de objetos. El motor con el que trabajé tenía algunos analizadores de encabezado simples que crearían automáticamente estos metadatos sobre las estructuras, e hizo triviales ciertos tipos de operaciones de datos. Analizar archivos de encabezado C ++ arbitrarios es esencialmente imposible, y tan pronto como agregue la herencia y las funciones virtuales, perderá la capacidad de saber exactamente dónde están las cosas en la memoria
  2. El tiempo de compilación es significativamente más corto porque puede mantener sus archivos de encabezado muy compactos y aprovechar las declaraciones directas de estructuras.
  3. La depuración puede mejorarse porque sin el uso de plantillas y herencia es muy fácil descubrir exactamente qué es un determinado objeto y qué está haciendo.

Todos estos beneficios también podrían lograrse con la misma facilidad usando un código restringido de C ++ que se abstiene de usar plantillas y herencia en objetos serializados, pero fue la decisión del CTO que sería más fácil hacer cumplir la simplicidad si los elementos más confusos de C ++ no fueran disponible.

Personalmente, creo que esto fue un poco extremo, ya que realmente eché de menos la capacidad de declarar sensatamente variables para bucles y los muchos usos completamente legítimos para la herencia. Pero, en realidad, no nos costó mucha productividad al final, considerando todo

Ben Zeigler
fuente
55
Realmente no hay nada que le impida implementar la herencia en C. Y si usa C99 puede declarar variables para bucles.
jsimmons
15
No estoy de acuerdo con el punto 3. Es tan fácil escribir código desordenado y difícil de depurar en C como en C ++. Una mejor depuración no es algo inherente al lenguaje C.
Dan Olson
77
Incluso el código limpio puede ser más difícil de entender en C ++: con sobrecarga, plantillas, funciones virtuales y excepciones, es mucho más difícil ver de un vistazo exactamente cuál será el flujo de control real.
Kylotan
66
@Dan: Simplemente por tener más cosas, C ++ es más difícil de depurar. Por supuesto, puede restringirse de usar cualquiera de esas cosas, en cuyo caso se vuelve tan fácil de depurar como C - porque se convierte en C.
Menos cosas es en realidad la razón por la que me gusta C. Por ejemplo, en CI solo puedo copiar bits y bytes con un memcpypara cualquier cosa porque el sistema de tipos no permite cosas como copiar ctors y dtors. Puedo escribir código sabiendo que no tendré que revertir los efectos secundarios en casi cualquier línea de código dado, ya que no puedo salir implícitamente de una función a menos que regrese explícitamente; no hay excepciones lanzadas. Todo esto hace que la escritura de estructuras de datos sea mucho más fácil: en C ++ solo escribir un estándar cumple vectormucho tiempo, especialmente si desea hacerlo ...
18

Estoy reescribiendo un motor de juego 2D escrito en C ++ y Lua en C y Lua. Hasta ahora la experiencia ha sido bastante buena. Obviamente, hacer operaciones de vectores y matrices no termina tan bien en C. Pero aparte de eso, he encontrado la experiencia bastante refrescante después de pasar más de 10 años como desarrollador de C ++.

C tiene una serie de ventajas sobre C ++:

  1. El compilador se asegurará de que no se ejecute ningún código en el tiempo de inicialización estático. Eso hace que sea completamente seguro asignar estáticamente datos globales como cadenas utilizadas como claves, por ejemplo
  2. Transparencia. En la asignación de C o en la asignación o definición de una variable no se ejecutarán cargas de código. C ++ generará automáticamente constructores de copias para que tenga menos control sobre lo que se ejecuta al realizar la asignación.
  3. Una gran cantidad de depuración puede ser más fácil debido a que no se alteran los nombres de las funciones
  4. Por lo general, está bien usar memcpy en C, pero fácilmente causará problemas en C ++, porque los constructores de copias no se ejecutarán. Dado que memcpy es mucho más rápido que std :: copy que importa.

Aparte de eso, hay una serie de ventajas para entrar en la forma de pensar C. En C ++ a menudo me encuentro haciendo que las cosas estén un poco generalizadas y abstractas. En CI generalmente se eliminan cosas como los métodos get-set y, a menudo, se asignan previamente matrices de tamaño fijo en lugar de utilizar matrices dinámicas. A menudo termino con un código más corto y más fácil de depurar en C. Las estructuras de datos suelen ser más planas y fáciles de ver en un depurador.

Para ser justos, nunca haría una aplicación exclusivamente en C. La razón por la que funciona es que la combino con un lenguaje de nivel superior como Lua que puede complementar C muy bien, si C no es tan fuerte.

El software de identificación escribe que la mayoría de sus motores en CI creen, puede mirar Volver al castillo Wolfenstein que fue escrito en C.

Escribí sobre algo de mi experiencia sobre la escalabilidad de C frente a C ++ y las desventajas del vector STL en comparación con las matrices simples.

Erik Engheim
fuente
11
Para su información, en cada caso que he verificado (que es, creo, darwin gcc y vc2008), std :: copy simplemente se compilará en una llamada a memcpy si ambos tipos son POD.
Sorteo el
3
Además, RE: STL vector frente a matrices simples, ¿por qué no usar las partes agradables del vector y usar punteros C normales en lugar de iteradores si no te gustan? Puedes simplemente hacer & myvector [N]. Es como lo mejor de ambos mundos, suponiendo que su código C haga la asignación de memoria de la misma manera. O, en busca de bucles, echa un vistazo a BOOST_FOREACH. Lo hace aún más simple que C.
Sorteo
1
Gracias por el consejo sobre std :: copy memcpy. No lo sabia. Cuando Alexandrescu trató esto hace algunos años, no era el caso. Acerca de los iteradores de C ++. Se trata principalmente de la filosofía, trato de programar cómo C ++ debía ser un programa tanto por el bien de las personas con las que trabajo como para aprovechar las características de C ++. Se hizo principalmente para señalar que algunas mejoras de C ++ como los contenedores STL no siempre son mejores que hacerlo a la antigua manera de C.
Erik Engheim el
7

Como alguien más señaló, C ++ ofrece la ventaja de grandes hombros sobre los que puedes pararte (BOOST, STL, etc.). Al final, es una elección personal, pero elegiría C ++ debido a los recursos disponibles. Si hay características en C ++ que no desea usar, no las use.

usuario266
fuente
1
Tenga en cuenta que el 99% de los motores de juegos comerciales e internos se alejan de Boost y STL por varias razones (garantía de rendimiento, depuración, seguridad del hilo, control).
Kaj
42
Y el 99% de las estadísticas están compuestas.
Sorteo el
Siento que debería ser una regla citar todas las estadísticas.
Matt Jensen
3

No creo que nadie use C exclusivamente en estos días, generalmente se combina con un lenguaje de nivel superior.

La programación en C tiene algunos beneficios sobre, por ejemplo, la programación en C ++. C ++ puede hacer muchas cosas invisibles para el usuario, lo que puede afectar el rendimiento si no tiene cuidado. C ++ también puede ser terrible cuando se trata del uso de la memoria caché, lo que de nuevo puede dañar su rendimiento.

Por lo tanto, puede traer algunos beneficios escribir las partes críticas de rendimiento de un juego en forma de C, en lugar de hacerlo en una forma tradicional de C ++. Sin embargo, nunca he oído hablar de nadie, en los últimos años, que haya escrito un juego completo en C.

En algunas plataformas, como el iPhone, el uso de C ++ puede aumentar el tamaño de su ejecutable con un cierto trozo de kilobytes (olvidé cuánto, lo siento), razón por la cual algunos desarrolladores de iPhone eligen escribir su código en una combinación de C y Objective -C.

Sander van Rossen
fuente
3

Te daré un par de razones más por las cuales no sería razonable escribir un motor de juego en C en lugar de C ++ hoy: STL y BOOST.

No puedo imaginar cómo valdría la pena escribir otra listimplementación más cuando pudieras confiar en el código que funciona de fábrica (¡y que no tienes que escribir!)

Loris
fuente
1
¿Algún gran estudio realmente usa boost? Incluso el uso de STL todavía está en debate, debido a la portabilidad. Al menos para motores de consola.
slicedlime
2
Personalmente, estoy usando Boost.FunctionTypes para la interacción c ++ / lua (vea gamedev.net/reference/programming/features/CPPLuaExport/… ) y la biblioteca de números aleatorios Boost para la generación uniforme de números aleatorios (para sistemas de partículas). Además, Boost.Foreach es ordenado. Por cierto, ¿a quién le importa si los grandes estudios no están utilizando BOOST? Tienen la mano de obra para escribir sus propias bibliotecas STL desde cero, yo no.
Loris
1
Sí, pero también date cuenta de que también hay bibliotecas similares para C.
jsimmons
2
Mucha gente usa el impulso en los juegos, creo. Pero está lejos de ser un requisito (o incluso deseable) para muchos de nosotros.
Dan Olson
66
Gente, lo que crees es irrelevante: sabes o no sabes .
o0 '.
3

Escribir un motor de juego en C es razonable. Es rápido y se puede portar a múltiples sistemas. Por ejemplo, podría usar para Android (con el uso del NDK). Podría usarlo para el iPhone (Objective c es solo una extensión de c). También puede usarlo para y para el sistema operativo principal, como Linux, Mac o Windows. Si te sientes cómodo con c, te sugiero que lo pruebes.

Luke Taylor
fuente
2

Por supuesto que es razonable. Yo personalmente no lo haría, y la mayoría de los fanáticos de C que conozco en realidad solo escriben código tipo C en archivos .cpp. Pero los idiomas son lo suficientemente similares a donde realmente no importa.

En cuanto a por qué alguien elegiría hacer esto, creo que se debe principalmente a la filosofía anti-C ++. Personalmente, todavía no creo que esta sea una buena razón para elegir C sobre "C-style C ++". La locura typedef struct es una razón suficiente para mantenerse alejado de C, y hay una serie de otros.

Lamentablemente, C y C ++ son lenguajes bastante terribles cuando lo hacemos. Esa es una razón por la que la gente ha estado tratando de hacer mucho de su código en script en los últimos años.

Si está buscando ejemplos de personas que trabajan en C, puede ignorar la identificación, ya que recuerdo haber leído que han abandonado C hace mucho tiempo. Sin embargo, Cryptic Studios (Star Trek Online) hace todo su desarrollo de motores en C. Por lo que puedo decir, sí, es por la filosofía más que por cualquier ventaja tangible.

Dan Olson
fuente
0

Si y no. Sí, lo he hecho hace unos años, pero necesitaba que mi juego se ejecutara en 3D en un servidor remoto de 64 bits Unix (no Linux) con los jugadores en terminales tontas. No fue trivial. C puede ser bueno si quieres integrar LUA pero finalmente conseguí que lua trabaje en C ++, así que diría que sí, es posible pero no lo hagas.

Jeff
fuente
0

¿Puede una posible buena respuesta ser "usar ambos"?

Como escuché que los proyectos de panda3d podrían optimizarse, eliminando el cuello de botella ya sea usando algún cython o recodificando esas partes.

La mayoría de las veces, las partes que deben optimizarse son la parte con muchas iteraciones y anidamiento o con mucha computación numérica, por lo que mi (salvaje) suposición es que un compromiso justo sería usar ambos lenguajes, usando C para partes que incluyen una gran cantidad de programación de bajo nivel, por lo que no puede hacer un mal uso del lenguaje C ++ para la parte que necesita velocidad, y C ++ para el resto del juego.

Idealmente, debe hacer la parte rápida del motor teniendo en cuenta el alto nivel, y luego usar un lenguaje de script o C ++ que usará mucho menos nido / bucles.

Por supuesto, nunca podrías hacer un motor que se ajuste a todos los juegos que los desarrolladores tendrían que hacer, excepto si dedicas tu motor para un tipo especial de juego ...

Pero no dé por sentado mi consejo, ya que no soy un desarrollador de juegos experimentado ni un desarrollador experimentado ... Creo que C lo obliga a escribir código rápido, mientras escribe código C ++ bueno y rápido para un proyecto tan grande como un juego es una cosa diferente ...

jokoon
fuente
0

C funcionó para John Carmack , puede obtener muchas ventajas al usar C, pero hasta que llegue allí para beneficiarse de ellos, puede llevarle un tiempo.

Aquí puede encontrar una lista de motores de juegos, algunos de ellos escritos en C, tal vez pueda obtener algunas ideas sobre cómo hacer un motor de juegos en C revisando su código fuente.


fuente
0

El código C es normalmente un código C ++ válido.

Los principales problemas con C ++ lo están usando incorrectamente ( Linus Torvalds lo odia por esta razón , también tuvo otros problemas con la portabilidad de la biblioteca y, por lo tanto, está trabajando a nivel de sistemas operativos y tiene que poder ejecutar cosas de forma aleatoria chip por ahí).

Por ejemplo, casi no hay ventaja en usar una matriz cstyle [] sobre un c ++ std :: vector <> (o contenedor similar).

Los vectores son seguros para los tipos y se pueden verificar los límites (puede acceder a los elementos usando get () o [], incluso si no utiliza el método de matriz comprobada, aún puede consultar el tamaño en lugar de cargarlo con el puntero).

Pero los vectores pueden ser más lentos si, por ejemplo, no declara el tamaño predeterminado en el constructor. También agregar cosas a un vector puede causar ralentizaciones si luego necesita un cambio de tamaño. C ++ 11 también agrega muchas ventajas, como la inicialización uniforme (ahora puede declarar e inicializar vectores usando la misma sintaxis) y hay constructores de movimiento que pueden permitirle evitar la copia. Incluso puede hacer sus propios inicializadores personalizados (si quisiera hacer algo más que usar malloc por alguna razón).

O, por supuesto, si necesita cambiar el tamaño de las cosas, entonces los vectores son aún más fáciles de hacer, no tiene que perder el tiempo con malloc, copiar manualmente las cosas, etc.

C ++ le proporciona código orientado a objetos. Cuando se compila, será igual de eficiente, ya que en realidad es solo una abstracción para los humanos que trabajan con el código. Aunque cosas como los constructores pueden ralentizar la creación de objetos. Pero necesitará que el constructor establezca los valores predeterminados o, de lo contrario, puede inicializar objetos sin usar el constructor (dejando de lado los ()).

Pero la orientación a objetos hace que programar juegos sea mucho más fácil. Los juegos a menudo tratan con objetos.

David C. Bishop
fuente