SKLabelNode positioning not working as expected - objective-c

I am working on a game and i need to implement the top bar, holding the details like score and other stuff.
My top bar should have the following (left to right):
- a 50x50 icon that changes according to level, but it's the same size
- a label with some text that changes according to level
- ... other elements
The problem is that when the label text changes, the label sometimes is too far from the icon and other times is over the icon (depending on the text length)
I thought I understood positioning, but apparently i didn't..
//create array for level text label
levelTextArray = [[NSArray alloc] initWithObjects:#"\"Uuu! Bubbles!\"",#"\"Noob\"",#"\"I’m getting it..\"",#"\"This is easy\"",#"\"Wha?\"",#"\"It’s ooon now!\"",#"\"Come on..\"",#"\"Dude…\"",#"\"You’re pushing it..\"",#"\"I’ll show you!!\"",#"\"AAAAAAA!!!\"",#"\"Holy Bubbles… \"",#"\"Ninja mode on!\"",#"\"I’m on fire!!\"",#"\"The wheel's spinning, but the hamsters dead. \"", nil];
//add level text label
levelTextLabel = [[SKLabelNode alloc] init];
levelTextLabel.text = levelTextArray[0];
levelTextLabel.position = CGPointMake(60, CGRectGetMidY(scoreImage.frame)+5);
levelTextLabel.fontColor = [UIColor colorWithRed:0/255.0f green:1/255.0f blue:0/255.0f alpha:1.0f];
levelTextLabel.fontName = #"Noteworthy-Light";
levelTextLabel.fontSize = 14.0;
[self addChild:levelTextLabel];
scoreImage is the icon in this case. Also..for the image to appear completely in the view I position it like this:
scoreImage = [[ SKSpriteNode alloc] initWithImageNamed:levelText];
scoreImage.name = #"LevelImage";
scoreImage.size = CGSizeMake(50, 50);
scoreImage.position = CGPointMake(0+scoreImage.size.width/2, CGRectGetMaxY(self.frame)-scoreImage.size.height/2);
I have the feeling that I'm doing something wrong here.
Any help is appreciated.
P.S. The label text as well as the icon image is changed according to level in -(void)update:(CFTimeInterval)currentTime {

Try setting the horizontalAlignmentMode of the SKLabelNode:
levelTextLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
The default is SKLabelHorizontalAlignmentModeCenter.

Related

How do I create a horizontal line with text in the middle?

I'm very new to Objective C but I'm looking at the source code of an existing app so there's a lot here to sift through.
I'm trying to create something like this:
-------------- or --------------
...only with a solid horizontal line instead of the dashes.
I have the "or" text defined as this:
_orLabel = ^{
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.textColor = [UIColor blackColor];
label.font = [UIFont mainFontWithSize:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline].pointSize];
label.adjustsFontSizeToFitWidth = YES;
label.textAlignment = NSTextAlignmentCenter;
label.text = NSLocalizedString(#"or", nil);
[view addSubview:label];
return label;
}();
That's working great to get "or" to show up but I have no idea how to get the horizontal lines on either side.
I would subclass UILabel and override drawTextInRect:. The easiest way is to call super so that the text gets drawn. Now you are still in a graphics context (CGContext) so you can use ordinary Quartz drawing commands to draw your horizontal lines.
The simplest approach is to make use of certain Unicode characters that will give you a solid line.
label.text = #"───────── or ─────────";
That text is using a series of "BOX DRAWINGS LIGHT HORIZONTAL" characters (U+2500).
I would use IB to add a view on each side of the label. Make the views have a height of 1 or 2 with a black background, and use autolayout to make them size appropriately for the label and screen situation:
Make view #1 anchored to the left edge of the screen and the right side of the label.
Make view #2 anchored to the right edge of the screen and the left side of the label.
Make the 2 views and the label have the same vertical center.

UILabel remove bottom margin

I am having a trouble with a UILabel.
I am trying to have the UILabel so that there is no margin at all in the container.
I tried different things, like sizeToFit, boundsToRect and others, but never got the solution so far.
Here is my code:
UILabel* saveLabel = [[UILabel alloc] init];
saveLabel = [[UILabel alloc] init];
saveLabel.text = "USER SAVE";
saveLabel.textAlignment = NSTextAlignmentRight;
saveLabel.layer.borderWidth = 2;
[saveLabel sizeToFit];
When I add this to my view I would expect that the border at the bottom (from the border) touch the letter of the labels, but there is a space in between.
I have attached a picture of the bottom effect if you want to see.
http://oi62.tinypic.com/n62b0w.jpg
I really cant understand why this margin is there and how to get rid of it.
All the other margin, top, left and right are fine, just the bottom one.
Any help on this would be very appreciated,
Thanks
The frame includes space for lower case letters like g and y which 'descend' below the text's baseline. In your case, you're only using uppercase letters, so you may wish to remove the descender portion of the frame. You can access the height of the descender via saveLabel.font.descender and then subtract that from the height of the fitted frame.
[saveLabel sizeToFit];
saveLabel.frame = CGRectMake(saveLabel.frame.origin.x
saveLabel.frame.origin.y,
saveLabel.frame.size.width,
saveLabel.frame.size.height - saveLabel.font.descender);
The following article has a good diagram:
https://www.cocoanetics.com/2010/02/understanding-uifont/

UIPageViewController: Change color of page indicator/pagecontrol per page

I am able to successfully change the color of PageControl/page indicator on UIPageViewController for the first page only. My use case requires each page to be a different color, requiring the PageControl/page indicator to match color with a page. I tried changing color based on the page index but it doesn't work.
Anyone know how to fix this?
- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index
{
if ([tutorialItems count] == 0) {
return nil;
}
// Create a new view controller and pass suitable data.
PageContentViewController *pageContentViewController
= [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
TutorialItem *tutorialItem = [tutorialItems objectAtIndex:index];
pageContentViewController.imageFile = tutorialItem.tutorialImageFileName;
pageContentViewController.titleText = tutorialItem.tutorialTitle;
pageContentViewController.tutorialText = tutorialItem.tutorialText;
int red = tutorialItem.tutorialRedKey;
int green = tutorialItem.tutorialGreenKey;
int blue = tutorialItem.tutorialBlueKey;
pageContentViewController.pageIndex = index;
tutorialBackgroundColor = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1.0f];
pageContentViewController.tutorialBackgroundColor = tutorialBackgroundColor;
UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor blackColor];
pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
pageControl.backgroundColor = [UIColor clearColor];
pageContentViewController.pageControllerColor = tutorialBackgroundColor;
return pageContentViewController;
}
appearance proxy attributes only get set when a component is first added to the window. Changing an appearance attribute will not change it for already visible components. If you want to change the color of a component that is already on the screen, you will need to reference it and change the color on it directly, or remove it from the view hierarchy and re-add it.
You can read the documentation here
Relevant quote:
iOS applies appearance changes when a view enters a window, it doesn’t
change the appearance of a view that’s already in a window. To change
the appearance of a view that’s currently in a window, remove the view
from the view hierarchy and then put it back.

Fill SKShapeNode with pattern image

I'm trying to fill a SKShapeNode with an Image/pattern but I'm still unsuccessfull.
Can you help me solving this or giving me an alternative? I want to create a collidable custom shape (from any SpriteKit kind) filled with a pattern image.
I've tried the following:
UIBezierPath *path = [[UIBezierPath alloc] init];
[path addArcWithCenter:CGPointMake(0.0, 0.0) radius:50.0 startAngle:0.0 endAngle:(M_PI*2.0) clockwise:YES];
SKShapeNode *shape = [[SKShapeNode alloc] init];
UIImage *patternImg = [UIImage imageNamed:#"pattern"];
shape.path = path.CGPath;
shape.fillColor = [[SKColor alloc] initWithCGColor:[[UIColor alloc] initWithPatternImage:patternImg].CGColor];
and also:
shape.fillColor = [[SKColor alloc] initWithPatternImage:[[UIImage alloc] initWithCGImage:[UIImage imageNamed:#"Basketball"].CGImage]];
This works (but it isn't what I'm looking for):
shape.fillColor = [SKColor redColor];
Thank you!
Starting from iOS 8.0 there is fillTexture property in the SKShapeNode.
i had the sample problem in my game, finally my solution was to add a SKSpriteNode as a child of the SKShapeNode and it worked fine.
SKSpriteNode* node = [[SKSpriteNode alloc] initWithImageNamed:#"bombIcon.png"];
node.name = #"bomb";
node.size = CGSizeMake(10, 10);
[self.bombNode addChild:node];
Where self.bombNode is a SKShapeNode.
Hope it helps
You could try to achieve that with SKCropNode. However, I've seen several questions here that SKShapeNode cannot act as maskNode for SKCropNode, but I haven't tested it myself. In this case you probably have to use SKSpriteNode instead of SKShapeNode.
Well, using modern Swift (you're using Swift by now, right?), you could try:
var marbleNode: SKSpriteNode!
Then later, in your init method:
marbleNode = SKSpriteNode(imageNamed: "SmallerSwirl");
marbleNode.physicsBody = SKPhysicsBody(circleOfRadius: 35.0)
marbleNode.physicsBody?.dynamic = true
marbleNode.physicsBody?.affectedByGravity = true
print(marbleNode.physicsBody)
marbleNode.position = CGPointMake(centerPoint.position.x + 10.0, centerPoint.position.y + 10.0)
self.addChild(marbleNode)
Okay, so that gives us a round sprite node to work with. The Sprite node is responsive to physics, because you set up its physics body separately. So far, so good. Now we need to address the glossed-over part, namely the introduction of the SmallerSwirl .png image.
When you set up your project, it included an Assets.xcassets (pronounced, "x c assets") entry. Click on it, then click on the "+" sign at the middle/bottom of the first column, by the word filter. From the menu that appears, select "New Image Set". A new entry labeled "Image" appears. Click on the word "Image" to change it to "SmallerSwirl".
Next to the SmallerSwirl entry, you see blanks labeled 1x, 2x, and 3x. They are for different screen resolutions. Start by dragging your preferred .png image into the 1x square. That image can be named whatever you want it to be named. It doesn't have to be named SmallerSwirl, though it can be. Drag other images to the 2x and 3x slots if you like.
Run, and you should see your preferred image embodied as a sprite, dancing around the screen.

highlight and make note in UIwebview

I am deveoping an ebook app for ipad/iphone which loads epub file. I would like to know how to highlight a text with a background color and make notes similar to iBook or Kindle in UIWebView and NOT UIView. I am able to drag select the text by long tapping. But I can only see "copy" option. I would like to add highlight and add note to that menu. How to hightlight the text with a background color?... My document is loaded in UIWebView.
Thank you.
What you need to do is add the note and highlight options to your shared menu. In your viewcontroller viewdidload (or anytime after your view has been added). The following adds two menu items with two selector methods to your menu.
UIMenuItem *customMenuItem1 = [[UIMenuItem alloc] initWithTitle:#"Highlight" action:#selector(doHighlight:)];
UIMenuItem *customMenuItem2 = [[UIMenuItem alloc] initWithTitle:#"Note" action:#selector(doNote:)];
//[myArray addObject:customMenuItem2];
NSMutableArray *myArray = [[NSMutableArray alloc]initWithObjects:customMenuItem1,customMenuItem2, nil ] ;
[UIMenuController sharedMenuController].menuItems = myArray;
You may also want to use a bit of javascript to determine the rect that holds your selection, then overlay a translucent uiview over the text.
So, within your doNote method, load up javascript and run it, see the below javascript for an example of what you may want to do.
NSString *rectString = [webView stringByEvaluatingJavaScriptFromString:rectStringText];
The following will get a rect around the text, though it will inherently be larger than your text: if you've highlighted at char 10 on line 2 through char 50 on line 5, it will return a rect that highlights char 0 line 2 through endline line 5.
function selectEl(x,y){
document.designMode = "on";
var el = document.elementFromPoint(x, y);
var rect = el.getBoundingClientRect();
var vx = rect.left;
var width = rect.right - vx;
var height = rect.bottom - rect.top;
var vy = rect.top;
var range = document.createRange();
range.selectNodeContents(el);
var sel = document.getSelection();
sel.removeAllRanges();
sel.addRange(range);
document.designMode = "off";
rectString = '{{'+vx+','+vy+'},{'+width+','+height+'}}';
}
So, now that you have a rectangle string, you can create a CRect from the string returned and uiview to overlay within your webview. [Note, you will have to figure out how to deal with zooming and saving this data for your next load]