applyImpulse not working when touching node - ios

I have a circle on the screen that will slowly get bigger (incidentally, Balloon class is a type of SKShapeNode). In touchesBegan I click on the circle and it prints that I touched it, however no impulse is applied. How can I find the issue? I'm fairly new to SpriteKit.
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var radius = 40.0
var balloon : Balloon? = nil
override func didMove(to view: SKView) {
balloon = Balloon(radius: radius, position: CGPoint(x: frame.midX, y: frame.minY + 250))
balloon?.name = "balloon"
let physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(radius))
physicsBody.affectedByGravity = false
balloon?.physicsBody = physicsBody
balloon?.physicsBody?.isDynamic = true
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
self.addChild(balloon!)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
let node : SKNode = self.atPoint(location)
if node.name == "balloon" {
print("touching balloon.")
balloon?.physicsBody?.applyImpulse(CGVector(dx: 10.0, dy: 10.0), at: location)
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
radius += 0.05
self.balloon?.radius = radius
let physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(radius))
physicsBody.affectedByGravity = false
balloon?.physicsBody = physicsBody
balloon?.physicsBody?.isDynamic = true
}
}

You are creating a new body every update. If you want to inflate your balloon, use scale:
var scale = 1.0
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
scale += 0.05
self.balloon?.setScale(scale)
}
Then your physics body will be able to have the impulse applied to it because you won't be creating a new body each update.

The following line:
let location = touch.location(in: self)
finds the location of the touch in the scene. However, in the function call applyImpulse, it is relative to the node. Instead of
balloon?.physicsBody?.applyImpulse(CGVector(dx: 10.0, dy: 10.0), at: location)
use:
balloon?.physicsBody?.applyImpulse(CGVector(dx: 10.0, dy: 10.0), at: touch.location(in: balloon))

Related

SpriteKit interplay between line and node: line should give a direction and speed to the node

I would like to have the following interplay between line and ball in my game: a line gives direction and speed to the ball. The longer the line, the faster the ball.
What I have now: a ball is following the line and stops at the end of it. But it shouldn't stop here. Of course, I understand that the ball is only following the path I made. But how could I change it?
Here is my code:
import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
// Basic for dynamic sizes step01
var width = CGFloat()
var height = CGFloat()
var ball:SKSpriteNode!
var line:SKShapeNode!
var startPoint: CGPoint!
var location = CGPoint()
override func didMove(to view: SKView) {
self.backgroundColor = .purple
//declare dynamic size of the screen
width = self.frame.size.width
height = self.frame.size.height
self.physicsBody = SKPhysicsBody(edgeLoopFrom: frame)
self.physicsWorld.gravity = CGVector.zero
createBall()
}
func createBall(){
ball = SKSpriteNode(imageNamed: "yellowBtn")
ball.position = CGPoint(x:0, y: -(height/2.5))
ball.size = CGSize(width: width/6, height: width/6)
self.addChild(ball)
}
func drawLine(endPoint:CGPoint){
if(line != nil ){ line.removeFromParent() }
startPoint = ball.position
let path = CGMutablePath()
path.move(to: startPoint)
path.addLine(to: endPoint)
line = SKShapeNode()
line.path = path
line.lineWidth = 5
line.strokeColor = UIColor.white
self.addChild(line)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if(line != nil ){ line.removeFromParent()
for touch in (touches ) {
let location = touch.location(in: self)
drawLine(endPoint: location)
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches ) {
let location = touch.location(in: self)
drawLine(endPoint: location)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches ) {
location = touch.location(in: self)
drawLine(endPoint: location)
}
let moveAction = SKAction.move(to: location, duration: 10)
ball.run(moveAction)
}
override func update(_ currentTime: TimeInterval) {
}
}
I have found at least a part of answer to my question: I need to calculate CGVector manually (lastPoint - firstPoint) and then apply impulse to the ball:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches ) {
location = touch.location(in: self)
drawLine(endPoint: location)
}
let dx = location.x - startPoint.x
let dy = location.y - startPoint.y
let movement = CGVector(dx: dx, dy: dy)
ball.physicsBody = SKPhysicsBody(circleOfRadius: 50)
ball.physicsBody?.applyImpulse(movement)
}
Now I should find the second part: how to set the speed of the ball accordingly to the length of the line.

Spritkit : Detect collision while drawing line using finger

I am trying to detect collision contactPoint between existing line and line which user currently drawing using finger.
Here is my code :
let padding: CGFloat = 100
override func didMove(to view: SKView) {
physicsWorld.contactDelegate = self
let startPoint1 = CGPoint(x: self.frame.minX + padding , y: self.frame.minY + padding)
let leftHorizontalPoint = CGPoint(x: self.frame.minX + padding, y: self.frame.maxY - padding)
let line1 = SKShapeNode()
let line_path:CGMutablePath = CGMutablePath()
line_path.move(to: startPoint1)
line_path.addLine(to: leftHorizontalPoint)
line1.path = line_path
line1.lineWidth = 3
line1.strokeColor = UIColor.white
addChild(line1)
line1.physicsBody = SKPhysicsBody(edgeLoopFrom: line1.frame)
line1.physicsBody?.isDynamic = true
line1.physicsBody?.categoryBitMask = PhysicsCategory.solidLine
line1.physicsBody?.collisionBitMask = PhysicsCategory.currentLine
line1.physicsBody?.contactTestBitMask = PhysicsCategory.currentLine
}
Then on touchBegin, touchMove & touchEnd I am having following code :
var currentLineNode: SKShapeNode!
var startPoint: CGPoint = CGPoint.zero
func touchDown(atPoint pos : CGPoint) {
startPoint = pos
}
func touchMoved(toPoint pos : CGPoint) {
if currentLineNode != nil {
currentLineNode.removeFromParent()
}
currentLineNode = SKShapeNode()
currentLineNode.zPosition = 1
let line_path:CGMutablePath = CGMutablePath()
line_path.move(to: startPoint)
line_path.addLine(to: pos)
currentLineNode.path = line_path
currentLineNode.lineWidth = 3
currentLineNode.strokeColor = UIColor.red
addChild(currentLineNode)
currentLineNode.physicsBody = SKPhysicsBody(edgeLoopFrom: currentLineNode.frame)
currentLineNode.physicsBody?.isDynamic = true
currentLineNode.physicsBody?.categoryBitMask = PhysicsCategory.currentLine
currentLineNode.physicsBody?.collisionBitMask = PhysicsCategory.solidLine
currentLineNode.physicsBody?.contactTestBitMask = PhysicsCategory.solidLine
}
func touchUp(atPoint pos : CGPoint) {
if currentLineNode != nil {
currentLineNode.removeFromParent()
}
currentLineNode = SKShapeNode()
let line_path:CGMutablePath = CGMutablePath()
line_path.move(to: startPoint)
line_path.addLine(to: pos)
currentLineNode.path = line_path
currentLineNode.lineWidth = 3
currentLineNode.strokeColor = UIColor.red
addChild(currentLineNode)
currentLineNode.physicsBody = SKPhysicsBody(edgeLoopFrom: currentLineNode.frame)
currentLineNode.physicsBody?.isDynamic = true
currentLineNode.physicsBody?.categoryBitMask = PhysicsCategory.currentLine
currentLineNode.physicsBody?.collisionBitMask = PhysicsCategory.solidLine
currentLineNode.physicsBody?.contactTestBitMask = PhysicsCategory.solidLine
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
physicsWorld's contactDelegate as follow : (Delegate not even executed)
extension GameScene : SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
// This never get detected :(
print(contact.contactPoint)
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
}
}
Here is my output where even though passing from white colored line its not detecting collision.
What could be wrong? Any suggestion on this will be helpful.
You are using 2 edge based bodies. Edge based bodies will always be isDynamic = false no matter if you set it or not. You need at least 1 volume based body to be able to perform a contact.
Plus on top of that you are constantly removing and adding a node, which is a terrible idea.
I would recommend adding your node on the touchesBegan only, then update only the path on touchesMoved
you are creating your physics body with an edge loop. Apple defines edge loops as...
An edge has no volume or mass and is always treated as if the isDynamic property is equal to false. Edges may only collide with volume-based physics bodies.
changing your physics body to this works
currentLineNode.physicsBody = SKPhysicsBody(rectangleOf: currentLineNode.frame.size, center: CGPoint(x: startPoint.x + currentLineNode.frame.size.width / 2, y: startPoint.y + currentLineNode.frame.size.height / 2))
also should be noted that changing your physics body in touchesEnded is redundant and adds nothing. I removed it from touchesEnded and it works fine

Joystick, clamping the control stick inside the joystick base

I have a circular joystick i created in SpriteKit, how do i clamp the smaller control stick inside of the larger joystick base and prevent it from going outside the joystick base programmatically.
The code setting up my joystick inside of my didMove(toView:) method.
var DPad = SKSpriteNode(imageNamed: "dpad")
DPad.size = CGSize(width: 150, height: 150)
DPad.position = CGPoint(x: -270, y: -100)
var thumbNode = SKSpriteNode(imageNamed: "joystick")
thumbNode.size = CGSize(width: 50, height: 50)
thumbNode.position = CGPoint(x: DPad.position.x, y: DPad.position.y)
touchesBegan methods
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if thumbNode.contains(location) && isTracking == false {
isTracking = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if isTracking == true {
thumbNode.run(SKAction.move(to: location, duration: 0.01))
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
thumbNode.run(SKAction.move(to: DPad.position, duration: 0.01))
if thumbNode.position.x > DPad.size.width || thumbNode.position.y > DPad.size.height {
thumbNode.position = DPad.position
}
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
if thumbNode.physicsBody?.velocity.dx > Float(0) || thumbNode.physicsBody?.velocity.dx < Float(0) {
print("greater")
}
}
For this, you can use SKConstraint.distance(SKRange(upperLimit: radius), to: baseNode)
To add it, just do joystickNode.constraints = [SKConstraint.distance(SKRange(upperLimit: radius), to: baseNode)]

how to have a enemy be added in every 10 seconds and have this enemy track your location and follow it

im currently working on an app in which your player which is a small round ball, gets dragged around the screen by your finger. Then every 10 seconds a enemy ball gets added in which automatically tracks your ball and follows it until it runs into it. this is the code I have for this so far. you can drag your ball around the screen, bu the enemy ball which is only showing up as a red x even though its file is in the assets gets spawned every frame and they just move to the position of where your ball was when it was spawned. is there any way I can fix this, any help is appreciated. the contact between the balls I will add later on.
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var me = SKSpriteNode()
let enemy = SKSpriteNode (imageNamed: "ellipse 1")
override func didMove(to view: SKView) {
me = self.childNode(withName: "me") as! SKSpriteNode
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
}
}
override func update(_ currentTime: TimeInterval) {
let enemy = SKSpriteNode (imageNamed: "ball 2")
enemy.position = CGPoint(x:667, y: -200)
enemy.run(SKAction.moveTo(x: me.position.x, duration: 1.5))
enemy.run(SKAction.moveTo(y: me.position.y, duration: 1.5))
enemy.zPosition = +1
addChild(enemy)
}
}
So the problem you're having is that your enemy ball images aren't loading, and you're seeing a red X instead?
If so you need to break your code that creates your sprite into steps. First load the image into a temporary variable, print it, and then use the image to create your sprite:
let enemyImage = imageNamed: "ellipse 1"
print("enemyImage = \(enemyImage)")
let enemy = SKSpriteNode (enemyImage)
If enemyImage is nil, you need to figure out why that is.
Here is a modified version of your code that'll spawn an enemy once every 10 seconds and have them follow you. I used the Spaceship graphic provided by Apple's SpriteKit template for the enemy. As for your issue with the enemy graphic not showing up I'd make sure that the image is named "ball 2" in the assets folder.
import SpriteKit
import GameplayKit
class Enemy: SKSpriteNode {
var enemySpeed: CGFloat = 4
}
class GameScene: SKScene {
var me: SKSpriteNode!
var enemies = [Enemy]()
override func didMove(to view: SKView) {
me = self.childNode(withName: "me") as! SKSpriteNode
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
spawnEnemy() // Spawn an enemy to begin with
Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(spawnEnemy), userInfo: nil, repeats: true) // Spawns an enemy every 10 seconds
}
func spawnEnemy() {
let enemy = Enemy(imageNamed: "Spaceship")
enemy.xScale = 0.25
enemy.yScale = 0.25
enemy.position = CGPoint(x: CGFloat(arc4random() % UInt32(size.width)) - size.width / 2, y: CGFloat(arc4random() % UInt32(size.height)) - size.height / 2)
enemy.zPosition = 1
addChild(enemy)
enemies.append(enemy)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
me.run(SKAction.move(to: location, duration: 0.05))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
me.run(SKAction.move(to: location, duration: 0.05))
}
}
override func update(_ currentTime: TimeInterval) {
for enemy in enemies {
let angle = CGFloat(atan2f(Float(me.position.y - enemy.position.y), Float(me.position.x - enemy.position.x)))
enemy.zRotation = angle - CGFloat.pi / 2
enemy.position = CGPoint(x: enemy.position.x + cos(angle) * enemy.enemySpeed, y: enemy.position.y + sin(angle) * enemy.enemySpeed)
}
}
}
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var me = SKSpriteNode()
override func didMove(to view: SKView) {
me = self.childNode(withName: "me") as! SKSpriteNode
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 10.0)])))
}
func createEnemy () {
let enemy = SKSpriteNode(imageNamed: "ball 1")
enemy.name = "enemy"
enemy.position = CGPoint(x:667, y: -200)
enemy.run(SKAction.moveTo(x: me.position.x, duration: 1.5))
enemy.run(SKAction.moveTo(y: me.position.y, duration: 1.5))
enemy.zPosition = +1
addChild(enemy)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
}
}
override func update(_ currentTime: TimeInterval) {
}
}

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