英文:
Phaser : Hitbox of character move anormally since animations added
问题
I managed to fix the issue with hardcoding the position of the hitbox with
this.player.body.setOffset(28, 24);
In every case for going up, left, and right, and the same set to 0, 0 for going down, but it is something I really don't like.
Thanks everyone!
英文:
I'm new to Phaser and trying to do a top down game.
Since I added walking animations, the hitbox of my characters moves anormaly :
Going down : ok !
Any other direction : not ok !
As you can see on the images, the hitbox is correctly placed around the character when going down, but if I go up, left, or right, the hitbox is always placed at the same spot : top left of the character.
This seems to happen since I added animations.
I really don't know what to change, there is not much code about this in my project yet :
main.js
import Phaser from "./lib/phaser.js";
import Game from "./scenes/Game.js";
export default new Phaser.Game({
  type: Phaser.AUTO,
  scene: Game,
  width: 750,
  height: 500,
  autoCenter: Phaser.Scale.CENTER_BOTH,
  physics: {
    default: "arcade",
    arcade: {
      debug: true
    }
  }
});
Game.js
import Phaser from "../lib/phaser.js";
export default class Game extends Phaser.Scene {
  constructor() {
    super("game");
  }
  preload() {
    this.load.image("tiles", "assets/MasterSimple.png");
    this.load.image("character", "../../assets/Player/idle/idle down1.png");
    // Marche
    this.load.image("wd1", "../../assets/Player/walk/walk down1.png");
    this.load.image("wd2", "../../assets/Player/walk/walk down2.png");
    this.load.image("wd3", "../../assets/Player/walk/walk down3.png");
    this.load.image("wd4", "../../assets/Player/walk/walk down4.png");
    this.load.image("wu1", "../../assets/Player/walk/walk up1.png");
    this.load.image("wu2", "../../assets/Player/walk/walk up2.png");
    this.load.image("wu3", "../../assets/Player/walk/walk up3.png");
    this.load.image("wu4", "../../assets/Player/walk/walk up4.png");
    this.load.image("wl1", "../../assets/Player/walk/walk left1.png");
    this.load.image("wl2", "../../assets/Player/walk/walk left2.png");
    this.load.image("wl3", "../../assets/Player/walk/walk left3.png");
    this.load.image("wl4", "../../assets/Player/walk/walk left4.png");
    this.load.image("wr1", "../../assets/Player/walk/walk right1.png");
    this.load.image("wr2", "../../assets/Player/walk/walk right2.png");
    this.load.image("wr3", "../../assets/Player/walk/walk right3.png");
    this.load.image("wr4", "../../assets/Player/walk/walk right4.png");
    this.load.tilemapTiledJSON("level1", "assets/level1.json");
  }
  create() {
    const level1 = this.make.tilemap({
      key: "level1",
      tileWidth: 16,
      tileHeight: 16,
    });
    const tileset = level1.addTilesetImage("MasterSimple", "tiles");
    // Calques
    const eauLayer = level1.createLayer("eau", tileset, 0, 0);
    eauLayer.scale = 3;
    const solLayer = level1.createLayer("sol", tileset, 0, 0);
    solLayer.scale = 3;
    const murLayer = level1.createLayer("mur", tileset, 0, 0);
    murLayer.scale = 3;
    // Personnages
    this.player = this.physics.add.sprite(500, 300, "character").setScale(3.5);
    this.cursors = this.input.keyboard.createCursorKeys();
    this.physics.add.collider(this.player, eauLayer);
    eauLayer.setCollisionBetween(81, 82);
    this.physics.add.collider(this.player, murLayer);
    murLayer.setCollisionBetween(110, 140);
    // Animations
    // Vers le bas
    const walkDownFrames = [
      { key: "wd1" },
      { key: "wd2" },
      { key: "wd3" },
      { key: "wd4" },
    ];
    this.anims.create({
      key: "walkDown",
      frames: walkDownFrames,
      frameRate: 10,
      repeat: -1,
    });
    // Vers le haut
    const walkUpFrames = [
      { key: "wu1" },
      { key: "wu2" },
      { key: "wu3" },
      { key: "wu4" },
    ];
    this.anims.create({
      key: "walkUp",
      frames: walkUpFrames,
      frameRate: 10,
      repeat: -1,
    });
    // Vers la gauche
    const walkLeftFrames = [
      { key: "wl1" },
      { key: "wl2" },
      { key: "wl3" },
      { key: "wl4" },
    ];
    this.anims.create({
      key: "walkLeft",
      frames: walkLeftFrames,
      frameRate: 10,
      repeat: -1,
    });
    // Vers la droite
    const walkRightFrames = [
      { key: "wr1" },
      { key: "wr2" },
      { key: "wr3" },
      { key: "wr4" },
    ];
    this.anims.create({
      key: "walkRight",
      frames: walkRightFrames,
      frameRate: 10,
      repeat: -1,
    });
    // Camera
    this.cameras.main.startFollow(this.player);
  }
  update() {
    this.player.setVelocityY(0);
    this.player.setVelocityX(0);
    const speed = 300;
    if (this.cursors.up.isDown) {
      this.player.setVelocityY(-speed);
      this.player.anims.play("walkUp", true);
    } else if (this.cursors.down.isDown) {
      this.player.setVelocityY(speed);
      this.player.anims.play("walkDown", true);
    } else if (this.cursors.left.isDown) {
      this.player.setVelocityX(-speed);
      this.player.anims.play("walkLeft", true);
    } else if (this.cursors.right.isDown) {
      this.player.setVelocityX(speed);
      this.player.anims.play("walkRight", true);
    } else {
      this.player.anims.stop();
    }
  }
}
I managed to fix the issue with hardcoding the position of the hitbox with
this.player.body.setOffset(28,24);
In every case for going up, left, and right, and the same set to 0, 0 for going down, but it is something I really don't like.
Thanks everyone !
答案1
得分: 0
问题可能与图像的大小以及Sprite对象的缩放有关。用于创建Sprite对象的键/图像应具有与动画的frameSize完全相同的尺寸,否则物理体可能会偏移。
信息: 由于缩放,即使有轻微的偏移也会导致更大的偏移。
这里有一个演示展示了这个问题:
初始纹理用于创建物理体的大小和位置。
document.body.style = 'margin:0;';
var config = {
    type: Phaser.AUTO,
    width: 536,
    height: 183,
    physics: {
        default: 'arcade',
        arcade: {            
            gravity:{ y: 0 },
            debug: true
        }
    },
    scene: { preload, create }
}; 
function preload(){
    this.load.spritesheet('brawler', 'https://labs.phaser.io/assets/animations/brawler48x48.png', { frameWidth: 48, frameHeight: 48 });
}
function create () {
    this.add.text(10, 10, 'Wrong Sprite')
        .setScale(1.5)
        .setOrigin(0)
        .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
        
    this.add.text(260, 10, 'Correct Sprite')
        .setScale(1.5)
        .setOrigin(0)
        .setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
    let graphics  = this.make.graphics();
    graphics.fillStyle(0xffffff);
    graphics.fillRect(0, 0, 10, 10);
    graphics.generateTexture('img', 10, 10);
    
    // just one animation for testing
    this.anims.create({
        key: 'walk',
        frames: this.anims.generateFrameNumbers('brawler', { frames: [ 0, 1, 2, 3 ] }),
        frameRate: 8,
        repeat: -1
    });
    
    let wrongSprite = this.physics.add.sprite(50, 50, 'img').setScale(2).setOrigin(0);
    wrongSprite.play('walk')
    
    let correctSprite = this.physics.add.sprite(270, 50, 'brawler').setScale(2).setOrigin(0);
    correctSprite.play('walk')
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
(请注意,这是代码的翻译,不包括代码本身。)
英文:
The problem has probably to do with the sizes of the images and also the scaling of the Sprite object. They key / image used to create the Sprite object, should have the exact dimensions of the frameSize of the animations, if not the physics body, can be offset.
> Info: And due to the scaling even an minor offset can cause much bigger offset.
Here a demo show casing this problem:
The initial texture is use to create the size and position of the physics body.
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {            
gravity:{ y: 0 },
debug: true
}
},
scene: { preload, create }
}; 
function preload(){
this.load.spritesheet('brawler', 'https://labs.phaser.io/assets/animations/brawler48x48.png', { frameWidth: 48, frameHeight: 48 });
}
function create () {
this.add.text(10, 10, 'Wrong Sprite')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
this.add.text(260, 10, 'Correct Sprite')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
let graphics  = this.make.graphics();
graphics.fillStyle(0xffffff);
graphics.fillRect(0, 0, 10, 10);
graphics.generateTexture('img', 10, 10);
// just one animation for testing
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('brawler', { frames: [ 0, 1, 2, 3 ] }),
frameRate: 8,
repeat: -1
});
let wrongSprite = this.physics.add.sprite(50, 50, 'img').setScale(2).setOrigin(0);
wrongSprite.play('walk')
let correctSprite = this.physics.add.sprite(270, 50, 'brawler').setScale(2).setOrigin(0);
correctSprite.play('walk')
}
new Phaser.Game(config);
<!-- language: lang-html -->
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论