1

I have a player sprite 'this.player' and a weapon sprite 'this.weapon'. I want to attach the weapon around my characters body. My updated code will be on https://replit.com/@JackF99/test-2d-array#script.js. My current code is pasted below,

    const map = getMap();
  //Declare variables at the top of code
  let random;
  //Create phaser settings
  let config = {
    type: Phaser.AUTO,
    width: 1000,
    height: 500,
    physics: {
        default: 'arcade',
        arcade: {
            gravity: {
                y: 0
            },
            debug: false
        }
    },
    scene: {
        preload: preload,
        create: create,
        update: update
    }
  };
  //Create phaser game
  const game = new Phaser.Game(config);
  
  function preload() {
    //Preloading assets needed
    this.load.spritesheet("player", "assets/sprites/player.png", {
        frameWidth: 16,
        frameHeight: 30
    });
    this.load.spritesheet("weapon", "assets/sprites/attack.png", {
        frameWidth: 10,
        frameHeight: 22
    });
    this.load.spritesheet("spikes", "assets/sprites/spikes.png", {
        frameWidth: 16,
        frameHeight: 16
    });
  
    this.load.image("floor", "assets/tiles/floor.png");
    this.load.image("floor_1", "assets/tiles/floor_1.png");
    this.load.image("floor_2", "assets/tiles/floor_2.png");
    this.load.image("floor_3", "assets/tiles/floor_3.png");
    this.load.image("floor_4", "assets/tiles/floor_4.png");
    this.load.image("floor_5", "assets/tiles/floor_5.png");
    this.load.image("floor_6", "assets/tiles/floor_6.png");
    this.load.image("floor_7", "assets/tiles/floor_7.png");
  
    this.load.image("wallLeft", "assets/tiles/wallLeft.png");
    this.load.image("wallRight", "assets/tiles/wallRight.png");
    this.load.image("wallBottom", "assets/tiles/wallBottom.png");
    this.load.image("wallTop", "assets/tiles/wallTop.png");
    this.load.image("bg", "assets/tiles/bg.png");
  }
  
  function create() {
    //Spawn player with restrictions
    //Declare Static objects
    this.wall = this.physics.add.staticGroup();
    this.bg = this.physics.add.staticGroup();
    this.floor = this.physics.add.staticGroup();
    this.spikes = this.physics.add.staticGroup();
    //Generate Map
    let mapArr = map.split('.');
    let drawX = 0;
    let drawY = 0;
    mapArr.forEach(row => {
        drawX = 0;
        for (let a = 0; a < row.length; a++) {
            random = Math.floor(Math.random() * (15 - 0) + 1);
            if (row.charAt(a) == 0) {
                this.bg.create(drawX, drawY, "bg");
            } else if (row.charAt(a) == 1) {
                this.floor.create(drawX, drawY, "floor");
          var container = this.add.container(drawX, drawY);
              var sprite0=this.add.sprite(0, 0, "player");
          var sprite1=this.add.sprite(10, 2, "weapon");
          container.add([ sprite0, sprite1 ]);
            this.physics.add.collider(container, this.wall);
            this.cameras.main.startFollow(container);
            } else if (row.charAt(a) == 7) {
                if (random == 1) {
                    this.floor.create(drawX, drawY, "floor_1");
                } else if (random == 2) {
                    this.floor.create(drawX, drawY, "floor_2");
                } else if (random == 3) {
                    this.floor.create(drawX, drawY, "floor_3");
                } else if (random == 4) {
                    this.floor.create(drawX, drawY, "floor_4");
                } else if (random == 5) {
                    this.floor.create(drawX, drawY, "floor_5");
                } else if (random == 6) {
                    this.floor.create(drawX, drawY, "floor_6");
                } else if (random == 7) {
                    this.floor.create(drawX, drawY, "floor_7");
                } else if (random == 8) {
            //this.physics.add.sprite(drawX, drawY, "spikes");
            this.spikes.create(drawX, drawY, "spikes");
                } else {
                    this.floor.create(drawX, drawY, "floor");
                }
            } else if (row.charAt(a) == 8) {
                this.wall.create(drawX, drawY, "wallBottom");
            } else if (row.charAt(a) == 9) {
                this.wall.create(drawX, drawY, "wallTop");
            } else if (row.charAt(a) == 6) {
                this.wall.create(drawX, drawY, "wallRight");
            } else if (row.charAt(a) == 5) {
                this.wall.create(drawX, drawY, "wallLeft");
            } else if (row.charAt(a) == 4) {
                this.floor.create(drawX, drawY, "floor");
            }
            drawX += 16;
        }
        drawY += 16;
    });
    //Generate player above map images
    container.depth=100;
    this.cameras.main.setZoom(2);
    //Create animations
    this.anims.create({
        key: "walk",
        frames: this.anims.generateFrameNumbers('player', {
            start: 4,
            end: 7,
            first: 4
        }),
        frameRate: 10,
        repeat: -1
    });
    this.anims.create({
        key: "stand",
        frames: this.anims.generateFrameNumbers('player', {
            start: 0,
            end: 3,
            first: 0
        }),
        frameRate: 1,
        repeat: -1
    });
    this.anims.create({
        key: "attack",
        frames: this.anims.generateFrameNumbers('weapon', {
            start: 0,
            end: 5,
            first: 0
        }),
        frameRate: 15,
        repeat: 0
    });
    this.anims.create({
        key: "weapon",
        frames: this.anims.generateFrameNumbers('weapon', {
            start: 6,
            end: 6,
            first: 6
        }),
        frameRate: 1,
        repeat: 1
    });
    this.anims.create({
        key: "spikes",
        frames: this.anims.generateFrameNumbers('spikes', {
            start: 0,
            end: 3,
            first: 0
        }),
        frameRate: 1,
        repeat: -1
    });
    //Declare Keys used in  game
    this.key_W = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
    this.key_A = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
    this.key_S = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
    this.key_D = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
    this.key_Q = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q);
    //Container
    this.spikes.playAnimation('spikes');
  }
  function update() {
    //Apply animations
    //this.spikes.play('spikes');
    //Setting player animations and movement
    if (this.key_A.isDown) {
        this.player.setVelocityX(-200);
      this.attack.setVelocityX(-200);
        this.player.anims.play("walk", true);
        this.player.flipX = true;
      this.attack.flipX = true;
    } else if (this.key_D.isDown) {
        this.player.setVelocityX(200);
      this.attack.setVelocityX(200);
        this.player.anims.play("walk", true);
        this.player.flipX = false;
      this.attack.flipX = false;
    } else if (this.key_W.isDown) {
        this.player.setVelocityY(-200);
      this.attack.setVelocityY(-200);
        this.player.anims.play("walk", true);
    } else if (this.key_S.isDown) {
        this.player.setVelocityY(200);
      this.attack.setVelocityY(200);
        this.player.anims.play("walk", true);
    } else if (this.key_Q.isDown) {
      this.attack.anims.play("attack", true);
      this.player.setVelocityX(0);
      this.attack.setVelocityY(0);
    } else {
        this.player.anims.play("stand", true);
      this.attack.anims.play("sword",true);
        this.player.setVelocityX(0);
        this.player.setVelocityY(0);
      this.attack.setVelocityX(0);
        this.attack.setVelocityY(0);
    }
  }
  //END OF GAME

I tried using a container, but the floor is overlapping the character and none of my update function stuff will load. (Could you show me how to use the animations and movement code with container and help me find why it wont work?

this.player = this.physics.add.sprite(drawX, drawY, "player");
        this.player.body.setGravityY(0);
        this.physics.add.collider(this.player, this.wall);
          this.physics.add.collider(this.player, this.attack);
        this.cameras.main.startFollow(this.player);
        this.player.depth=100;

    if (this.key_A.isDown) {
        this.player.setVelocityX(-200);
      this.attack.setVelocityX(-200);
        this.player.anims.play("walk", true);
        this.player.flipX = true;
      this.attack.flipX = true;
      ...
    }

I want to implement all of this code with the player in a container.

winner_joiner
  • 12,173
  • 4
  • 36
  • 61
JackF99
  • 125
  • 6

1 Answers1

1

Well there are several things you would have to do:

  1. create a container add the player and the sword/weapon (I would keep the this.player and this.sword properties, so that I can access them later in the update function):

    ...
    else if (row.charAt(a) == 1) {
        this.floor.create(drawX, drawY, "floor");
        // I call the container "cPlayer" to show it is the container
        this.cPlayer = this.add.container(drawX, drawY);
        // like this the player sprite is still accessible
        this.player = this.add.sprite(0, 0, "player");
        // like this the weapon sprite is still accessible
        this.sword = this.add.sprite(10, 2, "weapon");
    
        // set the size of the container (for the physics body )
        this.cPlayer.setSize(16,16); // I'm Just guessing the size
    
        this.physics.add.existing(this.cPlayer)
    
        this.cPlayer.add([ this.player, this.sword ]);
        this.physics.add.collider(this.cPlayer, this.wall);
        this.cameras.main.startFollow(this.cPlayer);
    } 
    ...
    
  2. Now you can update the update function, to move only the container:

     function update() {
    
         if (this.key_Q.isDown) {
             this.sword.play("attack", true);
         } else {
             this.sword.play("sword", true)
         }
    
         if (this.key_A.isDown) {
             this.cPlayer.body.setVelocityX(-200);
             // Flip the Container with the scale function
             this.cPlayer.setScale(-1,1);
             this.player.play("walk", true);
         } else if (this.key_D.isDown) {
             this.cPlayer.body.setVelocityX(200);
             // Flip the Container with the scale function
             this.cPlayer.setScale(1);
             this.player.play("walk", true);
         } else if (this.key_W.isDown) {
             this.cPlayer.body.setVelocityY(-200);
             // Flip the Container with the scale function
             this.cPlayer.setScale(1);
             this.player.play("walk", true);
         } else if (this.key_S.isDown) {
             this.cPlayer.body.setVelocityY(200);
             // Flip the Container with the scale function
             this.cPlayer.setScale(1);
             this.player.play("walk", true);
         } else {
             this.player.play("stand", true);
             this.attack.play("sword", true);
             // Flip the Container with the scale function
             this.cPlayer.setScale(1);
             this.cPlayer.body.setVelocity(0);                
         }
     }
    

Some side notes:

  1. So that the rendering works, with the right depth sorting, I would suggest adding this 3 lines at the end of the create function. Using the setDepth function on a group sets it for all the children. In your case, if you don't set this, after about 100 tiles the player would be below the tiles:

     this.cPlayer.setDepth(100);
     this.bg.setDepth(1);
     this.floor.setDepth(2);
     this.wall.setDepth(3);
    
  2. The Container doesn't work 100% like other GameObjects, as mentioned in the documentation (first paragraph). Check the documenation if something doesn't work as expected.

  3. I would really recommend looking into Tilemap of phaser, you can save alot of time and build on functionality that works out-of-the-box. Code checkout this example with an array or here is the whole official tilemap collection.

winner_joiner
  • 12,173
  • 4
  • 36
  • 61
  • The movement wont work with the code you wrote. Everything else works great. Specifically this code wont work after I tested it this.cPlayer.setVelocityX(-200);. Ill let you know if I find a fix. Also, thx 4 help and recommendations I will try to use tilemap tonight. – JackF99 Apr 13 '23 at 17:36
  • @JackF99 For the movement you need to use `this.cPlayer.body.setVelocityX(-200)` the **body** part is missing, on all the velocity lines. I couldn't test the code, so sadly I made a mistake. Sorry for that. I updated my answer to me more accurate, I hope I didn't miss anything else. Thank you for your feedback. – winner_joiner Apr 13 '23 at 20:20
  • when I move left I am able to walk through walls. Do you have any idea why and how to fix that? I just tested and, this.cPlayer.setScale(-1, 1); allows the player to walk through the walls. – JackF99 Apr 13 '23 at 21:02
  • Best way to find this issue is to turn on the physics debug option to see the collision boxes. because of the `setScale` the box might be flipped. just add the `debug` property into the game config and set it to `true`. to see the boxes. you might have to move the container on _flipping_ it. – winner_joiner Apr 13 '23 at 21:09
  • Yeah, it works now. I tried to create a tile map but Im not sure why its not working. I created a new post if u dont mind looking at it https://stackoverflow.com/questions/76010712/how-to-make-my-2d-array-into-a-map-using-tile-map-phaser. For the tile map im not sure how I would create a collider between the walls and the player, and it just wont show up for me right now. – JackF99 Apr 14 '23 at 00:16