我有4个元素:从屏幕顶部掉下来的绿球,黄球,橙球和红球
我也有一个元素,蓝球,跟着我的触摸。
所有这些都很有效! :d
但是,我想检测绿球与蓝球相交的时间
我的蓝色球被放置在viewDidLoad的视图中,4个球被放置在视图上,基于调用onTimer的nstimer。
所有5个球都在同一层上创建:
[self.view insertSubview:greenImage belowSubview:bottomBar]
我可以检测到红球和绿球碰撞的时间:
if (CGRectIntersectsRect(greenImage.frame, redImage.frame)) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"title" message:@"points" delegate:nil cancelButtonTitle:@"cool" otherButtonTitles:nil];
[message show];
[message release];
}
如果我将“redImage”替换为“blueball”,我就不会收到警报。我认为这可能是因为它们没有在同一方法中声明。
有关如何检测此碰撞的任何想法?
谢谢!
---编辑---
使用下面的建议我正在做以下事情:
greenImage = [[UIImageView alloc] initWithImage:green];
greenImage.frame = CGRectMake(startX,0,43,43);
[self.view insertSubview:greenImage belowSubview:bottomBar];
[UIView beginAnimations:nil context:greenImage];
[UIView setAnimationDuration:5 * speed];
greenImage.frame = CGRectMake(startX, 500.0, 43,43);
CGFloat r1 = greenImage.frame.size.width * .5;
CGFloat r2 = blueBall.frame.size.width * .5;
if(CGPointDistance(greenImage.center, blueBall.center) < (r1 + r2)){
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"notice" message:@"hit!" delegate:nil cancelButtonTitle:@"cool" otherButtonTitles:nil];
[message show];
[message release];
}
在这个方法之下我有:
CGFloat CGPointDistance(CGPoint p1, CGPoint p2)
{
return sqrtf((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
}
收到错误:
'CGPointDistance'的冲突类型
并发出警告:
函数'CGPointDistance'的隐式声明
答案 0 :(得分:1)
要确定两个圆是否相交,您只需查看中心之间的距离是否小于它们的半径之和。例如......
CGFloat CGPointDistance(CGPoint p1, CGPoint p2)
{
return sqrtf((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
}
看起来你的“球”是视图......假设“球”填满了框架,半径将是宽度的1/2 ......
BOOL BallsCollide(UIView *v1, UIView *v2)
{
CGFloat r1 = v1.frame.size.width * .5;
CGFloat r2 = v2.frame.size.width * .5;
return CGPointDistance(v1.center, v2.center) < (r1 + r2);
}
好的 - 我已经砍了一个快速的样本。您几乎可以将其放入视图控制器中。不要将它用于制作东西......就像你可以做什么的一个例子......你可以把它放在顶部,控制器的其余部分放在它下面......
// I do not recommend using this approach for naything non-trivial,
// but it demonstrates the very simple collision detection for circle shapes.
@interface Ball : UIView {
}
@property (nonatomic, strong) UIColor *origColor;
@property (nonatomic, strong) UIColor *color;
+ (id)ballWithRadius:(CGFloat)radius color:(UIColor*)color;
- (BOOL)doesIntersectWith:(Ball*)ball;
@end
@implementation Ball
@synthesize color = _color;
@synthesize origColor = _origColor;
+ (id)ballWithRadius:(CGFloat)radius color:(UIColor*)color
{
CGFloat diameter = radius * 2;
Ball *ball = [[Ball alloc] initWithFrame:CGRectMake(0, 0, diameter, diameter)];
ball.color = ball.origColor = color;
ball.backgroundColor = [UIColor clearColor];
return ball;
}
- (BOOL)doesIntersectWith:(Ball *)ball
{
// Two circles overlap if the sum of their radii
// is less than the distance between the two centers.
CGFloat r1 = self.frame.size.width * .5;
CGFloat r2 = ball.frame.size.width * .5;
CGFloat diffX = self.center.x - ball.center.x;
CGFloat diffY = self.center.y - ball.center.y;
return (diffX*diffX) + (diffY*diffY) < (r1+r2)*(r1+r2);
}
- (BOOL)containsPoint:(CGPoint)point
{
// Contains a point if distance from center is less than radius
CGFloat r = self.frame.size.width *.5;
CGFloat diffX = self.center.x - point.x;
CGFloat diffY = self.center.y - point.y;
return (diffX*diffX) + (diffY*diffY) < r*r;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
[self.color setFill];
[self.color setStroke];
CGContextSetLineWidth(context, 1);
CGContextFillEllipseInRect(context, self.bounds);
}
@end
@interface CollideVC() {
NSMutableDictionary *activeTouches;
NSMutableSet *currentCollisions;
}
@end
@implementation CollideVC
- (void)ball:(Ball*)ball touched:(UITouch*)touch
{
[activeTouches setObject:ball forKey:[NSValue valueWithPointer:(__bridge void*)touch]];
}
- (Ball*)getBallTouchedBy:(UITouch*)touch
{
return [activeTouches objectForKey:[NSValue valueWithPointer:(__bridge void*)touch]];
}
- (void)stopTouch:(UITouch*)touch
{
[activeTouches removeObjectForKey:[NSValue valueWithPointer:(__bridge void*)touch]];
}
- (void)ball:(Ball*)ball1 hasCollidedWith:(Ball*)ball2
{
[currentCollisions addObject:ball1];
[currentCollisions addObject:ball2];
ball1.color = ball2.color = [UIColor yellowColor];
[ball1 setNeedsDisplay];
[ball2 setNeedsDisplay];
}
// NOTE: You should delegate handling of collisions...
- (void)checkForCollisions
{
// Should filter those that don't actually need redisplay...
// For simplicity, all that were or are colliding get it...
[currentCollisions enumerateObjectsUsingBlock:^(Ball *ball, BOOL *stop) {
[ball setNeedsDisplay];
ball.color = ball.origColor;
}];
[currentCollisions removeAllObjects];
NSArray *views = self.view.subviews;
for (size_t i = 0; i < views.count; ++i) {
id v = [views objectAtIndex:i];
if (![v isKindOfClass:[Ball class]]) continue;
Ball *ball1 = v;
for (size_t j = i+1; j < views.count; ++j) {
v = [views objectAtIndex:j];
if (![v isKindOfClass:[Ball class]]) continue;
Ball *ball2 = v;
if ([ball1 doesIntersectWith:ball2]) {
[self ball:ball1 hasCollidedWith:ball2];
}
}
}
}
- (void)addBallWithRadius:(CGFloat)radius point:(CGPoint)point color:(UIColor*)color
{
Ball *ball = [Ball ballWithRadius:radius color:color];
ball.center = point;
[self.view addSubview:ball];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
for (Ball *ball in self.view.subviews) {
if ([ball containsPoint:touchLocation]) {
[self ball:ball touched:touch];
}
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
// Use relative distance so center does nt jump to tap location.
CGPoint prev = [touch previousLocationInView:self.view];
CGPoint curr = [touch locationInView:self.view];
CGPoint c = [self getBallTouchedBy:touch].center;
[self getBallTouchedBy:touch].center = CGPointMake(c.x+curr.x-prev.x, c.y+curr.y-prev.y);
}
// NOTE: This does not check the path between the moves, only the new point.
// So a fast movement "past" the other object will not get detected.
// If you want to do comple detection, use an existing engine
[self checkForCollisions];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
[self stopTouch:touch];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
activeTouches = [NSMutableDictionary dictionary];
currentCollisions = [NSMutableSet set];
[self addBallWithRadius:20 point:CGPointMake(110, 100) color:[UIColor blueColor]];
[self addBallWithRadius:20 point:CGPointMake(200, 200) color:[UIColor redColor]];
[self addBallWithRadius:20 point:CGPointMake(235, 250) color:[UIColor greenColor]];
}
答案 1 :(得分:0)
也许这会对某些人有所帮助,只需对上面的代码进行一些修改。
-(CGFloat)CGPointDistance:(CGPoint)p1 p2:(CGPoint)p2
{
return sqrtf(powf(p1.x - p2.x) + powf(p1.y-p2.y));
}
-(BOOL)DidCollide:(View*)v1 v2:(View*)v2 v1Radius:(CGFloat)v1Radius v2Radius:(CGFloat)v2Radius
{
CGFloat r1 = v1.frame.size.width * v1Radius;
CGFloat r2 = v2.frame.size.width * v2Radius;
return [self PointDistance:v1.center p2:v2.center] < (r1 + r2)
}
并检查你刚刚做的碰撞
if([self DidCollide:view1 v2:view2 v1Radius:radius v2Radius:radius])
{
//do something
}