2017-02-14 1 views
0

스프라이트에는 물리학자가 있습니다. 스프라이트가 어떤 방향으로 움직이면 물리 몸체는 그 방향으로 옮겨집니다 (첨부 된 이미지 참조). 이것은 접촉과 충돌에 좋지 않습니다.스프라이트 키트 : 이동 중에 물리학 자 본체가 이동 됨

물리 구조체는 이동 중에 만 이동합니다. 스프라이트가 멈 추면 물리학자가 옮겨지지 않습니다.

내 질문 : 물리 단위가 스프라이트 키트에서 이동 방향으로 어긋나는 이유는 무엇입니까? 그것을 막을 수있는 방법이 있습니까?

덕분에 많은

는 편집 :

OK .. 나는이 문제를 설명하기 작은 테스트를 썼다. 중력에 영향을받지 않는 물리 구조를 가진 노드가 하나뿐입니다. 물리학 세계에는 중력도 없습니다. 화면을 터치하여 영웅이 위쪽으로 이동합니다. 코드를 테스트하려면 SKView showsPhysics property = 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


편집 2 :

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

enter image description here

+0

나는 그것이 당신이 무엇을 요구하고 있는지 정말로 이해하지 못한다. 물론 물리학 몸체가 스프라이트와 함께 움직입니다. 왜 그렇게 원하지 않습니까? – Pierce

+0

관련 코드를 업로드해야합니다 ... – Whirlwind

+0

예, 물리 본문이 스프라이트와 함께 이동합니다. 그러나 물리학자가 옮겨진다. 첨부 된 이미지를 참조하십시오. 미사일이 뒤쪽에있는 우주선과 충돌하면 우주선의 물리 구조가 첨부 된 이미지와 같이 전면으로 이동하기 때문에 접촉/충돌이 발생하지 않습니다. – suyama

답변

0

,이 문제에 대한 최선의 해결책은 (사과 다큐에 설명) :

이 didBeginContact 내부 플래그를 설정 : 또는 didEndContact : 및 업데이트의 해당 플래그에 대한 응답의 변화를 합니다 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 init을 경우 cs 본문을 제대로 부모 노드 밖으로 옮겨야합니다. 예, 물리 구조가 움직이지만 동일한 경로가 노드를 움직일 것입니다. 물리 구조 체형을 확인하십시오.

+0

죄송합니다. 나는 이것이 당신이 의미하는 바를 이해하지 못합니다 : "물리학 자 몸을 제대로 초기화하면 그것은 부모 노드 밖으로 옮겨 져야합니다". 물리학 자의 몸은 운동 중에 그리고 그때 만 옮겨진다. 스프라이트가 멈 추면 물리 바디는 스프라이트를 중심으로 정확합니다. – suyama

+0

@suyama 노드가 멈 추면 어떻게됩니까? 아직도 실향입니까? – Whirlwind

+0

@Whirlwind 노드가 멈 추면 물리학자가 옮겨지지 않습니다. 물리학 몸체는 노드가 움직일 때만 옮겨집니다. 위치를 변경하여 노드를 이동합니다. 노드를 이동하기 위해 액션을 사용하지 않습니다. – suyama

1

SpriteKit을 사용하면 physics contact 핸들러 대리자 메소드에서 스프라이트의 위치를 ​​업데이트 할 때이 문제가 발생하는 것으로 나타났습니다.

콜백 위임 메소드 내에서 기본 노드의 위치/회전/스케일을 업데이트하지 마십시오. 대신 물리 콜백 내에서 필요한 업데이트를 식별하고 추적하는 메커니즘이 필요하며 노드의 변경 사항을 적용하는 장면의 업데이트 메소드에서 호출되는 별도의 메소드가 있어야합니다. 몇 가지 테스트 후

+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

관련 문제