我正在尝试使用基于网格的地图编写简单的2D自顶向下游戏,我在操作某些画布区域中的像素时遇到问题。我有以下功能:
changeCellBackground(x, y, r, g, b){
let cell = this.context.getImageData(x * this.TILE_SIZE, y * this.TILE_SIZE, this.TILE_SIZE, this.TILE_SIZE);
for(let i=0; i<cell.data.length; i+=4){
cell.data[i] += r;
cell.data[i+1] += g;
cell.data[i+2] += b;
}
this.context.putImageData(cell, x * this.TILE_SIZE, y * this.TILE_SIZE);
}
其中context是canvas 2d context:
this.screen = $('#game');
this.context = this.screen[0].getContext('2d');
和Img标签有src链接到tileset:
let tileSet = $('<img></img>').attr('src', '../assets/tiles.png');
然而,当我尝试使用上述功能时,我得到了SecurityError: The operation is insecure.
。据我所知,这是因为CORS限制,所以我尝试add crossOrigin="anonymous"
属性Img
:
let tileSet = $('<img></img>').attr('crossOrigin', 'anonymous').attr('src', '../assets/tiles.png');
但现在我得到了NS_ERROR_NOT_AVAILABLE:
。我想这是因为当脚本的其余部分开始执行时,图像还没有加载。我该如何解决?我试过这个:
let tileSet = $('<img></img>');
tileSet.onload = function(){
tileSet.attr('crossOrigin', 'anonymous').attr('src', '../assets/tiles.png');
gameScreen.drawAnimatedImage(0, 0, 'waterfall');
gameScreen.drawAnimatedImage(2, 2, 'fountain');
gameScreen.drawAnimatedImage(11, 5, 'street_lamp');
gameScreen.drawAnimatedImage(10, 5, 'street_lamp');
gameScreen.changeCellBackground(10, 15, -30, -30, -30);
};
但它也不起作用 - 当我在console.log(tileSet)
函数结束时设置onload
时,控制台上没有记录任何内容。似乎没有触发onload函数。为什么会发生这种情况?我该如何解决这个问题?
答案 0 :(得分:1)
这是一种向画布上的像素添加值的更简单方法。
你的功能
changeCellBackground(x, y, r, g, b){
将r,g,b添加到拼贴上x,y
处的每个像素可以用
完成function changeCellBackground(x, y, r, g, b){
this.context.fillStyle = "rgb(" + Math.floor(r) + "," + Math.floor(g) + "," + Math.floor(b) + ")";
this.context.globalCompositeOperation = "lighter"; // adds the fill color to existing pixels
this.context.fillRect(x * this.TILE_SIZE, y * this.TILE_SIZE, this.TILE_SIZE, this.TILE_SIZE);
this.context.globalCompositeOperation = "source-over"; // restore default composite operation
}
上述功能与您的功能相同,但无需访问像素数据。这意味着您不必担心不安全的图像,并且可以在没有交叉原始标题的情况下加载它。
作为猜测,如果您正在使用硬盘驱动器(即../assets/tiles.png
在您的硬盘驱动器上),您将无法获得CORS映像,因为这需要服务器。
您可以在计算机上设置服务器(有很多选项),然后使用域localhost,在这种情况下,图像不是跨域的,不需要标头。或者您可以查看浏览器安全开关并关闭跨源安全性,这样您也可以访问图像数据。
答案 1 :(得分:0)
您问题中的changeCellBackground()
与tileset
之间没有任何关联,所以我不确定是否还有更多问题,但要等待要加载的图像,实际上你需要将src部分放在函数之外:
let tileSet = $('<img></img>');
tileSet.onload = function(){
gameScreen.drawAnimatedImage(0, 0, 'waterfall');
gameScreen.drawAnimatedImage(2, 2, 'fountain');
gameScreen.drawAnimatedImage(11, 5, 'street_lamp');
gameScreen.drawAnimatedImage(10, 5, 'street_lamp');
gameScreen.changeCellBackground(10, 15, -30, -30, -30);
};
tileSet.attr('crossOrigin', 'anonymous').attr('src', '../assets/tiles.png');
因为它当前没有触发onload事件,因为没有要加载的src。