2017-02-14 10 views
0

スプライトに物理ボディがあります。スプライトがいずれかの方向に移動すると、物理ボディはその方向に移動します(添付の画像を参照)。これは接触と衝突に悪いことです。スプライトキット:移動中に物理ボディが移動した

物理的なボディは、移動中にのみ移動します。スプライトが静止していると、物理学のボディはずれることはありません。

私の質問: スプライトキットの物理方向が移動方向にずれているのはなぜですか?それを防ぐ方法はありますか?

どうもありがとう

EDIT:

OK ..私はこの問題を示すために小さなテストを書きました。重力の影響を受けていない物理的なボディを持つノードは1つしかありません。物理学の世界にも重力はありません。スクリーンに触れることで、ヒーローが上に移動します。コードをテストしたい場合は、SKView showsPhysicsプロパティ= YESを設定します。タッチすることで、物理的な体が正しい場所からどのように動くかを観察します。その後、移動のたびに移動方向に移動します。

ありがとうございます。

// header file 

#import <SpriteKit/SpriteKit.h> 

@interface TestScene : SKScene <SKPhysicsContactDelegate> 

@end 


// implementation file 


#import "TestScene.h" 

@implementation TestScene 
{ 
    SKNode *_world; 
    SKSpriteNode *_hero; 

    BOOL _play; 
    BOOL _touch; 
    CGFloat _startY; 
} 

- (instancetype)initWithSize:(CGSize)size 
{ 
    if(self = [super initWithSize:size]) 
    { 
     self.backgroundColor = [SKColor whiteColor]; 
     self.physicsWorld.contactDelegate = self; 
     // no gravity 
     //self.physicsWorld.gravity = CGVectorMake(0.0f, -9.8f); 

     _play = NO; 
     _touch = NO; 
     _startY = 50; 

     [self addWorld]; 
     [self addHero]; 
    } 

    return self; 
} 

- (void)addWorld 
{ 
    _world = [SKNode node]; 
    _world.position = CGPointMake(0, 0); 
    [self addChild:_world]; 
} 

- (void)addHero 
{ 
    _hero = [SKSpriteNode spriteNodeWithImageNamed:@"hero"]; 
    _hero.size = CGSizeMake(50, 50); 
    _hero.position = CGPointMake(CGRectGetMidX(self.frame), _startY); 
    [_world addChild:_hero]; 

    _hero.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_hero.size.width/2.0f]; 
    _hero.physicsBody.affectedByGravity = NO; 
    _hero.physicsBody.dynamic = YES; 
    _hero.physicsBody.allowsRotation = NO; 
} 

- (void)applyHeroUpwardForce 
{ 
    [_hero.physicsBody applyForce:(CGVectorMake(0, 100))]; 

    // limit velocity 
    CGVector vel = _hero.physicsBody.velocity; 
    vel.dy = vel.dy > 1000 ? 1000 : vel.dy; 
    _hero.physicsBody.velocity = vel; 

    // control the hero movement. it really moves upwards even we don’t see that, since the _world moves downwards 
    NSLog(@"_hero.position.y: %f", _hero.position.y); 
} 

- (void)updateWorld 
{ 
    _world.position = CGPointMake(_world.position.x, -(_hero.position.y - _startY)); 
} 

- (void)didSimulatePhysics 
{ 
    if(!_play) 
     return; 

    if(_touch) 
    { 
     [self applyHeroUpwardForce]; 
     [self updateWorld]; 
    } 

} 

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    if(!_play) 
     _play = YES; 

    _touch = YES; 
} 

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    _touch = NO; 
} 

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    _touch = NO; 
} 

@end 

enter image description here


EDIT 2:

The same issue in the game 'Pierre Penguin Escapes The Antarctic'

enter image description here

+0

私は本当にあなたが求めていることを理解していません。もちろん、物理学のボディはスプライトと一緒に動きますが、なぜあなたはそれを望んでいませんか? – Pierce

+0

関連するコードをアップロードする必要があります... – Whirlwind

+0

はい、物理ボディはスプライトと共に移動します。しかし、物理学の身体は追い出される。添付の画像をご覧ください。ミサイルが裏側の宇宙船に当たった場合、宇宙船の物理的ボディが添付の画像に示すように前面に移動するため、接触/衝突は発生しません – suyama

答えて

0

、(リンゴのドキュメンタリーで説明)この問題の最善の解決策:またはdidEndContact:

はdidBeginContact内のフラグを設定し、更新でそのフラグに応じて変更 を行いますforScene : SKSceneDelegateのメソッド:それだ

@implementation TestScene 
{ 
    // . . . 

    BOOL _didBeginContact; 
    SKPhysicsContact *_contact; 
} 


- (instancetype)initWithSize:(CGSize)size 
{ 
    if(self = [super initWithSize:size]) 
    { 
     // . . . 

     _didBeginContact = NO; 
     _contact = nil; 
    } 

    return self; 
} 

- (void)didBeginContact:(SKPhysicsContact *)contact 
{ 
    // to be on the safe side: avoid multiple contacts 
    if(_didBeginContact || _contact) 
     return; 

    // set your variables which you maybe need in your contact method 

    _contact = contact; 
    _didBeginContact = YES; 
} 

- (void)didContact 
{ 
    // to be on the safe side 
    if(_contact == nil) 
     return; 

    // what ever you need during/after contact. 
    // use _contact set in didBeginContact: 

    if(_contact.bodyA.categoryBitMask // what ever 
    if(_contact.bodyB.categoryBitMask // what ever 
    // etc. 

    // . . . 

    // important 
    _contact = nil; 
} 

- (void)update:(NSTimeInterval)currentTime 
{ 
    // if contact happens, so call your contact: method 
    if(_didBeginContact) 
    { 
     _didBeginContact = NO; // important 
     [self didContact]; 
    } 
} 

。ありがとうございます。

0

あなたはphysiを初期化した場合cs本体を親ノードから外す必要があります。 はい、物理学のボディは動くでしょうが、正確に同じパスがノードを動かすでしょう。 物理的なボディの形状を確認してください。

+0

すみません。私はあなたが何を意味するのか理解していません。「あなたが物理学の身体を適切に初期化すると、親ノードからはずれるはずです。物理学の身体は、運動中、そしてその時だけ移動される。スプライトが静止しているとき、物理体はスプライトの周りに正確です。 – suyama

+0

@suyamaノードが停止するとどうなりますか?まだそれは移住しているのか? – Whirlwind

+0

@Whirlwindノードが停止すると、フィジックスボディがずれることはありません。物理学のボディは、ノードが動いているときだけ移動します。私は、ノードの位置を変えてノードを移動させます。私はノードを移動するためにアクションを使用しません。 – suyama

1

SpriteKitでは、物理コンタクトハンドラのデリゲートメソッドでスプライトの位置を更新する場合にこれが発生することがあります。

コールバックデリゲートメソッド内の配下のノードの位置/回転/スケールを更新しないでください。代わりに、物理コールバック内で行われる必要な更新を識別して追跡するメカニズムを用意し、ノードの変更を適用するシーンの更新メソッドから呼び出される別のメソッドを用意します。いくつかのテストの後

+0

私はdidSimulatePhysicsの位置を更新します。私はdidFinishUpdateのアップデートをやろうとしましたが、同じ問題です。物理学の身体は、運動中に依然として移動しました。 – suyama

+0

私の編集とコードをご覧ください。ありがとうございます – suyama

+0

私は今何を意味するのか理解しています。しかし、私はこの問題の別の(より良い)例を持っています。 GitHubの「Pierre Penguin Escapes The Antarctic」のゲームです:(https://github.com/vsrz/Pierre-Penguin-Escapes-The-Antarctic)とApp Store(https://itunes.apple.com/us/) app/pierre-penguin-escapes-antarctic/id994820199?mt = 8)。私の編集も見てください。ありがとうございました。 – suyama

関連する問題