Javascript 从画布精灵获取图像像素数据

Javascript 从画布精灵获取图像像素数据,javascript,canvas,sprite,Javascript,Canvas,Sprite,我试图在我的画布游戏中实现像素完美的碰撞检测,但是我似乎无法从我的精灵中获得像素信息 我需要精灵每个像素的x和y值,根据我所读到的内容,我使用getImageData方法来实现这一点 但是,这不起作用: this.sprite = new Image(); this.sprite.src = 'img/player.png'; console.log(this.sprite.getImageData()); 我是不是用错了雪碧?因为我在控制台中遇到此错误: 未捕获的TypeError:对象没有

我试图在我的画布游戏中实现像素完美的碰撞检测,但是我似乎无法从我的精灵中获得像素信息

我需要精灵每个像素的x和y值,根据我所读到的内容,我使用getImageData方法来实现这一点

但是,这不起作用:

this.sprite = new Image();
this.sprite.src = 'img/player.png';
console.log(this.sprite.getImageData());
我是不是用错了雪碧?因为我在控制台中遇到此错误:

未捕获的TypeError:对象没有方法 “getImageData”

下面介绍如何使用精灵的像素数据进行像素完美命中测试

首先,在可见画布上正常绘制精灵

在隐藏画布上创建精灵的红色蒙面副本。此副本与精灵的大小完全相同,但仅包含透明或红色像素

跟踪可见精灵的边界框。单击边界框时,计算鼠标单击相对于精灵边界框的X/Y,而不是相对于画布的X/Y

然后,参考红色遮罩精灵,查看X/Y对应的像素是红色还是透明。如果像素是红色的,则有一个像素完美点击。如果像素是透明的,则不会命中

在本图中,假设蓝色圆点是X/Y单击位置。由于红色遮罩画布中对应的X/Y像素为“红色”,因此这是一个成功的例子

下面是创建红色蒙面精灵的代码。我不会在这里显示命中测试的代码,但是如果您尝试了,但无法编写命中测试,我也会花时间编写命中测试的代码

重要提示:要运行此代码,必须避免跨域安全限制。请确保您的图像源位于本地域上,否则您将遇到跨域安全冲突,并且不会绘制遮罩图像…因此您不能对您的精灵源执行此操作:

将处于变换状态的sprite2绘制到第三个画布中

在此绘制之后,第三个画布仅包含sprite1和sprite2的冲突部分

测试第三个画布中的每个像素是否为不透明像素。如果发现任何不透明像素,则两个精灵发生碰撞

根据碰撞时要采取的操作,您可能会在找到第一个碰撞像素时退出。以下是如何使用精灵的像素数据进行像素完美命中测试

首先,在可见画布上正常绘制精灵

在隐藏画布上创建精灵的红色蒙面副本。此副本与精灵的大小完全相同,但仅包含透明或红色像素

跟踪可见精灵的边界框。单击边界框时,计算鼠标单击相对于精灵边界框的X/Y,而不是相对于画布的X/Y

然后,参考红色遮罩精灵,查看X/Y对应的像素是红色还是透明。如果像素是红色的,则有一个像素完美点击。如果像素是透明的,则不会命中

在本图中,假设蓝色圆点是X/Y单击位置。由于红色遮罩画布中对应的X/Y像素为“红色”,因此这是一个成功的例子

下面是创建红色蒙面精灵的代码。我不会在这里显示命中测试的代码,但是如果您尝试了,但无法编写命中测试,我也会花时间编写命中测试的代码

重要提示:要运行此代码,必须避免跨域安全限制。请确保您的图像源位于本地域上,否则您将遇到跨域安全冲突,并且不会绘制遮罩图像…因此您不能对您的精灵源执行此操作:

将处于变换状态的sprite2绘制到第三个画布中

在此绘制之后,第三个画布仅包含sprite1和sprite2的冲突部分

测试第三个画布中的每个像素是否为不透明像素。如果发现任何不透明像素,则两个精灵发生碰撞


根据碰撞时要采取的操作,当您找到第一个碰撞像素时,您可能会退出。

getImageData是画布而不是图像的一种方法。从我的精灵中获取像素信息是什么意思?框检测并没有那么困难-基于像素形状的检测可能会非常耗时。看:而且:啊,我想可能是的。我的意思是,我想知道我的精灵中每个像素在画布上的x和y坐标@迪奥多斯,没有你想象的那么多。虽然可以使用很多对象,但我一次只能在画布上使用几个精灵。此外,框检测还不够好,因为精灵不是矩形的。getImageData是画布的一种方法,而不是图像。从我的精灵中获取像素信息是什么意思?框检测并没有那么困难-基于像素形状的检测可能会非常耗时。看,还有:啊,我爱你
也许是这样。我的意思是,我想知道我的精灵中每个像素在画布上的x和y坐标@迪奥多斯,没有你想象的那么多。虽然可以使用很多对象,但我一次只能在画布上使用几个精灵。此外,框检测还不够好,因为精灵不是矩形的。谢谢你的回答@markE。但是有一个问题,如果我们要使用“目的地in”,为什么我们需要红色遮罩精灵?非重叠像素无论如何都不会被绘制,然后我们继续搜索非透明像素。谢谢您的回答@markE。但是有一个问题,如果我们要使用“目的地in”,为什么我们需要红色遮罩精灵?无论如何都不会绘制非重叠像素,然后我们继续搜索非透明像素。
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:10px; }
    canvas{border:1px solid blue;}
</style>

<script>
    $(function(){

        var c=document.getElementById("canvas");
        var ctx=c.getContext("2d");

        var img=new Image();
        img.onload=function(){
          ctx.drawImage(this,100,25);

          // make a red-masked copy of just the sprite
          // on a separate canvas
          var canvasCopy=document.getElementById("canvasCopy");
          var ctxCopy=canvasCopy.getContext("2d");
          canvasCopy.width=this.width;
          canvasCopy.height=this.height;
          ctxCopy.drawImage(img,0,0);

          // make a red-masked copy of the sprite on a separate canvas
          var imgData=ctxCopy.getImageData(0,0,c.width,c.height);
          for (var i=0;i<imgData.data.length;i+=4)
            {
                if(imgData.data[i+3]>0){
                    imgData.data[i]=255;
                    imgData.data[i+1]=0;
                    imgData.data[i+2]=0;
                    imgData.data[i+3]=255;
                }
            }
          ctxCopy.putImageData(imgData,0,0);         

        }
        img.src = "houseIcon.png";

    }); // end $(function(){});
</script>

</head>

<body>
    <p>Original sprite drawn on canvas at XY:100/25</p>
    <canvas id="canvas" width="400" height="300"></canvas>
    <p>Red-masked on canvas used for hit-testing</p>
    <canvas id="canvasCopy" width="300" height="300"></canvas>

</body>
</html>
context.globalCompositeOperation = 'destination-over';