Really Need Help About UITouch (Sprite Kit) - swift

i Like to create left side and right side that when i touch them , A bird will fly to the left or right !
I create a bird
var birdtexture = SKTexture(imageNamed: "flappy1.png")
bird = SKSpriteNode(texture: birdtexture)
bird.position
bird.size
bird.physicsBody = SKPhysicsBody(circleOfRadius: bird.size.width/2)
bird.physicsBody?.dynamic = true
bird.physicsBody?.allowsRotation = false
self.addChild(bird)
Then i create left node
var groundleft = SKSpriteNode()
groundleft.position = CGPoint(x: 0, y: 50)
groundleft.size = CGSize(width: 500, height: 100)
groundleft.color = UIColor(red: 7, green: 5, blue: 7, alpha: 20)
groundleft.physicsBody = SKPhysicsBody(rectangleOfSize:CGSizeMake(self.size.width, 100))
groundleft.physicsBody?.dynamic = true
groundleft.physicsBody?.affectedByGravity = false
groundleft.name = "toleft"
self.addChild(groundleft)
then i go to TouchBegan
let touch = touches.first as! UITouch
let touchLocation = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(touchLocation)
if(touchedNode.name == "toleft"){
bird.physicsBody?.velocity = CGVectorMake(0, 0)
bird.physicsBody?.applyImpulse(CGVectorMake(-10, 100))
}
why it didnt work . Is my method wrong ? Is there any another way for me to make it work ??
please help , so many thanks

In your touchesBegan method try this:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if let touch = touches.first as? UITouch {
let touchLocation = touch.locationInNode(self)
if nodeAtPoint(touchLocation) == groundleft { //your sprite node
//do something
}
}
super.touchesBegan(touches , withEvent:event)
}

Related

How to force on touch.location to work only in special place on screen?

that is my first question here so - Hello Word.
I have a small problem with my code. I want to force on this program to make balls appear only if you will touch over and equal y: 650 point and boxes to appear only if you will touch under y: 650 point. x position makes here no role.
That is my code:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let objects = nodes(at: location)
if objects.contains(editLabel) {
editingMode = !editingMode
} else {
if editingMode {
let size = CGSize(width: GKRandomDistribution(lowestValue: 16, highestValue: 128).nextInt(), height: 16)
let box = SKSpriteNode(color: RandomColor(), size: size)
box.zRotation = RandomCGFloat(min: 0, max: 3)
box.position = location
box.physicsBody = SKPhysicsBody(rectangleOf: box.size)
box.physicsBody!.isDynamic = false
addChild(box)
} else {
let ball = SKSpriteNode(imageNamed: "ballRed")
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width / 2.0)
ball.physicsBody!.contactTestBitMask = ball.physicsBody!.collisionBitMask
ball.physicsBody!.restitution = 0.4
ball.position = location
ball.name = "ball"
addChild(ball)
}
}
}
}
Looking forward for help :)
For me this worked:
ball.position = location
if (location.y < 500) {
ball.position.y = 500
}

Swift Sprite Kit Began Touch Function

Im messing around with an xcode project and I am trying to make a red ball SKShapeNode move around when I touch it. My own source code in the touch began class is not doing the trick. What is the flaw with my code and what do I need to do in order to fix it.
import SpriteKit
class GameScene: SKScene {
//Rectangle Skeletions
var leftWallRect = CGRect(x: 0, y: 0, width: 40, height: 1000)
var ball = SKShapeNode(circleOfRadius: 25);
override func didMoveToView(view: SKView) {
// Declare the Sprites in your scene
var ball = SKShapeNode(circleOfRadius: 25);
let leftWall = SKShapeNode(rect: leftWallRect);
let rightWall = SKShapeNode(rect: leftWallRect);
let pin = SKSpriteNode(imageNamed: "pin");
// Ball Properties
ball.strokeColor = UIColor.blackColor()
ball.fillColor = UIColor.redColor()
ball.position = CGPointMake(self.frame.width / 2 , self.frame.height / 4 - 100 )
self.addChild(ball)
// Left Wall Properties
leftWall.fillColor = UIColor.purpleColor()
leftWall.strokeColor = UIColor.blackColor()
leftWall.position = CGPointMake(self.frame.size.width / 3 - 45, self.frame.size.height / 2 - 400)
self.addChild(leftWall)
//Right Wall Properties
rightWall.fillColor = UIColor.purpleColor()
rightWall.strokeColor = UIColor.blackColor()
rightWall.position = CGPointMake(self.frame.size.width / 2 + 175, self.frame.size.height / 2 - 400)
self.addChild(rightWall)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
let touch = touches.first as! UITouch
let touchLocation = touch.locationInNode(self)
if touchLocation == ball.position{
ball.position = touchLocation
println("Touches");
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
LOL wow, this is a funny one, if touchLocation == ball.position I would be impressed if you can hit the exact pixel location of your ball. What you want is this:
let touch = touches.first as! UITouch
let touchLocation = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(touchLocation)
if touchedNode == ball{
...
But personally, what I would do is make a sub class of SKSpriteNode, and do your ball's touch code inside this child's touch routine

Sprite-Kit Began Touch Error

Im trying to create a method that when I touch a sprite named StartSprite Through my touchesbegan function it will print out something in my console. But for some reason when I click on the sprite nothing happens. This is my code.
import SpriteKit
class GameScene: SKScene {
let StartSprite = SKSpriteNode(imageNamed: "startLabel")
override func didMoveToView(view: SKView) {
let borderRect = CGRect(x: 0 , y: 0 , width: 400, height: 725)
let welcomeLabel = SKLabelNode(fontNamed: "welcome");
welcomeLabel.text = "Welcome";
welcomeLabel.fontColor = UIColor.whiteColor()
welcomeLabel.fontSize = 65
welcomeLabel.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2 + 150)
self.addChild(welcomeLabel)
//StartLabel
let rectangleBorder = SKShapeNode(rect: borderRect)
rectangleBorder.position = CGPoint(x: 315, y: 25)
rectangleBorder.strokeColor = UIColor.whiteColor()
self.addChild(rectangleBorder)
self.backgroundColor = UIColor.grayColor()
StartSprite.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
self.addChild(StartSprite)
println("Hello")
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let touchLocation = touch.locationInNode(self)
if touchLocation == StartSprite.position{
println("Touches")
}
}
}
Your code requires that you touch exactly the one pixel at StartSprite.position.
Try this instead:
let p = StartSprite.convertPoint(touchLocation, fromNode: self)
if StartSprite.containsPoint(p) {
print("touched StartSprite")
}
If you're going to add more buttons, you might want to do this instead:
let target = nodeAtPoint(touchLocation)
if target == StartSprite {
print("touched StartSprite"
}
// check other buttons here

SkNode name nil on TouchesBegan with Sprite Kit

I've got 4 SKNode's in my Scene.
In TouchesBegan method, one of them has nil as name, even if I've assigned it on instantiation.
After touching another node, that node shows the correct name.
What could be the problem?
I'm a newbie with Sprite Kit Framework.
Here are initializations.
var rightPortBorder = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: 10, height: UIScreen.mainScreen().bounds.height/5))
rightPortBorder.position = CGPoint(x: UIScreen.mainScreen().bounds.width-5, y: (UIScreen.mainScreen().bounds.size.height/2))
rightPortBorder.name = rightPortCategoryName
var rightPortBody = SKPhysicsBody(rectangleOfSize: rightPortBorder.size)
rightPortBody.friction = 0.0
rightPortBody.dynamic = false
rightPortBody.contactTestBitMask = portCategory
rightPortBorder.physicsBody = rightPortBody
rightPort = rightPortBorder
self.addChild(rightPortBorder)
var leftPortBorder = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: 10, height: UIScreen.mainScreen().bounds.height/5))
leftPortBorder.position = CGPoint(x: 5, y: (UIScreen.mainScreen().bounds.size.height/2))
leftPortBorder.name = leftPortCategoryName
var leftPortBody = SKPhysicsBody(rectangleOfSize: leftPortBorder.size)
leftPortBody.friction = 0.0
leftPortBody.dynamic = false
leftPortBody.contactTestBitMask = portCategory
leftPortBorder.physicsBody = leftPortBody
leftPort = leftPortBorder
self.addChild(leftPortBorder)
var topPortBorder = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: UIScreen.mainScreen().bounds.height/5, height: 10))
topPortBorder.position = CGPoint(x: (UIScreen.mainScreen().bounds.size.width/2), y: UIScreen.mainScreen().bounds.size.height-5)
topPortBorder.name = topPortCategoryName
var topPortBody = SKPhysicsBody(rectangleOfSize: topPortBorder.size)
topPortBody.friction = 0.0
topPortBody.dynamic = false
topPortBody.contactTestBitMask = portCategory
topPortBorder.physicsBody = topPortBody
topPort = topPortBorder
self.addChild(topPortBorder)
var bottomPortBorder = SKSpriteNode(color: UIColor.yellowColor(), size: CGSize(width: UIScreen.mainScreen().bounds.height/5, height: 10))
bottomPortBorder.position = CGPoint(x: (UIScreen.mainScreen().bounds.size.width/2), y: 5)
bottomPortBorder.name = bottomPortCategoryName
var bottomPortBody = SKPhysicsBody(rectangleOfSize: bottomPortBorder.size)
bottomPortBody.friction = 0.0
bottomPortBody.dynamic = false
bottomPortBody.contactTestBitMask = portCategory
bottomPortBorder.physicsBody = bottomPortBody
bottomPort = bottomPortBorder
self.addChild(bottomPortBorder)
And here's touches began method
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
var touch = touches.first as! UITouch
var touchLocation = touch.locationInNode(self)
if let body = physicsWorld.bodyAtPoint(touchLocation) {
if body.node!.name == rightPortCategoryName {
println("Began touch on right paddle")
resetAllFlagsTouch()
isFingerOnRightPort = true
}
else if body.node!.name == topPortCategoryName {
println("Began touch on top paddle")
resetAllFlagsTouch()
isFingerOnTopPort = true
}
else if body.node!.name == bottomPortCategoryName {
println("Began touch on bottom paddle")
resetAllFlagsTouch()
isFingerOnBottomPort = true
}
if body.node!.name == leftPortCategoryName {
println("Began touch on left paddle")
resetAllFlagsTouch()
isFingerOnLeftPort = true
}
}
}
I solved my problem editing the touchesBegan method: instead of getting the node from the world, I used the method locationInNode to get my node.
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
var touch = touches.first as! UITouch
var touchLocation = touch.locationInNode(self)
var node = self.nodeAtPoint(touchLocation)
if node.name == rightPortCategoryName {
println("Began touch on right paddle")
resetAllFlagsTouch()
isFingerOnRightPort = true
}
else if node.name == topPortCategoryName {
println("Began touch on top paddle")
resetAllFlagsTouch()
isFingerOnTopPort = true
}
else if node.name == bottomPortCategoryName {
println("Began touch on bottom paddle")
resetAllFlagsTouch()
isFingerOnBottomPort = true
}
if node.name == leftPortCategoryName {
println("Began touch on left paddle")
resetAllFlagsTouch()
isFingerOnLeftPort = true
}
}

Stopping the countUp speed rate

I just started to learn Swift and Sprite Kit. I need assistance with the following code.
I have a countUp that when the ball is touched the countUp starts but my problem is that every time I tap the ball the rate of speed in the countUp increases. I want the CountUp to be stable. Any help will be appreciated.
class Game: SKScene {
var Ball = SKSpriteNode(imageNamed: "Red.png")
var QuitOption = SKLabelNode()
var ScoreLabel = SKLabelNode()
var timescore = Int()
var timesecond = Int()
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.blackColor() // background for the display
self.physicsWorld.gravity = CGVectorMake(0, -9.8)
let SceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
SceneBody.friction = 0
self.physicsBody = SceneBody
Ball.size = CGSize(width: 120, height: 120)
Ball.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height*0.7)
Ball.physicsBody = SKPhysicsBody(circleOfRadius: 60)
Ball.physicsBody?.affectedByGravity = true
Ball.physicsBody?.restitution = 0.5
Ball.physicsBody?.linearDamping = 0
Ball.name = "Ball"
self.addChild(Ball)
QuitOption.text = "Quit"
QuitOption.fontName = "Noteworthy-Light"
QuitOption.fontColor = SKColor.greenColor()
QuitOption.fontSize = 35
QuitOption.position = CGPoint(x: self.frame.size.width/2 - 160, y: self.frame.size.height*1 - 110)
QuitOption.name = "Quit"
addChild(QuitOption)
ScoreLabel = SKLabelNode(fontNamed: "Noteworthy-Light")
ScoreLabel.fontSize = 50 // The + will move it to the right side and - to the left side for more accuracy.
ScoreLabel.position = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/4 + 400) // position of ScoreLabelNode
ScoreLabel.name = "Score+"
ScoreLabel.hidden = false
self.addChild(ScoreLabel)
}
// Making the ball jump after user touches ball
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
var touch = touches.first as! UITouch
var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
if (node.name == "Quit"){
let myScene = GameScene(size: self.size)
myScene.scaleMode = scaleMode
let reveal = SKTransition.fadeWithDuration(1)
self.view?.presentScene(myScene, transition: reveal)
}
if (node.name == "Ball"){
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
Ball.physicsBody?.allowsRotation = true
Ball.physicsBody?.velocity = CGVectorMake(0, 0)
Ball.physicsBody?.applyImpulse(CGVectorMake(0, 100))
}
}
var actionwait = SKAction.waitForDuration(0.5)
var actionrun = SKAction.runBlock({
self.timescore++
self.timesecond++
if self.timesecond == 60 {self.timesecond = 0}
self.ScoreLabel.text = " \(self.timescore/60):\(self.timesecond)"})
ScoreLabel.runAction(SKAction.repeatActionForever(SKAction.sequence([actionwait,actionrun])))
}
}
I guess that's happening because you are running same block over and over again after every touch. To ensure you run block only once, you can use some Bool indicator and after the first run, set its value appropriately, like this:
if(!self.locked){
self.locked = true // at start, this value should be false
var actionrun = SKAction.runBlock({
self.timescore++
self.timesecond++
if self.timesecond == 60 {self.timesecond = 0}
self.ScoreLabel.text = " \(self.timescore/60):\(self.timesecond)"})
ScoreLabel.runAction(SKAction.repeatActionForever(SKAction.sequence([actionwait,actionrun])))
}
}
Something as an addition to this topic and for future readers could be found here.