touch moking sprite by tap not swipe swift - ios

I have a block in my code where the sprite will only move if you tap the screen. I would like to have this behaviour when I swipe up or down instead. Here is my code
import SpriteKit
import UIKit
class GameScene: SKScene {
var porker:Porker!
var touchLocation = CGFloat()
var gameOver = false
override func didMoveToView(view: SKView) {
addBG()
addPig()
}
func addBG() {
let bg = SKSpriteNode(imageNamed: "bg");
addChild(bg)
}
func addPig() {
let Pig = SKSpriteNode(imageNamed: "pig")
porker = Porker(guy:Pig)
addChild(Pig)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches{
if !gameOver {
touchLocation = (touch.locationInView(self.view!).y * -1) + (self.size.height/2)
}
}
let moveAction = SKAction.moveToY(touchLocation, duration: 0.5)
moveAction.timingMode = SKActionTimingMode.EaseOut
porker.guy.runAction(moveAction)
}
}
func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}

Replace touchesBegan with this code:
// Store the start touch position
let yTouchCurrentPosition = 0.0
let yTouchDistance = 0.0
let yTouchStartPosition = 0.0
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
yTouchStartPosition = touch.locationInNode(self).y
}
}
// Calculate the distance of the touch movement
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
yTouchCurrentPosition = touch.locationInNode(self).y
yTouchDistance = yTouchStartPosition - yTouchCurrentPosition
}
}
// Reset all movement states and move sprite
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
yTouchCurrentPosition = 0.0
yTouchDistance = 0.0
yTouchStartPosition = 0.0
let moveAction = SKAction.moveToY(CGPoint(porker.guy.location.x, porker.guy.location.y + yTouchDistance), duration: 0.5)
moveAction.timingMode = SKActionTimingMode.EaseOut
porker.guy.runAction(moveAction)
}

Related

How to change the clickable area of a SpriteKit Sprite Node from rectangle to circle?

I have a play button on my menu screen but it detects touches in the area of the entire rectangle instead of just the circle. Is there any way to change the clickable bounds to a circle either within xcode?
Or will i have to programmatically do it within initialization or a function:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {}
Just add it programmatically to the GameScene.
var playButton: SKSpriteNode!
override func didMove(to view: SKView) {
playButton = SKSpriteNode(imageNamed: "playButton")
playButton.name = "playButton"
playButton.position = CGPoint(x: self.frame.midX , y: self.frame.midY)
playButton.zPosition = 0
playButton.alpha = 1
addChild(playButton)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
let pos = touch.location(in: self)
let node = self.atPoint(pos)
if node.name == "playButton"{
//Do Something
}
}

Swift 3/SpriteKit - Draw independent shapes with finger

I'm a beginner following the tutorial here for drawing shapes in Swift.
import SpriteKit
class GameScene: SKScene {
var activeSlice: SKShapeNode!
var activeSlicePoints = [CGPoint]()
override func didMove(to view: SKView) {
createSlices()
}
func createSlices() {
activeSlice = SKShapeNode()
activeSlice.strokeColor = UIColor(red: 1, green: 0.9, blue: 0, alpha: 1)
activeSlice.lineWidth = 9
addChild(activeSlice)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if let touch = touches.first {
let location = touch.location(in: self)
activeSlicePoints.append(location)
redrawActiveSlice()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let location = touch.location(in: self)
activeSlicePoints.append(location)
redrawActiveSlice()
}
override func touchesEnded(_ touches: Set<UITouch>?, with event: UIEvent?) {
}
func redrawActiveSlice() {
let path = UIBezierPath()
path.move(to: activeSlicePoints[0])
for i in 1 ..< activeSlicePoints.count {
path.addLine(to: activeSlicePoints[i])
}
activeSlice.path = path.cgPath
}
}
With this code, when you release the finger then touch again to draw, you have a line connecting the two shapes.
I would like to draw independent shapes.
Perhaps by modifying the code so that for each instance of touchesEnded(), the array of points that represents the shape is stored in a multidimensional array, and by creating an array of points for each new instance of touchesBegan()?
Thank you for your help.
It's something like
override func touchesEnded(_ touches: Set<UITouch>?, with event: UIEvent?) {
createSlices()
}

Node not moving

I'm trying to throw a node around the screen, I've taken the below code but nothing actually happens.
When the scene loads the node spawns in the middle of the screen then drops to the bottom.
The code was taken from elsewhere in the site and granted it was a bit old so I'm assuming I'm missing something?
var sprite: SKSpriteNode!
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
sprite = SKSpriteNode(color: UIColor.red, size: CGSize(width: 50, height: 50))
sprite.physicsBody = SKPhysicsBody(rectangleOf: sprite.size)
sprite.position = CGPoint(x: 50.0, y: 50.0)
self.addChild(sprite)
}
func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.location(in: self)
if sprite.frame.contains(location) {
touchPoint = location
touching = true
}
}
}
func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.location(in: self)
touchPoint = location
}
}
func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
touching = false
}
func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
touching = false
}
func update(currentTime: TimeInterval) {
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
sprite.physicsBody!.velocity = velocity
}
}
}

How can I stop moving object when I touch to object?

My game app has randomly moving object. I want to stop that and print some words on the screen when I touch/catch that. But I don't know what can I do this in gamescene.swift page. What should I write in touchesBegan? Here is my code :
import SpriteKit
let BallCategoryName = "ball"
class GameScene: SKScene {
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVectorMake(15, 15)
let ball = childNodeWithName(BallCategoryName) as! SKSpriteNode
ball.physicsBody!.applyImpulse(CGVectorMake(10, -10))
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch = touches.first as! UITouch
}
}
First you need to put the variable ball outside didMoveToView:
class GameScene: SKScene {
let ball = childNodeWithName(BallCategoryName) as! SKSpriteNode
override func didMoveToView(view: SKView) {
[...]
}
}
touchesBegan:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch:AnyObject in touches{
let location = (touch as! UITouch).locationInNode(self)
let nodeTouched = nodeAtPoint(location)
//Detect if the ball is touched
if(nodeTouched == ball){
//Do something
}
}
}

Throwing an object with SpriteKit

I have the following code at the moment. Even though the code build is successful, i cannot seem to get it to work. I am trying to make it so when you flick the object, it moves at the velocity of your begin and end touch.
import SpriteKit
class GameScene: SKScene {
var sprite: SKSpriteNode!
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
override func didMoveToView(view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sprite = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 50))
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
self.addChild(sprite)
}
//for touch: AnyObject in touches {
//let location = touch.locationInNode(self)
//let touchedNode = self.nodeAtPoint(location)
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if sprite.frame.contains(location) {
touchPoint = location
touching = true
}
}
func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
touchPoint = location
}
func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
touching = false
}
func update(currentTime: CFTimeInterval) {
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
sprite.physicsBody!.velocity = velocity
}
}
}}}
You accidentally placed touchesMoved, touchesEnded and update inside touchesBegan. Besides that your code works. A hint that there were problems was the fact you didn't need to prefix touchesMoved, touchesEnded or update with override.
In the future, I would recommend using breakpoints and print statements to check the methods you expect to execute, are in fact running. Doing that you'd see that your versions of touchesMoved, touchesEnded and update weren't being called.
Anyway, here's it corrected it and now it works perfectly:
import SpriteKit
class GameScene: SKScene {
var sprite: SKSpriteNode!
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
override func didMoveToView(view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sprite = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 50))
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
self.addChild(sprite)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if sprite.frame.contains(location) {
touchPoint = location
touching = true
}
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
touchPoint = location
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
touching = false
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
touching = false
}
override func update(currentTime: NSTimeInterval) {
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
sprite.physicsBody!.velocity = velocity
}
}
}
ABakerSmith's solutions updated for Swift 4:
import SpriteKit
class GameScene: SKScene {
var sprite: SKSpriteNode!
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody.init(edgeLoopFrom: self.frame)
sprite = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite.physicsBody = SKPhysicsBody.init(rectangleOf: sprite.size)
sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
self.addChild(sprite)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first?.location(in: self) {
if sprite.frame.contains(touch) {
touchPoint = touch
touching = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches {
let location = t.location(in: self)
touchPoint = location
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func update(_ currentTime: TimeInterval) {
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
sprite.physicsBody!.velocity = velocity
}
}
}
Solution updated to not have the touch/drag snap to the middle of the sprite. If you're dragging/throwing an object you're going to want that throw to come from where the user touched the object and not snap to the middle of the object. This will make it look a lot smoother
import SpriteKit
class GameScene: SKScene {
var sprite: SKSpriteNode!
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
var xDif = CGFloat()
var yDif = CGFloat()
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody.init(edgeLoopFrom: self.frame)
sprite = SKSpriteNode(color: .red, size: CGSize(width: 50, height: 50))
sprite.physicsBody = SKPhysicsBody.init(rectangleOf: sprite.size)
sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
self.addChild(sprite)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first?.location(in: self) {
xDif = sprite.position.x - touch.x
yDif = sprite.position.y - touch.y
if sprite.frame.contains(touch) {
touchPoint = touch
touching = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches {
let location = t.location(in: self)
touchPoint = location
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func update(_ currentTime: TimeInterval) {
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-sprite.position.x + xDif, dy: touchPoint.y-sprite.position.y + yDif)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
sprite.physicsBody!.velocity = velocity
}
}
}

Resources