ios - Swift with Spritekit - 带旋钮的操纵杆教程
问题描述
这些天我正在使用 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 轴上移动 - 就像在轨道上的上、下、左、右一样。
我真的理解代码 - 我认为它更像是一个数学问题:)
有人能告诉我如何在轨道上的十字内移动旋钮吗?
解决方案
为了使您的角度保持在十字准线上,您需要将角度四舍五入到 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)
}
推荐阅读
- sql-server - 如何在合并中插入多行?
- sql-server - 高逻辑读
- angular - 如何将角度动画附加到角度水平步进器cdk中的步骤之间的过渡?
- php - mssql_connect 不会连接同一 SQL Server 上的不同数据库
- android - Android Webview 中的电子邮件链接显示为 [email protected]
- liferay - Liferay 7 Eclipse IDE 覆盖默认类别行为
- c# - 如何使用高度和宽度调整 Texture2D 的大小?
- unity3d - Unity 实时 GI - 烘焙导致奇怪的阴影
- azure - 如何在我的应用程序中使用 azure app service env 变量?
- sql-server - 使用 SSIS 加载 .xlsb 文件时连接管理器抛出异常