Reputation: 363
On the screenshot provided, the red arrow and cross are just for demonstration purposes and are not in the game. I would like the sprite of the spaceship to face the direction of the ball it shoots.
Here is my current code for touch location
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
var bullet = SKSpriteNode(imageNamed: "bullet")
bullet.position = cannon.position
bullet.size = CGSize(width: 35, height: 35)
//physics
bullet.physicsBody = SKPhysicsBody(circleOfRadius: bullet.size.width/2)
bullet.physicsBody?.categoryBitMask = PhysicsCategory.bullet
bullet.physicsBody?.collisionBitMask = PhysicsCategory.enemy
bullet.physicsBody?.contactTestBitMask = PhysicsCategory.enemy
bullet.name = "bullet"
bullet.physicsBody?.affectedByGravity = false
self.addChild(bullet)
var dx = CGFloat(location.x - cannon.position.x)
var dy = CGFloat(location.y - cannon.position.y)
let magnitude = sqrt(dx * dx + dy * dy)
dx /= magnitude
dy /= magnitude
let vector = CGVector(dx: 120.0 * dx, dy: 120.0 * dy) //adjust constant to increase impluse.
bullet.physicsBody?.applyImpulse(vector)
// I found this code bellow this comment, but it just moves the cannon's y position
let direction = SKAction.moveTo(
CGPointMake(
400 * -cos(bullet.zRotation - CGFloat(M_PI_2)) + bullet.position.x,
400 * -sin(bullet.zRotation - CGFloat(M_PI_2)) + bullet.position.y
),
duration: 0.8)
cannon.runAction(direction)
}
}
Upvotes: 8
Views: 2278
Reputation: 21
I found that with the answer submitted by James that this caused it to rotate in the wrong way, fine if you have something like a canonball but as it was used on my game which had a mage and a fireball with a trail it caused an issue, this can be easily fixed with
let angle = atan2(touchlocation.x - cannon.position.x , touchlocation.y -
cannon.position.y)
cannon.zRotation = -(angle - CGFloat(Double.pi/2))
use Double.pi / 2 and M_PI_2 is depriciated now
Upvotes: 2
Reputation: 363
Here is the code I found which works perfectly.
Rotate a sprite to sprite position not exact in SpriteKit with Swift
let angle = atan2(location.y - cannon.position.y , location.x - cannon.position.x)
cannon.zRotation = angle - CGFloat(M_PI_2)
Upvotes: 7
Reputation: 433
If you want to rotate only you shouldn't call the moveTo action. Calculate the angle between touch location and location of the cannon and call action rotateToAngel
here is the code
let angle = atan2(dy, dx) - CGFloat(M_PI_2)
let direction = SKAction.rotateToAngle(angle, duration: 0.4, shortestUnitArc: true)
cannon.runAction(direction)
Upvotes: 4
Reputation: 20804
I had been working some time ago in something like what you want so, here is my results
first you need to use VectorMath.swift
created by Nick Lockwood and this is my code to make my spider move towards user touch
import SpriteKit
import SceneKit
class GameScene: SKScene {
let sprite = SKSpriteNode(imageNamed:"Aranna")
var velocity = Vector2(x: 0, y: 0)
var positionV2D = Vector2(x: 0, y: 0)
var headingVector = Vector2(x: 0, y: 1)
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:"Chalkduster")
myLabel.text = "Hello, World!";
myLabel.fontSize = 45;
myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
sprite.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame));
positionV2D = Vector2(point:sprite.position);
let testVector = Vector2(x: 10, y: 14);
velocity += testVector;
print(velocity.toString());
velocity += Vector2(x: 1, y: 1);
//velocity = velocity + testVector;
print(velocity.toString());
velocity *= 0.5;
velocity.printVector2D();
velocity = Vector2(x: 2, y: 2);
velocity.normalized();
velocity.printVector2D();
self.addChild(sprite)
}
func ToRad(grados:CGFloat) ->CGFloat
{
return ((CGFloat(M_PI) * grados) / 180.0)
}
func ToDeg(rad:CGFloat) ->CGFloat
{
return (180.0 * rad / CGFloat(M_PI))
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
let toTarget = Vec2DNormalize(Vector2(point:location) - positionV2D);
let angle2 = headingVector.angleWith(toTarget);
print(ToDeg(CGFloat(angle2)));
headingVector.printVector2D();
self.sprite.runAction(SKAction.rotateToAngle(CGFloat(angle2), duration: 0.1))
self.sprite.runAction(SKAction.moveTo(location, duration: 0.5))
positionV2D = Vector2(point: location);
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
I hope this helps you
Upvotes: 5