![](/img/trans.png)
[英]How do I change background colour programmatically in swift using SpriteKit
[英]How do I applyImpulse at a certain angle in SpriteKit using Swift 5?
我试图在一个 iOS 游戏中向 touchEnded 方法的方向扔一个球。 我已经搜索了许多线程,但有些线程很旧,而对于其他线程,我无法弄清楚问题所在。
我正在尝试做的事情如下:
1- 添加一个球作为 SKShapeNode - 将受影响的重力设置为 false。
2- 在 touchesEnded - 我得到了位置 CGPoint(不知何故我得到了 y position 反转 - 我更正了)。
3- 我使用 atan() 计算角轴承。
4- 我根据角度的 sin() 和 cos() 计算 CGVector dx 和 dy 脉冲。
5- 我根据上面的 CGVector 对球应用Impulse。
我的问题是球没有完全按照 touchesEnded 方向射出。 如果 touchesEnded 方向在球的垂直下方,那么它可以工作。 离垂直越远,偏差越大。
为了帮助解决问题并将问题可视化,我添加了一条线并在球应该遵循的方向结束蓝色球。 理想情况下,红球应该与蓝球相撞。 但是,我得到的真正方向是添加的绿球。 理想情况下,绿球应该在线上。
我试图完全像这里所做的那样做,但我没有得到结果: SpriteKit 物理 applyImpulse in direction
感谢你的帮助。 '''
import SpriteKit
class GameScene: SKScene {
var sprite = SKShapeNode()
var radius: CGFloat = 10
var ballSpawnPosition: CGPoint = CGPoint(x: 0, y: 0)
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
ballSpawnPosition = CGPoint(x: frame.midX, y: frame.maxY - 50)
spawnBall()
}
func spawnBall() {
sprite = SKShapeNode(circleOfRadius: radius)
sprite.physicsBody = SKPhysicsBody(circleOfRadius: radius)
sprite.physicsBody?.collisionBitMask = 0x1
sprite.fillColor = .red
sprite.position = ballSpawnPosition
addChild(sprite)
sprite.physicsBody?.affectedByGravity = false
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: view)
let blueTestTouchPointBall = SKShapeNode(circleOfRadius: radius)
blueTestTouchPointBall.physicsBody = SKPhysicsBody(circleOfRadius: radius)
blueTestTouchPointBall.physicsBody?.categoryBitMask = 0x1
blueTestTouchPointBall.fillColor = .blue
let y = frame.size.height - position.y
blueTestTouchPointBall.position = CGPoint(x: position.x, y: y)
blueTestTouchPointBall.physicsBody?.affectedByGravity = false
addChild(blueTestTouchPointBall)
var path = CGMutablePath()
path.move(to: ballSpawnPosition)
path.addLine(to: CGPoint(x: position.x, y: y))
path.closeSubpath()
let line = SKShapeNode()
line.path = path
line.strokeColor = .white
line.lineWidth = 2
addChild(line)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first { //should not work if dragged.
let position = touch.location(in: view)
let dx = position.x - ballSpawnPosition.x
let dy = frame.size.height - abs( position.y - ballSpawnPosition.y)
let ang = atan(abs(dx)/abs(dy))
//let tang = sqrt(dx*dx + dy*dy)
let impulse: CGFloat = 15.0
let x_impulse = impulse * sin(ang) * dx/abs(dx)
let y_impulse = -1.0 * impulse * cos(ang)
// let x_impulse = impulse * dx/abs(dx) * dx/tang
// let y_impulse = impulse * -1 * dy/tang
sprite.physicsBody?.applyImpulse(CGVector(dx: x_impulse , dy: y_impulse ))
let greenTestBall = SKShapeNode(circleOfRadius: radius/2)
greenTestBall.fillColor = .green
greenTestBall.position = CGPoint(x: ballSpawnPosition.x + 300 * sin(ang) * dx/abs(dx), y: ballSpawnPosition.y - 300 * cos(ang) )
addChild(greenTestBall)
}
}
}
'''
您正在不同坐标系中混合点。 应该使用UITouch
的location(in:)
方法并传入SKNode
将UITouch
的位置转换为球所在的节点(通常是场景,但也可以是另一个节点)。 有关 SpriteKit 中坐标转换的更多信息,请参见此处。 由于球是场景的孩子,所以改变
let position = touch.location(in: view)
至
let position = touch.location(in: self) // i.e. the `GameScene`
假设您使用球生成 position 作为参考点并且相对于垂直方向取角度,则还需要调整角度计算。 改变
let dy = frame.size.height - abs(position.y - ballSpawnPosition.y)
至
let dy = abs(position.y - ballSpawnPosition.y)
更改上述内容会创建我相信您正在寻找的内容。 请注意,动量是相加的:在球向左移动时向右施加冲量不一定会导致球开始向左移动(除非冲量足够大)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.