Конкуренция с C ++ для программирования игр

21

Мне любопытно, почему C ++ так популярен для разработки игр, а не других языков. Я знаю, что с его помощью можно создать очень быстрый код, но что именно делает его популярным?

Это только потому, что это быстро? Это какая-то другая особенность языка, такая как парадигма ОО или переносимость? Это из-за всех библиотек, которые были созданы со временем? Или какая-то комбинация всех этих (и других) причин?

Если бы кто-то мог рассказать мне об этом, я был бы очень счастлив. :-)

KasMA1990
источник
7
Для меня достаточно скорости, тем более что жалобы каждого на язык не имеют для меня никакого смысла.
Бенджамин Линдли
Быстрое предположение: большинство игр написаны для Windows. Языки C и C ++ активно поддерживаются Microsoft. И, наконец, C ++ предпочтителен из-за ООП и шаблонного метапрограммирования.
@ Мэтт Спасибо, не знал, что он существует. Могу ли я перенести тему туда или я должен удалить эту тему и воссоздать ее там?
Об этом уже спрашивали несколько раз.
Zan Lynx
1
@ Бенджамин: Тогда, полагаю, вы недостаточно написали на C ++ или никогда не использовали более выразительный язык, такой как Python (или даже C # с LINQ). Однако, даже если по какой-то безумной причине вы предпочитаете писать 20-строчный код для того, что многие другие языки могут делать в 1, чрезвычайно плохая грамматика C ++ означает, что программы компилируются значительно дольше, чем должны, и надлежащие инструменты IDE (рефакторинг и т. Д.) труднее, если не невозможно, создать.
BlueRaja - Дэнни Пфлугхофт

Ответы:

29

Многочисленные причины:

  • Большой, который вы пропустили: он портативный, упрощая перенос вашего игрового движка на iOS, XBOX, PS3, что угодно
  • Это быстро
  • Все SDK поддерживают его изначально
  • Много доступных библиотек
  • Все, кто пишет игры, знают это, поэтому легко нанять опытных разработчиков игр для своей команды
  • Встраивать язык сценариев игрового движка, такой как Lua, тривиально

источник
Хорошо, спасибо за ваши ответы всем, вы думаете, все, что мне нужно, я думаю. :-)
KasMA1990
14

Есть несколько причин, которые я хотел бы упомянуть в дополнение к тому, что поднял @Graham.

  • Устаревший код - многие студии имеют много кода на C ++, к вашим услугам библиотеки.
  • C ++ на самом деле является ассемблером высокого уровня, имеет прямой доступ к аппаратному обеспечению (настолько прямой, насколько вы можете запустить поверх операционной системы по крайней мере) и довольно быстрый. Если вы хотите, в C ++ вы можете перейти прямо на ассемблер для контроля уровня команд (не то, что это всегда разумно, просто невозможно с Java, C #, Python и т. Д.)
  • DirectX и OpenGL изначально поддерживают C ++, большинство других языков имеют «привязки» к базовым библиотекам через промежуточные уровни, это не означает, что они не быстрые или не могут делать много одинаковых вещей, но это добавляет слой программного обеспечения между ваша игра и оборудование.
  • Как упоминает @Graham, многие программисты знают об этом, поэтому его легко найти опытных разработчиков, а также он довольно переносим, ​​по сравнению с C #, который застрял в .NET Framework (есть Mono, но обычно отстает от реализации Microsoft .)
Nate
источник
Разве вы не имеете в виду низкий уровень?
Джокинг
5
C ++ - это low-levelязык; но high-levelассемблер, имо.
Nate
3
Я не согласен. C ++ - это язык высокого уровня, со встроенной возможностью использовать C (язык низкого уровня).
Foo
7
C ++ - это язык высокого уровня, как и C. Сборка - это низкий уровень. Теперь C ++ выше, чем C, так же, как C # выше, чем C ++, а Ruby / Python выше, чем C #.
А.А. Грапсас
4
Почему устаревший код должен быть устаревшим (а не устаревшим)? «Устаревший код» означает, что он старый, а не плохой.
8

Необработанная скорость является основной причиной, но на самом деле это не то или иное решение, поэтому многие игровые компании начинают использовать другие языки для частей игры. Некоторые задачи требуют, чтобы компьютер работал как можно быстрее (например, процедуры рендеринга ядра), но многие задачи в коде игрового процесса не должны выполняться слишком быстро (например, открывать дверь, когда игрок нажимает на нее), что означает разумно использовать для этих частей гораздо более простой (и, следовательно, более быстрый для написания программ) язык. Вот почему многие игровые движки написаны на C ++, но для написания игрового кода встраивают язык сценариев, такой как Lua.

Сложно понять, что при выборе языков программирования существует общий компромисс между эффективностью для компьютера и эффективностью для программиста. То есть, что для вас важнее, как быстро компьютер выполняет код или как быстро программист пишет код?

jhocking
источник
3

В C ++ вы можете размещать локальные переменные, которые исчезают после завершения функции. Обычно они располагаются в стеке.

Переменные стека не вносят вклад в проблемы динамического выделения памяти при фрагментации и накладных расходах. Выделение места в стеке происходит быстро и легко (просто настраивая указатель). Динамическое распределение памяти обычно включает в себя поиск в контейнере адекватного блока памяти, маркировку памяти, а затем пометить ее как занятую. Выделение включает в себя добавление блока памяти в контейнер и, возможно, объединение его с существующими блоками. Намного больше накладных расходов, чем просто изменение указателя.

Java и C # распределяют память динамически, за исключением примитивных типов. Эти языки зависят от среды выполнения, которая помечает переменную для удаления, а затем запускает сборщик мусора через произвольные (незапланированные) интервалы для восстановления памяти. В общем, программист не контролирует, когда переменная будет помечена для удаления или когда она будет возвращена (восстановление использованной памяти - сложная тема, с которой большинство программистов на C ++ и Java не сталкиваются).

Скорость C ++ в первую очередь обусловлена ​​его прямым переводом в исполняемый код. Java и C # компилируются в промежуточный код, который затем интерпретируется виртуальной машиной. В целом, интерпретирующие языки медленнее, чем языки с прямым переводом.

Томас Мэтьюз
источник
1
-1 (если бы я мог) - локальные примитивы размещаются в стеке как на Java, так и на C #, а в C # вы можете создавать выделенные в стеке structs. Более того, чрезвычайно малое увеличение скорости, которое вам дает, недостаточно для оправдания одного языка перед другим. @Graham Perks указывает на настоящую причину: это то, что разработчики игр должны знать, так это то, что узнают новые разработчики игр и для чего предназначены новые SDK. Существует множество языков (например, Go), которые бывают такими же быстрыми и быстрыми, и не столь неудобными для написания.
BlueRaja - Дэнни Пфлюгофт
C ++ не очень хорош в распределении стека; на самом деле, очень трудно выделить STL-совместимые объекты в стеке. Например, последний большой движок, над которым я работал, был на C, и у нас была строка, которую вы могли бы запустить в стеке с фиксированным размером (обычно 1 КБ). Если оно прошло мимо, оно прозрачно переместилось в кучу. Вы можете сделать что-то подобное с помощью пользовательских распределителей std :: string в C ++, но код намного сложнее понять правильно.
1
@Joe Wreschnig: C ++ отлично справляется с распределением стека, просто выведите список языков ассемблера. Однако большинство поставщиков компиляторов не выделяют для стека огромный объем памяти. Распространенное понимание опытных программистов на C ++ заключается в том, что огромные объекты выделяются динамически (куча), а не локальное хранилище (стек). Огромные объекты в стеке могут переполняться в кучу на некоторых платформах, когда стек и куча растут навстречу друг другу.
Томас Мэтьюз
1
Общее понимание более опытных программистов на C ++, особенно программистов на игровых приставках, заключается в том, что все, что не переполняет стек, является выделенным или предварительно выделенным стеком. C делает это легко, потому что распределитель не является частью структурного типа объекта. Это также позволяет освободить что-то неправильно, но, по моему опыту, это редкая проблема по сравнению с тем, кто испортил реализацию / совместимость распределителя, совместимого с stdlib. Есть также некоторые приемы с размещением новых, но, опять же, это сложнее, чем эквивалент в C.
2
Нет. Преимущество C ++ в скорости связано с его способностью использовать собственный диспетчер памяти, созданный пользователем, для распределения кучи . Каждый здравомыслящий язык распределяет местных жителей по стеку.
Nevermind
3

Игры когда-то были написаны на машинном языке, потому что у них было экзотическое оборудование, для которого не было компилятора. Аппаратному обеспечению также не хватало функций, которые программисты на С воспринимают как должное, таких как эффективная 16-разрядная целочисленная математика.

Как только игры установились на знакомом оборудовании, стали доступны компиляторы Си, и в скором времени все игры были написаны на Си.

В свое время C ++ казался хорошей идеей, и большинство игр сегодня - это C ++, но инженеры теперь бормочут о возвращении в C, и это может действительно случиться. Я хотел бы поработать над игрой в Си, как и многие коллеги. В C ++ нет ничего нового, что, я думаю, улучшает игры.

Казалось бы, теперь, когда компьютеры работают в 1000 раз быстрее, чем несколько лет назад, язык высокого уровня сократит время разработки ($), что сделает C устаревшим.

Этого не произошло, потому что покупатели игр знают, что аппаратное обеспечение в 1000 раз лучше, и хотят обменять свои доллары на игру, которая выглядит и звучит в 1000 раз лучше. Это устраняет слабость системы, которую потребляет язык высокого уровня.

Требования к производительности в играх жестоки. Новый графический кадр должен быть обработан менее чем за 33 мс (или 16 мс!) В обязательном порядке. Все оборудование должно быть учтено, чтобы этот бюджет был выполнен. Любой язык, который выходит из строя и делает что-то с аппаратным обеспечением, которое программист не понимает или не ожидает, очень усложнит выполнение этого бюджета. Это автоматический минус против всего высокого уровня.

Программисты игр не только работают на языке низкого уровня, но также избегают структур данных высокого уровня и алгоритмов. Игры обычно не имеют связанных списков и редко имеют деревья. Есть движение к тому, чтобы избегать указателей, когда это возможно *. Любой алгоритм с более чем O (N) временем или O (1) пространством не находит широкого применения.

* Если указатель не вызывает пропадание кэша, то зачем тратить 32 бита на его хранение? Если указатель действительно вызывает ошибку кэша, лучше всего избавиться от этой ошибки кэша.

bmcnett
источник
1
«В C ++ нет ничего нового, что, я думаю, улучшает игры». СМЕШНО? ООП? Класс humanс дериватами playerи enemy?
orlp
2
@nightcracker: Basic is-наследование отлично работает в C; отношения, которые вы описываете, лучше реализуются с помощью has-a по соображениям производительности и чистоты в любом случае.
3
Растет согласие с тем, что функции ООП C ++ не подходят для игр, потому что эти функции работают на предположениях, которые враждебны к производительности кэширования.
bmcnett
Даже если вы считаете, что C ++ не дает никаких преимуществ по сравнению с C, вы должны обязательно признать, что возврат к C не дает никаких преимуществ по сравнению с C ++.
Дэн Олсон
@Dan Возврат к Си дает преимущество в том, что «лучшие практики», такие как не использование шаблонов или ООП, вызываются ошибками во время компиляции, а не преследуют младших программистов с помощью палки. Кроме того, так как язык проще, предположительно, компилятор и отладчик обходятся дешевле.
bmcnett
3

У каждого языка программирования есть сильные и слабые стороны по целому ряду факторов. Примеры этих факторов:

  • Скорость на конкретной платформе
  • Использование памяти на конкретной платформе
  • Какую функциональность он предоставляет с большей готовностью
  • На каких платформах он существует
  • Какие соображения должен принять программист на борт

Одним из наиболее важных факторов, который волнует программиста игры, является производительность. Они хотят создавать интерактивный опыт, что означает, что он должен быть реактивным и способен выводить как можно больше полезных (или интересных) данных. Вы хотите знать, сколько у вас здоровья в любое время и не хотите его ждать. И если вы нажмете кнопку, вы ожидаете, что пистолет выстрелит или ваш персонаж подпрыгнет, когда вы так скажете. Небольшая задержка может помешать этой интерактивности, поэтому вам нужна производительность.

Другим важным фактором является предпочтение программирования на языке проблемы, а не на языке реализации. Программист игры хочет иметь дело с людьми, орками и гоночными машинами, а не с регистром памяти ED0. Они по-прежнему хотят опустить детали реализации, если им нужна производительность, но было бы замечательно, если бы по большей части они могли иметь дело с уровнем сущностей в их игровом мире. Им достаточно беспокоиться о симуляции игрового мира, не заботясь о том, как работает связанный список.

C ++ очень хорошо подходит для этих двух основных факторов. Вы можете получить преимущества производительности сборки или кода C с выразительностью объектов. Чтобы понять, почему это естественно подходит для игр, сравните с некоторыми другими языковыми опциями:

  • Сборка: это грубая сила. То, что вы пишете, в основном то, что делает процессор. Но на каждом этапе вам нужно знать, что происходит с регистрами и как это происходит, и это никогда не выглядит как сущности в вашем игровом мире. Программист должен сделать мысленное соответствие того, что делает их код, с тем, что происходит в игре. Это может быть довольно душевным.
  • C: Здесь у нас хорошая производительность, но мы можем использовать опыт гуру для выполнения стандартных задач (таких как выделение памяти, работа со строками и использование стандартных математических функций). Здесь мы приближаемся к выразительности, но язык более или менее заставляет вас сосредоточиться на реализации, потому что вы действительно можете работать только с обычными типами данных. Все действительно чарс, int или тому подобное. структуры, указатели и массивы могут объединять вещи, но все же нужно думать о внутренних элементах.
  • Java: мы перепрыгиваем через C ++ и переходим к Java. Java отталкивает от деталей реализации. На самом деле, большую часть времени вы не получаете доступ к нижним уровням. Java абстрагирует большую часть деталей реализации (например, какой процессор или ОС вы используете) по той причине, что она хочет быть кроссплатформенной. Вы не можете получить доступ к деталям, потому что их там нет. Вы не программируете для компьютера, вы программируете для платформы (платформа Java, которая существует на большинстве компьютеров). Более того, Java имеет, возможно, лучший язык для решения проблемы на языке, чем C ++. Компромисс в том, что вы не можете оптимизировать работу под конкретный компьютер. Имеет ли это практическое значение или нет, зависит от специфики программы и компьютера.
  • Язык сценариев игры. Под этим я подразумеваю что-то вроде UnrealScript или пользовательских языков сценариев, привязанных к игровому движку. В них у вас нет доступа к базовому движку. Вы делегируете движку соображения производительности, позволяя себе не беспокоиться о создании игры. Проще написать игру, сложнее оптимизировать ее производительность самостоятельно.
  • Haskell (или ваш любимый малоизвестный язык): любой язык программирования, полный по Тьюрингу, эквивалентен любому другому. Таким образом, в то время как вы можете написать любую программу на любом языке, вы делаете компромиссы, некоторые объективные, некоторые субъективные. Такой язык, как Хаскелл, больше ориентирован на работу в математическом духе. Проблемы, на которые он ориентирован, несколько отличаются от проблем, с которыми сталкиваются в играх. Это не значит, что он не может или не должен использоваться для игр, просто он не подходит для этого.

Последний пункт заключается в том, что часть этого является исторической и политической. Многие пламенные войны велись между различными языками программирования. Например, C # может быть таким же подходящим для разработки игр, но он появился после C ++. Или людям не нравится, что это от Microsoft. Некоторые люди перешли на C #, некоторые нет. Некоторые люди до сих пор программируют игры на BASIC, Pascal и C. Что бы ни устраивали программисты, они будут придерживаться. Программисты игр в основном чувствовали себя комфортно с C ++, возможно потому, что они выросли на C и C ++, и это отвечало их потребностям. Если компьютерная индустрия находится в состоянии, когда производительность и популярность Java удовлетворяют достаточное количество людей, то, возможно, Java будет де-факто стандартным языком разработки игр.

BrettW
источник
2

Наследие и импульс.

Когда-то код был написан на ассемблере для максимальной производительности. По мере увеличения вычислительной мощности скомпилированные языки стали более жизнеспособными, и C обеспечил лучший компромисс между мощностью и производительностью, на базовом уровне, являющемся немногим больше, чем макроассемблер.

C ++ был просто естественным преемником C. Вы не выбрасываете прежний код или знания, но у вас есть потенциал для расширения в новые методологии. C ++ в конечном счете очень гибок, и мне еще предстоит увидеть парадигму дизайна, которая не может быть, по крайней мере, смоделирована в C ++, и в то же время способна поддерживать практически полный контроль над производительностью.

Саймон Лэйси
источник
2

Если вы разрабатываете для консолей, у вас нет выбора: профессиональные SDK выпускаются только в вариантах C ++. Обычно они также имеют C-доступ к большинству вещей.

Поскольку многие разработчики являются Consoles + PC, имеет смысл выполнять всю работу на ПК на одном языке и напрямую делиться технологиями.

Так как именно здесь живет проиндустрия, и большинство из них хотят быть частью этого, большинство программистов игр - программисты на С ++.

Поскольку все это происходит, большинство разработчиков движков тоже являются разработчиками на C ++, поэтому при оценке движков профессионального уровня почти все ваши решения будут выбраны на C ++.

Это все большой самоподдерживающийся двигатель. Нарушение этого потребует не только технического прогресса.

Крис Субаджио
источник
2

FWIW: C # набирает популярность для разработки игр. Смотрите сообщение в блоге Мигеля де Иказы . Очень интересно читать, ИМХО.


источник
2
Как обычно, Мигель продвигает свои любимые (обычно маргинальные) технологии, игнорируя при этом способы, которыми C # фактически стал крупным игроком в отрасли, например, XNA.
2

Хотя я довольно сильно настроен против C, C и C ++, единственное, что у них есть, что есть у немногих других языков - это полный контроль над платформой, на которой он работает, вы можете быть точно уверены, что будет происходить всегда, нет GC, без глюков.

Это не так важно в наши дни, но это может быть для недостаточно мощных платформ.

На ПК / Mac / Linux это, вероятно, наименее переносимый язык, с которым вы можете столкнуться в наши дни, и бонус к скорости уже не так уж и важен - Minecraft (Java) плавный и работает на довольно минимальных платформах (и любых ОС). с одним исполняемым файлом - я еще не видел индийского C / C ++-приложения с низкой рабочей силой, с таким большим количеством функциональных возможностей и небольшим количеством ошибок, не говоря уже о работе на трех платформах.

Поэтому на данный момент я бы сказал, что большая часть этого - инерция и концепция того, что настоящие игры всегда делаются на C / C ++, хотя способность «портировать» на iPhone и приставки значительна (хотя я вполне уверен, что большинство пользовательский интерфейс игр требует много усилий для портирования, кроме как между Windows и XBox).

Билл К
источник
1
О, я не знаю, насколько это важно только для "слабых" платформ. Другой способ взглянуть на это состоит в том, что игры всегда находятся на переднем крае производительности на любой платформе: любая новая мощь немедленно поглощается. Если мы говорим о профессиональной разработке игр, то производительность в значительной степени важна: вы не пишете Unreal, не максимизируя каждый последний цикл, который может предложить машина. Каждый; не замужем; цикл. На каждом уровне, от графического движка и доступа к диску до вашего пользовательского интерфейса.
Крис Субаджио
@Chris: лучший способ, который я нашел, чтобы описать это для неигровых программистов, это то, что игры - это область, где скорость является конкурентным преимуществом. Если ваш текстовый процессор запускается через 5 секунд, где MS Word занимает 10, или перезапускается через 0,1 секунды, когда Word занимает 0,2, это ничего не стоит. Но если ваша игра может выкачать еще на 10% больше фрагментов или показать еще одного подробного персонажа, это может стать огромным конкурентным преимуществом.
Тогда не было бы глупо когда-либо кодировать что-либо кроме сборки? Это было бы, по крайней мере, на 10% быстрее. Есть момент, когда вы призываете к компромиссу между производительностью и удобством обслуживания и скоростью разработки. Как правило, в эти дни это C ++. Было бы хорошо, если бы способность кроссплатформенности, подобной Minecraft, имела больший вес.
Билл К
Ах, но ошибочно то, что кодирование в ассемблере происходит быстрее: современные чипы достаточно сложны, чтобы программисту было непросто превзойти компилятор. Только в более ограниченных областях, таких как SPU на PS3, внутренние физические циклы и шейдеры на графических процессорах все еще имеют явные преимущества. C ++ действительно в настоящее время является приятным местом с оговоркой, что ООП не всегда лучший выбор: текущее обсуждение Struct of Arrays vs Array of Structs не является языковым обсуждением, но C ++ явно приводит вас к AoS; Иногда ... ты действительно хочешь С.
Крис Субаджио
Шаг в эффективности программиста между ассемблером и C / C ++ также на порядок больше, чем шаг в эффективности программиста между C и C ++ или C ++ и C # / Java. Фред Брукс указал на это 25 лет назад.