简体   繁体   中英

Converting Points to Node in Sprite-Kit

I've been working on this problem for a few days now and I just can't seem to figure it out. I've done a ton of searching for an answer, and I've seen hints that maybe the problem is with Sprite-Kit itself, so I am debating moving to Cocos2D and starting over. But, I hope that someone here can help me.

I have a basic camera node called _world that I am using to pan around the world and to zoom. The panning and zooming works fine, but I've been trying to get the world node to move to the center of where the pinch occurs. It sort of works, but converting the point to a position in the world node seems to be the problem. Here is my code:

I use this code to convert a scene point to a world point elsewhere in the code and it works fine:

CGPoint positionInScene = [touch locationInNode:self];
CGPoint locationInWorld = [self.scene convertPoint:positionInScene toNode:_world];

But later I try to do this using the middle point of the two points found in the pinch, and it doesn't seem to convert properly:

originalLocationOne = [sender locationOfTouch:0 inView:self.view];
originalLocationTwo = [sender locationOfTouch:1 inView:self.view];
//I do this because SpriteKit doesn't have a ccpAdd method
originalAddedMidPoint = CGPointMake(originalLocationOne.x + originalLocationTwo.x, originalLocationOne.y + originalLocationTwo.y);
//same thing here but for ccpMidPoint
originalMidPoint = CGPointMake(originalAddedMidPoint.x * 0.5f, originalAddedMidPoint.y * 0.5f);
_newWorldPos = [self convertPoint:originalMidPoint toNode:_world];

I would really appreciate it if someone can point me in the right direction! Thank you so much!

EDIT: I've been working on this problem some more, and certainly something weird is happening but I still can't tell what. Here is my complete touchesbegan method:

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    _myTouches = [[NSMutableArray alloc]init];
    for (UITouch *touch in touches) {
        [_myTouches addObject:touch];
    }
    if (_myTouches.count > 1) {
        UITouch *touch1 = [_myTouches objectAtIndex:0];
        UITouch *touch2 = [_myTouches objectAtIndex:1];
        CGPoint touch1Location = [touch1 locationInView:self.view];
        CGPoint touch2Location = [touch2 locationInView:self.view];
        NSLog(@"tpoint1 = %@, tpoint2 = %@", NSStringFromCGPoint(touch1Location), NSStringFromCGPoint(touch2Location));
        CGPoint touchAddedPoint = CGPointMake(touch1Location.x + touch2Location.x, touch1Location.y + touch2Location.y);
        CGPoint touchMidPoint = CGPointMake(touchAddedPoint.x * 0.5f, touchAddedPoint.y * 0.5f);
        NSLog(@"touch mid point = %@", NSStringFromCGPoint(touchMidPoint));
        CGPoint newWorldPoint = [self convertTouchPointToWorld:touchMidPoint];

        //camera needs to be offset to work properly
        CGPoint alteredWorldPoint = CGPointMake(-newWorldPoint.x * 0.75f, -newWorldPoint.y * 0.75f);

       _firstTouch = alteredWorldPoint;
       _tempWorldLocation = _firstTouch;
       _worldMovedForUpdate = YES;
    }
}

Here is the method that I extracted to convert the position to the world node:

-(CGPoint) convertTouchPointToWorld:(CGPoint)touchLocation {
    CGPoint firstLocationInWorld = [self.scene convertPoint:touchLocation toNode:_world];
    NSLog(@"inside converting method %@", NSStringFromCGPoint(firstLocationInWorld));
    return firstLocationInWorld;
}

Here is the entire method that places a building in the game map based on its position in the world map:

-(void)selectNodeForTouch:(CGPoint)touchLocation {
    SKSpriteNode *touchedNode = (SKSpriteNode *)[self nodeAtPoint:touchLocation];
    //NSLog(@"node name is = %@", touchedNode.name);

    _selectedNode = touchedNode;
    if ([[touchedNode name] isEqualToString:@"hudswitch1"]) {
        if([self.theGame getMovesLeft] == 0){
            _hudNeedsUpdate = YES;
            _turnNeedsUpdating = YES;
        }
    }
    if ([self.theGame getMovesLeft] > 0) {
        [self handleButtonsForTouch:touchedNode];
    }
    //this inserts the tile at the location in world node
    NSLog(@"touchLocation.x = %f, touchlocation.y = %f", touchLocation.x, touchLocation.y);
    if ([[touchedNode name] isEqualToString:@"tile"] && _selectedBuildingType != 0) {

        //CGPoint locationInWorld = [self.scene convertPoint:touchLocation toNode:_world];
        CGPoint locationInWorld = [self convertTouchPointToWorld:touchLocation];
        CGPoint gameLocation = [self convertWorldPointToGamePoint:locationInWorld];

        NSLog(@"locationWorld.x = %f, locationWorld.y = %f", locationInWorld.x, locationInWorld.y);

        if(![self.theGame isBuildingThere:gameLocation] && [self.theGame isValidLocation:gameLocation]) {
            [self updateActiveTilePos:locationInWorld];
        }
   }
}

Inserting a tile into the map works fine. It gets the world location and then divides it by the tile size to figure out the position to place the tile in the world map. It is always inserting a tile in the proper place.

However when I use the middle point of the two touches in a pinch and convert it to a world point, it returns a value but the value is off by a large amount, and different amounts depending on the distances from the center...

Maybe I just need to figure out how to offset the camera properly? Thanks again for any help with this problem, it is driving me crazy!

I had the same problem.
It is counterintuitive but point conversion is not smart.
It does not convert from one node to another node.
It can convert to scene coordinates and to node coordinates from scene coordinates.
It does not work from one node to another node. What you need to do is convert point from node and then convert point to node. After two these calls coordinates will be in the node you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM