I'm stuck on how to detect if a line (made from 2 touch locations) cuts through a pizza. Here's an example of what I mean.
would return YES:

would return NO:

would return NO:

anyone have any ideas?
A fast, easy to use, free, and community supported 2D game engine
I'm stuck on how to detect if a line (made from 2 touch locations) cuts through a pizza. Here's an example of what I mean.
would return YES:

would return NO:

would return NO:

anyone have any ideas?
If the two touch locations are not inside the circle, and if the point in the middle of the two points is.
Not sure if this is the most efficient, but this is what I ended up doing:
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint endTouch = [self convertTouchToNodeSpace:touch];
// Check if two points are in circle
// If they are, we don't want it, so we return
CGPoint circleCenter = ccp(..., ...);
float circleRadius = ...;
if( (ccpLengthSQ(ccpSub(circleCenter, startTouch_)) < (circleRadius * circleRadius)) ||
(ccpLengthSQ(ccpSub(circleCenter, endTouch)) < (circleRadius * circleRadius)) )
{
return;
}
// m = (y2-y1)/(x2-x1); b = y - mx
float m = (endTouch.x - startTouch_.x) != 0 ? (endTouch.y - startTouch_.y) / (endTouch.x - startTouch_.x) : 0;
int b = startTouch_.y - m * startTouch_.x;
int startX = ceil(startTouch_.x);
int endX = floor(endTouch.x);
// iterate through all x values
// we add 1 because we want to ignore first value
// we don't use <= because we want to ignore last value
BOOL pointIsInCircle = NO;
for(int x = MIN(startX, endX) + 1; x < MAX(startX, endX); x++)
{
int y = round(m * x + b);
CGPoint point = ccp(x, y);
// Detect if point is in circle...
if(ccpLengthSQ(ccpSub(circleCenter, point)) < (circleRadius * circleRadius))
{
pointIsInCircle = YES;
break;
}
}
if(pointIsInCircle)
{
NSLog(@"slice");
}
}
It first checks if the 2 touches are in the circle. If they are, it returns. Then, it calculates all integer points on the line segment in a for loop. If it finds one that's in the circle, it breaks from the loop because we know that it was sliced.
In the loop, I used MIN and MAX because it will start at the lower one and iterate up, so if it started at the bigger one and ended with the smaller one, it would lead to an infinite loop.
Thanks to @manucorporat for code to check if a point is in a circle.
Hope this helps someone :)
Calculate ALL integer points?
That CERTAINLY isn't the most efficient way, but it might be the most stupid ...
After you have checked that endpoints are outside, you weight a point on the line, according to the endpoint distances from pizza center. If distance from this point to center is less than radius ... voila ...
And please shape up on the rest of the game ... ;)
Ups sorry this is only for a point not a line...
I think this is what you need
yeah, iterating through 100+ points isn't very elegant when it's only going to help in rare situations... I changed it to this, it catches about 99% of slices but if someone were to try to cut the very edge (for some reason) it would report that it didn't slice it when it really did.... but this is good enough
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint endTouch = [self convertTouchToNodeSpace:touch];
// Check if two points are in circle
// If they are, we don't want it, so we return
CGPoint circleCenter = ...;
float circleRadius = ...;
if( (ccpLengthSQ(ccpSub(circleCenter, startTouch_)) < (circleRadius * circleRadius)) ||
(ccpLengthSQ(ccpSub(circleCenter, endTouch)) < (circleRadius * circleRadius)) )
{
return;
}
CGPoint midpoint = ccpMidpoint(startTouch_, endTouch);
if( (ccpLengthSQ(ccpSub(circleCenter, midpoint)) < (circleRadius * circleRadius)) )
{
NSLog(@"slice");
}
}Judging from your drawings, center point is probably a good approach, and as you pizza probably is larger than 32 * 32 pixels in a 1024 * 1024 game field, I bet it works.
However. If your game was a "slice'em up", gameplay would be heavily dependent on 100% correct slice detection.
http://mathworld.wolfram.com/Circle-LineIntersection.html gives a way of detecting whether a line intersects a circle at 0,0. So just translate your line and circle to 0,0, apply the math (you don't need to calculate the actual point of intersection unless you need it, just Δ) and you get your result.
(First hit for Googling for circle line intersection)
@TBBle, that works, but it's for (infinite) lines, I guess I probably should have said line segment. When I used that, if I started a line that might cut it it would still say that it intersected. I found this ( http://ubuntuforums.org/showthread.php?t=1392474 ) and I it works with this code ;)
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint endTouch = [self convertTouchToNodeSpace:touch];
// Check if two points are in circle
// If they are, we don't want it, so we return
CGPoint circleCenter = ...;
float circleRadius = ...;
if( (ccpLengthSQ(ccpSub(circleCenter, startTouch_)) < (circleRadius * circleRadius)) ||
(ccpLengthSQ(ccpSub(circleCenter, endTouch)) < (circleRadius * circleRadius)) )
{
return;
}
CGPoint a = ccpSub(endTouch, startTouch_);
CGPoint b = ccpSub(circleCenter, startTouch_);
float c = ccpDot(a, b) / ccpDot(a, a);
c = (c < 0.0f) ? 0.0f : c;
c = (c > 1.0f) ? 1.0f : c;
CGPoint d = ccpAdd(startTouch_, ccpMult(a, c));
CGPoint e = ccpSub(circleCenter, d);
float f = ccpDot(e, e);
BOOL isSlice = (f <= circleRadius * circleRadius);
if(isSlice)
{
NSLog(@"slice");
}
}The issue I see with determining a slice using a center-point is that this will not be considered as a slice:

Maybe you can calculate the length of the line and set 3 check points: 25%, 50%, 75%.
If any of these are inside (and the start & end touch points are outside), then it's a slice.
So it's checking only 3 points instead of many, and eliminating many of the situations where a slice won't be registered.
yeah, that's what I was thinking when I said it would miss a few of the slices. But above your post I used a different method that catches all of them ;)
Use the link I posted to find the point of intersection, and check that it's on the segment of your line that you're interested in.
I'm amazed that people keep posting things like "Pick some points, test 'em, and hope for the best"...
You must log in to post.