Вот так вот начнешь изучать фамильные портреты...
Я отдал Дейва на бета-тест Александру Шестипалову @shestipaloff и он, конечно же, нашел уже порядочно багов, за что ему огромное спасибо. Но этот глюк был с интересной историей.
В Дейве есть "телепорты" - двери, с помощью которых можно перемещаться между локациями. Чтобы уйти в такую открытую дверь, нужно нажать клавишу "вверх". На выходе Дейв оказывается прямо у "ответной" открытой двери, и если клавиша "вверх" еще не отпущена, то Дейв, конечно, уйдет обратно в телепорт. Новая локация не появляется мгновенно, и такая ситуация маловероятна, подумал я. Но иногда (очень редко) в процессе испытательных забегов я все-таки сталкивался с таким явлением. "Надо будет точки появления Дейва на выходах сделать дальше от двери", подумал я. Как еще с этим бороться? Буфер клавиатуры можно сбросить, но что если игрок пользуется джойстиком? А нефиг держать кнопку нажатой!
И вот Алекс, конечно, тоже умудрился найти этот эффект, хотя это случалось очень редко (и теперь понятно почему редко). Но именно поэтому я и отдавал ему на тест свои игры - он мучал и Принца и Goonies и находил там всякие редкие приколы.
Сначала были предположения, что это глюк эмулятора, некое залипание клавиш. Алекс сообщил, что глюк проявляется только при управлении от клавиатуры. Я сделал сброс буфера клавиатуры при выходе Дейва из двери и ничего не изменилось. Я пытался сам повторить этот глюк и у меня это долго не получалось. Но потом кааак получилось!
Конечно, я открыл отладчик и стал смотреть, что там происходит. Вот Дейв вышел из двери, вот сбросился буфер клавиатуры, все ок, уйти не должен. И вот Дейв ушел снова в дверь. Штаа?? Видимо, проблема в таблицах движений, может там не тот код движения и он зацикливается в телепортации сам на себя? А почему в других дверях не зацикливается? Да и в этой далеко не сразу зациклился. А таблицах все ок, движение "телепортация" должно перейти в "базовая стойка" и оно так и происходит. И никак Дейв не может вдруг решить уйти в дверь, только если он стоит в базовой стойке и только если нажата кнопка "вверх".
Наливаю кофе, готовлюсь к более детальной отладке. Вот Дейв телепортировался, вот он перешел в базовую стойку. Успешно сброшен буфер клавиатуры. Вот начались процедуры проверки на наличие пола под ногами, всякая мелочь... Вот Дейв смотрит в буфер клавиатуры, чтобы выяснить, что там хочет от него игрок. Ага, пусть смотрит, там же ниче... а там код клавиши "вверх".
Ну и откуда же он там взялся? Ведь никто ничего и не думал нажимать! Кто посмел его туда подсунуть? Смотрю в исходники - напрямую к регистру данных процедура выдачи нового движения не лезет. В эмуляторе GID отличный отладчик и момент доступа к ячейке буфера я нахожу быстро - и это та самая процедура получения нового движения в зависимости от управления. Она проверяет флаг "было ли прицеливание с клавиатуры" и если было - запихивает в буфер клавиатуры код клавиши "вверх". Зачем она так делает понятно, это я реализовал возможность с клавиатуры прицелиться вверх (или вниз), потом выстрелить и снова автоматически вернуться к состоянию прицеливания. Ведь на БК нельзя жать несколько клавиш одновременно, как иначе сделать прицеливание и выстрел? Я сделал вот так.
Это все хорошо, но ведь прицеливания никакого не было, Дейв просто в телепорт зашел. И вот тут начинается уже самое интересное. Дальше связь одного события с другим теряется. Прицеливания не было, но флаг (он же код клавиши, которой прицеливались) появился. Почему дальше Дейв начал таскаться в двери ясно - он думает, что нажата кнопка "вверх". Неясно, почему вдруг это произошло.
Снова берем отладчик, кофе, какой-нибудь прикольный музон, начинаем отлаживать саму процедуру телепорта. Вот ушли в дверь, надо взять параметры новой локации. Ок. Теперь надо и Дейва туда впихнуть, изменить ему координаты и все такое. Вот процедура сброса текущих данных профиля Дейва. Всяких флагов там море, так что проще их все скопом обнулить, а нужные потом сами выставятся процедурами позиционирования, надо всего лишь задать координаты и фазу движения. Сброс это просто очистка нужного участка памяти нужного разме....
А размер-то не тот! Точнее, когда-то он был верным, но профиль Дейва с тех пор вырос, в него добавились новые параметры, а очистка осталась прежней. В итоге на новом месте в параметрах Дейва некоторые данные оставались старыми. И как это до сих пор не проявилось? Ведь это происходит при каждой телепортации. Видимо, все же проявлялось, но было не так заметно. Ну или могло знатно провиться в будущем, мало ли какие сочетания параметров там возникнут. И только невинный повторный заход Дейва в дверь сигнализировал об этом. При этом недостаточно было просто зайти в дверь, в старых данных должен был торчать код прицеливания с клавиатуры! Ведь если бы этот флаг попал в диапазон все еще сбрасываемых процедурой очистки, то Дейв не стал бы ни в какие двери заходить и это осталось бы незамеченным. Или если бы клавиши прицела с клавы не совпала бы с клавишей ухода в дверь. Или если бы я просто сделал выход из двери дальше, чем вход...
Вот так знаменитый бета-тестер Алекс Шестипалов (Зоркий Глаз) помог раскрыть этот коварный заговор.
Спасибо, Алекс!
бк0011м
глюки
граблинг
баги
dave