Sah*_*Ch. 7 collision-detection kineticjs
我实现了一个检测两个形状之间碰撞的函数,以及另一个在检测到碰撞时将dragBound限制为边框的函数,以实现捕捉功能,然后添加到Kinetic.Group.所以实际上我将放置目标限制为现有矩形的边界.
这是一个明确查看我的问题的方法:http://jsfiddle.net/4Y87X/6/
当width = height时,这个逻辑适用于大矩形.但是,当我拖动小灰色矩形(代表我项目中的一个窗口)时,仅在大矩形的右侧和顶部检测到碰撞,未检测到左侧和底部!这是由于DragBoundWindow方法中的一些数学方程吗?
如果有人能找到错误,请?
代码:
var stage = new Kinetic.Stage({
container: "container",
width: 900,
height: 600
});
var leftLayer = new Kinetic.Layer({
x:0,
y:0,
id: 'leftLayer',
width:250,
height:600
});
var leftBackground = new Kinetic.Rect({
width: 250,
height: 600,
stroke: "red"
});
leftLayer.add(leftBackground);
stage.add(leftLayer);
var rightLayer = new Kinetic.Layer({
x: 280,
y:0,
id: 'rightLayer',
width:600,
height:600
});
var rightBackground = new Kinetic.Rect({
x: 0,
y: 0,
width: 600,
height: 600,
stroke: "green"
});
rightLayer.add(rightBackground);
stage.add(rightLayer);
//draw a room
var room = new Kinetic.Rect({
width: 100,
height: 100,
fill: 'cornsilk',
stroke: 'black',
strokeWidth: 3,
dragOnTop: false
});
var window = new Kinetic.Rect({
x: 30,
y: 250,
width: 40,
height: 4,
name: 'window',
id: "window_ID",
fill: '#ccc',
stroke: 'black',
strokeWidth: 1
});
var rooms = [];
var id = 0
var group = new Kinetic.Group({
x: 10,
y: 100,
width: 100,
height: 100,
id: id++
});
group.add(room);
leftLayer.add(group);
leftLayer.add(window);
stage.draw();
group.on('mousedown touchstart', function(e){
if (e.which != 3) {
var cloneOfItem= group.clone({added: false, id: id++});
cloneOfItem.setDraggable(true);
cloneOfItem.off('mousedown touchstart');
leftLayer.add(cloneOfItem);
cloneOfItem.dragBoundFunc(dragBoundCarre);
cloneOfItem.on('dragmove', function(){
this.moveToTop();
});
cloneOfItem.on('dragend', function(){
var userPos = stage.getPointerPosition();
if (userPos.x>280 && userPos.y>0 && !this.getAttr('added'))
{
this.setAttr('added', true);
this.x(this.x() - 280);
this.moveTo(rightLayer);
rooms.push(this);
}
else if (userPos.x<280)
{
this.destroy();
rightLayer.draw();
rooms.splice(this,1);
}
stage.draw();
});
cloneOfItem.fire('mousedown');
cloneOfItem.fire('touchstart');
}
});
window.on('mousedown touchstart', function(e){
if (e.which != 3) {
var cw = window.clone({draggable:true});
leftLayer.add(cw);
cw.off('mousedown touchstart');
cw.dragBoundFunc(dragBoundWindow);
cw.on('dragstart', function(){
this.startX=this.x();
this.startY=this.y();
this.lastPos=this.position();
this.getParent().moveToTop();
});
cw.on('dragmove', function(){
var pos=this.position();
this.lastPos = pos;
rightLayer.draw();
});
cw.on('dragend', function(e){
var userPos = stage.getPointerPosition();
if (userPos.x > 280 && userPos.y > 0)
{
var pos = cw.getAbsolutePosition();
var x = pos.x;
var y = pos.y;
var hit = -1;
for (var i = 0; i < rooms.length; i++)
{
var c = rooms[i];
var cpos = c.getAbsolutePosition();
var cx = cpos.x + room.x();
var cy = cpos.y + room.y();
//detect collision
if (x >= cx && x <= cx + c.width() && y >= cy && y <= cy + c.height())
{
hit = i;
rooms[hit].off('dragend');
this.x(x - rooms[hit].x()-280);
this.y(y - rooms[hit].y());
this.moveTo(rooms[hit]);
}
}
if (hit < 0)
{
this.x(x - 280);
this.y(y);
this.moveTo(rightLayer);
alert("Window is not in the rigth target. \n\nTry again.");
}
}
else
{
this.remove();
}
rightLayer.draw(this);
stage.draw();
});
cw.fire('mousedown');
cw.fire('touchstart');
cw.fire('dragstart');
}
rightLayer.draw();
});
stage.add(rightLayer);
stage.add(leftLayer);
stage.draw();
function dragBoundCarre(pos, event) {
var collided = doObjectsCollide(pos, this);
if (collided.length > 1) {
pos.x = this.getAbsolutePosition().x;
pos.y = this.getAbsolutePosition().y;
}
else if (collided.length === 1) {
collided = collided[0];
var colAbsX = collided.getAbsolutePosition().x;
var colAbsY = collided.getAbsolutePosition().y;
var tempPos = Object.create(pos);
tempPos.x -= colAbsX;
tempPos.y -= colAbsY;
if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x < 0 && Math.abs(tempPos.x) < collided.width()) {
pos.x = colAbsX - this.width();
} else if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x > 0 && Math.abs(tempPos.x) < collided.width()) {
pos.x = colAbsX + collided.width();
} else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y < 0 && Math.abs(tempPos.y) < collided.height()) {
pos.y = colAbsY - this.height();
} else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y > 0 && Math.abs(tempPos.y) < collided.height()) {
pos.y = colAbsY + collided.height();
}
}
return {
x: pos.x,
y: pos.y
};
}
function dragBoundWindow(pos, event, group) {
var collided = doObjectsCollide(pos, this);
if (collided.length > 1) {
pos.x = this.getAbsolutePosition().x;
pos.y = this.getAbsolutePosition().y;
}
else if (collided.length === 1) {
collided = collided[0];
var colAbsX = collided.getAbsolutePosition().x;
var colAbsY = collided.getAbsolutePosition().y;
var tempPos = Object.create(pos);
tempPos.x -= colAbsX;
tempPos.y -= colAbsY;
if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x < 0 && Math.abs(tempPos.x) < collided.width()) {
pos.x = colAbsX - this.width() + 40;
//switch width and height
this.setWidth(window.getHeight());
this.setHeight(window.getWidth());
console.log('collision: left');
} else if (Math.abs(tempPos.x) > Math.abs(tempPos.y) && tempPos.x > 0 && Math.abs(tempPos.x) < collided.width()) {
pos.x = colAbsX + collided.width();
this.setWidth(window.getHeight());
this.setHeight(window.getWidth());
console.log('collision: right');
} else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y < 0 && Math.abs(tempPos.y) < collided.height()) {
pos.y = colAbsY - this.height();
this.setWidth(window.getWidth());
this.setHeight(window.getHeight());
console.log('collision: top');
} else if (Math.abs(tempPos.x) < Math.abs(tempPos.y) && tempPos.y > 0 && Math.abs(tempPos.y) < collided.height()) {
pos.y = colAbsY + collided.height();
this.setWidth(window.getWidth());
this.setHeight(window.getHeight());
console.log('collision: bottom');
}
}
return {
x: pos.x,
y: pos.y
};
group.add(this);
}
function doObjectsCollide(pos, a) {
var col = [];
for (var i = 0; i < rooms.length; i++) {
var b = rooms[i];
if (a.id() != b.id()) {
if (!((pos.y + a.getHeight()) < (b.getAbsolutePosition().y) || (pos.y > (b.getAbsolutePosition().y + b.getHeight())) || ((pos.x + a.getWidth()) < b.getAbsolutePosition().x) || (pos.x > (b.getAbsolutePosition().x + b.getWidth()))))
{
col.push(b);
}
}
}
return col;
}
Run Code Online (Sandbox Code Playgroud)