Кузовной ремонт автомобиля

 Покраска в камере, полировка

 Автозапчасти на заказ

Как сделать раскоксовку двигателя


раскоксовка движка.подробная инструкция — DRIVE2

Самостоятельная очистка двигателя от гари и кокса.

В процессе работы автомобильного двигателя в его камере сгорания топлива при высоких температурах происходит образование кокса и гари. Кокс – это твердые отложения, которые образуются при прокаливании без доступа воздуха топлива и масла, откладывающиеся на стенках камеры сгорания двигателя. Гарь представляет собой сыпучие мелкие остатки кокса. Конечно, идеально было бы, если бы маслосъемные поршневые кольца начисто снимали бы масло со стенок цилиндров двигателя, но на практике этого добиться не представляется возможным. А еще при этом масло с выпускных клапанов вместе с потоком топливной смеси также попадает в цилиндры. При возрастании числа пробега автомобиля возрастает и вероятность попадания масла в камеры сгорания его двигателя не только через те пути, о которых уже говорилось, но и через другие его элементы.

Нельзя игнорировать такую ситуацию. Поэтому при появлении признаков нагара рекомендуется осуществление процесса раскоксовки, то есть удаления гари и кокса со всех поверхностей деталей автомобильного двигателя.

Познакомимся с некоторыми признаками, указывающими на то, что двигателю Вашего автомобиля требуется процедура раскоксовки:

1. Появление вылетающей гари из выхлопной трубы и устойчивого запаха гари в салоне при включении зажигания или повышенной «дымности» в процессе заведения холодного двигателя.
2. Рост расхода масла по сравнению с обычным расходом.
3. Резкое снижение динамики авто.
4. Неравномерная работа двигателя на холостом ходу.
5. Появление существенного разброса в пределах 1-5 атм. компрессионных показаний по цилиндрам.
6. Возникновение резкого ухудшения запуска двигателя во время холодов при отсутствии проблем с аккумулятором.

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

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

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

Теперь рассмотрим процесс выполнения раскоксовки поэтапно и подробно:

1. Сначала необходимо выкрутить свечи зажигания.
2. Дальше следует выполнить установку поршней цилиндров приблизительно в среднее положение, приподняв для этого с помощью домкрата, заднее или переднее колесо соответственно на заднеприводных или переднеприводных машинах. Затем, включив последнюю, то есть пятую или четвертую передачу – в зависимости от коробки, прокрутив колесо, с помощью отвертки через отверстия свечей определиться с положением поршней.
3. Через отверстия свечей аккуратно залить в цилиндры, ранее купленную химию, предназначенную для выполнения процедуры раскоксовки. Заливать следует в каждый цилиндр приблизительно по 25 мл. Удобнее всего осуществлять процесс заливки, используя обыкновенный шприц.
4. Для более быстрого попадания средства к поршневым кольцам и эффективного размачивания нагара следует поддомкраченное колесо поворачивать, покачивая его с некоторой небольшой амплитудой, шевеля при этом и поршни следующим образом: 2-3 движения колеса, затем несколько минут «отдыха». В зависимости от силы и свойств, применяемого химического средства, на процесс разрыхления отложений может уйти 10-60 минут. За этот период времени нагар способен перейти в желеобразное или полужидкое состояние и затем в ходе работы двигателя происходит его выгорание и вылет из камеры сгорания.
5. Далее обязательно необходимо выключить передачу и осуществить прокручивание двигателя стартером приблизительно 10 секунд для удаления оставшейся в цилиндрах жидкости. Следующей процедурой является закручивание свечей. Если этого не сделать, то при заведении автомобиля может произойти повреждение двигателя за счет ощутимого гидроудара. Обязательно перед выполнением прокрутки двигателя необходимо, сняв с крышки трамблера, сделать фиксацию центрального высоковольтного провода, создавая зазор между наконечником провода и массой, приблизительно на несколько сантиметров. Выполнить это нужно для избегания появления пробоя катушки зажигания или иной нежелательной неприятности.
6. Итак, закрутив свечи, следует вернуть провод на место – на крышку трамблера и завести машину. При этом не нужно пугаться дыма, имеющего довольно неприятный запах, который может выходить из выхлопной трубы и затруднений, возникающих при запуске мотора после процедуры раскоксовки. Все эти явления могут быть в процессе раскоксовки и пугаться их не стоит. Дым с неприятным запахом может идти из выхлопной трубы авто почти до 10 первых километров пробега после раскоксовки.
7. В конце процесса раскоксовки следует дать поработать двигателю автомобиля около 20 минут на холостых оборотах, и только затем можно начинать движение.

#авто@mensrule

Как быстро и просто создать рекомендательный движок | Ян Тейхманн

Часть 1: введение, как добраться до производства через неделю и куда идти после этого

Отдых мультфильма Рины Пикколо (Cartoonist Group)

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

Мы еще не войдем в передовые позиции, но мы не будем далеко от них.

Прочтите часть 2, чтобы ознакомиться с более сложными примерами использования, когда быстрое и простое больше не достаточно хорошо:

Системы рекомендаций повсюду, и для многих онлайн-платформ их механизмы рекомендаций - это реальный бизнес. Это то, что сделало Amazon большим: они очень хорошо рекомендовали вам, какие книги читать. Есть много других компаний, которые все строят вокруг систем рекомендаций: YouTube, Netflix, Spotify, платформы социальных сетей. Параллельно потребители стали ожидать персонализированного опыта и сложных систем рекомендаций, чтобы найти соответствующие продукты и контент, чтобы сэкономить время и деньги потребителей.

Но как построить механизм рекомендаций?

Механизмы рекомендаций были известны в течение некоторого времени, и были использованы некоторые ключевые уроки:

  1. Действия пользователя являются лучшим индикатором намерения пользователя. Рейтинги и отзывы имеют тенденцию быть очень предвзятыми и более низкие объемы.
  2. Прошлые акции и покупки приводят к новым покупкам, и совпадение с покупками и действиями других людей является фантастическим предиктором.

Системы рекомендаций обычно используют перекрытие или совместное вхождение для вынесения рекомендации.Как в следующем примере, где мы рекомендуем Этану щенка на основе сходства Этана с Софией:

Воссоздание иллюстрации в «Практическом машинном обучении, Тед Даннинг и Эллен Фридман, О'Рейли 2014»

На практике механизм рекомендаций вычисляет матрица совпадений из матрицы истории событий и действий. Это достаточно просто, но в реальных сценариях необходимо преодолеть трудности. Что делать, если все хотят единорога? Хорошая рекомендация - высокая вероятность появления единорогов в следующем примере?

Восстановление иллюстрации в «Практическом машинном обучении», Тед Даннинг и Эллен Фридман, O'Reilly 2014

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

Воссоздание иллюстрации в «Практическом машинном обучении», Тед Даннинг и Эллен Фридман, O’Reilly 2014

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

Чтобы создать модель пользовательских элементов, мы могли бы применить простую матричную факторизацию или обучить нейронную сеть для прогнозирования результатов ввода пользовательского элемента.Как правило, модели отдельных элементов более устойчивы и дают лучшие результаты, когда мы не вкладываем больше средств в разработку функций, настройку моделей и т. Д.

Однако существует еще несколько проблем, которые должна решить система с хорошими рекомендациями. Рекомендовать одно и то же снова и снова - это скучно, . Хуже того, рекомендация одного и того же дает неверных данных, и усталости содержимого .

Spotify не будет производить такой набор результатов! Их поисковые и рекомендательные системы на высшем уровне! Этот пример нуждался в редактировании.Po Spotify

Две простые и интуитивно понятные стратегии для повышения ценности рекомендаций:

  1. Защита от наводнений: оштрафуйте вторую и третью рекомендации, если они имеют одинаковые оценки сходства с верхней рекомендацией.
  2. Дизеринг: добавьте шаблонную рекомендацию, чтобы создать новые интересные точки данных для системы рекомендаций, чтобы постоянно узнавать о другом контенте.

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

Системы рекомендаций лучше всего работают с объективными откликами пользователей , такими как покупка продуктов, просмотр видео или прослушивание песни. Если вам повезло, и у вас есть такой набор данных, даже простой подход будет работать очень хорошо. Тем не менее, во многих случаях использования у вас есть в основном неявные отзывы, такие как просмотры страниц, клики или поисковые запросы. К сожалению, эти данные также сильно смещены, например, рейтинг кликов сильно зависит от позиции контента на странице. Неявная обратная связь также имеет тенденцию работать хуже, т.е.грамм. клик по результату поиска может просто научить вас тому, насколько кликабит заголовок или CTA, а не релевантности реального контента. Это приводит к высоким показателям отказов после изначально высокой частоты кликов (очень распространенный случай!).

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

  • Ваш каталог продукции не слишком велик, товары очень долговечны и могут легко взаимодействовать с несколькими пользователями.Давайте использовать Zoopla в качестве примера, где мы попадаем в неприятности: Zoopla.co.uk - это портал недвижимости, и в любой момент времени в нем живут более 1,3 миллиона записей. Список аренды в Лондоне очень короток, и может пройти несколько дней, прежде чем недвижимость будет сдана в аренду и снята с рынка. Очевидно, что вы не можете сдать в аренду или продать квартиру нескольким людям одновременно! С размером каталога Zoopla действительно трудно генерировать значительное количество совместного использования даже при объемах трафика Zoopla.
  • Вы не зависите от рекомендаций по открытию новинок. Поскольку совместная фильтрация требует совместного использования для генерации сигналов, алгоритм имеет большую проблему холодного запуска . Любой новый элемент в каталоге продуктов не встречается одновременно и не может быть рекомендован без первоначального вовлечения пользователей в новый продукт. Это может быть приемлемо, если ваш бизнес использует, например, много CRM и маркетинг как стратегия продвижения новых продуктов.

Одним из вариантов будет использование Spark и алгоритма (ссылки) с чередованием наименьших квадратов (ALS), который является простым решением для обучения модели, но не обеспечивает немедленного решения для развертывания и оценки.Для начала я рекомендую другой подход:

Как оказалось, математические задачи поиска и рекомендации поразительно похожи. Самое главное, хороший пользовательский опыт в поиске и рекомендации почти неразличимы. По сути, результаты поиска являются рекомендациями, если мы можем сформулировать рекомендации как поисковые запросы. Это идеальное решение, поскольку многие веб-сайты и компании уже используют поисковые системы в своих бэкэндах, и мы можем использовать существующую инфраструктуру для создания нашей системы рекомендаций.Elasticsearch хорошо масштабируется и существует как полностью управляемые развертывания, например на AWS. Нет более безопасной ставки, если вы хотите быстро запустить механизм рекомендаций в производство!

Как создать рекомендацию с помощью поисковой системы?

  1. Мы храним все пользовательские взаимодействия в поисковом индексе.
  2. Когда пользователь на странице яблок, мы ищем всех пользователей, у которых есть яблоки вasticsearch. Это определяет нашу переднюю популяцию.
  3. Мы ищем совместное появление на нашем переднем плане, которое дает нам щенков.
  4. Ищем щенков на фоне популяции.
  5. Мы рассчитываем какую-то оценку для нашей рекомендации щенка.

Хорошая новость: Elasticsearch реализует для нас все 5 шагов в одном запросе!

Если мы храним наши пользовательские взаимодействия в упругом поиске следующим образом

 {
"_id": "07700f84163df9ee23a4827fd847896c",
"user": "user_1",
"products": ["apple", "book", "lemon", "puppy"]
}

с таким отображением документа:

 {
"пользователь": {"тип": "ключевое слово"},
"продукты": {"тип": "ключевое слово" }
}

тогда все, что необходимо для выработки некоторых рекомендаций, - это следующий запрос e.грамм. с использованием Python:

 из эластичного импорта import Elasticsearch, RequestsHttpConnection 
из aws_requests_auth.boto_utils import BotoAWSRequestsAuthes = Elasticsearch (
host = host, port = port,
connection_class =
010101Bext) поиск (
index = index, doc_type = doc_type,
body = {
"query": {
"bool": {
"must": {
"term": {"products": "apple"}
}
}
},
«aggs»: {
«рекомендации»: {
«значимые_термы»: {
«поле»: «продукты»,
«исключить»: «яблоко»,
«min_doc_count»: 100
}
}
}
}
)

Elasticsearch вернет рекомендации с JLH балла по умолчанию, но есть диапазон доступных баллов (документация).

 {
...
"агрегаты": {
"рекомендации": {
"doc_count": 12200,
"bg_count": 130000,
"корзины": [
{
"ключ": "щенок",
"doc_count": 250,
"оценка": 0,15,
"bg_count": 320,
}
]
}
}
}

В нашем примере поиск яблока возвратил приоритетную группу из 12 200 пользователей с фоновое население в 130 000 пользователей, у которых не было яблок в их продуктах. Щенок встречался 250 раз на переднем плане и 320 раз на заднем плане.Оценка JLH представляет собой простую величину изменения между фоновой коллекцией и результатами локального поиска, представленную (fg_percentage - bg_percentage) * (fg_percentage / bg_percentage) , которая дает оценку 0,15

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

Это простая, но мощная первая итерация механизма рекомендаций, которая может быть запущена в течение недели или даже меньше! Важно отметить, что любая версия 1 не должна быть более сложной, чем эта. Время на производство гораздо важнее на ранних стадиях. Обычно вашему первому рекомендательному механизму требуется несколько итераций для оптимизации пользовательского интерфейса и UX, а не математики.

Elasticsearch - это не только очень мощный бэкэнд для рекомендаций, но и очень гибкий! Есть много вариантов улучшить нашу систему рекомендаций, сохраняя бэкэнд эластичного поиска.Выиграть!

Прочтите часть 2, чтобы ознакомиться с более сложными примерами использования, когда быстрое и простое больше не подходит:

Шаг 1:

Мы можем использовать более сложные алгоритмы, такие как ALS, для создания индикаторов для наших рекомендаций, и мы ставим эти показатели в эластичный поиск. Это упрощает оценку рекомендаций до простого просмотра, поскольку мы выполняем тяжелую работу на этапе обучения, например. используя Spark. Таким образом ,asticsearch - это просто эффективный уровень представления наших заранее рассчитанных показателей для соответствующих рекомендаций.Вы можете легко добавить это в существующий каталог продуктов в качестве новых метаданных.

Шаг 2:

В настоящее время мы используем двоичный флаг в массиве продуктов, что означает, что каждый продукт в массиве продуктов вносит одинаковый вклад в оценку JLH. Без многих изменений мы могли бы использовать некоторую метрику для оценки самого появления продукта, чтобы получить более богатый сигнал. Мы могли бы использовать счетчик кликов. Или, что еще лучше, мы могли бы использовать рейтинг кликов, нормализуя клик по средней ожидаемой величине клика по местоположению страницы, генерирующей клик.Например. в списке результатов поиска мы можем рассчитать ожидаемый CTR для элементов в первой позиции, второй и т. д. Затем мы можем рассчитать изменение величины JLH из суммы показателей метрик элементов вместо их простых подсчетов.

Шаг 3:

Пользователи обычно генерируют серию событий, имеющих отношение к рекомендациям, например, нажав на несколько товаров или добавив несколько товаров в корзину. Стоит добавить к вашему механизму рекомендаций кэш взаимодействия с пользователем (1) для создания более сложных поисковых запросов, использующих серию событий, и (2) создать дельту между пакетным процессом ETL, который обновляет индекс эластичного поиска, и взаимодействиями с пользователем, которые произошли после последнее обновление вашего рекомендательного движка.

Использование последовательности событий для выработки рекомендаций может помочь с (1) созданием более релевантных результатов и (2) увеличением числа переднего плана для генерации большего числа одновременных случаев в случае небольших объемов трафика или очень больших каталогов. Для переключения на запрос и требуется только незначительное изменение:

 es.search (
index = index, doc_type = doc_type,
body = {
"query": {
"bool": {
"should": [
{"term": {"products": "apple"}},
{"term": {"products": "pony"}},
],
" imum_should_match ": 1,
}
},
" aggs ": {
" рекомендации ": {
" значимые_термы ": {
" поле ":" продукты ",
" исключить ": [" apple "," пони " "],
" min_doc_count ": 10
}
}
}
}
)

Параметр imum_should_match позволяет оптимизировать увеличение численности населения переднего плана или повысить релевантность результатов, сопоставляя пользователей с возрастающим сходством.

Шаг 4:

В настоящее время наш поиск - это точный поиск предметов. Это имеет некоторые последствия: все, что мы узнаем из взаимодействий пользователей с точки зрения совместного использования, связано с их конкретными элементами. Когда элемент убирается из каталога продукции, мы теряем все, что узнали из него. Мы также не можем обобщать что-либо в аналогичные элементы, например, красные яблоки и зеленые яблоки являются отличительными элементами, и совместное появление ограничено точными совпадениями красных яблок или зеленых яблок.Чтобы преодолеть это, нам нужно математически описать предметы, чтобы вычислить сходство предметов. Это называется вложением. Прочитайте мой предыдущий пост в блоге, где я создаю географическую область. Другими вариантами создания вложений являются автокодеры или факторизация матрицы в модели пользовательских элементов, как описано выше. После того, как мы превратили простой product_id во вложение, мы можем использовать вероятностный или нечеткий поиск, чтобы найти нашу переднюю группу населения и / или совместные вхождения.

Это должно помочь вам начать с рекомендаций.Это также дает вам широкие возможности для построения первой итерации, извлекая уроки из обратной связи.

Первые шаги в рекомендациях стоят или падают гораздо чаще из-за UI и UX, а не из-за простоты математики.

Как правило, продукты имеют множество метаданных, которые мы должны использовать, например, цена, описания, изображения, обзоры рейтингов, сезонность, теги и категории. После того, как мы превратили богатый набор метаданных в вложение, описывающее наши продукты, мы можем обучить нейронную сеть отображать входные вложения в вложение рекомендаций, которое имеет (1) меньшую размерность и (2) желаемое поведение косинусного подобия подходящих рекомендаций, являющихся высокая.Одним из отличных решений для этого являются сиамские нейронные сети.

Входные данные представляют собой многомерный вектор составных вложений метаданных продукта. Выход нейронной сети представляет собой гораздо более компактный вектор внедрения рекомендаций. Функция ошибки определяется косинусным сходством выходных векторов. Мы можем использовать совместную фильтрацию данных, чтобы создавать метки обучения под наблюдением для комбинаций, которые должны быть одинаковыми или нет. Важно отметить, что в сиамских нейронных сетях вес обеих сетей всегда одинаков, что дает им свое имя.У двигателя с такой рекомендацией больше не будет проблем с холодным запуском! Наконец, создание рекомендации может быть выполнено с помощью поиска k-ближайших соседей вложений выходных рекомендаций.

Вы можете прочитать больше о следующих шагах в следующем:

.

Как написать собственный игровой движок на C ++

В последнее время я пишу игровой движок на C ++. Я использую его для создания маленькой мобильной игры под названием Hop Out . Вот клип, снятый с моего iPhone 6. (Включите звук!)

Hop Out - это та игра, в которую я хочу играть: ретро аркадный геймплей с трехмерным мультяшным видом. Цель состоит в том, чтобы изменить цвет каждого пэда, как в Q * Bert.

Hop Out все еще находится в разработке, но мощность его двигателя начинает становиться достаточно зрелой, поэтому я решил поделиться здесь несколькими советами по разработке двигателя.

Почему вы хотите написать игровой движок? Есть много возможных причин:

  • Вы тинкер. Вы любите строить системы с нуля и видеть, как они оживают.
  • Вы хотите узнать больше о разработке игр. Я провел 14 лет в игровой индустрии, и я до сих пор в этом разбираюсь. Я даже не был уверен, что смогу написать движок с нуля, поскольку он сильно отличается от повседневных обязанностей программиста в большой студии. Я хотел выяснить.
  • Тебе нравится контроль. Приятно организовать код именно так, как вы хотите, зная, где все всегда.
  • Вас вдохновляют классические игровые движки, такие как AGI (1984), id Tech 1 (1993), Build (1995) и отраслевые гиганты, такие как Unity и Unreal.
  • Вы считаете, что мы, игровая индустрия, должны попытаться демистифицировать процесс разработки движка. Не то чтобы мы освоили искусство создания игр. Отнюдь не! Чем больше мы исследуем этот процесс, тем больше у нас шансов улучшить его.

Игровые платформы 2017 года - мобильные, консольные и ПК - очень мощные и во многом похожи друг на друга. Разработка игрового движка - это не столько борьба со слабым и экзотическим оборудованием, сколько в прошлом. На мой взгляд, это больше о борьбе со сложностью собственного производства . Создать монстра легко! Вот почему советы в этом посте сосредоточены на том, чтобы держать вещи под контролем. Я разбил его на три части:

  1. Используйте итеративный подход
  2. Подумайте дважды, прежде чем слишком много объединять
  3. Имейте в виду, что сериализация является большой темой

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

Используйте итеративный подход

Мой первый совет - быстро запустить что-нибудь (что угодно!), А затем повторить.

Если возможно, начните с примера приложения, которое инициализирует устройство и рисует что-то на экране. В моем случае я скачал SDL, открыл Xcode-iOS / Test / TestiPhoneOS.xcodeproj , а затем запустил образец testgles2 на своем iPhone.

Вуаля! У меня был прекрасный вращающийся куб, использующий OpenGL ES 2.0.

Мой следующий шаг - загрузить 3D-модель, сделанную кем-то из Марио. Я написал быстрый и грязный загрузчик файлов OBJ - формат файла не так уж сложен - и взломал пример приложения для рендеринга Марио вместо куба.Я также интегрировал SDL_Image, чтобы помочь загрузить текстуры.

Затем я применил двойное управление для перемещения Марио. (Вначале я обдумывал создание двойного шутера. Но не с Марио.)

Затем я хотел исследовать скелетную анимацию, поэтому я открыл Blender, смоделировал щупальце и оснастил его двухкостным скелетом, который шевелился взад-вперед.

На этом этапе я отказался от формата файла OBJ и написал скрипт Python для экспорта пользовательских файлов JSON из Blender.Эти файлы JSON описывают скины с сеткой, скелет и данные анимации. Я загрузил эти файлы в игру с помощью библиотеки C ++ JSON.

Как только это сработало, я вернулся в Blender и приобрел более сложный характер. (Это был первый сфальсифицированный 3D человек, которого я когда-либо создавал. Я очень гордился им.)

В течение следующих нескольких месяцев я предпринял следующие шаги:

  • Началось выделение векторных и матричных функций в моей собственной трехмерной математической библиотеке.
  • Заменен .xcodeproj на проект CMake.
  • Получил движок на Windows и iOS, потому что мне нравится работать в Visual Studio.
  • Начал перемещать код в отдельные библиотеки «движок» и «игра». Со временем я разделил их на еще более детальные библиотеки.
  • Написал отдельное приложение для преобразования моих файлов JSON в двоичные данные, которые игра может загружать напрямую.
  • В конце концов удалил все библиотеки SDL из сборки iOS.(Сборка Windows по-прежнему использует SDL.)

Дело в том: Я не планировал архитектуру движка до того, как начал программировать . Это был осознанный выбор. Вместо этого я просто написал самый простой код, который реализовал следующую функцию, а затем я посмотрел на код, чтобы увидеть, какая архитектура возникла естественным образом. Под «архитектурой движка» я подразумеваю набор модулей, составляющих игровой движок, зависимости между этими модулями и API для взаимодействия с каждым модулем.

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

Вы можете подумать, что при таком подходе тратится много времени, так как вы всегда пишете плохой код, который необходимо очистить позже.Но большая часть очистки включает перемещение кода из одного файла .cpp в другой, извлечение объявлений функций в файлы .h или одинаково простые изменения. Решить , куда деваться , - сложная задача, и это легче сделать, когда код уже существует.

Я бы сказал, что больше времени тратится впустую при противоположном подходе: слишком стараться придумать архитектуру, которая будет делать все, что, по вашему мнению, вам понадобится раньше времени. Две из моих любимых статей об опасностях чрезмерной инженерии - «Порочный круг обобщения» Томаша Домбровского и «Не позволяйте астронавтам архитектуры пугать вас» Джоэла Спольски.

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

Итеративный подход дал мне гораздо более элегантную архитектуру, чем я когда-либо мог себе представить, глядя на чистый лист бумаги.Сборка iOS моего движка теперь на 100% оригинален, включая пользовательскую математическую библиотеку, шаблоны контейнеров, систему отражения / сериализации, фреймворк рендеринга, физику и аудио микшер. У меня были причины для написания каждого из этих модулей, но вы, возможно, не нашли необходимости писать все эти вещи самостоятельно. Существует множество отличных библиотек с открытым исходным кодом, которые вы можете найти подходящими для вашего движка. GLM, Bullet Physics и STB-заголовки - это всего лишь несколько интересных примеров.

Подумай дважды, прежде чем объединять вещи

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

Время от времени сопротивляйся принципу СУХОЙ

В качестве примера, мой движок содержит несколько шаблонных классов «умного указателя», по духу похожих на std :: shared_ptr . Каждый из них помогает предотвратить утечки памяти, выступая в качестве оболочки вокруг необработанного указателя.

  • Owned <> - для динамически размещаемых объектов, которые имеют одного владельца.
  • Ссылка <> использует подсчет ссылок, чтобы у объекта было несколько владельцев.
  • audio :: AppOwned <> используется кодом вне звукового микшера. Это позволяет игровым системам владеть объектами, которые использует звуковой микшер, например голосом, который воспроизводится в данный момент.
  • audio :: AudioHandle <> использует систему подсчета ссылок, встроенную в микшер аудио.

Может показаться, что некоторые из этих классов дублируют функциональность других в нарушение принципа СУХОЙ (не повторяй себя). Действительно, ранее в процессе разработки я пытался максимально использовать существующий класс Reference <> . Однако я обнаружил, что время жизни аудиообъекта регулируется особыми правилами: если звуковой голос закончил воспроизводить семпл, а игра не удерживает указатель на этот голос, этот голос можно сразу поставить в очередь для удаления.Если в игре есть указатель, то голосовой объект не следует удалять. И если в игре есть указатель, но владелец указателя уничтожен до того, как голос закончится, голос должен быть отменен. Вместо того, чтобы добавлять сложность к Reference <> , я решил, что было бы более практичным вместо этого ввести отдельные классы шаблонов.

95% времени, повторное использование существующего кода это путь. Но если вы начинаете чувствовать себя парализованным или обнаруживаете, что добавляете сложность чему-то, что когда-то было простым, спросите себя, должно ли что-то в кодовой базе быть двумя вещами.

Можно использовать разные соглашения о вызовах

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

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

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

  • C ++ 11 представил std :: function , который является удобным способом хранения функций обратного вызова.Также можно написать свою собственную версию std :: function , в которую менее болезненно входить в отладчике.
  • Многие функции обратного вызова могут быть реализованы с помощью пары указателей: указатель на функцию и непрозрачный аргумент. Это просто требует явного приведения внутри функции обратного вызова. Вы часто видите это в чистых библиотеках Си.
  • Иногда базовый тип фактически известен во время компиляции, и вы можете связать вызов функции без каких-либо дополнительных накладных расходов во время выполнения.Turf, библиотека, которую я использую в своем игровом движке, во многом опирается на эту технику. Смотрите, например, turf :: Mutex . Это всего лишь typedef для класса, специфичного для платформы.
  • Иногда самый простой подход состоит в том, чтобы создать и поддерживать таблицу необработанных указателей функций самостоятельно. Я использовал этот подход в своем аудио микшере и системе сериализации. Интерпретатор Python также интенсивно использует эту технику, как упомянуто ниже.
  • Вы даже можете сохранять указатели функций в хеш-таблице, используя имена функций в качестве ключей.Я использую эту технику для отправки входных событий, таких как события мультитач. Это часть стратегии - записывать входные данные игры и воспроизводить их с помощью системы воспроизведения.

Динамическая рассылка - большая тема. Я только поцарапал поверхность, чтобы показать, что есть много способов достичь этого. Чем больше вы пишете расширяемый низкоуровневый код - что часто встречается в игровом движке - тем больше вы будете искать альтернативы. Если вы не привыкли к такого рода программированию, интерпретатор Python, написанный на C, является отличным ресурсом для изучения.Он реализует мощную объектную модель: каждый PyObject указывает на PyTypeObject , а каждый PyTypeObject содержит таблицу указателей функций для динамической отправки. Документ «Определение новых типов» является хорошей отправной точкой, если вы хотите сразу перейти прямо.

Знайте, что Сериализация - Большой Субъект

Сериализация - это процесс преобразования объектов времени выполнения в последовательность байтов и из нее. Другими словами, сохранение и загрузка данных.

Для многих, если не для большинства игровых движков, игровой контент создается в различных редактируемых форматах, таких как .png , .json , .blend или проприетарные форматы, а затем в конечном итоге преобразуется в специфичные для платформы игровые форматы, которые может использовать движок. загрузить быстро. Последнее применение в этом конвейере часто называют «плитой». Плита может быть интегрирована в другой инструмент или даже распределена по нескольким машинам. Обычно плита и ряд инструментов разрабатываются и поддерживаются в тандеме с самим игровым движком.

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

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

 void load (InStream & in, u32 fileVersion) { в >> m_position; в >> m_direction; if (fileVersion> = 2) { в >> m_velocity; } } 

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

Когда вы собираете Blender из исходного кода, происходит много шагов. Сначала компилируется и запускается пользовательская утилита с именем makedna . Эта утилита анализирует набор файлов заголовков C в исходном дереве Blender, а затем выводит краткую сводку всех типов C, определенных внутри, в специальном формате, известном как SDNA. Эти данные SDNA служат данными отражения .Затем SDNA связывается с самим Blender и сохраняется с каждым файлом .blend , который записывает Blender. С этого момента, когда Blender загружает файл .blend , он сравнивает SDNA файла .blend с SDNA, связанным с текущей версией во время выполнения, и использует универсальный код сериализации для обработки любых различий. Эта стратегия дает Blender впечатляющую степень обратной и прямой совместимости. Вы все еще можете загрузить файлы 1.0 в последней версии Blender и новой версии .Файлы blend могут быть загружены в более старых версиях.

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

Очевидно, я опускаю много деталей. В этом посте я только хочу показать, что существует много разных способов сериализации данных, некоторые из которых очень сложны. Программисты просто не обсуждают сериализацию так же, как другие системы движка, хотя большинство других систем полагаются на нее. Например, из 96 докладов о программировании, представленных на GDC 2017, я насчитал 31 доклад о графике, 11 об онлайн, 10 об инструментах, 4 об искусственном интеллекте, 3 о физике, 2 об аудио - но только один, который коснулся непосредственно сериализации.

Как минимум, постарайтесь понять, насколько сложными будут ваши потребности. Если вы делаете крошечную игру, например, Flappy Bird, с несколькими активами, вам, вероятно, не нужно слишком задумываться о сериализации. Вы можете загружать текстуры непосредственно из PNG, и все будет хорошо. Если вам нужен компактный двоичный формат с обратной совместимостью, но вы не хотите разрабатывать свои собственные, взгляните на сторонние библиотеки, такие как Cereal или Boost.Serialization. Я не думаю, что Google Protocol Buffers идеально подходят для сериализации игровых ресурсов, но, тем не менее, их стоит изучить.

Написание игрового движка - даже маленького - это большое дело. Я мог бы сказать об этом гораздо больше, но для поста такой длины это, честно говоря, самый полезный совет, который я могу дать: работайте итеративно, не поддавайтесь желанию немного объединить код и знайте, что сериализация является большой предмет, так что вы можете выбрать подходящую стратегию. По моему опыту, каждая из этих вещей может стать камнем преткновения, если ее игнорировать.

Мне нравится сравнивать заметки по этому материалу, поэтому мне было бы очень интересно узнать мнение других разработчиков.Если вы написали движок, привел ли ваш опыт к каким-либо из тех же выводов? И если вы не написали ни одного, или просто думаете об этом, мне тоже интересны ваши мысли. Что вы считаете хорошим ресурсом для изучения? Какие части все еще кажутся вам загадочными? Не стесняйтесь оставлять комментарии ниже или напишите мне в Twitter!

,

Смотрите также


avtovalik.ru © 2013-2020