How do I drag and drop a sprite in Swift 3.0?
I have an implementation where I've subclassed a UIImageView and called it a "DraggableImage"
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
originalPosition = self.center
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: self.superview)
self.center = CGPoint(x: position.x, y: position.y)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.center = originalPosition
}
Move a sprite randomly using Swift 3
That is happening because only the last action from the for loop is executed. You have to make a queue of actions. So you should append them to an array, and run them in a sequence, like this:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
private let greenDragonNode = SKSpriteNode(color: .green, size: CGSize(width: 20, height: 20))
func getRandomPoint(withinRect rect:CGRect)->CGPoint{
let x = CGFloat(arc4random()).truncatingRemainder(dividingBy: rect.size.width)
let y = CGFloat(arc4random()).truncatingRemainder(dividingBy: rect.size.height)
return CGPoint(x: x, y: y)
}
override func didMove(to view: SKView) {
greenDragonNode.position = self.getRandomPoint(withinRect: frame)
addChild(greenDragonNode)
var actions:[SKAction] = []
for i in 1...20 {
let destination = getRandomPoint(withinRect: frame)
let move = SKAction.move(to:destination, duration: 1.0)
actions.append(move)
let label = SKLabelNode(text: "\(i)")
label.position = destination
addChild(label)
}
let sequence = SKAction.sequence(actions)
greenDragonNode.run(sequence)
}
}
(Xcode Swift SpriteKit) How do I move a sprite in the direction it is facing
You will need to use sin and cos. An SKAction may not be the best thing for you, so I would just do this in the update method for now till you find a better spot:
sprite.position = CGPoint(x:sprite.position.x + cos(sprite.zRotation) * 10,y:sprite.position.y + sin(sprite.zRotation) * 10)
Where 10 is the magnitude that you want the sprite to move (aka move 10 pixels)
This assumes that angle 0 means the sprite is looking right, angle 90 (PI/2) is looking up, angle 180 (PI) is looking left, and angle 270 (3PI/2) is looking down.
Dragging and flicking/throwing skspritenode
This should work, I just dug it out from an old project.
CGFloat dt is for changing the speed/power of the movement.
var touching = false
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let location = touch.locationInNode(self)
if sprite.frame.contains(location) {
touchPoint = location
touching = true
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
let touch = touches.first as! UITouch
let location = touch.locationInNode(self)
touchPoint = location
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
touching = false
}
override func update(currentTime: CFTimeInterval) {
if touching {
if touchPoint != sprite.position
{
let dt:CGFloat = 0.15
let distance = CGVector(dx: touchPoint.x-sprite.position.x, dy: touchPoint.y-sprite.position.y)
let vel = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
sprite.physicsBody!.velocity = vel
}
}
}
EDIT:
The reason it gets stronger the farther the distance, is because the vector IS the distance between the the sprite and the touch point.
Try popping this in as the update function. It should work...
override func update(currentTime: CFTimeInterval) {
if touching {
if touchPoint != sprite.position
{
let pointA = touchPoint
let pointB = sprite.position
let pointC = CGPointMake(sprite.position.x + 2, sprite.position.y)
let angle_ab = atan2(pointA.y - pointB.y, pointA.x - pointB.x)
let angle_cb = atan2(pointC.y - pointB.y, pointC.x - pointB.x)
let angle_abc = angle_ab - angle_cb
let vectorx = cos(angle_abc)
let vectory = sin(angle_abc)
let dt:CGFloat = 15
let vel = CGVector(dx: vectorx * dt, dy: vectory * dt)
sprite.physicsBody!.velocity = vel
}
}
}
With the touchPoint (pointA), and the sprite's position (pointB) we can create an angle.
atan2, is a very famous function from C, it creates the angle between two points.
BUT, it's 0 degrees is in a different location than usual.
So, we need our own 0 degrees marker, I use the mid-right of the point as my marker.
It's the common 0 degree placement:
Since it's to the right of the sprite's position, we create a point just to the right of the sprite (pointC).
We now use atan2 to find the angle.
To create a vector from an angle, we just use cos and sin for the x and y values.
How to drag and release an object with velocity
Dragging and releasing a sprite with velocity can be accomplished by
First, a struct
to store touch data
struct TouchInfo {
var location:CGPoint
var time:NSTimeInterval
}
Declare SKScene
subclass properties
var selectedNode:SKSpriteNode?
var history:[TouchInfo]?
In touchesBegan
- Save the sprite that the user touched
- Save touch event data
Swift code:
let touch = touches.anyObject() as UITouch
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "player") {
// Step 1
selectedNode = node as? SKSpriteNode;
// Stop the sprite
selectedNode?.physicsBody?.velocity = CGVectorMake(0,0)
// Step 2: save information about the touch
history = [TouchInfo(location:location, time:touch.timestamp)]
}
In touchesMoved
- If a sprite was selected in touchesBegan, move the sprite to the new location
- Save the touch event data
Swift code:
let touch = touches.anyObject() as UITouch
let location = touch.locationInNode(self)
if (selectedNode != nil) {
// Step 1. update sprite's position
selectedNode?.position = location
// Step 2. save touch data at index 0
history?.insert(TouchInfo(location:location, time:touch.timestamp),atIndex:0)
}
In touchesEnded
- Calculate the differences in x and y from the last touch and the current touch
- Find the time difference between touch events
- Calculate and keep a sum of the velocity components in x and y
- Create a velocity vector and apply it to the sprite
- Unselect the node
Swift code:
if let history = history, history.count > 1 && selectedNode != nil {
var vx:CGFloat = 0.0
var vy:CGFloat = 0.0
var previousTouchInfo:TouchInfo?
// Adjust this value as needed
let maxIterations = 3
var numElts:Int = min(history.count, maxIterations)
// Loop over touch history
for index in 0..<numElts {
let touchInfo = history[index]
let location = touchInfo.location
if let previousTouch = previousTouchInfo {
// Step 1
let dx = location.x - previousTouch.location.x
let dy = location.y - previousTouch.location.y
// Step 2
let dt = CGFloat(touchInfo.time - previousTouch.time)
// Step 3
vx += dx / dt
vy += dy / dt
}
previousTouchInfo = touchInfo
}
let count = CGFloat(numElts-1)
// Step 4
let velocity = CGVectorMake(vx/count,vy/count)
selectedNode?.physicsBody?.velocity = velocity
}
// Step 5
selectedNode = nil
history = nil
Sprite won't move with finger/ SpriteKit / Swift 3
this code
simpleS = self.childNode(withName: "simpleS") as! SKSpriteNode
connects the sprites in your GameScene.sks with GameScene.swift
so in the first step you have to make sure that you set the right name (exactly "simpleS") in your sks file.
if you did it right, so please send the error for us.
i have built and ran your code and everything works in a right way.
another point is that if you want your sprites only moves by your finger movement you have to delete the codes in touchesBegan function, because touchesBegan moves your sprite wherever you touch.
Related Topics
Global Function Sequence(State:Next:) and Type Inference
Get an Array of Dates of the Current Week Starting on Monday
Could Not Find an Overload for '^' That Accepts the Supplied Arguments
For Loop Cycle Showing Always the Last Array Value Swift 3 After Http Request
Block Scroll Down in Scrollview - Swiftui
Fibonacci Calculator Stack Overflows at 93Nd Number in Swift
How to Upload Zip Data with Alamofire
Read Data Firebase Assign Value
Firebase Observe Called After Following Command
Implicit Return in a Closure Causing an Error
Segue from a Slpagingviewswift Vc and Dismiss the Destination Vc to Return
Which Format File for 3D Model Scenekit/Arkit Better to Use
In Swift, How to Get Memory Back to Normal After an Skscene Is Removed
Swift: How to Call Cckeyderivationpbkdf from Swift
Differencebetween Swift 2.0 Do-Try-Catch and Regular Java/C#/C++ Exceptions
How to Set Top Left and Right Corner Radius with Desired Drop Shadow in Uitabbar