Reputation: 1436
I am trying to create a Sling shot mechanism where I rotate a node with an object attached at the end. The slingshot starts off with a touch and hold interaction to rotate the object and on release, launches the object attached at the end - A similar effect is seen here
This is my code for the rotation which has worked. Not sure how to start the joining and slinging part.
var touchingScreen = false
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
super.touchesBegan(touches, withEvent: event)
touchingScreen = true
println("Screen Touched")
}
override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {
super.touchesCancelled(touches, withEvent: event)
touchingScreen = false
println("Screen Not Touched")
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
super.touchesEnded(touches, withEvent: event)
touchingScreen = false
println("Screen Not Touched")
}
override func update(currentTime: CFTimeInterval) {
if touchingScreen {
var RotatingAngle = CGFloat(M_PI)
var rotationDuration = 20.0
var rotateCanon = SKAction.rotateByAngle(CGFloat(RotatingAngle), duration: rotationDuration)
canon.runAction(rotateCanon)
} else if !touchingScreen {
var RotatingAngleTwo = CGFloat(0)
var rotationDurationTwo = 0.0
var rotateCanon = SKAction.rotateByAngle(CGFloat(RotatingAngleTwo), duration: rotationDurationTwo)
canon.runAction(rotateCanon)
}
}
Thanks for the help.
Upvotes: 2
Views: 695
Reputation: 12753
Some thoughts...
and some code...
enum State {
case Stopped
case Rotating
case Launched
}
let two_pi = CGFloat(M_PI*2.0)
let pi = CGFloat(M_PI)
// These are useful vector/point operators
func * (left:CGPoint, right:CGFloat) -> CGPoint {
return CGPointMake(left.x*right, left.y*right)
}
func += (inout left:CGPoint, right:CGPoint) {
left = CGPointMake(left.x+right.x, left.y+right.y)
}
func * (left:CGVector, right:CGFloat) -> CGVector {
return CGVectorMake(left.dx*right, left.dy*right)
}
func / (left:CGVector, right:CGFloat) -> CGVector {
return CGVectorMake(left.dx/right, left.dy/right)
}
class GameScene: SKScene {
let shape = SKShapeNode(circleOfRadius: 7)
let radius:CGFloat = 30
var center = CGPointZero
var currentAngle = -pi/2
let angleIncr = two_pi / 60.0
var state:State = .Stopped
override func didMoveToView(view: SKView) {
scaleMode = .ResizeFill
// Set the center of the sling
center = CGPointMake (CGRectGetMidX(view.frame),CGRectGetMidY(view.frame))
addBall()
let circle = SKShapeNode(circleOfRadius: radius)
circle.position = CGPointMake (CGRectGetMidX(view.frame),CGRectGetMidY(view.frame))
addChild(circle)
}
// Adds a circle shape node at the bottom of the sling
func addBall() {
currentAngle = -pi/2
shape.fillColor = SKColor.blueColor()
shape.position = CGPointMake (center.x, center.y-radius)
shape.physicsBody = SKPhysicsBody(circleOfRadius: 7)
shape.physicsBody?.affectedByGravity = false
shape.physicsBody?.mass = 0.5
shape.zPosition = 1
addChild(shape)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if let touch = touches.first as? UITouch {
let location = touch.locationInNode(self)
if (state == .Stopped) {
// Start rotating the ball around the sling
state = .Rotating
}
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
if (state == .Rotating) {
// Launch the ball on a vector tangent to its current position on the circle
state = .Launched
// Normal vector
var normal = CGVectorMake(shape.position.x-center.x, shape.position.y-center.y)
normal = normal / magnitude(normal)
// Tangent vector
let vector = CGVectorMake(normal.dy, -normal.dx)
// Convert angular to linear speed
let speed = angleIncr * 60.0 * radius
shape.physicsBody?.velocity = vector*speed
runAction(SKAction.waitForDuration(1.0)) {
self.shape.removeFromParent()
self.state = .Stopped
self.addBall()
}
}
}
override func update(currentTime: CFTimeInterval) {
switch (state) {
case .Rotating:
var point = angleToPoint(currentAngle) * radius
point += center
shape.position = point
currentAngle -= angleIncr
// Wrap at 2 pi
currentAngle %= two_pi
default:
break
}
}
func angleToPoint(angle:CGFloat) -> CGPoint {
return CGPointMake(cos(angle), sin(angle))
}
func magnitude(v1:CGVector) -> CGFloat {
return sqrt(v1.dx*v1.dx+v1.dy*v1.dy)
}
}
and a video...
Upvotes: 1