(iphone) a very simple Iphone game - iphone

Hi I want to implement a very simple game on iphone. I have a image and a text. If a user draw a line between the image and the text then it says "correct"
Now what I am thinking is that whenever a user touch the screen I will get the location (like X,Y) of that touching spot ( which method to call to get the location? ) and then I will draw a black dot there. If the user continuously and smoothly touch the screen then a line will form. Finally I will only need to judge whether the starting point of the line locates within the image and the ending point locates within the text.
I dont know whether my idea is a correct way to implement this kinda game. If it is how to get coordinate of touching spot and draw a black dot in that specific location?
Thanks for helping!

You may get the touch coordinates in touchesMoved of your view controller:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touch_point = [touch locationInView:self.view];
NSLog(#"x: %.0f y: %.0f", touch_point.x, touch_point.y);
}
To draw the line, you have add a view and draw line in drawRect:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 1.0);
CGContextSetStrokeColorWithColor(context, [UIColor orangeColor].CGColor);
// ...
CGContextMoveToPoint(context, one_x, one_y);
CGContextAddLineToPoint(context, two_x, two_y);
CGContextStrokePath(context);
// ...
}
where one_x one_y two_x two_x are coordinates for two points ..

This is exactly how the iPhone touch delegation works. It calls touchesBegan:, touchesMoved: and touchesEnded:. To draw the lines, you need this code:
CGContextRef context = UIGraphicsGetCurrentContext();
[current set];
CGContextSetLineWidth(context, 4.0f);
for (int i = 0; i < (self.points.count - 1); i++)
{
CGPoint pt1 = POINT(i);
CGPoint pt2 = POINT(i+1);
CGContextMoveToPoint(context, pt1.x, pt1.y);
CGContextAddLineToPoint(context, pt2.x, pt2.y);
CGContextStrokePath(context);
}
And with the help of this code, you should be ready to make it. If you need any help, just comment on this or make another question.
CGPoint pt = [[touches anyObject] locationInView:self];
[self.points addObject:[NSValue valueWithCGPoint:pt]];
[self setNeedsDisplay];

Related

How to connect two buttons( dots) with a line in iOS? [duplicate]

This question already has answers here:
draw line between two points in iphone?
(3 answers)
Closed 9 years ago.
I want to make a project in which I have to touch one dot and connect it with another dot and after connect it to another dot. When I connect one dot with another dot the line will create between them.
Actually when I click/ touch one dot The line will show and When I touch second dot the line will create between the two dots.
I am not able to do this yet, I am trying and searching on the net but unable to find the solution yet.
This is my need Like this one https://play.google.com/store/apps/details?id=zok.android.dots&hl=en
I think this is done by UIGesture Recogniser? Or is this something else? How I can achieve this?
Any Idea or suggestions from experts would be highly welcome.
Modify this code according to your requiements
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *currentColor = [UIColor blackColor];
CGContextSetStrokeColorWithColor(context, currentColor.CGColor);
CGContextSetLineWidth(context, 2.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, touchStart.x, touchStart.y);
CGContextAddLineToPoint(context, touchEnd.x, touchEnd.y);
CGContextStrokePath(context);
#Nisha:
Make gloabal instances of CGPoint touchStart and touchEnd and get them like this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
touchEnd = CGPointZero;
touchStart = CGPointZero;
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
NSLog(#"start point >> %#",NSStringFromCGPoint(point));
touchStart = point;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
touchEnd = point;
[self setNeedsDisplay];
}
You can store the touched locations in two different CGPoint with the help of the touchedEnded method.
Then, when you have your two points, you can add a new UIView as subview which is aware of the two CGPoint and will draw a line in its drawRect method. Or do it in the current view, by calling [view setNeedsDisplay] to trigger its own drawRect method.
Check out this link.
If it is possible for you please get the coordinates of two button with UI touch methods. You can find the touched locations in two different CGPoint with the help of the touchedEnded method.To find touch location documentation is here
After getting the location of UIButtons on your view you can draw the line between then with this method-
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetStrokeColorWithColor(context, [[UIColor blackColor]CGColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
Hope this helps
Try below steps.
Create one subclass of UIView. Add your UIButtons on it.
Implement Touches delgates, like touchesBegan, moved, end.
Inside touchesBegan check if touch isinsideview:myButton1 then make a flag true.
EDIT:
UITouch *touch = [[UITouch alloc] init];
touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
if(CGRectContainsPoint(myButton1.frame, point))
NSLog(#"Inside myButton1");
Another way to test if subview is hit by touches is
CGPoint pt = [[touches anyObject] locationInView:self.view];
UIView *touchedView = [self.view hitTest:pt withEvent:event];
inside touches moved check if flag true then drawline()... and keep checking if touches are in insideview:myButton2. call setNeedsDisplay.
Now you will get number of ways and sample code to draw line in UIView. Just apply above logic.

Trying to fill a path with colour in CGContext without much luck

I currently have the following code to try and allow the user to draw a dotted path and make a custom shape. Once they have made this shape, I wanted it to automatically be filled with colour. That isn't happening.
At the moment I am getting this error for the code below:
<Error>: CGContextClosePath: no current point.
Here's the code I'm using:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint previous = [touch previousLocationInView:self];
CGPoint current = [touch locationInView:self];
#define SQR(x) ((x)*(x))
//Check for a minimal distance to avoid silly data
if ((SQR(current.x - self.previousPoint2.x) + SQR(current.y - self.previousPoint2.y)) > SQR(10))
{
float dashPhase = 5.0;
float dashLengths[] = {10, 10};
CGContextSetLineDash(context,
dashPhase, dashLengths, 2);
CGContextSetFillColorWithColor(context, [[UIColor lightGrayColor] CGColor]);
CGContextFillPath(context);
CGContextSetLineWidth(context, 2);
CGFloat gray[4] = {0.5f, 0.5f, 0.5f, 1.0f};
CGContextSetStrokeColor(context, gray);
self.brushSize = 5;
self.brushColor = [UIColor lightGrayColor];
self.previousPoint2 = self.previousPoint1;
self.previousPoint1 = previous;
self.currentPoint = current;
// calculate mid point
self.mid1 = [self pointBetween:self.previousPoint1 andPoint:self.previousPoint2];
self.mid2 = [self pointBetween:self.currentPoint andPoint:self.previousPoint1];
if(self.paths.count == 0)
{
UIBezierPath* newPath = [UIBezierPath bezierPath];
CGContextBeginPath(context);
[newPath moveToPoint:self.mid1];
[newPath addLineToPoint:self.mid2];
[self.paths addObject:newPath];
CGContextClosePath(context);
}
else
{
UIBezierPath* lastPath = [self.paths lastObject];
CGContextBeginPath(context);
[lastPath addLineToPoint:self.mid2];
[self.paths replaceObjectAtIndex:[self.paths indexOfObject:[self.paths lastObject]] withObject:lastPath];
CGContextClosePath(context);
}
//Save
[self.pathColors addObject:self.brushColor];
self.needsToRedraw = YES;
[self setNeedsDisplayInRect:[self dirtyRect]];
//[self setNeedsDisplay];
}
}
Why is this happening and why is the inside of the path not being filled with colour?
Your code has a few issues:
You should be doing your drawing in your view's drawRect: method, not the touch handler.
You never set the variable context with a value for the current context. Do that with the UIGraphicsGetCurrentContext() method. Again, within your drawRect: method.
You go through the trouble of creating a UIBezierPath object, but you never use it. Do that by calling CGContextAddPath( context, newPath.CGPath ), changing the variable name as needed in the two places you appear to the using a UIBezierPath.
Keep the call to setNeedsDisplayInRect: in your touch handler method. That tells the system to do the work to update your view using the drawing that your (yet to be implemented) drawRect: method draws.

I want to draw a rectangle like shape with drag-able corners in IOS

I want to overlay a a box shape over a photograph and allow the user to select each corner, and drag the corners to where they want.
I could use 4 invisible buttons(to represent each corner) that respond to drag events to get the x,y points for each corner, but is there some line drawing functionality available in xcode without touching any of the game api classes? I guess I want to draw lines onto a UIView.
Many Thanks,
-Code
Make a subclass of UIView to represent your view. Add a UIImageView to your view. This will hold the image with user's drawing.
Enable user interaction in the UIView sub-class.
self.userInteractionEnabled = YES;
Detect the starting tap by implementing this method in your subclass:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// We are starting to draw
// Get the current touch.
UITouch *touch = [touches anyObject];
startingPoint = [touch locationInView:self];
}
Detect the last tap to draw straight line:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
endingPoint = [touch locationInView:self];
// Now draw the line and save to your image
UIGraphicsBeginImageContext(self.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 10);
CGContextMoveToPoint(context, NULL, startingPoint.x, startingPoint.y);
CGContextAddLineToPoint(context, NULL, endingPoint.x, endingPoint.y);
CGContextSetRGBFillColor(context, 255, 255, 255, 1);
CGContextSetRGBStrokeColor(context, 255, 255, 255, 1);
CGContextStrokePath(context);
self.image = UIGraphicsGetImageFromCurrentImageContext();
CGContextRelease(context);
}

how to draw continuous lines by QuartzCore in iOS

I have got a question about quartz core on iOS
When I use Quartz to draw lines, the following happens and I can't find the reason:
when I draw the second line the first line would disappear
when I draw the third line the second would the disappear, and the 1st and 3rd would show
..
when I draw the 2n+1th line, 1,3,5,...2n-1th lines shows, and 2,4,6,8... 2n dissappears
see the code below. I don't save contexts and paths
as my understanding, I think it should be one of the two cases
display all lines I drawn
display the last line I drawn and the previous lines should disappear
But the two cases don't happen.
- (void)drawInContext:(CGContextRef)context {
// 橡皮擦
//CGContextClearRect(context, CGRectMake(0, 0, 320, 480));
CGContextSetLineWidth(context, 4.0);
CGContextMoveToPoint(context, previousPoint.x, previousPoint.y);
CGContextSetRGBStrokeColor(context, 0, 1.0, 1.0, 1.0);
CGContextAddLineToPoint(context, nextPoint.x,nextPoint.y);
CGContextStrokePath(context);
//NIF_TRACE(#"began : %# moved : %#", NSStringFromCGPoint(previousPoint),NSStringFromCGPoint(nextPoint));
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
previousPoint = [touch locationInView:self];
nextPoint = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
previousPoint = nextPoint;
nextPoint = [touch locationInView:self];
[self setNeedsDisplay];
}
I saw a demo that use NSMutableArray to save all UIBezierPaths it drawn, when the View redraw, it transfer paths saved in array, restores them in drawRect:
UIBezierPath is a wrapper of Objective C, and it only works in 3.2+
I need do something make it work in 3.0+
I think it must be exists a better method to save contexts and paths (Colors,Paths,strokeWidths)
Anybody have ideas?
Every time you "drawInContext" you are clearing the drawing area and placing the new line.... This clear code:
CGContextClearRect(context, CGRectMake(0, 0, 320, 480));
Needs to be somewhere else in your code... somewhere where it will only be activated 1 time (or if you need to clear the whole drawing (perhaps an erase all function))
You need to save the image on canvas:
CGImageRef imageRef;
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
if (imageRef) {
// Restore the screen that was previously saved
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, rect, imageRef);
CGImageRelease(imageRef);
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
}
// Your drawing code here...
imageRef = CGBitmapContextCreateImage(context);
}

Redrawing a path using CGContextStrokePath after initial load

I have a basic map view in my app which contains a set of user definable way points. When the view is loaded I draw a path connecting the way points. This works well.
However, when the user drags a way point around the view, I would like it to re-draw the paths and that is my problem. I dont know how to hacant get it to draw anything after the first time. Here's my code:
- (void)drawRect:(CGRect)rect { ////// works perfectly
context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1, 0, 1, .7);
CGContextSetLineWidth(context, 20.0);
WaypointViewController *w = [arrayOfWaypoints objectAtIndex:0];
CGPoint startPoint = w.view.center;
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
for (int i = 1; i<[arrayOfWaypoints count]; i++) {
WaypointViewController *w2 = [arrayOfWaypoints objectAtIndex:i];
CGPoint nextPoint = w2.view.center;
CGContextAddLineToPoint(context,nextPoint.x, nextPoint.y);
}
CGContextStrokePath(context);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (moving) {
UITouch *touch = [touches anyObject];
currentWaypoint.view.center = [touch locationInView:self];
[delegate setUserInteraction:NO];
[self drawInContext:context];
[NSThread detachNewThreadSelector:#selector(drawInContext:) toTarget:self withObject:nil];
}
}
- (void)drawInContext:(CGContextRef)context { ///gets called, but does nothing
CGContextSetRGBStrokeColor(context, 1, 0, 1, .7);
CGContextSetLineWidth(context, 20.0);
WaypointViewController *w = [arrayOfWaypoints objectAtIndex:0];
CGPoint startPoint = w.view.center;
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
for (int i = 1; i<[arrayOfWaypoints count]; i++) {
WaypointViewController *w2 = [arrayOfWaypoints objectAtIndex:i];
CGPoint nextPoint = w2.view.center;
CGContextAddLineToPoint(context,nextPoint.x, nextPoint.y);
}
CGContextStrokePath(context);
}
You can not use the context that is active in drawRect: anywhere else.
Instead of calling [self drawInContext:context] call [self setNeedsDisplay]
The context that you are pointing to in your drawRect: might be freed or might still be active you don't know, but either way there is no way to get the bits you put into that context onto the screen.
Also, please read the docs on drawing on iOS here
You may not save the context for use after drawRect: returns. What you need to do is call [self setNeedsDisplay] (or setNeedsDisplayInRect:, if you can determine the bounding rectangle of the change), which will cause the system to call drawRect: again for you.
You can do all your drawing only in drawRect ...Hope this helps ... hence - (void)drawInContext:(CGContextRef)context will not be able to do any drawing. if after user's touch action , you need to do some redrawing then you need to call [self setNeedsDisplay] in your touchmethods.