我正在尝试检测两个圆圈的碰撞。当用户创建圆圈(按钮单击),然后在其中一个圆圈上单击鼠标以激活它时,该过程将起作用。鼠标单击活动圆圈外的任何位置都会将圆圈移动到鼠标单击的x,y。我想要做的是,如果活动圆的路径中有另一个圆圈,则停止移动。
NSPoint P =鼠标点击(通过通知中心传入)
activeView =选定的圆圈(NSView的子类)
我的过程是指向移动点,根据起点和终点确定移动方向,以及x起点和终点的增量数,循环增量,使用动画制作方法NSView移动视图,遍历所有非活动视图(所有其他圆圈)并使用公式((x1 * x2)+(x1 * x2))+(y1)将它们的位置与活动视图的当前位置进行比较* y2)+(y1 * y2)并且比较两个圆的半径的平方(圆圈在30x30矩形中,圆圈上有4个像素的笔划,所以我使用26作为我的半径(26 * 26)检查。
我有几个问题(除了我重新发明轮子的愿望:D - 这对我来说是一个学习练习):
1:运动代码部分实际效果很好。但是,我想在鼠标点击时获得圆的中心点,此时圆圈正在停止,以便包含它的NSRect(30x30)x,y坐标是鼠标单击(这不是翻转,所以它的左下方。)
2:我正在进行一些碰撞检测,但这似乎只有当两个包含rects的x,y相交时,而不是圆边。
3:与所有这些无关,我将NSColor设置为clearColor,它们最初以这种方式开始,但是当我移动它们时,它们又恢复为默认颜色(灰色)。每次重绘视图时是否必须指定clearColor?
感谢您的帮助。
hasCollision = NO;
//get point clicked value
NSValue* pVal = [[notification userInfo] objectForKey:@"dataPoint"];
//convert value to point (end point)
NSPoint p = [pVal pointValue];
//get activeView frame
NSRect avFrame = [activeView frame];
float startX = avFrame.origin.x; //x1
float startY = avFrame.origin.y; //y1
float endX = p.x; //x2
float endY = p.y; //y2
//set direction of activeView movement
if (endX > startX && endY > startY) {
//NSLog(@"endXY > startXY");
cStart = startX;
cCheck =endX;
distanceX = endX - startX;
incrementY = (endY - startY)/distanceX;
} else if (endX < startX && endY > startY) {
//NSLog(@"endX<startX, endY>startY");
cStart = endX;
cCheck =startX;
distanceX = startX - endX;
incrementY = (endY - startY)/distanceX;
} else if (endX < startX && endY < startY) {
//NSLog(@"endX<startX, endY<startY");
cStart = endX;
cCheck =startX;
distanceX = startX - endX;
incrementY = (startY - endY)/distanceX;
} else {
//NSLog(@"endX>startX, endY<startY");
cStart = startX;
cCheck =endX;
distanceX = endX - startX;
incrementY = (startY - endY)/distanceX;
}
//NSLog(@"Start:%f:%f:End%f:%f:::distance=%f:::Y Increment=%f", startX, startY, endX, endY, distanceX, incrementY);
float currentX = startX;
float currentY = startY;
for(int c=cStart; c<cCheck; c++) {
//get move coordinates
if (endX > startX && endY > startY) {
currentX++;
currentY = currentY + incrementY;
} else if (endX < startX && endY > startY) {
currentX--;
currentY = currentY + incrementY;
} else if (endX < startX && endY < startY) {
currentX--;
currentY = currentY - incrementY;
} else {
currentX++;
currentY = currentY - incrementY;
}
//move view
[[activeView animator] setFrame:NSMakeRect(currentX, currentY, avFrame.size.width, avFrame.size.height)];
//make a rect for each object
NSRect avRect = [activeView frame];
//store previous positions
prevPos = [activeView frame];
//check for collisions
for(int v=0; v<[createdViewsDict count]; v++) {
//get the id of the view in the dict
NSString* nextNum = [NSString stringWithFormat:@"circle_%i", v+1];
//init a view and assign it to the next view in the dict
NSView* thisView = [createdViewsDict objectForKey:nextNum];
//make sure this view is not our active view
if (thisView != activeView) {
NSRect tvRect = [thisView frame];
//get the xy coordinates to compare
float x1 = avRect.origin.x;
float y1 = avRect.origin.y;
float x2 = tvRect.origin.x;
float y2 = tvRect.origin.y;
float radius = 26.0;
float dx = x2-x1;
float dy = y2-y1;
float radii = radius + radius;
if ( ( dx * dx ) + ( dy * dy ) < radii * radii ) {
hasCollision = YES;
//[[activeView animator] setFrame:NSMakeRect(prevPos.origin.x, prevPos.origin.y, avFrame.size.width, avFrame.size.height)];
NSLog(@"Collision!!Moving object coords:x=%f,y=%f,:::::::::Stationary object coords:x=%f,y=%f", avRect.origin.x, avRect.origin.y, tvRect.origin.x, tvRect.origin.y);
}
/*
//check for collision
NSRect collisionRect = NSIntersectionRect(avRect, tvRect);
//move circle to previous
if ( !NSIsEmptyRect(collisionRect) ) {
hasCollision = YES;
[[activeView animator] setFrame:NSMakeRect(prevPos.origin.x, prevPos.origin.y, avFrame.size.width, avFrame.size.height)];
NSLog(@"Collision!!Moving object coords:x=%f,y=%f,:::::::::Stationary object coords:x=%f,y=%f", avRect.origin.x, avRect.origin.y, tvRect.origin.x, tvRect.origin.y);
}
*/
}
}
if(hasCollision == YES) {
[[activeView animator] setFrame:NSMakeRect(prevPos.origin.x - 20.0, prevPos.origin.y - 20.0, avFrame.size.width, avFrame.size.height)];
hasCollision = NO;
break;
}
}