I'm working on a game where nodes are continuously scrolling down the screen. I have them set up to spawn at a certain position and everything looks even:
The issue occurs when the user pauses the game repeatedly, the nodes get misaligned like so:
I believe that when I pause the game my timing is thrown off. Here are my updateCurrentTime() functions. I have it set so it adds a new random row every 0.6 seconds.
func updateWithTimeSinceLastUpdate (_ timeSinceLastUpdate:CFTimeInterval) {
lastYieldTimeInterval += timeSinceLastUpdate
if lastYieldTimeInterval > 0.6 {
lastYieldTimeInterval = 0
addRandomRow()
}
}
override func update(_ currentTime: TimeInterval) {
if screenIsPaused == 1{
pauseScreen()
}else if screenIsPaused == 0{
unPauseScreen()
screenIsPaused = 2
} else if screenIsPaused == 3{
gameLayer.isPaused = true
}
var timeSinceLastUpdate = currentTime - lastUpdateTimeInterval
lastUpdateTimeInterval = currentTime
if timeSinceLastUpdate > 1 {
timeSinceLastUpdate = 1/60
lastUpdateTimeInterval = currentTime
}
updateWithTimeSinceLastUpdate(timeSinceLastUpdate)
}
Here is the code that I use to pause my game:
func pauseScreen(){
overlay.color = UIColor.black
overlay.alpha = 0.6
overlay.size.height = self.size.height
overlay.size.width = self.size.width
overlay.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
overlay.zPosition = 100
addChild(overlay)
gameLayer.isPaused = true
screenIsPaused = 3
label.text = "Press screen to play!"
label.fontColor = SKColor.white
label.fontSize = 50
label.position = CGPoint(x: self.size.width / 2, y: self.size.height / 2)
addChild(label)
let Fade = SKAction.sequence([SKAction.fadeIn(withDuration: 1), SKAction.fadeOut(withDuration: 1)])
label.run(SKAction.repeatForever(Fade))
}
func unPauseScreen(){
label.removeFromParent()
overlay.removeFromParent()
screenIsPaused = 2
gameLayer.isPaused = false
}
The pause function is called in touchesEnded() and the un-pause function is called in touchesBegan.
Please let me know if there is anything I can try or if you require more information. Thanks!
I finally found a solution. I'm not sure if it is the best answer; however, it works. I modified my function updateWithTimeSinceLastUpdate here it is now:
func updateWithTimeSinceLastUpdate (_ timeSinceLastUpdate:CFTimeInterval) {
if lastYieldTimeInterval > 0.6 {
lastYieldTimeInterval = 0
addRandomRow()
}
if screenIsPaused == 1{
pauseScreen()
lastYieldTimeInterval += timeSinceLastUpdate
}else if screenIsPaused == 0{
unPauseScreen()
lastYieldTimeInterval += timeSinceLastUpdate
screenIsPaused = 2
} else if screenIsPaused == 3{
gameLayer.isPaused = true
}else if screenIsPaused == 2{
lastYieldTimeInterval += timeSinceLastUpdate
}
}
I moved that screenIsPaused if statements here instead of my update(_ currentTime: TimeInterval). In addition, I added lastYieldTimeInterval += timeSinceLastUpdate into each of the if statements. Now every time the game pauses or un-pauses the time is updated.
Related
I am trying to find the distance between two nodes, specifically rocks. Now this is simple math; but I am running into a problem. I want to check to see if the topRock is within a distance, that distance is to be determined, of btmRock. The code I have is ->
extension CGPoint {
func distanceFromCGPoint(point:CGPoint)->CGFloat{
return sqrt(pow(self.x - point.x,2) + pow(self.y - point.y,2))
}
}
Now in my update function I have ->
var updateTopTime : Double = 0
var updateBottomTime : Double = 0
var genInterval : Double = 2
var genOffset : Double = 3.5
override func update(_ currentTime: TimeInterval) {
moveBackgroundImg()
//optional prevents generation if game is not playing
//guard gameState == .playing else { return }
if updateTopTime == 0 {
updateTopTime = currentTime
}
if updateBottomTime == 0 {
updateBottomTime = currentTime
}
if currentTime - updateBottomTime > genOffset {
createBtmRock()
genOffset = genInterval
updateBottomTime = currentTime
}
else if currentTime - updateTopTime > genInterval {
createTopRock()
updateTopTime = currentTime
}
var distance = btmRock.position.distanceFromCGPoint(point: topRock.position)
print(distance)
if distance <= 10 {
btmRock.position.x += 10
}
if holdingTouch{
progressBar.progress -= 0.001
voloc += 15
plane.physicsBody?.velocity = CGVector(dx: 0, dy: voloc)
//plane.physicsBody?.applyImpulse(CGVector(dx: 0, dy: ))
}
}
The problem is that distance returns 244.201193259997. My topRock and btmRock are randomly generated as well as they move. Even when the nodes are moving the result stays the same. This is how I move my nodes ->
func moveBackgroundImg(){
self.enumerateChildNodes(withName: "BackgroundImg", using: ({
(node, error) in
node.position.x -= self.backgroundMovingSpeed
if node.position.x < -((self.scene?.size.width)!){
node.position.x += (self.scene?.size.width)! * 3
}
}))
self.enumerateChildNodes(withName: "GroundImg", using: ({
(node, error) in
node.position.x -= self.backgroundMovingSpeed
if node.position.x < -((self.scene?.size.width)!){
node.position.x += (self.scene?.size.width)! * 3
}
}))
self.enumerateChildNodes(withName: "TopRock", using: ({
(node, error) in
node.position.x -= self.backgroundMovingSpeed
if node.position.x < -((self.scene?.size.width)!){
node.removeFromParent()
}
}))
self.enumerateChildNodes(withName: "BtmRock", using: ({
(node, error) in
node.position.x -= self.backgroundMovingSpeed
if node.position.x < -((self.scene?.size.width)!){
node.removeFromParent()
}
}))
}
I am confused on how my nodes are created randomly so they have different x and y points; but I am still getting 244.201193259997. If it helps this is how my nodes are created ->
func setupRocks() {
//create the base bottom rock
var btmRockChoice = [SKTexture(image: #imageLiteral(resourceName: "rock")), SKTexture(image: #imageLiteral(resourceName: "rockGrass")), SKTexture(image: #imageLiteral(resourceName: "rockSnow")), SKTexture(image: #imageLiteral(resourceName: "rockIce"))]
btmRock = SKSpriteNode(texture: btmRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10, height: (self.scene?.size.height)! / 2.2))
btmRock.zPosition = -9
btmRock.position = CGPoint(x: self.frame.width, y: frame.minY + btmRock.frame.height / 2)
btmRock.name = "BtmRock"
btmRock.physicsBody = SKPhysicsBody(texture: btmRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10, height: (self.scene?.size.height)! / 2.2))
btmRock.physicsBody?.categoryBitMask = physicsCatagory.topRock
btmRock.physicsBody?.collisionBitMask = physicsCatagory.plane
btmRock.physicsBody?.contactTestBitMask = physicsCatagory.plane
btmRock.physicsBody?.affectedByGravity = false
btmRock.physicsBody?.isDynamic = false
//create the base top rock
var topRockChoice = [SKTexture(image: #imageLiteral(resourceName: "rockDown")), SKTexture(image: #imageLiteral(resourceName: "rockGrassDown")), SKTexture(image: #imageLiteral(resourceName: "rockSnowDown")), SKTexture(image: #imageLiteral(resourceName: "rockIceDown"))]
topRock = SKSpriteNode(texture: topRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10, height: (self.scene?.size.height)! / 2.2))
topRock.zPosition = -9
topRock.name = "TopRock"
topRock.position = CGPoint(x: self.frame.width + topRock.size.width * 2, y: frame.maxY - topRock.frame.height / 2)
topRock.physicsBody = SKPhysicsBody(texture: topRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10, height: (self.scene?.size.height)! / 2.2))
topRock.physicsBody?.categoryBitMask = physicsCatagory.topRock
topRock.physicsBody?.collisionBitMask = physicsCatagory.plane
topRock.physicsBody?.contactTestBitMask = physicsCatagory.plane
topRock.physicsBody?.affectedByGravity = false
topRock.physicsBody?.isDynamic = false
}
func createTopRock() {
//You can make this number a class variable to increase the rate as the game progresses
let randomNum = arc4random_uniform(2)
//there is a 1 in 3 chance that this rock will get created
if randomNum == 0 {
let rock = topRock.copy() as! SKSpriteNode
self.addChild(rock)
}
}
func createBtmRock() {
//You can make this number a class variable to increase the rate as the game progresses
let randomNum = arc4random_uniform(2)
//there is a 1 in 2 chance that this rock will get created
if randomNum == 0 {
let rock = btmRock.copy() as! SKSpriteNode
self.addChild(rock)
}
}
override func didMove(to view: SKView) {
spawnDelayForeverTop = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.createTopRock), userInfo: nil, repeats: false)
spawnDelayForeverBtm = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(self.createBtmRock), userInfo: nil, repeats: false)
}
UPDATE: I believe it has something to do with anchor points but I am unsure.
You topRock and bottomRock nodes are not actually the ones you see in your scene and are not added as children. What you're adding to the scene are copies of these two "template" objects. The position of topRock and bottomRock are never changed because they are not part of the scene's children (and I don't see any place in your code where you change the position of these two instances)
I have an issue whereby I am moving the character based on the accelerometer data using the following code in the update function as follows:
let currentX = self.player.position.x
if motionManager.isAccelerometerAvailable == true {
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
data, error in
self.destX = currentX + CGFloat((data?.acceleration.x)! * 40)
print(CGFloat((data?.acceleration.x)!))
})
}
player.position.x = destX
Originally I was moving the player using SKAction.moveTo but have removed this for testing purposes.
This works ok but the problem is, I have a sound that is being played upon collision of an invisible object and when this is enabled it sends the accelerometer all funny. There is no specific pattern to it but after a little while the player usually sticks to either side of the screen or just hovers in the middle and the accelerometer doesn't have any effect on the movement.
I am playing the sound using
let playSound = SKAction.playSoundFileNamed("phaserDown3.mp3", waitForCompletion: false)
At the top of the file and then calling run on a collision.
The full code is in here http://pastebin.com/f6kWTnr7 and I have made a little video of the issue here https://youtu.be/tcGYyrKE4QY - as you will see, in this case when the score is at around 15 it sticks to the left for a little bit, then returns to normal then sticks to the right. It isn't always at score 15, it can be sooner or even later there is no consistency at all.
Any input will be greatly appreciated, thank you in advance
Take a look at this updated scene, some of the major changes are I combined your 3 separate blocks into 1 SKNode so that I only have to move the single SKNode, and I set it up where you score at the end of a contact, not the beginning. You can also see that the blocks now die when done scrolling, and your background is more efficient with its scrolling. If you have any other questions on the changes, feel free to ask.
//
// GameScene.swift
// SpriteKitSimpleGame
//
// Created by James Leist on 28/11/2016.
// Copyright © 2016 James Leist. All rights reserved.
//
import SpriteKit
import CoreMotion
var motionManager = CMMotionManager()
enum BodyType:UInt32 {
case player = 1
case score = 2
case dontCollide = 4
case sides = 8
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var killNodes = [SKNode]()
//let player = SKSpriteNode(imageNamed: "Airplane")
let player = SKSpriteNode(color: .green, size: CGSize(width:32,height:32))
var bg1:SKSpriteNode!
var bg2:SKSpriteNode!
let block = SKNode()
let blockHeight = 50
var currentScore = 0
var scoreLabel:SKLabelNode!
let playSound = SKAction.playSoundFileNamed("phaserDown3.mp3", waitForCompletion: false)
let move = SKAction.move(by:CGVector(dx:0,dy:-4 * 60),duration:1) //this means we move 4 every 1/60 of a second
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
backgroundColor = SKColor.white
addScrollingBG()
createRandomBlock()
addRandomBlocks1()
// sideRestraints()
scoreLabel = SKLabelNode(fontNamed: "Copperplate-Bold")
scoreLabel.text = String(currentScore)
scoreLabel.fontSize = 80
scoreLabel.position = CGPoint(x: frame.size.width - 60, y: frame.size.height - 60)
scoreLabel.zPosition = 20
self.addChild(scoreLabel)
player.name = "Player"
player.zPosition = 15
player.position = CGPoint(x: size.width * 0.5, y: size.height * 0.5)
// player.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "Airplane"), size: CGSize(width: player.size.width, height: player.size.height))
player.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: player.size.width, height: player.size.height))
player.physicsBody?.affectedByGravity = false
player.physicsBody!.categoryBitMask = BodyType.player.rawValue
player.physicsBody!.contactTestBitMask = BodyType.score.rawValue | BodyType.sides.rawValue
player.physicsBody!.collisionBitMask = 0
addChild(player)
startAccelerometer()
}
func startAccelerometer()
{
if motionManager.isAccelerometerAvailable == true {
motionManager.startAccelerometerUpdates(to: OperationQueue.current!, withHandler: {
[weak self] data, error in
guard let strongSelf = self else {return}
var destX = UInt32(strongSelf.player.position.x + CGFloat((data?.acceleration.x)! * 40))
// Called before each frame is rendered */
if destX <= 0 {
destX = 0
}
else if destX >= UInt32(strongSelf.frame.size.width) {
destX = UInt32(strongSelf.frame.size.width)
}
strongSelf.player.position.x = CGFloat(destX)
print(CGFloat((data?.acceleration.x)!))
})
}
}
func addScrollingBG() {
bg1 = SKSpriteNode(imageNamed: "bgPlayScene")
bg1 = SKSpriteNode(color:.blue,size:self.size)
bg1.anchorPoint = CGPoint.zero
bg1.position = CGPoint(x: 0, y: 0)
// bg1.size = CGSize(width: frame.size.width, height: frame.size.height)
bg1.zPosition = 0
addChild(bg1)
bg2 = SKSpriteNode(imageNamed: "bgPlayScene")
bg2 = SKSpriteNode(color:.purple,size:self.size)
bg2.anchorPoint = CGPoint.zero
bg2.position = CGPoint(x: 0, y: bg1.size.height)
// bg2.size = CGSize(width: frame.size.width, height: frame.size.height)
bg2.zPosition = 0
self.addChild(bg2)
setupBackgroundAnimation()
}
func setupBackgroundAnimation()
{
let reset = SKAction.customAction(withDuration: 1,actionBlock:
{
node,time in
guard let sNode = node as? SKSpriteNode else {return}
sNode.position = sNode.position.y <= -sNode.size.height ?
CGPoint(x: sNode.position.x, y: sNode.position.y + sNode.size.height * 2) : sNode.position
})
let scroll = SKAction.repeatForever(SKAction.group([move,reset]))
bg1.run(scroll)
bg2.run(scroll)
}
func createRandomBlock()
{
block.position = CGPoint(x:0,y:size.height + CGFloat(blockHeight))
//let partialBlock = SKSpriteNode(imageNamed: "block")
let partialBlock = SKSpriteNode(color:.yellow, size:CGSize(width: 1, height: blockHeight))
let blockLeft1 = partialBlock.copy() as! SKSpriteNode
blockLeft1.name = "left"
blockLeft1.anchorPoint = CGPoint.zero
blockLeft1.size = CGSize(width: 1, height: blockHeight)
blockLeft1.zPosition = 5;
blockLeft1.position = CGPoint.zero
block.addChild(blockLeft1)
let leftBody = SKPhysicsBody(rectangleOf: blockLeft1.size)
leftBody.affectedByGravity = false
leftBody.categoryBitMask = BodyType.sides.rawValue
leftBody.contactTestBitMask = 0
leftBody.collisionBitMask = 0
leftBody.isDynamic = false
blockLeft1.physicsBody = leftBody
let blockRight1 = partialBlock.copy() as! SKSpriteNode
blockRight1.color = .green
blockRight1.anchorPoint = CGPoint.zero
blockRight1.name = "right"
blockRight1.size = CGSize(width: 1, height: blockHeight)
blockRight1.zPosition = 5;
blockRight1.position = CGPoint(x:size.width,y:0)
block.addChild(blockRight1)
let rightBody = SKPhysicsBody(rectangleOf: blockRight1.size)
rightBody.affectedByGravity = false
rightBody.categoryBitMask = BodyType.sides.rawValue
rightBody.contactTestBitMask = 0
rightBody.collisionBitMask = 0
rightBody.isDynamic = false
blockRight1.physicsBody = rightBody
let scoreBody = SKPhysicsBody(rectangleOf:CGSize(width:Int(frame.size.width),height:blockHeight))
scoreBody.affectedByGravity = false
scoreBody.categoryBitMask = BodyType.score.rawValue
scoreBody.contactTestBitMask = 0
scoreBody.collisionBitMask = 0
scoreBody.isDynamic = false
block.physicsBody = scoreBody
}
func addRandomBlocks1() {
let randomLeftWidth : UInt32 = arc4random_uniform(UInt32(size.width) - 50)
let randomRightWidth : UInt32 = arc4random_uniform((UInt32(size.width) - randomLeftWidth) - 50)
guard let newBlock = block.copy() as? SKNode else {return} //ifw e do not have a node return
if let leftBlock = newBlock.childNode(withName:"left") as? SKSpriteNode
{
leftBlock.xScale = CGFloat(randomLeftWidth)
}
if let rightBlock = newBlock.childNode(withName:"right") as? SKSpriteNode
{
rightBlock.xScale = -CGFloat(randomRightWidth)
}
let addRandom = SKAction.customAction(withDuration: 0, actionBlock:
{
[unowned self] node,time in
if Int(node.position.y) < -self.blockHeight
{
node.removeFromParent()
self.addRandomBlocks1()
}
})
newBlock.run(SKAction.repeatForever(SKAction.group([move,addRandom])))
addChild(newBlock)
}
override func update(_ currentTime: CFTimeInterval) {
}
override func didFinishUpdate()
{
killNodes.forEach{$0.removeFromParent()}
}
func didBegin(_ contact: SKPhysicsContact) {
//This will organize the bodies so that the lowest category is A
let bodies = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (A:contact.bodyA,B:contact.bodyB) : (A:contact.bodyB,B:contact.bodyA)
switch (bodies.A.categoryBitMask,bodies.B.categoryBitMask)
{
case let (a, b) where ((a & BodyType.player.rawValue) | (b & BodyType.sides.rawValue)) > 0:
killNodes.append(bodies.A.node!)
let label = SKLabelNode(text: "Gameover")
label.position = CGPoint(x:self.size.width/2,y:self.size.height/2)
addChild(label)
default:()
}
}
func didEnd(_ contact: SKPhysicsContact) {
//This will organize the bodies so that the lowest category is A
let bodies = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (A:contact.bodyA,B:contact.bodyB) : (A:contact.bodyB,B:contact.bodyA)
switch (bodies.A.categoryBitMask,bodies.B.categoryBitMask)
{
case let (a, b) where ((a & BodyType.player.rawValue) | (b & BodyType.score.rawValue)) > 0:
currentScore += 1
run(playSound, withKey:"phaser")
scoreLabel.text = String(currentScore)
default:()
}
}
}
I am making a spritekit game where you need to move the player back and forth to catch objects falling down the screen. (You gain a point when the player collides with the falling object.)Recently I added restart button function. Before the restart button comes up everything works fine but when I restart the scene and the objects fall to hit the player the player falls off the screen once they make contact. This is odd because I have already set it to make the player (or person) not affected by gravity and not to be dynamic. Again before I press the button it works fine. Why are the characteristics of the person not there once I restart the scene. If you could take a look at my code and tell me why this is happening I would greatly appreciate it.
import SpriteKit
struct physicsCatagory {
static let person : UInt32 = 0x1 << 1
static let Ice : UInt32 = 0x1 << 2
static let IceTwo : UInt32 = 0x1 << 3
static let IceThree : UInt32 = 0x1 << 4
static let Score : UInt32 = 0x1 << 5
}
class GameScene: SKScene, SKPhysicsContactDelegate {
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
scorenumber = 0
lifenumber = 0
createScene()
random()
//spawnThirdIce()
Died = false
}
func createScene(){
physicsWorld.contactDelegate = self
lifenumber = 0
SpeedNumber = 1
BackGround.size = CGSize(width: self.frame.width, height: self.frame.height)
BackGround.position = CGPointMake(self.size.width / 2, self.size.height / 2)
BackGround.zPosition = -5
self.addChild(BackGround)
Score.size = CGSize(width: 2563, height: 1)
Score.position = CGPoint(x: 320, y: -20)
Score.physicsBody = SKPhysicsBody(rectangleOfSize: Score.size)
Score.physicsBody?.affectedByGravity = false
Score.physicsBody?.dynamic = false
Score.physicsBody?.categoryBitMask = physicsCatagory.Score
Score.physicsBody?.collisionBitMask = 0
Score.physicsBody?.contactTestBitMask = physicsCatagory.IceThree
Score.color = SKColor.blueColor()
Score.zPosition = -5
self.addChild(Score)
person.zPosition = 1
person.position = CGPointMake(self.size.width/2, self.size.height/10)
person.setScale(0.6)
person.physicsBody = SKPhysicsBody (rectangleOfSize: CGSize(width: 40, height: 50))
person.physicsBody?.affectedByGravity = false
person.physicsBody?.categoryBitMask = physicsCatagory.person
person.physicsBody?.contactTestBitMask = physicsCatagory.Ice
person.physicsBody?.collisionBitMask = physicsCatagory.Ice
person.physicsBody?.dynamic = false
person.physicsBody?.affectedByGravity = false
ScoreLable = SKLabelNode(fontNamed: "Zapfino")
ScoreLable.position = CGPoint(x: self.frame.width / 2, y: 1700)
ScoreLable.text = "\(scorenumber)"
ScoreLable.fontColor = UIColor.yellowColor()
ScoreLable.fontSize = 150
ScoreLable.fontName = "Zapfino "
self.addChild(ScoreLable)
self.addChild(person)
}
func random() -> CGFloat{
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min min: CGFloat, max: CGFloat) -> CGFloat{
return random() * (max - min) + min
}
var gameArea: CGRect
override init(size: CGSize) {
let maxAspectRatio: CGFloat = 16.0/9.0
let playableWidth = size.height / maxAspectRatio
let margin = (size.width - playableWidth) / 2
gameArea = CGRect(x: margin, y: 0, width: playableWidth, height: size.height)
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var timeOfLastSpawn: CFTimeInterval = 0.0
var timePerSpawn: CFTimeInterval = 1.2
var scorenumber = Int()
var lifenumber = Int()
var SpeedNumber : Double = 0.5
var person = SKSpriteNode(imageNamed: "Person1")
let Score = SKSpriteNode()
var ScoreLable = SKLabelNode()
let BackGround = SKSpriteNode (imageNamed: "BackGround")
var restartButton = SKSpriteNode()
var Died = Bool()
override func didMoveToView(view: SKView) {
createScene()
}
func createButton(){
restartButton = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 200, height: 100))
restartButton.position = CGPoint(x: self.gameArea.width/2, y: self.gameArea.height/2)
restartButton.zPosition = 6
self.addChild(restartButton)
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.person && secondBody.categoryBitMask == physicsCatagory.IceThree || firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.person{
scorenumber++
if scorenumber == 20 {
timePerSpawn = 1.0
}
if scorenumber == 40{
timePerSpawn = 0.89
}
if scorenumber == 60{
timePerSpawn = 0.6
}
if scorenumber == 80{
timePerSpawn = 0.5
}
if scorenumber == 100{
timePerSpawn = 0.4
}
if scorenumber == 120{
timePerSpawn = 0.3
}
ScoreLable.text = "\(scorenumber)"
CollisionWithPerson(firstBody.node as! SKSpriteNode, Person: secondBody.node as! SKSpriteNode)
}
if firstBody.categoryBitMask == physicsCatagory.Score && secondBody.categoryBitMask == physicsCatagory.IceThree ||
firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.Score{
lifenumber++
if lifenumber == 1{
//person.texture
person.texture = SKTexture (imageNamed: "Flower#2")
}
if lifenumber == 2{
person.texture = SKTexture (imageNamed: "Flower #3")
}
if lifenumber == 3{
createButton()
// self.view?.presentScene(EndScene())
Died = true
}
}
}
func CollisionWithPerson (Ice: SKSpriteNode, Person: SKSpriteNode){
Person.removeFromParent()
}
func spawnThirdIce(){
var Ice = SKSpriteNode(imageNamed: "Ice")
Ice.zPosition = 2
Ice.setScale(1.5)
Ice.physicsBody = SKPhysicsBody(rectangleOfSize: Ice.size)
Ice.physicsBody?.categoryBitMask = physicsCatagory.IceThree
Ice.physicsBody?.contactTestBitMask = physicsCatagory.person | physicsCatagory.Score
Ice.physicsBody?.affectedByGravity = false
Ice.physicsBody?.dynamic = true
let randomXStart = random(min:CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea))
let randomXend = random(min:CGRectGetMinX(gameArea),max: CGRectGetMaxX(gameArea))
let startPoint = CGPoint(x: randomXStart, y: self.size.height * 1.2)
let endpoint = CGPoint(x: randomXend, y: -self.size.height * 0.2)
Ice.position = startPoint
let moveEnemy = SKAction.moveTo(endpoint, duration: 2.0)
let deleteEnemy = SKAction.removeFromParent()
let enemySequence = SKAction.sequence([moveEnemy , deleteEnemy])
Ice.runAction(enemySequence)
self.addChild(Ice)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches{
let location = touch.locationInNode(self)
if Died == true{
if restartButton.containsPoint(location){
restartScene()
}
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
if Died == true {
}
else{
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousTouch = touch.previousLocationInNode(self)
let ammountDragged = location.x - previousTouch.x
person.position.x += ammountDragged
if person.position.x > CGRectGetMaxX(gameArea) - person.size.width/2{
person.position.x = CGRectGetMaxX(gameArea) - person.size.width/2
}
if person.position.x < CGRectGetMinX(gameArea) + person.size.width/2{
person.position.x = CGRectGetMinX(gameArea) + person.size.width/2
}
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (currentTime - timeOfLastSpawn > timePerSpawn) {
spawnThirdIce()
self.timeOfLastSpawn = currentTime
}
}
}
Im am making a game in sprite kit that requires the user to move the player across the x axis to catch things. I am trying to make it impossible for the player to move off the screen because that looks bad. I have tried to do this with an if statement saying if it moves past a certain point teleport it back to the correct point but am not sure how to do this. That might be the right way to do this but i'm not sure. Please tell / show me what I should do to make this work. I will post the code below.
import SpriteKit
struct physicsCatagory {
static let person : UInt32 = 0x1 << 1
static let Ice : UInt32 = 0x1 << 2
static let IceTwo : UInt32 = 0x1 << 3
static let IceThree : UInt32 = 0x1 << 4
static let Score : UInt32 = 0x1 << 5
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var timeOfLastSpawn: CFTimeInterval = 0.0
var timePerSpawn: CFTimeInterval = 1.2
var scorenumber = Int()
var lifenumber = Int()
var SpeedNumber : Double = 0.5
var person = SKSpriteNode(imageNamed: "Person1")
let Score = SKSpriteNode()
var ScoreLable = SKLabelNode()
let BackGround = SKSpriteNode (imageNamed: "BackGround")
override func didMoveToView(view: SKView) {
self.scene?.backgroundColor = UIColor.blueColor()
physicsWorld.contactDelegate = self
self.scene?.size = CGSize(width: 640, height: 1136)
lifenumber = 0
SpeedNumber = 1
BackGround.size = CGSize(width: self.frame.width, height: self.frame.height)
BackGround.position = CGPointMake(self.size.width / 2, self.size.height / 2)
BackGround.zPosition = -5
self.addChild(BackGround)
Score.size = CGSize(width: 648, height: 1)
Score.position = CGPoint(x: 320, y: -90)
Score.physicsBody = SKPhysicsBody(rectangleOfSize: Score.size)
Score.physicsBody?.affectedByGravity = false
Score.physicsBody?.dynamic = false
Score.physicsBody?.categoryBitMask = physicsCatagory.Score
Score.physicsBody?.collisionBitMask = 0
Score.physicsBody?.contactTestBitMask = physicsCatagory.IceThree
Score.color = SKColor.blueColor()
self.addChild(Score)
person.zPosition = 1
person.position = CGPointMake(self.size.width/2, self.size.height/10)
person.setScale(0.32)
person.physicsBody = SKPhysicsBody (rectangleOfSize: CGSize(width: 40, height: 50))
person.physicsBody?.affectedByGravity = false
person.physicsBody?.categoryBitMask = physicsCatagory.person
person.physicsBody?.contactTestBitMask = physicsCatagory.Ice
person.physicsBody?.collisionBitMask = physicsCatagory.Ice
person.physicsBody?.dynamic = false
ScoreLable = SKLabelNode(fontNamed: "Zapfino")
ScoreLable.position = CGPoint(x: self.frame.width / 2, y: 1000)
ScoreLable.text = "\(scorenumber)"
ScoreLable.fontColor = UIColor.yellowColor()
ScoreLable.fontSize = 100
ScoreLable.fontName = "Zapfino "
self.addChild(ScoreLable)
self.addChild(person)
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.person && secondBody.categoryBitMask == physicsCatagory.IceThree || firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.person{
scorenumber++
if scorenumber == 20 {
timePerSpawn = 1.0
}
if scorenumber == 40{
timePerSpawn = 0.89
}
if scorenumber == 60{
timePerSpawn = 0.6
}
if scorenumber == 80{
timePerSpawn = 0.5
}
if scorenumber == 100{
timePerSpawn = 0.4
}
if scorenumber == 120{
timePerSpawn = 0.3
}
ScoreLable.text = "\(scorenumber)"
CollisionWithPerson(firstBody.node as! SKSpriteNode, Person: secondBody.node as! SKSpriteNode)
}
if firstBody.categoryBitMask == physicsCatagory.Score && secondBody.categoryBitMask == physicsCatagory.IceThree ||
firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.Score{
lifenumber++
if lifenumber == 1{
//person.texture
person.texture = SKTexture (imageNamed: "Flower#2")
}
if lifenumber == 2{
person.texture = SKTexture (imageNamed: "Flower #3")
}
if lifenumber == 3{
self.view?.presentScene(EndScene())
}
}
}
func CollisionWithPerson (Ice: SKSpriteNode, Person: SKSpriteNode){
Person.removeFromParent()
}
func spawnThirdIce(){
var Ice = SKSpriteNode(imageNamed: "Ice")
Ice.zPosition = 2
Ice.setScale(0.9)
Ice.physicsBody = SKPhysicsBody(rectangleOfSize: Ice.size)
Ice.physicsBody?.categoryBitMask = physicsCatagory.IceThree
Ice.physicsBody?.contactTestBitMask = physicsCatagory.person | physicsCatagory.Score
Ice.physicsBody?.affectedByGravity = false
Ice.physicsBody?.dynamic = true
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 20
let SpawnPoint = UInt32(MaxValue - MinValue)
Ice.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
self.addChild(Ice)
let action = SKAction.moveToY(-85, duration: 2.0)
let actionDone = SKAction.removeFromParent()
Ice.runAction(SKAction.sequence([action,actionDone]))
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousTouch = touch.previousLocationInNode(self)
let ammountDragged = location.x - previousTouch.x
person.position.x += ammountDragged
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (currentTime - timeOfLastSpawn > timePerSpawn) {
spawnThirdIce()
self.timeOfLastSpawn = currentTime
}
}
}
You might do something like:
if node.position.x > scene.width {
node.position.x = scene.width
}
if node.position.x < 0 {
node.position.x = 0
}
I’m new to programming and I recently did a tutorial that I found online to make a endless frogger game. The tutorial person didn’t show me how to do the score label and I have tried endlessly to find a video tutorial that will show me how to position a score label in the top left corner. I have tried using this code:
label.horizontalAlignmentMode = .Left
label.position = CGPoint(x:0.0, y:self.size.height)
but I have had no luck, It does not show up in the top left corner. So i tried another way to get it positioned in the corner and I played around with the values and ended up with this
scoreLabel.position = CGPointMake(frame.size.width / -2.231, frame.size.height / 2.29)
which positions it perfectly in the corner of the screen on the simulator, but not for all the devices. I have a seperate swift file for my score label with is here:
import Foundation
import SpriteKit
import UIKit
class Score: SKLabelNode {
var number = 0
init (num: Int) {
super.init()
fontColor = UIColor.whiteColor()
fontName = "Helvetica"
fontSize = 150.0
number = num
text = "\(num)"
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func addOneToScore() {
number++
text = "\(number)"
}
}
I have a world node that has a player inside it and the camera position is focused on the player. I have provided my game Scene class for you to have a look at. All I want is to be able to position a score label in the top left or top right corner of the screen for all devices.
import SpriteKit
enum BodyType:UInt32 {
case player = 1
case roadObject = 2
case waterObject = 4
case water = 8
case road = 16
}
enum LevelType:UInt32 {
case road, water
}
class GameScene: SKScene, SKPhysicsContactDelegate {
//recongises swipe and tap gestures
let TapUpRec = UITapGestureRecognizer()
let swipeRightRec = UISwipeGestureRecognizer()
let swipeLeftRec = UISwipeGestureRecognizer()
let swipeDownRec = UISwipeGestureRecognizer()
//defines the attributes for level units.
var levelUnitCounter:CGFloat = 1 // Not sure, i think it starts the frog further up.
var levelUnitWidth:CGFloat = 0 //will be screenwidth
var levelUnitHeight:CGFloat = 50 // changes the height of the level units
var initialUnits:Int = 10 // tells how many level units will be spawned as you climb.
//defines the world node for the scene & defines the player image in a constant.
var screenWidth:CGFloat = 0
var screenHeight:CGFloat = 0
let worldNode:SKNode = SKNode()
let thePlayer:Player = Player(imageNamed: "Frog")
var increment:CGFloat = 0
// variables with boolean values to check if the player is on certain types of levels or objects.
var onLilyPad:Bool = false
var onWater:Bool = false
var onRoad:Bool = false
//same variable that checks if the player is dead.
var isDead:Bool = false
//variable that links with the swift file called object and (maybe passes it through :( )
var waterObject:Object?
//creates a constant that will be the starting point of the player
let startingPosition:CGPoint = CGPointMake(0, 0)
var direction:CGFloat = 1
// var nodeToMove:Object?
// var moveInProgress:Bool = false
override func didMoveToView(view: SKView) {
/* Setup your scene here */
// Defines the view as the target defines the direction and calls the function (in red)
swipeRightRec.addTarget(self, action:"swipedRight")
swipeRightRec.direction = .Right
self.view!.addGestureRecognizer(swipeRightRec)
swipeLeftRec.addTarget(self, action: "swipedLeft")
swipeLeftRec.direction = .Left
self.view!.addGestureRecognizer(swipeLeftRec)
TapUpRec.addTarget(self, action: "tapUp")
self.view!.addGestureRecognizer(TapUpRec)
swipeDownRec.addTarget(self, action: "swipedDown")
swipeDownRec.direction = .Down
self.view!.addGestureRecognizer(swipeDownRec)
//makes the background colour black and defines the screenWidth variable as sk view boundry
self.backgroundColor = SKColor.greenColor()
screenWidth = self.view!.bounds.width
screenHeight = self.view!.bounds.height
//makes the world able to have objects that can collide (I Think)
physicsWorld.contactDelegate = self
//physicsWorld.gravity = CGVector(dx:0.3, dy:0.0)
//creates the world node point to be in the middle of the screen
self.anchorPoint = CGPointMake(0.5, 0.5)
addChild(worldNode)
let scoreLabel = Score(num: 0)
scoreLabel.horizontalAlignmentMode = .Left
scoreLabel.position = CGPoint(x:0.0, y:self.size.height)
addChild(scoreLabel)
//scoreLabel.position = CGPointMake(frame.size.width / -2.231, frame.size.height / 2.29)
// let highscoreLabel = Score(num: 0)
//adds a child node to the world node (so the player is playing within the world node)
worldNode.addChild(thePlayer)
thePlayer.position = startingPosition
thePlayer.zPosition = 500 // zPosition is the order the player will be displayed.
addLevelUnits() //runs the func that addds levelUnits.
}
func addScoreLabels(){
}
// this function along with the next three run the swipe and tap gesture actions.
func swipedRight(){
let amountToMove:CGFloat = levelUnitHeight
let move:SKAction = SKAction.moveByX(amountToMove, y: 0, duration: 0.1)
thePlayer.runAction(move) // links the action with the players
}
func swipedLeft(){
let amountToMove:CGFloat = levelUnitHeight
let move:SKAction = SKAction.moveByX(-amountToMove, y: 0, duration: 0.1)
thePlayer.runAction(move)
}
func swipedDown(){
let amountToMove:CGFloat = levelUnitHeight
let move:SKAction = SKAction.moveByX(0, y: -amountToMove, duration: 0.1)
thePlayer.runAction(move)
// clearNodes()
}
func tapUp(){
let amountToMove:CGFloat = levelUnitHeight
let move:SKAction = SKAction.moveByX(0, y: amountToMove, duration: 0.1)
thePlayer.runAction(move)
clearNodes()
}
func resetLevel(){
//searches the world node for child nodes that have the name "levelUnit"
worldNode.enumerateChildNodesWithName("levelUnit") {
node, stop in
//removes all the child nodes from the parent.
node.removeFromParent()
}
levelUnitCounter = 1
addLevelUnits()
}
func addLevelUnits() {
for (var i = 0; i < initialUnits; i++ ) {
createLevelUnit()
}
}
func createLevelUnit() {
if (direction == 1) {
direction = -1
} else {
direction = 1
}
print(direction )
let levelUnit:LevelUnit = LevelUnit()
worldNode.addChild(levelUnit)
levelUnit.zPosition = -1
levelUnit.levelUnitWidth = screenWidth
levelUnit.levelUnitHeight = levelUnitHeight
levelUnit.direction = direction
levelUnit.setUpLevel()
levelUnit.position = CGPointMake( 0 , levelUnitCounter * levelUnitHeight) // counts the level unit and multiplies it so t goes above the last level unit.
levelUnitCounter++ //constantly makes the level units appear.
}
func clearNodes(){
var nodeCount:Int = 0
worldNode.enumerateChildNodesWithName("levelUnit") {
node, stop in
let nodeLocation:CGPoint = self.convertPoint(node.position, fromNode: self.worldNode) //converts cordinates of level units with the world node.
if ( nodeLocation.x < -(self.screenWidth / 2) - self.levelUnitWidth ) { // checks to see if the node is off the screen.
node.removeFromParent()
print("levelUnit was removed", terminator: "")
} else {
nodeCount++
}
}
print( "levelUnits in the scene is \(nodeCount)")
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
worldNode.enumerateChildNodesWithName("levelUnit"){
node, stop in
let levelUnit:LevelUnit = node as! LevelUnit //cast as an actual LevelUnit class
levelUnit.enumerateChildNodesWithName("obstacle"){
node, stop in
let obstacle:Object = node as! Object //cast as an actual Object class
obstacle.update()
let obstacleLocation:CGPoint = self.convertPoint(obstacle.position, fromNode: levelUnit)
let buffer:CGFloat = 150
if (obstacleLocation.x < -(self.screenWidth / 2) - buffer) { //changes the speed of object when it reaches middle of the screen.
levelUnit.changeSpeed()
obstacle.position = CGPointMake(obstacle.position.x + (self.screenWidth + (buffer * 2)) , obstacle.position.y)
} else if (obstacleLocation.x > (self.screenWidth / 2) + buffer ) { //changes the speed of the object again.
levelUnit.changeSpeed()
obstacle.position = CGPointMake(obstacle.position.x - (self.screenWidth + (buffer * 2)) , obstacle.position.y)
}
}
}
// creates new level units if always centering horizontally
let nextTier:CGFloat = (levelUnitCounter * levelUnitHeight) - (CGFloat(initialUnits) * levelUnitHeight)
if (thePlayer.position.y > nextTier) {
createLevelUnit()
}
//deal with the players location....
let playerLocation:CGPoint = self.convertPoint(thePlayer.position, fromNode: worldNode)
var repositionPlayer:Bool = false
if ( playerLocation.x < -(screenWidth / 2)) {
repositionPlayer = true
} else if ( playerLocation.x > (screenWidth / 2)) {
repositionPlayer = true
} else if ( playerLocation.y < 0) {
repositionPlayer = true
} else if ( playerLocation.y > screenHeight) {
repositionPlayer = true
}
if (repositionPlayer == true) {
/* great code for reference later */
killPlayer()
thePlayer.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
}
}
// this function centers the world node on teh player.
override func didSimulatePhysics() {
self.centerOnNode(thePlayer)
if (onLilyPad == true) {
thePlayer.position = CGPointMake(thePlayer.position.x + waterObject!.xAmount , thePlayer.position.y)
}
}
//centers the camera on the node world.
func centerOnNode(node:SKNode) {
let cameraPositionInScene:CGPoint = self.convertPoint(node.position, fromNode: worldNode)
worldNode.position = CGPoint(x: worldNode.position.x , y:worldNode.position.y - cameraPositionInScene.y )
}
func didBeginContact(contact: SKPhysicsContact) {
// Defines the contact between objects.
/// lily pad
if (contact.bodyA.categoryBitMask == BodyType.player.rawValue && contact.bodyB.categoryBitMask == BodyType.waterObject.rawValue ) {
waterObject = contact.bodyB.node!.parent as? Object
onLilyPad = true
self.removeActionForKey("checkOnLilyPad")
let waterObjectLocation:CGPoint = self.convertPointToView(waterObject!.position)
thePlayer.position = self.convertPointFromView(waterObjectLocation)
} else if (contact.bodyA.categoryBitMask == BodyType.waterObject.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue ) {
waterObject = contact.bodyA.node!.parent as? Object
onLilyPad = true
self.removeActionForKey("checkOnLilyPad")
let waterObjectLocation:CGPoint = self.convertPointToView(waterObject!.position)
thePlayer.position = self.convertPointFromView(waterObjectLocation)
}
//// check on water
if (contact.bodyA.categoryBitMask == BodyType.player.rawValue && contact.bodyB.categoryBitMask == BodyType.water.rawValue ) {
onRoad = false
onWater = true
waitAndThenCheckOnLilyPad()
} else if (contact.bodyA.categoryBitMask == BodyType.water.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue ) {
onRoad = false
onWater = true
waitAndThenCheckOnLilyPad()
}
//// cars
if (contact.bodyA.categoryBitMask == BodyType.player.rawValue && contact.bodyB.categoryBitMask == BodyType.roadObject.rawValue ) {
killPlayer()
} else if (contact.bodyA.categoryBitMask == BodyType.roadObject.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue ) {
killPlayer()
}
//// check on road
if (contact.bodyA.categoryBitMask == BodyType.player.rawValue && contact.bodyB.categoryBitMask == BodyType.road.rawValue ) {
onRoad = true
onWater = false
onLilyPad = false
} else if (contact.bodyA.categoryBitMask == BodyType.road.rawValue && contact.bodyB.categoryBitMask == BodyType.player.rawValue ) {
onRoad = true
onWater = false
onLilyPad = false
}
}
func waitAndThenCheckOnLilyPad() {
let wait:SKAction = SKAction.waitForDuration(0.1)
let check:SKAction = SKAction.runBlock(checkIfOnLilyPad)
let seq:SKAction = SKAction.sequence([wait, check])
self.runAction(seq, withKey:"checkOnLilyPad")
}
func checkIfOnLilyPad() {
if ( onRoad == false) {
if ( onWater == true && onLilyPad == false) {
killPlayer()
} else if ( onWater == true && onLilyPad == true) {
print("safely on water")
// maybe play sound here
}
}
}
func didEndContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch (contactMask) {
case BodyType.waterObject.rawValue | BodyType.player.rawValue:
onLilyPad = false
waterObject = nil
onWater = true
waitAndThenCheckOnLilyPad()
default:
return
}
}
func killPlayer() {
if ( isDead == false) {
isDead = true
let fadeOut:SKAction = SKAction.fadeAlphaTo(0, duration: 0.2)
let move:SKAction = SKAction.moveTo(startingPosition, duration: 0.2)
let block:SKAction = SKAction.runBlock(revivePlayer)
let seq:SKAction = SKAction.sequence([fadeOut, move, block])
thePlayer.runAction(seq)
}
}
func revivePlayer() {
isDead = false
onRoad = false
onWater = false
onLilyPad = false
let fadeOut:SKAction = SKAction.fadeAlphaTo(0, duration: 0.2)
let block:SKAction = SKAction.runBlock(resetLevel)
let fadeIn:SKAction = SKAction.fadeAlphaTo(1, duration: 0.2)
let seq:SKAction = SKAction.sequence([fadeOut, block, fadeIn])
worldNode.runAction(seq)
let wait:SKAction = SKAction.waitForDuration(1)
let fadeIn2:SKAction = SKAction.fadeAlphaTo(1, duration: 0.2)
let seq2:SKAction = SKAction.sequence([wait , fadeIn2])
thePlayer.runAction(seq2)
}
}
If other solutions don't work, you could try something like this:
import UIKit
var screenSize = UIScreen.mainscreen().bounds
var screenWidth = screenSize.width
var screenHeight = screenSize.height
This will get the dimensions of the screen and store them in the screenHeight and screenWidth variables.
Then when you call scoreLabel.position you could say
scoreLabel.position = CGPoint(x: screenWidth / 10, y: screenHeight / 15)
Or something like that but experiment with the math until it is in the correct position.
If this doesn't work you may also need to declare the size or scoreLabel. Let me know if it works.
Swift 4 and Xcode 9 code:
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
self.menuButton.position = CGPoint(x: screenWidth / 10, y: screenHeight / 15)
I think you are on the right track with:
let scoreLabel = Score(num: 0)
scoreLabel.horizontalAlignmentMode = .Left
scoreLabel.position = CGPoint(x:0.0, y:self.size.height)
addChild(scoreLabel)
But I think you also need to add
scoreLabel.verticalAlignmentMode = .Top
as the default is.Baseline which would cause it draw most off the screen.