我正在制作一个需要平铺背景的小游戏,我从png tileSet(16x16平铺)中挑选的平铺。即使图块是16x16,它们也会在spriteSheet的画布上显示为32x32图块(请参阅下面的代码)。 问题是,当我人工放大瓷砖的尺寸时,它需要一小块瓷砖紧挨着它。图像可能比文字描述得更好:
你可以在水中看到,有一条粉红色的线,不应该在这里(我检查了瓷砖组上没有分离,0,0在我相信的正确位置)。我还尝试使用原始尺寸的瓷砖(16x16而不是32x32)作为背景,没有看到粉红色的线条,灰色网格也消失了:
所以我猜它来自32x32,但我不知道如何解决它... 这是我用来加载tileset并显示背景的代码:
loadImage('/img/dungeon.png')
.then(image => {
const sprites = new SpriteSheet(image, 16, 16);
sprites.define('stone_floor', 1, 0, 32, 32);
sprites.define('water', 2, 7, 32, 32);
sprites.define('wall_top', 2, 0, 32, 32);
sprites.define('void', 0, 0, 32, 32);
sprites.define('stone_floor&water', 3, 7, 32, 32);
loadLevel('1-2')
.then(level => {
drawBackground(level.background, context, sprites);
})
});
SpriteSheet类:
class SpriteSheet {
constructor(image, width, height, offset = 0){
this.image = image;
this.width = width;
this.height = height;
this.offset = offset;
this.tiles = new Map();
}
define(name, x, y, imgw, imgh){
const buffer = document.createElement('canvas');
buffer.width = imgw;
buffer.height = imgh;
buffer
.getContext('2d')
.drawImage(this.image,
x * this.width + x*this.offset, y * this.height + y*this.offset,
this.width, this.height,
0, 0, imgw, imgh);
this.tiles.set(name, buffer);
}
draw(name, context, x, y){
const buffer = this.tiles.get(name);
context.drawImage(buffer, x, y);
}
drawTile(name, context, x, y){
const buffer = this.tiles.get(name);
context.drawImage(buffer, x * buffer.width, y * buffer.height);
}
}
PS:这个项目高度基于MethMethMethod的教程:video
答案 0 :(得分:0)
根据@ Blindman67的评论:
相邻图块的出血是由于向上缩放图块时的双线性过滤。简单的解决方案是转动瓷砖的双线性过滤。 ctx.imageSmoothingEnabled = false;如果您希望保持过滤,那么唯一的选择是将图块大小增加到18,在图块周围添加边框以匹配边缘颜色。您仍然只渲染16 * 16图块,但过滤将从边框像素而不是相邻图块进行采样。
我能够解决我的问题,虽然提出的第一个选项不起作用(关闭图像平滑)。我设法修改了我的spriteSheet类,以便它首先通过将1个18x18图块覆盖相同的图块,16x16并居中来创建一个18x18px的缓冲图像:
defineTile(name, x, y, imgw, imgh) {
const img_buffer = document.createElement('canvas');
img_buffer.width = this.width + 4;
img_buffer.height = this.height + 4;
img_buffer
.getContext('2d')
.drawImage(this.image,
x * this.width + x * this.offset, y * this.height + y * this.offset,
this.width, this.height,
0, 0, this.width + 4, this.height + 4);
img_buffer
.getContext('2d')
.drawImage(this.image,
x * this.width + x * this.offset, y * this.height + y * this.offset,
this.width, this.height,
2, 2, this.width, this.height);
const buffer = document.createElement('canvas');
buffer.width = imgw;
buffer.height = imgh;
buffer
.getContext('2d')
.drawImage(img_buffer,
2, 2,
this.width, this.height,
0, 0, imgw, imgh);
this.tiles.set(name, buffer);
}
即使我不知道这是否是最优化的方式,但它能很好地完成工作!我对任何可以使这部分当然更好的建议持开放态度,但我认为问题已经解决了。