Не поддается обновление сцены вручную

Больше
10 года 4 мес. назад - 10 года 4 мес. назад #87824 от Logan
Вношу дополнения в плагин, который, изменяет внешний вид окна Статуса героев.
Пытаюсь через свою функцию вызвать обновление информации в окне, не загружая это же окно по-новой.
Но что-то я недопонял в синтаксисе и сломал голову об следующую ошибку:

Упрощенная часть кода:
Code:
/// Моя функция: LMV_CharacterProfileScene.prototype.manualRun = function() { LMV_CharacterProfileScene.prototype.nextIndex(); }; /// LMV_CharacterProfileScene.prototype.nextIndex = function() { ++ this._index; if($gameSystem._characterOnProfile[this._index] === undefined || $gameSystem._characterOnProfile[this._index] === null) this._index = 0; this.refreshActor(); } LMV_CharacterProfileScene.prototype.refreshActor = function() { this._statusWindow.setActor($gameSystem._characterOnProfile[this._index]); this._statusWindow.activate(); };

То есть, я пытаюсь вызвать nextIndex(), который в свою очередь запускает this.refreshActor(), который выдает ошибку при обращении к setActor:
Code:
TypeError: Cannot read property 'setActor' of undefined at LMV_CharacterProfileScene.refreshActor

Не могу понять, почему эта ошибка появляется, так как эти же функции исправно обрабатываются при инициализации сцены? И нет ошибок, если ткнуть в эту клавишу, что меня еще больше запутывает:
Code:
... this._statusWindow.setHandler('pagedown', this.nextIndex.bind(this)); ...
Последнее редактирование: 10 года 4 мес. назад пользователем Logan.

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

3 место Готв Учитель 2 место
Больше
10 года 4 мес. назад - 10 года 4 мес. назад #87825 от EvilCat
Похоже, это типичный случай потери контекста - распространённая специфическая ошибка в Яваскрипте при начале его изучения.

При вызове метода его контекст (содержимое this) задаётся не тем, как был объявлен метод и где хранится, а тем, как он был вызван. Например, такая конструкция:
Code:
var obj= { f: function() { console.log(this); } } var obj2={} obj2.method=obj.f; var f=obj.f; obj.f(); obj2.method(); f();

В этом коде создаётся объект с методом f, который печатает в консоль контекст вызова. Затем создаётся ещё один объект, и в его поле method записывается метод f первого объекта. Затем поочерёдно этот метод вызывается у первого объекта, у второго и самостоятельно. В консоли будет видно, что содержимое this определяется тем, что стоит слева от точки при вызове; и в последнем случае оно будет пустым.
Code:
this._statusWindow.setHandler('pagedown', this.nextIndex.bind(this));

Здесь в качестве хендлера устанавливается не сам метод nextIndex, а его вызов с заданным контекстом. Именно этот вызов возвращает bind(this). Такую привязку приходится делать в Яваскрипте довольно часто.

Посмотри свой код. Где-то искомый метод вызывается без контекста или с неправильным контекстом слева от точки.

Ну точно. Нужно исправить так:
Code:
LMV_CharacterProfileScene.prototype.manualRun = function() { this.nextIndex(); };

См. мануалы call , apply , bind .
Последнее редактирование: 10 года 4 мес. назад пользователем EvilCat.

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

Больше
10 года 4 мес. назад - 10 года 4 мес. назад #87827 от Logan
Спасибо за мануалы, повкуриваю.

EvilCat пишет: Ну точно. Нужно исправить так:

Code:
LMV_CharacterProfileScene.prototype.manualRun = function() { this.nextIndex(); };


Не помогло, та же ошибка:




Вариант
Code:
LMV_CharacterProfileScene.prototype.nextIndex.call(this);
то же эту ошибку выдает.
Последнее редактирование: 10 года 4 мес. назад пользователем Logan.

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

3 место Готв Учитель 2 место
Больше
10 года 4 мес. назад #87842 от EvilCat
Ну, теперь-то this точно должен быть правильный... Раньше он был объектом-прототипом вместо искомого объекта.

Значит, в этой строчке
Code:
this._statusWindow.setActor($gameSystem._characterOnProfile[this._index]);

this._statusWindow разрешается как undefined, то есть, поле не задано. Я бы поставила там останов и посмотрела, что там действительно есть у контекстного объекта.

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

Больше
10 года 4 мес. назад - 10 года 4 мес. назад #87855 от Logan

EvilCat пишет:

Code:
this._statusWindow.setActor($gameSystem._characterOnProfile[this._index]);

this._statusWindow разрешается как undefined, то есть, поле не задано.


Не понял, то есть, он определен при инициализации, но не при вызове из моей функции?

EvilCat пишет: Я бы поставила там останов и посмотрела, что там действительно есть у контекстного объекта.

Oк. Как это сделать?
Последнее редактирование: 10 года 4 мес. назад пользователем Logan.

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

3 место Готв Учитель 2 место
Больше
10 года 4 мес. назад #87856 от EvilCat

Не понял, то есть, он определен при инициализации, но не при вызове из моей фунуции?


В Яваскрипте очень мало понятия о приватности, так что если он при вызове функции не определяется, то разве что если он был удалён в какой-то момент после инициализации...

Ок. Как это сделать?


Во время прогона игры нажми F8, чтобы показать отладчик (ну, это ты явно уже знаешь). В отладчике есть вкладка Sources, где находятся исходники скриптов. В js/plugins найди свой плагин и нужную строчку. Ты можешь даже перейти на неё автоматически из сообщения об ошибке в консоли. Кликни сбоку (слева) от строчки два раза, чтобы поставить там останов. Или, кажется, можно кликнуть правой кнопкой мыши на строчку и выбрать "Toggle Breakpoint". После этого нажми F5, чтобы перезапустить игру (не закрывай её вручную, потому что тогда все настройки отладчика сбросятся).

Когда игра дойдёт до отмеченной строчки, она остановится: ты увидишь это в отладчике. Сбоку будет панель текущими значениями разных переменных - локально объявленных и значение this... Ещё там будет стёк вызовов, а сверху - панелька Watch, где вообще можно ввести любые выражения и названия переменных, чтобы подсмотреть их. Массивы и объекты можно раскрывать, чтобы смотреть их содержимое. В общем, таким образом можно получить, что именно данный вызов считает за this и есть ли у него _statusWindow.

Единственная трудность может возникнуть в том, что иногда MV запускает те или иные плагины в "виртуальной машине". Не знаю, когда и зачем, но тогда остановы не действуют. Отличить виртуальную машину можно по тому, что лист с кодом будет жёлтого цвета, а сверху около названия файла будет написано "VM". Кажется, он делает это довольно бессистемно, возможно, в зависимости от тормозов или количество обращений к скрипту.

Если ты сможешь дать мне код или проект в целом, я с интересом попробую найти ошибку.
Спасибо сказали: RastaManGames, KageDesu, Logan

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

Больше
10 года 4 мес. назад - 10 года 4 мес. назад #87857 от Logan
Если есть желание посмотреть на код в целом, лучше выложу проект) По-немногу выявление проблемы затянется на длинную переписку.

www.dropbox.com/s/pcnt6tc3yb2uhzl/Test.exe?dl=0

Я убрал из проекта все лишние плагины, очистил карты - оставил то, что относится к вопросу.


Думаю, с комментариями все будет понятно, что я делал, но опишу на всякий случай:

Старался я добавить в плагин Профилей окно с выбором персонажей из другого плагина. Своим нубским кодингом заставил окно работать, затем пытался связать выбор необходимого персонажа с обновлением информации о нем. То есть, менять номер требуемого актера и запускать refreshActor. В результате мой франкенштейн стал выводить ошибки, поэтому, я пробовал различные комбинации, обращался к другим плагинам и т.д и т.п. - то, что закомменченно в строках 390-393 - это мусор от попыток, не имеет смысла для этого плагина.

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

Номера строк с моим кодом:
276
320
347

Я весь за, если появится желание доработать плагин.
Последнее редактирование: 10 года 4 мес. назад пользователем Logan.
Спасибо сказали: RastaManGames

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

Больше
10 года 4 мес. назад #87862 от KageDesu
Привет, Logan.
Проблема твоя была не в функции, а в её вызове.

В строке 384: if (v == 0){LMV_CharacterProfileScene.prototype.manualRun();} - так делать нельзя.
Получается ты вызываешь метод класса LMV_CharacterProfileScene, а надо метод объекта класса.

Поменяй строку 384 на такую: if (v == 0){this.stage.manualRun();}
В данном контексте stage - это сцена родитель, т.е. объект LMV_CharacterProfileScene.
Спасибо сказали: Logan

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

Больше
10 года 4 мес. назад #87864 от Logan
Заработало, спасибо большое!

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

3 место Готв Учитель 2 место
Больше
10 года 4 мес. назад #87869 от EvilCat
Спасибо, KageDesu! А я даже посмотреть не успела %)

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

Время создания страницы: 0.109 секунд
Работает на Kunena форум