вопрос об обнаружении столкновений какао

Я понимаю концепцию NSIntersectionRect для обнаружения столкновений, но, похоже, не могу придумать, как реализовать ее в моем проекте. Ничего особенного, нажмите кнопку, и будет вызван подкласс представления, который поместит кружок в окно в случайном месте. Щелкните внутри этого представления, и круг начнет мигать (это сделает его активным). Если у вас есть активный вид, щелчок в любом месте за его пределами (но не на другом круге) переместит этот вид в точку щелчка.

Я использую [activeView animator setFrame: NSMakeRect (x, y, w, h)] для перемещения активного представления. Могу ли я использовать это для обнаружения столкновений или мне нужно использовать CABasicAnimation? В основном то, что я ищу, - это обнаруживать столкновения с другими кругами (на данном этапе физика не требуется, просто остановите движение) и / или с границами окна приложения.

Если бы кто-то мог подтолкнуть меня в правильном направлении (ссылка на руководство, фрагмент кода), я был бы признателен.

Изменить: на основе хорошо подробного ответа ниже мне нужно быть немного более ясным. Я не понимаю, где реализовать обнаружение столкновений. Метод аниматора класса представления - это одна строка кода. Как мне перебрать каждый статический кружок на экране, чтобы выполнить проверку на столкновение? Вот почему я сначала задаюсь вопросом, нужно ли мне использовать CoreAnimation, OpenGL или что-то вроде Chipmunk, а затем, если бы я мог получить толчок или помощь, это было бы здорово.


person PruitIgoe    schedule 19.02.2011    source источник


Ответы (1)


Позже .. в ответ на ваши недавние вопросы:

Вот почему я сначала задаюсь вопросом, нужно ли мне использовать CoreAnimation, OpenGL или что-то вроде Chipmunk, а затем, если бы меня подтолкнули или помогли, это было бы здорово.

Ответ - вам абсолютно точно не нужен OpenGL :) Далее, вам определенно не нужна физическая библиотека, такая как Box2D или Chipmunk ... вы могли бы пойти этим путем, если бы захотели, но это будет огромный объем ненужной работы. Для ясности: пока вы полностью не освоите DrawRect, такие вещи, как Chipmunk, все равно бесполезны для вас, так что просто забудьте об этом.

Core Animation вам не поможет. Для ясности, вы, возможно, захотите прервать анимацию, когда она происходит. Это правильно?

Я не понимаю, где реализовать обнаружение столкновений. Метод аниматора класса представления - это одна строка кода. Как мне перебрать каждый статический кружок на экране, чтобы выполнить проверку на столкновение?

Плохие новости ... если вы действительно хотите прервать анимацию, в случае столкновения забудьте о Core Animation. Core Animation позволит вам отправить его из A в B как «одну единицу» анимации. Он НЕ позволит вам остановить его посередине (в случае столкновения). Вот и все.

Чтобы было ясно, это то, что вы хотите делать правильно? Вы приводите круг в движение, и ЕСЛИ он что-то наталкивает на своем пути, вы хотите, чтобы он остановился. Это правильно? в таком случае полностью забудьте о Core Animation и выбросьте всю работу, которую вы уже проделали.

Вам придется погрузиться в «настоящее» программирование (что бы это ни значило) и начать использовать drawRect. Готовы ли вы к этому ?!

Здесь я мог бы просто упомянуть: подумайте о покупке копии Corona (это примерно 100 долларов - я уверен, что демоверсия бесплатна). Вы можете сделать все, что описываете, буквально за пять минут с помощью Corona. (1/10 времени, потраченного на написание этого поста ??) Я всегда рекомендую это людям, которым iPhone любопытно. Если вы действительно не хотите тратить от 6 до 18 месяцев на то, чтобы стать программистом iPhone с оружием, просто нажмите Corona для iPhone, и за долю времени, потраченного вами на использование Stack Overflow, вы сможете ваши круги дико подпрыгивают на экране iPhone.

Итак, в противном случае вам придется приступить к работе и узнать, как запустить таймер (NSTimer) и использовать drawRect в UIView.

Создайте новый класс MyFirstView (файлы .h и .m), который является подклассом UIView (не UIViewController, который предназначен для слабаков!). Вам понадобится метод drawRect в MyFirstView, и продолжайте оттуда!


Оригинальный ответ ..

Я не уверен, что понимаю, что вы говорите, но для ясности:

Вы хотите обнаружить столкновение двух кругов. В вашем случае все круги одного диаметра. Это правильно?

Если так, то, к счастью, это очень легко сделать.

Напишите процедуру, которая определяет расстояние между двумя точками CGPoints. (Если вы не знаете, как это сделать, я включил это ниже.)

Следующим шагом вы должны знать ДИАМЕТР своих кругов. Скажем, это 50.0 для примера.

Далее, вот процедура, которая проверяет, не сталкиваются ли два круга:

static inline bool areTwoCirclesColliding( CGPoint aa, CGPoint bb )
    {
    return ( distanceBetweenTwoCGPoints(aa,bb) < 50.0 );
    }

(Примечание ... если вы новичок в Objective C, обратите внимание, что приведенный выше код является полностью допустимым. Просто вставьте его в начало файла. ОК?)

Наконец, вам просто нужно сравнить все свои круги друг с другом, чтобы увидеть, не сталкиваются ли они.

Если у вас есть простое фиксированное количество кругов, скажем, три или около того, просто напишите все строки кода, чтобы проверить, не совпадают ли какие-либо комбинации, следовательно:

areTwoCirclesColliding(a,b)
areTwoCirclesColliding(a,c)
areTwoCirclesColliding(b,c)

Если у вас есть массив или какой-то список кругов, вам просто нужно просмотреть их все и убедиться, что каждый из них не касается другого. В псевдокоде это может быть примерно так ...

for n in 1 to numberCircles
   oneCircle = circles[n]
   for m in n+1 to numberCircles
      anotherCircle = circles[m]
      if ( areTwoCirclesColliding(oneCircle,anotherCircle) )
         .. break, you found a collision

В качестве альтернативы вы могли бы написать это так, без разницы ..

for each aa in circles
  for each bb in circles
    if (aa != bb) if (areTwoCirclesColliding(aa,bb)) .. break, found collision

{В сторону - для протокола совершенно неважно, что вы дважды проверяете каждую пару в этом псевдокоде, без проблем.}

Я не могу написать для вас реальный код, так как я понятия не имею, какую структуру вы используете, извините.

Конечно, если ваш круг является объектом, вы могли бы разумно заставить его проверить себя на всех других кругах, та же идея. Если у вас есть база данных кругов SQL, сравните их все друг с другом.

Итак, к счастью, вы можете видеть, что это одна (1) строка кода, чтобы проверить, не сталкиваются ли два круга. И это примерно 3 или 4 строки кода, чтобы проверить все ваши круги на предмет столкновений. К счастью, всего около 5 строк!

Итак, это невероятно простой урок по физике видеоигр, часть 1.1.1.1 !!!! Надеюсь, поможет! Если это не то, чего вы пытались достичь, печатать было напрасно! :)

Для записи, вот процедура для получения расстояния между двумя CGPoints:

static inline float rawDistance(float x, float y, float p, float q)
    {
    return sqrt( ((x-p)*(x-p)) + ((y-q)*(y-q)) );
    }
static inline float distanceBetweenTwoCGPoints( CGPoint a, CGPoint b )
    {
    return rawDistance( a.x, a.y, b.x, b.y );
    }

(Примечание ... если вы новичок в Objective C, обратите внимание, что приведенный выше код является полностью допустимым. Просто вставьте его в начало файла. Хорошо? Это точно так же, как использование любой повседневной функции. от Apple, например x = CGLayerGetContext (). Наслаждайтесь!)

Позже .. и по многочисленным просьбам на объект Круг ...

-(bool)isTouchingOtherCircle:(circle)c
  {
  return areTwoCirclesColliding(self.center, c.center);
  }
-(bool)isTouchingAnyOtherCircle
  {
  for oc in yourCircles
    if (oc != self)
      if ( [self isTouchingOtherCircle:oc] )
        return false;
  return true;
  }
person Fattie    schedule 19.02.2011
comment
Неплохой ответ, но PruitIgoe использует Objective-C, поэтому может быть лучше представить ваш код на C или Objective-C. - person LandonSchropp; 19.02.2011
comment
спасибо за ответ, там есть кое-что хорошее. Мне нужно быть более конкретным в отношении Objective-c в моем вопросе. Смотрите мои правки к оригиналу. - person PruitIgoe; 19.02.2011
comment
@joe ... спасибо за советы ... Я уже делал вещи NSTimer в других приложениях, так что это не страшно, и я действительно изначально использовал программный подход к этому, но потом подумал, позвольте мне дважды проверить, что там есть . Я не возражаю против программирования, это действительно будет весело, так что пора подумать над этим. : D - edit: не беспокойтесь о том, что вы не разместите весь код, я действительно просто хотел указать в правильном направлении, и сумма, которую вы уже предоставили, была потрясающей. - person PruitIgoe; 20.02.2011