Javascript TypeError, не может получить доступ к методам объекта - PullRequest
0 голосов
/ 07 апреля 2019

Я использую p5.js, node.js и socket.io, чтобы создать небольшую многопользовательскую игру в браузере.Объект с именем 'player' передается от одного к другому клиенту для синхронизации обоих клиентов.Это прекрасно работает для другого кода, который не зависит от вызовов методов.Но теперь, когда я также хочу получить доступ к методам хранимых объектов в объекте player, он больше не работает.

Это будет объект, который хранит все переменные и массив с объектами между двумя клиентами:

var player = {
  structures: []
};

Теперь, если я добавлю к нему объект с именем campfire следующим образом:

player.structures.push(new campfire(mouseX,mouseY));

И попробуйте вызвать метод draw () объекта campfire, который выглядит следующим образом:

class campfire {
constructor(x,y){
    this.scale = 40;
    this.x = x;
    this.y = y;
    this.maxLevel = 3;
    this.button = new button(this.x, this.y+50, this.x-50, this.y-70, upgrade, upgrade_hover, this);
    this.show_upgrade_button = true;
}

draw(){
    switch(player.campfire.level){
        case 1: image(fire, this.x, this.y, this.scale, this.scale);break;
        case 2: image(campfire_2, this.x, this.y, this.scale, this.scale);break;
        case 3: image(campfire_3, this.x, this.y, this.scale, this.scale);break;
        default: console.log("cant upgrade, this shouldn't happen.");
    }
    if(this.show_upgrade_button){
        this.button.draw();
    }
}

trigger(){      
    if(player.campfire.level + 1 <= this.maxLevel && this.show_upgrade_button == true){
        this.button.trigger();
    }
}}

с использованием

player.structures[i].draw();

Консоль (если клиент не использует объект 'campfire' для массива 'структуры') выводит следующую ошибку:

gui.js:38 Uncaught TypeError: player.structures[i].draw is not a function

Клиент, который помещает объект campfire в массив, может сделать вызов draw () и не выводит сообщение об ошибке.Однако другой клиент, который не выдвинул объект в массив, не может использовать метод и выводит ошибку, даже если они оба используют один и тот же объект player.Что странно, так это то, что тот, кто распечатывает ошибку, все еще может получить доступ ко всем переменным объекта у костра, поэтому он, похоже, влияет только на методы.

Единственный ресурс, который я нашел по этому поводу, - это статья https://airbrake.io/blog/javascript-error-handling/x-is-not-a-function-typeerror Я попытался переименовать функцию в draw = function () {} и campfire.prototype.draw = function () {}, но для меня это не имеет значения.Я думаю, что функции не объявлены правильно?Это было бы единственно возможным объяснением для меня прямо сейчас.

Спасибо, что уделили время на чтение моего вопроса!

РЕДАКТИРОВАТЬ: вот ссылка на проект: https://github.com/Mayhoon/Multiplayer-Browsergame

1 Ответ

1 голос
/ 07 апреля 2019

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

Я бы посоветовал только толкать state вперед и назад. У игрока есть молоток? Сколько жизней у игрока? У игрока есть костер? Другими словами, синхронизировать только данные, которые постоянно меняются.

Поскольку функциональность костра (функция рисования) одинакова для всех игроков, нет необходимости постоянно нажимать этот код взад-вперед каждые несколько секунд! Это довольно неэффективно!

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

В коде, который может выглядеть так (просто идея):

Синхронизирующий объект для socket.io

var player = {
  structures: {campfire:true}
};

Код клиента

// create campfire instances, tell the campfire which player it belongs to
if(player.structures.campfire) {
    let cf = new Campfire(player)
    cf.draw()
}

примечание: вполне возможно, что socket.io удаляет исполняемый код

...