I'm working on a 2D space shooter type of game in typescript using Phaser 3 and am trying to get a parallax background with different depths going. But I'm having trouble getting the math right.
You can see my work in progress here: https://www.youtube.com/watch?v=Pea9yVbTD64
As stated in the video everything works if the players x and y are positive, but breaks when they are negative, and I can't figure out what I am doing wrong. Any help would be greatly appreciated. Or perhaps there is a better way to accomplish this?
What I'm doing is randomly generating out a bunch of the Sprites, storing them in an Array
, and then updating their position with this code.
- _Nebulas: is an
Array<NebulaParticle>
. - p.distance: is a number between 1 and 5 to signify how far away the sprite is and is used to make them move slower when they are furher away.
- _Width and _Height are both arbitrary numbers to signify how big the area is that the parallax should cover, in the video they are both set to 80.
- OriginalOffsetX/Y is the original random position the Sprite was given.
(this line is here because the below code formatting wont work otherwise.)
public update(delta: number, playerx: number, playery: number) {
console.log(playerx + ", " + playery );
for (let i = 0; i < this._Nebulas.length; i++) {
let p = this._Nebulas[i];
p._Sprite.x = (playerx + (this._Width / 2)) - (((playerx / p.distance) + p.OriginalOffsetX) % this._Width);
p._Sprite.y = (playery + (this._Width / 2)) - (((playery / p.distance) + p.OriginalOffsetY) % this._Height);
}
}
class NebulaParticle {
public _Sprite: Phaser.GameObjects.Sprite;
public OriginalOffsetX: number;
public OriginalOffsetY: number;
public distance: number;
}
2 Answers 2
The reason you're having trouble is the behaviour of the modulo operator %
in JavaScript. (And therefore in TypeScript.) If the dividend is negative then the remainder will also be negative:
console.log((-729) % 100); // -29
and your code is assuming that the result of a division modulo d
will always fall into the range 0
to d
, when in fact it falls into the range -d
to d
.
My usual workaround is to add another copy of the modulo at the end, to force the result to be positive, and then take the modulus again. So add this line:
p._Sprite.x = (playerx + (this._Width / 2)) - (((playerx / p.distance) + p.OriginalOffsetX) % this._Width);
p._Sprite.x = (p._Sprite.x + this._Width) % this._Width;
and the same for the y-coordinate.
-
\$\begingroup\$ I know this question is nearly 7 years old, but it got bumped to the front page and I figured I might as well answer it while it's there. \$\endgroup\$Toph– Toph2025年09月08日 13:10:09 +00:00Commented 2 days ago
Just use a camera with the gameobject method setScrollFactor
. Setting 0 makes it fixed to the camera; setting a number between 0-1 will make it scroll at varying rates, which you can use to set up parallax scrolling layers.
See an example here
-
\$\begingroup\$ Thank you, but I can get this to work, the problem comes in when I want to loop around an object so that when it leaves the trailing edge it comes in on the leading one. That is I want the parallax background to be infinite and self looping in all directions forever. \$\endgroup\$JensB– JensB2018年12月05日 08:03:29 +00:00Commented Dec 5, 2018 at 8:03
-
\$\begingroup\$ In the example you linked the hotdog should come back in on the leading edge when it goes out of the screen view from being left behind, it's that part which I can't get right. \$\endgroup\$JensB– JensB2018年12月05日 08:04:44 +00:00Commented Dec 5, 2018 at 8:04