Sprite Kit: SKSpriteNodes hanging off left side of screen despite (0,0) anchor points - objective-c

I'm adding an array of SKSpriteNodes (640px wide) directly to my SKScene:
for (backgroundTile in backgroundTiles) {
backgroundTile.anchorPoint = CGPointMake(0.0, 0.0);
backgroundTile.position = CGPointMake(BG_TILE_X_POS, tilePlacementPositionY);
[self addChild:backgroundTile];
tilePlacementPositionY += tileHeight;
}
(BG_TILE_X_POS is 0.0)
But despite having an X position of 0.0 and their anchor points being set to (0.0,0.0) they still hang off the left side of the screen by 150px.
I can compensate that by giving them an X position of 150 and have also tried:
self.size = view.bounds.size;
…but that only enlarges the visible parts of the sprites so that they fill the screen; cropping off the top sprite.
I assume I'm making a rookie mistake but, looking through the documentation, nothing's striking me as obvious (which I guess it should be).
So, how do I position the sprites flush to the left edge? Any help would be appreciated.
Thanks.

I'd overlooked the obvious. I'd only created placeholder sprites at x2 resolution but stored them in their image sets as 1x resolution. Finally, with the setting:
self.size = view.bounds.size;
everything behaves as expected.
Silly mistake. I was convinced the problem was with the code, not the assets.

Related

How to draw half an ellipse in Win2D?

I want to draw either the lower or the upper half of an elliptical arc using Win2D in a C++/winrt app. I can draw the curve, but it includes a diagonal line at its start that looks as if I had begun with a straight line segment - as if the figure didn't begin at the arc but rather some distance down and to the right. How I can restrict drawing to just the arc? Here is the code and an image of the result:
float2 arcSize(100, 6);
auto pathBuilder = CanvasPathBuilder(drawingSession.Device());
pathBuilder.BeginFigure(244, 175);
//Starting at 3 o"clock, sweep pi radians, that is, to 9:00
pathBuilder.AddArc(arcSize,50,6,0.0, 3.14);
pathBuilder.EndFigure(CanvasFigureLoop::Open); //Don't close path
auto geometry = CanvasGeometry::CreatePath(pathBuilder);
session.DrawGeometry(geometry,244, 175, Colors::Black(),1.5);
OK, thanks to that hint from Inspectable I have the solution: the problem lies in where the path begins. In my code I had mistakenly used the proposed arc size as the first argument to AddArc when really that should be the arc center coordinates. And the BeginFigure in the case of this arc must be the point lying at the right edge, at what would be 3:00 in a circle. With the ArcCenter correct in relation to the BeginFigure then AddArc doesn't draw the extra line.
[Update:] p.s. The x and y coordinates for the DrawGeometry call should be zero in this case; that draws it at its original coordinates from BeginFigure, not offset. Maybe this p.s can gain me another -1 for this question.

Troubles Prepositioning Node Using Coordinate System Conversions

Okay so I have been trying to preposition a sprite node before adding it to the scene. The only problem is that I need to know the (0, 0.5) or (left, middle) position of the node, in scene coordinates before I can position it properly.
I know about the convertPoint:(CGPoint) toNode/fromNode:(SKSpriteNode *) methods and currently I have worked out the following within the Scene's code:
[node convertPoint:CGPointMake(0,0.5) toNode: self]
I also wasn't sure if it was confusing self (the scene) with self (the node), so I tried
SKScene *scene = self;
[node convertPoint:CGPointMake(0,0.5) toNode: scene]
I am pretty sure that I didn't have to make the distinction but I tried any ways.
The logged result of both attempts was (0,0.5).
The node.position is (50, 100).
In case the above is not clear, I am trying to find the position on the edge of the frame, which should be equal to the nodes width. The reason why I am not using width though is because I am placing it in respect to another node and the two nodes may be rotated.
The theories I am trying to reference are from Apples Spritekit Programming Guide
If there is an easier way to establish a distance between two nodes based on the width of one node, taking into account rotation, feel free to post it for I would love to know, although I still need the node conversion for other methods.
Thank you in advance for all of your help.
You shouldn't change the anchor point once the node has been added as it will inherently change its position. If you are using anchor 0.5, 0.5 to rotate the nodes leave it like that. If you want to get the maxX point from a rotated node you could do something like this:
SKSpriteNode *sprite2 = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:CGSizeMake(50, 50)];
float angle = - sprite.zRotation;
CGPoint dirVect = CGPointMake(cosf(angle), sinf(angle));
CGFloat distance = sprite.frame.size.width/2 + sprite2.frame.size.width/2;
CGPoint destPoint = CGPointMake(sprite.position.x + (dirVect.x * distance),
sprite.position.y + (dirVect.y * distance));
sprite2.position = destPoint;
[self addChild:sprite2];
Where sprite is the node you have rotated and sprite2 the node you want to add respect of the first node. distance should be the distance (excuse the pun) between the anchor points of the two nodes.
Let me know if this is what you are looking for. If not, a screenshot would help :)

Visualizing the Anchor Point of a UIImageView

Is there an easy way of putting a mark (like a cross for example) on the anchor point of an UIImageView? I'm trying to line up several rotating images by their anchor point, and being able to see these points would make the job a lot easier.
Many thanks.
You are asking how to visualize the anchor point within a view but it seem to me that you are asking for it so that you can help align the anchor points. I'll try and answer both questions.
Visualizing the anchor point.
Every view on iOS have an underlying layer that has an anchor point. The anchor point is in unit coordinate space of the layer (x and y goes from 0 to 1). This means that you can multiply x by the width and y by the height to get the position of the anchor point inside the layer in the coordinate space of the view/layer. You can then place a subview/sublayer there to show the location of the anchor point.
In code you could do something like this to display a small black dot where the anchor point is.
CALayer *anchorPointLayer = [CALayer layer];
anchorPointLayer.backgroundColor = [UIColor blackColor].CGColor;
anchorPointLayer.bounds = CGRectMake(0, 0, 6, 6);
anchorPointLayer.cornerRadius = 3;
CGPoint anchor = viewWithVisibleAnchorPoint.layer.anchorPoint;
CGSize size = viewWithVisibleAnchorPoint.layer.bounds.size;
anchorPointLayer.position = CGPointMake(anchor.x * size.width,
anchor.y * size.height);
[viewWithVisibleAnchorPoint.layer addSublayer:anchorPointLayer];
You can see the result in the image below for four different rotations.
Aligning layers by their anchor point
That is cool and all but it's actually easier then that to align anchor points.
The key trick is that the position and the anchorPoint is always the same point, only in two different coordinate spaces. The position is specified in the coordinate space of the super layer. The anchor point is specified in the unit coordinate space of the layer.
The nice thing about this is that views that have their position property aligned will automatically have their anchorPoint aligned. Note that the content is drawn relative to the anchor point. Below is an example of a bunch of views that all have the same y component of their position, thus they are aligned in y.
There really isn't any special code to do this. Just make sure that the position properties are aligned.

Draw rotated text to parent coordinate system

I have a UIView, which I'm drawing manually in the 'drawRect'-Function.
It is basically a coordinate system, which has 'Values' on the Y-Axis and 'Time' on the 'X-Axis'.
Due to space issues, I want the Timestamps to be vertical, instead of horizontal.
For this purpose, I use:
CGContextSaveGState(ctx); //Saves the current graphic context state
CGContextRotateCTM(ctx, M_PI_2); //Rotates the context by 90° clockwise
strPos = CGContextConvertPointToUserSpace(ctx, strPos); //SHOULD convert to Usercoordinates
[str drawAtPoint:strPos withFont:fnt]; //Draws the text to the rotated CTM
CGContextRestoreGState(ctx); //Restores the CTM to the previous state.
ctx (CGContextRef), strPos (CGPoint) and str (NSString) are variables, that have been initialized properly and correctly for 'horizontal text', with a width of the text height.
While this code works flawlessly on the iPhone 3, it gives me a complete mess on the iPhone 4 (Retina), because the CGContextConvertPointToUserSpace function produces completely different results, even though the coordinate system of the iPhone is supposed to remain the same.
I also tried using CGAffineTransform, but only with the same results.
To summarize my question: How do I draw a text to a calculated position in the parent coordinate system (0, 0 being top left)?
After studying the Apple docs regarding Quartz 2D once more, I came to realize, that the rotation by Pi/2 moves all my writing off screen to the left.
I can make the writing appear in a vertical line by translating the CTM by +height.
I'll keep trying, but would still be happy to get an answer.
Edit: Thanks to lawicko's heads-up I was able to fix the problem. See Answer for details.
I would like to thank lawicko for pointing this out.
During my tests I made two mistakes...but he is of course correct. Using CGContextShowTextAtPoint is the most simple solution, since it doesn't require the rotation of the entire CTM.
Again, THANK you.
Now, for the actual answer to my question.
To draw a rotated text at position x/y, the following code works for me.
CGAffineTransform rot = CGAffineTransformMakeRotation(M_PI_2); //Creates the rotation
CGContextSelectFont(ctx, "TrebuchetMS", 10, kCGEncodingMacRoman); //Selects the font
CGContextSetTextMatrix(ctx, CGAffineTransformScale(rot, 1, -1)); //Mirrors the rotated text, so it will be displayed correctly.
CGContextShowTextAtPoint(ctx, strPos.x, strPos.y, TS, 5); //Draws the text
ctx is the CGContext, strPos the desired position in the parent coordinate system, TS a char array.
Again, thank you lawicko.
I probably would've searched forever if not for your suggestion.
Maybe this answer will help someone else, who comes across the same problem.

Draw line with increasing lineWidth on iPhone

I'm drawing a line on iOS by stroking a path onto a CALayer. How can I stroke this line with an increasing lineWidth (stroke width), so that the left end of the line is thinner than the right end? (It really has to be a line, not a shape or closed path, since I'm going to be using the strokeEnd property.)
Thank you for your help!
Use a draw function. It's pretty annoying to get used to at first, but it does its job. If you need anymore help just leave comment
-(void)draw{
float lineHeight = 5;//change this as you see fit, like set it equal to an incrementing/decrementing variable of your choice...
glEnable(GL_LINE_SMOOTH);
glLineWidth(lineHeight); // change this as you see fit
glColor4ub(255,255,255,255); // change these as you see fit :)
ccDrawLine(ccp(10,310), ccp(30,310)); // these numbers are probably off, you'll have to mess with these to get it in the right position :)
[super draw];
}