- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
简介
我正在使用 ARKit 在增强现实中设计一款 iPhone 游戏。我的游戏的一部分涉及用户滑动以将球扔向目标。我的目的是创建一个向量,其中包含目标的 y 值和 z 值,但包含用户滑动位置的 x 值。然而,在测试这个系统时,球总是向左移动。我认为这是我使用的轴的问题,但我无法理解如何更改它。目标可以是 AR 世界中飞机上的任何地方。
图像中提供了描述。用户从球上滑动,球应向目标的 y 和 z 坐标以及滑动结束位置的 x 值移动。
当前代码
我使用的大部分代码都是基于以下 Tutorial on RayWenderlich.com .
我首先实现 touchesBegan 和 touchesEnded 函数,如下所示,以计算滑动的终点和滑动的速度:
var startTouch: UITouch?
var endTouch: UITouch?
var startTouchTime: TimeInterval!
var endTouchTime: TimeInterval!
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if self.currentMode == .throwingProjectiles {
guard let firstTouch = touches.first else { return }
let point = firstTouch.location(in: sceneView)
let hitResults = sceneView.hitTest(point, options: [:])
if hitResults.first?.node == projectileIndicator {
startTouch = touches.first
startTouchTime = Date().timeIntervalSince1970
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard startTouch != nil else { return }
endTouch = touches.first
endTouchTime = Date().timeIntervalSince1970
throwBall()
}
然后我按如下方式实现 throwBall() 函数:
func throwBall() {
guard let endingTouch = endTouch else { return }
let firstTouchResult = sceneView.hitTest(
endingTouch.location(in: sceneView),
options: nil
).filter({
$0.node == targetNode || $0.node == floorNode
}).first
guard let touchResult = firstTouchResult else {return}
let vp = endingTouch.location(in: sceneView)
let vpWithDepth = SCNVector3Make(Float(vp.x), Float(vp.y), 0)
let scenePoint = sceneView.unprojectPoint(vpWithDepth)
let timeDifference = ( endTouchTime - startTouchTime)/4
let velocityComponent = Float(min(max(1 - timeDifference, 0.1), 10.0))
let impulseVector = SCNVector3(
x: scenePoint.x,
y: targetNode.worldPosition.y + 1.005 * velocityComponent * 5,
z: targetNode.worldPosition.z * velocityComponent * 10
)
spawnProjectile()
currentBallNode?.name = "Ball"
balls.append(currentBallNode!)
currentBallNode?.physicsBody?.applyForce(impulseVector, asImpulse: true)
currentBallNode = nil
startTouchTime = nil
endTouchTime = nil
startTouch = nil
endTouch = nil
}
取消项目点代码来自这里:https://stackoverflow.com/a/25154025/6642130
所以我的问题是,我如何促进这种 throw ?
最佳答案
我修复了滑动,这看起来很完美。当我发现如何完美地做到这一点时,我改变了答案。我使用一个 PanGestureRecognizer,它被拖到我的 ARview sceneView 中。
@objc func handlePan(recognizer : UIPanGestureRecognizer) {
guard let food = foodToShot else {return}
//If removes the finger or something
if recognizer.state == .cancelled {
food.removeFromParentNode()
//If it actually shoots
} else if recognizer.state == .ended {
//I do something only when direction makes sense - MARK: MAYBE STUDY THIS
switch recognizer.direction {
case .bottomToTop :
//Takes swipe velocity in CGFloat/seconds
let velocity = recognizer.velocity(in: sceneView)
//Calculate V
let magnitude = sqrt((velocity.x * velocity.x) + (velocity.y * velocity.y))
//Adjustements to have a decent not too fast velocity
let slideMultiplier = magnitude / 200
let slideFactor = 0.1 * slideMultiplier
//I save current frame
let currentFrame = self.sceneView.session.currentFrame!
//Creation of physicalBody
let foodPhysicsBody = SCNPhysicsBody(
type: .dynamic,
shape: SCNPhysicsShape(geometry: SCNSphere(radius: 0.04))
)
foodPhysicsBody.isAffectedByGravity = true
//Collisions
foodPhysicsBody.categoryBitMask = CollisionCategory.food.rawValue
foodPhysicsBody.categoryBitMask = CollisionCategory.floor.rawValue
foodPhysicsBody.contactTestBitMask = CollisionCategory.food.rawValue
foodPhysicsBody.mass = 3
foodPhysicsBody.restitution = 0.75
foodPhysicsBody.damping = 0.1
foodPhysicsBody.friction = 2
food.physicsBody = foodPhysicsBody
//Calculate with my V and Vx and my acot modified function
let closeTranslation = simd_make_float4(0,Float(acotForSwipes(x: Double(magnitude / velocity.x))),-1.2,0)
let rotatedForce = simd_mul(currentFrame.camera.transform, closeTranslation)
//Calculate force
let force = SCNVector3Make(rotatedForce.x, rotatedForce.y, rotatedForce.z)
//I give force to physicBody
food.physicsBody?.applyForce(force * SCNFloat(slideFactor) * 15, asImpulse: true)
//I don't care about other swipes
case .leftToRight:
return
case .rightToLeft:
return
case .topToBottom:
return
case .undefined:
return
}
}
}
这是我的反正切函数,针对滑动进行了修改:
//Arcotangent modified to suit my swipe needs
func acotForSwipes(x : Double) -> Double {
if x > 1.0 || x < -1.0{
return atan(1.0/x)
} else {
return .pi/2 - atan(x)
}
}
最后,如果您关心的话,这是 panGestureRecognizer 的扩展
public enum UIPanGestureRecognizerDirection {
case undefined
case bottomToTop
case topToBottom
case rightToLeft
case leftToRight
}
public enum TransitionOrientation {
case unknown
case topToBottom
case bottomToTop
case leftToRight
case rightToLeft
}
extension UIPanGestureRecognizer {
public var direction: UIPanGestureRecognizerDirection {
let velocity = self.velocity(in: view)
let isVertical = abs(velocity.y) > abs(velocity.x)
var direction: UIPanGestureRecognizerDirection
if isVertical {
direction = velocity.y > 0 ? .topToBottom : .bottomToTop
} else {
direction = velocity.x > 0 ? .leftToRight : .rightToLeft
}
return direction
}
public func isQuickSwipe(for orientation: TransitionOrientation) -> Bool {
let velocity = self.velocity(in: view)
return isQuickSwipeForVelocity(velocity, for: orientation)
}
private func isQuickSwipeForVelocity(_ velocity: CGPoint, for orientation: TransitionOrientation) -> Bool {
switch orientation {
case .unknown : return false
case .topToBottom : return velocity.y > 1000
case .bottomToTop : return velocity.y < -1000
case .leftToRight : return velocity.x > 1000
case .rightToLeft : return velocity.x < -1000
}
}
}
extension UIPanGestureRecognizer {
typealias GestureHandlingTuple = (gesture: UIPanGestureRecognizer? , handle: (UIPanGestureRecognizer) -> ())
fileprivate static var handlers = [GestureHandlingTuple]()
public convenience init(gestureHandle: @escaping (UIPanGestureRecognizer) -> ()) {
self.init()
UIPanGestureRecognizer.cleanup()
set(gestureHandle: gestureHandle)
}
public func set(gestureHandle: @escaping (UIPanGestureRecognizer) -> ()) {
weak var weakSelf = self
let tuple = (weakSelf, gestureHandle)
UIPanGestureRecognizer.handlers.append(tuple)
addTarget(self, action: #selector(handleGesture))
}
fileprivate static func cleanup() {
handlers = handlers.filter { $0.0?.view != nil }
}
@objc private func handleGesture(_ gesture: UIPanGestureRecognizer) {
let handleTuples = UIPanGestureRecognizer.handlers.filter{ $0.gesture === self }
handleTuples.forEach { $0.handle(gesture)}
}
}
extension UIPanGestureRecognizerDirection {
public var orientation: TransitionOrientation {
switch self {
case .rightToLeft: return .rightToLeft
case .leftToRight: return .leftToRight
case .bottomToTop: return .bottomToTop
case .topToBottom: return .topToBottom
default: return .unknown
}
}
}
extension UIPanGestureRecognizerDirection {
public var isHorizontal: Bool {
switch self {
case .rightToLeft, .leftToRight:
return true
default:
return false
}
}
}
如果有人觉得这个答案有帮助,请告诉我,这是我第一次回答 :)
关于swift - 如何根据用户手势在 SceneKit 中正确实现 throw 弹丸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47464555/
有没有办法在 .swift 文件(编译成 .swift 模块)中声明函数,如下所示: 你好.swift func hello_world() { println("hello world")
我正在尝试使用 xmpp_messenger_ios 和 XMPPFramework 在 iOS 上执行 MUC 这是加入房间的代码。 func createOrJoinRoomOnXMPP()
我想在我的应用程序上创建一个 3D Touch 快捷方式,我已经完成了有关快捷方式本身的所有操作,它显示正确,带有文本和图标。 当我运行这个快捷方式时,我的应用程序崩溃了,因为 AppDelegate
我的代码如下: let assetTag = Expression("asset_tag") let query2 = mdm.select(mdm[assetTag],os, mac, lastRe
我的 swift 代码如下所示 Family.arrayTuple:[(String,String)]? = [] Family.arrayTupleStorage:String? Family.ar
这是我的 JSON,当我读取 ord 和 uniq 数据时出现错误 let response2 : [String: Any] = ["Response":["status":"SUCCESS","
我想将 swift 扩展文件移动到 swift 包中。但是,将文件移动到 swift 包后,我遇到了这种错误: "Type 'NSAttributedString' has no member 'ma
使用CocoaPods,我们可以设置以下配置: pod 'SourceModel', :configurations => ['Debug'] 有什么方法可以用 Swift Package Manag
我正在 Xcode 中开发一个 swift 项目。我将其称为主要项目。我大部分都在工作。我在日期选择器、日期范围和日期数学方面遇到了麻烦,因此我开始了另一个名为 StarEndDate 的项目,其中只
这是 ObjectiveC 代码: CCSprite *progress = [CCSprite spriteWithImageNamed:@"progress.png"]; mProgressBar
我正在创建一个命令行工具,在 Xcode 中使用 Swift。我想使用一个类似于 grunt 的配置文件确实如此,但我希望它是像 Swift 包管理器的 package.swift 文件那样的快速代码
我假设这意味着使用系统上安装的任何 swift 运行脚本:#!/usr/bin/swift 如何指定脚本适用的解释器版本? 最佳答案 Cato可用于此: #!/usr/bin/env cato 1.2
代码说完全没问题,没有错误,但是当我去运行模拟器的时候,会出现这样的字样: (Swift.LazyMapCollection (_base:[ ] 我正在尝试创建一个显示报价的报价应用。 这是导入
是否可以在运行 Swift(例如 Perfect、Vapor、Kitura 等)的服务器上使用 RealmSwift 并使用它来存储数据? (我正在考虑尝试将其作为另一种解决方案的替代方案,例如 no
我刚开始学习编程,正在尝试完成 Swift 编程书中的实验。 它要求““编写一个函数,通过比较两个 Rank 值的原始值来比较它们。” enum Rank: Int { case Ace = 1 ca
在您将此问题标记为重复之前,我检查了 this question 它对我不起作用。 如何修复这个错误: error: SWIFT_VERSION '5.0' is unsupported, suppo
从 Xcode 9.3 开始,我在我的模型中使用“Swift.ImplicitlyUnwrappedOptional.some”包裹了我的字符串变量 我不知道这是怎么发生的,但它毁了我的应用程序! 我
这个问题在这里已经有了答案: How to include .swift file from other .swift file in an immediate mode? (2 个答案) 关闭 6
我正在使用 Swift Package Manager 创建一个应用程序,我需要知道构建项目的配置,即 Debug 或 Release。我试图避免使用 .xcodeproj 文件。请有人让我知道这是否
有一个带有函数定义的文件bar.swift: func bar() { println("bar") } 以及一个以立即模式运行的脚本foo.swift: #!/usr/bin/xcrun s
我是一名优秀的程序员,十分优秀!