Spencer Ingram
Spencer Ingram

Reputation: 65

Creating a box that moves accross the screen in phaser 3

This is my code, I posted this question earlier but it was not very clear so I am making a repost The issue is in the createBox() function (or when it gets called). The box gets created once when the game starts but cannot be created again with the keypress of s. I would like help making the box spawn in when s is pressed and move across the screen. The player should be able to jump off of the box.

const config = {
  type: Phaser.AUTO,
  width: 1905,
  height: 1000,
  backgroundColor: '#000',
  physics: {
    default: 'arcade',
    arcade: {
      gravity: {
        y: 300
      },
      debug: false
    }
  },
  scene: {
    preload: preload,
    create: create,
    update: update
  }
};
const game = new Phaser.Game(config);
var player
var wait = 1
var boxes
function preload() {
  this.load.image('player', 'assets/repl.png');
  this.load.image('ocean', 'assets/water.png');
  this.load.image('background', 'assets/background.png');
  this.load.image('box', 'assets/box.png');
  this.load.image('platform1', 'assets/platform1.png');
  this.load.image('platform2', 'assets/platform2.png');
  this.load.image('platform3', 'assets/platform3.png');
  this.load.image('platform4', 'assets/platform4.png');
}

function create() {
  this.add.image(950, 450, 'background').setScale(1.4);
  this.w = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W)
  this.a = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A)
  this.s = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S)
  this.d = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D)
  waters = this.physics.add.staticGroup();
  waters.create(952, 958, 'ocean').setScale(1.4).refreshBody();

  platform1s = this.physics.add.staticGroup();
  platform1s.create(952, 858, 'platform1').setScale(0.5).refreshBody();

  player = this.physics.add.sprite(1000, 500, 'player').setScale(0.05);
  player.setCollideWorldBounds(true);

  box = this.physics.add.group();
  boxes = box.create(0, 900, 'box').setScale(0.1);
  boxes.body.setAllowGravity(false);
  boxes.setVelocityX(200)

  this.physics.add.collider(player, waters, hitWater, null, this);
  this.physics.add.collider(player, platform1s);
  // this.physics.add.collider(player, platform2s);
  // this.physics.add.collider(player, platform3s);
  // this.physics.add.collider(player, platform4s);
  this.physics.add.collider(player, boxes);
}

function update() {
  let cursors = this.input.keyboard.createCursorKeys();
  if (this.a.isDown) {
    player.setVelocityX(-300)
  } else if (this.d.isDown) {
    player.setVelocityX(300)
  } else {
    player.setVelocityX(0)
  }
  if (this.w.isDown && player.body.touching.down) {
    player.setVelocityY(-400)
  }
  if (this.s.isDown) {
    if (wait = 1) {
      createBox()
    }
  }
}
function createBox() {
  box = this.physics.add.group();
  boxes = box.create(0, 900, 'box').setScale(0.1);
  boxes.body.setAllowGravity(false);
  boxes.setVelocityX(200)
  this.physics.add.collider(player, boxes);
  this.time.delayedCall(1000, delayer, null, this);
}
function hitWater() {
  this.physics.pause();
  player.setTint(0xff0000);
  this.time.delayedCall(3000, restart, null, this);
}
function restart() {
  this.scene.stop();
  this.scene.start();
}
function delayer() {
  wait = 1
}

Upvotes: 1

Views: 410

Answers (1)

winner_joiner
winner_joiner

Reputation: 14695

the fastest solution would be to bind the scene to the function createBox in the update function:

  ...
  if (this.s.isDown) {
    if (wait == 1) {
      createBox.bind(this)(); // binding the context
    }
  }
  ...

doesn't look great but works.

bind is a javascript function that set's the this object of function, here is the documenation
createBox.bind(this) creates a new function where the this inside the function, is the passed parameter.

In most Javascript events like key-down or mouse or ... the this object is the window object, that's why you need to some set the context.

An Alternative: you could pass the scene as a parameter to the function, but for that you would have to alter the createBox function abit more:

...
if (this.s.isDown) {
    if (wait == 1) {
        createBox(this)
    }
}
...

function createBox(scene) {
    box = scene.physics.add.group();
    boxes = box.create(0, 900, 'box').setScale(0.1);
    boxes.body.setAllowGravity(false);
    boxes.setVelocityX(200)
    scene.physics.add.collider(player, boxes);
    scene.time.delayedCall(1000, delayer, null, scene);
}

Upvotes: 1

Related Questions