0

I'm trying to make a game isometric style, but when I draw the tiles they leave lines in between

My device's canvas parameters are 2560w 1440h. I did the math and don't see any floating points and such, no fractions. I still have tried using Math.round on the coordinates, but no difference

I have tried increasing the size of the original tile image's size: 64x40, 128x80 256x160 & 512x320. Lines seem to get better very little, but how big can I really make my tiles?

I have checked this post, but I don't think same logic applies to isometric as much:

Link: Unwanted lines apearing in html5 canvas using tiles

I don't know how to fix this

UPDATE

If I take the sides off on the tile, only leaving the top, I get white lines (from the whitebackground)

If I fill in the whole tile and sides with just plain red, there are no more lines

Tile

enter image description here

Preview

Preview

for(var i = 0; i < 50; i++){
    for(var j = 0; j < 50; j++){
        ctx.drawImage(isometricTile,
                      (c.width/2 - c.width/20) + (c.width/20 * i) + (-c.width/20 * j),
                      (c.width/40 * i) + (c.width/40 * j),
                       c.width/10,
                       c.width/10 * 0.625);
}
Community
  • 1
  • 1
tery.blargh
  • 405
  • 1
  • 6
  • 23

1 Answers1

0

Problems with antialiasing

The lines are due to the anti aliasing of the shape edges you are drawing.

Tile pre render fix.

For a tile based game you should render as much as you can to an off screen canvas and use those images to render to the display. Doing this will allow you to scan the image and increase or decrease the alpha so that the edges are no longer anti-aliased. It is only the edges at the bottom (z depth) 4 sides of the tiles that need fixing.

Aliased edges

The image shows the pixels that need to be fixed. You will have to check if the pixels are inside or outside the title isometric area. Pixels outside need to be removed completely, pixels inside that have an alpha < 255 need to have the alpha set to 255.

This fix need happen only once. If the titles are not animated and do not change between clients then this can be done during production and the tile set delivered as an image.

To create a offscreen canvas

var tiles = document.createElement(canvas);
var tiles.width = tiles.height = 256;
var tiles.ctx = tiles.getContext("2d");

Then use the context to create the tiles, you can then get the pixel data with

var imgData = tiles.ctx.getImageData(0,0,256,256);

The array imgData.data holds 4 bytes for each pixel one each for red, green, blue, and alpha each have a range of 0 - 256.

To convert a pixel address into a array index

var pixelIndex = Math.floor(x) * 4 + Math.floor(y) * imgData.width;

to get the pixel data

var r,g,b,a;

r = imgData.data[pixelIndex];
g = imgData.data[pixelIndex + 1];
b = imgData.data[pixelIndex + 2];
a = imgData.data[pixelIndex + 3];

to set a pixel

imgData.data[pixelIndex] = r;
imgData.data[pixelIndex + 1] = g;
imgData.data[pixelIndex + 2] = b;
imgData.data[pixelIndex + 3] = a;

The array typed array as a clamped 8 bit unsigned values. this means that values are automatically rounded down, and if less than or greater than 0 - 255 they are clamped to 0, 255 respectively.

To put the pixels back into the image

tiles.ctx.putImageData(pixelData,0,0);

unlike draw commands all pixels are replaced, so pixels with alpha < 255 will replace existing pixels rather than let them show through.

To render the tile canvas to the display

var tilePos = {  // where on the tiles image the tile is
    x : 64,
    y : 64,
    w : 128,
    h : 64,
}
var screenPos = { // where on the screen to draw the tile
   x : 100,
   y : 100,
}
ctx.drawImage(  // render function
    tiles,      // source image
    tilePos.x,  // source rect to get pixels to render
    tilePos.y,
    tilePos.w,
    tilePos.h,
    screenPos.x,  // destination location
    screenPos.y,
    tilePos.w,
    tilePos.h
)

Fix via rendering cludge.

If the tiles need to be rendered in real time then the fix is to add a small outline ctx.lineWidth = 0.5 the same colour as the fill and then to draw only from pixel centers. ctx.lineTo(Math.floor(x) + 0.5, Math.floor(y) + 0.5) this will completely remove the background showing through.

For a more detailed look see this question How to draw on Canvas more precisely to avoid background leaking from underneeth The code snippet shows the results of various methods of combating the problem.

Community
  • 1
  • 1
Blindman67
  • 51,134
  • 11
  • 73
  • 136