SpriteKit中的持续移动 [英] Constant movement in SpriteKit

查看:237
本文介绍了SpriteKit中的持续移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个游戏,我想向左或向右移动一个SKNode,具体取决于用户是否触摸屏幕的左侧或右侧。当用户触摸屏幕时,如何将恒定运动应用于节点?

I have a game where I would like to move an SKNode left or right depending on if the user touches the left or right side of the screen. How to I apply a constant movement to a node while the user is touching the screen?

推荐答案

您确实有三种保留选项速度。

You really have three options for preserving the velocity.

其中一个就是每次更新时都要将速度重新设置为所需的速度。在这种情况下,我选择了200,200。这将使你的动作完全静止。

One is to simply keep reseting the velocity back to your desired amount every update. In this case I chose 200,200. This will make your motion completely static.

-(void)update:(NSTimeInterval)currentTime {
    node.physicsBody.velocity=CGVectorMake(200, 200);
}

第二个选项是保持速度,但为运动扭曲留出空间比率因子。下面的例子可以将速度保持在200,200但不是瞬间。相反,它取决于速率。这将使您的动作更加逼真,不那么静止。例如,假设您有一个以恒定速度移动的角色并且您改变方向,当它变为新的恒定速度值时,您将看到一个微小的加速度,使得运动中的变化不那么静止且更加动态。我强烈推荐这个选项。

The second option is to preserve the velocity but leave room for motion distortions using a rate factor. The example below would preserve the velocity to 200,200 but not instantaneously. Instead it would depend on the rate. This will make your motion much more realistic and a little less static. For example, lets say you have a character moving at constant speed and you change direction, you will see a tiny acceleration as it changes to the new constant speed value, making the change in motion less static and more dynamic. I highly recommend this option.

-(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);

}

您拥有的第三个选项是设置速度或施加冲动 ONCE (与我们上面所做的每一帧相反),但关闭它的重力和空气阻力。这种方法的问题在于它不会总是保持你的速度。它只会保持恒定的速度,直到外力作用(即摩擦,与另一个身体碰撞等)。这种方法适用于您希望某些对象以恒定速度移动但仍保持完全动态的情况。如果您希望控制和/或保持对象速度,我根本不建议使用此选项。我能想到的唯一场景可能是一个移动小行星的游戏,它以恒定的速度漂浮在屏幕周围,但仍然受到外力的影响(即2个小行星碰撞,这将导致新的恒定速度)。

The third option you have is to just set the velocity or apply an impulse ONCE (as opposed to every frame like we did above), but turn off its gravity and air resistance. The problem with this approach is that it will not always preserve your velocity. It will only keep constant speed until acted on by an external force (i.e. friction, colliding with another body, etc). This approach works for cases where you want some object to move at constant speed but still remain completely dynamic. I don't recommend this option at all if you are looking to control and/or preserve your objects velocity. The only scenario I could think of for this is maybe a game with moving asteroids that float around the screen at constant speed but are still affected by external forces (i.e. 2 asteroids collide which will result in a new constant speed).

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.我尝试匹配您的描述。它只是以恒定速度向左或向右移动节点。请务必尝试使用费率系数。

Here is an example project I wrote in Swift using option 2. I tried to match your description. It simply moves a node left or right at constant speed. Be sure to experiment with the rate factor.

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元素等简单的事情,您不需要在每一步跟踪它们的运动,因此使用动画

By real-time motion, I mean motion in which the position and velocity of your objects are important to you at each step in their simulation. Whereas in animation, you are really only concerned with the start and end points over some duration. For example, a game with moving characters requires real-time motion. You need to be able to monitor at each step in the simulation the positions and velocities of your characters, and potentially make adjustments at certain intervals. But for simpler things like moving UI elements, you don't need to track their motion at each step, so use animation

这篇关于SpriteKit中的持续移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆