Spritekiit Swift: Touch a Moving Object

SpriteKiit Swift: touch a moving object

you have to set a name for your sprite like "ballNode", then in "touchesBegan" function you can handle it.

 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in (touches) {
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name {
if name == "ballNode" {
//make it hidden by touchedNode.isHidden = true
//or remove it from parent by touchedNode.removeFromParent()
}
}
}
}

Touching moving Sprites in SpriteKit

Are your entities too small? With the given info, I recreated a small scene in a playground, and all is working as expected. If I have a presented child node, defined as

let circle = SKShapeNode(circleOfRadius: 20)

And I have defined both the physicsWorld of the SKScene, and physicsBody of the SKNode, with the given touchesBegan, there is no problem in detecting a collision.

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let location = touches.first?.location(in: self)
if self.atPoint(location) === circle {
print("TOUCH")
}
}
}

Continuous Touch/Moving Swift & SpriteKit

Personally, I would create a controller class that has an update function that you poll on your scene update to determine whether a button state is up or down, and go off of that (Touch begins puts button in down state, touch end puts it in up state. update polls state, and performs actions based on state) But in your case, to keep things simple without changing a lot of code, I would just use SKAction.moveBy

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

for touch: AnyObject in touches {
let location = touch.locationInNode(self)

if location.y > 400{

move = true

}else{
//tap somewhere above this to make character jump
if(location.y > 250) {
player.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 200))
}
else
{
let direction = (location.x > CGRectGetMidX(self.frame)) ? 30 : -30
let move = SKAction.moveBy(x:direction,y:0,duration:0)
let rep = SKAction.repeatActionForever(move)
player.runAction(rep,forKey:"Moving")
}
}
}
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

player.removeActionForKey("Moving")
move = false

}

Move a node to finger using Swift + SpriteKit

You can save yourself a lot of trouble by using: myShip.physicsBody.applyImpluse(vector). It works by acting as if you gave myShip a push in the direction vector points. If you calculate vector as the x distance from your last touch location to myShip, then it'll accelerate, decelerate, change direction, etc. pretty close to the way you're describing because it'll be giving it little pushes in the right direction on each update.

Basically you store the last touch location then, in your update function, you calculate the CGVector pointing from myShip to lastTouch and apply that as an impulse to your physics body.

Something like:

var lastTouch: CGPoint? = nil

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject() as UITouch
let touchLocation = touch.locationInNode(self)
lastTouch = touchLocation
}

override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
let touch = touches.anyObject() as UITouch
let touchLocation = touch.locationInNode(self)
lastTouch = touchLocation
}

// Be sure to clear lastTouch when touches end so that the impulses stop being applies
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
lastTouch = nil
}

override func update(currentTime: CFTimeInterval) {
// Only add an impulse if there's a lastTouch stored
if let touch = lastTouch {
let impulseVector = CGVector(touch.x - myShip.position.x, 0)
// If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range
myShip.physicsBody.applyImpluse(impulseVector)
}
}

You'll also probably want to play with the linearDamping and angularDamping values on myShip.physicsBody. They'll help determine how fast myShip accelerates and decelerates.

I maxed out the values at 1.0 in my app:

myShip.physicsBody.linearDamping = 1.0
myShip.physicsBody.angularDamping = 1.0

If myShip doesn't stop fast enough for you, you can also try applying some breaking in your update function:

override func update(currentTime: CFTimeInterval) {
// Only add an impulse if there's a lastTouch stored
if let touch = lastTouch {
let impulseVector = CGVector(touch.x - myShip.position.x, 0)
// If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range
myShip.physicsBody.applyImpluse(impulseVector)
} else if !myShip.physicsBody.resting {
// Adjust the -0.5 constant accordingly
let impulseVector = CGVector(myShip.physicsBody.velocity.dx * -0.5, 0)
myShip.physicsBody.applyImpulse(impulseVector)
}
}


Related Topics



Leave a reply



Submit