Сохранение SKShapeNode в пределах SKSpriteNode

Я должен упустить что-то действительно очевидное здесь. Моя цель: создать коробку в центре экрана, внутри которой должен оставаться прыгающий мяч. Я пытаюсь создать SKSpriteNode на основе ребра для ограничивающей рамки и SKShapeNode на основе объема для внутреннего шара. Мяч появляется в центре коробки, падает через коробку, падает за пределы экрана, очевидно, ударяется о что-то ниже нижней части экрана и несколько раз отскакивает от нижнего края, прежде чем окончательно исчезнуть. Все это время didBeginContact никогда не срабатывает.

Вопрос 1: почему мой мяч падает через видимую коробку, но при этом касается чего-то под краем экрана? Мое физическое тело смещено от фактического спрайта?

Вопрос 2: почему didBeginContact не срабатывает? [Редактировать, хорошо, это было просто. Забыл установить physicsworld.delegate]

Спасибо!

Сцена.h

#define MAX_WORLD_CELLS_X 10
#define MAX_WORLD_CELLS_Y 10
#define BGTILE_SIZE 100

typedef enum : uint32_t {
    TYPE_SUBSPACE       = 1,
    TYPE_WORLD          = 2,
    TYPE_CHILD          = 4
} ColliderTypes;

@interface helloScene : SKScene
                <SKPhysicsContactDelegate>
{
    SKSpriteNode    *layerSubSpace,*layerWorld;  
}
@end

Scene.m, сделалНачалоКонтакты

-(void) didBeginContact:(SKPhysicsContact *)contact
{
    NSLog(@"Function: GameScene.m:didBeginContact");
}

Scene.m, initWithSize

-(id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        CGSize layerSize = CGSizeMake(MAX_WORLD_CELLS_X * BGTILE_SIZE *2, MAX_WORLD_CELLS_Y * BGTILE_SIZE *2);
        layerSubSpace = [SKSpriteNode spriteNodeWithColor:[UIColor redColor] size:layerSize];

        //center subSpace on the screen's center 
        layerSubSpace.position = CGPointMake(CGRectGetMidX(self.frame),         
                                         CGRectGetMidY(self.frame));        

        CGRect subspaceRect = CGRectMake(-layerSubSpace.size.width/2, -layerSubSpace.size.height/2, layerSubSpace.size.width, layerSubSpace.size.height);
        layerSubSpace.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:subspaceRect];
        layerSubSpace.physicsBody.affectedByGravity = NO;
        layerSubSpace.physicsBody.categoryBitMask = TYPE_SUBSPACE;
        layerSubSpace.physicsBody.contactTestBitMask = TYPE_WORLD;
        layerSubSpace.physicsBody.collisionBitMask = TYPE_WORLD;
        [self addChild:layerSubSpace];

        SKShapeNode *ball = [[SKShapeNode alloc] init];
        CGMutablePathRef myPath = CGPathCreateMutable();
        CGPathAddArc(myPath, NULL, 0,0, 60, 0, M_PI*2, YES);
        ball.path = myPath;
        ball.lineWidth = 1.0;
        ball.fillColor = [SKColor blueColor];

        ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:60];
        ball.physicsBody.restitution = 1;
        ball.physicsBody.categoryBitMask = TYPE_WORLD;
        ball.physicsBody.collisionBitMask = TYPE_SUBSPACE;
        ball.physicsBody.contactTestBitMask = TYPE_SUBSPACE;
        [layerSubSpace addChild:ball];
    }

    layerSubSpace.xScale = 0.25;
    layerSubSpace.yScale = 0.25;

    return self;
}

person Thunk    schedule 08.12.2013    source источник


Ответы (1)


1) Причина, по которой ваша физическая симуляция не совпадает с вашим визуальным представлением, заключается в том, что вы установили x/yScale свойства layerSubSpace на 0,25. Эти свойства влияют на визуальные представления ваших спрайтов, но не на базовую физическую модель. Основная проблема заключается в том, что размер вашего мяча и коробки уменьшаются в четыре раза в каждом измерении, но расстояние, на которое падает мяч, совсем не уменьшается.

Я подозреваю, что решение состоит в том, чтобы просто явно уменьшить размер всего в четыре раза, а не полагаться на свойства x/yScale. Когда я уменьшаю BGTILE_SIZE до 25, а радиус круга, как в CGPathAddArc, так и в bodyWithCircleOfRadius:, до 15, мяч останавливается на дне коробки на симуляторе iPad.

2) Как вы сказали, вы не установили self.physicsWorld.contactDelegate = self;

person godel9    schedule 08.12.2013
comment
Спасибо, это хороший момент. После уменьшения BGTILE_SIZE я действительно могу разместить поле физики на экране. Но вот в чем дело, он все еще больше, чем красный прямоугольник, связанный с SKSpriteNode. Поскольку я использовал одни и те же факторы при расчете размера спрайта и физического тела, я ожидал, что они будут совпадать по размеру (и масштабироваться вместе). Почему поле физического тела не выровнено по спрайту? - person Thunk; 08.12.2013
comment
@Thunk Извините, я пропустил настройки строк xScale и yScale, когда скопировал ваш код в свой тестовый проект. Я обновил свой ответ, чтобы объяснить, почему вы до сих пор не видите, что все выстраивается в линию. - person godel9; 08.12.2013
comment
Спасибо, это поставило меня на правильный путь. Масштабирование всей сцены вместо layerSubSpace дало желаемые результаты. Я могу изменить размер прямоугольника (подпространства) относительно экрана, и мяч остается точно внутри независимо от масштабирования. - person Thunk; 08.12.2013