Wie kann ich im Swift-Code eine kontinuierliche Benutzerberührung erkennen? Mit Continuous meine ich, dass der Benutzer seinen Finger auf dem Bildschirm hat. Ich möchte einen Sprite-Kit-Knoten in die Richtung der Berührung des Benutzers verschieben, solange der Benutzer den Bildschirm berührt.Wie erkennen Sie kontinuierliche Berührung in Swift?
Antwort
Das Schwierigste an diesem Prozess einzelne Berührungen innerhalb einer Multi-Touch-Umgebung verfolgt. Das Problem mit der "einfachen" Lösung für dieses Problem (dh, "istouched" in touchesBegan
einschalten und in touchesEnded
ausschalten) ist, dass, wenn der Benutzer einen anderen Finger auf dem Bildschirm berührt und hebt es dann die Aktionen der ersten Berührung ab .
Um dies kugelsicher zu machen, müssen Sie einzelne Berührungen über ihre Lebensdauer hinweg verfolgen. Wenn die erste Berührung erfolgt, speichern Sie den Ort dieser Berührung und verschieben Sie das Objekt an diesen Ort. Alle weiteren Berührungen sollten mit der ersten Berührung verglichen werden und sollten ignoriert werden, wenn sie nicht die erste Berührung sind. Mit diesem Ansatz können Sie auch mit Multitouch arbeiten, bei dem das Objekt zu einem beliebigen Finger auf dem Bildschirm bewegt werden kann, und dann zum nächsten Finger gehen, wenn der erste Finger abgehoben wird, und so weiter.
Es ist wichtig zu beachten, dass UITouch
Objekte über touchesBegan
konstant sind, touchesMoved
und touchesEnded
. Sie können sich ein UITouch
Objekt vorstellen, das in touchesBegan
erstellt, in touchesMoved
geändert und in touchesEnded
zerstört wurde. Sie können die Phase einer Berührung im Laufe ihrer Lebensdauer verfolgen, indem Sie einen Verweis auf das Berührungsobjekt in einem Wörterbuch oder einem Array speichern, wie es in touchesBegan
erstellt wird, dann können Sie unter touchesMoved
die neue Position aller vorhandenen Berührungen überprüfen und ändern der Verlauf des Objekts, wenn der Benutzer seinen Finger bewegt (Sie können Toleranzen anwenden, um Jitter zu vermeiden, z. B. wenn der X/Y-Abstand kleiner als eine Toleranz ist, ändern Sie nicht den Kurs). In touchesEnded
können Sie prüfen, ob die fokussierte Berührung beendet ist, und die Bewegung des Objekts abbrechen oder es so einstellen, dass es sich zu einer anderen Berührung bewegt, die noch immer auftritt. Dies ist wichtig, als ob Sie nur nach einem alten Touch-Objekt-Ende suchen, das andere Berührungen ebenfalls abbricht, was zu unerwarteten Ergebnissen führen kann.
Dieser Artikel ist in Obj-C, aber der Code ist leicht portiert Swift und zeigt Ihnen, was Sie tun müssen, nur die Materialkontrolle heraus unter „einer komplexen Multitouch-Sequenz Handling“: https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/multitouch_background/multitouch_background.html
Die grundlegenden Schritte
- Shop die Lage der Berührungsereignisse (
touchesBegan
/touchesMoved
) - Verschieben Sprite Knoten in Richtung dieser Position (
update
) - Stop, um den Knoten, wenn Berührung Bewegen nicht mehr erkannt wird (
touchesEnded
)
Hier ist ein Beispiel dafür, wie das zu tun,
Xcode 8
let sprite = SKSpriteNode(color: SKColor.white, size: CGSize(width:32, height:32))
var touched:Bool = false
var location = CGPoint.zero
override func didMove(to view: SKView) {
/* Add a sprite to the scene */
sprite.position = CGPoint(x:0, y:0)
self.addChild(sprite)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touched = true
for touch in touches {
location = touch.location(in:self)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
location = touch.location(in: self)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// Stop node from moving to touch
touched = false
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
if (touched) {
moveNodeToLocation()
}
}
// Move the node to the location of the touch
func moveNodeToLocation() {
// Compute vector components in direction of the touch
var dx = location.x - sprite.position.x
var dy = location.y - sprite.position.y
// How fast to move the node. Adjust this as needed
let speed:CGFloat = 0.25
// Scale vector
dx = dx * speed
dy = dy * speed
sprite.position = CGPoint(x:sprite.position.x+dx, y:sprite.position.y+dy)
}
Xcode 7
let sprite = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(32, 32))
var touched:Bool = false
var location = CGPointMake(0, 0)
override func didMoveToView(view: SKView) {
self.scaleMode = .ResizeFill
/* Add a sprite to the scene */
sprite.position = CGPointMake(100, 100)
self.addChild(sprite)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Start moving node to touch location */
touched = true
for touch in touches {
location = touch.locationInNode(self)
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Update to new touch location */
for touch in touches {
location = touch.locationInNode(self)
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
// Stop node from moving to touch
touched = false
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (touched) {
moveNodeToLocation()
}
}
// Move the node to the location of the touch
func moveNodeToLocation() {
// How fast to move the node
let speed:CGFloat = 0.25
// Compute vector components in direction of the touch
var dx = location.x - sprite.position.x
var dy = location.y - sprite.position.y
// Scale vector
dx = dx * speed
dy = dy * speed
sprite.position = CGPointMake(sprite.position.x+dx, sprite.position.y+dy)
}