0

我正在尝试在触摸时绘制线条精灵,然后在触摸时操纵这些线条。画线参考论坛链接:cocos2d forum

操作包括拖动和旋转线条。仅在触摸中心区域时才可以拖动,并且可以正常工作。

关于旋转,我需要做的是当触摸在任何端点区域时,我需要旋转线(不改变其长度)保持另一端随着触摸移动而固定。

以下是我到目前为止所做的..

#import <GameKit/GameKit.h>

// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"

// HelloWorldLayer
@interface HelloWorldLayer : CCLayer <GKAchievementViewControllerDelegate, GKLeaderboardViewControllerDelegate>
{
    CGPoint lastTouchPoint;
    CCSprite *line;
    CCSprite *selectedSprite;
    CGFloat rotation;
    NSMutableArray *pointLoader;
    NSMutableArray *startPointLoader;

    BOOL moved;
    BOOL doubleTap;
    BOOL touchedTop;
    BOOL touchedBottom;
}

// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;

@end

实现文件如下:

#import "HelloWorldLayer.h"
#import "CCTouchDispatcher.h"
// Needed to obtain the Navigation Controller
#import "AppDelegate.h"

#pragma mark - HelloWorldLayer

// HelloWorldLayer implementation
@implementation HelloWorldLayer

// Helper class method that creates a Scene with the HelloWorldLayer as the only child.
+(CCScene *) scene
{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    HelloWorldLayer *layer = [HelloWorldLayer node];

    // add layer as a child to scene
    [scene addChild: layer];

    // return the scene
    return scene;
}
-(id) init
{
    // always call "super" init
    // Apple recommends to re-assign "self" with the "super's" return value
    if( (self=[super init]) ) {
        // create and initialize our seeker sprite, and add it to this layer

        lastTouchPoint = ccp(-1.0f,-1.0f);
        pointLoader = [[NSMutableArray alloc]init];
        startPointLoader = [[NSMutableArray alloc]init];

        self.isTouchEnabled = YES;
        [[CCDirector sharedDirector] setDisplayStats:NO];
    }

    return self;
}
-(void) registerWithTouchDispatcher{
    [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];

}

-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{

    line = [CCSprite spriteWithFile:@"list.png"];

    if( touch ) {
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];

        if ([pointLoader count] != 0) {
            [self selectSpriteOnTouch:location];
        }
        //
        if( CGPointEqualToPoint(lastTouchPoint, ccp(-1.0f,-1.0f) ) ){
            lastTouchPoint = ccp(location.x, location.y);
            [startPointLoader addObject:NSStringFromCGPoint(lastTouchPoint)];



        }   

    }


    return YES;
}


-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{


    if (selectedSprite) {
        CGRect firstRect = CGRectMake(selectedSprite.boundingBox.origin.x, selectedSprite.boundingBox.origin.y, selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);
        CGRect secondRect = CGRectMake(selectedSprite.boundingBox.origin.x+(2*selectedSprite.boundingBox.size.width/3), selectedSprite.boundingBox.origin.y, selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);

        CGPoint touchLocation = [touch locationInView:[touch view]];
        touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
        touchLocation = [self convertTouchToNodeSpace:touch];

        CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
        oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
        oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];

        if (CGRectContainsPoint(firstRect, touchLocation)) {
            NSLog(@"Touched top");
//Code to rotate when clicking on top region of line

            touchedTop = YES;

            lastTouchPoint = ccp(-1.0f,-1.0f);


        }
        else if (CGRectContainsPoint(secondRect, touchLocation)){
            NSLog(@"Touched bottom");
            touchedBottom = YES; 
     //Code to rotate when clicking on bottom region of line

            lastTouchPoint = ccp(-1.0f,-1.0f);

        }
        else{
        CGPoint translation = ccpSub(touchLocation, oldTouchLocation);
        [self Translation:translation];
        lastTouchPoint = ccp(-1.0f,-1.0f);
        }
    }
    else{
        moved = YES;
    }

}


-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{



    //If there was a touch move..

    if (moved==YES) {
        line = [CCSprite spriteWithFile:@"list.png"];
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        CGPoint endPoint = ccp(location.x, location.y);
        CGPoint diff = ccpSub(lastTouchPoint, endPoint);
        float rads = atan2f( diff.y, diff.x);
        float degs = -CC_RADIANS_TO_DEGREES(rads);
        float dist = ccpDistance(lastTouchPoint, endPoint);
        [line setAnchorPoint:ccp(0.0f, 0.5f)];
        [line setPosition:endPoint];
        [line setScaleX:dist/line.boundingBox.size.width];
        [line setRotation: degs];
        [pointLoader addObject:line];
        [self addChild:line z:0];
        moved = NO;
        lastTouchPoint = ccp(-1.0f,-1.0f);
        CCLOG(@" line location is (%f,%f)",line.position.x, line.position.y);
        CCLOG(@"lastTouchPoint is now(%f,%f), location is (%f,%f)", lastTouchPoint.x, lastTouchPoint.y, location.x, location.y);
    }

    else if (touchedTop ==YES) {
        [selectedSprite.parent removeChild:selectedSprite cleanup:YES];
        line = [CCSprite spriteWithFile:@"list.png"];
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        CGPoint endPoint = ccp(location.x, location.y);
        CGPoint diff = ccpSub(selectedSprite.position, endPoint);
        float rads = atan2f( diff.y, diff.x);
        float degs = -CC_RADIANS_TO_DEGREES(rads);
        float dist = ccpDistance(selectedSprite.position, endPoint);
        [line setAnchorPoint:ccp(0.0f, 0.5f)];
        [line setPosition:endPoint];
        [line setScaleX:dist/line.boundingBox.size.width];
        [line setRotation: degs];
        [pointLoader addObject:line];
        [self addChild:line z:0];
        touchedTop = NO;
        lastTouchPoint = ccp(-1.0f,-1.0f);

    }
    else if (touchedBottom ==YES) {
        [selectedSprite.parent removeChild:selectedSprite cleanup:YES];
        line = [CCSprite spriteWithFile:@"list.png"];
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        CGPoint endPoint = ccp(location.x, location.y);
        CGPoint diff = ccpSub(selectedSprite.position, endPoint);
        float rads = atan2f( diff.y, diff.x);
        float degs = -CC_RADIANS_TO_DEGREES(rads);
        float dist = ccpDistance(selectedSprite.position, endPoint);
        [line setAnchorPoint:ccp(0.0f, 0.5f)];
        [line setPosition:endPoint];
        [line setScaleX:dist/line.boundingBox.size.width];
        [line setRotation: degs];
        [pointLoader addObject:line];
        [self addChild:line z:0];
        touchedBottom = NO;
        lastTouchPoint = ccp(-1.0f,-1.0f);

    }

    //

    else if ([touch tapCount]==3){          //code to clear all screen
        [self removeAllChildrenWithCleanup:YES];
        rotatorSprite = nil;
        selectedSprite = nil;
        [pointLoader removeAllObjects];
        NSLog(@"Screen Cleared");
        lastTouchPoint = ccp(-1.0f,-1.0f);

    }

}
- (void)selectSpriteOnTouch:(CGPoint)touchLocation {
    //  for (CCSprite *sprite in pointLoader) {
    //      if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
    //          NSLog(@"sprite was touched");
    ////            [self removeChild:sprite cleanup:YES];
    //          [sprite.parent removeChild:sprite cleanup:YES];
    ////            break;  // putting break does not solve the multiple deletion problem... it only disables the deletion
    //          NSLog(@"sprite moving");
    //
    //
    //      }
    //  }
    //  lastTouchPoint = ccp(-1.0f,-1.0f);

    if (doubleTap == YES) {
        id rotate = [CCRotateBy actionWithDuration:10 angle:360];
        for(CCSprite *sprite in pointLoader){
            if(CGRectContainsPoint(sprite.boundingBox, touchLocation)){
                rotatorSprite = sprite;
                [rotatorSprite setAnchorPoint:ccp(0.0f, 0.5f)];
                [rotatorSprite runAction:rotate];
                break;
            }
        }
        doubleTap = NO;
        lastTouchPoint = ccp(-1.0f,-1.0f);

    }

    else{
        CCSprite * newSprite = nil;
        for (CCSprite *sprite in pointLoader) {
//          CGRect rect = CGRectMake(sprite.position.x-(sprite.contentSize.width/2), sprite.position.y-(sprite.contentSize.height/2),
//                                   sprite.contentSize.width, sprite.contentSize.height);
//          if (CGRectContainsPoint(rect, touchLocation)) {
            if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
                newSprite = sprite;
                NSLog(@"Sprite was Touched");

                CCLOG(@" newSprite location is (%f,%f)",newSprite.position.x, newSprite.position.y);
                break;
            }
        }
        if (newSprite != selectedSprite) {
            selectedSprite = newSprite;
        }
    }
}

- (void)Translation:(CGPoint)translation {
    if (selectedSprite) {
        CGPoint newPos = ccpAdd(selectedSprite.position, translation);
        selectedSprite.position = newPos;

        CCLOG(@" selectedSprite location is (%f,%f)",selectedSprite.position.x, selectedSprite.position.y);
    }
    lastTouchPoint = ccp(-1.0f,-1.0f);

}




// on "dealloc" you need to release all your retained objects
- (void) dealloc
{
    // in case you have something to dealloc, do it in this method
    // in this particular example nothing needs to be released.
    // cocos2d will automatically release all the children (Label)

    // don't forget to call "super dealloc"
    [super dealloc];
}

#pragma mark GameKit delegate

-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
    [[app navController] dismissModalViewControllerAnimated:YES];
}

-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
    AppController *app = (AppController*) [[UIApplication sharedApplication] delegate];
    [[app navController] dismissModalViewControllerAnimated:YES];
}
@end

旋转正在发生,但不是按需要发生的,并且在平行于 x 和 y 轴时也会停止。

请帮我解决旋转问题....

谢谢

4

1 回答 1

0

我现在可以旋转它,虽然不完全按照需要旋转,因为旋转后有一个精灵复制..这就是我所做的..

#pragma mark Touch Processing

-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{

    line = [CCSprite spriteWithFile:@"2X2Pix.png"];

    if( touch ) {
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        location = [self convertToNodeSpace:location];
        if ([pointLoader count] != 0) {
            [self selectSpriteOnTouch:location];

            CGRect firstRect = CGRectMake(selectedSprite.boundingBox.origin.x, selectedSprite.boundingBox.origin.y, selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);
            CGRect secondRect = CGRectMake(selectedSprite.boundingBox.origin.x+(2*selectedSprite.boundingBox.size.width/3), selectedSprite.boundingBox.origin.y, selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);
            CGRect middleRect = CGRectMake(selectedSprite.boundingBox.origin.x+selectedSprite.boundingBox.size.width/8, selectedSprite.boundingBox.origin.y, 2*selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);


            if (CGRectContainsPoint(middleRect, location)) {
                NSLog(@"Touched Middle");
                touchedMiddle = YES;
                touchedBottom = NO;
                touchedTop = NO;

            }
            else if (CGRectContainsPoint(firstRect, location)){
                NSLog(@"Touched Top");
                touchedTop = YES;
                touchedBottom = NO;
                touchedMiddle = NO;
                [selectedSprite removeFromParentAndCleanup:YES];

            }
            else if (CGRectContainsPoint(secondRect, location)){                    
                NSLog(@"Touched Bottom");
                touchedBottom = YES;
                touchedTop = NO;
                touchedMiddle = NO;
                [selectedSprite removeFromParentAndCleanup:YES];

            }


        }
        //
        if( CGPointEqualToPoint(lastTouchPoint, ccp(-1.0f,-1.0f) ) ){
            if (!selectedSprite) {
                lastTouchPoint = ccp(location.x, location.y);

                [startPointLoader addObject:NSStringFromCGPoint(lastTouchPoint)];
//              startPointCount++;
//              NSLog(@"start point loaded count = %d", startPointCount);
                CCLOG(@"Start Point is (%f,%f)", lastTouchPoint.x, lastTouchPoint.y);
            }
            //[line setPosition:lastTouchPoint];                        // need not set line to the first point

        }
        else {      //Enable THIS for Tap Drawing

            CCLOG(@"lastTouchPoint is now(%f,%f), location is (%f,%f)", lastTouchPoint.x, lastTouchPoint.y, location.x, location.y);    //log
            CGPoint diff = ccpSub(location, lastTouchPoint);
            float rads = atan2f( diff.y, diff.x);
            float degs = -CC_RADIANS_TO_DEGREES(rads);
            float dist = ccpDistance(lastTouchPoint, location);
            [line setAnchorPoint:ccp(0.0f, 0.5f)];
            [line setPosition:lastTouchPoint];
            [line setScaleX:dist/line.contentSize.width];
            [line setRotation: degs];

            [pointLoader addObject:line];
            lineCount++;
            NSLog(@"Tap Line loaded count = %d ", lineCount);
            [self addChild:line];                                           //adds the child to the layer

            //lastTouchPoint = ccp(location.x, location.y);                 // to make the last touch the new starting point for line

            lastTouchPoint = ccp(-1.0f,-1.0f);

        }


    }


    return YES;
}


-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{

    if (selectedSprite) {

        CGPoint touchLocation = [touch locationInView:[touch view]];
        touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
        touchLocation = [self convertToNodeSpace:touchLocation];

        CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
        oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
        oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];

        if (touchedMiddle == YES) {

            [selectedSprite removeChild:line cleanup:YES];
            [self removeChild:line cleanup:YES];
            CGPoint translation = ccpSub(touchLocation, oldTouchLocation);
            [self spriteTranslation:translation];
            NSUInteger index = [pointLoader indexOfObject:selectedSprite];
            CGPoint startPoint = CGPointFromString([startPointLoader objectAtIndex:index]);

            startPoint = ccpAdd(startPoint, translation);
            [startPointLoader replaceObjectAtIndex:index withObject:NSStringFromCGPoint(startPoint)];

            lastTouchPoint = ccp(-1.0f, -1.0f);
        }
        else{
            if (touchedTop) {
                NSLog(@"Touched Top");
                rotated = YES;
                [selectedSprite removeFromParentAndCleanup:YES];    //Disable only if needed to see the original sprite before the rotation

                NSUInteger index = [pointLoader indexOfObject:selectedSprite];
                CGPoint startPoint = CGPointFromString([startPointLoader objectAtIndex:index]);

                [self removeChild:line cleanup:YES];                // to remove wheeling during the rotation
                [self lineRotater:touchLocation from:startPoint];
                lastTouchPoint = ccp(-1.0f,-1.0f);
                [self removeChild:line cleanup:YES];            //Enabling this removes the line updation on move
//              [selectedSprite removeAllChildrenWithCleanup:YES];

            }
            else if (touchedBottom){
                NSLog(@"Touched Bottom");
                rotated = YES;
                [selectedSprite removeFromParentAndCleanup:YES];    //Disable only if needed to see the original sprite before the rotation

                NSUInteger index = [pointLoader indexOfObject:selectedSprite];
                CGPoint startPoint = CGPointFromString([startPointLoader objectAtIndex:index]);

                [self removeChild:line cleanup:YES];                // to remove wheeling during the rotation
                [self lineRotater:touchLocation from:startPoint];
                lastTouchPoint = ccp(-1.0f,-1.0f);
                [self removeChild:line cleanup:YES];            //Enabling this removes the line updation on move
//              [selectedSprite removeAllChildrenWithCleanup:YES];
            }
        }



    }
    else {
        if (!CGPointEqualToPoint(lastTouchPoint, ccp(-1.0f,-1.0f))) {

//      NSLog(@"Line Plotting Started");

        moved = YES;
        CGPoint touchLocation = [touch locationInView:[touch view]];
        touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
        touchLocation = [self convertToNodeSpace:touchLocation];
        [self removeChild:line cleanup:YES];
        [self linePlotter:touchLocation from:lastTouchPoint];

        }
    }

}


-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{


    //If there was a touch move..

    if (moved==YES) {

            [self removeChild:line cleanup:YES];
            line = [CCSprite spriteWithFile:@"2X2Pix.png"];
            CGPoint location = [touch locationInView: [touch view]];
            location = [[CCDirector sharedDirector] convertToGL:location];
            CGPoint endPoint = ccp(location.x, location.y);
            CGPoint diff = ccpSub(lastTouchPoint, endPoint);
            float rads = atan2f( diff.y, diff.x);
            float degs = -CC_RADIANS_TO_DEGREES(rads);
            float dist = ccpDistance(lastTouchPoint, endPoint);
            [line setAnchorPoint:ccp(0.0f, 0.5f)];
            [line setPosition:endPoint];
            [line setScaleX:dist/line.contentSize.width];
            [line setRotation: degs];
            [pointLoader addObject:line];
//          lineCount++;
//          NSLog(@"Moved Line loaded count = %d ", lineCount);
            [self addChild:line];
            moved = NO;
            selectedSprite = nil;
            lastTouchPoint = ccp(-1.0f,-1.0f);

            NSLog(@"Line touch ended");

            CCLOG(@"lastTouchPoint is now(%f,%f), End Point location is (%f,%f)", lastTouchPoint.x, lastTouchPoint.y, location.x, location.y);
    }

    else if (touchedTop ==YES) {

        NSLog(@"Touched top Ended");

        [selectedSprite.parent removeChild:selectedSprite cleanup:YES];
        NSUInteger index = [pointLoader indexOfObject:selectedSprite];
        CGPoint startPoint = CGPointFromString([startPointLoader objectAtIndex:index]);
        line = [CCSprite spriteWithFile:@"2X2Pix.png"];
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        CGPoint endPoint = ccp(location.x, location.y);
        CGPoint diff = ccpSub(startPoint, endPoint);
        float rads = atan2f( diff.y, diff.x);
        float degs = -CC_RADIANS_TO_DEGREES(rads);
        float dist = ccpDistance(startPoint, endPoint);
        [line setAnchorPoint:ccp(0.0f, 0.5f)];
        [line setPosition:endPoint];
        [line setScaleX:dist/line.contentSize.width];
        [line setRotation: degs];
//      NSLog(@"Moved Line loaded count = %d ", lineCount);
        [pointLoader replaceObjectAtIndex:index withObject:line];
        [self addChild:line];
        touchedTop = NO;
        selectedSprite = nil;
        lastTouchPoint = ccp(-1.0f,-1.0f);
    }
    else if (touchedBottom ==YES) {

        NSLog(@"Touched bottom Ended");

        [selectedSprite.parent removeChild:selectedSprite cleanup:YES];
        NSUInteger index = [pointLoader indexOfObject:selectedSprite];
        CGPoint startPoint = CGPointFromString([startPointLoader objectAtIndex:index]);         // Here.. Crashing
        line = [CCSprite spriteWithFile:@"2X2Pix.png"];
        CGPoint location = [touch locationInView: [touch view]];
        location = [[CCDirector sharedDirector] convertToGL:location];
        CGPoint endPoint = ccp(location.x, location.y);
        CGPoint diff = ccpSub(startPoint, endPoint);
        float rads = atan2f( diff.y, diff.x);
        float degs = -CC_RADIANS_TO_DEGREES(rads);
        float dist = ccpDistance(startPoint, endPoint);
        [line setAnchorPoint:ccp(0.0f, 0.5f)];
        [line setPosition:endPoint];
        [line setScaleX:dist/line.contentSize.width];
        [line setRotation: degs];
//      NSLog(@"Moved Line loaded count = %d ", lineCount);
        [pointLoader replaceObjectAtIndex:index withObject:line];
        [self addChild:line];
        touchedBottom = NO;
        selectedSprite = nil;
        lastTouchPoint = ccp(-1.0f,-1.0f);

    }

    //
    //
    //
    //  if ([touch tapCount] == 2) {                //code for touched sprite deletion
    //      doubleTap = YES;
    //      CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
    //      [self selectSpriteOnTouch:touchLocation];
    //      NSLog(@"Touch was Detected");
    //
    //  }
    //
    //
    //
    else if ([touch tapCount]==3){          //code to clear all screen
        [self removeAllChildrenWithCleanup:YES];
        selectedSprite = nil;
        [pointLoader removeAllObjects];
        [startPointLoader removeAllObjects];
        NSLog(@"Screen Cleared");
        lastTouchPoint = ccp(-1.0f,-1.0f);

    }


}

感谢所有花时间回答我的问题的人。

问候

于 2013-07-03T11:59:59.340 回答