我现在正在使用Swift进行SpriteKit教程。
我用一个旋钮对操纵杆进行了编程,旋钮可以在操纵杆圈内的任何位置移动。
以下是相关的代码段:
for touch in touches {
let position = touch.location(in: joystick)
let length = sqrt(pow(position.y, 2) + pow(position.x, 2))
let angle = atan2(position.y, position.x)
if knobRadius > length {
joystickKnob.position = position
} else {
joystickKnob.position = CGPoint(x: cos(angle) * knobRadius, y: sin(angle) * knobRadius)
}}
以下是教程中的图片:
但现在我想这样做有点不同。
我希望旋钮只能在X和Y轴上像十字架一样移动 - 如上,下,左,右在轨道上。
我真的理解代码 - 我认为它更像是一个数学问题:)
有人能告诉我如何在铁轨上的十字架内移动旋钮吗?
答案 0 :(得分:1)
因此,您希望将angle
约束为.pi / 2
(90度)的倍数。 atan2
函数返回-.pi ... +.pi
范围内的值。将它从弧度转换为四分之一转(直角)单位,舍入为整数,然后转换回弧度。
let touchAngle = atan2(position.y, position.x) // -.pi ... +.pi
let quarterTurns = touchAngle * 2 / .pi // -2 ... +2
let integralQuarterTurns = quarterTurns.rounded() // -2, -1, 0, +1, or +2
let angle = integralQuarters * .pi / 2
或者,查看abs(position.x)
和abs(position.y)
中哪一个更大,并使用它来确定angle
:
let angle: CGFloat
switch abs(position.x) > abs(position.y) {
case true where position.x > 0: angle = 0
case true where position.x < 0: angle = .pi
case false where position.y > 0: angle = .pi / 2
case false where position.y < 0: angle = .pi / -2
default: angle = 0 // position == .zero so joystick is actually centered
}
答案 1 :(得分:1)
要使角度保持在十字准线上,您需要将角度四舍五入到pi / 2
的间隔这样做,只需:
angle = (angle * 2 / CGFloat.pi).rounded() * (CGFloat.pi / 2)
下面我修改了你的代码以便更好地工作,并允许你避免分支。
我使用的是基本半径而不是旋钮半径,因此您永远不会超过基数。
for touch in touches {
let position = touch.location(in: joystick)
let radius = min(baseRadius,sqrt(pow(position.y, 2) + pow(position.x, 2))
// a nicer way to get radius
//let radius = min(baseRadius,position.distance(to:CGPoint.zero))
let angle = atan2(position.y, position.x)
if crossHairStick
{
angle = (angle * 2 / CGFloat.pi).rounded() * (CGFloat.pi / 2)
}
joystickKnob.position = CGPoint(x: cos(angle) * radius, y: sin(angle) * radius)
}
如果要将旋钮保持在底座内,请减去旋钮半径。 (这假设两个半径都是正的,否则使用半径的绝对值)
for touch in touches {
let position = touch.location(in: joystick)
let radius = min(baseRadius - knobRadius,sqrt(pow(position.y, 2) + pow(position.x, 2))
let angle = atan2(position.y, position.x)
if crossHairStick
{
angle = (angle * 2 / CGFloat.pi).rounded() * (CGFloat.pi / 2)
}
joystickKnob.position = CGPoint(x: cos(angle) * radius, y: sin(angle) * radius)
}