Jump to content

Bullet scaling


NYCdotNet
 Share

Recommended Posts

I'm making a Robotron 2084 clone using some Legend of Zelda art (just for fun).

The SNES art is too small for a modern screen, so I'm scaling it up.  My problem is that the hit area of the arrows is not scaling.  Take a look at this image with debug turned on.  The green box on the arrows should be the whole arrow not the upper left corner of it (see attached gif).

There doesn't seem to be a way to set the scale for all bullets on a weapon globally so I am wondering if this is just not supported?  Is there something I can do in that forEach loop to get each bullet to scale its hitbox too?

Thanks very much.

Here's the relevant code:

let playerScale = 3;

let player = game.add.sprite(40, 100, 'linkRunning');
player.scale.setTo(playerScale, playerScale);
player.anchor.setTo(0.5, 0.5);
game.physics.enable(player, Phaser.Physics.ARCADE);

let weapon = game.add.weapon(30, 'arrow', 5);
weapon.bullets.forEach((b : Phaser.Bullet) => {
  b.scale.setTo(playerScale, playerScale);
}, this);

weapon.bulletKillType = Phaser.Weapon.KILL_WORLD_BOUNDS;
weapon.bulletSpeed = 700;
weapon.fireRate = 120;
weapon.trackSprite(player);

player.bringToTop();

 

lagging-arrow-hit-area.gif

Link to comment
Share on other sites

Probably not.  In the above code sample, I'm iterating through the weapon.bullets group and setting the scale on each bullet.  This is causing the bullets (really arrows) to draw with the correct size.  This does not seem to change the hitbox of the bullet, though.

I am loading the texture for the arrows like this in the preload function:

game.load.spritesheet('arrow', 'images/Arrow.png', 20, 20);

Is there some way to apply a scaling function to the texture itself prior to assigning it to the weapon?  Would I have to pull the arrow image out of the cache somehow to do that?

Sorry if this is a noobish question, but I have been searching through the API docs and haven't found an obvious way to do this.

Link to comment
Share on other sites

No, you're doing it right, but you've run into an Arcade Physics bug. I think it happens when:

  1. The scale of a sprite with an existing physics body is modified
  2. The sprite (or body) is reset before body.preUpdate() is called (as when a Weapon is fired)

A workaround is to call body.updateBounds() after you modify the sprite scale:

weapon.bullets.forEach((b) => {
    b.scale.setTo(playerScale, playerScale);
    b.body.updateBounds();
}, this);

 

Link to comment
Share on other sites

Actually, another related question - I've noticed that the bullet "hitbox" doesn't rotate along with the firing direction.  This probably isn't an issue with circular bullets, but with arrows it's a problem.

I'm using the following code to fire (Robotron-style controls - the second stick allows firing in 360 degrees):

  if (pad0secondstick) {
    if (pad0secondstick.x !== 0 || pad0secondstick.y !== 0) {
      weapon.fireAtXY(player.centerX + pad0secondstick.x, player.centerY + pad0secondstick.y);
    }
  }

It's not bad when firing at a slight angle, but when firing up or down, the hitbox is quite wide.

bullet hitbox not rotated.pngbullet hitbox not rotated 2.png

I tried using the body.setSize() function to set the hitbox on the arrow head - this works great when shooting right, but when shooting left, the hitbox lags behind the arrow - it's still to the right instead of rotating along with the sprite.  (it's worse when shooting up or down as the hit box is to the right of the arrow so it will incorrectly hit or miss.)

Do you think the fact that the hitbox doesn't rotate when fireAtXY is called might be a bug too?

The way I've started working around it is to call body.setSize inside a weapon.onFire event handler, using a formula based on the body.rotation value with the goal of having the hitbox be a small square that sticks to the arrowhead.  Does that sound right?  Is this definitely not something Phaser currently handles?

Thanks for all the help.

 

 

 

Link to comment
Share on other sites

In Arcade Physics the hitbox itself never rotates, that's just the nature of it. For projectiles like arrows I usually resize the hitbox into a square centered on the sprite and spanning its shorter side (here it could be 5 × 5) and it looks good enough.

But your idea of moving the hitbox onto the rotated arrowhead should work. Remember that with body.setSize you're positioning the body within the original, unscaled texture instead of the current size of the sprite (which has been scaled up). It will depend on your texture dimensions (and you may need negative offsets on the shorter axis), but I'd imagine it would include positions like

body.setSize(3, 3, 12, 6); // pointing WEST
body.setSize(3, 3, 0 , 6); // pointing EAST

If you need true polygonal projectiles you can use P2 Physics but I bet you can make this work well without it.

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...