Objective c SpriteKit-使用物理/速度在一帧内移动对象的精确距离

Objective c SpriteKit-使用物理/速度在一帧内移动对象的精确距离,objective-c,sprite-kit,Objective C,Sprite Kit,我又在为一款定制的Touchengine制作一款曲棍球游戏 我的问题是精确位置更新和物理引擎的结合 示例:每一帧我都得到了触摸的位置。让我们假设上一帧是(100100),现在是(200100)。现在我想要一个带有PhysicsBody的SKNode,它在一帧内从(100100)移动到(200100) 仅仅将速度设置为(100,0)不起作用,因为它的移动方式有所不同。这些动作不会施加任何力。仅仅设置位置也不起作用 有什么想法吗 edit1:我试图将物理对象约束到我刚刚移动的节点。不起作用。这些约束

我又在为一款定制的Touchengine制作一款曲棍球游戏

我的问题是精确位置更新和物理引擎的结合

示例:每一帧我都得到了触摸的位置。让我们假设上一帧是(100100),现在是(200100)。现在我想要一个带有PhysicsBody的SKNode,它在一帧内从(100100)移动到(200100)

仅仅将速度设置为(100,0)不起作用,因为它的移动方式有所不同。这些动作不会施加任何力。仅仅设置位置也不起作用

有什么想法吗

edit1:我试图将物理对象约束到我刚刚移动的节点。不起作用。这些约束似乎只是重置了位置,而没有物理意义。
我还尝试将物理绑定到另一个节点,仅在被物理移动时才适用…

我对物理引擎了解不多,但我相信LearnCos2D不会搜索任何进一步的精确解决方案,但我得到了一个适合我的解决方案:

我使用SpriteKit循环的不同步骤:

-(无效)更新
首先:我使用新的触摸位置来计算新旧位置之间的运动矢量
秒:我将向量乘以某个因子(在我的例子中是15),在一帧中得到几乎相同的距离
-第三:将对象速度设置为此向量

-(无效)模拟物理
(对象现在几乎处于我想要的位置)
为确保物体确实紧贴触摸,请将物体的位置精确设置为触摸位置


我知道,这不是100%,有时会有一些小的重叠,因为物体的位置不完全是它在物理引擎中的位置,但是它已经足够好了。也许系数15可以动态调整,以确保更好的行为,但我不需要它,所以我不使用时间。(不过,如果有人知道更好的解决方案,我很高兴听到Box2D中的

在所需方向上施加一个力,然后,一旦物体到达位置,对物体施加一个逐渐增大的阻尼,直到速度为0,这样效果就不会觉得不自然。一旦物体接近des,你就可以开始施加阻尼但若你们决定改变身体或世界的物理性质,那个么它将是相当不稳定的

就我而言,您可以通过
SKPhysicsBody
velocity
linearDamping
属性在SpriteKit中执行相同的操作

如果阻尼不起作用,你也可以施加相反的力

我没有任何SpriteKit示例,但如果有帮助,我可以在Box2d中提供一个示例

再次编辑以添加此示例。应测试它如何与其他实体交互,并调整一些值以获得所需的效果

-(void)didMoveToView:(SKView *)view {


    /* Setup your scene here */
    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
    self.physicsWorld.gravity = CGVectorMake(0, 0);



    SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
    [sprite setScale:0.5f];
    sprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:sprite.size.width/2];
    sprite.physicsBody.dynamic = YES;
    sprite.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    [self addChild:sprite];
    self.mallet = sprite;

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */

    for (UITouch *touch in touches) {
        self.touchLocation = [touch locationInNode:self];
        self.controlling = YES;

    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    self.touchLocation = [touch locationInNode:self];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    self.controlling = NO;
}

-(void)update:(CFTimeInterval)currentTime {
    if (self.controlling) {
        CGFloat distance = hypotf(self.mallet.position.x - self.touchLocation.x, self.mallet.position.y - self.touchLocation.y);
        CGFloat damping = sqrt(distance * 100);


        if (damping < 0) {
            damping = 0.0f;
        }

        self.mallet.physicsBody.linearDamping = damping;
        self.mallet.physicsBody.angularDamping = damping;

        CGPoint bodyPos = self.mallet.position;
        CGPoint translation = CGPointMake(self.touchLocation.x - bodyPos.x, self.touchLocation.y - bodyPos.y);
        self.mallet.physicsBody.velocity = CGVectorMake(translation.x * 100,
                                                        translation.y * 100);
    }
}
-(void)didMoveToView:(SKView*)视图{
/*在这里设置场景*/
self.physicsBody=[SKPhysicsBody-withedgeloopfromrect:self.frame];
self.physicsWorld.gravity=CGVectorMake(0,0);
SKSpriteNode*sprite=[SKSpriteNode SPRITENODEWITHIMAGENAME:@“宇宙飞船”];
[雪碧设置刻度:0.5f];
sprite.physicsBody=[SKPhysicsBody-withcircleofradius:sprite.size.width/2];
sprite.physicsBody.dynamic=是;
sprite.position=CGPointMake(CGRectGetMidX(self.frame)、CGRectGetMidY(self.frame));
[self addChild:sprite];
self.mallet=精灵;
}
-(无效)触摸开始:(NSSet*)触摸事件:(UIEvent*)事件{
/*当触摸开始时调用*/
用于(UITouch*触摸屏){
self.touchLocation=[touch locationInNode:self];
自我控制=是;
}
}
-(无效)触摸移动:(NSSet*)触摸事件:(UIEvent*)事件{
UITouch*touch=[触摸任何对象];
self.touchLocation=[touch locationInNode:self];
}
-(void)touchesend:(NSSet*)toucheevent:(UIEvent*)event{
自我控制=否;
}
-(无效)更新:(CFTimeInterval)currentTime{
如果(自我控制){
CGFloat distance=hypotf(self.mallet.position.x-self.touchLocation.x,self.mallet.position.y-self.touchLocation.y);
CGFloat阻尼=sqrt(距离*100);
如果(阻尼<0){
阻尼=0.0f;
}
self.mallet.physicsBody.linearDamping=阻尼;
self.mallet.physicsBody.angular阻尼=阻尼;
CGPoint bodyPos=自锤位置;
CGPoint translation=CGPointMake(self.touchLocation.x-bodyPos.x,self.touchLocation.y-bodyPos.y);
self.mallet.physicsBody.velocity=CGVectorMake(translation.x*100,
翻译:y*100);
}
}

除非您完全控制物理(意思是:源代码),否则尝试使用物理引擎实现精确定位/移动几乎是不可能的。我建议寻找其他解决方案。谢谢你的提示,也许我可以学习一些不同的东西,但atm。我被迫使用SpriteKit。我有一些解决方法,对我来说很好。我会把它放在答案部分。是的,这应该是一种空中曲棍球游戏。玩家控制木槌击打冰球,然后弹起在游戏场上。问题是,我不知道在一个帧中将一个物体移动到想要的位置要施加何种力。用户不应该在手指移动和看到的反应之间有任何延迟。所以我不能只是在一个方向上以某种速度移动,然后开始阻尼。从我在其他曲棍球比赛中看到的情况来看,有一个木槌的控制有点延迟,这还不足以影响游戏性。在Box2d中,你可以使用鼠标点来模拟接触点和你试图控制的身体之间的一种绳索。看看另一个问题:无论如何,你的答案可能在任何一个SKPhysicsJoint中。对不起,没有更多的帮助。我可能会