0

I have a bunch of sprites i want to render side by side.

let sprites = [sprite1, sprite2, sprite3];

sprites.forEach((_, i) => {
    _.position.set(i * _.width, 0);
});

I want to move these sprites along the x axis controlled by tileX variable.

sprites.forEach((_, i) => {
    _.position.set(tileX + i * _.width, 0);
});

Tricky part is when a sprite reaches the left or right edge of the screen I want to move it to the opposite edge so it is rendered again.

gman
  • 100,619
  • 31
  • 269
  • 393
eguneys
  • 6,028
  • 7
  • 31
  • 63
  • I'd just like to point out that using `_` as a variable name is [*conventionally*](https://stackoverflow.com/a/27637038/10549827) done to say, "this parameter is ignored, but I had to put one here." Not that it matters to the question at hand, but I would suggest renaming `_` to `s` or something, since you are actually using it. :) – matthew-e-brown Mar 31 '20 at 00:30
  • In Scala there is a notation `_.useThisVariable` – eguneys Mar 31 '20 at 00:32

2 Answers2

1

Assuming you don't want the sprites to pop on the left and right then you need to mod the position with the (displayAreaWidth + spriteWidth) and subtract that amount if the sprite is off the right side

It's not 100% clear what you're trying to do but if you just use x % displayWidth then sprites will pop in on the left. They need to start -width off the left.

  sprites.forEach((_, i) => {
      const scrollWidth = ctx.canvas.width + _.width;
      let x = (tileX + i * _.width) % scrollWidth;
      if (x < 0) x += scrollWidth;
      if (x > ctx.canvas.width) x -= scrollWidth;
      _.position.set(x, 0);
  });

const ctx = document.querySelector('canvas').getContext('2d');
const sprites = [...Array(16).keys()].map(i => {
  return {
    id: String.fromCharCode(i + 65),
    color: `hsl(${i / 26 * 360}, 100%, 50%)`,
    width: 20,
    height: 20,  
    position: {
      x: 0,
      y: 0,
      set(x, y) {
        this.x = x;
        this.y = y;
      },
    },
  };
});

requestAnimationFrame(animate);

function animate(time) {
  time *= 0.001;
  
  update(time);
  render();
  requestAnimationFrame(animate);
}

function update(time) {
  tileX = Math.sin(time) * 100;
  sprites.forEach((_, i) => {
      const scrollWidth = ctx.canvas.width + _.width;
      let x = (tileX + i * _.width) % scrollWidth;
      if (x < 0) x += scrollWidth;
      if (x > ctx.canvas.width) x -= scrollWidth;
      _.position.set(x, 0);
  });
}

function render() {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  
  ctx.font = '28px sans-serif';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  
  for (const sprite of sprites) {
    ctx.fillStyle = sprite.color;
    ctx.fillRect(sprite.position.x, sprite.position.y, sprite.width, sprite.height);
    ctx.fillStyle = 'black';
    ctx.fillText(
        sprite.id,
        sprite.position.x + sprite.width / 2, 
        sprite.position.y + sprite.height / 2);
  }
}
canvas { border: 1px solid black; }
<canvas></canvas>
gman
  • 100,619
  • 31
  • 269
  • 393
0

First you need to find the size of the canvas or the screen, something like canvas.clientWidth. Then use the operator % (module) to find the position. As you said it could reach the left side of the screen, I assume this number can be negative. In that case, you need to add to the screen width.

var screenWidth = canvas.clientWidth;
var positionX = (tileX + i * _.width) % screenWidth;
if (positionX < 0) positionX += screenWidth;
ariel
  • 15,620
  • 12
  • 61
  • 73