I have two labels. One lane occupies the top left section of the screen and the other occupies the top right section of the screen. Even though it states bottom alignment mode the position is still on the top of the screen
scoreLabel.text = " Score: 0"
scoreLabel.fontSize = 70
scoreLabel.fontColor = SKColor.white
scoreLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.left
scoreLabel.position = CGPoint(x: self.size.width*0.15, y: self.size.height + scoreLabel.frame.size.height)
scoreLabel.zPosition = 100
self.addChild(scoreLabel)
livesLabel.text = "LIVES: 5"
livesLabel.fontSize = 70
livesLabel.fontColor = SKColor.white
livesLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.right
livesLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.bottom
livesLabel.position = CGPoint(x: self.size.width*0.85, y: self.size.height + livesLabel.frame.size.height)
livesLabel.zPosition = 100
self.addChild(livesLabel)
How can I write code so that both of these labels occupy the the bottom left and right sections of the screen?
Related
I want the UILabel text to be larger, but when I change value_row_height, there is no change in size.
var value_row_x = 30
var value_row_y = 100
var value_row_height = 320
var value_row_width = 30
let heart_rate_title_UILabel = UILabel(frame: CGRect(x: value_row_x, y: value_row_y, width: value_row_width, height: value_row_height ))
heart_rate_title_UILabel.center = CGPoint( x: value_row_x + value_row_width / 2, y: value_row_y + value_row_height/2 )
heart_rate_title_UILabel.textAlignment = .left
heart_rate_title_UILabel.text = "heart: "
heart_rate_title_UILabel.sizeToFit()
self.view.addSubview( heart_rate_title_UILabel)
UPDATE:
I added following code, but size failed to change...
heart_rate_title_UILabel.font = label.font.withSize(20)
heart_rate_title_UILabel.minimumScaleFactor = 0.1 //or whatever suits your need
heart_rate_title_UILabel.adjustsFontSizeToFitWidth = true
heart_rate_title_UILabel.lineBreakMode = .byClipping
heart_rate_title_UILabel.numberOfLines = 0
You are changing the physical height of the label. You are not saying anything about what the text size should be. Text size is a matter of setting the label's font (which includes size).
This worked jim-dandy....
value_row_y -= 10
value_row_x += 45 + inter_value_gap_pix // + width of heart rate value
let title_UILabel = UILabel(frame: CGRect(x: value_row_x, y: value_row_y, width: value_row_width, height: value_row_height ))
title_UILabel.center = CGPoint( x: value_row_x + value_row_width / 2, y: value_row_y + value_row_height/2 )
title_UILabel.textAlignment = .left
title_UILabel.text = " RSP: "
self.view.addSubview( title_UILabel)
// set font height to biggest (ie. label height)...
title_UILabel.numberOfLines = 1;
title_UILabel.font = title_UILabel.font.withSize(30)
I set up the sprite's physics body, zPosition, color, size, etc., but it won't appear visually. (It has the highest zPosition of my sprites, and YES I did import SpriteKit)
let wall = SKSpriteNode()
wall.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
//Takes screen size / width to make each piece one/(value set by "maze" at top) of the screen
let width: CGFloat = (UIScreen.main.bounds.width) / CGFloat(mazeSize)
let height: CGFloat = (UIScreen.main.bounds.height - 134) / CGFloat(mazeSize) //subtract so there's extra room on top+bottom of screen
wall.color = UIColor(ciColor: .black)
wall.isHidden = false
wall.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: width, height: height))
wall.physicsBody?.restitution = 0
wall.physicsBody?.friction = 0
wall.physicsBody?.isDynamic = false
wall.zPosition = 4
//sets up x+y location based on row count and which row this is on
//locations (ONLY positive)
let xLoc: CGFloat = ((UIScreen.main.bounds.width) / CGFloat((mazeSize/2))) * CGFloat(i/mazeSize)
let yLoc: CGFloat = ((UIScreen.main.bounds.height - 134) / CGFloat(mazeSize/2)) * CGFloat(i/mazeSize)
if((i/mazeSize) > (mazeSize/2)){ //if positive on x
wall.position.x = xLoc
}
else{ //if negative on x
wall.position.x = -xLoc
}
if(i > ((mazeSize^2)/2)){ //if positive on y
wall.position.x = yLoc
}
else{ //if negative on y
wall.position.y = yLoc
}
I'm using this to set up walls in a maze (Yes I know the x+y positions are wrong, but they still "appear" clumped in the middle), but only the physics of these nodes show up. Is there a way I can make these black walls appear?
The geometry of the sprite node and the geometry of the physics body don't have to be related, and in this case you've made a rectangular physics body and basically an empty sprite node. Try something like
let wall = SKSpriteNode(color: .black, size: CGSize(width: 100, height: 100)
or using the SKSpriteNode(texture:) initializer.
How can I make an arrow swing like in this video?
So far, I can rotate my node back and forth like in this video using the following code in didMove(to:) in my SKScene:
// Ball
let ballNode = SKSpriteNode(imageNamed: "Ball")
let offsetFromCorner: CGFloat = 20
ballNode.position = CGPoint(x: frame.minX + ballNode.size.width / 2 + offsetFromCorner, y: frame.minY + ballNode.size.height / 2 + offsetFromCorner)
addChild(ballNode)
/* ... */
// Aim arrow
let aimArrowNode = SKSpriteNode(imageNamed: "AimArrow")
aimArrowNode.position.y += aimArrowNode.size.height / 2
ballNode.addChild(aimArrowNode)
ballNode.zRotation = -.pi / 18 * 8
let rotateUp = SKAction.rotate(toAngle: -.pi / 18, duration: 1)
let rotateDown = SKAction.rotate(toAngle: -.pi / 18 * 8, duration: 1)
let combinedActions = SKAction.sequence([rotateUp, rotateDown])
ballNode.run(SKAction.repeatForever(combinedActions))
However, I want the arrow to appear to "slow down" as it gets nearer to the edge. How can I achieve this?
If you have any questions, please ask!
Luckily, the answer is actually built into SKAction.
Just add these after you create the actions:
rotateUp.timingMode = .easeInEaseOut
rotateDown.timingMode = .easeInEaseOut
Now you get the effect I was looking for! :)
So in my GameScene I have these lines in the beginning of func didMoveToView
let border = SKPhysicsBody(edgeLoopFromRect: self.frame)
border.friction = 0
self.physicsBody = border
self.physicsWorld.contactDelegate = self
It works fine for preventing my player from going outside the screen; However, I want my player, or anything else in the scene, to go to the other side of the screen when touching the border. In other words: If i kept going right i would keep going right until i hit the border then my player would appear from the left border and continue going right in an endless loop.
Same goes for y axis.
How is this possible in code?
Try this code:
if player.position.x + player.size.width / 2 > size.width {
player.position.x = -player.size.width
}
else if player.position.x + player.size.width / 2 < 0 {
player.position.x = size.width + player.size.width / 2
Same logic for Y axis.
For whoever is interested to reproduce this, I had to delete the following code:
let border = SKPhysicsBody(edgeLoopFromRect: self.frame)
border.friction = 0
self.physicsBody = border
self.physicsWorld.contactDelegate = self
Then, in touchesMoved I added:
if Player.position.x + Player.size.width / 16 > size.width {
Player.position.x = Player.size.width / 16
}
else if Player.position.x + Player.size.width / 16 < 0 {
Player.position.x = size.width - Player.size.width / 16
}
for the x axis. & the same can be done for the Y axis except we will change the x to y & the width to height.
I am simply trying to draw a rectangle and placing it in the bottom left hand side of the screen
var rectW:CGFloat = CGFloat(200.0)
var rectH:CGFloat = ceil(self.frame.height * 0.15)
var rect = SKShapeNode(rectOfSize: CGSize(width: rectW, height: rectH));
let posX:CGFloat = 0.0 + (rect.frame.width / 2)
let posY:CGFloat = self.frame.height - (self.frame.height - rect.frame.height)
rect.position = CGPointMake(posX,posY)
rect.fillColor = SKColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
rect.lineWidth = 1
self.addChild(rect)
The issue is that even though i believe all the maths is correct the rectangle is about 38 points/pixels that are under the screen, as you can see from the image below (the white border shows the limit).
For your information here is an output of the positions, heights and widths.
PosX: 100.5
PosY: 117.0
Rect Width: 201.0
Rect Height: 117.0
Frame Height: 768.0
Frame Weight: 1024.0
If i simple take this line but add 38 points/pixels it works, but why? Is there something I am missing?
let posY:CGFloat = self.frame.height - (self.frame.height - rect.frame.height) + 38
I found the answer via the following two answers:
SpriteKit coordinate system messed up
Problems understanding coordinate system SpriteKit using Swift
The problem turns out to be with GameScene.sks having it's size set differently.
Open up GameScene.sks and go to 'Show SKNodeInspector' should be the third box in the top right hand side of the screen.
Then set the dimensions to 320 x 568
Save then run. Should be working.