0

I'm generating a random "map" like so:

generateTiles() {
    for (let x = 0; x < this.width; x++) {
      for (let y = 0; y < this.height; y++) {
        if (Math.random() < 0.3) {
          this.worldmap[x][y] = new Wall(x, y);
        } else {
          this.worldmap[x][y] = new Floor(x, y);
        }
      }
    }
  }

Then, I try to render it to canvas by mapping over rows & cells:

drawMap(context) {
    this.worldmap.map(function(row) {
      return row.map(function(cell) {
        return this.drawSprite(
          context,
          loadSpritesheet(sprites),
          cell.attributes.sprite,
          cell.x,
          cell.y,
          this.tilesize
        );
      }, this);
    }, this);
  }

By the above only renders a single tile in a {x: 0, y:0}. When I inspect the row and cell arrays over which map is iterating they all have distinct coordinates. This implies that the generation part works fine, and the problem lies with how I loop & render the map.

I read few answers on SO about preloading images. Its something to consider for the future but as I'm only loading a single spritesheet I don't think this is my issue.

I can't figure this one out, suggestions will be greatly appreciated!

For completeness sake, here is my drawing function:

drawSprite(context, spritesheet, sprite, x, y, tilesize) {
    context.drawImage(
      spritesheet, // image
      sprite * 16, // sx
      0, // sy
      16, // sWidth
      16, // sHeight
      x, // dx
      y, // dy
      tilesize, // dWidth
      tilesize // dHeight
    );
  }

And a function loading the spritesheet:

const loadSpritesheet = src => {
  const spritesheet = new Image();
  spritesheet.src = src;

  return spritesheet;
};

export default loadSpritesheet;

Also, here is a gist with more complete code exhibiting described problem.

EDIT: As per @CertainPerformance suggestion, I tried nested for loop:

for (let x = 0; x < this.worldmap.length; x++) {
  for (let y = 0; y < this.worldmap[x].length; y++) {
    this.drawSprite(
      context,
      loadSpritesheet(sprites),
      this.worldmap[x][y].attributes.sprite,
      this.worldmap[x][y].x,
      this.worldmap[x][y].y,
      this.tilesize
    );
  }
}

Still, only a single tile is being rendered.

boojum
  • 574
  • 6
  • 19
  • `.map` should only be used to create a new array - if you want side effects, use `forEach` or a `for` loop instead – CertainPerformance Apr 01 '20 at 00:24
  • @CertainPerformance - thanks for suggestion! Sadly, the effect is the same, see my update above. – boojum Apr 01 '20 at 00:39
  • First preload all your assets, then initiialize your app and when it runs only reference the already loaded assets (this means you have to store all the in variables available to your drawing code) – Kaiido Apr 01 '20 at 01:47
  • @Kaiido - I have to disagree. I only have one asset, which loads just fine as apart from the tile map I'm able to render a player sprite. As I mentioned in my question, I had a look already at various SO answers suggesting preloading but it doesn't seem to work for me. Can you re-open the question? – boojum Apr 01 '20 at 02:19
  • @Kaiido - in fact, my issue was due to the tiles being drawn on top of each other. Multiplying coordinates by the tile size fixed it. Suggestion for the future, ask OP what they tried before closing a question. – boojum Apr 01 '20 at 02:25
  • The code in your question is not preloading the images. Loading an image is always asynchronous. So even if you had already fetched the resource, you can't synchronously use your img after you do `img.src = url`. Until you don't modify the code in your question to reflect that you did something against this error, I'm not willing to reopen it, because it's at least the first error that the code in question has. Ps: the onus is on you to write a correct question to begin with, not to us to try to investigate what you may have done or not. We can only act on what you give to us. – Kaiido Apr 01 '20 at 02:27
  • I don't want to argue. As I said, I fixed the issue by multiplying coordinates by the size of a tile. No need to preload anything, and no need to reopen the question. – boojum Apr 01 '20 at 02:38

0 Answers0