Ryoku
Ryoku

Reputation: 101

Position on Node After Rotation

Okay so I have a node that's node.size is a (5,5) rectangle. Its position is (100,100), and its anchor point is the default (0.5, 0.5).

I tried to find the point at the farthest right, but still centre Y. Naturally this returned the point (102.5, 100). This is perfect. I found the point by simply using CGPointMake(node.position + node.size.width/2, node.position);

This works great, but the thing is I want to rotate the node while still knowing what that point is. I was wondering if their was some kind of math I could perform using the nodes zRotation in order to find the new point (the same point on the nodes frame) after the rotation.

To make it clear I want to know where the point that is originally 102.5, 100, is after the node rotates.

Thank you all very much in advance for all of your answers

Upvotes: 0

Views: 344

Answers (2)

0x141E
0x141E

Reputation: 12773

Let r be the distance from the anchor point of the sprite to the point of interest. In your case,

r = sqrt(dx*dx+dy*dy) = 2.5;

where dx = 2.5 and dy = 0.

Also, let theta be the rotation angle, which is initially zero. We now have a point in polar coordinates, (r, theta), that represents the point (2.5, 0). We can now rotate the point about the sprite's anchor point by changing theta. After rotating the sprite, we convert (r, theta) to cartesian coordinates by

x = r * cos(theta);
y = r * sin(theta);

and add the sprite's position to convert the point to scene coordinates.

x = x + sprite.position.x;
y = y + sprite.position.y;

EDIT: I think this is what you are trying to implement.

@interface MyScene()

@property SKSpriteNode *object1;
@property SKSpriteNode *object2;

@end

@implementation MyScene

-(id)initWithSize:(CGSize)size
{
    if(self = [super initWithSize:size]) {
        _object1 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(10,5)];
        _object1.position = CGPointMake(100, 100);
        [self addChild:_object1];
        SKAction *wait = [SKAction waitForDuration: 2.5f];
        SKAction *rotate = [SKAction rotateByAngle:3*M_PI/4 duration:2.0f];
        SKAction *addObject = [SKAction runBlock:^{
            _object2 = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10,5)];

            _object2.zRotation = _object1.zRotation;

            CGFloat dx = _object1.size.width / 2;
            CGFloat dy = 0;
            CGFloat r = sqrtf(dx*dx + dy*dy);
            CGFloat x = r*cosf(_object1.zRotation);
            CGFloat y = r*sinf(_object1.zRotation);

            _object2.position = CGPointMake(_object1.position.x + 2*x, _object1.position.y + 2*y);

            [self addChild:_object2];
        }];
        SKAction *seq = [SKAction sequence:@[wait, rotate, addObject]];
        [_object1 runAction:seq];
    }
    return self;
}

Upvotes: 2

Ryoku
Ryoku

Reputation: 101

Okay, I had to post code so I had to make this an answer.

So I tried your method 0x141E, and it worked perfectly. The only problem I am having is that whenever the angle is not a multiple of 0.5PI it seems to calculate improperly. Maybe its just the way that I coded it though. The goal of my code was to place one object right beside another by measuring the distance between a left most, middle point of one object with the other objects right most, middle point. This way they would be touching left side with right side... Side-by-Side basically. I placed one object first and added the second using your given algorithm, but the result as I stated above got a little funky in between angles divisible by 0.5 PI. Here's what I've done, it should work if you import the code straight into XCode if you want to see what I am talking about (I'm sorry but I don't have enough rep to attach images or I would give a screenshot):

//This is the MyScene implementation file
@interface MyScene()
{
    SKSpriteNode *_object1;
    SKSpriteNode *_object2;
}
@end

@implementation MyScene
-(id)initWithSize:(CGSize)size
{
    if(self = [super initWithSize:size]
    {
        object1 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(10,5)];
        [self addChild:object1];
        //The wait is just to make it feel smoother and not so sudden when starting up the simulator
        SKAction *wait = [SKAction waitForDuration: 2.5f];
        SKAction *rotate = [SKAction rotateByAngle:0.25*M_PI duration:2.0f];
        SKAction *addObject = [SKAction runBlock:^{
            _object2 = [spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10,5)];

            //I set the rotation of the second object to the rotation of the first so they will always be touching side-by-side
            _object2.zRotation = _object1.zRotation;

            //I used the full width and heigth rather than half to save time. The two ojects are of equal width and height so instead of finding both distances and adding them together I just doubled the distance
            CGFloat r = sqrtf(_object2.frame.size.width*_object2.frame.size.width+_object2.frame.size.height*_object2.frame.size.height);
            CGFloat x = r*cosf(_object2.zRotation);
            CGFloat y = r*sinf(_object2.zRotation);

            object2.position = CGPointMake(_object2.position.x + x, _object2.position + y);

            [self addChild:_object2];
        }
        SKAction *seq = [SKAction sequence:@[wait, rotate, addObject]];
        [self runAction:seq];
    }
}
@end

Thank you again for all of your help thus far, and thank you even more for all of your potential future help.

Upvotes: 0

Related Questions