Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте

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

    Разработка Need For Speed III Modern Patch

    Вообще я достаточно редко играю в компьютерные игры. Бывало, не играл по несколько лет подряд. Но иногда во мне просыпается маленький реверс-инженер, который мотивирует меня забраться в машинный код какой-нибудь любимой игрушки из прошлого. В последний год я занимался доработкой Need For Speed III: Hot Pursuit (1998 года). Это моя любимая игра в жанре, но теперь я, к своему сожалению, знаю о том, насколько отвратительно она написана. Большое количество маленьких багов в самых неожиданных местах — прямое следствие низкого качества кода.

    Насколько всё плохо?


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

    Сколько ошибок может быть в 4 вариантах одного и того же кода?


    В игре присутствовал один незначительный баг, связанный с отступами в выпадающих меню. Например, если был выбран режим «Hot Pursuit», левый отступ всех верхних выпадающих списков значительно увеличивался без явной на то необходимости.

    image image

    Я предположил, что это связано с ошибкой в коде, который добавляет пространство для вывода иконок прохождения в выпадающем списке трасс, которые как раз и должны отображаться только в режиме «Hot Pursuit».

    image image

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

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

    Так оказалось и здесь. Поскольку в меню используется два разных типа выпадающих списков (обычный и верхний), весь код работы с ними был целиком продублирован дважды. Помимо этого оказалось, что левый отступ выбирается разными фрагментами кода при вычислении левой и правой границы выпадающего списка. Итого — по идее у нас должно быть 4 копии одного и того же кода. Как бы не так!

    Вариант 1 (при вычислении отступа левой границы обычной выпадашки):
    image
    На C это выглядело примерно так:
    dw_padding = (stricmp(str_element_name, "tracks") == 0 && dw_cfg_race_type == 3) ? 35 : 15;
    

    Вариант 2 (при вычислении отступа правой границы обычной выпадашки):
    image
    На C это выглядело примерно так:
    dw_padding = (stricmp(str_element_name, "tracks") == 0 || stricmp(str_element_name, "rectrk") == 0) ? 35 : 15;
    

    Варианты 3 и 4 (при вычислении отступа левой и правой границ выпадашки под заголовком):
    image image
    На C это выглядело примерно так:
    dw_padding = (dw_cfg_race_type == 3) ? 35 : 15;
    

    Все варианты вместе (для наглядности):
    dw_padding = (stricmp(str_element_name, "tracks") == 0 && dw_cfg_race_type == 3) ? 35 : 15;
    dw_padding = (stricmp(str_element_name, "tracks") == 0 || stricmp(str_element_name, "rectrk") == 0) ? 35 : 15;
    dw_padding = (dw_cfg_race_type == 3) ? 35 : 15;
    

    Какой же вариант правильный? Ответ: ни один! Только если мы объединим все проверки вместе, мы можем получить единственно верный вариант кода, и выглядел бы он примерно так:
    dw_padding = (dw_cfg_race_type == 3 && (stricmp(str_element_name, "tracks") == 0 || stricmp(str_element_name, "rectrk") == 0)) ? 35 : 15;
    

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

    Как это было исправлено?


    О том, как вносятся изменения в машинный код, я писал ранее. Для исправления проблемы я написал одну функцию:
    image
    Все приведённые выше фрагменты кода были заменены на вызов этой функции. Теперь отступы в списках выбираются правильно :) И это лишь одно из более чем 200 изменений, которые были сделаны в патче. Описанное изменение на самом деле одно из самых маленьких, но зато сама ошибка, на мой взгляд, была интересной (как демонстрация вреда от соответствующего антипаттерна).

    Выводы?


    А теперь подумайте. Если здесь нашёлся самозванец, который взялся исправлять без спроса чужие баги в программе без исходных кодов, может найтись и тот, кто в итоге будет настолько зол, что у него появится желание отыскать разработчика или его родственников. А оно вам надо? Пишите качественный код :)
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 86
    • +1
      Может и было раньше просто зависимость от race_type, а потом надобавляли сравнение строк. В одном месте сработало, а в других не сработало. По идее это «нормально». Просто наверное минорным багом посчитали и так и не пофиксили. Люди и не с такими багами в релиз идут.
      • +14
        Это да, просто забавно, что 3 разные ошибки в 4 вариантах одного кода, и при этом ни один вариант не является правильным. На самом деле в этом патче было исправлено большое количество серьёзных проблем, связанных с падениями и зависаниями, но удивительными они мне не показались. Хотя описание поиска и исправление одного deadlock хотелось бы описать в будущем, там был любопытный случай, который связан как раз с с тем, что (судя по всему) забыли удалить один уже ненужный вызов. Как раз и демонстрация работы с WinDbg будет.
        • +8
          Было бы очень интересно почитать про это.
      • +6
        Сегодня читал чей-то класс на 2500 строк, глаза болели от ужасного кода, а больнее всего было в сотый раз натыкаться на комментарий:
        "//TODO: сделать нормально"

        Не сделали…
        • +9
          2500? Tюю. Да это же так, мелочь пузатая :) В проекте сишный код достался из начала 90х, там файлы по 15-20к строк плюс заголовочные с десятками включений.

          А TODO это хорошо, говорит о том, что человек знал что делает, что это плохо и места пометил для потомков. Некоторые даже не понимают, что они плохо делают, потом рефакторинг зубы ломает.
          • +1
            Просто загляните в исходники андроида. Там 2500 строк — это обыденность. Вот пример:
            androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
            • 0
              подумаешь 2500… Более известный пример это android TextView.
              Вот сейчас там 10к строк androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/widget/TextView.java
              • 0
                а наследуется он от View на 22к строк… http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/View.java
                • 0
                  В исходниках Clang-а, есть модуль Sema — семантика языка С++. Там SemaOverload.cpp — 12к строк, другие классы ненамного меньше. Но меня больше если честно не размер cpp убивал, а хедеров… очень тяжело ориентироваться.
          • –11

            ты псих

            • +15
              Полагаю, в данном случае уместнее будет термин «благородное безумие».
          • +4
            В качестве комментария к предыдущей статье: я предпочитаю патчи делать прокси-дллками системных если честно. По большей части (что конечно тоже само по себе в какой-то мере грязный хак) можно в DllMain сделать все нужные патчи, в том числе с помощью VirtualProtect изменить нужные страницы памяти на чтение и подправить асм код на свой, либо просто записать long jump на свою процедуру, скомпиленную с __declspec(naked), а потом push addr, retn для возврата обратно.
            • +3
              Аналогично, и под линукс это делать куда проще, через LD_PRELOAD. Использую простую функцию:
              #define UNPROTECT(addr,len) (mprotect((void*)(addr-(addr%len)),len,PROT_READ|PROT_WRITE|PROT_EXEC))
              
              void detour_function(void * new_adr, int addr)
              {
                  int call = (int)(new_adr - addr - 5);
                  UNPROTECT(addr, 4096);
                  *((unsigned char*)(addr)) = 0xE9;
                  *((int*)(addr + 1)) = call;
              }

              Потом достаточно написать свои функции и перенаправить вызов:
              detour_function(&hasp_init_game, (int)0x080BD120);

              Очень просто и быстро. А если нужна поддержка разных версий, то есть еще и код, который ищет функцию в заданном адресном промежутке по ее сигнатуре.
              • 0
                Однако, такой подход выглядит достаточно костыльным. Вместо того, чтобы исправить проблему «на месте», предлагается создавать отдельную сущность (загрузчик или прокси-dll), которая будет при каждой загрузке на лету вносить те же изменения в машинный код исходной программы в памяти.

                Вообще я бы подключал код на C++ только в случае переписывания огромных частей кода. Например, в NFS3 меню заточено строго под 640×480, и для поддержки современных разрешений его по хорошему нужно полностью переписать (и перерисовать всю соответствующую графику). Вот при такой переделке я бы стал писать новый код уже на C++ :)
                • +2
                  Зато можно писать комментарии к каждому патчу, включать и выключать их по отдельности. Но, согласен, иногда проще и пропатчить файл. Но если у вас игра, к которой постоянно выходят обновления, но вы замучаетесь патчить ее каждый раз, все равно придется делать либо лоадер, либо динамический патчер.
                  • 0
                    Позволяет не модифицировать исходные бинари. Что вызовет элементарный механизм отключения патчей если вдруг что не то, да и вообще очень сильно упрощает установку — согласитесь, гораздо проще просто закинуть в папку лишнюю длл чем, собственно, заменять (а ещё лучше сначала забэкапить оригинал!) файл. Плюс может динамически апплаиться к нескольким версиям файлов если сделать либо чек версии, либо просто патч по паттерну который слабо изменяется — конечно не совсем касается ретро-игр, но тем не менее.

                    Теоретически с легальной точки зрения всё тоже проще, но тут к юристам лучше, наверное не всё так просто.
              • +12
                Есть 2 момента:
                1) Вполне возможно, что и с таким кривым исполнением Need For Speed III была весьма рентабельна для производителя. Если юзер не видит бага (а юзер не будет в коде ковыряться) — проблемы для рынка условно нет.
                2) Бывает еще, что начальство бегает и орет: «Где результат, млин? Сроки прошли!». В такой ситуации человеку придется делать кое-как с комментариями "//TODO: сделать нормально". Ибо кушать хочется, дети малые дома сидят, ипотека не плачена…
                • 0
                  Batman: Arkham Knight с его кривым исполнением тоже наверняка был рентабельным, хоть его проблемы и видны юзерам.
                  • 0

                    На PC не был. Деньги вернули и если, что и заработали, то только на тех кто не успел вернуть деньгу.

                    • 0
                      Steamspy говорит о 550к владельцах бэтмена. Думаю, затраты на портирование более чем окупились.
                      • 0
                        Я купил, потому что пол Free Edition прошел, и не так уж он и баговал если честно… Особенно текущая версия в стим
                        • 0
                          Не знаю насчёт текущей версии, но пару месяцев назад она была всё ещё не очень.
                          • 0
                            Я если честно вообще ни разу не натыкался на баг с полётом, хотя играю на мыше :) Единственное под конец игры она начинает фризится сильно, но ssd решил и эту проблему
                            • 0
                              Возможно зависит от железа. Я закончил прохождение игры 11.10.2015. и у меня работало все идеально. Скорей всего из-за плохого портирования она потребляет огромное и неоправданное кол-во процессорного времени и оперативной памяти. По этому у кого мощный ПК мог проблем и не заметить.
                              • 0
                                Предполагают, что Denuvo тоже влияет на производительность.
                    • +4
                      К сожалению, уже через несколько лет код этой игры начал ломаться, что точно было заметно пользователям. Например, в рендерере DX6 поддерживаемые форматы текстур записывались в массив из 14 элементов, и если система поддерживает больше — переполнение буфера и падение при запуске. В результате пользователи ругали производителей драйверов (это можно найти на форумах), что при обновлении драйвера версии X на более новую версию X+1 игра начинала падать. А ведь на самом деле драйвер просто узнал о каком-то новом формате текстур, и это объективно хорошо. Это в игре была заложена бомба замедленного действия. И это далеко не единственный пример.
                      • +9
                        Ага. И обычно после такого производитель драйверов вставляет в новую версию драйвера код:
                        if (Process_Is_NFS3()) { отдавать старый список форматов текстур };
                        • 0
                          А это вечная практика всех разработчиков. Всеми любимый windows тому пример — вставим таких костылей для стороннего софта (а то покупатель обидится, что его симсити не работает под новой операционкой). Windows не пример? — okay, скатимся в древность и к железу — award bios: обработка исключений для десятка PCI плат расширения (пара звуковушек и S3Trio там были точно), мегакостыльный обработчик int 13h с фиксами для некоторых устройств. А дрова nvidia, ну тут можно и нижнюю челюсть вывихнуть, если посмотреть сколько там индивидуальных настроек для кучи .exe файлов валяется.
                      • +1
                        Многие клиенты/начальники между «идеальный код» и «относительно вовремя и работает» выберут второе. Потому что идеальным кодом не выплатить зарплаты и дивиденды, не заплатить за офис, да и просто тупо не выйти на рынок.

                        Вспоминается история Oracle, где пока их конкуренты вдумчиво пилили что-то, ораклы методом «херак херак и в продакшн» получили рабочий (более-менее) продукт и начали получать заказы от крупных клиентов, в том числе военщины.
                        • НЛО прилетело и опубликовало эту надпись здесь
                      • 0
                        Сам не успел, т.к. на работе, но брат, сорокадвухлетний бородач уже рубится. Спасибо!
                        • +1
                          Может брата тоже на работу устроить?))
                        • +1
                          После прочтения заголовка думал, что будет процитирована вся история с ныне мёртвого ItHappens: Адекватный друг и абсолютный глюк (http://ithappens.me/story/11872/
                          По теме: копипаста действительно может сыграть злую шутку, так как можно не учесть условия применимости используемых кусков, как указано в посте — ещё и с ошибками.
                          • +4

                            Если вы про фразу в заголовке статьи, то фраза старая и встречается у многих авторов. Обычно приписывают Стиву Макконелу, в Code Complete.

                            • 0
                              Понятно. Я имел в виду, что подобный рассказ неплохо подходит для затравки, по аналогии с картинкой для привлечения внимания.
                              • 0
                                Но это не его фраза тоже. Он на ее авторство и не претендует. И вроде в его книге я встречал указание на кого-то конкретного, но может ошибаюсь. В электронном варианте нашел один случай упоминания — автором значится Аноним.
                              • +1
                                Кстати, есть информация, что с ним случилось? А то как-то я захожу, а новых историй нет… И молчание везде.
                                • +4
                                  Думаю, уволился копирайтер, придумывавший все истории.
                                  • –1
                                    Мне они не казались выдуманными. Вполне себе «айтишный башорг», там даже иногда были перепалки, ответ на ответ на ответ на… Нужно обладать очень богатой фантазией, чтобы достоверно придумать подобное.
                                    • +2
                                      Ну по крайней мере та история, на которую сослался AiMAX, выглядит выдуманной (или по крайней мере сильно преувеличенной).
                                      • 0
                                        Ну да, там её больше для юмора, наверное, выложили.
                                  • 0
                                    Кстати, есть информация, что с ним случилось
                                    Да я сам хотел бы знать. Тоже искал — нигде никакой информации, а уже больше года с последнего «поста» прошло про сильных программистов… Только и остается, что перечитывать старые истории, поностальгировать, так сказать…
                                    Хотя один плюс в этом есть — IThappens хотя бы остался до самого своего конца «айтишным», а вот с того же Баша, как писали недавно на нём же, сначала исчезли айтишные шутки и истории, потом — околоайтишные, а затем и просто шутки, а остались срачи.
                                  • +2
                                    http://stackoverflow.com/questions/876089/who-wrote-this-programing-saying-always-code-as-if-the-guy-who-ends-up-maintai

                                    Bill Mitchell View profile More options Sep 26 1991, 1:57 am In article <5...@ksr.com> j...@ksr.com (John F. Woods) writes:

                                    [...] Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. Code for readability.
                                    Damn right!


                                    1991 year — OMG!
                                  • +1

                                    Каждый раз, когда вижу вот такие реверс-инженерные статьи, я восхищаюсь авторами.
                                    Но смотря на вроде бы знакомые команды в целом нефига не понятно.
                                    Поэтому вопрос: в какую сторону покурить, чтобы быть немного в теме? (Так-то некоторые представления об ассемблере х86 имею, писал на нем, правда совсем чуть-чуть). Какие программные средства используются для этого дела?


                                    Пример непоняток

                                    image
                                    Что это за блоки кода с соединительными линиями?

                                    • +1

                                      Для реверса часто используется IDA (скрины оттуда же) (https://ru.wikipedia.org/wiki/IDA).
                                      Красные/зелёные стрелки для обозначения перехода по ложному/истинному условию, синие для безусловного перехода.

                                      • 0

                                        Спасибо. Я был знаком только с OllyDbg, там все выглядело несколько иначе

                                      • +1
                                        К IDA есть ещё HexRays который может попытаться представить это всё дело как Си код. Получается не всегда хорошо, но значительно облегчает жизнь.
                                        • 0
                                          HexRays весело плющит, когда он натыкается на оптимизации компиляторов. В часности вызов функции из массива, который казалось-бы выглядит примерно как(до оптимизации, и чего тут оптимизировать)
                                          mov eax, ds:[functable+ebx*4h]
                                          call eax

                                          он раскрывал в полный ужас, понять который было нереально.
                                          Хотя согласен, длинные функции с кучей параметров через него изучать проще.
                                          • +1
                                            Скорее уж «получается обычно отвратно». Честно. Понять только какие-то оч простые вещи можно, но не более.
                                            • 0
                                              Тут зависит от того что исследуешь. Иногда если разобраться как хранятся стуктуры и ткнуть его носом где что получается Си код который можно спокойно копипастить ещё куда нибудь. Ну а если что то современное написанное с использованием всяких Boost, Qt и прочего то да зачастую только хуже.
                                        • +2
                                          NFS3 навевает приятные воспоминания. Мне тоже кажется лучшей частью в серии. А может просто ностальгия.
                                          • 0
                                            Не глядя на косяки, NFS3 всё равно классная. Перед тем, как взяться за патч, я пробовал разные варианты на замену, но ничего не зацепило. Не исключаю, что это синдром утёнка. Вообще в современных гонках, как оказалось, сплит-скрин уже не обязательная возможность. А для меня это обязательная возможность, потому что я играю в гонки (и другие игры) как раз тогда, когда кто-нибудь ко мне заглянет в гости поболтать. С геймпадами, сидя на диване, а не как в детстве, два человека за одной клавиатурой.
                                            • 0
                                              Вообще в современных гонках, как оказалось, сплит-скрин уже не обязательная возможность. А для меня это обязательная возможность, потому что я играю в гонки (и другие игры) как раз тогда, когда кто-нибудь ко мне заглянет в гости поболтать. С геймпадами, сидя на диване, а не как в детстве, два человека за одной клавиатурой.

                                              И подобный oldschool, я считаю, здорово. У меня так вообще эти гонки прошли в основном под знаком PS1. Кстати, интересно было бы сравнить код с консольной версией.
                                              • 0
                                                Судя по всему, какую-то часть кода они делят между собой. Я встречал остатки хардкода, которые предназначались для пасхальных трасс, которые были в NFS3 PS1, но которых не было в NFS3 PC (PC-версия вышла после PS1-версии).
                                                • 0
                                                  Интересно было бы увидеть еще статьи на подобные темы. Особенно связанные со старыми играми, когда деревья были толще и небо зеленее.
                                              • 0
                                                «С геймпадами, сидя на диване, а не как в детстве, два человека за одной клавиатурой.»

                                                Планируете поддержку Xinput?
                                                • 0
                                                  Оно и без Xinput хорошо работает. Единственное, что хотелось бы изменить умолчания для Xbox-совместимых геймпадов. И ещё меню научить управлению с геймпадов. Но сейчас уже не будет времени заниматься проектом, так что если это и будет в патче, то не скоро. Сейчас в меню управляюсь с небольшой беспроводной клавиатуры — это не такое уж и значительное неудобство.
                                              • 0
                                                ИМХО лучшей по физике и атмосфере была Posche Unleashed. Особенно в золотую эру, раздолбать машину при заносе было абсолютно не проблема. Плюс самые красоты Европы (ну конечно схематично, но зачем нам воображение то?), Пирнеи, Шварцвальд, Альпы, Автобан, Корсика и т.д.
                                                • 0
                                                  В плане красот Европы соглашусь. Я в эту часть играл просто наслаждаясь видами.
                                              • 0
                                                Спасибо за патчи! Круто, когда есть запал и навыки, чтобы реверсить в свободное время.)
                                                Кстати, в 1998 году вышла еще одна крутая и сильно багованная игра — Trespasser. И у нее тоже есть фанаты, которые реверсом и такой-то матерью делают патчи, улучшают движок и даже добавляют новые уровни…
                                              • 0
                                                Эх, круто! Завидую — откуда ж столько свободного времени?

                                                Сам раньше часто ковырялся в игрушках популярных, иногда код вызывает ночные кошмары, когда видишь, например, что все данные сделаны глобально статическими и доступны просто отовсюду из любой функции! Удобно ж блин! :D

                                                Зато потом за свой код не стыдно особо, когда видишь, что мировые гиганты пишут такое говно в продакшн.
                                                • +6
                                                  Для тех, кто не в теме:

                                                  EA Games прославилась как самая соковыжимающая компания. Переработки обязательны. Разработчики в кубиклах и ящики редбула. (Довольно известная история, с фотографиями и десятилетиями обсуждения)

                                                  И уже давно ДОКАЗАНО, что те 60-80 часов в неделю, которые EA Games требует привели к меньшей эффективности, чем традиционные 40 часов.
                                                  Насколько я знаю они не меняли подхода к разработке до сих пор.

                                                  Так, что эти глупые ошибки делали Сишные программисты-зомби в анабиозе. (Не стеляйте программиста, пристрелите таких управленцев)
                                                  • 0
                                                    Программисты не имеют сознания и воли? Если 60-80 часов и низкая производительность, значит это их добровольный выбор.
                                                    • 0
                                                      в США не существует каких-либо обязательных норм про 40 часов. Так что выбора немного.
                                                      • 0
                                                        Наоборот, это и показывает что выбор был их решением. Даже с наличием норм по 40 часам у нас в России, вы можете работать и 20 и 10 часов. Запретить никто не может.
                                                      • 0
                                                        А давайте сейчас все руку на сердце положим. Геймдев и 40 часов? Не верю. Галенкин в подкасте тоже как-то шутил на эту тему…
                                                    • 0
                                                      Женя, ты хексрейсом часто пользуешься или все по хардкору?
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                        • +2
                                                          Такой подход плох тем, что вместо кода «отражения» модели трассы в одном единственном месте программы, разработчику необходимо не забывать вставлять соответствующую проверку и инверсию в каждом месте кода, где используется «лево» и «право», то есть это будет размазано по всему проекту. И разработчики таки забыли об этом, о чём было рассказано :) Проблему с отражёнными надписями на машинах нужно решать созданием отдельного варианта текстур с надписями, где надписи будут отражены, что тоже достаточно странно.

                                                          Хотя, конечно, реализация этого костыльного метода была сама по себе проще, и на реализацию переворачивания модели трассы при загрузке наверняка ушло бы больше времени. Зато было бы надёжнее :)
                                                          • –1
                                                            а что мешает менять прям в рендере а не везде7
                                                            • +2
                                                              Потому что где находится «лево» и «право» важно не только при рендеринге. Начинаем мы с того, что добавляем условие, которое инвертирует «право» и «лево» в коде ввода. Затем оказывается, что код отрисовки руля (при виде «из кабины») тоже нужно переделать, иначе он будет визуально поварачиваться не в ту сторону. Потом мы вспоминаем, что когда копы ставят шипы, по рации можно услышать, с какой стороны дороги они их поставили, и это тоже нужно не забыть инвертировать… Ну и в этом духе.
                                                              • –1
                                                                я бы сделал класс для этого.
                                                                • +3
                                                                  И что этот класс будет делать? Это ведь вмешательство в совершенно разные части программы, и по условию «включен режим отражённой трассы» подпирать всё придётся разными костылями. Где-то умножить на -1, где-то инвертировать булево значение, где-то вместо одной текстуры прочитать другую (с отражёнными надписями). А где-то об этом можно просто случайно забыть, что разработчики NFS3 и сделали.
                                                                  • –1
                                                                    он будет хранить все правила.
                                                                    • +2
                                                                      Изъясните понятнее свою мысль. Что за правила он будет хранить и как он будет это делать? Какую проблему это решит? Почему из-за вашего предложения этот подход перестанет быть костыльным?
                                                                • 0
                                                                  Про руль не понял. Я жму влево, это на этапе ввода интерпретируется как «вправо», соот-но руль поворачивается вправо, но зеркально отражается, и я вижу поворот влево. Зачем дополнительно менять отображение руля?

                                                                  update: или кабина там позже рисуется и не отображается зеркально?
                                                                  • +1
                                                                    Салон авто не отражается, машина из леворульной не превращается в праворульную. Он там выводится так же, как HUD, то есть просто накладывается поверх изображения.
                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                            • +1
                                                              потому что через 20 лет какой-нибудь маньяк будет изучать и дорабатывать машинный код вашего продукта, и он может захотеть вас найти
                                                              Если кто-то через 20 лет захочет изучить и доработать ваш код это значит, что вы написали очень хорошую программу иначе ее бы давным давно выкинули на свалку.
                                                              • +1
                                                                Игры столько лет спустя ценят не за код, а за геймплей. Ничто не мешает хорошей внешне программе иметь отвратительный код.
                                                              • +1
                                                                обожаю такие посты! автору желаю вдохновения и времени для новых.
                                                                • +1
                                                                  Пишите код так, будто маньяк, который захочет вас убить — это вы сами.
                                                                  • 0
                                                                    Если уровень понимания, как там всё работает и устроено столь велик, то может быть стоило бы подумать о свободной реализации этой игрушки с ресурсами из оригинальной игры?
                                                                    • 0
                                                                      Всё же исправить основные ошибки в существующей программе как-то проще, нежели написать 1 в 1 с нуля. Настолько глубокого понимания кода, чтобы переписать его целиком на C++, нет. Если работать над таким в одиночку — это задача не на один год, как мне кажется.

                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.