可可碰撞检测问题

发布于 2024-10-18 02:53:03 字数 539 浏览 1 评论 0原文

我了解了用于碰撞检测的 NSIntersectionRect 的概念,但我似乎无法想到如何在我的项目中实现它。这并不奇怪,单击一个按钮,就会调用一个视图子类,并在窗口中的随机位置放置一个圆圈。在该视图中单击,圆形脉冲(这使其成为活动视图)。如果您有一个活动视图,单击其外部的任意位置(但不在另一个圆上)都会将该视图移动到单击点。

我正在使用 [activeView animator setFrame: NSMakeRect(x, y, w, h)] 移动活动视图。我可以使用它进行碰撞检测还是必须使用 CABasicAnimation?基本上我想做的是检测与其他圆圈的碰撞(此时不需要物理,只需停止移动)和/或与应用程序窗口的边界的碰撞。

如果有人可以将我推向正确的方向(教程链接、代码片段),我将不胜感激。

编辑:根据下面详细的答案,我需要更清楚一点。我对在哪里实现碰撞检测感到困惑。视图类的动画方法是一行代码。我如何迭代屏幕上的每个静态圆圈来运行碰撞检查?这就是为什么我首先想知道我是否需要使用 CoreAnimation、OpenGL 或 Chipmunk 之类的东西,然后如果我能得到推动或帮助那就太好了。

I get the concept of the NSIntersectionRect for collision detection but I can't seem to think of how to implement it for my project. It's nothing fancy, click a button and a view subclass is called and places a circle in the window at a random location. Click within the that view and the circle pulses (this makes it the active view). If you have an active view, clicking anywhere outside it (but not on another circle) will move that view to the click point.

I'm using [activeView animator setFrame: NSMakeRect(x, y, w, h)] to move the active view. Can I use this for collision detection or do I have to go with CABasicAnimation? Basically what I am looking to do is detect collisions with other circles (no physics needed at this point, just stop the movement) and/or with the bounds of the app window.

If someone could nudge me in the right direction (tutorial link, code snippet) I'd appreciate it.

Edit: Based on the well detailed answer below I need to be a bit more clear. I'm confused on where to implement the collision detection. The animator method of a view class is one line of code. How would I iterate through every static circle on the screen to run a collision check? Which is why I am wondering first, if I need to go with CoreAnimation, OpenGL or something like Chipmunk and then if I could get a nudge or assist that would be great.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

似狗非友 2024-10-25 02:53:03

稍后..回答您最近的问题:

这就是为什么我首先想知道,我是否需要使用 CoreAnimation、OpenGL 或花栗鼠之类的东西,然后如果我能得到推动或帮助,那就太好了。< /em>

答案 - 你绝对不需要 OpenGL :) 接下来,你绝对不需要像 Box2D 或 Chipmunk 这样的物理库......如果你愿意,你可以这样做,但是,这将是一个巨大的数量不必要的工作。需要明确的是:在您完全熟悉使用 DrawRect 之前,像 Chipmunk 这样的东西对您来说无论如何都是无用的,所以忘记它吧。

核心动画不会真正帮助你。需要明确的是,您可能希望在动画发生时中断它。这是正确的吗?

我对在哪里实现碰撞检测感到困惑。视图类的动画方法是一行代码。我如何遍历屏幕上的每个静态圆圈来运行碰撞检查?

坏消息... 如果您确实想中断动画,如果发生碰撞,请忘记核心动画。核心动画将允许您将其作为动画的“一个单元”从 A 发送到 B。 它不会让你在中间停下来(以防发生碰撞)。所以,就是这样。

需要明确的是,这就是您想要做的事情,对吧?您让圆圈开始运动,如果它沿途撞到某些东西,您希望它停止。这是正确的吗?如果是这样,请完全忘记核心动画并扔掉您迄今为止所做的任何工作。

您将必须深入研究“真正的”编程(无论这意味着什么)并开始使用drawRect。你准备好了吗?

此时我可能会提到:考虑购买 Corona 的副本(大约 100 美元——我确信演示是免费的)。使用 Corona,您实际上可以在五分钟内完成您所描述的所有操作。 (写这篇文章所用时间的 1/10??)我总是向那些对 iPhone 好奇的人推荐这个。如果您真的不想花 6 到 18 个月的时间成为一名 iPhone 程序员 - 只需点击 Corona for iPhone,只需花费您使用 Stack Overflow 所需时间的一小部分,您就可以你的圆圈在 iPhone 屏幕上疯狂地跳动。

因此,如果做不到这一点,您将不得不开始工作并学习如何启动计时器 (NSTimer) 并在 UIView 中使用 drawRect。

创建一个名为 MyFirstView (.h 和 .m 文件)的新类,它是 UIView 的子类(不是 UIViewController,这是给胆小鬼的!)。您需要在 MyFirstView 中使用一个 drawRect 方法,然后从那里继续!


原始答案..

我不确定我是否理解您在说什么,但要明确:

您想要检测两个圆之间的碰撞。在你的情况下,所有圆的直径都相同。这是正确的吗?

如果是这样,幸运的是这很容易做到。

编写一个例程来获取两个 CGPoint 之间的距离。 (如果您不知道该怎么做,我将其包含在下面。)

下一步,您必须知道圆圈的直径。假设该示例为 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 部分!!!!希望有帮助!如果这不是您想要实现的目标,那么打字完全是浪费! :)

作为记录,这里有一个获取两个 CGPoint 之间距离的例程:(

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())完全一样。

稍后...根据大众的需求,对于一个对象,Circle...

-(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;
  }

Later .. in answer to your recent questions:

Which is why I am wondering first, if I need to go with CoreAnimation, OpenGL or something like Chipmunk and then if I could get a nudge or assist that would be great.

Answer - you absolutely definitely do not need OpenGL :) Next, you definitely do not need a physics library like Box2D or Chipmunk ... you could go that way if you wanted to, but, it would be a huge amount of unnecessary work. To be clear: until you are totally familiar with using DrawRect, things like Chipmunk are useless for you anyway, so just forget that.

Core Animation will not really help you. To be clear, you possibly want to interrupt an animation as it is happening. Is that correct?

I'm confused on where to implement the collision detection. The animator method of a view class is one line of code. How would I iterate through every static circle on the screen to run a collision check?

Bad news... if you actually want to interrupt the animation, if there is a collision, forget about Core Animation. Core Animation will let you send it from A to B as "one unit" of animation. It will NOT let you stop it in the middle (in case of a collision). So, that's that.

To be clear, that is what you want to do right? You set the circle in motion, and IF it hits something along the way, you want it to stop. Is this correct? if so, completely forget about Core Animation and throw away any work you've done so far.

You are going to have to dive in to "real" programming (whatever that means) and start using drawRect. Are you up for it?!

At this point I might just mention: consider buying a copy of Corona (it's like $100 -- I'm sure the demo is free). You can do everything you are describing in, literally, five minutes using Corona. (1/10th the time taken to write this post??) I always recommend this to people who are iPhone Curious. If you don't really want to spend 6 to 18 months becoming a gun iPhone programmer - just click to Corona for iPhone and in a fraction of the time it's taken you to use Stack Overflow, you can have your circles bouncing wildly on the iPhone screen.

So, failing that, you're gonna have to get to work and learn how to launch a timer (NSTimer) and use drawRect in a UIView.

Craate a new class called MyFirstView (.h and .m file) that is a subclass of UIView (not UIViewController, which is for wimps!). You'll need a drawRect method in MyFirstView and proceed from there!


Original answer..

I'm not sure I understand what you are saying, but to be clear:

You want to detect a collision between two circles. In your case, all the circles are the same diameter. Is that correct?

If so, fortunately it is very easy to do.

Write a routine that gets the distance between two CGPoints. (If you don't know how to do that I included it below.)

Next step, you must know the DIAMETER of your circles. Let's say it is 50.0 for the example.

Next, here is a routine that checks if two circles are colliding:

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

(Note... if you are new to Objective C, note that the above is totally valid code. Simply paste it in at the top of your file. OK?)

Finally, you just have to check all your circles, one against the other, to see if any are colliding.

If you have a simple fixed number of circles, let's say three or so, just write out all the lines of code to check if any of the combinations are colliding, hence:

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

If you have an array or some sort of list of circles, you just have to go through them all and check that each one is not touching any other. In pseudocode it might be something like this...

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

Alternately you could write it like this, makes no difference..

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

{Aside - For the record it is utterly unimportant that you check each pair twice in that pseudocode, no problem.}

It is impossible for me to write the actual code for you as i have no idea what structure you are using, sorry.

Of course if your circle is an object, you could sensibly make it test itself against all the other circles, same idea. If you have an SQL database of circles, test them all against each other.

So fortunately you can see it is one (1) line of code to check if two circles are colliding. And it's about 3 or 4 lines of code to check all your circles for collisions. So fortunately about 5 lines in total!

So, that is an incredibly simple tutorial on video game physics, part 1.1.1.1 !!!! Hope it helps! If that is not what you were trying to achieve, it was a complete waste of typing! :)

For the record here's a routine to get the distance between two 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 );
    }

(Note... if you are new to Objective C, note that the above is totally valid code. Simply paste it in at the top of your file. OK? It's exactly like using any everyday function supplied by Apple such as x=CGLayerGetContext(), for example. Enjoy!)

Later .. and by popular demand, for an object, Circle...

-(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;
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文