2016-08-29 30 views
1

我一直在試圖做的是創建一個可以移動玩家的「Joy棒」。以下是我迄今爲止:快速製作「Joy Stick」

import UIKit 
import SpriteKit 
import SceneKit 

class GameViewController: UIViewController, SCNSceneRendererDelegate { 

var isTracking = false 
var firstTrackingLocation = CGPoint.zero 
var trackingVelocity = CGPoint.zero 
var trackingDistance : CGFloat = 0.0 
var previousTime : NSTimeInterval = 0.0 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let scene = SCNScene(named: "art.scnassets/level.scn")! 
    let scnView = self.view as! SCNView 
    scnView.delegate = self 
    scnView.scene = scene 
    scnView.showsStatistics = true 
} 

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    if isTracking == false { 
     for touch in touches { 
      isTracking = true 
      let location = touch.locationInView(self.view) 
      firstTrackingLocation = location 
     } 

    } 
} 

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    if isTracking { 
      trackingVelocity = touches.first!.locationInView(self.view) 
    } 
} 

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    isTracking = false 
    trackingVelocity = CGPoint.zero 
} 

func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) { 
    if isTracking == true { 

     let scnView = self.view as! SCNView 
     let character = scnView.scene!.rootNode.childNodeWithName("person", recursively: true) 

     let deltaTime = time - previousTime 

     let pointsPerSecond: CGFloat = 1.0 * CGFloat(deltaTime) 

     var xResult:CGFloat = 0.0 
     var yResult:CGFloat = 0.0 

     let point = firstTrackingLocation 
     let endPoint = trackingVelocity 

     let direction = CGPoint(x: endPoint.x - point.x, y: endPoint.y - point.y) 
     if direction.x > direction.y { 
      let movePerSecond = pointsPerSecond/direction.x 
      xResult = direction.x*movePerSecond 
      yResult = direction.y*movePerSecond 

     } else { 
      let movePerSecond = pointsPerSecond/direction.y 
      xResult = direction.x*movePerSecond 
      yResult = direction.y*movePerSecond 
     } 
     character!.position = SCNVector3(CGFloat(character!.position.x) + (xResult), CGFloat(character!.position.y), CGFloat(character!.position.z) + (yResult)) 

     let camera = scnView.scene?.rootNode.childNodeWithName("camera", recursively: true) 
     camera?.position = SCNVector3(CGFloat(camera!.position.x) + (xResult), CGFloat(camera!.position.y), CGFloat(camera!.position.z) + (yResult)) 
    } 
    previousTime = time 
} 

override func shouldAutorotate() -> Bool { 
    return true 
} 

override func prefersStatusBarHidden() -> Bool { 
    return true 
} 

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 
    return UIInterfaceOrientationMask.Landscape 
} 
} 

現在這個工作,如果你拖動你的手指在手機的另一端,除了角色移動速度快10倍那麼它將如果你幾乎沒動你的手指。所以我想要的是一個Joy棒,如果你拖動一點或者到屏幕的另一側,它就會以相同的速度移動角色。而且我還希望如果你改變了屏幕另一側的角色,那麼角色會以另一種方式移動。所以,我的猜測是,當touchesMoved被調用時,需要保存lastPoint,以某種方式計算從lastPoint到currentPoint的方向,然後在渲染器中移動該角色。我明白,大部分代碼可能是垃圾,但是要提前感謝。

+0

如果您有興趣,可以在Apple的[使用Xcode場景編輯器構建SceneKit遊戲]中的示例(https://developer.apple.com/library/ios/samplecode/Fox/Listings/Swift_Common_GameControls_swift.html) – mnuages

回答

0

這似乎是一個很好的情況下使用定製UIGestureRecognizer。見Apple API Reference

在這種特殊情況下,您會創建一個連續手勢。結果CGVector將從屏幕上的操縱桿的中心(原點)計算出來。如果未選擇操縱桿節點,則識別器將失敗,如果未選中(取消選擇),則結束。得到的CGVector將被更新,而手勢的狀態是移動

現在要弄清楚的棘手部分就是移動節點圖像,讓用戶能夠感受到操縱桿的感覺。爲此,您可能需要更新節點紋理並對節點位置進行輕微調整,以顯示移動節點的情況。

看看這可以幫助你:Single Rotation Gesture Recognizer

讓我知道,如果這點你在正確的方向。

2

您的操縱桿應該是從0到1的值,您需要確定操縱桿的半徑,然後計算(觸摸到控制中心點的距離)和控制角與弧度之間的距離。

現在我們需要確保我們永遠不會超過maxRadius,所以如果我們的距離> maxRadius,我們將其設置爲最大半徑,然後我們將該值除以我們的maxRadius以獲得距離比。

然後,我們只是取我們角度的cos和sin,然後乘以我們的距離比,得到x和y比值。 (應該介於0和1之間)

最後,取這個x和y值,並將其乘以對象應該移動的速度。

let maxRadius = 100 //Your allowable radius 
let xDist = (p2.x - p1.x) 
let yDist = (p2.y - p1.y) 
let distance = (sqrt((xDist * xDist) + (yDist * yDist)) 
let angle = atan2(yDist , xDist) 
let controlDistanceRatio = (distance > maxRadius) ? 1 : distance/maxRadius 
let controllerX = cos(angle) * controlDistanceRatio 
let controllerY = sin(angle) * controlDistanceRatio 
0

您聲明的問題是角色以可變比率移動,取決於用戶拖動手指的起點距離多遠。在代碼中的關鍵點似乎是這樣的

let direction = CGPoint(x: endPoint.x - point.x, y: endPoint.y - point.y) 

端點與點之間的差異是可變的,所以你得到你的方向可變幅度。爲了簡化,你可以只是把在一個恆定值一樣

let direction = CGPoint(x: 10, y: 10) 

,當用戶按下操縱桿,但性格始終是移動相同的方向得到字符以恆定速度移動。

所以不知何故,你必須在變量方向值中括起來。 ,想到的第一件事就是用最小和最大

let direction = CGPoint(x: endPoint.x - point.x, y: endPoint.y - point.y) 
direction.x = min(direction.x, 10) 
direction.x = max(direction.x, -10) 
direction.y = min(direction.y, 10) 
direction.y = max(direction.y, -10) 

這似乎將保持-10和10之間的方向值這不會讓速度完全恆定的幅度,並且它允許沿着對角線行進的速度要快於平行於x或y軸的行程,但也許它更接近你想要的。