0

I'm writing a small word search game for the iPad. i have a UIViewController and I tile the letters random in a UIView (lettersView). I set the label's tag in a 10x10 size matrix, using a UILabel for each letter.

Here is my problem: I don't know how to draw over letters (UILabels). I have researched the matter and am confused which way to use (touch, opengl, quartz, hittest).

  • I just want to draw a straight line from the first point to the last point (touch down to touch up).
  • when user taps on the lettersView, I must find which letter was tapped. I can find the letter if I get the which UILabel was tapped first.
  • while the user moves their finger, it should draw the line, but while the user moves it must delete the old ones.
  • when the user touches up how can I get the last UILabel? i can check if its drawable, if I get the first and last uilabel.

(i found a small drawing sample written in ARC mode. but i cant convert it to non-ARC.)


i did all what you said. but i have some problems. it draws the line on drawRect method. when i draw second line, it deletes the old one. here is the codes:

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    touchStart = [[touches anyObject] locationInView:self];
    float xPos=touchStart.x;
    float yPos=touchStart.y;

    startIndexCol = floor(xPos / letterWidth);
    startIndexRow = floor(yPos / letterHeight);

    xPos = (startIndexCol * letterWidth) + letterWidth/2;
    yPos = (startIndexRow * letterHeight) + letterHeight/2;
    touchStart = CGPointMake(xPos, yPos);
    touchCurrent = touchStart;
    [self setNeedsDisplay];
}

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    touchCurrent = [[touches anyObject] locationInView:self];
    //CGRect frame = CGRectMake(touchStart.x, touchStart.y, touchCurrent.x, touchCurrent.y);
    //[self setNeedsDisplayInRect:frame];
    [self setNeedsDisplay];
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    touchCurrent = [[touches anyObject] locationInView:self];
    //[self hitTest:touchCurrent withEvent:event];
    float xPos=touchCurrent.x;
    float yPos=touchCurrent.y;

    endIndexCol = floor(xPos / letterWidth);
    endIndexRow = floor(yPos / letterHeight);

    xPos = (endIndexCol * letterWidth) + letterWidth/2;
    yPos = (endIndexRow * letterHeight) + letterHeight/2;
    touchCurrent = CGPointMake(xPos, yPos);
    //CGRect frame = CGRectMake(touchStart.x, touchStart.y, touchCurrent.x, touchCurrent.y);
    //[self setNeedsDisplayInRect:frame];


    //check if it can be drawn
    if ((startIndexCol == endIndexCol) && (startIndexRow == endIndexRow)) {
        //clear, do nothing
        touchStart = touchCurrent = (CGPoint) { -1, -1 };
        startIndexCol = startIndexRow = endIndexCol = endIndexRow = -1;
    }
    else{
        if (startIndexRow == endIndexRow) {//horizontal
            if (endIndexCol > startIndexCol) {
                [delegate checkWordInHorizontal:startIndexRow start:startIndexCol end:endIndexCol];
            }
            else{
                [delegate checkWordInHorizontalBack:startIndexRow start:startIndexCol end:endIndexCol];
            }
        }
        else if (startIndexCol == endIndexCol){ //vertical
            if (endIndexRow > startIndexRow) {
                [delegate checkWordInVertical:startIndexCol start:startIndexRow end:endIndexRow];
            }
            else{
                [delegate checkWordInVerticalBack:startIndexCol start:startIndexRow end:endIndexRow];
            }
        }
    }


    [self setNeedsDisplay];
}

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    UIView *subview = [super hitTest:point withEvent:event];
    if ([subview isEqual:self]) {
        NSLog(@"point:%f - %f", point.x, point.y);
        return self;
    }
    return nil;

}

-(void)drawLine{
    NSLog(@"draw it");
    drawIt=YES;
    [self setNeedsDisplay];
}


- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    if (drawIt) {
        NSLog(@"drawit");
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSetLineWidth(ctx, 20.0);
        CGContextSetRGBStrokeColor(ctx, 1.0, 2.0, 0, 0.5);
        CGContextMoveToPoint(ctx, touchStart.x, touchStart.y);
        CGContextAddLineToPoint(ctx, touchCurrent.x, touchCurrent.y);

        CGContextStrokePath(ctx);
        drawIt=NO;
        touchStart = touchCurrent = (CGPoint) { -1, -1 };
        startIndexCol = startIndexRow = endIndexCol = endIndexRow = -1;
    }

        [[UIColor redColor] setStroke];
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:touchStart];
        [path addLineToPoint:touchCurrent];
        [path setLineWidth:20.0];
        [path strokeWithBlendMode:kCGBlendModeNormal alpha:0.5];
//        [path stroke];
}
Nathaniel Waisbrot
  • 23,261
  • 7
  • 71
  • 99
fulberto100
  • 313
  • 5
  • 23

1 Answers1

1

First, the UILabels are likely to cause you more trouble than good. For such as simple grid, it is likely easier to just draw the letters by hand in drawRect:, along with your connecting line. The overall structure would look like this:

  • In touchesBegan:withEvent:, you would make a note of the starting point in an ivar.
  • In touchesMoved:withEvent:, you would update the end-point in an ivar and call [self setNeedsDisplayInRect:]. Pass the rectangle defined by your two points.
  • In touchesEnded:withEvent:, you would make a hit-test, do whatever processing that entails, and then clear your starting and end points and call [self setNeedsDisplayInRect:].
    • By "make a hit-test," I mean calculate which letter is under the touch. Since you're laying these out in a grid, this should be very simple math.
  • In drawRect:, you would use [NSString drawAtPoint:withFont:] to draw each letter. You would then use UIBezierPath to draw the line (you could also use CGPathRef, but I'd personally use the UIKit object).
Rob Napier
  • 286,113
  • 34
  • 456
  • 610