Competere con C ++ per la programmazione di giochi


21

Sono curioso di sapere perché C ++ sia così popolare per lo sviluppo di giochi e non per altre lingue. So che puoi creare un codice molto veloce con esso, ma cos'è esattamente che lo rende popolare?

È solo perché è veloce? È un'altra caratteristica del linguaggio, come il paradigma OO o la portabilità? È a causa di tutte le librerie che sono state create nel tempo? O una combinazione di tutti questi (e altri) motivi?

Se qualcuno mi potesse compilare su questo, sarei molto felice. :-)


7
La velocità è una ragione sufficiente per me, soprattutto perché le lamentele di tutti sulla lingua non hanno davvero senso per me.
Benjamin Lindley,

Una rapida ipotesi: la maggior parte dei giochi sono scritti per Windows. I linguaggi C e C ++ sono stati fortemente supportati da Microsoft. E infine il C ++ è preferito a causa della metaprogrammazione OOP e template.

@ Matt Grazie, non sapevo che esistesse. Posso spostare l'argomento lì o devo eliminare questo e ricrearlo laggiù?

Questo è già stato chiesto più volte.
Zan Lynx,

1
@Benjamin: Quindi oso dire che non hai scritto abbastanza in C ++ o che non hai mai usato un linguaggio più espressivo come Python (o persino C # con LINQ). Tuttavia, anche se per qualche pazza ragione preferisci scrivere un codice di 20 righe per quello che molte altre lingue possono fare in 1, la grammatica estremamente scarsa di C ++ significa che i programmi impiegano molto più tempo a compilare di quanto dovrebbero e strumenti IDE adeguati (refactoring, ecc.) sono più difficili, se non impossibili, da creare.
BlueRaja - Danny Pflughoeft

Risposte:


29

Numerose ragioni:

  • Uno grande che ti sei perso: è portatile, semplifica le porte del tuo motore di gioco su iOS, XBOX, PS3, qualunque cosa
  • È veloce
  • Tutti gli SDK lo supportano in modo nativo
  • Molte librerie disponibili
  • Tutti quelli che scrivono giochi lo sanno, quindi è facile assumere sviluppatori di giochi esperti per la tua squadra
  • È banale incorporare un linguaggio di scripting del motore di gioco come Lua

Bene, grazie per le risposte a tutti, avete coperto tutto ciò di cui avevo bisogno, penso. :-)
KasMA1990

14

Ci sono alcuni motivi che vorrei menzionare in aggiunta a ciò che @Graham ha sollevato.

  • Codice legacy - molti studi hanno un sacco di codice C ++, va alla tua menzione di librerie.
  • Il C ++ è davvero un assemblatore di alto livello e ha accesso diretto all'hardware (almeno diretto come si può eseguire su un sistema operativo almeno) ed è abbastanza veloce. Se vuoi, in C ++ puoi scendere direttamente nel linguaggio assembly per il controllo a livello di istruzione (non che sia sempre saggio, non è possibile con Java, C #, Python, ecc.)
  • DirectX e OpenGL supportano nativamente C ++, la maggior parte degli altri linguaggi ha "collegamenti" alle librerie sottostanti attraverso livelli intermedi, questo non vuol dire che non sono veloci o non possono fare molte delle stesse cose, ma aggiunge un livello di software tra il tuo gioco e l'hardware.
  • Come menziona @Graham, molti programmatori lo sanno, quindi è facile trovare sviluppatori esperti, ed è anche abbastanza portatile, rispetto a C # che è bloccato su .NET Framework (c'è Mono, ma generalmente è in ritardo di una generazione dietro l'implementazione di Microsoft .)

Non intendi di basso livello?
jhocking

5
C ++ è un low-levellinguaggio; ma un high-levelassemblatore, IMO.
Nate,

3
Non sono d'accordo. C ++ è un linguaggio di alto livello, con la possibilità di ricorrere al C (che è un linguaggio di basso livello).
foo,

7
C ++ è un linguaggio di alto livello, così come C. Assembly è di basso livello. Ora, C ++ ha un livello più alto di C, proprio come C # è più alto di C ++ e Ruby / Python sono più alti di C #.
AA Grapsas,

4
Perché il codice legacy dovrebbe essere deprecato (non ammortizzato)? "Codice legacy" significa solo che è vecchio, non che sia cattivo.

8

La velocità pura è la ragione principale, ma in realtà non è una delle due decisioni, quindi molte società di gioco stanno iniziando a usare altre lingue per parti del gioco. Alcune attività richiedono che il computer funzioni il più velocemente possibile (ad es. Routine di rendering di base) ma molte attività nel codice di gioco non devono essere eseguite così velocemente (ad es. Aprire la porta quando il giocatore fa clic su di esso), il che significa che è intelligente usare un linguaggio molto più semplice (e quindi più veloce per scrivere programmi) per quelle parti. Ecco perché molti motori di gioco sono scritti in C ++ ma incorporano un linguaggio di scripting come Lua per la scrittura di codice di gioco.

La cosa difficile da capire è che quando si scelgono i linguaggi di programmazione c'è un compromesso generale tra efficienza per il computer ed efficienza per il programmatore. Cioè, che è più importante per te, quanto velocemente il computer esegue il codice o quanto velocemente il programmatore scrive il codice?


3

In C ++ è possibile allocare variabili locali che scompaiono al termine della funzione. Di solito, questi sono allocati su uno stack.

Le variabili dello stack non contribuiscono ai problemi di allocazione dinamica della memoria di frammentazione e sovraccarico. Allocare spazio in pila è semplice e veloce (basta regolare un puntatore). L'allocazione dinamica della memoria di solito comporta la ricerca in un contenitore di un blocco di memoria adeguato, contrassegnando la memoria, quindi contrassegnandola come occupata. La deallocazione comporta l'aggiunta del blocco di memoria a un contenitore e la possibile fusione con blocchi esistenti. Molto più sovraccarico che semplicemente cambiare un puntatore.

Java e C # allocano la memoria in modo dinamico, ad eccezione dei tipi primitivi. Queste lingue dipendono da un ambiente di runtime che contrassegnerà una variabile da eliminare, quindi eseguirà un garbage collector a intervalli casuali (non programmati) per recuperare la memoria. In generale, il programmatore non ha alcun controllo su quando la variabile verrà taggata per l'eliminazione né su quando verrà recuperata (il recupero della memoria utilizzata è un argomento avanzato che la maggior parte dei programmatori C ++ e Java non sperimenta).

La velocità del C ++ è dovuta principalmente alla sua traduzione diretta in codice eseguibile. Java e C # vengono compilati in un codice intermedio che viene quindi interpretato da una macchina virtuale. In generale, le lingue interpretative sono più lente rispetto alle lingue tradotte direttamente.


1
-1 (se potessi) - le primitive locali sono allocate nello stack sia in Java che in C #, e in C # è possibile creare allocazioni in pila structs. Più precisamente, il estremamente estremamente piccolo aumento della velocità di questo reti non è quasi sufficiente a giustificare una lingua sull'altra. Il vero motivo è affermato da @Graham Perks: è ciò che gli sviluppatori di giochi dovrebbero sapere, quindi è ciò che apprendono i nuovi sviluppatori di giochi e a cosa sono destinati i nuovi SDK. Ci sono un sacco di lingue (es. Go), che sono altrettanto veloce o più veloce, e non quasi come scomodo da scrivere.
BlueRaja - Danny Pflughoeft

C ++ non è molto bravo nell'allocazione dello stack; infatti, è molto difficile allocare oggetti compatibili con STL nello stack. ad es. L'ultimo grande motore su cui ho lavorato era in C, e avevamo una stringa che si poteva iniziare in pila ad una dimensione fissa (di solito 1K). Se passava oltre si spostava in modo trasparente al mucchio. Puoi fare alcune cose simili con gli allocatori personalizzati std :: string in C ++, ma il codice è molto più complicato da ottenere.

1
@Joe Wreschnig: C ++ è eccellente nell'allocazione dello stack, basta scaricare un elenco di linguaggio assembly. Tuttavia, la maggior parte dei produttori di compilatori non alloca un'enorme quantità di memoria nello stack. Una comprensione comune dei programmatori C ++ esperti è che gli oggetti Enormi vengono allocati dinamicamente (heap) e non archiviazione locale (stack). Enormi oggetti sullo stack possono invadere l'heap su alcune piattaforme mentre stack e heap crescono l'uno verso l'altro.
Thomas Matthews,

1
Una comprensione comune dei programmatori C ++ più esperti, in particolare quelli sulle console di gioco, è che tutto ciò che non trabocca dallo stack viene assegnato allo stack o preallocato. C rende tutto più semplice perché l'allocatore non fa parte del tipo strutturale dell'oggetto. Questo rende anche possibile liberare qualcosa in modo errato, ma nella mia esperienza questo è un problema raro rispetto a qualcuno che rovina le implementazioni / compatibilità degli allocatori compatibili con stdlib. Ci sono anche alcuni trucchi con il posizionamento nuovo, ma di nuovo, è più complicato dell'equivalente in C.

2
No. Il vantaggio in termini di velocità di C ++ è dovuto alla sua capacità di utilizzare il proprio gestore di memoria scritto per allocazioni di heap . Ogni lingua sana alloca i locali in pila.
Nevermind,

3

Una volta i giochi venivano scritti in linguaggio macchina, perché avevano hardware esotico per il quale non esisteva un compilatore. L'hardware mancava anche di funzionalità che i programmatori C danno per scontate, come la matematica integer efficiente a 16 bit.

Una volta che i giochi si stabilirono su hardware familiare, i compilatori C diventarono disponibili e in breve tempo tutti i giochi furono scritti in C.

Il C ++ sembrava una buona idea in una volta, e la maggior parte dei giochi sono in C ++ oggi, ma gli ingegneri ora stanno borbottando sul ritorno al C, e questo potrebbe effettivamente accadere. Mi piacerebbe lavorare su un gioco in C, e così anche molti colleghi. Non ci sono nuove funzionalità in C ++ che penso migliorino i giochi.

Sembrerebbe che i computer siano 1000 volte più veloci rispetto a qualche anno fa, un linguaggio di alto livello ridurrebbe i tempi di sviluppo ($) rendendo C obsoleto.

Questo non è accaduto perché gli acquirenti di giochi sanno che l'hardware è 1000 volte migliore e vogliono scambiare i loro dollari con un gioco che sembra e sembra 1000 volte migliore. Ciò elimina dal sistema il gioco che un linguaggio di alto livello consumerebbe.

I requisiti di prestazione nei giochi sono brutali. Un nuovo fotogramma grafico deve essere eseguito senza errori in meno di 33 ms (o 16 ms!). Tutto ciò che fa l'hardware deve essere contabilizzato, in modo che questo budget possa essere soddisfatto. Qualsiasi lingua che si spegne e fa qualcosa con l'hardware che il programmatore non capisce o non si aspetta renderà molto difficile rispettare questo budget. Questo è un aspetto negativo automatico contro qualsiasi cosa di alto livello.

I programmatori di giochi non solo lavorano in un linguaggio di basso livello, ma evitano anche strutture e algoritmi di dati di alto livello. I giochi in genere non hanno elenchi collegati e raramente hanno alberi. C'è un movimento per evitare i puntatori quando possibile *. Qualsiasi algoritmo con più del tempo O (N) o spazio O (1) tende a non trovare largo uso.

* Se un puntatore non causa un errore nella cache, perché spendere 32 bit per memorizzarlo? Se un puntatore causa un errore nella cache, è meglio eliminare tale errore.


1
"Non ci sono nuove funzionalità in C ++ che penso migliorino i giochi." LOL? OOP? Una classe humancon derivati playere enemy?
orlp,

2
@nightcracker: Basic is-a eredity funziona benissimo in C; la relazione che descrivi viene implementata meglio usando has-a per motivi di prestazioni e pulizia.

3
Vi è un crescente consenso sul fatto che le funzionalità OOP di C ++ non siano appropriate per i giochi, poiché queste funzionalità operano su presupposti ostili alle prestazioni della cache.
bmcnett,

Anche se ritieni che C ++ non offra vantaggi rispetto a C, dovresti sicuramente riconoscere che un ritorno a C non offre vantaggi rispetto a C ++.
Dan Olson,

@Dan Un ritorno a C offre il vantaggio che "best practice" come non usare template o OOP sono imposte da errori di compilazione piuttosto che inseguire i programmatori junior con un bastone. Anche dal momento che il linguaggio è più semplice, presumibilmente, anche la manutenzione del compilatore e del debugger è più economica.
bmcnett,

3

Ogni linguaggio di programmazione presenta punti di forza e di debolezza in una serie di fattori. Esempi di questi fattori sono:

  • Velocità su una piattaforma particolare
  • Utilizzo della memoria su una piattaforma particolare
  • Quale funzionalità espone più facilmente
  • Su quali piattaforme esiste
  • Quali considerazioni deve prendere in considerazione un programmatore

Uno dei fattori più importanti a cui un programmatore di giochi tiene bene è la prestazione. Vogliono produrre un'esperienza interattiva, il che significa che deve essere reattivo e in grado di produrre quanti più dati utili (o interessanti) possibili. Vuoi sapere quanta salute hai in qualsiasi momento e non vuoi aspettare. E se fai clic su un pulsante, ti aspetti che una pistola spari o che il tuo personaggio salti quando lo dici. Un piccolo ritardo può interferire con questa interattività, quindi hai bisogno di prestazioni.

Un altro fattore importante sta preferendo programmare nella lingua del problema, piuttosto che nella lingua dell'implementazione. Un programmatore di giochi vuole trattare con umani, orchi e macchine da corsa, non con il registro di memoria ED0. Vogliono ancora l'opzione di immergersi nei dettagli dell'implementazione se hanno bisogno di prestazioni, ma sarebbe bello se per la maggior parte fossero in grado di affrontare il livello delle entità nel loro mondo di gioco. Hanno abbastanza da preoccuparsi di simulare il mondo di gioco senza preoccuparsi sempre di come funziona un elenco collegato.

Il C ++ si adatta molto bene a questi due fattori principali. È possibile ottenere i vantaggi in termini di prestazioni dell'assembly o del codice C con l'espressività degli oggetti. Per capire perché si adatta perfettamente ai giochi, confrontalo con alcune altre opzioni di lingua:

  • Montaggio: questo è potere crudo. Quello che scrivi è fondamentalmente quello che fa la CPU. Ma in ogni fase devi sapere cosa sta succedendo con i registri e l'effetto di questo, e non assomiglia mai alle entità nel tuo mondo di gioco. Il programmatore deve fare la corrispondenza mentale di ciò che fa il suo codice rispetto a ciò che accade nel gioco. Questo può essere piuttosto un sovraccarico mentale.
  • C: Qui abbiamo buone prestazioni, ma possiamo sfruttare l'esperienza dei guru per fare cose standard (come allocare memoria, operare su stringhe e usare funzioni matematiche standard). Ci avviciniamo maggiormente all'espressività qui, ma il linguaggio ti costringe più o meno a concentrarti sull'implementazione perché puoi davvero operare solo su normali tipi di dati. Tutto è davvero un personaggio, un int o simili. strutture, puntatori e matrici possono tenere insieme le cose, ma devono ancora pensare agli interni.
  • Java: scavalchiamo C ++ e arriviamo a Java. Java si allontana ulteriormente dai dettagli di implementazione. In effetti, la maggior parte delle volte non si ottiene l'accesso ai livelli inferiori. Java estrae gran parte dei dettagli dell'implementazione (ad es. Quale CPU o sistema operativo stai utilizzando) per il motivo che vuole essere multipiattaforma. Non è possibile accedere ai dettagli perché non sono presenti. Non programmi per il computer, programmi per la piattaforma (la piattaforma Java, che esiste sulla maggior parte dei computer). Inoltre, Java ha un linguaggio probabilmente migliore per gestire il linguaggio del problema rispetto al C ++. Il compromesso è che non è possibile ottimizzare per un determinato computer. Se questo fa una differenza pratica o no dipende dalle specifiche del programma e del computer.
  • Linguaggio di scripting di gioco: con questo intendo qualcosa come UnrealScript , o linguaggi di script personalizzati collegati a un motore di gioco. In questi non hai accesso al motore sottostante. Deleghi le considerazioni sulle prestazioni al motore, lasciandoti libero di preoccuparti di creare un gioco. È più facile scrivere il gioco, più difficile da ottimizzare le prestazioni da soli.
  • Haskell (o il tuo linguaggio oscuro preferito): qualsiasi linguaggio di programmazione completo di Turing è equivalente a qualsiasi altro. Quindi, mentre puoi scrivere qualsiasi programma in qualsiasi lingua, fai dei compromessi, alcuni obiettivi, altri soggettivi. Un linguaggio come Haskell è più concentrato sul lavoro in uno spirito matematico. I problemi a cui è orientato sono in qualche modo diversi dai problemi affrontati nei giochi. Ciò non significa che non possa o non debba essere utilizzato per i giochi, non è semplicemente adatto ad esso.

L'ultimo punto è che parte di questo è storico e politico. Molte guerre di fiamma sono state combattute tra i diversi linguaggi di programmazione. C # per esempio potrebbe essere adatto allo sviluppo di giochi, ma è arrivato dopo C ++. O alla gente non piace che provenga da Microsoft. Alcune persone si sono trasferite in C #, altre no. Alcune persone programmano ancora i giochi in BASIC, Pascal e C. Qualsiasi cosa i programmatori si sentano a loro agio, si atterranno. I programmatori di giochi sono stati per lo più a proprio agio con C ++, probabilmente perché sono cresciuti con C e C ++ e hanno soddisfatto le loro esigenze. Se l'industria dei computer si trova in uno stato in cui le prestazioni e la diffusione di Java soddisfano abbastanza persone, forse Java sarebbe di fatto il linguaggio di sviluppo del gioco standard.


2

Eredità e slancio.

C'era una volta un codice temporale scritto in assemblatore per le massime prestazioni. Con l'aumentare della potenza di calcolo, i linguaggi compilati divennero più praticabili e C offrì il miglior compromesso tra potenza e produttività, a un livello molto basso essendo poco più di un assemblatore di macro.

Il C ++ è stato solo il naturale successore di C. Non butti via alcun codice o conoscenza precedente, ma hai il potenziale per espandersi in nuove metodologie. Il C ++ è in definitiva molto flessibile e devo ancora vedere un paradigma di progettazione che non può essere almeno simulato in C ++, pur potendo mantenere un controllo quasi totale sulle prestazioni.


2

Se stai sviluppando per le console, non hai scelta: gli SDK professionali sono disponibili solo in versioni C ++. Di solito hanno anche accesso C alla maggior parte delle cose.

Poiché molti sviluppatori sono Console + PC, ha senso svolgere tutto il proprio PC nella stessa lingua e condividere direttamente la tecnologia.

Perché è lì che vive l'industria dei professionisti, e quasi tutti vogliono farne parte, la maggior parte dei programmatori di giochi sono programmatori C ++.

Perché tutto ciò accade, la maggior parte degli sviluppatori di motori sono anche sviluppatori C ++, quindi quando si valutano motori di livello professionale quasi tutte le scelte saranno C ++.

È tutto un grande motore autosufficiente. La sua interruzione richiederebbe molto più che un semplice progresso tecnico.


2

FWIW: C # sta guadagnando popolarità per lo sviluppo del gioco. Vedi il post sul blog di Miguel de Icaza . Lettura molto interessante, IMHO.


2
Come al solito, Miguel spinge le sue tecnologie preferite (di solito marginali) ignorando i modi in cui C # è diventato un grande attore nel settore, ad esempio XNA.

2

Anche se sono abbastanza fortemente anti-C, C e C ++, l'unica cosa che hanno che poche altre lingue hanno è il controllo completo sulla piattaforma su cui è in esecuzione, puoi essere sicuro esattamente cosa accadrà in ogni momento, no GC, nessun problema tecnico.

Questo non è così importante in questi giorni, ma può essere per piattaforme poco potenti.

Su PC / Mac / Linux è probabilmente il linguaggio meno portatile che incontrerai in questi giorni e il bonus di velocità non è più una grande differenza - Minecraft (Java) è fluido e funziona su piattaforme piuttosto minimali (e qualsiasi sistema operativo) con un singolo eseguibile - Devo ancora vedere un'app indi C / C ++ a bassa manodopera con la stessa funzionalità e il minor numero di bug, figuriamoci lavorare su tre piattaforme.

Quindi a questo punto direi che la maggior parte è inerzia e l'idea che i giochi reali siano sempre fatti in C / C ++, sebbene la capacità di "port" su iPhone e console sia significativa (anche se sono abbastanza sicuro che la maggior parte dell'interfaccia utente dei giochi richiede molto sforzo per il port tranne tra Windows e XBox).


1
Oh, non so se sia importante solo per piattaforme "sottodimensionate". L'altro modo di vedere questo è che i giochi sono sempre in prima linea nelle prestazioni su qualsiasi piattaforma: ogni nuova potenza viene immediatamente divorata. Se parliamo di sviluppo di giochi professionali, le prestazioni sono praticamente la preoccupazione principale: non si scrive Unreal senza massimizzare ogni singolo ultimo ciclo che la macchina ha da offrire. Ogni; singolo; ciclo. A tutti i livelli, dal motore grafico e l'accesso al disco fino al ciclo dell'interfaccia utente.
Chris Subagio,

@ Chris: Il modo migliore che ho trovato per descriverlo ai programmatori non di gioco è che i giochi sono un dominio in cui la velocità è un vantaggio competitivo. Se il tuo elaboratore di testi si avvia in 5 secondi in cui MS Word impiega 10 o si ridispone in 0,1 secondi in cui Word richiede 0,2, è inutile. Ma se il tuo gioco può pompare anche il 10% in più di frammenti o mostrare anche un personaggio più dettagliato, questo può essere un enorme vantaggio competitivo.

Quindi non sarebbe sciocco codificare mai altro che assembly? Sarebbe sicuramente più veloce di almeno il 10%. C'è un punto in cui si effettua una chiamata per compensare le prestazioni per manutenibilità e velocità di sviluppo. Di solito quel punto è C ++ in questi giorni. Sarebbe bello se la capacità di attraversare la piattaforma come Minecraft avesse un peso maggiore.
Bill K,

Ah, ma è un errore il fatto che la codifica in assembly sia più veloce: i chip attuali sono abbastanza complessi che è difficile per un programmatore sovraperformare costantemente un compilatore. Solo in domini più limitati come SPU su PS3, loop di fisica interna e shader su GPU ci sono ancora chiari vantaggi. Il C ++ è in effetti attualmente il punto debole, con l'avvertenza che OOP non è sempre la scelta migliore: la discussione in corso Struct of Arrays vs Array of Structs non è esattamente una discussione linguistica, ma C ++ ti porta chiaramente ad AoS naturalmente; A volte ... vuoi davvero C.
Chris Subagio

Il passo nell'efficienza del programmatore tra assemblatore e C / C ++ è anche un ordine di grandezza maggiore del passo nell'efficienza del programmatore tra C e C ++, o C ++ e C # / Java. Fred Brooks lo ha sottolineato 25 anni fa.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.