我有一个游戏,我想根据用户触摸屏幕的左侧或右侧来向左或向右移动SKNode。如何在用户触摸屏幕时对节点应用恒定移动?
发布于 2013-11-26 08:49:03
你真的有三个选择来保持速度。
一种是每次更新都简单地将速度重置回您想要的数量。在本例中,我选择了200,200。这将使您的运动完全静态。
-(void)update:(NSTimeInterval)currentTime {
node.physicsBody.velocity=CGVectorMake(200, 200);
}第二种选择是保留速度,但使用速率因子为运动扭曲留出空间。下面的示例将速度保持为200,200,但不是瞬时的。相反,它将取决于利率。这将使您的运动更加逼真,并且不那么静态。例如,假设您有一个以恒定速度移动的角色,当您更改方向时,您将看到一个微小的加速度,因为它更改为新的恒定速度值,从而使运动中的更改不那么静态,而更具动态性。我强烈推荐这个选项。
-(void)update:(NSTimeInterval)currentTime {
CGFloat rate = .05;
CGVector relativeVelocity = CGVectorMake(200-node.physicsBody.velocity.dx, 200-node.physicsBody.velocity.dy);
node.physicsBody.velocity=CGVectorMake(node.physicsBody.velocity.dx+relativeVelocity.dx*rate, node.physicsBody.velocity.dy+relativeVelocity.dy*rate);
}第三个选择是只设置速度或应用脉冲一次(与我们上面做的每一帧相反),但关闭它的重力和空气阻力。这种方法的问题是,它并不总是保持您的速度。它只会保持恒定的速度,直到受到外力(即摩擦、与另一个物体的碰撞等)的作用。这种方法适用于您希望某些对象以恒定速度移动但仍保持完全动态的情况。如果你想控制和/或保持你的对象速度,我根本不推荐这个选项。我能想到的唯一场景可能是游戏中移动的小行星以恒定的速度在屏幕上漂浮,但仍然受到外力的影响(即两个小行星相撞,这将导致新的恒定速度)。
node.physicsBody.velocity=CGVectorMake(200, 200);
node.physicsBody.linearDamping = 0; //You may want to remove the air-resistance external force.
node.physicsBody.affectedByGravity = false; //You may want to remove the gravity external force这是我在Swift中使用选项2编写的一个示例项目。我尝试与您的描述相匹配。它只是以恒定的速度向左或向右移动节点。请务必使用速率因子进行实验。
import SpriteKit
class GameScene: SKScene {
var sprite: SKSpriteNode!
var xVelocity: CGFloat = 0
override func didMoveToView(view: SKView) {
sprite = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 50))
sprite.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
sprite.physicsBody.affectedByGravity = false
sprite.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
self.addChild(sprite)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch = touches.anyObject() as UITouch
let location = touch.locationInNode(self)
if (location.x<self.size.width/2.0) {xVelocity = -200}
else {xVelocity = 200}
}
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
xVelocity = 0
}
override func update(currentTime: CFTimeInterval) {
let rate: CGFloat = 0.5; //Controls rate of motion. 1.0 instantaneous, 0.0 none.
let relativeVelocity: CGVector = CGVector(dx:xVelocity-sprite.physicsBody.velocity.dx, dy:0);
sprite.physicsBody.velocity=CGVector(dx:sprite.physicsBody.velocity.dx+relativeVelocity.dx*rate, dy:0);
}
}注意:为了实时运动,尽量远离SKActions。仅用于动画。
所谓实时运动,是指对象的位置和速度在其模拟的每一步对您都很重要的运动。而在动画中,您实际上只关心一段时间内的起点和终点。例如,具有移动角色的游戏需要实时运动。您需要能够在模拟中的每个步骤监视角色的位置和速度,并可能以特定的间隔进行调整。但是对于像移动UI元素这样更简单的事情,您不需要在每一步都跟踪它们的运动,所以使用动画
发布于 2013-10-10 13:18:11
添加一个ivar:
CGPoint velocity;设置运动,例如向右移动:
velocity.x = 5;每一步的积分速度:
-(void) update:(NSTimeInterval)currentTime
{
CGPoint pos = self.position;
pos.x += velocity.x;
pos.y += velocity.y;
self.position = pos;
}PS:动作对于连续的操作来说是出了名的不好,特别是移动,因为它们是基于时间的,即应该在一定的持续时间后结束。但是,如果操作的时间在到达目的地之前就用完了怎么办?
发布于 2014-08-01 03:33:17
我直接设置velocity.dx,但是我不推荐这种方法,因为它完全忽略了以前的速度。
public func setSpeed(speed: CGFloat) {
physicsBody.velocity.dx = speed
}我想为你提供一个解决方案,可以更好地与现有的spritekit物理引擎,但我没有一个,我将提供它的赏金,因为我也需要一个解决方案。
对于Swift中的touches,您可以这样做:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
player.setSpeed(100) // You can use touches.anyObject().position to see the touch position and implement left/right movement
}https://stackoverflow.com/questions/19286610
复制相似问题