1
\$\begingroup\$

I'm having a problem with my spritesheet, I generate a map but when I zoom in on it I can observe these lines as in the image below:

enter image description here

When I used the tiles each in their separate image, that did not happen, how do I avoid this case?

I'm drawing like this, the problem happens when I give a "ctx.scale":

ctx.drawImage(
    imgSolos.img,
    (imgSolos.width * resultSolo), // resultSolo is current frame in the spritesheet
    0,
    32,
    32,
    x, 
    y,
    imgSolos.width,
    imgSolos.height
);
\$\endgroup\$
  • \$\begingroup\$ Please add more details about how you draw those tiles and how you implemented that zooming feature (browser-window zooming? css style of the canvas? context.scale?) \$\endgroup\$ – Philipp Jul 20 '18 at 12:34
  • \$\begingroup\$ @Philipp I use ctx.scale to zoom in. I have edited the question. \$\endgroup\$ – PerduGames Jul 20 '18 at 12:45
4
\$\begingroup\$

Keep in mind that context.scale does not change the internal resolution of the canvas. It just adds a multiplication factor to all coordinates you pass to the drawing functions. Due to floating point inaccuracies on scale factors which are not factors of 2, those coordinates might no longer be pixel-perfect. The result is what you see in that screenshot.

Possible solutions are:

  • Implement scaling by changing the width and height of the destination rectangle of your drawImage calls. Use the same number of pixels for the x- and y-increments in your map drawing loops. Use integers only.

    Note that this might still cause artifacts between the tiles because you will have blurring on each individual tile but no blurring across tile borders.

  • Draw your map to a second, invisible canvas without scaling. Then draw that invisible canvas to the visible canvas with scaling. That way the whole map will get scaled as one image (this might seem inconvenient, but most 2d engines end up adding such an additional layer of indirection sooner or later for a variety of reasons)
  • Use CSS to change the size of the canvas in the HTML document. The browser will then stretch the output of the canvas. This actually has the same effect as the previous method, but moves the implementation to the browser's rendering engine
  • Only use scale factors which are either integers, or 1 divided by a powers of 2 (0.5, 0.25, 0.125...).
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the reply, but how could I limit it to the power of 2? for example something that looks like this: zoomCamX += 0.1; \$\endgroup\$ – PerduGames Jul 20 '18 at 13:22
  • \$\begingroup\$ @PerduGames implement zoom-in and zoom-out as zoomCamX *= 2.0 and zoomCamX /= 2.0. \$\endgroup\$ – Philipp Jul 20 '18 at 13:23
  • \$\begingroup\$ but I can still see the lines. When it moves away I can no longer see the lines, but when I get closer I see them. \$\endgroup\$ – PerduGames Jul 20 '18 at 13:28
  • \$\begingroup\$ @PerduGames It works for me. Are you sure you start out with a scale factor of 1? When power-of-2 zooms are too fast for your game, then try one of the other 3 solutions I suggested. \$\endgroup\$ – Philipp Jul 20 '18 at 13:32
  • \$\begingroup\$ Going back here, I could show an example javascript in how to do: "Draw your map to a second, invisible canvas without scaling..." I'm not sure if I'm looking right. \$\endgroup\$ – PerduGames Jul 24 '18 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.