Compitiendo con C ++ para la programación de juegos

21

Tengo curiosidad por saber por qué C ++ es tan popular para el desarrollo de juegos y no por otros lenguajes. Sé que puedes crear un código muy rápido con él, pero ¿qué es exactamente lo que lo hace popular?

¿Es solo porque es rápido? ¿Es alguna otra característica en el lenguaje, como el paradigma OO o la portabilidad? ¿Se debe a todas las bibliotecas que se han creado con el tiempo? ¿O alguna combinación de todas estas (y otras) razones?

Si alguien pudiera informarme sobre esto, estaría muy feliz. :-)

KasMA1990
fuente
77
La velocidad es razón suficiente para mí, especialmente porque las quejas de todos sobre el idioma realmente no tienen sentido para mí.
Benjamin Lindley
Una suposición rápida: la mayoría de los juegos están escritos para Windows. Los lenguajes C y C ++ han sido muy compatibles con Microsoft. Y finalmente se prefiere C ++ debido a la OOP y la metaprogramación de plantilla.
@ Matt Gracias, no sabía que existía. ¿Puedo mover el tema allí, o debería eliminar este y volver a crearlo allí?
Esto ya se ha pedido varias veces.
Zan Lynx
1
@Benjamin: Entonces me atrevo a decir que no has escrito lo suficiente en C ++, o que nunca has usado un lenguaje más expresivo como Python (o incluso C # con LINQ). Sin embargo, incluso si por alguna extraña razón prefiere escribir un código de 20 líneas para lo que muchos otros lenguajes pueden hacer en 1, la gramática extremadamente pobre de C ++ significa que los programas tardan mucho más en compilarse de lo que deberían, y las herramientas IDE adecuadas (refactorización, etc.) son más difíciles, si no imposibles, de crear.
BlueRaja - Danny Pflughoeft

Respuestas:

29

Numerosas razones:

  • Uno grande que te perdiste: es portátil, simplifica los puertos de tu motor de juego a iOS, XBOX, PS3, lo que sea
  • Es rápido
  • Todos los SDK lo admiten de forma nativa
  • Muchas bibliotecas disponibles
  • Todos los que escriben juegos lo saben, por lo que es fácil contratar desarrolladores de juegos experimentados para su equipo.
  • Es trivial incrustar un lenguaje de script de motor de juego como Lua

fuente
Bien, gracias por sus respuestas a todos, creo que han cubierto todo lo que necesitaba. :-)
KasMA1990
14

Hay algunas razones que me gustaría mencionar además de lo que trajo @Graham.

  • Código heredado: muchos estudios tienen un montón de código C ++, según su mención de bibliotecas.
  • C ++ es realmente un ensamblador de alto nivel, y tiene acceso directo al hardware (tan directo como puede ejecutarse sobre un sistema operativo al menos) y es bastante rápido. Si lo desea, en C ++ puede soltar directamente en lenguaje ensamblador para el control del nivel de instrucción (no siempre es aconsejable, simplemente no es posible con Java, C #, Python, etc.)
  • DirectX y OpenGL admiten de forma nativa C ++, la mayoría de los otros lenguajes tienen "enlaces" a las bibliotecas subyacentes a través de capas intermedias, eso no quiere decir que no sean rápidos o que no puedan hacer muchas de las mismas cosas, pero agrega una capa de software entre tu juego y el hardware
  • Como @Graham menciona, muchos programadores lo saben, por lo que es fácil encontrar desarrolladores experimentados, y también es bastante portátil, en comparación con C #, que está atascado en .NET Framework (hay Mono, pero generalmente va un poco por detrás de la implementación de Microsoft .)
Nate
fuente
¿No te refieres a bajo nivel?
jhocking
55
C ++ es un low-levellenguaje; pero un high-levelensamblador, IMO.
Nate
3
Estoy en desacuerdo. C ++ es un lenguaje de alto nivel, con la función integrada de recurrir a C (que es un lenguaje de bajo nivel).
foo
77
C ++ es un lenguaje de alto nivel, al igual que C. El ensamblaje es de bajo nivel. Ahora, C ++ tiene un nivel más alto que C, al igual que C # es más alto que C ++ y Ruby / Python son más altos que C #.
AA Grapsas
44
¿Por qué el código heredado debe ser obsoleto (no depreciado)? "Código heredado" solo significa que es antiguo, no es que sea malo.
8

La velocidad bruta es la razón principal, pero en realidad no es una decisión o una decisión, por lo que muchas compañías de juegos están comenzando a usar otros idiomas para partes del juego. Ciertas tareas requieren que la computadora funcione lo más rápido posible (p. Ej., Rutinas de representación central), pero muchas tareas en el código de juego no tienen que ejecutarse tan rápido (p. Ej., Abrir la puerta cuando el jugador hace clic), lo que significa que es inteligente usar un lenguaje mucho más simple (y por lo tanto más rápido para escribir programas) para esas partes. Es por eso que muchos motores de juegos están escritos en C ++ pero incorporan un lenguaje de script como Lua para escribir código de juego.

Lo difícil de entender es que al elegir lenguajes de programación hay una compensación general entre la eficiencia para la computadora y la eficiencia para el programador. Es decir, ¿qué es más importante para usted, qué tan rápido la computadora ejecuta el código o qué tan rápido el programador escribe el código?

jhocking
fuente
3

En C ++ puede asignar variables locales que desaparecen una vez que finaliza la función. Por lo general, estos se asignan en una pila.

Las variables de pila no contribuyen a los problemas de asignación de memoria dinámica de fragmentación y sobrecarga. Asignar espacio en la pila es rápido y fácil (solo ajustando un puntero). La asignación de memoria dinámica generalmente implica buscar en un contenedor un bloque de memoria adecuado, marcar la memoria y luego etiquetarla como ocupada. La desasignación implica agregar el bloque de memoria a un contenedor y posiblemente fusionarlo con los bloques existentes. Mucho más gastos generales que simplemente cambiar un puntero.

Java y C # asignan memoria dinámicamente, excepto los tipos primitivos. Estos lenguajes dependen de un entorno de tiempo de ejecución que marcará una variable para eliminar, luego ejecutará un recolector de basura a intervalos aleatorios (no programados) para recuperar la memoria. En general, el programador no tiene control sobre cuándo se etiquetará la variable para su eliminación ni cuándo se recuperará (la recuperación de la memoria utilizada es un tema avanzado que la mayoría de los programadores de C ++ y Java no experimentan).

La velocidad de C ++ se debe principalmente a su traducción directa a código ejecutable. Java y C # se compilan en un código intermedio que luego es interpretado por una máquina virtual. En general, los idiomas interpretativos tienen un rendimiento más lento que los idiomas traducidos directamente.

Thomas Matthews
fuente
1
-1 (si pudiera): las primitivas locales se asignan en la pila tanto en Java como en C #, y en C # se puede crear una pila asignada structs. Más aún, el aumento extremadamente pequeño de la velocidad que esto te proporciona no es suficiente para justificar un idioma sobre el otro. @Graham Perks afirma la verdadera razón: es lo que se espera que sepan los desarrolladores de juegos, por lo que es lo que aprenden los nuevos desarrolladores de juegos y para qué nuevos SDK están destinados. Hay un montón de idiomas (ej. Va), que son igual de rápido o más rápido, y no casi tan incómodo para escribir.
BlueRaja - Danny Pflughoeft
C ++ no es muy bueno en la asignación de la pila; de hecho, es muy difícil asignar objetos compatibles con STL en la pila. Por ejemplo, el último motor grande en el que trabajé fue en C, y teníamos una cadena que se podía iniciar en la pila en un tamaño fijo (generalmente 1K). Si creció más allá, se trasladó al montón de forma transparente. Puede hacer algunas cosas similares con los asignadores personalizados std :: string en C ++, pero el código es mucho más complicado de corregir.
1
@ Joe Wreschnig: C ++ es excelente en la asignación de la pila, simplemente volcar una lista de lenguaje ensamblador. Sin embargo, la mayoría de los proveedores de compiladores no asignan una gran cantidad de memoria a la pila. Una comprensión común de los programadores experimentados de C ++ es que los objetos enormes se asignan dinámicamente (montón), no el almacenamiento local (pila). Los objetos enormes en la pila pueden invadir el montón en algunas plataformas a medida que la pila y el montón crecen uno hacia el otro.
Thomas Matthews
1
Una comprensión común de los programadores de C ++ más experimentados, en particular los de las consolas de juegos, es que todo lo que no desbordará la pila está asignado o preasignado. C facilita esto porque el asignador no es parte del tipo estructural del objeto. Esto también hace posible liberar algo incorrectamente, pero en mi experiencia ese es un problema raro en comparación con alguien que está arruinando implementaciones / compatibilidad de asignadores compatibles con stdlib. También hay algunos trucos con la colocación nueva, pero de nuevo, eso es más complicado que el equivalente en C.
2
No. El beneficio de velocidad de C ++ se debe a su capacidad de usar su propio administrador de memoria personalizado para las asignaciones de almacenamiento dinámico . Cada idioma cuerdo asigna locales en la pila.
importa
3

Los juegos se escribieron una vez en lenguaje de máquina, porque tenían un hardware exótico para el que no había compilador. El hardware también carecía de características que los programadores de C dan por sentado, como la matemática de enteros de 16 bits eficiente.

Una vez que los juegos se instalaron en hardware conocido, los compiladores de C estuvieron disponibles y en poco tiempo todos los juegos se escribieron en C.

C ++ parecía una buena idea a la vez, y la mayoría de los juegos son C ++ en la actualidad, pero los ingenieros ahora están murmurando acerca de un regreso a C, y eso podría suceder. Me encantaría trabajar en un juego en C, y también lo harían muchos compañeros de trabajo. No hay ninguna característica nueva en C ++ que creo que mejore los juegos.

Parece que ahora las computadoras son 1000 veces más rápidas que hace unos años, un lenguaje de alto nivel reduciría el tiempo de desarrollo ($) haciendo que C sea obsoleto.

Esto no ha sucedido porque los compradores de juegos saben que el hardware es 1000 veces mejor y quieren cambiar sus dólares por un juego que se ve y suena 1000 veces mejor. Esto elimina la holgura del sistema que consumiría un lenguaje de alto nivel.

Los requisitos de rendimiento en los juegos son brutales. Se debe representar un nuevo marco de gráficos en menos de 33 ms (¡o 16 ms!) Sin falta. Todo lo que hace el hardware debe tenerse en cuenta para que se pueda cumplir con este presupuesto. Cualquier lenguaje que suene y haga algo con el hardware que el programador no entienda o espere hará que sea muy difícil cumplir con este presupuesto. Este es un menos automático contra cualquier cosa de alto nivel.

Los programadores de juegos no solo trabajan en un lenguaje de bajo nivel, sino que también evitan las estructuras de datos de alto nivel y los algoritmos. Los juegos generalmente no tienen listas vinculadas y rara vez tienen árboles. Hay un movimiento para evitar punteros siempre que sea posible *. Cualquier algoritmo con más de O (N) tiempo u O (1) espacio tiende a no encontrar un uso amplio.

* Si un puntero no causa una pérdida de caché, ¿por qué gastar 32 bits para almacenarlo? Si un puntero causa una falla de caché, es mejor deshacerse de esa falta de caché.

bmcnett
fuente
1
"No hay ninguna característica nueva en C ++ que creo que mejore los juegos". Jajaja OOP? ¿Una clase humancon derivados playery enemy?
orlp
2
@nightcracker: Basic es una herencia que funciona bien en C; la relación que describe se implementa mejor utilizando has-a por razones de rendimiento y limpieza de todos modos.
3
Existe un consenso cada vez mayor de que las características de OOP de C ++ no son apropiadas para los juegos, porque estas características operan en supuestos que son hostiles para el rendimiento de la memoria caché.
bmcnett
Incluso si cree que C ++ no ofrece ventajas sobre C, seguramente debería reconocer que un retorno a C tampoco ofrece ventajas sobre C ++.
Dan Olson
@Dan Un regreso a C ofrece la ventaja de que las "mejores prácticas", como no usar plantillas u OOP, se aplican por errores en tiempo de compilación en lugar de perseguir a los programadores junior con un palo. Además, dado que el lenguaje es más simple, presumiblemente el compilador y el mantenimiento del depurador también son más baratos.
bmcnett
3

Todos los lenguajes de programación tienen fortalezas y debilidades en una variedad de factores. Ejemplos de estos factores son:

  • Velocidad en una plataforma particular
  • Uso de memoria en una plataforma particular
  • Qué funcionalidad expone más fácilmente
  • En qué plataformas existe
  • Qué consideraciones debe tener en cuenta un programador

Uno de los factores más importantes que le importa a un programador de juegos es el rendimiento. Quieren producir una experiencia interactiva, lo que significa que debe ser reactivo y capaz de generar la mayor cantidad posible de datos útiles (o interesantes). Desea saber cuánta salud tiene en cualquier momento y no quiere esperar. Y si haces clic en un botón, esperas que dispare un arma o que tu personaje salte cuando lo dices. Un pequeño retraso puede interferir con esta interactividad, por lo que necesita rendimiento.

Otro factor importante es preferir programar en el lenguaje del problema, en lugar del lenguaje de la implementación. Un programador de juegos quiere tratar con humanos, orcos y autos de carrera, no con el registro de memoria ED0. Todavía quieren la opción de sumergirse en los detalles de implementación si necesitan rendimiento, pero sería genial si en su mayor parte pudieran lidiar con el nivel de las entidades en su mundo de juego. Tienen suficiente para preocuparse por simular el mundo del juego sin tener que preocuparse siempre de cómo funciona una lista vinculada.

C ++ se ajusta muy bien a estos dos factores primarios. Puede obtener los beneficios de rendimiento del ensamblaje o el código C con la expresividad de los objetos. Para ver por qué esto es un ajuste natural para los juegos, compárelo con algunas otras opciones de idioma:

  • Asamblea: Esto es potencia bruta. Lo que escribes es básicamente lo que hace la CPU. Pero en cada etapa necesitas saber qué está pasando con los registros y el efecto de esto, y nunca se ven como las entidades en tu mundo de juego. El programador tiene que hacer la correspondencia mental de lo que hace su código versus lo que sucede en el juego. Esto puede ser una sobrecarga mental.
  • C: Aquí tenemos un buen rendimiento, pero podemos aprovechar la experiencia de los gurús para hacer cosas estándar (como asignar memoria, operar en cadenas y usar funciones matemáticas estándar). Aquí nos acercamos a la expresividad, pero el lenguaje lo obliga más o menos a centrarse en la implementación porque realmente solo puede operar con tipos de datos normales. Todo es realmente un char, un int o similar. Las estructuras, punteros y matrices pueden mantener las cosas juntas, pero aún tienen que pensar en lo interno.
  • Java: saltamos sobre C ++ y llegamos a Java. Java se aleja aún más de los detalles de implementación. De hecho, la mayoría de las veces no tienes acceso a los niveles inferiores. Java extrae gran parte de los detalles de implementación (por ejemplo, qué CPU o sistema operativo está utilizando) por la razón de que quiere ser multiplataforma. No puede acceder a los detalles porque no están allí. No programa para la computadora, programa para la plataforma (la plataforma Java, que existe en la mayoría de las computadoras). Además, Java tiene un lenguaje posiblemente mejor para tratar el lenguaje del problema que C ++. La compensación es que no puede optimizar para una computadora en particular. Si esto hace una diferencia práctica o no se reduce a los detalles del programa y la computadora.
  • Lenguaje de programación de juegos: Con esto quiero decir algo como UnrealScript , o lenguajes de programación personalizados atados a un motor de juego. En estos no tienes acceso al motor subyacente. Delegas consideraciones de rendimiento al motor, dejándote libre de preocuparte por hacer un juego. Es más fácil escribir el juego, más difícil optimizar tu rendimiento tú mismo.
  • Haskell (o su lenguaje oscuro favorito): cualquier lenguaje de programación completo de Turing es equivalente a cualquier otro. Entonces, si bien puedes escribir cualquier programa en cualquier idioma, haces compensaciones, algunas objetivas, otras subjetivas. Un lenguaje como Haskell está más enfocado en trabajar con un espíritu matemático. Los problemas a los que se dirige son algo diferentes a los problemas que se enfrentan en los juegos. No significa que no pueda o no deba usarse para juegos, simplemente no es fácil de usar.

El último punto es que algo de esto es histórico y político. Se han librado muchas guerras de llamas entre los diferentes lenguajes de programación. C #, por ejemplo, podría ser tan adecuado para el desarrollo de juegos, pero vino después de C ++. O a la gente no le gusta que sea de Microsoft. Algunas personas hicieron el cambio a C #, otras no. Algunas personas todavía programan juegos en BASIC, Pascal y C. Cualquiera sea el programa con el que se sientan cómodos, se apegarán. Los programadores de juegos se han sentido cómodos con C ++, posiblemente porque crecieron con C y C ++ y satisfacían sus necesidades. Si la industria de la informática se encuentra en un estado en el que el rendimiento y la aceptación de Java satisfacen a suficientes personas, entonces quizás Java sería el lenguaje de desarrollo de juegos estándar de facto.

BrettW
fuente
2

Legado e impulso.

Había una vez un código escrito en ensamblador para obtener el máximo rendimiento. A medida que aumentaba la potencia de cómputo, los lenguajes compilados se volvieron más viables y C ofrecía el mejor compromiso entre potencia y productividad, en un nivel muy básico que era poco más que un ensamblador de macros.

C ++ fue simplemente el sucesor natural de C. No desecha ningún código o conocimiento anterior, pero tiene el potencial de expandirse a nuevas metodologías. C ++ es en última instancia muy flexible, y aún no he visto un paradigma de diseño que no se pueda simular al menos en C ++, al tiempo que pueda mantener un control casi total sobre el rendimiento.

Simon Lacey
fuente
2

Si está desarrollando para las consolas, no tiene otra opción: los SDK profesionales solo vienen en sabores C ++. Por lo general, también tienen acceso C a la mayoría de las cosas.

Debido a que muchos desarrolladores son Consolas + PC, tiene sentido hacer todo el trabajo de su PC en el mismo idioma y compartir directamente la tecnología.

Debido a que ahí es donde vive la industria profesional, y la mayoría de todos quieren ser parte de eso, la mayoría de los programadores de juegos son programadores de C ++.

Debido a que todo eso sucede, la mayoría de los desarrolladores de motores también son desarrolladores de C ++, por lo que al evaluar motores de grado profesional, casi todas sus opciones serán C ++.

Todo es un gran motor autosustentable. Interrumpirlo requeriría algo más que un avance técnico.

Chris Subagio
fuente
2

FWIW: C # está ganando popularidad para el desarrollo de juegos. Ver la publicación del blog de Miguel de Icaza . Muy interesante lectura, en mi humilde opinión.


fuente
2
Como de costumbre, Miguel empuja sus tecnologías favoritas (generalmente marginales) mientras ignora las formas en que C # se ha convertido en un gran jugador en la industria, por ejemplo, XNA.
2

Aunque soy bastante anti-C, C y C ++, lo único que TIENEN que tienen otros pocos idiomas es el control total sobre la plataforma en la que se está ejecutando, puede estar seguro de lo que sucederá en todo momento, no GC, sin problemas técnicos.

Esto no es tan importante en estos días, pero puede ser para plataformas con poca potencia.

En PC / Mac / Linux es probablemente el lenguaje menos portátil que encontrarás en estos días, y el bono de velocidad ya no es una gran diferencia: Minecraft (Java) es fluido y funciona en plataformas bastante mínimas (y cualquier sistema operativo) con un solo ejecutable: todavía no he visto una aplicación C / C ++ indi de baja mano de obra con tanta funcionalidad y pocos errores, y mucho menos trabajar en tres plataformas.

Entonces, en este punto, diría que la mayor parte es inercia y la concepción de que los juegos reales siempre se hacen en C / C ++, aunque la capacidad de "portar" a iPhone y consolas es significativa (aunque estoy bastante seguro de la interfaz de usuario de los juegos requiere MUCHO esfuerzo para portar, excepto entre Windows y XBox).

Bill K
fuente
1
Oh, no sé si solo es importante para las plataformas "con poca potencia". La otra forma de ver esto es que los juegos siempre están a la vanguardia del rendimiento en cualquier plataforma: cualquier potencia nueva se engulle de inmediato. Si hablamos de desarrollo profesional de juegos, el rendimiento es la principal preocupación: no escribes Unreal sin maximizar cada último ciclo que la máquina tiene para ofrecer. Cada; soltero; ciclo. En todos los niveles, desde el motor de gráficos y el acceso al disco hasta el bucle de la interfaz de usuario.
Chris Subagio
@Chris: La mejor manera que he encontrado para describirlo a los programadores que no son de juegos es que los juegos son un dominio donde la velocidad es una ventaja competitiva. Si su procesador de textos se inicia en 5 segundos donde MS Word toma 10, o se refluye en 0.1 segundos donde Word toma 0.2, eso no tiene valor. Pero si su juego puede generar incluso un 10% más de fragmentos o mostrar incluso un personaje más detallado, eso puede ser una gran ventaja competitiva.
Entonces, ¿no sería una tontería codificar en otra cosa que no sea el ensamblaje? Ciertamente sería al menos un 10% más rápido. Hay un punto en el que hace un llamado para cambiar el rendimiento por mantenimiento y velocidad de desarrollo. Generalmente ese punto es C ++ en estos días. Sería bueno si la capacidad de ir multiplataforma como Minecraft tuviera más peso.
Bill K
Ah, pero es una falacia que la codificación en el ensamblaje sea más rápida: los chips actuales son lo suficientemente complejos como para que un programador supere constantemente a un compilador. Solo en dominios más restringidos como las SPU en la PS3, los bucles físicos internos y los sombreadores en las GPU todavía tienen claras ventajas. De hecho, C ++ es actualmente el punto óptimo, con la advertencia de que OOP no siempre es la mejor opción: la discusión en curso de Struct of Arrays vs Array of Structs no es exactamente una discusión de lenguaje, pero C ++ claramente lo lleva a AoS naturalmente; A veces ... realmente solo quieres C.
Chris Subagio
El paso en la eficiencia del programador entre el ensamblador y C / C ++ también es un orden de magnitud mayor que el paso en la eficiencia del programador entre C y C ++, o C ++ y C # / Java. Fred Brooks señaló esto hace 25 años.