首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速制作"Joy stick“

快速制作"Joy stick“
EN

Stack Overflow用户
提问于 2016-08-29 23:15:38
回答 3查看 1.2K关注 0票数 1

我一直在尝试做的是创建一个可以移动玩家的“操纵杆”。这是我到目前为止所知道的:

代码语言:javascript
复制
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倍。所以我想要的是一个操纵杆,如果你拖动一点或者移动到屏幕的另一边,它会以相同的速度移动角色。我也希望如果你在屏幕的另一边改变方向,角色就会朝另一边移动。因此,我的猜测是,需要保存一个lastPoint,然后当调用touchesMoved时,我们以某种方式计算从lastPoint到currentPoint的方向,然后在渲染器中移动角色。我知道这段代码中的大部分可能都是垃圾,但还是要提前谢谢你。

EN

回答 3

Stack Overflow用户

发布于 2016-08-30 00:29:27

你的操纵杆应该是一个从0到1的值,你需要确定你的操纵杆的半径,然后计算距离(触摸到控制中心的点)和控制的角度。

现在我们需要确保我们永远不会超过半径,所以如果我们的距离> maxRadius,我们只需要将它设置为最大半径,然后我们将这个值除以我们的maxRadius得到距离比。

然后我们只需取角度的cos和sin,并将其乘以距离比,就可以得到x和y的比值。(应介于0和1之间)

最后,取此x和y值,并将其乘以您的对象应该移动的速度。

代码语言:javascript
复制
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
票数 2
EN

Stack Overflow用户

发布于 2016-08-30 00:06:24

这似乎是一个使用自定义UIGestureRecognizer.的好例子参见Apple API Reference

在这种情况下,您将创建一个连续的手势。生成的CGVector将从屏幕上操纵杆的中心(原点)计算得出。如果未选中操纵杆节点,识别器将失败;如果未选中(取消选中),识别器将终止。当手势的状态为moved时,生成的CGVector将被更新。

现在,要弄清楚的棘手部分是以这样一种方式移动节点图像,使用户有操纵杆的感觉。为此,您可能需要更新节点纹理并对节点位置进行细微调整,以提供四处移动节点的外观。

看看这是否对你有帮助:Single Rotation Gesture Recognizer

如果这给你指明了正确的方向,请告诉我。

票数 0
EN

Stack Overflow用户

发布于 2016-08-30 00:35:41

你所说的问题是角色以不同的速率移动,这取决于用户拖动手指离起始点有多远。代码中的关键点似乎是这样的

代码语言:javascript
复制
let direction = CGPoint(x: endPoint.x - point.x, y: endPoint.y - point.y)

endPoint和point之间的差异是可变的,所以你在你的方向上得到了一个可变的幅度。为了简化,您可以只放入一个常量值,如

代码语言:javascript
复制
let direction = CGPoint(x: 10, y: 10)

当用户按下操纵杆时,这会使角色以恒定的速度移动,但角色总是朝同一方向移动。

所以你必须在变量的方向值中加上括号。首先想到的是使用min和max

代码语言:javascript
复制
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轴的移动更快,但也许它更接近于您想要的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39209661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档