cocos2d coordinates system - iphone

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.

Related

Scale SKShapeNode from center?

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

Rotating UIImageView Moves the Image Off Screen

I have a simple rotation gesture implemented in my code, but the problem is when I rotate the image it goes off the screen/out of the view always to the right.
The image view that is being rotated center X gets off or increases (hence it going right off the screen out of the view).
I would like it to rotate around the current center, but it's changing for some reason. Any ideas what is causing this?
Code Below:
- (void)viewDidLoad
{
[super viewDidLoad];
CALayer *l = [self.viewCase layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30.0];
self.imgUserPhoto.userInteractionEnabled = YES;
[self.imgUserPhoto setClipsToBounds:NO];
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationDetected:)];
[self.view addGestureRecognizer:rotationRecognizer];
rotationRecognizer.delegate = self;
}
- (void)rotationDetected:(UIRotationGestureRecognizer *)rotationRecognizer
{
CGFloat angle = rotationRecognizer.rotation;
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
rotationRecognizer.rotation = 0.0;
}
You want to rotate the image around it's center, but that's not what it is actually happening. Rotation transforms take place around the origin. So what you have to do is to apply a translate transform first to map the origin to the center of the image, and then apply the rotation transform, like so:
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, self.imageView.bounds.size.width/2, self.imageView.bounds.size.height/2);
Please note that after rotating you'll probably have to undo the translate transform in order to correctly draw the image.
Hope this helps
Edit:
To quickly answer your question, what you have to do to undo the Translate Transform is to subtract the same difference you add to it in the first place, for example:
// The next line will add a translate transform
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 10, 10);
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, radians);
// The next line will undo the translate transform
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, -10, -10);
However, after creating this quick project I realized that when you apply a rotation transform using UIKit (like the way you're apparently doing it) the rotation actually takes place around the center. It is only when using CoreGraphics that the rotation happens around the origin. So now I'm not sure why your image goes off the screen. Anyway, take a look at the project and see if any code there helps you.
Let me know if you have any more questions.
The 'Firefox' image is drawn using UIKit. The blue rect is drawn using CoreGraphics
You aren't rotating the image around its centre. You'll need correct this manually by translating it back to the correct position

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.

Main view rotates from center point to 360 degree but inner views are also being rotated

I am rotating main view with 360 degrees, and I have subviews added inside main view, everything works correctly, but with one issue.
What I want to do is when I rotate main view, inner views should not lost their frames/position. Right now, when I rotate main view with infinte repeat count and dynamically if I add subview inside main view, it goes into proper position, but it does not retain its frame.
For example, I am implementing orbit, and for that, I have used entire transparent view as orbit and orbit is rotated from center point to 360 degree infinite times, and User can add many planets as he wants onto orbit, so when planets added on orbit, planets do not retain its frame. Can you suggest any idea?
Thanks in advance.
Well it sounds like you need to add a rotating animation for every subview that you add in your main view. If the main view rotates clockwise your subviews will need to rotate around their center in a counter-clockwise direction.
I guess you're trying to keep the subviews' orientations while rotating.
If I were you, I'd use CAAnimation instead of using a view to rotate.
You may add the animation to every subview, try this:
CAKeyframeAnimation* animation;
animation = [CAKeyframeAnimation animation];
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL,imgview.layer.position.x,imgview.layer.position.y);
int p = [self getblank:tag];
float f = 2.0*M_PI - 2.0*M_PI *p/PHOTONUM;
float h = f + 2.0*M_PI *num/PHOTONUM;
float centery = self.view.center.y;
float centerx = self.view.center.x;
float tmpy = centery + RADIUS*cos(h);
float tmpx = centerx - RADIUS*sin(h);
imgview.center = CGPointMake(tmpx,tmpy);
CGPathAddArc(path,nil,self.view.center.x, self.view.center.y,RADIUS,f+ M_PI/2,f+ M_PI/2 + 2.0*M_PI *num/PHOTONUM,0);
animation.path = path;
CGPathRelease(path);
animation.duration = TIME;
animation.repeatCount = 1;
animation.calculationMode = #"paced";
return animation;
I assume you have a stored variable that represents the rotation of the "world", correct? If not, you should.
Then, for each image you add, also store a variable with it that represents its rotation to the world.
For example, if your world is rotated 180°, and you added a cup (which you want to appear right-side up when the world is upside-down) the cup's "offset" to the world rotation would be -180°.
Then, if the world is at 180° and you rotate your world by adding 90°, then the cup's new rotation value would be cup_rotate_offset + world_rotation, or 180°+270°, which is the same as saying 90°, and the top of the world would be facing left and the cup's top would be facing right.
You have to independently track the offset values for each added object.

Cocos2D CCNode position in absolute screen coordinates

I've been looking around for a while, and I have not been able to find an answer to this for some reason. It seems simple enough, but maybe I just can't find the right function in the library.
I have a scene with a layer that contains a bunch of CCNodes with each one CCSprite in them.
During the application, I move around the position of the main layer, so that I "pan" around a camera in a way. (i.e. I translate the entire layer so that the viewport changes).
Now I want to determine the absolute position of a CCNode in screen coordinates. The position property return the position relative to the parent node, but I really would like this transformed to its actual position on screen.
Also, as an added bonus, it would be awesome if I could express this position as coordinate system where 0,0 maps to the upper left of the screen, and 1,1 maps to the lower right of the screen. (So I stay compatible with all devices)
Edit: Note that the solution should work for any hierarchy of CCNodes preferably.
Every CCNode, and descendants thereof, has a method named convertToWorldSpace:(CGPoint)p
This returns the coordinates relative to your scene.
When you have this coordinate, flip your Y-axis, as you want 0,0 to be in the top left.
CCNode * myNode = [[CCNode alloc] init];
myNode.position = CGPointMake(150.0f, 100.0f);
CCSprite * mySprite = [[CCSprite alloc] init]; // CCSprite is a descendant of CCNode
[myNode addChild: mySprite];
mySprite.position = CGPointMake(-50.0f, 50.0f);
// we now have a node with a sprite in in. On this sprite (well, maybe
// it you should attack the node to a scene) you can call convertToWorldSpace:
CGPoint worldCoord = [mySprite convertToWorldSpace: mySprite.position];
// to convert it to Y0 = top we should take the Y of the screen, and subtract the worldCoord Y
worldCoord = CGPointMake(worldCoord.x, ((CGSize)[[CCDirector sharedDirector] displaySizeInPixels]).height - worldCoord.y);
// This is dry coded so may contain an error here or there.
// Let me know if this doesn't work.
[mySprite release];
[myNode release];