cocoa collision detection question

时间秒杀一切 提交于 2019-12-11 12:30:22

问题


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.


回答1:


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


来源:https://stackoverflow.com/questions/5051921/cocoa-collision-detection-question

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!