I have a UIImageView which contains my main Character, and I have made the UIImageView appear circle see below code for creating my character
copter = [[UIImageView alloc] initWithFrame:CGRectMake(100, 500, 90, 90)];
[copter setContentMode:UIViewContentModeScaleAspectFit];
copter.layer.cornerRadius = roundf(copter.frame.size.width/2.0);
copter.layer.masksToBounds = YES;
[copter startAnimating];
[[self view] addSubview:copter];
[self setBat:copter];
I am having trouble with my collision between my character and other objects in the game. The collision is being detected on the rectangle rather than the circle. I have searched everywhere for an answer to fix this but no luck.
Here is my collision code I am using:
self.batVelocity += [link duration]*FBDownardBatAccelerationIpad;
[[self copter] setFrame:CGRectOffset([[self copter] frame], 0, [self batVelocity])];
UIView *removeBlock = nil;
for (UIView *block in [self blocks]) {
[block setFrame:CGRectOffset([block frame], [link duration]*FBSidewaysVelocityIpad, 0)];
if (CGRectIntersectsRect([[self copter] frame], [block frame])) {
[self failed];
So basically I need the circle bounds of the character to collide with a rectangle object, not the rectangle bounds of which the circle is in. I hope that makes sense.
Thanks in advance
I'd use a CGPathRef or CGMutablePathRef. So as #user3386109 suggests, check for collision between rects first, then if you have a pathRef for your sprite or whatever it is you can use CGPathContainsPoint(). Quartz has a few other comparison functions for CGPathRef for Rects as well, and for comparing a path against a second path, check the docs. I find CGPathRef to be quite efficient, but don't forget to release it with a CGPathRelease() to match every CGPathCreate or CGPathCopy() function or the leaks can add up real fast..
Right, so first you check for overlapping rectangles (which you've already done). When you find an overlap, then you need to refine the collision test. For each corner of the offending rectangle, compute the distance from the center of your character to the corner of the offending rectangle. If the distance from the center to any of the corners is less than the radius of the circle, then you have a collision. To optimize the code a little bit, compute (dx * dx + dy * dy) and compare that to the radius squared. That way you don't have to compute any square roots.
Upon further review, you also need to do an edge check in addition to the corner check. For example, if the top y value is above the center of the circle and the bottom y value is below the center of the circle, then compute the difference in x between the rectangle left edge and the center of the circle, and if that distance is less than the radius, then a collision has occurred. Likewise for the other three edges of the rectangle.
Here's some pseudo-code for the corner checking
int dx, dy, radius, radiusSquared;
radiusSquared = radius * radius;
for ( each rectangle that overlaps the player rectangle )
{
for ( each corner of the rectangle )
{
dx = corner.x - center.x;
dy = corner.y - center.y;
if ( dx * dx + dy * dy < radiusSquared )
Collision!!!
}
}
Related
I have two image views. The first is the blueish arrow, and the second is the white circle, with a black dot drawn to represent the center of the circle.
I'm trying to rotate the arrow so it's anchor point is the black dot in the picture like this
Right now I'm setting the anchor point of the arrow's layer to a point calculated like this
CGFloat y = _userImageViewContainer.center.y - CGRectGetMinY(_directionArrowView.frame);
CGFloat x = _userImageViewContainer.center.x - CGRectGetMinX(_directionArrowView.frame);
CGFloat yOff = y / CGRectGetHeight(_directionArrowView.frame);
CGFloat xOff = x / CGRectGetWidth(_directionArrowView.frame);
_directionArrowView.center = _userImageViewContainer.center;
CGPoint anchor = CGPointMake(xOff, yOff);
NSLog(#"anchor: %#", NSStringFromCGPoint(anchor));
_directionArrowView.layer.anchorPoint = anchor;
Since the anchor point is set as a percentage of the view, i.e. the coords for the center are (.5, .5), I'm calculating the percentage of the height in arrow's frame where the black dot falls. But my math, even after working out by hand, keeps resulting in .5, which isn't right because it's further than half way down when the arrow is in the original position (vertical, with the point up).
I'm rotating based on the user's compass heading
CLHeading *heading = [notif object];
// update direction of arrow
CGFloat degrees = [self p_calculateAngleBetween:[PULAccount currentUser].location.coordinate
and:_user.location.coordinate];
_directionArrowView.transform = CGAffineTransformMakeRotation((degrees - heading.trueHeading) * M_PI / 180);
The rotation is correct, it's just the anchor point that's not working right. Any ideas of how to accomplish this?
I've always found the anchor point stuff flaky, especially with rotation. I'd try something like this.
CGPoint convertedCenter = [_directionArrowView convertPoint:_userImageViewContainer.center fromView:_userImageViewContainer ];
CGSize offset = CGSizeMake(_directionArrowView.center.x - convertedCenter.x, _directionArrowView.center.y - convertedCenter.y);
// I may have that backwards, try the one below if it offsets the rotation in the wrong direction..
// CGSize offset = CGSizeMake(convertedCenter.x -_directionArrowView.center.x , convertedCenter.y - _directionArrowView.center.y);
CGFloat rotation = 0; //get your angle (radians)
CGAffineTransform tr = CGAffineTransformMakeTranslation(-offset.width, -offset.height);
tr = CGAffineTransformConcat(tr, CGAffineTransformMakeRotation(rotation) );
tr = CGAffineTransformConcat(tr, CGAffineTransformMakeTranslation(offset.width, offset.height) );
[_directionArrowView setTransform:tr];
NB. the transform property on UIView is animatable, so you could put that last line there in an animation block if desired..
Maybe better use much easier solution - make arrow image size bigger, and square. So the black point will be in center of image.
Please compare attached images and you understand what I'm talking about
New image with black dot in center
Old image with shifted dot
Now you can easy use standard anchor point (0.5, 0.5) to rotate edited image
How to determine whether value for angle of rotation of UIView is perpendicular to Y-axis or to restrict the angle of rotation to only quarter of the circle instead of whole 360 rotation.
I have a UIView with the below applied CATransformation,.
t = CATransform3DIdentity;
//Add the perspective!!!
t.m34 = 1.0/ 300;
t = CATransform3DRotate(t, 45.0f * M_PI / 180.0f, 0, 1, 0);
self.containerView.layer.sublayerTransform = t;
like in this link1
and changing the rotation angles based on UIPanGesture in the space outside of the rotated UIView with below code
- (void)handleRevealGestureStateChangedWithRecognizer:(UIPanGestureRecognizer *)recognizer{
//Calculating percent of translation.
CGPoint translation = [recognizer translationInView:recognizer.view.superview];
CGFloat rotationpercent = translation.x / recognizer.view.frame.size.width;
[self rotate:rotationpercent]; //calling method to transform based on translation value
}
- (void)rotate:(CGFloat)rotateDegress{
CGFloat angle = M_PI * rotateDegress;
t = CATransform3DRotate(t, angle, 0, 1, 0);
self.containerView.layer.sublayerTransform = t;
}
this rotates the view and for certain angles the view is either perpendicular to Y-axis on further it goes beyond window to rotate in full 360 degrees like shown in this link2.
Hence is it possible to determine if the angle is exceeding 90 degree so that rotation is disabled.
Thanks
Your code is using angles in degrees, which is fine (since you convert to radians before applying a rotation.)
Just put code in your gesture recognizer that limits the angles to a range of 0 to ~85 degrees. (Experiment with the upper limit to see how close to 90% you can get before the page is too thin to maintain the illusion of depth.) Problem solved.
Im trying to find out how to tell if my 2 round frames are intersecting each other. since they are round i cant use cgrectintersectsrect and am not sure how to go about this. is there a cgframeintersectsframe or something along those lines?
for my round uiimageviews i did
circle1 = [[uiimageview alloc] initwithframe:cgrectmake (100,100,50,50);
circle1.layer.cornerradius = 25;
circle1.clipstobounds = yes;
[self.view addsubview:circle1];
the other circle is basically like that too except with a different x and y origin
I also alreday imported quartzcore
Just calculate the distance between the centers of your circles and check if it's smaller than the radius:
float distanceBetweenCenters = sqrt(pow(circle1.center.x - circle2.center.x, 2) +
pow(circle1.center.y - circle2.center.y, 2));
BOOL isIntersecting = distanceBetweenCenters <= 2 * radius;
This will tell you whether the circles are intersecting or touching each other. Replace the <= with < to exclude 'touching'.
I am going out of my mind trying to detect a collision for the bottom of the ball when it touches the connect1 UIimageview
if (CGRectIntersectsRect(ball.frame, box.frame))
{
yesno.text=#"Found the spot";
}
**This obviously detects any part of the frame.
If anyone could point me in the correct direction I would be very appreciative.
Instead of looking at the intersection of the ball's frame and the box's frame, look for the intersection of the ball's frame with a rectangle whose top is aligned with the bottom of the box.
CGRect bottom = CGRectMake(box.frame.x, box.frame.y + box.frame.height, box.frame.width, 50.0);
if (CGRectIntersectsRect(ball.frame, bottom))
{
yesno.text=#"Found the spot";
}
Alternatively, assuming that the ball is normally inside the box, it's probably faster to simply check the position of the ball with respect to the box:
CGFloat ballBottom = ball.frame.y + ball.frame.height;
CGFloat boxBottom = box.frame.y + box.frame.height;
if (ballBottom > boxBottom) {
yesno.text=#"Found the spot";
}
I have a line, which is a sprite made by using this code
CGPoint diff = ccpSub(startLocation, endLocation);
float rads = atan2f( diff.y, diff.x);
float degs = -CC_RADIANS_TO_DEGREES(rads);
float dist = ccpDistance(endLocation, startLocation);
CCSprite *line = [CCSprite spriteWithFile:#"line.png"];
[line setAnchorPoint:ccp(0.0f, 0.5f)];
[line setPosition:endLocation];
[line setScaleX:dist / line.boundingBox.size.width];
[line setRotation: degs];
line.tag = 1;
[_lines addObject:line];
[self addChild:line];
Now in my collision detection code I use the following code to create a CGRect:
CGRect lineRect = CGRectMake(
line.position.x - (line.contentSize.width/2),
line.position.y - (line.contentSize.height/2),
line.contentSize.width,
line.contentSize.height);
This of course is faulty because the line is made using an angle.
I'm trying to compare a rectangle, a square sprite, with this rectangle.
The idea is that a character is moving and the player can draw a line, if the character hits the line it's bounces of in the opposite direction.
I have the angle, the x&y position of one side of the line and the length of the line.
How do I get the other x&y position of the other side of the line?
Hope you guys can help me out.
Thanks in advance!
It's a little hard to know if I understand you correctly, but when you say "...the other x&y position of the other side of the line," I'm assuming you meant what is the coordinates of the opposite endpoint of the line.
If so, I believe the actual formula you may be looking for is:
{x1, y1} = starting point that you already have
{x2, y2] = point you're looking to find
x2 = x1 + (distance * cosA)
y2 = y1 + (distance * sinA)
But as I mentioned earlier, I'm a little unsure whether this would give you exactly what you needed. If you're actually looking for the points of the vertices of the opposite side of the bounding box for the Line.png, then perhaps you could still use that formula, but change the degrees by 90 to determine the coordinates offset from the x&y that you already know.
Anyway, I hope that at least helps put you in a helpful direction.
You should probably look up the documentation for CGRectApplyAffineTransform, CGAffineTransformMakeRotation and possibly CGAffineTransformMakeTranslation.