Я пытаюсь обнаружить столкновение двух кругов. Процесс работает, когда пользователь создает круги (нажатие кнопки), а затем щелкает мышью один из кругов, чтобы активировать его. Если щелкнуть мышью в любом месте за пределами активного круга, он будет перемещен по оси 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: Я получаю определенное обнаружение столкновений, но, похоже, это происходит только тогда, когда пересекаются 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;
}
}