Phaser:添加动画后,角色的碰撞框移动异常

huangapple go评论131阅读模式
英文:

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 = &#39;margin:0;&#39;;
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: &#39;arcade&#39;,
arcade: {            
gravity:{ y: 0 },
debug: true
}
},
scene: { preload, create }
}; 
function preload(){
this.load.spritesheet(&#39;brawler&#39;, &#39;https://labs.phaser.io/assets/animations/brawler48x48.png&#39;, { frameWidth: 48, frameHeight: 48 });
}
function create () {
this.add.text(10, 10, &#39;Wrong Sprite&#39;)
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: &#39;bold&#39;, fontFamily: &#39;Arial&#39;});
this.add.text(260, 10, &#39;Correct Sprite&#39;)
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: &#39;bold&#39;, fontFamily: &#39;Arial&#39;});
let graphics  = this.make.graphics();
graphics.fillStyle(0xffffff);
graphics.fillRect(0, 0, 10, 10);
graphics.generateTexture(&#39;img&#39;, 10, 10);
// just one animation for testing
this.anims.create({
key: &#39;walk&#39;,
frames: this.anims.generateFrameNumbers(&#39;brawler&#39;, { frames: [ 0, 1, 2, 3 ] }),
frameRate: 8,
repeat: -1
});
let wrongSprite = this.physics.add.sprite(50, 50, &#39;img&#39;).setScale(2).setOrigin(0);
wrongSprite.play(&#39;walk&#39;)
let correctSprite = this.physics.add.sprite(270, 50, &#39;brawler&#39;).setScale(2).setOrigin(0);
correctSprite.play(&#39;walk&#39;)
}
new Phaser.Game(config);

<!-- language: lang-html -->

&lt;script src=&quot;//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月29日 23:25:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582491.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定