Почему игрок зависает при попытке вернуться со второй сцены на первую?

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

Дальнейшее объяснение:

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

Это клиентский код.

class FirstScene extends Phaser.Scene {
  constructor() {
    super({ key: 'first' });
  }

  init(data) {
    console.info('Updating FirstScene');
  }

  preload() {
    this.load.image('player', 'assets/player.png');
    this.load.image('otherPlayer', 'assets/player.png');
    this.load.image('mouse', 'assets/mouse.png');
  }

  create() {
    cursors = this.input.keyboard.createCursorKeys();
    let self = this;
    socket.on('currentPlayers', players => {
      Object.keys(players).forEach(playerId => {
        if (playerId === this.socket.id) {
          addPlayer(this, players[playerId]);
        } else {
          addOtherPlayers(this, players[playerId]);
        }
      });
    });

    socket.on('newPlayer', playerInfo => {
      addOtherPlayers(this, playerInfo);
    });

    socket.on('disconnectPlayer', playerId => {
      otherPlayers[playerId].destroy();
      delete otherPlayers[playerId];
    });

    socket.on('playerMoved', playerInfo => {
      otherPlayers[playerInfo.playerId].x = playerInfo.x;
      otherPlayers[playerInfo.playerId].y = playerInfo.y;
    });

    socket.on('mouseSpawned', mouseInfo => {
      const mouse = this.add.sprite(mouseInfo.x, mouseInfo.y, 'mouse').setDisplaySize(50, 50);
      mouse.id = mouseInfo.id;
      mice[mouse.id] = mouse;
    });

    addPlayer(this, { x: 400, y: 500 }); // temp location
    const trigger = this.add.rectangle(400, -12, 100, 100, 0xffffff).setDisplaySize(50, 50);
    // Define the collider after the player has been created
    this.physics.add.existing(trigger);
    trigger.body.setImmovable(true);
    this.physics.add.collider(player, trigger, () => {
      this.scene.switch('second');   
    });
  }

  update() {
    if (player) {
      if (cursors.left.isDown) {
        player.setVelocityX(-160);
      } else if (cursors.right.isDown) {
        player.setVelocityX(160);
      } else {
        player.setVelocityX(0);
      }
      if (cursors.up.isDown) {
        player.setVelocityY(-160);
      } else if (cursors.down.isDown) {
         player.setVelocityY(160);
      } else {
        player.setVelocityY(0);
      }
      socket.emit('playerMovement', { x: player.x, y: player.y });
    }
  }
}

class SecondScene extends Phaser.Scene {
  constructor() {
    super({ key: 'second' });
  }

  preload() {
    this.load.image('player', 'assets/player.png');
    this.load.image('otherPlayer', 'assets/player.png');
    this.load.image('mouse', 'assets/mouse.png');
    this.load.image('background', 'assets/background.png');
  }

  create() {
    cursors = this.input.keyboard.createCursorKeys();
    let self = this;
    this.add.sprite(0, 0, 'background').setOrigin(0, 0);

    socket.on('currentPlayers', players => {
      Object.keys(players).forEach(playerId => {
        if (playerId === this.socket.id) {
          addPlayer(this, players[playerId]);
        } else {
          addOtherPlayers(this, players[playerId]);
        }
      });
    });

    socket.on('newPlayer', playerInfo => {
      addOtherPlayers(this, playerInfo);
    });

    socket.on('disconnectPlayer', playerId => {
      otherPlayers[playerId].destroy();
      delete otherPlayers[playerId];
    });

    socket.on('playerMoved', playerInfo => {
      otherPlayers[playerInfo.playerId].x = playerInfo.x;
      otherPlayers[playerInfo.playerId].y = playerInfo.y;
    });

    socket.on('mouseSpawned', mouseInfo => {
      const mouse = this.add.sprite(mouseInfo.x, mouseInfo.y, 'mouse').setDisplaySize(50, 50);
      mouse.id = mouseInfo.id;
      mice[mouse.id] = mouse;
    });

    addPlayer(this, { x: 400, y: 500 }); // temp location

    const trigger = this.add.rectangle(400, -12, 100, 100, 0xffffff).setDisplaySize(50, 50);

    // Define the collider after the player has been created
    this.physics.add.existing(trigger);
    trigger.body.setImmovable(true);
    this.physics.add.collider(player, trigger, () => {
      this.scene.switch('first');
    });
  }

  update() {
    if (player) {
      if (cursors.left.isDown) {
        player.setVelocityX(-160);
      } else if (cursors.right.isDown) {
        player.setVelocityX(160);
      } else {
        player.setVelocityX(0);
      }
      if (cursors.up.isDown) {
        player.setVelocityY(-160);
      } else if (cursors.down.isDown) {
         player.setVelocityY(160);
      } else {
        player.setVelocityY(0);
      }

      socket.emit('playerMovement', { x: player.x, y: player.y });
    }
  }
}

const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 0 }
    }
  },
  scene: [FirstScene, SecondScene]
};

const game = new Phaser.Game(config);
const socket = io();
let cursors;
let otherPlayers = {};
let mice = {};
let player;

function addPlayer(self, playerInfo) {
  player = self.physics.add.image(playerInfo.x, playerInfo.y, 'player').setDisplaySize(200, 200);
  player.setCollideWorldBounds(true);
}

function addOtherPlayers(self, playerInfo) {
  const otherPlayer = self.add.sprite(playerInfo.x, playerInfo.y, 'otherPlayer').setDisplaySize(200, 200);
    otherPlayer.playerId = playerInfo.playerId;
    otherPlayers[playerInfo.playerId] = otherPlayer;
}

Возможно, уточните, что здесь означает «попытка вернуться к первому из второго».

Mark Schultheiss 02.05.2023 19:02

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

Kory 02.05.2023 19:06

update называется? Вы пытались установить точку останова и выполнить код с помощью отладчика?

jabaa 02.05.2023 19:23

FWIW Такое ощущение, что update() { может быть в одном месте с параметром player и вызывается, а не в двух, чтобы сделать его более СУХИМ.

Mark Schultheiss 02.05.2023 19:54

@Kory проверьте консоль браузера на наличие ошибки. Приложения Phaser зависают при возникновении ошибки

winner_joiner 02.05.2023 19:57

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

winner_joiner 03.05.2023 10:18
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
6
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, я предполагаю, что ошибка возникает из-за того, что player создается/устанавливается в сцене first, а не больше в сцене second, И в функции update смысла second вы обращаетесь к переменной player. (Или это может быть бесконечный цикл для одной и той же позиции триггера в обеих сценах)

Лучшим решением было бы использовать свойство игрока, а не глобальную переменную. как this.player = .... вам нужно будет создать проигрыватель в каждой сцене и/или передать данные, которыми нужно поделиться.

Информация: Если зависает игра/приложение Phaser, лучшим решением будет проверить консоль браузера на наличие ошибок. Таким образом, вы можете найти причину проблемы, довольно быстро.

Здесь работает урезанная версия вашего кода с вышеупомянутой коррекцией (минус материал сокета):

document.body.style = 'margin:0;';

const TEMP_LOCATION =  { x: 20, y: 20 };

class FirstScene extends Phaser.Scene {
  constructor() {
    super({ key: 'first' });
  }

  init(data) {
    console.info('Updating FirstScene');
  }

  create() {
    this.add.text(10,10, 'SCENE 1');
    this.cursors = this.input.keyboard.createCursorKeys();
   
    addPlayer(this, TEMP_LOCATION); 
    
    const trigger = this.add.rectangle(400, -12, 100, 100, 0xffffff).setDisplaySize(50, 50);
    // Define the collider after the player has been created
    this.physics.add.existing(trigger, true);
    
    this.physics.add.collider(this.player, trigger, () => {
      this.scene.switch('second');   
    });
  }

  update() {
    if (this.player) {
      if (this.cursors.left.isDown) {
        this.player.setVelocityX(-160);
      } else if (this.cursors.right.isDown) {
        this.player.setVelocityX(160);
      } else {
        this.player.setVelocityX(0);
      }
      if (this.cursors.up.isDown) {
        this.player.setVelocityY(-160);
      } else if (this.cursors.down.isDown) {
         this.player.setVelocityY(160);
      } else {
        this.player.setVelocityY(0);
      }
    }
  }
}

class SecondScene extends Phaser.Scene {
  constructor() {
    super({ key: 'second' });
  }

  create() {
    this.add.text(10,10, 'SCENE 2');
    this.cursors = this.input.keyboard.createCursorKeys();
    addPlayer(this, TEMP_LOCATION); // temp location

    const trigger = this.add.rectangle(400, -12, 100, 100, 0xffffff).setDisplaySize(50, 50);

    // Define the collider after the player has been created
    this.physics.add.existing(trigger, true);
    this.physics.add.collider(this.player, trigger, () => {
      this.scene.switch('first');
    });
  }

  update() {
    if (this.player) {
      if (this.cursors.left.isDown) {
        this.player.setVelocityX(-160);
      } else if (this.cursors.right.isDown) {
        this.player.setVelocityX(160);
      } else {
        this.player.setVelocityX(0);
      }
      if (this.cursors.up.isDown) {
        this.player.setVelocityY(-160);
      } else if (this.cursors.down.isDown) {
         this.player.setVelocityY(160);
      } else {
        this.player.setVelocityY(0);
      }
    }
  }
}

const config = {
  type: Phaser.AUTO,
  width: 536,
  height: 183,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: { y: 0 }
    }
  },
  scene: [FirstScene, SecondScene]
};

const game = new Phaser.Game(config);

function addPlayer(self, playerInfo) {
  self.player = self.physics.add.image(playerInfo.x, playerInfo.y, 'player');
  self.player.setCollideWorldBounds(true);
}
    <script src = "//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

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

Некоторая очистка кода:

class BaseScene extends Phaser.Scene {
    constructor(key) {
        super({ key });
    }

    create() {
        this.cursors = this.input.keyboard.createCursorKeys();
        addPlayer(this, TEMP_LOCATION);
        // and other duplicate code
        // ...
    }

    update() {
        if (this.player) {
            if (this.cursors.left.isDown) {
                this.player.setVelocityX(-160);
            } else if (this.cursors.right.isDown) {
                this.player.setVelocityX(160);
            } else {
                this.player.setVelocityX(0);
            }
            if (this.cursors.up.isDown) {
                this.player.setVelocityY(-160);
            } else if (this.cursors.down.isDown) {
                this.player.setVelocityY(160);
            } else {
                this.player.setVelocityY(0);
            }
        }
    }
}

class FirstScene extends BaseScene {
    constructor() {
        super('first');
    }

    create() {
        super.create();
        // other none duplicate code
        // ...
    }

    update() {
        super.update();
        // other none duplicate code
        // ...
    }
}

class SecondScene extends BaseScene {
    constructor() {
        super('second' );
    }

    create() {
        super.create();
        // other none duplicate code
        // ...
    }

    update() {
        super.update();
        // other none duplicate code
        // ...
    }
}

Другие вопросы по теме