这是我的游戏plnkr。
(编辑:另一个plnkr有一个静态怪物而不是多个动态怪物
输入或按钮将重新开始游戏。
有人能说出为什么从here取得的碰撞检测算法不起作用吗?它似乎没有准确地检测到命中(太广泛)。他们网站上的演示效果很好,但我不确定我做错了什么。
最相关的一段代码(内部更新功能):
// Are they touching?
if (heroImage.width) {
var heroImageData = ctx.getImageData(heroImage.x, heroImage.y, heroImage.width, heroImage.height);
var monsterImageData;
for (var i = 0; i < monsters.length; i++) {
var monster = monsters[i];
monster.x += monster.directionVector.x;
monster.y += monster.directionVector.y;
monsterImageData = ctx.getImageData(monster.monsterImage.x, monster.monsterImage.y, monster.monsterImage.width, monster.monsterImage.height);
if (isPixelCollision(heroImageData, hero.x, hero.y, monsterImageData, monster.x, monster.y)) {
stop();
}
}
}
答案 0 :(得分:2)
答案 1 :(得分:2)
您正在游戏的绘图上下文中使用imageData,因此,由于您有背景,因此根本没有透明像素,因此您的像素碰撞检测始终为真 - &gt;事实上,你只是在做一个边界框检查 算法的想法是比较两个只需要计算一次的静态imageData(getImageData是一个代价高昂的操作)。
一些建议:
•在启动游戏之前加载图像
•redim(裁剪)你的形象,它有很多空白,正如@Quantumplate注意到的那样
•在游戏启动之前,只在上下文中计算一次精灵的imageData。不要忘记在drawImage + getImageData之前使用clearRect()画布。这是解决你的bug的方法
•摆脱
if (xDiff < 4 && yDiff < 4) {
和相应的其他。这种“优化”毫无意义。使用像素检测的要点是精确的。 Redim(裁剪)你的形象更重要的是赢得很多时间(但你需要...... ??)
•Rq:像素检测算法写得多差! 1)绕数字,它正在使用!! 5种不同的方法(圆形,&lt;&lt; 0,~~,0 |,?:)!!! 2)当CPU缓存首先优先于Y时,它首先在X上循环,还有许多其他的东西......但是现在如果有效......
答案 2 :(得分:2)
正如@GameAlchemist指出你正在从画布背景中获取ImageData
的怪物和英雄,它已经被背景图像绘制。因此,总是有alpha值255(不透明)。
正在碰撞功能中检查
if (
( pixels [((pixelX - x ) + (pixelY - y ) * w ) * 4 + 3 /*RGBA, alpha @ 4*/] !== 0/*alpha zero expected*/ ) &&
( pixels2[((pixelX - x2) + (pixelY - y2) * w2) * 4 + 3 /*RGBA, alpha @ 4*/] !== 0/*alpha zero expected*/ )
) {
return true;
}
相反,应该通过将这些图像绘制到没有绘制任何内容的画布来生成ImageData。即使在做了碰撞算法之后似乎也没有那么好。
我创建了两个变量monsterImageData
和heroImageData
来保存imageData,这些变量只加载一次。
HTML文件id=testCanvas
中有一个新画布。这用于获取怪物和英雄的图像数据值。
以下是修改后代码的plunker link。
答案 3 :(得分:1)
准备:对于要测试碰撞的每个图像
context.getImageData
,进行像素完美碰撞测试
进行快速测试以查看图像是否发生碰撞。如果没有,你就完成了。
// r1 & r2 are rect objects {x:,y:,w:.h:}
function rectsColliding(r1,r2){
return(!(
r1.x > r2.x+r2.w ||
r1.x+r1.w < r2.x ||
r1.y > r2.y+r2.h ||
r1.y+r1.h < r2.y
));
}
计算2幅图像的交叉矩形
// r1 & r2 are rect objects {x:,y:,w:.h:}
function intersectingRect(r1,r2){
var x=Math.max(r1.x,r2.x);
var y=Math.max(r1.y,r2.y);
var xx=Math.min(r1.x+r1.w,r2.x+r2.w);
var yy=Math.min(r1.y+r1.h,r2.y+r2.h);
return({x:x,y:y,w:xx-x,h:yy-y});
}
比较两个alpha数组中的交叉像素。如果两个阵列在同一位置都有一个不透明的像素,那么就会发生碰撞。请务必通过抵消比较来对原点(x = 0,y = 0)进行标准化。
// warning untested code -- might need tweaking
var i=intersectingRect(r1,r2);
var offX=Math.min(r1.x,r2.x);
var offY=Math.min(r1.y,r2.y);
for(var x=i.x-offX; x<=(i.x-offX)+i.w; x++{
for(var y=i.y-offY; y<=(i.y-offY)+i.h; y++{
if(
// x must be valid for both arrays
x<alphaArray1[y].length && x<alphaArray2[y].length &&
// y must be valid for both arrays
y<alphaArray1.length && y<alphaArray2.length &&
// collision is true if both arrays have common non-transparent alpha
alphaArray1[x,y] && alphaArray2[x,y]
){
return(true);
}
}}
return(false);