Scale SKShapeNode from center? - sprite-kit

I have a SKShapeNode, and a label under one generic SKNode. If I try to scale that node, its position changes for no reason!. If I try to scale only the nodes it contains under it, it scales properly but not from the center, so it grows out to the up and right.
What am I doing wrong?
First before scale
After scale
Notice its position moves up. Can't figure out why, does it even if I do it as an action or not. Also, the position is not changing based on log, but it appears the frame got bigger (though that is expected)
Steps to recreate issue:
set height and width
#h = 50
#w = 256
create rect with height and width
CGRectMake(0, 0, #w, #h)
get path for rect
UIBezierPath.bezierPathWithRect(rect).CGPath
create skshape node with path, set position
antialiased: false,
lineWidth: 1.0,
strokeColor: SKColor.blackColor,
fillColor: SKColor.whiteColor
Create sklabel, vertical center alignment, set position
create generic SKNode, no properties, add skshapenode and sklabel to it as children
Scale the generic SKNode.

I had a similar problem: I created an SKShapeNode.ellipseInRect which look perfectly fine when I didn't need to scale it. Yet as soon as I tried to scale it down to fit the text it was behind, it would randomly shrink towards the bottom left of the screen!
I did a little debugging, and the number that surprised me was that the position was set to (0, 0) even though the ellipse was in the top left corner of the screen! I then realized that by initializing with a rect the "anchor point" (even though SKShapeNodes don't technically have them) was at (0, 0) too. This behavior would explain my shrinking towards that point and your growing away from that point.
What solved this problem for me was instead of putting my position in the rect, set the position afterwards. Then it scaled around my node's center-point and not the screen origin. Hope that helps!

Try this
SKLabelNode *labNode = [SKLabelNode labelNodeWithFontNamed:#"Arial"];
labNode.fontSize = 12.0f;
labNode.fontColor = [SKColor blackColor];
labNode.text = #"SMASH";
SKSpriteNode *topWithText = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(100, 30)];
topWithText.position = CGPointMake(100, 110);
[topWithText addChild:labNode];
SKSpriteNode *bottom = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(100, 10)];
bottom.position = CGPointMake(100, 100);
[self addChild:topWithText];
[self addChild:bottom];
[topWithText runAction:[SKAction sequence:#[
[SKAction waitForDuration:3.0],
[SKAction scaleBy:3.0 duration:3]
]]];

With the SKShapeNode, this is impossible.
I solved it by adding a move Action to center the node manually.
You need to apply this to the y and x coordinates

Related

bodyWithEdgeLoopFromRect doesn't match SKSpriteNode

I have in my scene playing board (for Tetris) - smaller then scene (750x510px). I need to frame it with bodyWithEdgeLoopFromRect. Here is a code :
SKSpriteNode *herniPlocha = [[SKSpriteNode alloc]initWithImageNamed:#"Plocha"];
herniPlocha.anchorPoint = CGPointMake(0, 0);
herniPlocha.position = CGPointMake(10, self.size.height-450);
herniPlocha.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:herniPlocha.frame];
[self addChild:herniPlocha];
but when I try to put block inside this board, the physicsBody doesn't match my board, it is about 40px moved to the right and up. Can you help me solve this problem, please?
Don't change the anchorPoint. The anchorPoint shifts the texture relative to the node's position and does nothing else. It certainly does not change where the physics shape is relative to the node.

Cocos2d, Weird position offset when using CCParallaxNode

I'm using cocos2d for iOS. Not sure if I'm doing something wrong here or if CCParallaxNode does something strange that I just don't understand.
I'm trying to create a few layers of parallax scrolling in the background of my game, at the moment I just have one layer added to the parallax node till I can figure out what's going wrong. When the game loads the layer it's always offset down and left by about 30% of the image size. I've uploaded an image demonstrating the difference in position here http://oi42.tinypic.com/29dz1av.jpg.
Here is my code:
background = [CCParallaxNode node];
background.anchorPoint = ccp(0,0);
background.position = ccp(0,0);
[self addChild: background];
background_image = [CCSprite spriteWithFile: #"layer01.png"
rect: CGRectMake(0, 0, 100, 100)];
background_image.anchorPoint = ccp(0,0);
background_image.position = ccp(0,0);
[background addChild: background_image z:0 parallaxRatio: ccp(0,0) positionOffset:ccp(0,0)];
The cocos2d icon is attached to the same layer as the parallax node and it's position and anchor point are set to 0,0 so the bottom left of the icon should be in the same location as the bottom left of the blue background image.
I have tested this using a basic sprite in place of the parallax node and everything lines up as it should so it's not the image itself.
Any help with this would be appreciated.
First, I don't suggest you to set parallax node & its children's anchor point & position directly because it will cause some unexpected results. You should add the parallax node to a layer as its child, and set the layer's anchor point & position to place your parallax.
Second, CCParallaxNode also provides a positionOffset that you can place your picture in parallax at first. This can help if you want to align several layers of pictures' view center.
So I think you should do something like this(Since I'm using cocos2d-x, I'm not sure its right with obj-C):
layer = [[CCLayer alloc]init];
background = [CCParallaxNode node];
[layer addChild: background];
[self addChild: layer];
Then you just have to add the picture sprite in background, and set layer's position & anchor point.
Hope it can help.
Make sure the background image size is 480x320.
Why did you write CGRectMake(0, 0, 100, 100) ? Why 100 and 100 ? You're limiting your 'CGRect', that's probably wrong..

CGAffineTransformMakeTranslation translate to a point rather then by a value.

My question is simple.
Let us say I use this method
CGAffineTransformMakeTranslation(5.0f, 0.0f);
which translates the image view 5 pixels to the right. But is there a similar method that does the exact same thing except takes the destination point as an argument rather then the values you want to move the image view by?
For example, if I wanted to move an image view to 100.0f, 0.0f what would I use?
You can use the following two options:
imgOne.center = CGPointMake(50, 50);
or
imgOne.frame = CGRectMake(50, 50, imgOne.frame.size.width, imgOne.frame.size.height);
If it's the center point you want to move to this coordinate, use:
imageView.center = CGPointMake(100.0f, 0.0f);
If it's one of the corner points, subtract/add half the view's frame's width/height to the coordinates. If you need this frequently, it's a good idea to write a small UIView category that allows you to position a view's corner on a particular coordinate.

Need help in understanding the positions of sprite in cocos2d?

I am new in cocos2d i have created a simple example
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *player = [CCSprite spriteWithFile:#"Player.jpg"
rect:CGRectMake(0, 0, 27, 40)];
player.position = ccp(player.contentSize.width/2, winSize.height/2);
[self addChild:player];
but I am not clear about the position of sprite how to manager it
Your code will create a sprite and position it within the parent node so that its lower-left corner is at ccp(player.contentSize.width/2, winSize.height/2).
If you wonder why your sprite is not centered respect to the coordinate you provide, the answer is that it is the lower-left corner which is positioned, not the sprite center.
You can tweak this behavior by defining the anchorPoint property of the sprite, like this:
player.anchorPoint = ccp(0.5,0.5);
player.position = ...
EDIT:
You can think of the anchor point as the "center of gravity" of the sprite: the texture is centered around it, any scaling or other kind of transformation will be relative to it.
If the anchor point is set at (0,0), then it coincides with the lower-left corner (default); if it is (0.5, 0.5) then it is exactly in the middle of the sprite (50% width, 50% height). Its coordinates are not point, but the relative displacement within the sprite; the coordinates can go from 0.0 to 1.0.

cocos2d coordinates system

CCLabelTTF *label = [CCLabelTTF labelWithString:#"Score : #" fontName:#"Arial" fontSize:14];
// ask director the the window size
CGSize size = [[CCDirector sharedDirector] winSize];
// position the label on the center of the screen
label.position = ccp( size.width + 0, size.height + 0 );
// add the label as a child to this Layer
[self addChild: label];
label.position = ccp( size.width + 0, size.height + 0 );
how would i get that label in the bottom left corner. I do not understand the coordinates system very well. From what I understand Y is bottom. X is far left. so how come when I use that code, the position of the label is top right. My application is portrait.
Also would it better to have the label as a sprite, or just keep it like that. ( its to hold a score )
In codos2d, the point (0,0) is the bottom left corner of the screen. Think of it as quadrant 1 on a x,y plane where x increases as you go right, and y increases as you go up.
So to get the label in the bottom left just do label.position = ccp(0, 0); but this might be the default so you might not have to do anything.
consider first answer for your first question, and for second question answer is, if label is for score, then it's better you use label, rather than sprites(because you'll need 1000s of them and it'll be heavy as well as complicated)
CCLabelTTF is expensive if updated rapidly (many times per second), but is fine if you're not updating it. One preferred way is to use CCLabelBMFont (I think that's the class...). You'll need the .fnt file and .png to go with it, but you can make those with a tool like Glyph Designer from 71squared.