iGe*_*tIt 17 sprite-kit swift swift3
我创建了两条固定在精灵上的线,相距30˚.我希望两条线像摆锤一样左右摆动,总是从一端到另一端摆动(这样它们在它们的初始位置的左右摆动45°).请看下面我想要实现的目标:
以下是我能够实现的代码:
extension Int {
var degreesToRadians: Double { return Double(self) * .pi / 180 }
}
extension FloatingPoint {
var degreesToRadians: Self { return self * .pi / 180 }
var radiansToDegrees: Self { return self * 180 / .pi }
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var anchorSprite = SKSpriteNode(imageNamed: "swingPin")
var armLeft = SKSpriteNode(imageNamed: "swingArm")
var armRight = SKSpriteNode(imageNamed: "swingArm")
override func didMove(to view: SKView) {
self.physicsWorld.gravity = CGVector(dx: 0, dy: -1.8)
self.physicsWorld.contactDelegate = self
var tealBg = SKSpriteNode(imageNamed: "tealBg")
tealBg.position = CGPoint(x: frame.midX, y: frame.midY)
tealBg.zPosition = 10
addChild(tealBg)
anchorSprite.position = CGPoint(x: frame.midX, y: frame.midY + frame.midY/2)
anchorSprite.zPosition = 20
anchorSprite.physicsBody = SKPhysicsBody(rectangleOf: anchorSprite.frame.size)
anchorSprite.physicsBody?.categoryBitMask = pinCategory
anchorSprite.physicsBody?.isDynamic = false
addChild(anchorSprite)
armRight.anchorPoint = CGPoint(x: 0.5, y: 1)
armRight.position = anchorSprite.position
armRight.zPosition = 20
armRight.physicsBody = SKPhysicsBody(rectangleOf: armRight.frame.size)
armRight.zRotation = CGFloat(Double(15).degreesToRadians)//CGFloat(Double.pi/6)
armRight.physicsBody!.isDynamic = true
addChild(armRight)
armLeft.anchorPoint = CGPoint(x: 0.5, y: 1)
armLeft.position = anchorSprite.position
armLeft.zPosition = 20
armLeft.physicsBody = SKPhysicsBody(rectangleOf: armRight.frame.size)
armLeft.zRotation = CGFloat(Double(-15).degreesToRadians)//CGFloat(-Double.pi/6)
armLeft.physicsBody!.isDynamic = true
addChild(armLeft)
// Create joint between two objects
//Pin joint
var pinAndRightArmJoint = SKPhysicsJointPin.joint(withBodyA: anchorSprite.physicsBody!, bodyB: armRight.physicsBody!, anchor: CGPoint(x: anchorSprite.position.x, y: self.armRight.frame.maxY))
self.physicsWorld.add(pinAndRightArmJoint)
var pinAndLeftArmJoint = SKPhysicsJointPin.joint(withBodyA: anchorSprite.physicsBody!, bodyB: armLeft.physicsBody!, anchor: CGPoint(x: anchorSprite.position.x, y: self.armLeft.frame.maxY))
self.physicsWorld.add(pinAndLeftArmJoint)
var fixArms = SKPhysicsJointFixed.joint(withBodyA: armLeft.physicsBody!, bodyB: armRight.physicsBody!, anchor: CGPoint.zero)
self.physicsWorld.add(fixArms)
pinAndRightArmJoint.shouldEnableLimits = true
pinAndRightArmJoint.lowerAngleLimit = CGFloat(Double(-60).degreesToRadians)
pinAndRightArmJoint.upperAngleLimit = CGFloat(Double(60).degreesToRadians)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//armRight.physicsBody?.angularVelocity = -100.0
let seq = SKAction.sequence([
SKAction.rotate(byAngle: CGFloat(Double(45).degreesToRadians), duration: 0.5),
SKAction.rotate(byAngle: CGFloat(Double(-45).degreesToRadians), duration: 1.0),
SKAction.rotate(byAngle: CGFloat(Double(45).degreesToRadians), duration: 1.0),
SKAction.rotate(byAngle: CGFloat(Double(-45).degreesToRadians), duration: 1.0),
SKAction.rotate(byAngle: CGFloat(Double(45).degreesToRadians), duration: 1.0),
SKAction.rotate(byAngle: CGFloat(Double(-45).degreesToRadians), duration: 1.0)
])
armRight.run(seq)
}
Run Code Online (Sandbox Code Playgroud)
从上面的代码我设置了较低和较高的角度限制,并尝试运行一个动作,但这只是使线条以一种非常不切实际的方式横向倾斜.我也尝试在物理体上应用角速度,但这只是使它以不一致的速度短暂摆动(我需要它从一端到另一端一致地摆动).
NB
由于每次都需要它从头到尾摆动,我需要摆动周期每次都保持一致,不一定是恒定的.当线条移动到中心时,一个周期通常会更快地摆动,而当从一个方向改变到另一个方向时,一个周期会减慢一点.这就是我想要运动的感觉.
这是实际的答案:
替换addChild(armRight)为anchorSprite.addChild(armRight).替换addChild(armLeft)为anchorSprite.addChild(armLeft).删除armRight.position = anchorSprite.position并删除armLeft.position = anchorSprite.position.此外,除非您在代码中使用物理关节进行其他移动,否则请删除所有这些,因为我的解决方案不需要关节.
现在你的手臂是儿童,anchorSprite并受到其坐标系统的影响.如果要同时在同一方向旋转两个手臂,可以在anchorSprite上运行旋转动作.如果您希望手臂朝不同方向旋转,则必须分别在每个手臂上执行旋转动作.对于这两种情况,你可以使用我为这个问题上的赏金所做的这个方便的功能:-P
func runPendulumRotationOnNode(_ node:SKNode, withAngle angle:CGFloat, period:TimeInterval, key:String) {
let initialRotate = SKAction.rotate(byAngle: angle/2, duration: period/2)
initialRotate.timingMode = .easeOut
let rotate = SKAction.rotate(byAngle: angle, duration: period)
rotate.timingMode = .easeInEaseOut
let rotateForever = SKAction.repeatForever(SKAction.sequence([rotate.reversed(), rotate]))
let rotateSequence = SKAction.sequence([initialRotate, rotateForever])
node.run(rotateSequence, withKey:key)
}
Run Code Online (Sandbox Code Playgroud)
我测试过它,效果很好!您可以像这样调用它来将两个手臂旋转在一起:
runPendulumRotationOnNode(anchorSprite, withAngle:CGFloat.pi/2, period:0.5, key:"")
Run Code Online (Sandbox Code Playgroud)
或者以相反的方向旋转手臂,您可以像这样使用它:
runPendulumRotationOnNode(armRight, withAngle:CGFloat.pi/2, period:0.5, key:"")
runPendulumRotationOnNode(armLeft, withAngle:-CGFloat.pi/2, period:0.5, key:"")
Run Code Online (Sandbox Code Playgroud)
一些小笔记,注意我的使用方式CGFloat.pi,π的简单常数.此功能还假设摆锤在旋转的中点开始,因此π/ 2(90度)将使臂π/ 4(45度)向任一方向旋转.